Differences between version 2 and previous revision of ActionAuthoring.

Other diffs: Previous Major Revision, Previous Author

Newer page: version 2 Last edited on Thursday, April 10, 2003 6:24:08 am. by ThomasFriedrichsmeier
Older page: version 1 Last edited on Thursday, April 10, 2003 5:40:18 am. by ThomasFriedrichsmeier
@@ -7,209 +7,213 @@
 For now, all Actions are kept in a single directory-tree. Each level in the menu-hierarchy has its own sub-directory, and every single action is also kept in it's own sub-directory. Every (sub-)directory, then, contains a file calle "description.xml", which is a very short XML-file that keeps just enough information to place the action (or menu-level) in the menu-hierarchy. Here's what a "description.xml"-file looks like: 
  
 1) for a directory: 
  
-<document>  
- <content type="dir"/>  
- <entry caption="bogus tests"/>  
-</document> 
+ <document>  
+ <content type="dir"/>  
+ <entry caption="bogus tests"/>  
+ </document> 
  
 Here, content can either be type="dir" or type="entry". The first means, that this is a menu-level, i.e. the sub-directories found in this directory will be placed as entries in a sub-menu. The "entry"-tag describes the entry that will be put in the menu-structure. Currently only a caption is supported, in the future, icons might be supported additionally. 
  
 2) for an Action: 
  
-<document>  
- <content type="entry"/>  
- <entry caption="cool bogus test"/>  
- <action filename="empty.action"/>  
-</document> 
+ <document>  
+ <content type="entry"/>  
+ <entry caption="cool bogus test"/>  
+ <action filename="empty.action"/>  
+ </document> 
  
 Here the content-tpye is "entry", hence this directory is taken to contain a single action. Subdirectories of this directory are ignored. The entry-tag is the same as for directores. For actions, however, one further tag is expected: "action" with the attribute filename. 
+ 
 The filename to specify is that of the more detailed description of the Action in XML-format, which will be described below. That file is parsed every time, the Action is selected form the menu. Note, that this file _should_ reside in the same directory as the description.xml. While you may specify a relative or absolute path to a file in a different directory, that may not be very portable across platforms, and should therefore be avoided. 
  
 If you add new Actions at run-time, you will have to get Obversive to regenerate the menu-structure. Currently the only way to do so (besides restarting obversive), is to select a different actions-directory in Preferences->Actions, and then set the correct one, again. 
  
 !!! B) Defining the Action 
 So now you have a new Action placed in the obversive menu-structure. Next you'll have to define the action in the file you specified in description.xml. Below is the code of the "Test Action" with explanations in between: 
  
-<!DOCTYPE obversive_action> 
+ <!DOCTYPE obversive_action> 
  
 DOCTYPE is not interpreted, yet, but set it to "obversive_action" for clarity. 
  
-<!-- This is a simple example, of how an "action" with both a dialog- and a   
-wizard-interface might be configured. --> 
+ <!-- This is a simple example, of how an "action" with both a dialog- and a wizard-interface might be configured. --> 
  
 Comments as usual. 
  
-<document>  
- <title>Some Test</title> 
+ <document>  
+ <title>Some Test</title> 
  
 Caption of the GUI-window. 
  
- <code filename="some.file"/> 
+ <code filename="some.file"/> 
  
 By default, the code-template (see below) used will be "code.tpt" in the directory, the action is located. You override this by specifying a different file, here. 
  
- <dialog> 
+ <dialog> 
  
 The document-element requires at least one of the child-elements "dialog" and/or "wizard". Their meaning should be obvious. If only either of "dialog" or "wizard" is given, only that sort of interface will be available. If both are given, the user can switch between the interfaces. All direct children of the "dialog" element will be placed horizontally from left to right. Better control of widget-placement can be achieved using a number of tags described further below. 
  
- <tabbook> 
+ <tabbook> 
  
 The "tabbook"-element opens a tabbook. The only direct children allowed are "tab"-elements, which each represent a page in the tabbook. The tabs will be placed in the book, in the order they appear in the XML. 
  
- <tab label="general"> 
+ <tab label="general"> 
  
 tab-elements take a (mandatory) attribute "label", which is the string written on the tab-item. 
  
- <varselector id="vars" label="select variable(s)"/> 
+ <varselector id="vars" label="select variable(s)"/> 
  
 The "varselector"-tag defines a list from which you can select available objects. Besides a label, this element requires an attribute "id", which should be a unique string, by which the varselector can be referenced at other places. Currently no further attributes are supported. 
  
- <column> 
+ <column> 
  
 This is another layouting-element. All direct children of a "column"-tag will be place vertically from top to bottom. Similarily a "row"-tag would arrange its children from left to right (which is the default outside of columns). Using nested "row"- and "column"-tags, you have a good deal of control over the looks of the GUI. 
  
- <varslot type="numeric" id="x" source="vars" required="true" label="compare"/>  
- <varslot type="numeric" id="y" source="vars" required="true" label="against"/> 
+ <varslot type="numeric" id="x" source="vars" required="true" label="compare"/>  
+ <varslot type="numeric" id="y" source="vars" required="true" label="against"/> 
  
 "varslot"s are the counterpart to the "varselector". This is, where selected variables may be held. The "source"-attribute references the "varselector", from which variables may be selected. The "type"-attribute (currently ignored) specifies, which sort of variables are allowed. Finally, the "required"-attribute specifies, whether this varslot has to be filled with a valid entry before the user can proceed. Of course, this widget also requires an "id"-attribute so that it can be referenced from outside. 
  
- <radio id="hypothesis" label="using test hypothesis">  
- <option value="two.sided" label="Two-sided"/>  
- <option value="greater" label="First is greater" checked="true"/>  
- <option value="less" label="Second is greater"/>  
- </radio> 
+ <radio id="hypothesis" label="using test hypothesis">  
+ <option value="two.sided" label="Two-sided"/>  
+ <option value="greater" label="First is greater" checked="true"/>  
+ <option value="less" label="Second is greater"/>  
+ </radio> 
  
 This defines a group of radio-buttons with three options, the second of which is checked by default. The "value"-attribute is the string-value that is assigned to this widget, when the corresponding option is checked. This string-value can be used to generate R-codee (see below). 
  
- <checkbutton label="assume equal variances" id="option_a" value="some option"/>  
- <checkbutton label="use some option" checked="true" id="option_b" value="use this option"/> 
+ <checkbutton label="assume equal variances" id="option_a" value="some option"/>  
+ <checkbutton label="use some option" checked="true" id="option_b" value="use this option"/> 
  
 Checkbuttons. The value assigned to the widget is the string given, if checked, an empty string if not checked. 
  
- </column>  
- </tab>  
- <tab label="stuff">  
- <column>  
- <text>These are a few useless test items (including a lengthy  
- text, which is so long, that it will have to be wrapped, which  
- is quite a long text, don't you think?)</text>  
- <text>Below is a tabbook in a tabbook:</text> 
+ </column>  
+ </tab>  
+ <tab label="stuff">  
+ <column>  
+ <text>These are a few useless test items (including a lengthy  
+ text, which is so long, that it will have to be wrapped, which  
+ is quite a long text, don't you think?)</text>  
+ <text>Below is a tabbook in a tabbook:</text> 
  
 Text. Long lines will be wrapped, spaces will be reduced to single spaces like in HTML. This is mostly equivalent to a <p>-tag in HTML. 
  
- <tabbook>  
- <tab label="there's"><text>nothing</text></tab>  
- <tab label="in this"><text>tabbook</text></tab>  
- </tabbook> 
+ <tabbook>  
+ <tab label="there's"><text>nothing</text></tab>  
+ <tab label="in this"><text>tabbook</text></tab>  
+ </tabbook> 
  
 You can place tabbooks inside tabbooks, of course. 
  
- <frame label="textframe"><text>This is text in a frame</text></frame> 
+ <frame label="textframe"><text>This is text in a frame</text></frame> 
  
 If a "frame"-tag contains child-elements, it will be shown as a rectangular frame around them. 
  
- <column>  
- <text>There's a line below this</text>  
- <frame/> 
+ <column>  
+ <text>There's a line below this</text>  
+ <frame/> 
  
 Otherwise (if it does not contain any child-elements), it is rendered as a line (horizontal in columns, vertical in rows). 
  
- <text>There's a line above this</text>  
- </column>  
- </column>  
- </tab>  
- <tab label="info">  
- <column>  
- <text>This dialog was parsed and created on the fly, at the time  
- you selected it from the menu.</text>  
- </column>  
- </tab>  
- </tabbook>  
- </dialog> 
+ <text>There's a line above this</text>  
+ </column>  
+ </column>  
+ </tab>  
+ <tab label="info">  
+ <column>  
+ <text>This dialog was parsed and created on the fly, at the time  
+ you selected it from the menu.</text>  
+ </column>  
+ </tab>  
+ </tabbook>  
+ </dialog> 
  
 So this is the end of the dialog-interface. 
  
- <wizard recommended="true"> 
+ <wizard recommended="true"> 
  
 And this is the wizard-interface. You can use recommended="true" to recommend the use of the wizard for this action. Users may chose (actually it's the default setting) to be presented a wizard-interface by default, whenever that is recommended. 
  
- <pane>  
- <text>first pane</text>  
- </pane> 
+ <pane>  
+ <text>first pane</text>  
+ </pane> 
  
 The "wizard"-element takes as only direct children "pane"-elements, which represent the pages of the wizard. Everthing inside panes will once again be layed out left to right (unless you use columns). 
  
- <pane>  
- <column>  
- <text>second pane</text>  
- <row>  
- <column>  
- <varselector id="vars" label="select variable(s)"/>  
- </column>  
- <column>  
- <varslot type="numeric" id="x" source="vars" required="true" label="compare"/>  
- <varslot type="numeric" id="y" source="vars" required="true" label="against"/>  
- </column>  
- </row>  
- </column>  
- </pane>  
- <pane>  
- <column>  
- <text>third pane</text>  
- <radio id="hypothesis" label="using test hypothesis">  
- <option value="two.sided" label="Two-sided"/>  
- <option value="greater" label="First is greater" checked="true"/>  
- <option value="less" label="Second is greater"/>  
- </radio>  
- <checkbutton label="assume equal variances" id="option_a" value="some option"/>  
- <checkbutton label="use some option" checked="true" id="option_b" value="use this option"/>  
- </column>  
- </pane>  
- </wizard> 
+ <pane>  
+ <column>  
+ <text>second pane</text>  
+ <row>  
+ <column>  
+ <varselector id="vars" label="select variable(s)"/>  
+ </column>  
+ <column>  
+ <varslot type="numeric" id="x" source="vars" required="true" label="compare"/>  
+ <varslot type="numeric" id="y" source="vars" required="true" label="against"/>  
+ </column>  
+ </row>  
+ </column>  
+ </pane>  
+ <pane>  
+ <column>  
+ <text>third pane</text>  
+ <radio id="hypothesis" label="using test hypothesis">  
+ <option value="two.sided" label="Two-sided"/>  
+ <option value="greater" label="First is greater" checked="true"/>  
+ <option value="less" label="Second is greater"/>  
+ </radio>  
+ <checkbutton label="assume equal variances" id="option_a" value="some option"/>  
+ <checkbutton label="use some option" checked="true" id="option_b" value="use this option"/>  
+ </column>  
+ </pane>  
+ </wizard> 
  
 As you see, all of this is mostly a duplication of what has been defined for the dialog-interface. You may of course make the wizard-interface look very different to the plain dialog. Be sure, however, to assign corresponding widgets the same "id" 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, but also simplifies writing your code-template (see below). 
  
-</document> 
+ </document> 
  
 So now we have the GUI defined (note, that you do not need to mention standard-elements like the "Submit"-button). Here's one more widget you can use (yes, this document is a patchwork): 
  
- <column>  
- <input type="string" id="name" label="Whom do you want to greet?" required="true"/>  
- <input type="numeric" type_hint="slider" id="liking" label="How much to you like them?" required="true" min="" max="1"/>  
- <input type="numeric;int" id="count" label="How often to say hello?" required="true" min="1" max="10"/>  
- </column> 
+ <column>  
+ <input type="string" id="name" label="Whom do you want to greet?" required="true"/>  
+ <input type="numeric" type_hint="slider" id="liking" label="How much to you like them?" required="true" min="" max="1"/>  
+ <input type="numeric;int" id="count" label="How often to say hello?" required="true" min="1" max="10"/>  
+ </column> 
  
 "input" is a widget for all sorts of discrete values (as opposed to vectors). The first line will be rendered as a textfield. All non-empty strings are accepted. 
+ 
 The second line requests a widget to be used to enter a number in the range "min"-"max", and suggests to use a slider for that. The idea is, that this sort of "type_hint" might be overridden by user settings (and will also be ignored, if no lower and upper bounds are given). 
+ 
 Finally the third line requests a widget to enter an integer number in the range 1..10. The default representation for this is a spinbox (type_hint="spinner" to request a spinner explicitely). 
+ 
 So acutally, an "input"-widget may look quite different depending on the given attributes and configuration-settings. The idea is however, that all "input"-widgets will not necessarily look the same, but serve the same function: reading a discrete value. 
  
 !!! C) Generating code 
 Now we have a GUI defined, but we still need to generate some R-code from that. For that, we need another text-file, by default "code.tpt" (you can override this in the GUI-description using the <code filename="..."/>-tag). 
 This file is mostly plain R-code, but may contain references to the defined widgets: 
  
-for (i in 1:@getValue ("count")) \{  
- print ("Hello @getValue ("name", "true")! Somebody likes you this much: @getValue ("liking")")  
-\} 
+ for (i in 1:@getValue ("count")) \{  
+ print ("Hello @getValue ("name", "true")! Somebody likes you this much: @getValue ("liking")")  
+ \} 
  
 So the interesting part about this are the calls to @getValue (widget_id, [quote_escaping]). For instance, 
  
-@getValue ("count") 
+ @getValue ("count") 
  
 will be replaced with whatever value the widget "count" currently holds. 
  
-@getValue ("name", "true") 
+ @getValue ("name", "true") 
  
 This will be replaced with the value held in name, additionally escaping quotation-marks, so quotes can be printed safely. 
  
 Other than that, you write more or less plain R-code. You will have to escape {}s, though, as shown in the example. Actually, you can do a lot more complicated stuff than just filling in strings. The language used here is TPT ( http://tazthecat.net/~isaac/libtpt/ ). 
+ 
 For instance the code below may still not be very complicated, but you can see, how you get a lot of additional flexibility using constructs like @if (and even @for, @while and the like are available). 
  
-bogus.test (@getValue ("x"), @getValue ("y"), @getValue ("hypothesis")\  
-@if (!@compare (@getValue ("option_a"), "some option")) {  
-, use.option.a\  
-}  
-
+ bogus.test (@getValue ("x"), @getValue ("y"), @getValue ("hypothesis")\  
+ @if (!@compare (@getValue ("option_a"), "some option")) {  
+ , use.option.a\  
+ }  
+
  
 This is all for now. Happy experimenting.