The Font of Wisdom: A Basic Boxely App, Part 2
by Kurt Cagle
April 2, 2007
In the first article in this series, we developed a Boxely framework for our FontViewer application: we created a Boxely window, placed boxes inside the window, and we applied Boxely button and text gadgets. In this article, we'll apply Boxely services and styles to complete the base FontViewer application.
Figure 1 shows the FontViewer application as it exists after the development described in "The Font of Wisdom: A Basic Boxely App, Part 1":

Figure 1. FontViewer with gadgets added
So far, this particular example doesn't look that radically different from XUL. However, one of the areas where XUL was a little weak was in componentization--utilizing the XBL language to define components that were then assignable, for the most part, from CSS. The approach that Boxely takes here is a little different--in that they focus on the deployment of "gadgets" as separate components.
Boxely Gadgets
A gadget can be thought of as a subcomponent that has its own scripting and structural bindings attached to it, and can in turn pass control onto subcontained objects. The gadget acts as a mechanism to define new XML elements, which can dramatically simplify the overall design of the application. For instance, suppose that rather than dealing with a generic button, you wanted to create a specialized button for FontViewer. The code for moving forward and back in the font list (which I'll cover later) is almost identical with regards to moving forward versus moving back in the data list, but I do need to maintain some kind of index about where in the list of fonts the application is pointing. A good fwButton can thus be defined with the resource library (<res:library>) as:
<res:library>
<res:gadget id="fvFontButton" type="control">
<res:attributes direction="forward" index="0"/>
<res:parts>
<box:button inherits="label=label"/>
</res:parts>
</res:gadget>
....
</res:library>
This component, when defined, can then be invoked as part of another gadget, in this case the "header" gadget:
<res:gadget id="header">
<res:parts>
<box:hbox s:flex="1">
<fvFontButton label="Previous Font" direction="back"/>
<fvFontTitle s:flex="1" s:hAlign="center"/>
<fvFontButton label="Next Font"/>
</box:hbox>
</res:parts>
</res:gadget>
The <res:attributes> element provides a way to define attribute parameters for a given gadget, and as importantly provides a mechanism for setting the default values for the parameters. Thus, direction is defined for fvFontButton element, but only needs to be explicitly given if the direction isn't forward.
The res: tag isn't strictly necessary, since we're defining that XML namespace as an attribute in the <window> element (see Listing 1 below). But explicitly stating the namespace repeatedly in the code won't stop your program from running. Some developers consider XML code easier to understand if explicit namespace labels are applied. Whichever you prefer will work.
Note also the use of the inherits attribute in the fvFontButton definition. This very useful property makes it possible to pass a particular value (in this case the contents of the label attribute) on the gadget to the label attribute on the <box:button> element. (The transfer goes from right to left; that is, label=label is the same as box:button:label = fvFontButton:label.) You can pass quantities defined in a gadget's <res:attributes> tag in the same way (i.e., <box:button inherits="label=direction"/>) and if you have multiple such inherited attributes, you'd use a comma to separate them: "label=direction,fontSize=myFontSize" and so on.
This can dramatically change the layout of the document, as it becomes possible to describe an application not in terms of Boxely elements but rather in terms of your own user-defined schema. For instance, Listing 1 illustrates the same document expressed as nested gadgets:
Listing 1. FontViewer defined using gadgets
<?import href="box://ocpToolkit/content/core/coreGadgets.box"?>
<?import href="box://ocpToolkit/theme/default/toolkit.box"?>
<window xmlns="http://www.aol.com/boxely/box.xsd"
xmlns:s="http://www.aol.com/boxely/style.xsd"
xmlns:on="http://www.aol.com/boxely/reaction.xsd"
xmlns:box="http://www.aol.com/boxely/box.xsd"
xmlns:res="http://www.aol.com/boxely/resource.xsd"
resizable="true" s:fill="white"
translucent="false" chromeless="false"
s:width="500" s:height="300" title="FontViewer"
>
<res:library>
<res:gadget id="fvFontButton" type="control">
<res:attributes direction="forward" index="0"/>
<res:parts>
<box:button inherits="label=label"/>
</res:parts>
</res:gadget>
<res:gadget id="fvFontTitle" >
<res:parts>
<box:text value="Font Name" s:fontSize="24pt"
s:hAlign="center" s:vAlign="center"
inherits="value=value" />
</res:parts>
</res:gadget>
<res:gadget id="fvFontSample">
<res:parts>
<box:text s:fontSize="18pt" inherits="value=value"
id="fontSample"/>
</res:parts>
</res:gadget>
<res:gadget id="fontWalker">
<res:attributes index="0" fontName=""/>
<res:parts>
<box:hbox s:flex="1">
<box:content/>
</box:hbox>
</res:parts>
</res:gadget>
<res:gadget id="textDisplay">
<res:parts>
<box:vbox s:flex="6">
<box:content/>
</box:vbox>
</res:parts>
</res:gadget>
<res:gadget id="fontViewer" language="jscript"
code="fontViewer.js" type="box">
<res:parts>
<box:vbox s:fill="white" s:flex="1">
<box:content/>
</box:vbox>
</res:parts>
</res:gadget>
<res:script/>
</res:library>
<fontViewer>
<fontWalker>
<fvFontButton label="Previous Font" on:click="moveCursor('previous')"/>
<fvFontTitle s:flex="1" s:hAlign="center" id="fontTitle"/>
<fvFontButton label="Next Font" on:click="moveCursor('next')"/>
</fontWalker>
<textDisplay>
<fvFontSample value="The quick brown fox jumps over the lazy dog."/>
<fvFontSample value="ABCDEFGHIJKLMNOPQRSTUVYWXYZ"/>
<fvFontSample value="abcdefghijklmnopqrstuvwxyz"/>
</textDisplay>
</fontViewer>
</window>
One final element of note with regard to gadgets: many gadgets are containers; that is, they contain other elements that may not in fact be used directly by the gadget in question. In order to facilitate the rendering of these components, you would use the <box:content/> element to indicate to Boxely that any subordinate children should be rendered in the context of the given container. For instance, the overall <fontViewer> gadget is defined in this manner:
<res:gadget id="fontViewer">
<res:parts>
<box:vbox s:fill="white" s:flex="1">
<box:content/>
</box:vbox>
</res:parts>
</res:gadget>
It's also worth mentioning here that gadget definitions, as resources, must be defined within the resource library. The library serves very much the same purpose as a DLL library does for a normal Windows app--the code within the library isn't directly executed, but instead contains the XML structures (and links to scripts) that are used like building blocks in the final application.
Abstract Application Description
Something pretty profound has happened here. The application went from being a listing of concentric blocks into being a completely abstract description of a system, where you are able, in turn, to define the specific behavior of each particular tag in that description. Normally (once you've got a few Boxely apps under your belt) you will likely start with that higher-order description and work your way down into the details, rather than building from the bottom up, but especially as you're learning it's usually best to start out with the physical description and work your way up to the abstraction. Additionally, you should think about the fact that you could, in theory, represent any XML document in this manner and create an implementation based upon that document (for instance, building an invoice system where each invoice XML representation had its own associated gadget). Admittedly, not all XML documents decompose nicely along application grounds (and there's usually a certain amount of semantic overhead that you need to incorporate into the model) but it's often a very good point from which to start.
Making the Application Interactive
Now, this particular model doesn't have a huge amount of functionality. You can press the buttons, but other than depressing and returning they don't do much of anything. The next stage is to take this UI and add a modicum of interactivity and functionality to it. This is where the <code> tag comes in. The role of a code tag is to define the interface functionality for a given application (or a gadget). You can define gadget-level code, but for the purposes of this article, the code in question will be defined at a global level.
The changes involved for incorporating user-defined code are fairly minimal. In this particular case, it is first necessary to place a pointer to a <code> element into the FontViewer application itself:
<fontViewer>
<code id="main" language="jscript" src="fontViewer.js" />
<fontWalker>
...
This indicates that the file uses the jscript language (the standard language, though Boxely may add other scripting libraries in the future) and that it points to the fontViewer.js file. This particular file should be located in the same directory as the myApp.box application (or the box indicated by the fontViewer.ini file)--in our case, the content directory. You can, of course, also define multiple blocks of code in this manner, with the potential of manipulating them, so the use of an ID to identify the code block can come in handy.
This particular script, fontViewer.js, is relatively simple (see Listing 2):
Listing 2. fontViewer.js
var fontIndex = 0;
var fontList = null;
var fontCount=0;
function onFontViewerInit(){
var dictionary = appUtils.enumFonts();
if (dictionary){
fontList = dictionary.allKeys();
var comparator = shell.serviceManager.basics.comparator;
fontList.sort(comparator.stringAscending, "en-Us");
fontCount = fontList.count;
}
}
function moveCursor(dir){
var dirValue = 1;
if (dir == "previous") {dirValue = -1;}
var fontTitleBox = scene.getBoxById("fontTitle");
fontIndex = (fontCount + fontIndex + dirValue) % fontCount;
var fontName = fontList.getValue(fontIndex)
fontTitleBox.setAttribute("value",fontName);
var fontSampleGadget = scene.getBoxById("fvFontSample");
var fontSamples = scene.getBoxesByTag("fvFontSample");
for (var i = 0; i != fontSamples.count;i++){
var fontSample = fontSamples.getValue(i);
var fontSampleText = fontSample.getPartById("fontSample");
fontSampleText.setStyle("fontFamily",fontName);
}
}
In this case, the application defines only two functions: onFontViewerInit(), to be invoked when the fontView is first initialized, and moveCursor(), which is used to set the current font from a list of fonts. The specific details of this application will be dealt with in greater depth, though in general what you are looking at is the use of the appUtils utility class to retrieve a dictionary of fonts that are then converted into a list of font names that provide the "data" for the application:
var dictionary = appUtils.enumFonts();
if (dictionary){
fontList = dictionary.allKeys();
var comparator = shell.serviceManager.basics.comparator;
fontList.sort(comparator.stringAscending, "en-Us");
The comparator object is an example of a Boxely service; in this case, one that returns a function for sorting the list of font names alphabetically. (The enumFonts() method returns the names in the order they were originally loaded, which would appear to be random to the user when they view the fonts.)
The initialization routine is invoked from within the containing <window> object, using the on:initialized handler:
<window xmlns="http://www.aol.com/boxely/box.xsd"
xmlns:s="http://www.aol.com/boxely/style.xsd"
xmlns:on="http://www.aol.com/boxely/reaction.xsd"
xmlns:box="http://www.aol.com/boxely/box.xsd"
xmlns:res="http://www.aol.com/boxely/resource.xsd" resizable="true" s:fill="white"
translucent="false" chromeless="false" s:width="500" s:height="300" title="FontViewer"
on:initialized="onFontViewerInit();"
>
The use of on:* as an event call may look a little odd unless you know that the on: namespace is used to identify reactions (also know as events). The window object has a number of such events that it can capture, but in this case the only one that was relevant was the initialized event. The event handler for this should then be invoked in the text block. This isn't the only way you can define events, but it's a useful convention.
The moveCursor function illustrates how you can work with various identified "boxes" within Boxely:
function moveCursor(dir){
var dirValue = 1;
if (dir == "previous") dirValue = -1;
fontIndex = (fontCount + fontIndex + dirValue) % fontCount;
var fontName = fontList.getValue(fontIndex)
var fontTitleBox = scene.getBoxById("fontTitle");
fontTitleBox.setAttribute("value",fontName);
var fontSampleGadget = scene.getBoxById("fvFontSample");
var fontSamples = scene.getBoxesByTag("fvFontSample");
for (var i = 0; i != fontSamples.count;i++){
var fontSample = fontSamples.getValue(i);
var fontSampleText = fontSample.getPartById("fontSample");
fontSampleText.setStyle("fontFamily",fontName);
}
}
The first part is fairly straightforward. The moveCursor() method takes a direction (either "previous" or "next"), translates that into a numeric direction, and calculates an index, rolling over to the beginning if the boundaries of the font list are exceeded. You can then use getValue() to retrieve the name of the indexed font from the font list. The fontTitle text box is retrieved using the scene.getBoxById() method, which retrieves the box from the abstract definition, and is set to the calculated name.
The second part is a little less obvious. The application contains three sample text blocks (fvFontSample). Using the scene.getBoxesByTag() method, it's possible to retrieve each block one at a time:
var fontSample = fontSamples.getValue(i);
and from this, retrieve the requisite part from the gadget that is specifically styled:
var fontSampleText = fontSample.getPartById("fontSample");
This corresponds to the initial <box:text id="fontSample"../> element. Once this is retrieved, the final step is to change the style (specifically the fontFamily) on that particular object, using
fontSampleText.setStyle("fontFamily",fontName);
This takes the fontName calculated previously and sets the font family accordingly on that particular gadget. Note that although there is a reference to the gadget, what is in fact being changed here is an instance of that gadget, not the actual template.
Finally, the buttons themselves to call moveCursor are invoked using on:click event handlers on the respective button definitions:
<fontViewer>
<code id="main" language="jscript" src="fontViewer.js" />
<fontWalker>
<fvFontButton label="Previous Font" on:click="moveCursor('previous')"/>
<fvFontTitle s:flex="1" s:hAlign="center" id="fontTitle"/>
<fvFontButton label="Next Font" on:click="moveCursor('next')"/>
</fontWalker>
<textDisplay>
<fvFontSample value="The quick brown fox jumps over the lazy dog."/>
<fvFontSample value="ABCDEFGHIJKLMNOPQRSTUVYWXYZ"/>
<fvFontSample value="abcdefghijklmnopqrstuvwxyz"/>
</textDisplay>
</fontViewer>
The application is now enabled, and by pressing the Previous Font and Next Font buttons, you can actually see the effects of applying different fonts on the samples. An example of this can be seen in Figure 2.

Figure 2. The functional FontViewer
Now, while this application does a (marginally) useful bit of activity, it suffers from being, well, seriously ugly. As an application, it also has too much of its presentation layer mixed in with the structure, making it difficult to "skin" at some future point to represent a somewhat different presentation layer. The solutions to both of these problems are related--we can use <style> resources to consolidate the stylistic features and make it easier to organize.
Adding Style
For example, it would be nice to be able to visually differentiate the FontWalker at the top from the text in the bottom. The style fill points to an internally defined resource, a red to black gradient, that's also contained in the library:
<res:library>
....
<res:style tag="fontWalker" fill="url(#fontWalkerGrad)"/>
<res:linearGradientBrush id="fontWalkerGrad">
<res:gradientStops>
<res:gradientStop color="#FF0000" offset="0%"/>
<res:gradientStop color="#000000" offset="100%"/>
</res:gradientStops>
</res:linearGradientBrush>
Anything that is defined on the style tag is assumed to be in the s: namespace, so it isn't necessary to use the prefixes explicitly on the tag. The challenge with fontWalker is that if you set the textColor attribute here, it doesn't inherit down to the fvFontTitle element. You can define a style element on that element specifically, and even provide separate styling to each part (where name points to an ID within the gadget):
<res:style tag="fvFontTitle">
<res:part name="fontTitle" fontSize="24pt" hAlign="center" vAlign="center"
textColor="white"/>
</res:style>
Finally you can apply styles directly to the containing <window> object:
<res:style tag="window" fill="url(#windowGrad)"/>
A completely styled application (with the gadgets and styles separated into two distinct sections), can be seen in Listing 3 and shown in Figure 3:
Listing 3. The FontViewer application with styling
<?import href="box://ocpToolkit/content/core/coreGadgets.box"?>
<?import href="box://ocpToolkit/theme/default/toolkit.box"?>
<window xmlns="http://www.aol.com/boxely/box.xsd"
xmlns:s="http://www.aol.com/boxely/style.xsd"
xmlns:on="http://www.aol.com/boxely/reaction.xsd"
xmlns:box="http://www.aol.com/boxely/box.xsd"
xmlns:res="http://www.aol.com/boxely/resource.xsd"
resizable="true" translucent="false" chromeless="false"
s:width="500" s:height="300" title="FontViewer"
on:initialized="onFontViewerInit();"
>
<res:library id="structure">
<res:gadget id="fvFontButton" type="control">
<res:attributes direction="forward" index="0"/>
<res:parts>
<box:button inherits="label=label"/>
</res:parts>
</res:gadget>
<res:gadget id="fvFontTitle" >
<res:parts>
<box:text value="Font Name" s:flex="10"
inherits="value=value" id="fontTitle"/>
</res:parts>
</res:gadget>
<res:gadget id="fvFontSample">
<res:parts>
<box:text s:fontSize="18pt" inherits="value=value"
id="fontSample"/>
</res:parts>
</res:gadget>
<res:gadget id="fontWalker">
<res:attributes index="0" fontName=""/>
<res:parts>
<box:hbox s:flex="1">
<box:content/>
</box:hbox>
</res:parts>
</res:gadget>
<res:gadget id="textDisplay">
<res:parts>
<box:vbox >
<box:content/>
</box:vbox>
</res:parts>
</res:gadget>
<res:gadget id="fontViewer" language="jscript"
code="fontViewer.js" type="box">
<res:parts>
<box:vbox s:flex="1">
<box:content/>
</box:vbox>
</res:parts>
</res:gadget>
</res:library>
<res:library id="presentation">
<res:linearGradientBrush id="fontWalkerGrad">
<res:scaleTransform x="180%" y="70%"/>
<res:translateTransform x="10%" y="0%" />
<res:gradientStops>
<res:gradientStop color="#FF0000" offset="0%"/>
<res:gradientStop color="#000000" offset="100%"/>
</res:gradientStops>
</res:linearGradientBrush>
<res:linearGradientBrush id="windowGrad">
<res:rotateTransform angle="270"/>
<res:gradientStops>
<res:gradientStop color="#FFFFFF" offset="0%"/>
<res:gradientStop color="#FFFF00" offset="75%"/>
<res:gradientStop color="#FF8040" offset="100%"/>
</res:gradientStops>
</res:linearGradientBrush>
<res:style tag="fontWalker" fill="url(#fontWalkerGrad)"/>
<res:style tag="fvFontTitle">
<res:part name="fontTitle" fontSize="24pt"
hAlign="center" vAlign="center"
textColor="white"/>
</res:style>
<res:style tag="window" fill="url(#windowGrad)"/>
</res:library>
<fontViewer>
<code id="main" language="jscript" src="fontViewer.js" />
<fontWalker>
<fvFontButton label="Previous Font" on:click="moveCursor('previous')"/>
<fvFontTitle s:flex="10" s:hAlign="center" id="fontTitle"/>
<fvFontButton label="Next Font" on:click="moveCursor('next')"/>
</fontWalker>
<textDisplay>
<fvFontSample value="The quick brown fox jumps over the lazy dog."/>
<fvFontSample value="ABCDEFGHIJKLMNOPQRSTUVYWXYZ"/>
<fvFontSample value="abcdefghijklmnopqrstuvwxyz"/>
</textDisplay>
</fontViewer>
</window>

Figure 3. The styled FontViewer application
Conclusion
While this application performs a basic function, it really does only one thing, and that not terribly well. Moreover, the application is getting to be large enough that it makes sense to start "decomposing" it into separate files and resources. In order to turn this from a one-trick app to something that has some real utility, it's worth stepping back a bit and rethinking what you're trying to do with it--perhaps replace or augment the buttons with a list that can display all of the fonts, find a way to load in text blocks to test, provide some way of identifying the author of the app, and finally, provide a useful way of distributing the application. This will be the focus of the next article, "Revenge of the Font of Wisdom: FontViewer 2.0."
Resources
- FontViewerCode.zip: The FontViewer application source code; to be unzipped into the userSamples directory beneath your AOLOCP Boxely installation directory
References
- "The Font of Wisdom: A Basic Boxely App, Part 1," by Kurt Cagle, AOL Developer Network, March 27, 2007
- "Thinking Inside the Boxely," by Kurt Cagle, AOL Developer Network, February 23, 2007
- dev.aol.com/boxely: The Boxely home page

Thanks
Thanks for zip file!
Bst Rgds,
Michael B.