Mozilla Platform – UI Basics [Part 2]

Last time I covered some simple XUL for creating windows, menus and toolbars. This time I’ll look at dialogs, your own and common OS dialogs too. Dialogs are pretty fundamental to a desktop application. Certain types of dialogs are used over and over. So much so that the OS can provide a default implementation. File open and save are good examples. Whenever possible, it is a good idea to reuse these ‘native’ dialogs so users get a consistent experience across applications.

Custom Dialogs

Building dialogs in XUL is very similar to creating windows. Each dialog seems to be in it’s own XUL file. Also like windows, XUL provides a

element to act as the container for the dialog. As their window counterparts, dialog XUL files can have DTD, CSS, JS links too. Here is an example XUL dialog:







  

  
  
    
    
      
      
      
    
  


XUL window elements have a special method to openDialogs. Here is the code needed to open a dialog:


function openDialog() {
  window.openDialog("chrome://basicapp/content/dialog.xul", "newdlg", "modal");
}

mydialog.png
(on Win2K)

The first thing that caught my eye about

is the button and related attributes. In an effort to make things easier for developers and more consistent for users, XUL has a mechanism to auto create and position the core dialog buttons (‘ok’, ‘cancel’ and help’ for example). The developer just declares the need for the button, the caption and access key for the button and the JS function to call if the button is pressed. XUL handles placing and styling the buttons on the dialog. This is also nice for cross-platform applications too. Each OS seems to have its own convention for where buttons should be placed on a dialog. Here is a short list of the button attributes (see the above link for a complete reference):

  • buttons – comma separated list of buttons to show on dialog (‘accept’, ‘cancel’, ‘help’, ‘extra1’ and ‘extra2’)
  • buttonlabelaccept – label for accept button (same for other buttons)
  • buttonaccesskeyaccept – access key for accept button (same for other buttons)
  • ondialogaccept – Javascript to execute if accept is pressed (same for other buttons)

XUL has a wide range of input controls you can use on a dialog. In the future, I will try to go into more detail on some of the existing and planned XUL input controls. Not too sure if I’ll use the , but if I did, the single element would be a big time saver over building the header from scratch.

Common Dialogs

Some of the most frequently used common dialogs are for opening and saving files. For instance, Windows has supported builtin file open and file save dialogs for many years. It makes creating an application easier for developers. The consisent UI also makes using an application easier too. XUL supports native implementations of filepickers (Mozilla for File Open and Save dialogs). Newer releases will allow using preferences to switch to a XUL emulation filepicker, if you want to. The XUL filepickers are XPCOM components and must be instantiated before using, like this:


function doFileOpen() {
  /* See: http://developer.mozilla.org/en/docs/XUL_Tutorial:Open_and_Save_Dialogs */
  
  var nsIFilePicker = Components.interfaces.nsIFilePicker;
  var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);

  fp.init(window, "Open File", nsIFilePicker.modeOpen);
  fp.appendFilters(nsIFilePicker.filterText | nsIFilePicker.filterAll);
  
  var res = fp.show();
  if (res == nsIFilePicker.returnOK) {
    var thefile = fp.file;
    alert(thefile.leafName);
    // --- do something with the file here ---
  }  
}

XUL does not appear to currently support any other common dialogs. That could change with Firefox 2 and 3 releases coming up. Firefox and Thunderbird both support nearly native Page Setup and Print dialogs. However, XUL does support elements to make creating Wizards a simple task as well.

I still want to look at Input Controls, Printing, Clipboard and XPCOM.

Mozilla Platform – Getting Started with XULRunner

I want to build a simple XUL-based Windows desktop application. If you’re going to build a XUL-based desktop application, you’ll probably need to install XULRunner. In this post, I try to get XULRunner installed and make sure it runs a bare-bones application.

Step 1 – Download XULRunner: The Mozilla developer page lists 1.8.0.1 as the most recent release, but I see there is also a 1.8.0.4, so that is the one I downloaded. UPDATE: 1.8.0.4 release and SDK are available from Mozilla FTP.

The XULRunner download is a ZIP file, not a true install. As a developer, I like the idea that XULRunner only needs to be unzipped onto my machine. I am assuming that it doesn’t need to hook into my Windows system and that’s a good thing.

Step 2 – Install XULRunner: I unzipped the archive to a new “c:\program files\xulrunner” folder. Pretty simple so far.

Time to start a simple, bare bones application shell. Call it a XUL “Hello World” if you want, but I need to make sure that XULRunner will work at all. Googling turned up a nice tutorial here. It is definately worth reading. Using the tutorial, I created a simple bootstrap application. All of what you see below can be found in Ryan’s tutorial and the Mozilla XULRunner documentation pages.

Step 3 – Create application folder struture: I create the root in a new “c:\program files\xulapp” folder. Here is the subfolder structure:


/xulapp
  /chrome
    /content
      main.xul
    chrome.manifest
  /defaults
    /preferences
      prefs.js
  application.ini

Notice that there are 4 files in the folder structure: application.ini, chrome.manifest, prefs.js & main.xul

Step 4 – Setup application.ini: The application.ini file acts as the XULRunner entry point for your application. It seems to be used to configure how your application intends to use the XULRunner platform as well as configure some information that XULRunner uses to run your application. Here is mine:


[App]
Vendor=Finkle
Name=Test App
Version=1.0
BuildID=20060101
Copyright=Copyright (c) 2006 Mark Finkle
ID=xulapp@starkravingfinkle.org

[Gecko]
MinVersion=1.8
MaxVersion=1.8

Step 5 – Setup Chrome Manifest: The chrome manifest file is used by XULRunner to define specific URI’s which in turn are used to locate application resources. This will become clearer when we see how the “chrome://” URI is used. Applications can be distributed compressed in a JAR file or uncompressed as folders and files. I am using the uncompressed method for now. Here is my manifest:

content myapp file:content/

Step 6 – Setup Preferences: The prefs.js files is used to tell XULRunner the name of the XUL file to use as the main window. Here is mine:

pref("toolkit.defaultChromeURI", "chrome://myapp/content/main.xul");

XULRunner preferences include:

Step 7 – Create some XUL: Finally, we need to create a simple XUL window. Nothing fancy here, just the minimum we need to make a window. No menus or anything:






  

Step 8 – Run the App: The moment of truth. We need to get XULRunner to launch the bare-bones application. From a command prompt opened to the “c:\program files\myapp” folder, we should be able to execute this:

xulrunner.exe application.ini

Of course, xulrunner.exe must be in the PATH. Because of where I unzipped XULRunner, I could also try this if xulrunner.exe is not in the PATH:

..\xulrunner\xulrunner.exe application.ini

Success! Here is a screenshot of the bare bones application running on Win2K:

My App screenshot

My next step will be to add much more to the bare bones application. I want to explore as much of XUL as I can as fast as I can. For those that want to skip straight to the end, here is a ZIP of the My App application:

My App sample

Mozilla Platform – Basic Desktop Application

After a short break, I am back to working with the Mozilla platform (XUL, JavaScript & XPCOM). I want to begin exploring the platform by building a basic desktop application using XULRunner. Given that Firefox, Thunderbird and the rest of the Mozilla suite is written using the platform, it a safe bet that it can be used to build a basic application. However, I know nearly nothing of the Mozilla platform, so I need to start somewhere.

I consider a basic desktop application to at least be able to support:

  • Main window, popup windows and dialogs (modal and non-modal)
  • Menus and toolbars (with images and themes)
  • Basic assortment of controls (edits, buttons, checkboxes, radiobuttons, lists, trees & tabs)
  • OS common dialogs (file open & save at a minimum)
  • Clipboard operations
  • Printing
  • Help system

Alright, I am off to build my basic application. I’ll update this post as I go. I wouldn’t go so far as to call it a tutorial, but I’ll link to any tutorials I find along the way.

Update:

  1. Getting Started with XULRunner
  2. UI Basics [Part 1]
  3. UI Basics [Part 2]

RichDraw – Simple VML/SVG Editor

Rich text editing is a feature that is finding it’s way into many new web applications. It’s becoming a feature that users can’t live without. We are also starting to see some graphical editing applications. In an effort to satisfy a potential, future, demand to have graphical editing everywhere (it could happen), I created a Javascript component called RichDraw.

RichDraw works in IE 6+, Firefox 1.5+ and Opera 9, using VML or SVG as the underlying renderer. Opera 9 has a small issue with the way I adjust/offset the mouse coordinates, but I’ll look into that. Currently the component supports:

  • Creating basic shapes (rectangle, rounded rectangle and ellipse) and lines.
  • Selecting shapes.
  • Deleting selected shapes.
  • Dragging shapes with mouse.
  • Setting fill color.
  • Setting line color and width.
  • Retrieving the markup.

I don’t know if there are any real uses for RichDraw in it’s current state. There is a lot that could be done to enhance RichDraw and make it more usable. Probably the most important feature would be loading markup back into the editor. On the surface, that’s easy enough to add. However, there could be situations where the markup is saved from IE (VML) and loaded back into Firefox (SVG). This would not work. I am planning on converting the VML to SVG when retrieving and converting it back when loading. That way RichDraw always appears to be using SVG. I will build from my IESVG code to handle the conversions.

Other enhancements include:

  • Resizing selected shapes.
  • Ordering (Bring to Front, Send to Back).
  • Scrollable workarea.
  • Inserting text.
  • Inserting images.

Required files: richdraw.js, svgrenderer.js, vmlrenderer.js

Demo file: richdraw_demo.htm

SVG in IE (Update)

I made some changes to the IESVG behavior. I am trying to get better feature coverage without making the rendering too slow. I have been testing the code using some SVG images from different places, trying to figure out what parts of SVG seem to be more important than others. Recents chanegs include:

  • Basic support for gradient fills. It’s pretty weak and may have not SVG-correct.
  • Basic support for svg:g elements.
  • Switched code to use DOM methods (appendChild and replaceChild) instead of slower, string-based methods.

I plan to add more support for gradients. I also plan to add some scripting support. You can do scripting now, but you need to treat the elements as VML, not SVG. I plan to add some methods to the VML elements to make them appear more SVG-like when scripting.

Files can be downloaded from here. I added the SVG lion to the samples:

Sample files: lion.htm (IE), lion.xhtml (Firefox)

Update: Fixed 404 on link above.

SVG in IE

Inspired by Emil’s emulation of the canvas tag in IE, I put together a simple SVG emulation behavior for IE. As with Emil’s code, I am making use of Internet Explorer’s VML support. The behavior will walk the SVG element structure and attempt to convert to appropriate VML elements. It’s far from complete, but it does a decent job. Supported features include:

  • Basic shapes: rect, ellipse, circle, polyline, polygon and path.
  • Simple fills commands (in attributes and CSS): fill and fill-opacity.
  • Simple stroke commands (in attributes and CSS): stroke, stroke-width, stroke-opacity and stroke-linejoin.

The behavior works on Inline-SVG, not standalone SVG files. Currently, the behavior only works on static SVG. You can’t use Javascript to interact with the SVG. Javascript can only access the VML elements. I plan to add support for and gradients (although this could be hard). I also want to eventually add support for scripting by adding SVG-like methods to the VML elements. You’ll notice that the SVG elements are in an explicit svg namespace. This seems to be a requirement for the behavior to work, but I am trying to remove the need.

Required files: iesvg.htc, iesvg.js

Sample files: iesvg_test.htm (IE), iesvg_test.xhtml (Firefox)

The sample files are exactly the same, only the extensions are different. Firefox must have Inline-SVG in an XHTML file. There is probably a way I can get Apache to trick Firefox into thinking the HTML file is an XHTML file (or get IE to think the XHTML file is an HTML file), but I haven’t got it working yet.

Update: Core files have been updated. Test files have gradient examples.

Hello JavaScript

Coming from a C++ background, I found JavaScript very comfortable when I started doing DHTML programming. I was impressed with some of the things it could do with properties and functions. Other dynamic languages, Python and Ruby for example, have been getting lots of press lately while JavaScript has been quietly powering the Web.

That seems to be changing. I am reading a lot more about JavaScript. This is due in large part to Google’s GMail and Suggest (how it works). These are great examples of what can be done with DHTML and created a lot of buzz. The JavaScript Weblog posted a summary of predictions that seem to be shared by others.

Go JavaScript!