Luxor Network: Luxor - Luxilla - Petra - Installer DeLux - Luxor Contrib - Luxor Forum - The Memphis Sun
Luxor XUL Logo
Making Building Classic Desktop-Style UIs As Easy As Building Web Pages
Overview . Tag Reference . Cheat Sheet . CSS Reference . API Reference . FAQ . History . Upcoming . Gallery . Notes . Powered By Luxor . Contribute . Mailing Lists & Forums . Premium Support . Credits . Glossary . Site Search . The Memphis Sun . Download . Download Luxilla . Download Plugins . Download Contrib . Source . Javadoc . Team . Who's Who . Donate . Luxor @ Sourceforge

Luxor Notes

Intro

This page holds notes about various topics to help you get started with Luxor and to collect footage for upcoming articles, tutorials, books, trilogies or road shows.

You are more than welcome to contribute your own short stories or novellas. Please post your opus to Luxor's mailinglist where we will pick it up to publish it here along with proper credit. If you prefer you can mail your oeuvre directly to a Luxor team member.

How To Package Your Chrome In Jars

You can package your app's chrome in its own jar separate from the app's jar holding all .class files. To make it work, you need to honor two rules:

The code snippet below demos how to use a resource anchor class to identify your chrome jar:
try
{
  Class chromeAnchorClazz = Class.forName( "ChromeAnchor" );

  XulResourceLoader xulResourceLoader = new XulJarResourceLoader( chromeAnchorClazz );
  XulManager.getXulManager().setResourceLoader( xulResourceLoader );
}
catch( ClassNotFoundException cex )
{
  System.err.println( "chrome anchor class '" + chrome + "' not found: " + cex.toString() );
}

A resource anchor is nothing more than an empty class that you bundle up in a jar along with your resources (that is, icons, XUL files, XML data, HTML pages, etc.). For a more detailed expose of the resource anchor technique check out the Web Start Resource Loading Tutorial at http://www.vamphq.com/tutorial.html third-party link. Finally, here are two uncut, full-length, real-world resource anchors:

public class ChromeAnchor
{
   public ChromeAnchor()
   {
   }
}

public class CrossRefAnchor
{
   public CrossRefAnchor()
   {
   }
}

Lastly, here is a peek into Venus Application Publisher's real-world chrome.jar revealing its directory structure:

Vamp Chrome Jar Directory Structure

Web Start - One-Click Startup - End Of Classpath Hell

Luxor is designed from the ground up for Web Start and, therefore, works out-of-the-box without the need for patches or dirty tricks. If Web Start doesn't ring a bell, check the links below to find out more:

Background Reading - Levarge Proven Technology - Learn More About Luxor XUL

Luxor XUL builds on proven technology such as XML, HTML, CSS, Velocity, HTTP, XSL/T, Python, XPath, JNLP and more. To learn more about Luxor XUL start by brushing up on the proven open standard technolgies leveraged by Luxor.

Mozilla XUL. Although Luxor XUL isn't a 100 % Mozilla XUL clone, it only breaks compatibility if there's a better way.

XUL Planent. More Mozilla XUL resources.

Apache Velocity. Resources about Luxor's template engine of choice.

Python/Jython. Resource about Luxor's scripting engine of choice.

Guido van Rossum, Fred L. Drake, Jr., Python Reference Manual - http://www.python.org/doc/current/ref/ref.html third-party link

Python is an interpreted, object-oriented, high-level programming language with dynamic semantics. Its high-level built in data structures, combined with dynamic typing and dynamic binding, make it very attractive for rapid application development, as well as for use as a scripting or glue language to connect existing components together. Python's simple, easy to learn syntax emphasizes readability and therefore reduces the cost of program maintenance. Python supports modules and packages, which encourages program modularity and code reuse. The Python interpreter and the extensive standard library are available in source or binary form without charge for all major platforms, and can be freely distributed.

Guido van Rossum, Comparing Python to Other Languages (Java, Javascript, Perl, Tcl, Smalltalk, C++, Lisp) - http://www.python.org/doc/essays/comparisons.html third-party link

Portlets - Pagelets - HTML Controls

Luxor XUL ships with built-in support for portlets and includes a light-weight portal engine.

What is a portlet? Portlets (also known as HTML pagelets or HTML controls) are basically like servlets, but return HTML snippets instead of complete HTML pages. Multiple portlets plus some sprinkled static XHTML fragments make up a complete web page also known as portal. Example:

<portal id="SYSTEM_INFO">
  <div align="center">
    <table border="0" width="90%" cellspacing="0" cellpadding="0">
      <tr>
        <td>
          <portlet id="USER_BANNER" />
          <portlet id="SYSTEM_INFO" />
          <portlet id="SYSTEM_PROPERTIES" />
        </td>
      </tr>
    </table>
  </div>
</portal>

To create your own portlet, you need to implement the luxor.spi.XulPortlet interface. XulPortlet's only method getContent() gets passed in a hashtable of name/value pairs and returns the HTML snippet as a string.

public interface XulPortlet
{
  public String getContent( Map args );
}

As most portlets return dynamic content, you can use Luxor's built-in Velocity template engine to help you create the portlets HTML snippet on-the-fly.

The SystemPropertiesPortlet example below creates a HTML table that lists all Java system properties alphabethicly using a Velocity template. (For the complete source code, download the Ramses example suite and look at the Hello Ramses example app.)

public class SystemPropertiesPortlet implements XulPortlet
{
  ...

  public String getContent( Map args )
  {
    // no required arguments

    List sysProps = createPropertyList( System.getProperties() );

    HashMap data = new HashMap();
    data.put( "sysProps", sysProps );

    XulManager xul = XulManager.getXulManager();
    String html = xul.getTemplate( data, "portlet/system-properties.html" );
    return html;
  }
}

The Velocity template loops over the portlet-supplied sorted system property list to contribute a HTML table to the portal (aka web page).

<h2> $sysProps.size() System Properties</h2>

<table border="1">

#foreach( $prop in $sysProps )
 <tr>
    <td>$prop.key</td>
    <td>$prop.value</td>
 </tr>
#end
</table>

To display the portal (aka web page) in your embedded web browser (e.g. JEditorPane) you can use Luxor's XulMangager.getPortal() method that returns the portal's HTML in a string that you pass on to JEditorPane. Example:

XulManager xul = XulManager.getXulManager();

String html = xul.getPortal( "SYSTEM_INFO" );

JEditorPane browser = new JEditorPane();
browser.setEditable( false );
browser.setContentType( "text/html" );
browser.setText( html );

A better method is to create a XulServlet. A XulServlet uses Luxor's built-in, ultra light-weight, multi-threaded web server to serve up the portals HTML to your embedded browser or the machine's household browser (e.g. Netscape, Opera, etc.). Example:

public class CmdSystemInfo extends XulAction implements XulServlet
{
  private AppShell _shell;

  public CmdSystemInfo(AppShell shell)
  {
    super( Chrome.Action.SYSTEM_INFO );
    _shell = shell;

    XulManager.getXulManager().addServlet( getId(), this );
  }

  public void execute()
  {
    onSystemInfo();
  }

  public String getContent( Map args )
  {
    XulManager xul = XulManager.getXulManager();

    String html = xul.getPortal( Chrome.Portal.SYSTEM_INFO );
    return html;
  }

  public void onSystemInfo()
  {
    UrlQueryString query = new UrlQueryString();
    query.add( "action", getId() );

    _shell.showDocument( query );
  }
}

The URL to display the portal in your household browser in the example above is: http://localhost:5454/ramses?action=system-info.

The URL breaks down as follows: The Hello Ramses example app starts the web server (aka http service) on port 5454.

static public final int PORT = 5454;
...
WebServer webServer = new WebServer( PORT, webResourceManager );
webServer.start();

Next, all Luxor XulServlets are made available through XulServletResourceLoader that takes in a context in its constructor. A context is the industry jargon for a part of an URL path. In this case, the context is simply ramses. Example:

WebResourceManager webResourceManager = WebResourceManager.getWebResourceManager();

// make xul servlets available through built-in web server
webResourceManager.addResourceLoader( new XulServletResourceLoader( "ramses" ) );

Lastly, Luxor's web server uses the query argument action to dispatch incoming requests. Therefore, the URL query convention is: action=<Xul Action Id> (e.g. action=sys-info). You can pass in additional parameters by appending them to the URL query string.

Portlet Links

XulManager shortcuts

To retrieve icons, menus, toolbars, templates and more you need to get a hand onto a XulManager reference. Example:

XulManager xul = XulManager.getXulManager();

JMenuBar menuBar = xul.createMenuBar( Chrome.MenuBar.MAIN );
JToolBar toolBar = xul.createToolBar( Chrome.ToolBar.MAIN );

ImageIcon icon = xul.lookupIcon( Chrome.Icon.RAMSES );

This is perfectly fine as long as you use the xul reference repeatedly. If all you want is retrieve an icon, box or template, for example, you can use Xuls static convenience methods that won't require a XulManager reference as a shortcut. Example:

Use

Xul.lookupIcon( Icon.JNLP_INFORMATION_ICON );

instead of

XulManager.getXulManager().lookupIcon( Icon.JNLP_INFORMATION_ICON );
Luxor's Status Toolkit - Errors, Warnings, Infos, Hints

Luxor includes a status (aka error reporting and logging) toolkit that you can use for GUI as well as GUI-less (aka command-line) apps. Luxor itself reports all errors, warnings and infos through its toolkit and ships with a couple of pre-built status handlers that you can reuse in your apps as well.

Architecture. Luxor's status toolkit uses the publish/subscribe model. Luxor sends reported errors, warnings, infos, hints, etc. to subscribed status handler. Status handler for command-line apps usually display incoming messages in plain text on the console, while GUI apps display incoming messages in the status bar or in a message box using styled text in various colors (e.g red for errors, orange for warnings, etc) with icons and other visual gimmicks.

To report errors, warnings, infos, hints, etc. use one of the static methods in luxor.status.Status. Example:

Status.info( "downloading " + _source.toExternalForm() + "..." );

Status.info( 3, carFile + " successfully created" );

Status.warning( "*** skipping unsupported file type:" + internalPath );

Status.error( "*** failed to startup web service: " + ioex.toString() );

Status.error( "*** source path for jar " + jar.getHref() + " required" );

To make sure that your reported messages get noticed and end up on the user's screen, you need to register status handlers. Use luxor.status.Status.addListener( StatusListener ) to tell Luxor who's in the loop and gets the latest updates. Example:

Status.addListener( new StatusConsole() );
Status.addListener( _statusPanel );
Status.addListener( _statusBarPanel );

Luxor ships with three pre-built status handlers.

Roll Your Own Status Handler. To create your own status handler, implement the interface luxor.event.StatusListener. Example:

public class StatusConsole implements StatusListener
{
  public void hint(String msg)    { System.out.println( msg ); }
  public void info(String msg)    { System.out.println( msg ); }
  public void warning(String msg) { System.out.println( msg ); }
  public void fatal(String msg)   { System.out.println( msg ); }
  public void error(String msg)   { System.out.println( msg ); }

  public void info( int level, String msg )
  {
    System.out.println( "[" + level +"] " + msg );
  }
}
Luxor's Form Validation Architecture

Luxor includes a form validation framework to let you check the user's input and report wrong formats, missing fields, and more.

To validate a input control's data register a luxor.event.XulInputValidationHandler. Example:

public class UserRegistrationForm extends XulForm
  implements XulInputValidationHandler
{
   XulInput _name;
   XulInput _address;
   XulInput _city;
   XulInput _zip;
   ...

   public void init()
   {
     _name    = new XulInput( this, "name" );
     _address = new XulInput( this, "address" );
     _city    = new XulInput( this, "city" );
     _zip     = new XulInput( this, "zip" );
     ...

     _name.addValidationHandler( this );
     _address.addValidationHandler( this );
     _city.addValidationHandler( this );
     _state.addValidationHandler( this );
     ...
   }

   public void validate( XulInput input )
   {
     if( input == _name )
     {
        InputValidator.checkRequired( _name );
     }
     else if( input == _address )
     {
        InputValidator.checkRequired( _address );
     }
     else if( input == _state )
     {
        InputValidator.checkRequired( _state );
     }
     else if( input == _zip )
     {
       if( InputValidator.checkRequired( _zip ) )
          InputValidator.checkZip( _zip );
     }
     ...
   }
}

How does the magic work? Every input control owns a list of validation errors and, therefore, knows if it is valid or not. As a form knows all it's input controls, it can loop over all input controls and check if the form is valid (that is, if there are no validation errors attached to any of its input controls). Every time an input control looses the focus (blurs) Luxor clears the input control's validation error list and calls all registered input control validators. It's the validator's task to add validation errors to the input control if no data is present, the zip format is wrong, etc. Example:

public static boolean checkRequired( XulInput input )
{
  String value = input.getText().trim();

  if( value.equals( "" ) )
  {
    input.getValidator().addError(
      new InputValidationError( input.getName() + " is required" ) );
    return false;
  }
  return true;
}

public static boolean checkAge( XulInput input )
{
  String value = input.getText().trim();

  if(    !isInteger( value )
      || !inRange( value, 1, 150 ) )
  {
    input.getValidator().addError(
      new InputValidationError( "number between 1 and 150 expected for " + input.getName() ));
    return false;
  }
  return true;
}

Display form validation summary in HTML. To display a form's validation errors create a luxor.event.XulFormListener that updates the form's validation errors on the user's screen every time an input control blurs (looses focus). Retrieve the form's validation error list using XulForm.getValidationErrors() and render it in HTML or plain-text using a Velocity template to create a form validation summary. Example:

private String getContent()
{
  // don't print anything if form is valid
  if( _form.isValid() )
    return "";

  HashMap data = new HashMap();
  data.put( "errors", _form.getValidationErrors() );

  String html = Xul.getTemplate( data, "template/validation-status.html" );
  return html;
}

And here is the validation-status.html Velocity template:

#if ($errors.size() == 1 )
  $errors.size() validation error
#else
  $errors.size() validation errors
#end

<ul>
#foreach( $error in $errors )
  <li> $error.getErrorMessage()
#end
</ul>

For a complete example that you can kick start at your very own desktop with full-source code, check out the validation example in Luxor's Ramses example suite.

Future additions. More to come. Note, that Luxor's validation framework is experimental, meaning that it isn't full-featured yet and that I will add more goodies in upcoming Betas based on real-world experience and examples including:

Hello Ramses - Luxor's Example Suite

Luxor ships with an example suite called Hello Ramses. Ramses includes the following apps:

Title Description
batik (work-in-progress) Batik SVG Viewer
box Shows Off Box Layout System
calc (work-in-progress) Calculator App
datagrid Shows Off Data Grid Filled With XML Data
form Shows Off Luxor XUL Forms
hello Shows Off Portlets; Portals; Menus; Toolbars; Embedded, Ultra Light-Weight, Multi-Threaded Web Server
image Shows Off Image Tag
mini Bare-minimum Luxor App
misc Shows Off Miscellaneous Luxor Goodies (e.g. Browser Target)
notepad (work-in-progress)Text Editor
transform Demos XSL/T Usage Inside XUL Documents To Build a Bookmark Menu
tree Shows Off Tree Tag
validate Demos XUL Form Validation Using HTML Validation Summaries
Luxor Config Data

Luxor's has built-in support for configuration data loaded automatically on startup. Luxor supports two formats: Java's type-less, anything-goes, name-value-pair property format and a strongly-typed XML format supporting strings, ints, booleans, arrays, base64 and more. Luxor picks up all config data files stored in the locale chrome directory tree. Example:

  locale
  +--en-us
     +--test.properties
     +--test.xml

Java's type-less, anything-goes, name-value-pair property format example:

app.vendor=Gerald Bauer
app.title=Misc Example App
app.descr=Tests Misc Luxor Services

Strongly-typed XML config data format example:

<config>

  <string id="about.title" value="About" />
  <string id="messages.title" value="Messages" />
  
  <int id="httpd.port" value="7272" />

  <array id="celia.banner">
    <string value="Vamp - Venus Application Publisher - (C)opyright Gerald Bauer 2001, 2002" />
    <string value=" Visit www.vamphq.com for more info" />
    <string value="" />     
  </array>
  
</config>

Luxor supports the following XML config data types:

Type Value Examples
int 32-bit integers between -2,147,483,648 and 2,147,483,647 <int id="proxy.port" value="5151"/>
<int id="proxy.port">5151</int>
double 64-bit floating-point numbers
boolean true(1) or false(0)
string Unicode text
date Date
base64 Binary information encoded as Base 64 as defined in RFC 2045
array Single-type array

To retrieve config data such as strings, ints, or doubles use the following XulManager methods:

Method Comments
String getString( String key )
String getString( String key, String defaultValue )
String[] getStringArray( String key )
int getInt( String key, int defaultValue )
Apache Velocity Templates

Luxor's built-in Velocity template engine is not limited to HTML. You can create plain-vanilla ASCII text, XML documents, SQL scripts and more.

Predefined Data Objects Luxor's lets you access all Java System properties in Velocity templates. Note, however, that you need to replace all dots with dashes (e.g user.name becomes user-name).

Luxor loads Velocity templates always on demand (that is, never on startup). Therefore, don't store them in the chrome's startup directory tree.

Velocity Logger Luxor redirects Velocity log messages to its own class luxor.template.LuxorVelocityLogger. To see Velocity log messages either turn on Java's built-in logging using properties (e.g. java.util.logging.*) or add Luxor status handlers. Example:

// make sure we don't miss any errors, warnings, hints.
Status.addListener( new StatusConsole() );

Links/Resources

Logging - Debugging Tips and Tricks

Luxor uses a thin wrapper around Java's 1.4 built-in java.util.logging.Logger class. By default Java's runtime spits out all log messages on the console ranking as INFO or higher. To let the runtime spit out more or less log messages or to let it send log messages to a file or to a socket use Java's standard java.util.logging.* properties.

Why bother wrapping Java's built-in logging toolkit?

Luxor uses the log message types below, ranked from highest to lowest. Luxor's types differ slightly from Java's built-in logging types: Instead of SEVERE for all errors Luxor uses FATAL and ERROR. Luxor adds DEBUG as an alias for FINE and adds the new message type HINT one notch below INFO and one above CONFIG/DEBUG.

Luxor java.util.logging Audience Comment
FATAL SEVERE Grandma (*)
ERROR SEVERE Grandma
WARNING WARNING Grandma
INFO INFO Grandma
HINT INFO Grandma
CONFIG CONFIG Sys Admin
DEBUG/FINE FINE Developer
FINER FINER Developer
FINEST FINEST Developer

(*) also known as end-user

Configuring Loggers. By default the Java runtime picks up the logging settings from the logging.properties config file in its lib directory (e.g. jre/v14/lib). Note, that if you installed a dev kit (aka JDK) you likely have two copies of the Java runtime on your machine. To find out which Java runtime Web Start picks up to fire off your app peek into javaws.cfg, Web Start's config file residing in its home directory (e.g. java/jws/v1.01-2). The snippet below reveals my box'es settings:

   
javaws.cfg.jre.1.product=1.4.0
javaws.cfg.jre.1.platform=1.4
javaws.cfg.jre.1.location=http\://java.sun.com/products/autodl/j2se
javaws.cfg.jre.1.path=c\:\\java\\jre\\v14\\bin\\javaw.exe

As an alternative you can kick start the Hello Ramses Luxor Example app (that is, hello.jnlp) and switch over to the system info page. Under the directories heading you'll find the nugget you are looking for. Example:

User Home: c:\windows
Temp Directory: c:\windows\temp
Java Home: c:\java\jre\v14
Web Start Home: c:\java\jws\v1.01-2

By default the Java runtime uses the settings below to spit out all log message ranked as INFO and above to the console (aka command line shell, dos box):

# "handlers" specifies a comma separated list of log Handler classes.
handlers= java.util.logging.ConsoleHandler

# Default global logging level.
.level= INFO

# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

To dump the log messages to a file in the user's home directory as well as to the console append a FileHandler and configure it. Example:

handlers= java.util.logging.ConsoleHandler, java.util.logging.FileHandler

# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.level = FINE
java.util.logging.FileHandler.limit = 10000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

Note, refrain from using the prelisted java.util.logging.XMLFormatter unless you have time to kill (as your app won't pop up in an instant).

As an alternative you can sidestep the factory-shipped jre/v1.4/lib/logging.properties logging config file and preserve it untouched and direct the Java Runtime to use your very own config file instead. Add a property tag for java.util.logging.config.file pointing to your config file to your app's JNLP startup file. Example:

<property name="java.util.logging.config.file" value="c:/sandbox/etc/logging.properties" />
Using Luxor's Built-In Ultra-Light Weight, Multi-Threaded Web Server

Why not embed Apache Tomcat? Luxor's built-in web server is ultra-light weight in contrast to Tomcat so that every Luxor app can startup, configure and use it's own web server (though they can share a caching proxy server). Luxor's web server is not designed to serve up mission critical, 24x7x365, always-up, high performance web sites hit by thousands of customers at the same time instead it is designed to serve Grandma playing with a Luxor app on a desktop computer.

Web Server Comparison Chart:

Web Server Domain Audience Simultaneous Users
Apache Galaxy Million Internet Surfers 1000+
Tomcat Family Home Network, Low-Traffic Web Site, Power User Workstation A Handful Users and/or Apps 10+
Luxor Luxor Desktop App Grandma Emma 1+

Start Me Up. To start Luxor's built-in, ultra light-weight, multi-threaded web service use the luxor.http.WebServer class. Pass in the socket port (e.g. 7272) plus a reference to a web resource manager and off you go. Example:

try
{
  WebServer webServer = new WebServer( 7272, webResourceManager );
  webServer.start();
}
catch( IOException ioex )
{
  Status.error( "*** failed to start http service (built-in web server): " + ioex.toString() );
}

Web Resource Manager. Use web resource managers to tell Luxor's built-in web server what you want to serve up. Luxor ships with the built-in, ready-to-use web resource mangers below:

Class Usage
luxor.http.loader.WebResourceManager
luxor.http.loader.ClassResourceLoader
luxor.http.loader.XulServletResourceLoader
luxor.http.loader.CacheResourceLoader
luxor.http.loader.FileResourceLoader
luxor.http.loader.FileContextResourceLoader

Scenario I: How to serve up web pages, graphics, and more packaged in jars stashed away in Web Start's cache.

// make content of selected jars availabe through built-in web server
try
{
 Class webResourceAnchorClazz = Class.forName( "WebResourceAnchor" );
 webResourceManager.addResourceLoader( new ClassResourceLoader( webResourceAnchorClazz ) );

 Class crossRefAnchorClazz = Class.forName( "CrossRefAnchor" );
 webResourceManager.addResourceLoader( new ClassResourceLoader( crossRefAnchorClazz ) );
}
catch( ClassNotFoundException cex )
{
  Status.error( "*** failed to locate built-in web resources: " + cex.toString() );
}

Scenario II: How to serve up portals, that is, web pages made up of portlets and static HTML snippets.

// make xul servlets available through built-in web server
webResourceManager.addResourceLoader( 
    new XulServletResourceLoader( "ramses" ) );

Scenario III: How to create wizards for your app with web pages and plain-vanilla hyperlinks.

Debugging Luxor's Box Layout

To help you figure out your layout when arranging your furniture using Luxor's horizontal (left-to-right) and vertical (top-to-bottom) boxes, turn on the xul.debug.layout property by adding it to your app's JNLP startup file. Example:

<property name="xul.debug.layout" value="true" />

Once you turned xul.debug.layout on, Luxor will draw a four-line-thick red border around vertical boxes and a four-line-thick blue border around horizontal boxes.

Tip: How To Keep Track Of Your Chrome Keys In Java

Avoid sprinkling your chrome keys all over your sources or even worse hard-wiring them in place without using constants. Instead collect all your chrome keys in constant holder classes. Once you have all your chrome keys lined up in a constant holder class you can, for example, use a code editor's auto-completion to speed up coding. Using constants also strengthens your apps as the compiler enforces at compile-time that you only use chrome keys defined as constants. If you feel ambitous you can even create your own chrome key checker that reads in constant holder classes and checks all your xul files if the keys match at compile-time.

public class Chrome
{
  public static class MenuBar
  {
      public static final String MAIN = "MAIN";
  }

  public static class Icon
  {
      public static final String CALC = "CALC";
  }

  public static class Box
  {
      public static final String DISPLAY = "display";
  }  
}

or put your keys in interfaces to spare you from typing public static final for each and every constant. Example:

public class Chrome
{
  public interface MenuBar
  {
     String MAIN = "MAIN";
  }

  public interface Icon
  {
     String CALC = "CALC";
  }

  public interface Box
  {
     String DISPLAY = "display";
  }  
}
Built-In Chrome Loaders

Class Description
luxor.core.loader.XulFileResourceLoader
luxor.core.loader.XulJarResourceLoader
luxor.core.loader.XulResourceLoaderManager
Tip: Shortcut for getting internationalized strings

The long-winded, type-intensive way to get internationalized string is using XulManager.getXulManager().getString() or Xul.getString().

The Better Way. To safe on typing and simplify your code, cut and paste the static str method below to every class where you use internationalized strings.

 private static String str( String key )
 {
  return XulManager.getXulManager().getString( 
     key, "string " + key + " not found" );
 }

Now you can type

setTitle( str( "app.title" ) ); 

instead of clumsy

setTitle( Xul.getString( "app.title" ) );
setTitle( XulManager.getXulManager().getString( "app.title" ) );
Chrome's Structure - What Goes Where?

You can divide up you app's chrome in three kingdoms: Startup, Locale and The Works.

Startup The startup directory tree holds all resources that Luxor loads at once when you call XulManager.load().

Do's

Don'ts

Locale

Do's

The Works (aka The Rest)

chrome:// - What it is - When to Use

Luxor adds the custom chrome:// URL protcol handler that lets use easily reference resources within your apps chrome no matter if packed up in jars or spread out in loose files.

Example chrome:// URLs.

Usage Example: Display Pre-packaged HTML page in built-in web browser window.

Usage Example: Use DisplayURL Tag to Display pre-packaged HTML page in built-in web browser window target.

Luxor And Open Standards - Welcome To The Free World

Luxor builts on proven open standards.

World Wide Web Consortium (W3C)

Web Standard Date Link
HTML - Hyper Text Markup Language 4.01 December 1999 http://www.w3.org/TR/html401 third-party link
XHTML - Extensible Hyper Text Markup Language 1.0 January 2000 http://www.w3.org/TR/xhtml1 third-party link
CSS1 - Cascading Style Sheets Level 1 (Revision) January 1999 http://www.w3.org/TR/REC-CSS1 third-party link
CSS2 - Cascading Style Sheets Level 2 May 1998 http://www.w3.org/TR/REC-CSS2 third-party link
XML - Extensible Markup Language 1.0 (Second Edition) October 2000 http://www.w3.org/TR/REC-xml third-party link
XSL - Extensible Stylesheet Language 1.0 October 2001 http://www.w3.org/TR/xsl/ third-party link
XSLT - XSL Transformations 1.0 November 1999 http://www.w3.org/TR/xslt third-party link
XPath - XML Path Language 1.0 November 1999 http://www.w3.org/TR/xpath third-party link
SVG - Scalable Vector Graphics 1.0 September 2001 http://www.w3.org/TR/SVG/ third-party link

Internet Engineering Task Force (IETF)

Mozilla.org

Apache Jakarta

Sun Microsystems

Guido van Rossum

More Quick Links: Batik SVG · Velocity · Python · Jython · Groovy · JDOM · dom4j · Jaxen · XDoclet · Eclipse SWT · wx4j · Java Gnome · KDE/Qt Java · Kaffe · gcj · SableVM · IKVM · Mono · DotGNU · Gtk# · Qt# · Parrot · Mozilla · Relax NG
Hosted by SourceForge SourceForge Logo For questions related to the use of Luxor, please consult our web pages. If that fails, the luxor-xul-user mailinglist might help.
Please send comments on our web pages and the development of Luxor to our public luxor-xul-develop mailinglist.
Maintained by Luxor Team
Copyright © 2001, 2002, 2003, 2004, 2005 Luxor Foundation