Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

XML Matters: GUIs and XML configuration data, Part 2

The Mozilla Project and XUL

David Mertz (mertz@gnosis.cx), Browser, Gnosis Software, Inc.
David Mertz
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/.

Summary:  David continues his discussion of how XML is used in the configuration of GUI interfaces. He looks at Mozilla's XML-based User Interface Language (XUL) which allows you to write applications that run without any particular dependency on the choice of underlying operating system. This may seem strange at first, but you'll soon see that this Mozilla project offers powerful tools for GUI building that allow you to develop for an extensive base of installed users.

View more content in this series

Date:  26 May 2004
Level:  Intermediate

Activity:  6438 views
Comments:  

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.

A toy application

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
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
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.


Checking out the XUL

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>


Other widgets

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.


Conclusion

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.


Resources

  • 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.

About the author

David Mertz

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/.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML
ArticleID=12403
ArticleTitle=XML Matters: GUIs and XML configuration data, Part 2
publish-date=05262004
author1-email=mertz@gnosis.cx
author1-email-cc=