Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
{scrollbar}

h1. Example: Hello World in XUL

All XUL files have the .xul extension, but are otherwise written in XML-compliant markup language.
{code}
<?xml version="1.0"?>
{code}

And can proivde a style sheet as well (this one is the default). This has no meaning in Pentaho XUL but makes previewing your XUL-file in Firefox much nicer:

{code}
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
{code}

Now you must declare a window or dialog as the root element of every XUL document. The window is often used as a placeholder in cases where we later pull a panel out to insert into a native UI (Spoon, RD).

{code}
<window id="hello_world" title="Hello World" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
{code}

A text box is the most basic XUL element. By default, the box will be horizontally oriented. Within the box you can put buttons, fields, and text. In this example, it's a simple box with one button:

{code}
<box>
<button id="Hello World!" label="Hello World!"/>
</box>
{code}

Then provide a closing tag for your window element:

{code}
</window>
{code}

Getting Started

Below are some quick steps for getting a new application started with Pentaho Xul. In this example Swing is used as the runtime toolkit. The same steps apply for creating a project with XUL-SWT. 

h3. Step 1: Get the libraries
You can build XUL yourself or download pre-compiled binaries from the Pentaho Build machine

*Subversion location:*
svn://source.pentaho.org/svnroot/pentaho-commons/pentaho-xul/trunk


If you're building yourself, for each of the Pentaho XUL projects you need to do the following:

# Run the "Resolve" task from the included build.xml file. This will bring down the supporting jars required for compilation.
# Run the "Dist" task to create a jar.
# Copy the resulting jar from the "dist" directory to the lib directory of your project. 
# Also copy all jars from the "lib" directory into the "lib" directory of the same project. This will ensure that you have all the required dependencies.


*Binaries:*
[XUL-Core|http://ci.pentaho.com/view/Commons/job/xul-core/lastSuccessfulBuild/artifact/pentaho-xul-core/dist/pentaho-xul-core-TRUNK-SNAPSHOT.jar]
[XUL-Swing|http://ci.pentaho.com/view/Commons/job/xul-swing/lastSuccessfulBuild/artifact/pentaho-xul-swing/dist/pentaho-xul-swing-TRUNK-SNAPSHOT.jar]
[XUL-SWT|http://ci.pentaho.com/view/Commons/job/xul-swt/lastSuccessfulBuild/artifact/pentaho-xul-swt/dist/pentaho-xul-swt-TRUNK-SNAPSHOT.jar]
[XUL-GWT|http://ci.pentaho.com/view/Commons/job/xul-gwt/lastSuccessfulBuild/artifact/pentaho-xul-gwt/dist/pentaho-xul-gwt-TRUNK-SNAPSHOT.jar]


h3. Step 2: Create your project

Create a new project in your IDE of choice. Add the XUL-Core jar and Swing, SWT or GWT jar depending on the final client UIs you want it to run in.

h3. Step 3: Loading your Xul Document

Loading of Xul documents is done with via a XulLoader. For each of the UI toolkits there's a corresponding XulLoader implementation to use. The loader parses the XML document and creates the real UI elements in the background. The resulting XulDomContainer contains a DOM with all the Xul tags parsed for the targeted UI technology. 

{code}
XulDomContainer container = new SwingXulLoader().loadXul("org/pentaho/barcamp/xul/contactManager.xul");
{code}

h3. Step 4: Adding Event Handlers

Interaction between the UI and your code is managed though event handlers (often called "controllers"). You can add these directly in the Xul document with the <script> tag:
{code}
<script id="handler" src="org.my.Handler.java"/>
<script id="handler2" src="anotherHandler.groovy"/>
{code}

However, most of the time you'll want to control the creation of your event handlers (dependancy injection for instance). Now is the time to create them and add them to the XulDomContainer.

{code}
MainController controller = new MainController();
container.addEventHandler(controller);
{code}

Event handlers added to the container are given a reference to the XulDomContainer. This allows them to access the XUL DOM as needed. If your handler extends "AbstractXulEventHandler" you interact with the XulDomContainer via the "document" member variable.

h3. Step 4: Starting it all up

The next step is to create a XulRunner and pass it your XulDomContainer instance. XulRunners handle "onload" events for your document and if you application is a <window> or <dialog>, can display display the UI if started.

{code}
XulRunner runner = new SwingXulRunner();
runner.addContainer(container);
runner.initialize();    //calls any onload events
runner.start();         //shows the UI
{code}

You may not want to start the runner. For instance, if you wanted to pull out a particular dialog or panel for use in your Swing application, you could do that here. If there were a <vbox> with an id of "sidePanel" in your document, you can pull it out of the document and use it as a JPanel in your Swing app by doing the following:

{code}
XulComponent vbox = (XulComponent) container.getDocumentRoot().getElementById("sidePanel");
JPanel panel = (JPanel) vbox.getManagedObject();
{code}

h3. Wrapping up

Here's the steps above all in one block. Change the Swing to SWT and you have your application running in a completely different UI toolkit.

{code}
XulDomContainer container = new SwingXulLoader().loadXul("path/to/your/application.xul");
    
MainController controller = new MainController();
container.addEventHandler(controller);

final XulRunner runner = new SwingXulRunner();
runner.addContainer(container);
runner.initialize();
runner.start();
{code}

h3. What's different in GWT?

Starting up a GWT Xul app is a little different due to the asynchronous nature of the technology.

{code}

public class MyGwtXulApp implements EntryPoint{

  public MyGwtXulApp(){
  }

  public void onModuleLoad() {
    AsyncXulLoader.loadXulFromUrl("contactManager.xul", "contactManager", new IXulLoaderCallback(){

      public void overlayLoaded() {}

      public void overlayRemoved() {}

      public void xulLoaded(GwtXulRunner runner) {

        try {

          XulDomContainer container = runner.getXulDomContainers().get(0);
          GwtBindingFactory bf = new GwtBindingFactory(container.getDocumentRoot());

          MainController controller = new MainController();
          container.addEventHandler(controller);
          
          runner.initialize();
          runner.start();

          Widget root = (Widget) ((XulComponent) container.getDocumentRoot().getRootElement()).getManagedObject();

          RootPanel.get().add(root);
        } catch (XulException e) {
          e.printStackTrace();
        }
      }
      
    });
  }

}
{code}

{scrollbar}