At a level above the use of widgets for different, singular functions in the application interface, Mozilla provides tools for hooking things together and creating application logic that can make your interfaces work more consistently and handle more complex tasks. If you have different elements in your application that execute the same function, for example, the command and observer system is the ideal way to facilitate reuse. Or you can use command sets to define command sets and key sets that can be overlaid and made available in different parts of your application, similar to how the cut and paste commands and others are spread over the Mozilla user interface but defined in a centralized file.
Broadcasters and observers are a mechanism for making any number of elements aware of state and event information from a single, "broadcasting" element. That broadcasting element can be an actual <broadcaster> or a regular element that broadcasts its state with special attributes. A common example of broadcasting is the disabling of a group of elements -- a menu item and a separate button for viewing source, for example -- when the source for a web page is not available.
The state of a broadcaster has to be changed explicitly for its observers to be updated:
<broadcasterset> <broadcaster id="save_command" disabled="false"/> </broadcasterset>
Once a broadcaster is defined, a XUL file may define elements that observe the broadcast command:
<button id="new" label="Save File" observes="save_command"/> <key id="key_new" xulkey="true" key="s" observes="save_command" /> <menuitem id="new_menuitem" label="New" observes="save_command"/>
Observing elements can also be more specific about the attribute they want to mimic. This is done by using the <observes> element:
<menuitem id="new_menuitem" value="New" observes="open_new"/> <observes element="open_new" attribute="disabled"/> </menu>
The element attribute associates the broadcaster and attribute tells the <menuitem> element to mimic the behavior of the broadcaster's "disabled" attribute.
Any number of commands can be contained in a <commandset>, and multiple sets can exist for different events in your application. It is also possible for sets to contain other command sets, mixed with commands or on their own. The idea is that there will be one base set that all other sets must inherit from; this base set can be defined in the top-level XUL file for your application. The following code has a command set that has its own commands and that pulls in a second set defined elsewhere (moreEditItems).
<commandset id="EditItems" oncommandupdate="updateCommandsetItems(this)" commandupdater="true" events="select"> <commandset id="moreEditItems" /> <command id="cmd_cut" oncommand="goDoCommand('cmd_cut');"/> <command id="cmd_copy" oncommand="goDoCommand('cmd_copy');"/> <command id="cmd_delete" oncommand="goDoCommand('cmd_delete');"/> </commandset>
The command updater is the mechanism used to pass command events between widgets in the UI. When an event is carried out, the message filters through to the command sets. Thus in the example above, if the select event is activated, all UI elements in this commandset become active. For example, setting the disabled attribute on a command set for saving disables all functional elements depending on it -- such as a menu item, a toolbar button, or a pop-up menu.
There are a number of ways to trigger the command updater. First, associate a widget with a particular command by using the command attribute:
<button id="cut-item" label="Cut" command="cmd_cut" enabled="true"/>
When this button is clicked, the command (cmd_cut) is located and carried out, firing the goDoCommand routine for that particular command.
Alternatively, your application might have a select event for a text element or an image. When the select event is fired, the message filters through to the command set, which, in turn, updates (by using oncommandupdate) the widgets-associated button with the commands.
The <keyset> element is a container for key elements. Key elements are used to execute commands from a keystroke combination. The keys Ctrl-Shift-s can be defined to execute a Save As command in your application (and that command can actually be defined in a command element):
<key id="key_saveas" key="s" modifiers="control,shift" command="cmd_saveas"/>
The key element has various special attributes like key, which is used to set an identifier shortcut key, or the modifiers attribute to set the trigger key. For example, modifiers="accel" would be the Ctrl key on Windows and GTK Unix platforms and the command button on Macintosh.
Example 3-15 shows a simple window that you can load up that has all element sets: commands, broadcasters, and keys.
Example 3-15. Shortcut keys with command observers
<?xml version="1.0"?> <window id="hello-goodbye" title="Hello Goodbye" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" style="min-width:100px;min-height:100px;background-color:white;"> <broadcasterset id="broadcasterset"> <broadcaster id="cmd_hello" oncommand="alert('Hello There!');" /> </broadcasterset> <keyset id="keyset"> <key id="key_h" key="H" observes="cmd_hello" modifiers="accel,shift" /> <key id="key_g" key="G" command="cmd_goodbye" modifiers="accel,shift" /> </keyset> <commandset id="commandset"> <command id="cmd_goodbye" oncommand="alert('Goodbye!');" /> </commandset> <spacer flex="1"/> <label value="hello/goodbye"/> <textbox value="type ctl+shft+h"/> <textbox value="type ctl+shft+g"/> <spacer flex="1"/> </window>