UIML (XML for user interfaces)
- From: Paul Hepworth <phepworth s-vision com>
- To: "'gnome-gui-list gnome org'" <gnome-gui-list gnome org>
- Subject: UIML (XML for user interfaces)
- Date: Mon, 2 Mar 1998 15:14:41 -0700
I really liked the XML idea for user-interface specification.
I have fleshed out the design by specifying a complete notepad-type
application using UIML -- the User Interface Markup Language, based
on XML.
A UIML "browser" would render the interface, interacting with the user.
The browser communicates with the application code in client-server
fashion. (The browser is the client, the actual application code is
the server.)
Separation of user interface and application code is assured. Assuming
a browser is implemented for all popular platforms, portability
depends only on writing the (non-gui) application code in an
environment-independent way. (The application code may be written in
any language.)
Here is the uiml specification for the notepad application:
(This is the uncommented version, to show the small size of a spec;
see below for a fully-commented version that will make more sense!
(seek down to "*******" if you want)
)
---- begin notepad.uiml
// xml headers and such go here
<dialog name="find">
<label>Find: </label> <entry name="findText"/>
<br/>
<checkbox name="strictCase">case sensitive</checkbox>
<hr/>
<button click="find $findText $strictCase" default=yes>^Find
next</button>
<button click=".close" escape=yes>^Close</button>
</dialog>
<dialog name="replace">
<label width=15>Find: </label>
<entry name="findText"/>
<br/>
<label width=15>Replace with: </label>
<entry name="replaceText"/>
<br/>
<checkbox name="strictCase">case sensitive</checkbox>
<hr/>
<button click="find $findText $strictCase" default=yes>^Find
next</button>
<button click="replace $replaceText; find $findText $strictCase">
^Replace</button>
<button click="replaceAll $findText $strictCase $replaceText">
Replace ^all</button>
<button click=".close" escape=yes>^Close</button>
</dialog>
<menu name="main">Notepad Menu
<menu>^File
<item cmd="file.new">^New</item>
<cmenu name="fileOpenHistory" cmd="file.open">^Open...
<init cmd="createFileOpenHistory fileOpenHistory"/>
</cmenu>
<item cmd="file.save">^Save</item>
<item cmd="file.save">Save ^as...</item>
<hr/>
<item cmd="app.exit">E^xit</item>
</menu>
<menu>^Edit
<item cmd="edit.cut">C^ut</item>
<item cmd="edit.copy">^Copy</item>
<item cmd="edit.paste">^Paste</item>
</menu>
<menu name="search">^Search
<item cmd=".dialog find" hotkey="search.find">^Find...</item>
<item cmd=".dialog replace"
hotkey="search.replace">^Replace...</item>
<item cmd="search.repeat">Repe^at</item>
</menu>
<helpmenu/> // help menu is auto-populated by the <help/> section
</menu>
<menu name="context.editor">
<item cmd="file.save">^Save</item>
<hr/>
<item cmd="edit.cut">C^ut</item>
<item cmd="edit.copy">^Copy</item>
<item cmd="edit.paste">^Paste</item>
<hr/>
<submenu name="search"/>
</menu>
<toolbar name="toolbar">Toolbar
<item cmd="file.new" icon="file.new">^New</item>
<item cmd="file.open" icon="file.open">^Open...</item>
<item cmd="file.save" icon="file.save">^Save</item>
<br/>
<item cmd="edit.cut">C^ut</item>
<item cmd="edit.copy">^Copy</item>
<item cmd="edit.paste">^Paste</item>
</toolbar>
<toolbar name="status">Status
<button name="status.modified" width=2 click="file.save"/>
<button name="status.row" width=4 losefocus="seek $status.row
$status.col"/>
<button name="status.col" width=3 losefocus="seek $status.row
$status.col"/>
</toolbar>
<tooltip name="status.modified">
"*" indicates file has been modified; click to save it
</tooltip>
// other tooltips go here
<help>
html help file text goes here (topics are extracted for help menu,
probably using a specified header tag, such as <h2>
</help>
<app code="applicationExecutableFileName" icon="notepad" decor="wm
hints"
name="aNameToStoreSettingsUnder"
tools="main, toolbar, status"
>
<entry multiline=yes name="editor" capture="K:*, M:*"/>
</app>
---- end notepad.uiml
****************************************
Here it is again, with embedded c++-style commentary:
----
// xml headers and such go here
<dialog name="find"
// other possible attributes:
// decor="wm hints"
// geometry="30%x30%"
// placement="parent.center"
// style="styleName" ...
>
<label>Find: </label> <entry name="findText"/>
<br/>
<checkbox name="strictCase">case sensitive</checkbox>
// could have included value=yes to start "checked" (default is no)
<hr/>
<button click="find $findText $strictCase" default=yes>^Find
next</button>
// notes:
// when this button is clicked (or enter is pressed (default button)),
// the command is sent to the application code (suppose strictCase is
checked
// and the findText entry contains 'foo' the application receives the
// command: 'find "foo" 1')
// The "^" in "^Find" indicates that F is the mnemonic (underlined or
// highlighted, depending on platform).
// (If "find one, then close dialog" were desired, the click command
// would have read "find $findText $strictCase; .close")
<button click=".close" escape=yes>^Close</button>
// when clicked or escape is pressed, the browser closes the dialog
// (".CMD" means browser executes CMD; nothing is sent to application)
</dialog>
<dialog name="replace">
<label width=15>Find: </label>
// width is in units of average-characer-width (based on curret font)
// alternatively, width may be specified as percentage of dialog size:
// width="30%"
<entry name="findText"/>
<br/>
<label width=15>Replace with: </label>
<entry name="replaceText"/>
<br/>
<checkbox name="strictCase">case sensitive</checkbox>
<hr/>
<button click="find $findText $strictCase" default=yes>^Find
next</button>
<button click="replace $replaceText; find $findText $strictCase">
^Replace</button>
<button click="replaceAll $findText $strictCase $replaceText">
Replace ^all</button>
<button click=".close" escape=yes>^Close</button>
</dialog>
<dialog name="exit">
// This dialog will be invoked by the application code on exit with
unsaved
// modifications. The application will pass the filename as $1.
<live>
<label>The file ;"e$1;"e has unsaved modifications.</label>
</live>
// <live> indicates that the item(s) within must be recreated each time
the
// dialog is displayed (so that the $1 substitution is "live")
<hr/>
<radio name="exitChoice">
<rbutton default=1 value="file.save; app.exit">
^Save the file and exit</rbutton>
<rbutton value="app.exit force">
^Discard the changes and exit</rbutton>
<rbutton value="">
Don't exit; ^return to application</rbutton>
</radio>
<hr/>
<button click=".close; $exitChoice" default=yes>O^K</button>
<hotkey hotkey="escape" cmd=".close"/>
// not sure if this one is a good idea or not (hotkey with no
corresponding
// visual element), but it makes sense to be able to press esc here, I
think
</dialog>
<menu name="main">Notepad Menu
<menu>^File
// <menu>'s may be nested to any level (cascading submenus)
<item cmd="file.new">^New</item>
<cmenu name="fileOpenHistory" cmd="file.open">^Open...
<init cmd="createFileOpenHistory fileOpenHistory"/>
// init tags just send cmd to application (once) as browser parses uiml
file
// cmenu is a conditional-cascade menu (i.e. clicking Open launches an
open
// dialog (or whatever the application wants to do), while clicking on
the
// arrow button to the right of "Open" brings up the file history
submenu)
</cmenu>
<item cmd="file.save">^Save</item>
<item cmd="file.save">Save ^as...</item>
<hr/>
<item cmd="app.exit">E^xit</item>
</menu>
<menu>^Edit
<item cmd="edit.cut">C^ut</item>
<item cmd="edit.copy">^Copy</item>
<item cmd="edit.paste">^Paste</item>
</menu>
<menu name="search">^Search
// we have named the search menu so that we can use it elsewhere, too
<item cmd=".dialog find" hotkey="search.find">^Find...</item>
// by default, hotkey==cmd, but we want the browser to launch the find
dialog
// while still using the standard hotkey
<item cmd=".dialog replace"
hotkey="search.replace">^Replace...</item>
<item cmd="search.repeat">Repe^at</item>
</menu>
<helpmenu/> // help menu is auto-populated by the <help/> section
</menu>
<menu name="context.editor">
<item cmd="file.save">^Save</item>
<hr/>
<item cmd="edit.cut">C^ut</item>
<item cmd="edit.copy">^Copy</item>
<item cmd="edit.paste">^Paste</item>
<hr/>
<submenu name="search"/> // use the previously defined search menu
</menu>
<toolbar name="toolbar">Toolbar
// toolbars are like menus, but they may be displayed as icon/text/both
// and they may accept other controls besides menu items
<item cmd="file.new" icon="file.new">^New</item>
// icon name expands to <icon>.<size>.xpm for unix
// (tries preferred size, then tries other sizes and scales),
// <icon>.ico then <icon>.<size>.bmp for win
// Note: I really should put the icon=... tags in the main menu, too
<item cmd="file.open" icon="file.open">^Open...</item>
<item cmd="file.save" icon="file.save">^Save</item>
<br/>
<item cmd="edit.cut">C^ut</item>
<item cmd="edit.copy">^Copy</item>
<item cmd="edit.paste">^Paste</item>
</toolbar>
<toolbar name="status">Status
<button name="status.modified" width=2 click="file.save"/>
<button name="status.row" width=4 losefocus="seek $status.row
$status.col"/>
// a full range of events are available, including click,
doubleclick,
// contextmenu, dragstart, drop, gainfocus, losefocus, keypress,
etc.
<button name="status.col" width=3 losefocus="seek $status.row
$status.col"/>
</toolbar>
<tooltip name="status.modified">
"*" indicates file has been modified; click to save it
</tooltip>
// other tooltips go here
<help>
html help file text goes here (topics are extracted for help menu,
probably using a specified header tag, such as <h2>
</help>
// alternatively, external help file may be used with <help file="..."/>
<app code="applicationExecutableFileName" icon="notepad" decor="wm
hints"
// the wm hints will be in a portable format usable by mwm-like and
'doze
name="aNameToStoreSettingsUnder"
tools="main, toolbar, status"
// inserts toolbars into window
// optionally, prefix with [tblrf]: to specify insertion point (default
t:)
// (top, bottom, left, right, floating)
// example: tools="t:main, f:toolbar, b:status"
>
<entry multiline=yes name="editor" capture="K:*, M:*"
// other avail attributes: readonly, password (shows *'s), html
// capture is a portable event mask string that specifies events to
capture
// and pass on to app (ex. mouse click, dblclick, keypress, move,
resize)
// Here, we want to capture keypresses and mouse clicks so we can update
// row/col/modified in status bar. (We could also add undo support)
/>
</app>
----
Now, the application code consists of a simple parser and interpretter
for commands sent from the UI.
Comments, please.
Paul
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]