In his book, The Inmates are Running the Asylum, famed software architect and an inventor of Visual Basic Alan Cooper, bemoaned developers' desire to control every aspect of user-facing applications. Cooper had noted that an application's success often relates to ease-of-use and other subjective usability features. He therefore suggested that developers relegate the design—especially user interaction design—aspects of their applications to specialist interaction designers.
Web application developers have, by and large, followed Cooper's advice: Web development teams routinely include visual designers, and Web application development tools are generally good at working with artifacts, such as stylesheets and image files, produced by designers. In addition, most Web application frameworks include some form of templating mechanism that allows the separation of visual elements from program logic in a Web page. As a result, Web applications using the same framework can have widely different visual styles.
Traditional desktop applications, by contrast, tend to inherit the visual defaults of a user-interface toolkit. For instance, Java Swing applications often use either the default Swing look-and-feel ("L&F"), such as Ocean, or use a third-party L&F library, such as JGoodies or Incors. Similarly, Windows-based applications tend to inherit the L&F of the Windows Foundation Classes native look.
Rich-clients applications gain most their power from having feature-rich, desktop-like components at their disposal. At the same time, rich Internet applications must work in designer-created Web environments, such as inside a Web page, and must therefore be able to either blend into that environment, or provide similar design freedoms as Web pages do.
Flex has allowed developers to customize the visual appearance of components via CSS style elements. Every Flex component in the Flex 3 SDK allowed a developer to override default component styling either by directly specifying CSS values on an element's MXML tag, with a CSS style sheet document attached to an MXML file, and even from ActionScript code.
While a powerful concept, embedding styling declarations directly into MXML files or ActionScript code provided only limited interaction between designers and Flex developers. For instance, designers could not easily use their familiar design tools to create full-fledged, customized look-and-feels for a Flex application. (Although such look-and-feels do exist, and are cataloged at Scale Nine.)
The upcoming Flex 4 SDK makes developer and designer interaction a key feature by completely separating a component's visual appearance from component logic. Flex 4's new component architecture—Spark—accomplishes that by defining a design-oriented subset of MXML, and by separating out design-oriented component features into a component's companion "skin" file.
Flex 4's new MXML subset for skins, FGX, is valid XML code, and can be specified either inside an MXML file defining a component or, more often, in a separate file. The advantage of using a separate file is that designer tools can read and write that file directly. Adobe, for instance, enhanced its designer tools to comprehend such FGX files, and even provided a specialized designer tool, Catalyst, for the purpose of working with FGX content.
FGX files can declare any visual aspect of a component. An FGX file, for instance, can define runtime graphics classes that draw shapes, specify containment of sub-components, define component effects, transitions, and even specify layout inside the component. In Flex 4, the runtime graphics primitives directly map to graphics classes in Flash Player 10.
Separating out visual concerns into a separate file allows a Flex component's core class to focus on component logic, such as responding to user gestures and data events. A new component lifecycle ensures that the component's core behavior is associated with the right skin file at runtime.
The Flex 4 components are designed in such a way that they can co-exist with existing Flex 3 components. That is because Flex 4's new component architecture subclasses the
UIComponent class, the base class for visual components in Flex 3. The result is that you can mix and match Flex 3 and Flex 4 components in a single application, providing for incremental upgrade of existing code.
The main Flex 4
UIComponent subclass is
SkinnableComponent, and all the skinnable Flex 4 components based on the Spark architecture extend that class. The Flex 4 SDK includes Spark-based implementations of most, though not all, Flex 3 components, such as Lists, Panels, Buttons, TextBoxes, and so. When there are both Flex 4 and Flex 3 versions of a component, a separate MXML name space is used to disambiguate the new component version.
UIComponent subclass in Flex 4,
Group, is designed for components that will not have associated skin classes. Those components typically act as containers and layouts for other components. In previous versions of Flex, such containment could be defined by placing Flex components inside an
HBox, for instance. Although
HBox is a visual class, it would seldom need to define its own look and feel elements. In addition, specifying containment and layout inside visual components makes it difficult to rearrange component layout at runtime. Switching from horizontal to vertical layout in Flex 3, for instance, would have required removing components from an
HBox and placing them inside a
Group mechanism makes layout more flexible by allowing a developer to specify a
layout attribute for a group. That attribute can be swapped for a different layout value at runtime.
While skinnable Flex 4 components subclass
SkinnableComponent, the skin definition is compiled into an instance of the
SparkSkin class. The runtime system instantiates an appropriate
SparkSkin for a component, and new Spark 4 component lifecycle methods performs a merging of a component's visual state with the component's main object state.
Note that because the skin and the component are represented by two separate instances, the component and the skin can each maintain its distinct state. Separate component and skin states are an important tool in Flex 4. Often, skin and component objects must move from one state to another in tandem: A button, for instance, has "up," "down," "over," and "disabled" states. The companion skin object would have corresponding visual states representing a depressed button, a button with a mouse over it, or a disabled button, for instance. However, it is also possible for the skin's state to change without the component's state to change. Regardless of whether component and skin states change in tandem or independently, the Spark component architecture defines how a component can choose the right skin object, and request its skin to change states.
Button component was the first to be implemented in the new Spark architecture, and is a good example of component and skin separation. The skin definition first references the component to which this skin can be applied. This optional metadata element allows the skin to hold a reference to the component class, if necessary. Next, the various component states are referenced, followed by visual definitions of the component:
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" minWidth="21" minHeight="21" alpha.disabled="0.5"> <fx:Metadata> <![CDATA[ [HostComponent("spark.components.Button")] ]]> </fx:Metadata> ... <s:states> <s:State name="up"/> <s:State name="over"> <s:State name="down"/> <s:State name="disabled"/> </s:states> <s:Rect left="-1" right="-1" top="-1" bottom="-1" radiusX="2" radiusY="2"> <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="0x000000" color.down="0xFFFFFF" alpha="0.01" alpha.down="0"/> <s:GradientEntry color="0x000000" color.down="0xFFFFFF" alpha="0.07" alpha.down="0.5"/> </s:LinearGradient> </s:fill> </s:Rect> ... <s:SimpleText id="labelElement" textAlign="center" verticalAlign="middle" lineBreak="toFit" truncation="1" horizontalCenter="0" verticalCenter="1" left="10" right="10" top="2" bottom="2"> </s:SimpleText> </s:SparkSkin>
The MXML tags in the skin definition use the FGX elements—those, in turn, are compiled into ActionScript classes that directly use the FlashPlayer 10 rendering and graphics primitives. Note that the visual declarations reference the component state with the
color.down, for instance, specifies the color in the
Although many user interface toolkits aim to separate the visual appearance of a component from other component logic, few toolkits go as far in that separation as Flex 4's Spark architecture. Because component skins are defined apart from main component behavior, in a separate file, skins can be edited by tools aimed primarily at designers—indeed, designer tools, such as Adobe's Catalyst can already understand skin FGX files.
Because FGX is a subset of MXML, however, Flex developer tools, such as Flash Builder 4, as well as the Flex 4 compiler, can incorporate such skins into the usual Flex developer workflow and into the Flex component lifecycle. The next installment of this Artima series will provide a tutorial on how to use Spark's component and skin separation to define a custom look and feel for a Flex application.
Adobe's Flash Builder 4
Frank Sommers is Editor-in-Chief of Artima.