index.docbook 279 KB
Newer Older
1
<?xml version="1.0" ?>
2
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
3
  <!ENTITY rkward '<application>RKWard</application>'>
4
  <!ENTITY r '<application>R</application>'>
5
  <!ENTITY pluginmap '<literal role="extension">.pluginmap</literal>'>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  <!ENTITY kapp "&rkward;"><!-- replace rkward here -->
  <!ENTITY % addindex "IGNORE">
  <!ENTITY % English "INCLUDE"><!-- change language only here -->
  
  
  <!-- Do not define any other entities; instead, use the entities
       from kde-genent.entities and $LANG/user.entities. -->
]>

<book lang="&language;">

<!-- This header contains all of the meta-information for the document such
as Authors, publish date, the abstract, and Keywords -->

<bookinfo>
<title>Introduction to Writing Plugins for RKWard</title>

<authorgroup>
<author>
<firstname>Thomas</firstname>
26
<surname>Friedrichsmeier</surname>
27
<affiliation>
28
<address><email>rkward-devel AT kde DOT org</email></address>
29
30
31
32
33
34
35
</affiliation>
</author>

<author>
<firstname>Meik</firstname>
<surname>Michalke</surname>
<affiliation>
36
<address><email>rkward-devel AT kde DOT org</email></address>
37
38
</affiliation>
</author>
39
<!-- Additional authors go here -->
40
41

<!-- TRANS:ROLES_OF_TRANSLATORS -->
Yuri Chornoivan's avatar
Yuri Chornoivan committed
42
43
44
</authorgroup>


45
46
47

<copyright>
<year>2006</year>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
48
<year>2007</year>
49
50
<year>2008</year>
<year>2010</year>
51
<year>2011</year>
52
<year>2012</year>
53
<year>2013</year>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
54
<year>2014</year>
55
<year>2015</year>
56
<holder>Thomas Friedrichsmeier</holder>
57
58
59
60
61
62
</copyright>
<!-- Translators: put here the copyright notice of the translation -->
<!-- Put here the FDL notice.  Read the explanation in fdl-notice.docbook 
     and in the FDL itself on how to use it. -->
<legalnotice>&FDLNotice;</legalnotice>

Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
63
64
<date>2015-11-05</date>
<releaseinfo>0.6.400</releaseinfo>
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

<abstract>
<para>
This is a guide to writing plugins for &rkward;.
</para>
</abstract>

<keywordset>
<keyword>KDE</keyword>
<keyword>R</keyword>
<keyword>rkward</keyword>
<keyword>plugins</keyword>
</keywordset>

</bookinfo>

<chapter id="introduction">
<title>Introduction</title>

84
85
	<note>
		<para>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
86
			Documentation as of &rkward; release 0.6.4.
87
88
89
		</para>
	</note>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
90
		This document describes how to write your own plugins. Note, that at the time of this writing, some of the concepts are not yet set in stone. Therefore, this document should be regarded as an introduction to the current approach, and as a basis for discussion. All sorts of comments are welcome.
91
92
93
		The documentation has grown quite large over time. Don't let that scare you. We recommend reading through the four basic steps (as
		outlined, below), to get a basic idea of how things work. After that you may want to skim the table of contents to see which advanced
		topics could be of relevance to you.
94
95
96
97
98
99
100
101
102
	</para>
	<para>
		For questions and comments, please write to the &rkward; development mailing list.
	</para>
	<para>
		<emphasis>You do not need to read this in order to use &rkward;.</emphasis> This document is about extending &rkward;. It is targeted at advanced users, or people willing to help improve &rkward;.
	</para>
	<para>
		Writing a standard plugin is basically a four-step process:
103
	</para>
104
105
106
107
108
109
		<itemizedlist>
			<listitem><para><link linkend="pluginmap">Placing a new Action in the menu hierarchy</link></para></listitem>
			<listitem><para><link linkend="mainxml">Describing the looks and behavior of the plugin GUI</link></para></listitem>
			<listitem><para><link linkend="jstemplate">Defining, how R-code is to be generated from the settings, the user makes in the GUI</link></para></listitem>
			<listitem><para><link linkend="pluginhelp">Adding a help page to your plugin</link></para></listitem>
		</itemizedlist>
110
	<para>
111
112
113
114
115
116
117
118
119
120
121
122
123
		Those will be dealt with in turn.
	</para>
	<para>
		Some advanced concepts may be used in those four steps, but are dealt with in separate chapters, to keep things simple:
		<itemizedlist>
			<listitem><para><link linkend="logic">GUI logic</link></para></listitem>
			<listitem><para><link linkend="embedding">Embedding Plugins into Plugins</link></para></listitem>
			<listitem><para><link linkend="plugin_series">Useful concepts for creating many series of similar plugins</link></para></listitem>
		</itemizedlist>
	</para>
	<para>
		Also, none of the chapters shows all options, but rather only the basic concepts. A complete <link linkend="reference">reference</link> of options is provided separately.
	</para>
124
125
</chapter>

126
<chapter id="whatareplugins">
Meik Michalke's avatar
Meik Michalke committed
127
<title>Preliminaries: What are plugins in &rkward;? How do they work?</title>
128
129
130
131
	<para>
		Of course the first question you might have is: What portions of &rkward; functionality is realized using plugins? Or: What can plugins do?
	</para>
	<para>
132
		One way to answer this is: Deselect all &pluginmap; files under <menuchoice><guimenu>Settings</guimenu><guimenuitem>Configure &rkward;</guimenuitem><guimenuitem>Plugins</guimenuitem></menuchoice>, and see what's missing. A slightly more helpful answer: Most actual statistics functions accessible via the GUI are realized using plugins. Also, you can create fairly flexible GUIs for all kinds of operations using plugins.
133
134
135
136
137
138
139
	</para>
	<para>
		The basic paradigm behind &rkward; plugins is the one we'll walk you through in this document: An XML file describes what the GUI looks like. An additional JavaScript file is used to generate &r; syntax from the GUI settings. That is, plugins do not really have to perform any statistical calculations. Rather plugins generate the &r; syntax needed to run those calculations. The &r; syntax is then sent to the &r; backend for evaluation, and typically a result is shown in the output window.
	</para>
	<para>
		Read on in the next chapters to see how this is done.
	</para>
140
141
</chapter>

142
143
<chapter id="pluginmap">
<title>Creating menu entries</title>
144
	<para>
145
		When you create a new plugin, you need to tell &rkward; about it. So the first thing to do, is to write a &pluginmap; file (or modify an existing one). The format of &pluginmap; is XML. I'll walk you through an example (also of course, be sure you have &rkward; configured to load your &pluginmap; -- <menuchoice><guimenu>Settings</guimenu><guimenuitem>Configure &rkward;</guimenuitem><guimenuitem>Plugins</guimenuitem></menuchoice>):
146
147
148
149
150
151
152
	</para>
	<tip>
		<para>
			After reading this chapter, have a look at the <link linkend="rkwarddev"><application>rkwarddev</application> package</link> as well. It provides some &r; functions to create most of &rkward;'s XML tags for you.
		</para>
	</tip>
	<programlisting>
153
&lt;!DOCTYPE rkpluginmap&gt;
154
155
156
157
158
	</programlisting>
	<para>
	The doctype is not really interpreted, but set it to <replaceable>"rkpluginmap"</replaceable> anyway.
	</para>
	<programlisting>
159
&lt;document base_prefix="" namespace="myplugins" id="mypluginmap"&gt;
160
161
	</programlisting>
	<para>
162
163
164
165
166
167
		The <parameter>base_prefix</parameter> attribute can be used, if all your plugins reside in a common directory. Basically, then you can omit that directory from the filenames specified below. It safe to leave this at <replaceable>""</replaceable>.
	</para><para>
		As you will see below, all plugins get a unique identifier, <parameter>id</parameter>. The <parameter>namespace</parameter> is a way to organize those IDs, and make it less likely to create a duplicate identifier accidentally. Internally, basically the namespace and then a <quote>::</quote> gets prepended to all the identifiers you specify in this &pluginmap;. In general, if you intend to <link linkend="sect_external_plugins">distribute your plugins in an R package</link>, it is a good idea to use the package name as <parameter>namespace</parameter> parameter. Plugins shipped with the official &rkward; distribution have <replaceable>namespace="rkward"</replaceable>.
	</para>
	<para>
		The <parameter>id</parameter> attribute is optional, but specifying an id for your &pluginmap; makes it possible for other people to make their &pluginmap;s load your &pluginmap;, automatically (see <link linkend="chapter_dependencies">the section on dependencies</link>).
168
169
	</para>
	<programlisting>
170
	&lt;components&gt;
171
172
173
174
175
	</programlisting>
	<para>
		Components? Aren't we talking about plugins? Yes, but in the future, plugins will be no more than a special class of components. What we do here, then, is to register all components/plugins with &rkward;. Let's look at an example entry:
	</para>
	<programlisting>
176
		&lt;component type="standard" id="t_test_two_vars" file="t_test_two_vars.xml" label="Two Variable t-Test" /&gt;
177
178
	</programlisting>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
179
		First the <parameter>type</parameter> attribute: Leave this to <replaceable>"standard"</replaceable> for now. Further types are not yet implemented. The <parameter>id</parameter> we've already hinted at. Each component has to be given a unique (in its namespace) identifier. Pick one that is easily recognizable. Avoid spaces and any special characters. Those are not banned, so far, but might have special meanings. With the <parameter>file</parameter> attribute, you specify where the <link linkend="mainxml">description of the actual plugin itself</link> is located. This is relative to the directory the &pluginmap; file is in, and the <parameter>base_prefix</parameter> above. Finally, give the component a label. This label will be shown wherever the plugin is placed in the menu (or in the future perhaps in other places as well).
180
181
	</para>
	<para>
182
		Typically a &pluginmap; file will contain several components, so here are a few more:
183
184
	</para>
	<programlisting>
185
186
187
188
189
190
		&lt;component type="standard" id="unimplemented_test" file="means/unimplemented.xml" /&gt;
		&lt;component type="standard" id="fictional_t_test" file="means/ttests/fictional.xml" label="This is a fictional t-test" /&gt;
		&lt;component type="standard" id="descriptive" file="descriptive.xml" label="Descriptive Statistics" /&gt;
		&lt;component type="standard" id="corr_matrix" file="corr_matrix.xml" label="Correlation Matrix" /&gt;
		&lt;component type="standard" id="simple_anova" file="simple_anova.xml" label="Simple Anova" /&gt;
	&lt;/components&gt;
191
192
193
194
195
	</programlisting>
	<para>
		Ok, this was the first step. &rkward; now knows those plugins exist. But how to invoke them? They need to be placed in a menu hierarchy:
	</para>
	<programlisting>
196
	&lt;hierarchy&gt;
197
		&lt;menu id="analysis" label="Analysis"&gt;
198
199
	</programlisting>
	<para>
200
		Right below the <command>&lt;hierarchy&gt;</command> tag, you start describing, in which <command>&lt;menu&gt;</command> your plugins should go. With the above line, you basically say, that your plugin should be in the <menuchoice><guimenu>Analysis</guimenu></menuchoice> menu (not necessarily directly there, but in a submenu). The <menuchoice><guimenu>Analysis</guimenu></menuchoice> menu is standard in &rkward;, so it does not actually have to be created from scratch. However, if it did not exist yet, using the <parameter>label</parameter> attribute you'd give it its name.
201
		Finally, the <parameter>id</parameter> once again identifies this <command>&lt;menu&gt;</command>. This is needed, so several &pluginmap; files can place their plugins in the same menus. They do this by looking for a <command>&lt;menu&gt;</command> with the given <parameter>id</parameter>. If the ID does not yet exist, a new menu will be created. Otherwise the entries will be added to the existing menu.
202
203
	</para>
	<programlisting>
204
			&lt;menu id="means" label="Means"&gt;
205
206
207
208
209
	</programlisting>
	<para>
		Basically the same thing here: Now we define a submenu to the <menuchoice><guimenu>Analysis</guimenu></menuchoice> menu. It is to be called <menuchoice><guimenuitem>Means</guimenuitem></menuchoice>.
	</para>
	<programlisting>
Meik Michalke's avatar
Meik Michalke committed
210
				&lt;menu id="ttests" label="t-Tests"&gt;
211
212
	</programlisting>
	<para>
213
		And a final level in the menu hierarchy: A submenu of the submenu <menuchoice><guimenuitem>Means</guimenuitem></menuchoice>.
214
215
	</para>
	<programlisting>
216
					&lt;entry component="t_test_two_vars" /&gt;
217
218
	</programlisting>
	<para>
219
		Now, finally, this is the menu we want to place the plugin in. The <command>&lt;entry&gt;</command> tag signals, this actually is the real thing, instead of another submenu. The <parameter>component</parameter> attribute refers to the <parameter>id</parameter> you gave the plugin/component above.
220
221
	</para>
	<programlisting>
222
223
224
225
					&lt;entry component="fictional_t_test" /&gt;
				&lt;/menu&gt;
				&lt;entry component="fictional_t_test" /&gt;
			&lt;/menu&gt;
226
			&lt;menu id="frequency" label="Frequency" index="2"/&gt;
227
228
229
230
231
	</programlisting>
	<para>
		In case you have lost track: This is another submenu to the <menuchoice><guimenu>Analysis</guimenu></menuchoice> menu. See the screenshot below. We'll skip some of what's not visible, marked with [...].
	</para>
	<programlisting>
232
233
				[...]
			&lt;/menu&gt;
234
235
236
			&lt;entry component="corr_matrix"/&gt;
			&lt;entry component="descriptive"/&gt;
			&lt;entry component="simple_anova"/&gt;
237
		&lt;/menu&gt;
238
239
	</programlisting>
	<para>
240
		These are the final entries visible in the screenshots below.
241
242
	</para>
	<programlisting>
243
		&lt;menu id="plots" label="Plots"&gt;
244
245
			[...]
		&lt;/menu&gt;
246
247
248
249
250
	</programlisting>
	<para>
		Of course you can also place your plugins in menus other than <menuchoice><guimenu>Analysis</guimenu></menuchoice>.
	</para>
	<programlisting>
251
		&lt;menu id="file" label="File"&gt;
252
253
			[...]
		&lt;/menu&gt;
254
255
256
257
258
	</programlisting>
	<para>
		Even in standard-menus such as <menuchoice><guimenu>File</guimenu></menuchoice>. All you need is the correct <parameter>id</parameter>.
	</para>
	<programlisting>
259
260
	&lt;/hierarchy&gt;	
&lt;/document&gt;
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
	</programlisting>
	<para>
		That's how to do it. And this screenshot shows the result:
	</para>
	<screenshot>
	<screeninfo>Menu hierarchy created by the code shown above</screeninfo>
		<mediaobject>
		<imageobject>
			<imagedata fileref="menu_hierarchy_example.png" format="PNG"/>
		</imageobject>
		<textobject>
			<phrase>Menu hierarchy created by the code shown above</phrase>
		</textobject>
		</mediaobject>
	</screenshot>
	<para>
277
		Confused? The easiest way to get started is probably taking some of the existing &pluginmap; files shipped with the distribution, and modifying them to your needs. Also, if you need help, don't hesitate to write to the development mailing list.
278
	</para>
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	<sect1 id="pluginmap_grouping"><title>Controlling the order of menu entries</title>
		<para>By default, all items (entries / submenus) inside a menu will be sorted alphabetically, automatically. In <emphasis>some</emphasis> cases you may want more control. In this case you can group elements as follows:</para>
		<itemizedlist>
			<listitem>
				<para>You can define groups inside any menu like this. All elements belonging to the same group will be grouped together:</para>
				<programlisting>
		&lt;group id="somegroup"/&gt;
				</programlisting>
			</listitem><listitem>
			<para>If you want the group to be visually separated from other entries, use:</para>
				<programlisting>
		&lt;group id="somegroup" separated="true"/&gt;
				</programlisting>
			</listitem><listitem>
				<para>Entries, menus, and groups can be appended to a specified group, using:</para>
				<programlisting>
		&lt;entry component="..." group="somegroup"/&gt;
				</programlisting>
			</listitem><listitem>
				<para>In fact, it is also possible to define groups (without separator lines) implicitly:</para>
				<programlisting>
		&lt;entry component="first" group="a"/&gt;
		&lt;entry component="third"/&gt;
		&lt;entry component="second" group="a"/&gt;
				</programlisting>
			</listitem><listitem>
				<para>Group names are specific to each menu. Group "a" in menu "Data" does not conflict with group "a" in menu "Analysis", for example.</para>
			</listitem><listitem>
				<para>The most common use case is defining groups at the top, or at the bottom of a menu. For this, there are pre-defined groups "top" and "bottom" in each menu.</para>
			</listitem><listitem>
				<para>Entries within each group are sorted, alphabetically. Groups appear in the order of declaration (unless appended to another group, of course).</para>
			</listitem><listitem>
				<para>Menus and entries without group specification logically form a group (""), too.</para>
			</listitem>
		</itemizedlist>
	</sect1>
315
316
317
318
</chapter>

<chapter id="mainxml">
<title>Defining the GUI</title>
319
320
321
322
323
324
325
326
327
328
<sect1 id="sect_defining_the_GUI"><title>Defining a dialog</title>
	<para>
		In the <link linkend="pluginmap">previous chapter</link> you've seen how to register a plugin with &rkward;. The most important ingredient was specifying the path to an XML file with a description of what the plugin actually looks like. In this chapter you'll learn how to create this XML file.
	</para>
	<tip>
		<para>
			After reading this chapter, have a look at the <link linkend="rkwarddev"><application>rkwarddev</application> package</link> as well. It provides some &r; functions to create most of &rkward;'s XML tags for you.
		</para>
	</tip>
	<para>
329
		Once again we'll walk you through an example. The example is a (slightly simplified) version of the two variable t-Test.
330
331
	</para>
	<programlisting>
332
&lt;!DOCTYPE rkplugin&gt;
333
334
335
336
337
	</programlisting>
	<para>
		The doctype is not really interpreted, yet. Set it to <replaceable>rkplugin</replaceable>, anyway.
	</para>
	<programlisting>
338
&lt;document&gt;
339
	&lt;code file="t_test_two_vars.js"/&gt;
340
341
342
343
344
	</programlisting>
	<para>
		All plugins generate some code. Currently the only way to do so is using JS, as detailed in <link linkend="jstemplate">the next chapter</link>. This defines, where to look for the JS code. The filename is relative to the directory the plugin XML is in.
	</para>
	<programlisting>
345
	&lt;help file="t_test_two_vars.rkh"/&gt;
346
347
348
349
350
	</programlisting>
	<para>
		It is usually a good idea to also provide a help page for your plugin. The filename of that help page is given, here, relative to the directory, the plugin XML is in. Writing help pages is documented <link linkend="pluginhelp">here</link>. If you do not provide a help file, omit this line.
	</para>
	<programlisting>
351
	&lt;dialog label="Two Variable t-Test"&gt;
352
353
	</programlisting>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
354
		As you know, plugins may have either a dialog or a wizard interface or both. Here we start defining a dialog interface. the <parameter>label</parameter> attribute specifies the caption of the dialog.
355
356
	</para>
	<programlisting>
357
358
		&lt;tabbook&gt;
			&lt;tab label="Basic settings"&gt;
359
360
361
362
363
	</programlisting>
	<para>
		GUI elements can be organized using a tabbook. Here we define a tabbook as the first element in the dialog. Use <command>&lt;tabbook&gt;</command>[...]<command>&lt;/tabbook&gt;</command> to define the tabbook and then for each page in the tabbook use <command>&lt;tab&gt;</command>[...]<command>&lt;/tab&gt;</command>. The <parameter>label</parameter> attribute in the <command>&lt;tab&gt;</command> element allows you to specify a caption for that page of the tabbook.
	</para>
	<programlisting>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
364
				&lt;row id="main_settings_row"&gt;
365
366
367
368
369
	</programlisting>
	<para>
		The <command>&lt;row&gt;</command> and <command>&lt;column&gt;</command> tags specify the layout of the GUI elements. Here you say, that you'd like to place some elements side-by-side (left to right). The <parameter>id</parameter> attribute is not strictly necessary, but we'll use it later on, when adding a wizard interface to our plugin. The first element to place in the row, is:
	</para>
	<programlisting>
370
					&lt;varselector id="vars"/&gt;
371
372
373
374
375
376
377
378
379
380
	</programlisting>
	<para>
		Using this simple tag you create a list from which the user can select variables. You have to specify an <parameter>id</parameter> for this element, so &rkward; knows how to find it.
	</para>
	<warning>
		<remark>
			You may NOT use a dot (.) in the <parameter>id</parameter> string.
		</remark>
	</warning>
	<programlisting>
381
					&lt;column&gt;
382
383
	</programlisting>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
384
		Next, we nest a <command>&lt;column&gt;</command> inside the row. That is the following elements will be placed above each other (top-to-bottom), and all will be to the right of the <command>&lt;varselector&gt;</command>.
385
386
	</para>
	<programlisting>
387
						&lt;varslot types="number" id="x" source="vars" required="true" label="compare"/&gt;
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
388
						&lt;varslot types="number" id="y" source="vars" required="true" label="against" i18n_context="compare against"/&gt;
389
390
391
392
	</programlisting>
	<para>
		These elements are the counterpart to the <command>&lt;varselector&gt;</command>. They represent <quote>slots</quote> into which the user can put variables. You will note that the <parameter>source</parameter> is set to the same value as the <parameter>id</parameter> of the <command>&lt;varselector&gt;</command>. This means, the <command>&lt;varslot&gt;</command>s will each take their variables from the varselector. The <command>&lt;varslot&gt;</command>s also have to be given an <parameter>id</parameter>. They may have a <parameter>label</parameter>, and they may be set to <parameter>required</parameter>. This means that the <guibutton>Submit</guibutton> button will not be enabled until the <command>&lt;varslot&gt;</command> holds a valid value. Finally the <parameter>type</parameter> attribute is not interpreted yet, but it will be used to take care that only the correct types of variables will be allowed in the <command>&lt;varslot&gt;</command>.
	</para>
393
394
395
396
	<para>
		In case you are wondering about the <parameter>i18n_context</parameter>-attribute: This is to provide context to help the correct translation of the word "against", used as the
		<command>&lt;varslot&gt;</command>'s label, but does not affect the functionality of the plugin, directly. More on this in <link linkend="i18n_general">a separate chapter</link>.
	</para>
397
	<programlisting>
398
399
400
401
402
						&lt;radio id="hypothesis" label="using test hypothesis"&gt;
							&lt;option value="two.sided" label="Two-sided"/&gt;
							&lt;option value="greater" label="First is greater"/&gt;
							&lt;option value="less" label="Second is greater"/&gt;
						&lt;/radio&gt;
403
404
405
406
407
	</programlisting>
	<para>
		Here, you define a group of <command>&lt;radio&gt;</command> exclusive buttons. The group has a <parameter>label</parameter> and an <parameter>id</parameter>. Each <command>&lt;option&gt;</command> (button) has a <parameter>label</parameter> and is assigned a <parameter>value</parameter>. This is the value the <command>&lt;radio&gt;</command> element will return when the option is selected.
	</para>
	<programlisting>
408
409
410
					&lt;/column&gt;
				&lt;/row&gt;
			&lt;/tab&gt;
411
412
413
414
415
	</programlisting>
	<para>
		Each tag has to be closed. We've put all the elements we wanted (the two <command>&lt;varslots&gt;</command> and the <command>&lt;radio&gt;</command>) in the <command>&lt;column&gt;</command>. We put all elements we wanted (the <command>&lt;varselector&gt;</command> and the <command>&lt;column&gt;</command> with those elements) in the <command>&lt;row&gt;</command>. And we've put all the elements we wanted into the first page in the <command>&lt;tabbook&gt;</command>. We're not yet done defining the <command>&lt;tabbook&gt;</command> (more pages to come), and of course there's more to come in the <command>&lt;dialog&gt;</command>, too. But this screenshot is basically what we've done so far:
	</para>
	<screenshot>
416
	<screeninfo>t-Test plugin</screeninfo>
417
418
419
420
421
		<mediaobject>
		<imageobject>
			<imagedata fileref="t_test_plugin_example.png" format="PNG"/>
		</imageobject>
		<textobject>
422
			<phrase>t-Test plugin</phrase>
423
424
425
426
		</textobject>
		</mediaobject>
	</screenshot>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
427
		Note that we have not specified the <guibutton>Submit</guibutton>, <guibutton>Close</guibutton>, &etc; buttons or the code view. Those elements get generated automatically. But of course we still have to define the second page of the <command>&lt;tabbook&gt;</command>:
428
429
	</para>
	<programlisting>
430
			&lt;tab label="Options"&gt;
Yuri Chornoivan's avatar
Yuri Chornoivan committed
431
				&lt;checkbox id="varequal" label="assume equal variances" value=", var.equal=TRUE"/&gt;
432
433
	</programlisting>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
434
		By default elements will be placed top-to-bottom like in a <command>&lt;column&gt;</command>. Since that is what we want here, we don't have to explicitly state a <command>&lt;row&gt;</command> or <command>&lt;column&gt;</command> layout. The first element we define is a checkbox. Just like the <command>&lt;radio&gt;</command><command>&lt;option&gt;</command>s, the checkbox has a <parameter>label</parameter> and a <parameter>value</parameter>. The <parameter>value</parameter> is what gets returned, if the check box is checked. Of course the checkbox also needs an <parameter>id</parameter>.
435
436
	</para>
	<programlisting>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
437
				&lt;frame label="Confidence Interval" id="frame_conf_int"&gt;
438
439
440
441
442
	</programlisting>
	<para>
		Here's yet another layout element: In order to signal that the two elements below  belong together, we draw a <command>&lt;frame&gt;</command> (box). That frame may have a <parameter>label</parameter> (caption). Since the frame is just a passive layout element, it does not need an <parameter>id</parameter>, we still define one here, as we'll refer to it later, when defining an additional wizard interface.
	</para>
	<programlisting>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
443
					&lt;checkbox id="confint" label="print confidence interval" value="1" checked="true"/&gt;
444
445
					&lt;spinbox type="real" id="conflevel" label="confidence level" min="0" max="1" initial="0.95"/&gt;
				&lt;/frame&gt;
446
447
	</programlisting>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
448
		Inside the <command>&lt;frame&gt;</command> we place another <command>&lt;checkbox&gt;</command> (using <parameter>checked=</parameter><replaceable>"true"</replaceable>, we signal that check box should be checked by default), and a <command>&lt;spinbox&gt;</command>. The spinbox allows the user to select a value between <replaceable>"min"</replaceable> and <replaceable>"max"</replaceable> with the default/initial value <replaceable>"0.95"</replaceable>. Setting the <parameter>type</parameter> to <replaceable>"real"</replaceable> signals that real numbers are accepted as opposed to <parameter>type=</parameter><replaceable>"integer"</replaceable> which would accept integers only.
449
450
	</para>
	<note><para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
451
		It is also possible, and often preferable, to make the <command>&lt;frame&gt;</command> itself checkable, instead of adding a <command>&lt;checkbox&gt;</command> inside. See the reference for details. This is not done here, for illustrational purposes.
452
453
	</para></note>
	<programlisting>
454
455
456
			&lt;/tab&gt;
		&lt;/tabbook&gt;
	&lt;/dialog&gt;
457
458
	</programlisting>
	<para>
459
		That's all for the second page of the <command>&lt;tabbook&gt;</command>, all pages in the <command>&lt;tabbook&gt;</command> and all elements in the <command>&lt;dialog&gt;</command>. We're finished defining what the dialog looks like.
460
461
	</para>
	<programlisting>
462
&lt;/document&gt;
463
464
465
466
467
	</programlisting>
	<para>
		Finally we close the <command>&lt;document&gt;</command> tag, and that's it. The GUI is defined. You can save the file now. But how does &r; syntax get generated from the GUI-settings? We'll deal with that in the <link linkend="jstemplate">next chapter</link>. First, however, we'll look into adding a wizard interface, and some general considerations.
	</para>
</sect1>
468

469
<sect1 id="wizard_interface">
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
470
471
	<title>Adding a wizard interface</title>
	<para>
472
		Actually we don't have to define an additional <command>&lt;wizard&gt;</command> interface, but here's how that would be done. To add a wizard interface, you'll add a <command>&lt;wizard&gt;</command> tag at the same level as the <command>&lt;dialog&gt;</command> tag:
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
473
474
	</para>
	<programlisting>
475
		&lt;wizard label="Two Variable t-Test"&gt;
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
476
			&lt;page id="firstpage"&gt;
477
478
479
				&lt;text&gt;As a first step, select the two variables you want to compare against
					each other. And specify, which one you theorize to be greater. Select two-sided,
					if your theory does not tell you, which variable is greater.&lt;/text&gt;
Meik Michalke's avatar
typo    
Meik Michalke committed
480
				&lt;copy id="main_settings_row"/&gt;
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
481
482
483
			&lt;/page&gt;
	</programlisting>
	<para>
484
		Some of this is pretty self explanatory: We add a <command>&lt;wizard&gt;</command> tag with a <parameter>label</parameter> for the wizard. Since a wizard can hold several pages that are shown one after another, we next define the first <command>&lt;page&gt;</command>, and put an explanatory <command>&lt;text&gt;</command> note in there. Then we use a <command>&lt;copy&gt;</command> tag. What this does, is really it saves us having to define yet again, what we already wrote for the <command>&lt;dialog&gt;</command>: The copy tag looks for another tag with the same <parameter>id</parameter> earlier in the XML. This happens to be defined in the <command>&lt;dialog&gt;</command> section, and is a <command>&lt;row&gt;</command> in which there are the <command>&lt;varselector&gt;</command>, <command>&lt;varslots&gt;</command> and the <quote>hypothesis</quote> <command>&lt;radio&gt;</command> control. All of this is copied 1:1 and inserted right at the <command>&lt;copy&gt;</command> element.
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
485
486
	</para>
	<para>
487
		Now to the second page:
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
488
	</para>
489
	<programlisting>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
490
			&lt;page id="secondpage"&gt;
491
492
				&lt;text&gt;Below are some advanced options. It's generally safe not to assume the
					variables have equal variances. An appropriate correction will be applied then.
Yuri Chornoivan's avatar
Yuri Chornoivan committed
493
					Choosing "assume equal variances" may increase test-strength, however.&lt;/text&gt;
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
494
				&lt;copy id="varequal"/&gt;
495
496
497
498
				&lt;text&gt;Sometimes it's helpful to get an estimate of the confidence interval of
					the difference in means. Below you can specify whether one should be shown, and
					which confidence-level should be applied (95% corresponds to a 5% level of
					significance).&lt;/text&gt;
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
499
500
501
502
503
				&lt;copy id="frame_conf_int"/&gt;
			&lt;/page&gt;
		&lt;/wizard&gt;
	</programlisting>
	<para>
504
		Much of the same thing here. We add some texts, and in between that <command>&lt;copy&gt;</command> further sections from the dialog interface.
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
505
506
	</para>
	<para>
507
		You may of course make the wizard interface look very different to the plain dialog, and not use the <command>&lt;copy&gt;</command> tag at all. Be sure, however, to assign corresponding elements the same <parameter>id</parameter> in both interfaces. This is not only used to transfer settings from the dialog interface to the wizard interface and back, when the user switches interfaces (which does not yet happen in the current version of &rkward;), but also simplifies writing your code template (see below).
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
508
	</para>
509
</sect1>
510

511
<sect1 id="mainxmltips">
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
512
513
	<title>Some considerations on GUI design</title>
	<para>
514
		This section contains some general considerations on which GUI elements to use where. If this is your first attempt of creating a plugin, feel free to skip over this section, as it isn't relevant to getting a basic GUI working. Come back here, later, to see, whether you can refine your plugin's GUI in some way or another.
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
515
516
	</para>
	
517
	<sect2 id="radio_vs_checkbox_vs_dropdown">
Yuri Chornoivan's avatar
Yuri Chornoivan committed
518
		<title>&lt;radio&gt; vs. &lt;checkbox&gt; vs. &lt;dropdown&gt;</title>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
519
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
520
			The three elements <command>&lt;radio&gt;</command>, <command>&lt;checkbox&gt;</command>, <command>&lt;dropdown&gt;</command>, all serve a similar function: To select one out of several options. Obviously, a check box only allows to choose between two options: checked or not checked, so you cannot use it, if there are more than two options to chose from. But when to use which of the elements? Some rules of thumb:
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
521
522
		</para>
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
523
			If you find yourself creating a <command>&lt;radio&gt;</command> or <command>&lt;dropdown&gt;</command> with only two options, ask yourself, whether the question is essentially a yes / no type of question. E.g. a choice between <quote>adjust results</quote> and <quote>do not adjust results</quote>, or between <quote>remove missing values</quote> and <quote>keep missing values</quote>. In this case a <command>&lt;checkbox&gt;</command> is the best choice: It uses little space, will have the least words of labels, and is easiest to read for the user. There are very few situations where you should chose a <command>&lt;radio&gt;</command> over a <command>&lt;checkbox&gt;</command>, when there are only two options. An example of that might be: <quote>Method of calculation: 'pearson'/'spearman'</quote>. Here, more methods might be thinkable, and they don't really form a pair of opposites.
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
524
525
		</para>
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
526
			Choosing between a <command>&lt;radio&gt;</command> and a <command>&lt;dropdown&gt;</command> is mostly a question of space. The <command>&lt;dropdown&gt;</command> has the advantage of using little space, even if there are a lot of options to chose from. On the other hand, a <command>&lt;radio&gt;</command> has the advantage of making all possible choices visible to the user at once, without clicking on the dropdown arrow. Generally, if there are six or more options to chose from, a <command>&lt;dropdown&gt;</command> is preferable. If there are five or less options, a <command>&lt;radio&gt;</command> is the better choice.
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
527
		</para>
528
	</sect2>
529
</sect1>
530
531
</chapter>

532
<chapter id="jstemplate">
533
<title>Generating R code from GUI settings</title>
534
535
<sect1 id="sect_generating_R_code"><title>Using JavaScript in RKWard plugins</title>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
536
		Now we have a GUI defined, but we still need to generate some &r; code from that. For that, we need another text file, <filename>code.js</filename>, located in the same directory as the <link linkend="mainxml"><filename>description.xml</filename></link>. You may or may not be familiar with JavaScript (or, to be technically precise: ECMA-script). Documentation on JS can be found in abundance, both in printed form, and on the Internet (&eg;: <ulink url="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide">https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide</ulink>). But for most purposes you will not need to know much about JS at all, as we'll only use some very basic features.
537
538
539
540
541
542
	</para>
	<tip>
		<para>
			After reading this chapter, have a look at the <link linkend="rkwarddev"><application>rkwarddev</application> package</link> as well. It provides some &r; functions to create JavaScript code commonly used in &rkward;. It can also autodetect variables used in a plugin XML file and create basic JavaScript code from that for you to start with.
		</para>
	</tip>
543
544
545
546
547
	<note>
		<para>
			Plugin .js files are assumed to be UTF-8 encoded. Be sure to check you editor's encoding, if using any non-ascii characters.
		</para>
	</note>
548
	<para>
549
		For the two variable t-test, the <filename>code.js</filename> file looks as follows (with comments in between):
550
551
552
	</para>
	<sect2 id="sect_JS_preprocess"><title>preprocess()</title>
		<programlisting>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
553
554
function preprocess () {
}
555
556
557
558
559
560
561
		</programlisting>
		<para>
			The JS file is organized into three separate functions: <function>preprocess()</function>, <function>calculate()</function>, and <function>printout()</function>. This is because not all code is needed at all stages. Currently the preprocess-function is not really used in many places (typically you will omit it altogether).
		</para>
	</sect2>
	<sect2 id="sect_JS_calculate"><title>calculate()</title>
		<programlisting>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
562
function calculate () {
563
564
	echo ('res &lt;- t.test (x=' + getString ("x") + ', y=' + getString ("y") + ', hypothesis="' + getString ("hypothesis") + '"' + getString ("varequal"));
	var conflevel = getString ("conflevel");
565
566
	if (conflevel != "0.95") echo (', conf.level=' + conflevel);
	echo (')\n');
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
567
}
568
569
570
571
572
		</programlisting>
		<para>
			This function generates the actual R syntax to be run from the GUI settings. Let's look at this in detail: The code to be used is generated using <function>echo()</function> statement. Looking at the <function>echo()</function> statement step by step, the first part of it is
		</para>
		<screen>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
573
res &lt;- t.test (
574
575
		</screen>
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
576
			as plain text. Next we need to fill in the value, the user selected as the first variable. We fetch this using <function>getString ("x")</function>, and append it to the string to be <quote>echoed</quote>. This prints out the value of the GUI-element with <parameter>id=</parameter><replaceable>"x"</replaceable>: our first <command>&lt;checkbox&gt;</command>. Next, we append a ', ', and do the same to fetch the value of the element <replaceable>"y"</replaceable> - the second <command>&lt;checkbox&gt;</command>. For the hypothesis (the <command>&lt;radio&gt;</command> group), and the equal variances <command>&lt;checkbox&gt;</command>, the procedure is very similar.
577
578
		</para>
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
579
			Note that instead of concatenating the output snippets with <quote>+</quote>, you can also use several <function>echo()</function> statements. Everything is printed on a single line. To produce a line break in the generated code, insert a <replaceable>"\n"</replaceable> in the echoed string. In theory, you can even produce many lines with a single echo-statement, but please keep it to one line (or less) of generated code per <function>echo()</function>.
580
		</para>
581
582
583
584
585
		<note>
			<para>Besides <function>getString()</function>, there are also functions <function>getBoolean()</function>, which will try to return the value as a logical (suitable for using in an <function>if()</function>-statement), and <function>getList()</function>, which will try to return list-like data in a JS <function>Array()</function>. We will show examples of those, later.</para>
			<para>When looking at existing plugins, you will also find plenty of plugins using <function>getValue()</function>, instead of <function>getString()</function>, and in fact the two are <emphasis>almost</emphasis> identical. However using <function>getString()</function>, <function>getBoolean()</function> and <function>getList()</function> is the recommended practice since version 0.6.1.
			</para>
		</note>
586
		<para>
587
			It gets a little more tricky for the confidence level. For reasons of aesthetics, we don't want to explicitly specify the confidence level to use, if it corresponds to the default value. Hence, instead of printing the value unconditionally, we first fetch into a variable. Then we check, whether that variable differs from <replaceable>"0.95"</replaceable> and if so print out an additional argument. Finally, we echo a closing bracket and a line break: <replaceable>")\n"</replaceable>. That's all for the calculate function.
588
589
590
591
		</para>
	</sect2>
	<sect2 id="sect_JS_printout"><title>printout()</title>
		<programlisting>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
592
function printout () {
593
	echo ('rk.header (' + i18n ("Two Variable t-Test") + ')\n');
594
	echo ('rk.print (res)\n');
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
595
}
596
597
		</programlisting>
		<para>
598
599
			And this was all there is to the printout function in most cases. <function>rk.header()</function> prints a standard headline for the results. Note that in the .js files, you have to
			mark up all translatable strings by hand, using <command>i18n()</command>, or some alternative commands. More on this in the <link linkend="i18n_js">chapter on internationaliation</link>.
Yuri Chornoivan's avatar
Yuri Chornoivan committed
600
			You can also add some more information to this, if you like, &eg;:
601
602
		</para>
		<programlisting>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
603
function printout () {
604
	new Header (i18n ("Two Variable t-Test"))
605
606
607
	          .addFromUI ("varequal")
	          .add (i18n ("Confidence level"), getString ("conflevel"))  // Note: written like this for illustration purposes. More automatic:
	//        .addFromUI ("conflevel")
608
	          .print ();
609
echo ('rk.print (res)\n');
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
610
}
611
612
		</programlisting>
		<para>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
613
			<function>rk.print()</function> utilizes the R2HTML package to provide HTML formatted output. Another helpful function is <function>rk.results()</function>, which can also output different kinds of result tables. If in doubt, however, just use <function>rk.print()</function>, and be done with. The JS class <function>Header</function> is a JS level helper to generate a call to <function>rk.header()</function> (just take a look at the generated &r; code). In some cases you may want to call <function>echo ('rk.header (...)')</function> directly to print a header for your output.
614
615
		</para>
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
616
			Note that internally, the output is just a plain HTML document at this point of time. Therefore you might be tempted to add custom HTML using <function>rk.cat.output()</function>. While this will work, please don't do this. The output format may change (&eg; to ODF) in the future, so it's best not to introduce HTML specific code. Rather keep things simple with <function>rk.header()</function>, <function>rk.print()</function>, <function>rk.results()</function>, and -- if needed -- <function>rk.print.literal()</function>. If those don't seem to satisfy your formatting needs, contact us on the mailing list for help.
617
618
619
620
621
622
		</para>
		<para>
			Congratulations! You created your first plugin. Read on in the next chapters for more advanced concepts.
		</para>
	</sect2>
</sect1>
623

624
<sect1 id="jsconventions">
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
625
<title>Conventions, policies, and background</title>
626
627
628
	<para>
		There are many ways to write &r; code for a certain task, and there are even more ways to generate this &r; code from JS. How exactly you do it, is left up to you. Still there are a number of considerations that you should follow, and background information you should understand.
	</para>
629

630
631
632
633
634
635
	<sect2 id="policylocal">
	<title>Understanding the <function>local()</function> environment</title>
		<para>
			More often than not you will have to create one or more temporary &r; objects in the code generated by your plugin. Normally, you do not want those to be placed in the user's workspace, potentially even overwriting user variables. Hence, all plugin generated code is run in a <function>local()</function> environment (see &r; help page on function <function>local()</function>). This means, all variables you create are temporary and will not be saved permanently.
		</para>
		<para>
636
			If the user explicitly asks for a variable to be saved, you will need to assign to that object using <function>.GlobalEnv$objectname &lt;- value</function>. In general, do not use the <function>&lt;&lt;-</function> operator. It will not necessarily assign in .GlobalEnv.
637
638
		</para>
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
639
			One important pitfall is using <function>eval()</function>. Here, you need to note that eval will by default use the current environment for evaluation, &ie; the local one. This will work well most of the times, but but not always. Thus, if you need to use <function>eval()</function>, you will probably want to specify the <parameter>envir</parameter> parameter: <function>eval(..., envir=globalenv()</function>).
640
641
		</para>
	</sect2>
642

643
644
645
	<sect2 id="policyformatting">
	<title>Code formatting</title>
		<para>
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
646
			The most important thing is for your generated &r; code to work, but it should be also easy to read. Therefore, please also keep an eye on formatting. Some considerations:
647
648
649
650
651
652
653
654
		</para>
		<para>
			Normal top-level &r; statements should be left aligned.
		</para>
		<para>
			Statements in a lower block should be indented with one tab (see example below).
		</para>
		<para>
655
656
			If you do very complex calculations, add a comment here and there, esp. to mark up logical sections. Note that there is a dedicated function <command>comment()</command> for inserting
			translatable comments in the generated code.
657
658
659
660
661
		</para>
		<para>
			For example, generated code might look like this. The same code without indentation or comments would be pretty hard to read, despite its modest complexity:
		</para>
		<programlisting>
662
# first determine the wobble and rotation
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
663
664
my.wobble &lt;- wobble (x, y)
my.rotation &lt;- wobble.rotation (my.wobble, z)
665
666

# boggling method needs to be chosen according to rotation
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
667
668
669
if (my.rotation &gt; wobble.rotation.limit (x)) {
	method &lt;- "foo"
	result &lt;- boggle.foo (my.wobble, my.rotation)
670
} else {
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
671
672
	method &lt;- "bar"
	result &lt;- boggle.bar (my.wobble, my.rotation)
673
}
674
675
		</programlisting>
	</sect2>
676

677
678
679
	<sect2 id="policysimplicity">
	<title>Dealing with complex options</title>
		<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
680
			Many plugins can do more than one thing. For instance, the <quote>Descriptive Statistics</quote> plugin can compute mean, range, sum, product, median, length, &etc; However, typically the user will only chose to have some of those calculations performed. In this case, please try to keep the generated code as simple as possible. It should only contain portions relevant to the options that are actually selected. To achieve this, here is an example of a common design patterns as you would use it (in JS; here, "domean", "domedian", and "dosd" would be &lt;checkbox&gt; elements):
681
682
		</para>
		<programlisting>
683
function calculate () {
684
	echo ('x &lt;- &lt;' + getString ("x") + ')\n');
685
686
	echo ('results &lt;- list ()\n');

687
688
689
	if (getBoolean ("domean.state")) echo ("results$" + i18n ("Mean value") + " &lt;- mean (x)\n");
	if (getBoolean ("domedian.state")) echo ("results$" + i18n ("Median") + " &lt;- median (x)\n");
	if (getBoolean ("dosd.state")) echo ("results$" + i18n ("Standard deviation") + " &lt;- sd (x)\n");
Thomas Friedrichsmeier's avatar
Thomas Friedrichsmeier committed
690
691
	//...
}
692
693
		</programlisting>
	</sect2>
694
</sect1>
695

696
<sect1 id="jstips">
697
<title>Tips and tricks</title>
698
699
700
701
	<para>
		Here are a few assorted tricks which may make writing plugins less tedious:
	</para>
	<para>
702
		If you need the value of a GUI setting at several places in you plugin's code, consider assigning it to a variable in JS, and using that instead of fetching it again and again with <function>getString()/getBoolean()/getList()</function>. This is faster, more readable, and less typing all at the same time:
703
704
	</para>
	<programlisting>
705
function calculate () {
706
	var narm = "";	// na.rm=FALSE is the default in all functions below
707
	if (getBoolean ("remove_nas")) {
708
709
		$narm = ", na.rm=TRUE";
	}
710
711
712
713
714
	// ...
	echo ("results$foo &lt;- foo (x" + narm + ")\n");
	echo ("results$bar &lt;- bar (x" + narm + ")\n");
	echo ("results$foobar &lt;- foobar (x" + narm "\n");
	// ...
715
716
717
718
719
720
721
722
723
724
725
726
}
	</programlisting>
	<para>
		The simple helper function <function>makeOption()</function> can make it easier to omit parameters that are at their default value, in many cases:
	</para>
	<programlisting>
function calculate () {
	var options
	//...
	// This will do nothing, if VALUE is 0.95 (the default). Otherwise it will append ', conf.int=VALUE' to options.
	options += makeOption ("conf.int", getString ("confint"), "0.95");
	//...
727
}
728
	</programlisting>
729
</sect1>
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
</chapter>

<chapter id="pluginhelp">
	<title>Writing a help page</title>
	<para>
		When your plugin basically works, the time has come to provide a help page. While typically you will not want to explain all the underlying concepts in depth, you may want to add some more explanation for some of the options, and link to related plugins and &r; functions.
	</para>
	<tip>
		<para>
			After reading this chapter, have a look at the <link linkend="rkwarddev"><application>rkwarddev</application> package</link> as well. It provides some &r; functions to create most of &rkward;'s XML tags for you. It's also capable of creating basic help file skeletons from existing plugin XML files for you to start with.
		</para>
	</tip>
	<para>
		You may recall putting this inside your plugin XML (if you haven't put this in, do so now):
	</para>
	<programlisting>
&lt;document&gt;
	[...]
	&lt;help file="filename.rkh" /&gt;
	[...]
&lt;/document&gt;
	</programlisting>
	<para>
		Where, obviously, you'd replace <filename>filename</filename> with a more appropriate name. Now it's time to create this <literal role="extension">.rkh</literal> file. Here is a self-descriptive example:
	</para>
	<programlisting>
&lt;!DOCTYPE rkhelp&gt;
&lt;document&gt;
	&lt;summary&gt;
In this section, you'll put some short, very basic information about what the plugin does.
This section will always show up on the very top of the help page.
	&lt;/summary&gt;

	&lt;usage&gt;
The usage section may contain a little more practical information. It does not explain all
the settings in detail (that's done in the "settings" section), however.

To start a new paragraph, insert an empty line, as shown above.
This line, in contrast, will be in the same paragraph.

In all sections you can insert some simple HTML code, such as &lt;b&gt;bold&lt;/b&gt; or
&lt;i&gt;italic&lt;/i&gt; text. Please keep formatting to the minimum needed, however.

The usage section is always the second section shown in a help page.
	&lt;/usage&gt;

	&lt;section id="sectionid" title="Generic section" short_title="Generic"&gt;
If you need to, you can add additional sections between the usage and settings sections.
However, usually, you will not need this while documenting plugins. The "id"-attribute
provides an anchor point to jump to this section from the navigation menu. The "short_title"
attribute provides a short title to use in the navigation bar. This is optional, by default
the main "title" will be used both as a heading to the section, and as the link name in the
navigation bar.

In any section you may want to insert links to further information. You do this by adding

&lt;link href="URL"&gt;link name&lt;/link&gt;

788
Where URL could be an external link such as http://rkward.kde.org .
789
790
791
792
793
Several special URLs are supported in the help pages:

&lt;link href="rkward://page/path/page_id"/&gt;

This links to a top level rkward help page (not for a plugin).
794

795
&lt;link href="rkward://component/[namespace/]component_id"/&gt;
796

797
This links to the help page of another plugin. The [namespace/] part may be omitted
Yuri Chornoivan's avatar
Yuri Chornoivan committed
798
(in this case, rkward is assumed as the standard namespace, &eg;:
799
800
&lt;link href="rkward://component/import_spss"/&gt; or
&lt;link href="rkward://component/rkward/import_spss"/&gt; are equivalent).
801
The component_id is the same that you specified in the <link linkend="pluginmap">&pluginmap;</link>.
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823

&lt;link href="rkward://rhelp/rfunction"/&gt;

Links to the R help page on "rfunction".

Note that the link names will be generated automatically for these types of links.
	&lt;/section&gt;

	&lt;settings&gt;
		&lt;caption id="id_of_tab_or_frame"/&gt;
		&lt;setting id="id_of_element"&gt;
Description of the GUI element identified by the given id
		&lt;/setting&gt;
		&lt;setting id="id_of_elementb" title="description"&gt;
Usually the title of the GUI element will be extracted from the
<link linkend="mainxml">XML definition of the plugin</link>, automatically. However,
for some GUI elements, this description may not be enough to identify them, reliably.
In this case, you can add an explicit title using the "title" attribute.
		&lt;/setting&gt;
		&lt;setting id="id_of_elementc"&gt;
Description of the GUI element identified by "id_of_elementc"
		&lt;/setting&gt;
824
		[...]
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
	&lt;/settings&gt;

	&lt;related&gt;
The related section typically just contains some links, such as:

&lt;ul&gt;
	&lt;li&gt;&lt;link href="rkward://rhelp/mean"/&gt;&lt;/li&gt;
	&lt;li&gt;&lt;link href="rkward://rhelp/median"/&gt;&lt;/li&gt;
	&lt;li&gt;&lt;link href="rkward://component/related_component"/&gt;&lt;/li&gt;
&lt;/ul&gt;
	&lt;/related&gt;

	&lt;technical&gt;
The technical section (optional, always last) may contain some technical details of the plugin
implementation, which are of interest only to RKWard developers. This is particularly relevant
for plugins that are designed to be embedded in many other plugins, and could detail, which
options are available to customize the embedded plugin, and which code sections contain which
R code.
	&lt;/technical&gt;
&lt;/document&gt;
845
846
847
848
	</programlisting>
</chapter>


849
<chapter id="logic">
850
851
852
853
854
855
856
857
858
<title>Logic interactions between GUI elements</title>
<sect1 id="sect_GUI_logic"><title>GUI logic</title>
	<para>
		All the basic concepts of creating a plugin for &rkward; have been described in the previous chapters. Those basic concepts should be sufficient for many -- if not most -- cases. However, sometimes you want more control over how your plugin's GUI behaves.
	</para>
	<para>
		For instance, suppose you want to extend the t-test example used in this documentation to allow both: comparing a variable against another variable (as shown), and comparing a variable against a constant value. Now, one way of doing this would be to add a radio-control that switches between the two modes, and adding a spinbox to enter the constant value to compare against. Consider this simplified example:
	</para>
	<programlisting>
859
860
&lt;!DOCTYPE rkplugin&gt;
&lt;document&gt;
861
	&lt;code file="code.js"/&gt;
862

863
864
865
866
	&lt;dialog label="T-Test"&gt;
		&lt;row&gt;
			&lt;varselector id="vars"/&gt;
			&lt;column&gt;
867
				&lt;varslot id="x" types="number" source="vars" required="true" label="compare"/&gt;
868
869
870
871
				&lt;radio id="mode" label="Compare against"&gt;
					&lt;option value="variable" checked="true" label="another variable (select below)"/&gt;
					&lt;option value="constant" label="a constant value (set below)"/&gt;
				&lt;/radio&gt;
872
873
				&lt;varslot id="y" types="number" source="vars" required="true" label="variable" i18n_context="Noun; a variable"/&gt;
				&lt;spinbox id="constant" initial="0" label="constant" i18n_context="Noun; a constant"/&gt;
874
875
876
877
			&lt;/column&gt;
		&lt;/row&gt;
	&lt;/dialog&gt;
&lt;/document&gt;
878
879
880
881
882
	</programlisting>
	<para>
		So far so good, but there are a number of problems with this GUI. First, both the varslot and the spinbox are always shown, whereas only one of the two is really used. Worse, the varslot always requires a valid selection, even if you compare against a constant. Obviously, if we create a multi-purpose GUI like this, we want more flexibility. Enter: the <command>&lt;logic&gt;</command> section (inserted at the same level as <command>&lt;code&gt;</command>, <command>&lt;dialog&gt;</command>, or <command>&lt;wizard&gt;</command>).
	</para>
	<programlisting>
883
	[...]
884
	&lt;code file="code.js"/&gt;
885
886
887
888
889

	&lt;logic&gt;
		&lt;convert id="varmode" mode="equals" sources="mode.string" standard="variable" /&gt;

		&lt;connect client="y.visible" governor="varmode" /&gt;
890
		&lt;connect client="constant.visible" governor="varmode.not" /&gt;
891
892
893
894
	&lt;/logic&gt;

	&lt;dialog label="T-Test"&gt;
	[...]
895
896
	</programlisting>
	<para>
897
		The first line inside the logic section is a <command>&lt;convert&gt;</command> tag. Basically, this provides a new boolean (on or off, true or false) property, which can be used later on. This property (<replaceable>"varmode"</replaceable>) is true, whenever the upper radio button is selected and false whenever the lower radio button is selected. How is this done?
898
899
	</para>
	<para>
900
		First, under <parameter>sources</parameter>, the source properties to work on are listed (in this case only one each; you could list several as <parameter>sources=</parameter><replaceable>"mode.string;somethingelse"</replaceable>, then <replaceable>"varmode"</replaceable> would only be true, if both <replaceable>"mode.string"</replaceable> and <replaceable>"somethingelse"</replaceable> are equal to the string <replaceable>"variable"</replaceable>). Note that in this case we don't just write <replaceable>"mode"</replaceable> (as we would in <function>getString("mode")</function>, but <replaceable>"mode.string"</replaceable>. This is actually the internal way a radio control works: It has a property <quote>string</quote>, which holds its string value. <function>getString("mode")</function> is just a shorthand, and equivalent to <function>getString("mode.string")</function>. See the reference for all properties of the different GUI elements.
901
902
	</para>
	<para>
903
		Second, we set the mode of conversion to <parameter>mode=</parameter><replaceable>"equals"</replaceable>. This means, we want to check, whether the source(s) is (are) equal to a certain value. Finally standard is the value to compare against, so with <parameter>standard=</parameter><replaceable>"variable"</replaceable>, we check whether the property <replaceable>"mode.string"</replaceable> is equal to the string <replaceable>"variable"</replaceable> (the value of the upper radio option). If it is equal, then the property varmode is true, else it is false.
904
905
	</para>
	<para>
906
		Now to the real stuff: We <command>&lt;connect&gt;</command> the <replaceable>"varmode"</replaceable> property to y.visible, which controls whether the varslot <replaceable>"y"</replaceable> is shown or not. Note that any element which is made invisible is implicitly non-required. Thus, if the upper radio-option is selected, the varslot <replaceable>"y"</replaceable> is required, and visible. Else it is not required and hidden.
907
908
	</para>
	<para>
909
910
911
		For the spinbox, we want the exact reverse. Fortunately, we do not need another <command>&lt;convert&gt;</command> for this: Boolean
		properties can be negated very easily by appending the modifier <replaceable>"not"</replaceable>, so we <command>&lt;connect&gt;</command> <replaceable>"varmode.not"</replaceable> to the spinbox's visibility property. In effect, either
		the varslot is shown and required, <emphasis>or</emphasis> the spinbox is shown and required - depending on which option is selected in the radio control. The GUI is changing itself according to the radio option. Try the example, if you like.
912
913
	</para>
	<para>
914
		For a complete list of properties, refer to the <link linkend="reference">reference</link>. One more property, however, is special in that all GUI elements have it: <quote>enabled</quote>. This is slightly less drastic that <quote>visible</quote>. It does not show/hide the GUI element, but only enables/disables it. Disabled elements are typically shown grayed out, and do not react to user input.
915
916
	</para>
	<note>
917
		<para>Besides <command>&lt;convert&gt;</command> and <command>&lt;connect&gt;</command>, there are several further elements for use in the <command>&lt;logic&gt;</command> section. E.g. conditional constructs can also be implemented using the <command>&lt;switch&gt;</command>-element. Refer to the <link linkend="logicelements">reference on logic elements</link> for details.</para>
918
919
	</note>
</sect1>
920
<sect1 id="logic_scripted">
921
<title>Scripted GUI logic</title>
922
923
924
925
	<para>
		While connecting properties as described above is often enough, sometimes it is more flexible or more convenient to use JS to script the GUI logic. In this way, the above example could be re-written as:
	</para>
	<programlisting>
926
927
	[...]
	&lt;code file="code.js"/&gt;
928
'
929
930
931
932
933
934
935
936
	&lt;logic&gt;
		&lt;script&gt;&lt;![CDATA[
			// ECMAScript code in this block
			// the top-level statement is only called once
			gui.addChangeCommand ("mode.string", "modeChanged ()");

			// this function is called whenever the "mode" was changed
			modeChanged = function () {
937
				var varmode = (gui.getString ("mode.string") == "variable");
938
939
940
941
942
943
944
945
				gui.setValue ("y.enabled", varmode);
				gui.setValue ("constant.enabled", !varmode);
			}
		]]&gt;&lt;/script&gt;
	&lt;/logic&gt;

	&lt;dialog label="T-Test"&gt;
	[...]
946
947
948
949
950
951
952
953
954
955
	</programlisting>
	<para>
		The first line of code tells &rkward; to call the function <function>modeChanged()</function> whenever the value of the <parameter>id=</parameter><replaceable>"mode"</replaceable> radio box changes. Inside this function, we define a helper-variable <replaceable>"varmode"</replaceable> which is true when the mode is <replaceable>"variable"</replaceable>, false is it is <replaceable>"constant"</replaceable>. Then we use <function>gui.setValue()</function> to set the and <quote>enabled</quote> properties of <replaceable>"y"</replaceable> and <replaceable>"constant"</replaceable>, in just the same way as we did using <command>&lt;connect&gt;</command> statements, before.
	</para>
	<para>
		The scripted approach to GUI logic becomes particularly useful when you want to change the available option according to the type of object that the user has selected. See <link linkend="guilogic_functions">the reference</link> for available functions.
	</para>
	<para>
		Note that the scripted approach to GUI logic can be mixed with <command>&lt;connect&gt;</command> and <command>&lt;convert&gt;</command>-statements if you like. Also note that the <command>&lt;script&gt;</command> tag allows to specify a script file name in addition to or as an alternative to inlining the script code. Typically, inlining the script code as shown above is most convenient, however.
	</para>
956
</sect1>
957
958
</chapter>

959
960
<chapter id="embedding">
<title>Embedding Plugins into Plugins</title>
961
962
963
964
965
966
967
968
<sect1 id="sect_embedding"><title>Use cases for embedding</title>
	<para>
		When writing plugins, you will often find that you're creating a number of plugins that only differ in some respects, but have a lot more in common. For instance, for plotting, there are a number of generic &r; options that can be used with mostly all types of plots. Should you create a GUI and JS-template for those over and over again?
	</para>
	<para>
		Obviously that would be quite a hassle. Fortunately, you don't have to do that. Rather you create the common functionality once, and later you can embed it into several plugins. In fact it is possible to embed any plugin into any other plugin, even if the original author of the embedded plugin never thought, somebody would want to embed their plugin into another one.
	</para>
</sect1>
969
<sect1 id="embedding_dialog">
970
<title>Embedding inside a dialog</title>
971
972
973
974
	<para>
		Ok, enough said. How does it work? Simple: Just use the <command>&lt;embed&gt;</command> tag. Here's a stripped down example:
	</para>
	<programlisting>
975
976
977
978
979
&lt;dialog&gt;
	&lt;tabbook&gt;
		&lt;tab [...]&gt;
			[...]
		&lt;/tab&gt;
980
		&lt;tab label="Plot Options" i18n_context="Options concerning the plot"&gt;
981
982
983
984
985
986
987
			&lt;embed id="plotoptions" component="rkward::plot_options"/&gt;
		&lt;/tab&gt;
		&lt;tab [...]&gt;
			[...]
		&lt;/tab&gt;
	&lt;/tabbook&gt;
&lt;/dialog&gt;
988
989
	</programlisting>
	<para>
Yuri Chornoivan's avatar
Yuri Chornoivan committed
990
		What happens here, is that the entire GUI or the plot options plugin (except of course for the standard elements like <guibutton>Submit</guibutton> button, &etc;) is embedded right into your plugin (try it!).
991
992
	</para>
	<para>
993
		As you can see the syntax of the <command>&lt;embed&gt;</command>-tag is fairly simple. It takes an <parameter>id</parameter> as most elements. The parameter component specifies which plugin to embed, as defined in the &pluginmap; file (<replaceable>"rkward::plot_options"</replaceable> is the result of concatenating the namespace <quote>rkward</quote>, a separator <quote>::</quote>, and the name of the component <quote>plot_options</quote>).
994
	</para>
995
996
</sect1>
<sect1 id="embedding_code">
997
<title>Code generation when embedding</title>
998
999
1000
	<para>
		So far so good, but what about the generated code? How are the code for the embedding and embedded plugin merged? In the embedding plugin's JS code, simply write something like this:
	</para>
For faster browsing, not all history is shown. View entire blame