[R-gui] Re: XML specifs for R GUIs dialog boxes
Warnes, Gregory R
gregory_r_warnes@groton.pfizer.com
Tue, 26 Nov 2002 16:27:13 -0500
A couple of ideas from the peanut gallery:
Why not use HTML forms syntax when this is possible? This would make things
simpler for folks who already know HTML.
Alternatively,
Has anyone taken a look at XForms specification that the W3C has been
working on? Since they have been working on a general method for handling
forms, we may be able to borrow some of what they have done.
-Greg
> -----Original Message-----
> From: thomas.friedrichsmeier@ruhr-uni-bochum.de
> [mailto:thomas.friedrichsmeier@ruhr-uni-bochum.de]
> Sent: Tuesday, November 26, 2002 1:08 PM
> To: r-sig-gui@stat.math.ethz.ch
> Subject: [R-gui] Re: XML specifs for R GUIs dialog boxes
>
>
> > - Since someone must initiate a document for the specifs, and Thomas
> > seems to have something almost ready, I proposed him to
> make a draft.
> > At this stage, modifications in a document will be more constructive
> > than loosy discussions in R-SIG-GUI.
>
> Ok, here's a rough draft. Note, that it is written from my subjective
> point of view, of what is needed and how it should be done. I'm
> picking up a few points raised in the discussion so far, but I'm
> simply ignoring others. This draft should therefore only serve as an
> aid in discussion.
>
> I call it "specification of a plugin-description language for R-
> frontends". "Plugin" refers to the fact, that the modules should be
> easy to insert into any R-frontend, preferrably but not necessarily
> without recompilation, but in any case without changes to the
> application-code. "R-frontends", because I'm currently only
> considering R. Extension to multiple backends (MatLab etc.) will
> require providing multiple variants of the "code"- and "result"-
> sections (see below).
>
> First of all, a few general considerations:
> - The specification should be useful both of the general approaches
> "extend R to have a GUI" and "build a GUI around R". It should make
> as little assumptions as possible on what data is stored where, how
> exactly it is passed to and from the backend etc.
> - It should be useful even to applications implementing only a
> limited subset of functionality, i.e. make as little assumptions as
> possible on what the application can interpret. Where advanced
> specifications are allowed, these should be designed to be truely
> optional, i.e. the plugin should still be useful, if those
> specifications are not handled by an application (though they may be
> used to enhance the functionality for applications that can handle
> them).
> - It should focus on describing core-functionality like "for a
> correlation you need at least two numeric vectors, and you can use
> these options". It should try to leave most fancy additional stuff to
> the application. It will however not be limited to describing core-
> functionality.
> - In general, the particular application using the plugin should be
> free to provide it's own consistent look and feel. That is, the major
> goal is not to provide a similar look-and-feel of a certain plugin
> across different applications using it, but rather consistency across
> different plugins used in the same application. Therefore, the
> specification will not be tailored towards allowing easy control of
> the exact look of a dialog.
> - In particular the specification should not make any specific
> assumptions on how e.g. context-help is invoked on a widget (right-
> click, short-cut, help-button, mouse-over...) or on how values can be
> entered (pasting, drag-and-drop, selection only vs. allowing manual
> editing, handwritten input via a stylus...).
> - Recurring tasks (such as selecting a vector/variable) should be
> handled by standard "widgets" whereever possible, custom solutions
> should only be used, when there is no good way to solve a problem
> using only the standard widgets. See above.
> - The specification will not describe the entire GUI of a plugin. The
> application will take care of providing standard-elements such as a
> "help"-button, "close"/"submit" and anything it thinks might be a
> good idea. The specification may however give a hint, if some of
> these standard-elements are not needed (not described below, yet).
>
> General structure:
> - The specification is written in an XML-variant.
> - It is divided into five or six main sections, which will be
> described in more detail below:
> a) a section "location", which describes, where the plugin logically
> belongs (e.g. in a menu-structure), and what it should be called.
> b) a section "layout" describing wich widgets are used, and how they
> should (preferrably) be placed, labeled etc.
> c) a section "code" describing how the values entered into the
> widgets should be used, i.e. what the resulting R-command should be
> d) a section "help" providing a use-centered help on the plugin
> e) a section "output" describing, how the output should be handled,
> e.g. what sort of information will be provided in R-output and how it
> can be parsed.
> f) potentially a section "dynamics" providing the ability to
> dynamically change things in the GUI (something like events).
>
> The sections is detail:
> "location":
> Only two different tags are allowed in this section: further
> "location"-tags and "entry"-tags. "location" describes a (new) level
> in the hierarchy (e.g. a sub-menu), "entry" marks the end-point,
> where the plugin will finally be placed (e.g. a menu-entry). The
> structure is strictly hierarchical, but it is allowed to specify
> multiple "locations" for a plugin:
>
> <location>
> <location id="first_menu" label="Analysis">
> <location id="x_tests" label="Fictional Tests">
> <entry id="my_test" label="Some
> purely fictional test"/>
> </location>
> <location id="y_tests" label="Absurd Tests">
> <entry id="my_test" label="Some
> purely fictional test"/>
> </location>
> </location>
> <location id="extras" label="Extras">
> <entry id="my_test" label="Some purely
> fictional test"/>
> </location>
> </location>
>
> The location-tag takes the following attributes:
> id: An internal identifier, that will be used to identify a point at
> a certain level in the hierarchy. E.g. if we have two plugins, both
> specifying "first_menu" as the id of the top-level location, this
> means, they will both be placed under that branch of the hierachy. If
> a certain id does not yet exist at a certain level in the hierarchy,
> the application will create that and label it:
> label: The label for this branch of the hierarchy. Will only be used
> for the first plugin encountered that creates this branch.
> The entry-tag takes the same attributes:
> id: It two entries at the same level in the hierarchy exist, the one
> encountered later will overwrite the first (this will make it
> possible for the user to load an enhanced or own-created plugin, that
> will be used instead of the standard-plugin for the same function).
> label: The label to be used.
>
> In the above example, the plugin is placed in three different places:
> Analysis->Fictional Tests->Some purely fictional test
> Analysis->Absurd Tests->Some purely fictional test
> Extras->Some purely fictional test
>
> Generally it is however desirable to use only a single unique place
> per plugin.
>
>
> "layout": It probably not the right term, since it also describes a
> lot of the functionality. In general this section is about creating
> and placing widgets. It allows two types of tags:
> a) tags used for arranging the widgets: "row", "column", "tabwidget"
> and "tab"
> b) tags describing widgets (both "active" and "passive"/decorational
> ones). To be detailed below.
>
> ad a):
> - The "row"-tag signals, that all widgets or layouts enclosed in it
> should be placed next to each other horizontally (from left to right)
> - Similarily widgets/layouts in a "column" will be arranged
> vertically.
> - Both tag take the attributes "width" and "height". These take
> integer-values that are interpreted as percent of the space available
> in the parent layout (or dialog), e.g.
> <row width="100">
> <column width="30">
> ...
> </column>
> <column width="70">
> ...
> </column>
> <row>
> "width" and "height" are only hints to the layouting engine, and may
> not be taken literally.
> [alternative approach: use something more similar to <table>, <tr>,
> <td> in HTML, allowing "colspan" and "rowspan" as attributes]
>
> - The <tabwidget>-tag takes as child elements <tab>-tags. Generally
> only one <tab> will be visible to the user at a time, and the
> <tabwidget> provides a way to switch between the tabs (this will not
> necessarily have to be real "tabs", the <tabwidget> might also
> provide buttons for the different tabs, with the tabs opening up in
> additional windows). <tab>/<tabwidget> should only be used, when
> there are a _lot_ of options not commonly used, that can not sensibly
> be shown all at the same time. The <tabwidget> does not need to
> occupy the whole dialog, i.e. does not have to be at the top-level.
> If it is not at the top-level, it takes the "width" and "height"-
> hints just like any other widget (see below).
>
> ad b):
> The following widgets are allowed. All widgets allow "width" and
> "height"-hints as described above:
>
> "passive" widgets:
>
> <text [wordwarp="boolean"]>Text to be displayed</text>:
> A simple text/label. "wordwrap" specifies, whether the text is
> wrapped automatically as required. A subtag <br/> is allowed for
> manual breaks.
>
> <frame><potentially furhter widgets/layouts></frame>
> If there are widgets/layouts enclosed in the frame-tag, the frame
> will be shown as a rectangle with those widgets insides it. If not,
> it will be shown as a line (vertical in rows, horizontal in columns).
>
> "active" widgets:
> Mostly all active widgets _require_ a unique id="string"-attribute
> used to identify them. All allow a label="string"-attribute (some
> require one), that describes a simple label directly attached to the
> widget. Further, all widgets allow a sub-tag
> <contexthelp>Description</contexthelp> that describes context-help
> that can be shown for this widget (in whatever way).
>
> - option-widgets:
>
> <radio [columnheight="integer"]></radio>:
> A group of radio-buttons. All <option> tags enclosed are radio-
> exclusive. Columnheight describes, how many <option>s should be
> placed below each other, before starting a new row of buttons. The
> <radio> automatically comes with a "frame" or something similar
> indicating that the options belong together, so there is no need, to
> place the <radio> inside a <frame>.
> <option value="string" label="string" [checked="bool"]/>:
> Represents a single option in a <radio>. Use checked="true" to
> specify that this button should be selected at start-up. Of course,
> only one may be set to "checked". "label" is the text shown next to
> the option. "value" is what becomes the value of the radio, if this
> option is checked. It is a string value, but of course that string
> may also be the string representation of a number. The <option>-tag
> does not need an "id", since it belongs to the <radio>, that already
> has an id. Of course it may have a <contexthelp> however.
>
> <checkbutton label="string" value="string" [checked="bool"]/>:
> Mostly like a radio-option, except that it is not contained in a
> group, since all buttons may be checked individually. That also
> means, that the button requires the id-attribute!
>
> <select selectable="integer"></select>:
> A string selector. "selectable" specifies, how many options may be
> selected simultaniously (0 for all). Takes as sub-tags the <option>s
> as described for the <radio>.
>
> Alternative (and probably better) approach to the above three
> widgets:
> <optionselector selectable="integer"
> [typehint="buttons|list"]/><option>s</optionselector>
> This would have the advantages, that a) the application would not
> have to be able to provide e.g. buttons, since a "list" can serve the
> same functionality. Also, the application could decide on it's own,
> what type of widget might be appropriate, e.g. buttons for less that
> 6 options (radiobuttons, if selectable="1"), list for more. b) It
> would be more abstract, and that'd make it easier to e.g. use options
> generated from an R-object.
>
> - object-selection-widgets:
>
> <varselector [offertype="string+string...;string..."]/>
> A widget, that presents a complete (preferrably hierarchical) list of
> all R-objects available. If "offertype" is specified, only objects of
> the given type(s) (e.g. numeric+vector) are offered (of course
> container-objects like lists and frames will always be shown). The
> "+" signals, that both conditions are required for an object to be
> acceptable. The ";" represents an OR.
>
> <varslot source="string" type="string+string...;string..."
> min="integer" max="integer"/>
> Holds at least "min", at most "max" variables (-1 for no limit). The
> widget will likely look different, depending on whether it can only
> hold a single or multiple objects. Since there may be more than one
> <varselector> in a dialog, "source" holds the "id" of the varselector
> that can be used as a source (of course you can still enter values
> manually). "type" specifies a list of acceptable object-types (see
> above).
> Note: The varslot is the only widget, that might potentially hold
> "invalid" entries. The application will have to check, whether the
> varslot is valid!
>
> <interaction sources="string;string;string"/>:
> Used for selecting interactions. "sources" is a ";" separated list of
> <varslot>s that hold the objects, between which interactions may
> occur.
>
> <input type="string"
> [typehint="slider|lineedit|textfield|dial|spinbox..."]/>:
> Takes a discrete value as input (either numeric or string ("type")).
> "typehint" suggest, what sort of widget should be used - the
> application may decide to ignore that hint if e.g. it does not
> support that widgettype.
>
> - output-widgets:
>
> <graph/>:
> For interactive graphs. The output section will have to describe,
> when and how to display something in this widget. Keep in mind, that
> some applications might chose to display <graph>s outside the dialog
> itself in a separate window, so make sure, the layout remains
> acceptable in this case. Ambitious applications will likely provide
> means to zoom/rotate/scale the graph, but this will not be detailed
> in the plugin-specification.
>
>
> "code"-section:
> approach a):
> <code>
> t.test ($x$, $y$, "$hypothesis$")
> </code>
> Everything between $-signs is interpreted as the id of a widget. It
> will be replaced with the value of that widget.
> approach b):
> <code>
> t.test (<?php echo "$x, $y, \"$hypothesis\""; ?>)
> </code>
> Of course in the example nothing is won, but using some scripting-
> language like PHP may come in handy for complex code.
>
> Either way, besides providing values for $x$, $y$..., the application
> should also be able to fill in the following:
> $x.valid$: boolean, whether the widget hold a valid entry
> $x.filled$: boolean, whether the widget holds something
> $x.type$: string, what type of data the widget holds
> $x.name$: string, the name of the object with escaped quotes, so it
> can be used inside e.g. print ("$x.name$")
> $x.label$: string, some applications may want to provide a more
> lengthy description for an object. Applications that don't, will
> place an empty string.
> $x.count$: integer, if more than one object/option may be selected,
> returns how many are selected.
>
>
> "help"-section:
> No real ideas on this, yet. plain HTML-body? Include something
> generated from the context-help?
>
>
> "output"-section:
> A very vague idea:
> <output>
> <returns>
> <value name="string" [label="string"]
> type="string"
> description="string"/>
> ...
> </returns>
> <parse>
> <?php /* parse output into separate
> variables if necessary. Those
> variables are described
> above in the
> <returns>-section. */ ?>
> </parse>
> <show>
> <?php /* generate an HTML-version of
> what the output might look
> like. This only generates a
> suggestion. The app may
> decide to do it's own formatting. */ ?>
> </show>
> </output>
>
>
> "dynamics"-section:
> An even more vague idea:
> <dynamics>
> <on event="x.changed" do="y.update"/>
> <on event="x.changed" do="z.changeTo(x.valid)"/>
> </dynamics>
> Here we're really getting into complicated stuff. I propose to use
> only one type of event:
>
> .changed : When the value of a widget was changed
>
> And a limited number of functions:
>
> .update : make the widget check, whether it is still valid, or re-
> read it's
> contents (esp. useful for the <graph>-widget
> .changeTo (newValue) : (newValue passed as string, but may represent
> a number)
> .setEnabled (boolean) : en-/disable widget
> .changeProperty (property, newValue) : a very powerful function,
> allowing to change the attributes of a widget dynamically. Will
> likely not work in many apps (or not soon, at least).
>
> _______________________________________________
> R-SIG-GUI mailing list
> R-SIG-GUI@stat.math.ethz.ch
> http://www.stat.math.ethz.ch/mailman/listinfo/r-sig-gui
>
LEGAL NOTICE
Unless expressly stated otherwise, this message is confidential and may be privileged. It is intended for the addressee(s) only. Access to this E-mail by anyone else is unauthorized. If you are not an addressee, any disclosure or copying of the contents of this E-mail or any action taken (or not taken) in reliance on it is unauthorized and may be unlawful. If you are not an addressee, please inform the sender immediately.