Before I jump in with a string of acronyms and funny words that not all readers might be familiar with, I'll start with some quick basics. Simply put, what Mozilla does is render XML and HTML -- really not much more or less than this. All the Web browser controls that you are accustomed to (back button, URL field, bookmarks bar, menus, and so on) as well as any content areas, are, in Mozilla, just renderings of some XUL (XML-based User Interface Language) or HTML data. The same applies to Mozilla's applications for reading news, mail, chat sessions, or editing HTML -- it is all simply rendered XML. Mozilla provides collections of chrome (the non-document widgets/controls) in its default applications, but the framework lets you create your own applications or extensions to the Mozilla-provided ones by writing a bit of extra XUL XML.
The entire Mozilla application suite and associated spin-offs (such as Firefox and Thunderbird) are, at heart, applications written using XUL, an XML language for defining user interfaces. The Mozilla project as a whole is built in several layers. At the bottom, is the Gecko Runtime Engine that renders visual elements on screen -- especially HTML tags and their associated attributes, children, and URL-referenced resources. Many Mozilla applications use the XPToolkit as the next layer, which is where XUL is supported; however, some applications like the Camino browser for Mac OS X choose instead to use native widgets as an interface to the Gecko engine.
Applications, of course, can't do much without program logic. It is quite possible to write an entire Mozilla application using only JavaScript for the program logic -- each XUL control activating some configured JavaScript function, perhaps passing arguments based on that control. (Controls like text fields, pick lists, or scrollbars are used to select specific values rather than merely trigger single actions.) But for more advanced applications, the Cross Platform Component Object Module (XPCOM) interface is a way to let XUL-configured interfaces call components written in other programming languages -- primarily components written in C++, but other programming languages like Python also have XPCOM bindings. XPCOM is analogous to COM on Windows, or to CORBA.
Now that I've described the overall framework for developing Mozilla
interfaces (XUL makes a call to JavaScript; JavaScript might call C++
components through XPCOM), the rest of this article will focus exclusively on the
XUL piece of the puzzle -- after all, this is a column about XML. In the
examples, trivial calls to the JavaScript alert() function and
friends will be used where a more realistic application would call
custom functionality.
To give you a feel for XUL code, I wrote the customized Mozilla
application called SimpleApp, which
consists of the one XUL file, SimpleApp.xul,
and one external JavaScript file, SimpleApp.js. All
this application does is put a few menus and toolbar buttons on
the screen, and display an HTML document in the remainder of the
screen area. Most of the actions configured in SimpleApp
simply pop up some alert boxes, but one of the toolbar buttons lets you
choose the HTML document URL to display. Within the HTML area, you
can navigate just as you would in a regular browser -- follow links,
fill in forms, and other actions.
First, take a look at how to choose an HTML URL:
Figure 1. Choosing a URL in SimpleApp
SimpleApp uses several different types of menus. This probably would
not be the best design for a real application, but I wanted to
illustrate the use of both native menus created with <menubar> tags
and XUL menus created with <menulist> tags. The latter menus can go
anywhere within an application, including in nested regions or as
pop-up menus attached to visible content. However, XUL also lets you
create system-style pop-ups using <menupopup>, which is not
demonstrated here (system-style pop-ups are activated with a
right-click or shift-click; typically, a <menulist> is attached to
text that is displayed in a frame).
Figure 2 shows how to activate an alert dialog from a native Mac OS X menu:
Figure 2. Native menus in SimpleApp
The items Foo and Bar behave like regular pull-down menus with child items, though this is not shown in the screenshots.
Now take a look at the XUL that makes up SimpleApp.
Like most applications, its root element is <window>. However,
utilities that are meant simply to enhance the functionality of an
existing application, such as the Mozilla browser, will have a root of
<overlay>. One application can contain many overlays.
I will break the XUL file into several parts, each with a pretty clear function. You can put the pieces back together if you wish.
Listing 1. SimpleApp.xul headers and scripts
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
<!DOCTYPE window>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
width="600" height="280"
title="SimpleApp">
<script src="SimpleApp.js" />
<script type="application/x-javascript">
<![CDATA[ function say(txt) { alert(txt); } ]]>
</script>
<script type="application/x-javascript">
<![CDATA[
function newcontent(url) {
frames['content'].location.href=url; } ]]>
</script>
|
The external file SimpleApp.js just defines one trivial JavaScript
function, eye(), which is activated by the toolbar icon of an eye. In
a real application, you would be likely to put a library of useful
JavaScript functions into such an external file. I also define two
simple JavaScript functions within the body of the XUL file.
Listing 2. SimpleApp.xul system menu configuration
<menubar id="main-menu">
<menu label="File">
<menupopup>
<menuitem label="Hello" oncommand="say('Hello world!');"/>
</menupopup>
</menu>
</menubar>
|
In Listing 2, SimpleApp defines a File
menu with the child item Hello. Figure 2 shows the result of invoking this menu.
Now take a look at how the window contents are placed:
Listing 3. SimpleApp.xul placement boxes and menu list
<vbox>
<hbox>
<menulist><label>Foo</label>
<menupopup>
<menuitem label="New SimpleApp"
oncommand="window.open('SimpleApp.xul','','chrome');"/>
<menuitem label="Something Else"
oncommand="window.open('test3.xul','','chrome');"/>
</menupopup>
</menulist>
<menulist><label>Bar</label>
<menupopup oncommand="alert('Menu item invoked.')">
<menuitem label="Item One"/>
<menuitem label="Item Two"/>
<menuitem label="Item Three"/>
</menupopup>
</menulist>
</hbox>
|
A useful way to control the geometry of XUL controls is by nesting them inside the following variations on boxes:
<vbox>and<hbox>(usually used together)<scrollbox><groupbox>
Not shown here is the use of
<grid> elements, which can achieve a similar effect. A <vbox> always arranges its content in a common vertical box (the box itself is invisible). Likewise for horizontal <hbox> elements. If you wish, you can add height and width attributes to explicitly size these containers, and/or attributes like flex, autosize, or equalsize to affect the arrangement of boxes within other elements (such as inside other boxes).
Specifically, the controls for SimpleApp are all placed inside a
controlling <vbox>, with one child <hbox> for the Foo and Bar
menus, and another <hbox> to hold the toolbar:
Listing 4. SimpleApp.xul placement boxes and toolbar
<hbox>
<toolbarbutton type="button"
oncommand="alert('Button invoked.');">
<image src="http://gnosis.cx/dW/images/doc.gif" />
</toolbarbutton>
<toolbarbutton type="menu">
<image src="http://gnosis.cx/dW/images/note.gif" />
<menupopup>
<menuitem label="IBM"
oncommand="newcontent('http://ibm.com/');"/>
<menuitem label="Google"
oncommand="newcontent('http://google.com/');"/>
<menuitem label="TPiP"
oncommand="newcontent('http://gnosis.cx/TPiP/');"/>
</menupopup>
</toolbarbutton>
<toolbarbutton type="menu-button" onclick="eye();">
<image src="http://gnosis.cx/dW/images/eye.gif"/>
</toolbarbutton>
</hbox>
</vbox>
|
The toolbar code is interesting -- Mozilla XUL allows for modern toolbar styles that include both direct activation and child pull-downs. The button attached to note.gif is a pulldown type, and is shown in Figure 1. Also worth noting is that the actual images on the toolbar are pulled from remote URLs. This is a very simple example of a fully networked application -- the application as a whole integrates resources from all over the Web (albeit quite simple ones in this case).
The final piece of the puzzle is the HTML content that you display. To do
this, you need to create an <iframe> within the html namespace:
Listing 5. SimpleApp.xul HTML content
<html:iframe id="content-frame" name="content"
src="http://gnosis.cx/TPiP/" flex="100%"/>
</window>
|
SimpleApp has a moderately reasonable layout -- almost like a normal
browser. You can also throw resources together in more garish and
complex arrangements. For example, in experimenting with XUL I
created a test case that combines odd-sized buttons and various remote
HTML pages. This shows off a few more placement features. Try copying
it to your local system:
Listing 6. Garish XUL experiment (test.xul)
<?xml version="1.0"?>
<grid xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<columns>
<column/>
<column/>
</columns>
<rows flex="1">
<row>
<image src="http://www.mozilla.org/images/mozilla-banner.gif"/>
</row>
<row flex="1">
<spacer width="10"/>
<vbox align="center">
<spacer height="10"/>
<description style="border:0px; width: 120px">
This text can be <html:b> bold </html:b> and can wrap to
several lines. If I add a few more words, I can get it to
fill its column. This is a weird interface, eh?
</description>
<spacer height="10"/>
<button accesskey="A" label="A"
image="http://gnosis.cx/TPiP/hugo.gif"
oncommand="alert('Button A pressed!');"/>
</vbox>
<spacer width="10"/>
<iframe flex="1" src="http://google.com"/>
</row>
<row flex="1">
<iframe flex="1" src="http://ibm.com/" />
<button accesskey="B" flex="1" label="Button B"
oncommand="alert('Button B pressed!');"/>
<button accesskey="C" flex="1" label="Button C"
oncommand="alert('Button C pressed!');"/>
</row>
</rows>
</grid>
|
In the sample application, I have only used a few of the available XUL controls. The "XUL Programmer's Reference Manual" is the place to look for comprehensive documentation on all the XUL elements, and the online book Creating XPCOM Components is an excellent source for details on programming XUL and XPCOM libraries.
Let me quickly survey a few more XUL elements. Grids and boxes are
mostly used for simple layouts, but decks, stacks, and
bulletin boards give you more control. The latter, <bulletinboard>,
gives you exact position placement, rather than automating the flow of
controls to fit into containers.
In addition to the menus shown above, basic UI elements such as radio boxes, checkboxes, and various buttons are included in XUL. Some more advanced user interface controls are trees, pop-ups, an editor component, and tabs, as well as feedback from progress meters and manipulation of large containers with a number of variations on scrollbars.
For the most part, all of these elements are named according to their purpose.
However, you may also include any HTML widgets you like inside your XUL applications. Just put them in
the html namespace and add them as you would in designing an DHTML
Web page.
In Listing 6, I snuck in another useful navigation
element that I have not yet mentioned. Those buttons have an
attribute for accesskey that lets you activate their action with either a
keypress or a mouse click. In the same manner, it is easy
to provide whatever keyboard navigation you feel is appropriate for
your application. Even by default, menus allow basic
tab-and-arrow selection, but shortcut keys make many actions easier.
It might seem odd to develop complete applications within a browser, but Mozilla is now much more than that -- it is a whole component and GUI architecture. Indeed, Mozilla is more cross-platform and more widely installed on user systems than probably any other GUI library you are likely to consider. What you might think of as general purpose GUI/widget libraries -- Qt, wxWindows, GTK, FOX, MFC, .NET, Carbon, and so on -- have various advantages and disadvantages. But none of them can be assumed to be already installed across user systems. Many of them are only available on a subset of the platforms Mozilla supports, and most are relatively difficult to install or have licensing issues. Mozilla is worth installing just because it is such a great browser; once you have it, you have a free platform for custom applications.
To be completely cross-platform in your Mozilla/XUL applications, you need to restrict yourself to configuring GUIs in XUL and programming their logic in JavaScript. This is not the place to write about the benefits and disadvantages of JavaScript, but clearly a lot of programmers would rather develop in other languages like C++, Python, and Perl. You can do that, but you need to use XPCOM to bind to external libraries, and doing that reduces portability -- or at least makes things more difficult. For script languages like Python and Perl, you can take advantage of general-purpose bindings/wrappers, and write pretty generic code (but you still need, for example, PyXPCOM for your platform). For C++, however, you really need to compile a library version for each platform you intend to support -- quite a bit more work. Still, for simple applications JavaScript is fine, especially when those applications are largely about piggybacking onto the networking capabilities inherent in the Mozilla framework.
- Participate in the discussion forum.
- Read David's previous column, "XML Matters: GUIs and XML configuration data" (developerWorks, April 2004), in which he looks at the use of XML in Mac OS X's Aqua GUI, and in the K Desktop Environment (KDE).
- Check out the Mozilla Googlebar project, a nice
application/overlay of custom XUL for enhancing the functionality of the
browser. It adds a variety of custom search widgets to an optional toolbar
of each browser window, and also enhances the context pop-up.
- Try the Mozilla Calendar for a
useful full-fledged application written in XUL, with some JavaScript
glue and calls into a C++ library through XPCOM.
Calendar is a just what the name would suggest: an application for
managing appointments, contacts, events, and the like. Mozilla
Calendar is similar to Outlook on Windows or iCal.app on Mac OS X (whose
open data format is used), but it runs nearly identically on any
Mozilla platform.
- Get comprehensive documentation on all the XUL elements at the
XUL Programmer's Reference
Manual, your definitive source for XUL information.
- Read Creating XPCOM
Components. The scope of this book goes beyond XUL itself, but it is an excellent, freely
available publication that explains the overall XPCOM architecture, including XUL.
- Access more XML resources on the developerWorks XML zone.
- IBM trial software for product evaluation: Build your next project with trial software available for download directly from developerWorks, including application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
- IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
- Find all previous installments of David's XML Matters column on the column summary page.
- Browse for books on these and other technical topics.

David Mertz thinks the WIMP interface will really take off one of these days. David may be reached at mertz@gnosis.cx; his life pored over at http://gnosis.cx/dW/. Suggestions and recommendations on this, past, or future columns are welcomed. Check out David's book Text Processing in Python at http://gnosis.cx/TPiP/.



