Thoughts on software and life.

Tuesday April 26

Boxely, Part 3 of 3

This is part 3 in a 3 part post about Boxely: Here is part 1 and part 2.

Boxely is different than XUL in many ways - some are incremental improvements that could be added to XUL, and others are fundamental differences that could not easily be ported.

XML Stylesheets - One of the most visible differences between Boxely and XUL is that Boxely's cascading stylesheet language is not CSS. Boxely stylesheets are just XML. Unlike CSS, these stylesheets can contain more than just style rules; they contain objects such as bitmaps, brushes, gradients, and animations which can be re-used and shared. In this way, the stylesheets are like a mix of CSS with SVG and SMIL.

Data Binding - Boxely had a very simple data binding system, although I can't tell if it still exists in the current beta. Unlike XUL, which requires that you beat your data model into a bloody RDF graph, Boxely simply asked you to implement a simple interface that mimicked a hierarchy. Better yet you could just bind a hierarchy of Python objects without having to write any new code.

Animation - Boxely supports an animation system similar to SMIL. Unlike SMIL, it is integrated with the style system, so you can write something like "when the mouse is over this text, play the animation that makes it glow from its current color to blue". You'll notice this kind of animation is very common in AIM, because it is so easy to write.

Absolute Positioning - Any Boxely element can be taken out of the flow and positioned absolutely, or relative to some other element. This works something like HTML absolute positioning, but goes a lot further. You can attach an element to any other element in the DOM, and make its position and size relative to that other element. For example, you could add a "sticky note" anywhere in the DOM, and then tell the sticky note to attach to the bottom-right corner of some button, and it would stay there even as the window is resized.

Z Ordering - Every Boxely element recognizes the "z-index" style. In XUL, there is only one Z order, and it cannot be changed. You'd be surprised how annoying this is. It's very common to want to draw something above or below another element, regardless of where the two are in the flow.

9-slice Backgrounds - Boxely supports 9-slice image backgrounds, which allow you to use a single image as the background for something like a button, in which the edges do not scale but the center does. This is really the only way to go for skinning resizable widgets that contain text.

Flow Layout - Boxely supported a layout model in which elements would wrap around to the next line when they overflow their container.

Tray Icons - Boxely lets you easily put an icon in the system tray with a control called "statusIcon". You can even attach a context menu to the tray icon the same way you'd attach a menu to any other control.

Popping out of Windows - Any Boxely element can drawn outside of the bounds of its window. This makes for some really neat tricks. I used to have two demos to show this off. One was a window with a drawer, like in OS X. The drawer was actually positioned at negative coordinates. The other drawer was a mock of the OS X dock. When icons balloon out as you mouse over them, they become wider than the dock itself, which is bounded by the main window, but the overflowed portions of the icons are still visible. Behind the scenes the native window is just expanded and repositioned seamlessly.

No-Nonsense Drag and Drop - Boxely doesn't require you to write a ton of script to do drag and drop, as XUL does. Setting and getting the data to be dragged is one line of code, where in XUL it takes dozens. As a bonus, it is trivial to create an image to follow the cursor during a drag with Boxely - you simply point to any box in the DOM, and the box is rendered to an offscreen buffer and fed to the OS drag and drop API.

Two-Way Broadcasters - Boxely supports two-way broadcasting of attributes. Mozilla supports only one way. Two way binding means, if an element is observing the broadcasted attribute "foo", and I change the value of "foo" on the element, it updates the broadcaster to its own value. This allows you to keep a bunch of stuff synchronized without any scripting.

Re-usable Event Bindings - One of the goals of Boxely was to make it easy to write new controls that "feel right". One of the ways that home-grown controls often don't "feel right" is if they don't support the keyboard and mouse interaction that you expect. For instance, if you write a new listbox-like control, I expect that typing shift-home is going to select everything from the current row to the top, but too often this sort of thing doesn't work. To make this trivial, Boxely supports something called "behaviors", which allow you define a set of event bindings that can be re-used. If you implement one of the common behavior interfaces, such as "selectable" or "button", you'll automatically get the correct keyboard and mouse bindings for the operating system. In XUL, every control author has to re-invent their behaviors from scratch, and they usually miss a few things.

Out-of-line Scripts - Boxely supports something like Mozilla's XBL, called Gadgets. The most important difference here is that Gadget methods and properties are not embedded in XML, as XBL's are. I always hated this about XBL, because an XML description of a class is so ugly and long-winded compared to the straight Javascript equivalent, plus you lose the Javascript syntax highlighting in your editor. So, Boxely Gadgets import a JS file and binds all of its global variables and functions as interface to the class.

Executable Files - Boxely applications could be started just by double-clicking any Boxely XML file. There was no need to package the app in a zip file and write a "manifest", though you could if you really wanted to.

NO COM - If you wanted to make your components scriptable, you wrote a Python binding, which is easily automated using a number of tools like SWIG. Then you got all the glories of the Python object system, and no nasty IIDs and ContractIDs polluting your code. Of course, AOL has decided they like COM, and so this feature is no more.

There are lots more features I could go on about, but you get the idea. The only regret I have is that I didn't make it open source from the start. Now AOL owns it, and I am left watching my creation grow out of my control.

On a closing note, I have a suggestion for my friends at AOL. If you were to port Boxely to OS X and Linux, and maybe, oh I don't know, open source the library, I think you'd have a real winner on your hands! ;)

Posting your comment. Please Wait...