The following sections describe several complex demos that bundled with Scaleform CLIK. Only high-level implementation details are provided. Note that these sections require a fairly thorough knowledge of Flash and ActionScript 2.
Figure 67: TreeView demo.
The TreeView Demo (Resources/AS2/CLIK/demos/TreeViewDemo.fla) implements a tree view control using the ScrollingList component as a base along with a custom ListItemRenderer and DataProvider.
Let’s consider the differences between a normal ScrollingList and a tree view:
The ScrollingList is an effective surrogate for a tree view built from scratch. For the demo, a custom ListItemRenderer called TreeViewItemRenderer and a custom data provider called TreeViewDataProvider are defined. The demo also uses a small utility class called TreeViewConstants to provide common enumerations. All of these classes can be found under the Resources/AS2/CLIK/demos/com/scaleform directory.
The first item to decide when implementing a tree view is its data representation. ActionScript 2 Objects are inherently hash tables, and this demo exploits this property. The tree is constructed using a tree of Objects, such as the following:
var root:Object = { label: "System", nodes:[ {label: "Applications", nodes:[ {label: "CGStudio", nodes:[ {label: "Data"}, {label: "Samples"}, {label: "Config"} ] }, {label: "Money Manager"}, {label: "Role Call v6"}, {label: "Super Draft", nodes:[ {label: "Templates"}, …
Each item in the tree is represented as an Object with two properties: label and nodes, which is an Array containing potential child nodes. To bridge this hierarchical representation with the ScrollingList, a custom data provider to parse and maintain the tree structure and expose the appropriate data to the list are required.
The TreeViewDataProvider takes in this tree object in its constructor and performs a preprocess step to annotate each item with special properties only useful for the data provider and the custom ListItemRenderer. These properties include the item type, its expanded/contracted state, parent/sibling links and an array of line graphic descriptors that describe which line graphics to use during rendering. The TreeViewDataProvider implements the appropriate public methods required by a CLIK data provider, but defers most of the work of item retrieval to several helper functions. For example, item range retrieval first finds the tree object using the list’s top most item index, and then collects a linear sequence of items starting from the top-most item via tree traversal.
The TreeViewItemRenderer receives its data from the TreeViewDataProvider via the ScrollingList. The data object it gets contains all the meta data required to render the item correctly, without any knowledge of the tree structure. The unmodified ListItemRenderer component symbol is reused in this demo, with its class linkage set to the TreeViewItemRenderer. The list item’s folder icons and line connector graphics are created dynamically. These graphical elements are pre-cached to avoid duplicate instantiations of the same symbol at the same ‘tab’ slot. The textField element of the ListItemRenderer is shifted to the right, based on the item’s depth.
The TreeViewConstants class contains enumerations for the following:
The latter enumerations are used for display purposes only. This demo uses folder icon and line graphics to provide seamless connections between items regardless of depth. To achieve this effect, the folder icons and line graphics must cover all different configurations of expanded and contracted views.
Since this tree view is based on a ScrollingList, a ScrollBar component can be connected to it. The scroll bar changes its appearance based on the state of the tree hierarchy; the expanded/contracted state of the tree affects the scrollbar’s grip size. Interacting with the scroll bar modifies the ScrollingList view as expected.
Figure 68: Window demo.
The Window Demo (Resources/AS2/CLIK/demos/WindowDemo.fla) provides a simple reusable window component capable of displaying arbitrary content. The Window component class can be found under Resources/AS2/CLIK/demos/com/scaleform/.
This Window component subclasses the core UIComponent class and thus is classified as a CLIK component. It does not exist under the core framework classes because a general purpose Window component is hard to define, let alone be implemented efficiently. The more features one adds to a component, the more cumbersome it becomes in terms of memory and performance.
Therefore, this class only implements a core set of common features expected from a Window component. They are:
The Window class exposes several inspectable properties:
Title | The title of the Window. |
formPadding | The amount of padding between the Window border and its contents. |
formType | Type of content to load. This value can be either ‘symbol’ or ‘swf’. If ‘symbol’, then the content is loaded from the library. If ‘swf’, then an external SWF file is loaded. |
formSource | The source of the content. This can either by a symbol name (if formType is ‘symbol’) or SWF file name (if formType is ‘swf’). |
allowResize | Shows or hides the resize button. |
minWidth, maxWidth, minHeight, maxHeight | The resizing dimensions of the window. If the max values are set to a negative value, then they will be clamped to its min counterparts. Setting both max values to negative values has the same effect as hiding the resize button, which disables resizing completely. If the max values are set to 0, then the component can be resized without a max limit. The minimum will always be the initial size of the content. |
Adding an inspectable property to a custom component class is quite easy. If a public property does not require any code to execute when getting or setting the property, then it can be declared as follows:
[Inspectable(name="formType", enumeration="symbol,swf"] private var _formType:String = "symbol";
For more information on the Inspectable meta data syntax, please refer to the Flash documentation. Note that the Inspectable meta data provides support for aliasing the actual property; in this case the _formType property is aliased as formType for readability.
If the property requires code to be executed after setting or getting its value, then the property should define getter and setter functions:
[Inspectable(defaultValue="Title")] public function get title():String { return _title; } public function set title(value:String):Void { _title = value; invalidate(); }
This Window component inherently supports several subelements, such as the title button, close button and resize button. Each of these buttons is a CLIK Button component. Since these buttons are required by the class, the component symbol must reflect this requirement by including the appropriate subelements.
Since the Window class subclasses the UIComponent class, the two main methods are overriden: configUI() and draw(). The configUI() method sets up the button listeners and the constraints object for resizing. The draw() method generally performs reflowing of the component’s layout either manually or using the constraints object. However, it also contains logic to load the content using a symbol name or file path. After loading a private method, configForm(), is called to set up the contents.
File loading is performed using the Flash 8 MovieClipLoader. Since file loading is performed asynchronously in Scaleform when threading support is enabled, the component invokes configForm() from within a MovieClipLoader.onLoadComplete() callback that is triggered when file loading has completed.
The form content loaded either via symbol or file path are added to the internal constraints object. Whenever the Window component is resized, it is invalidated. This causes the draw() method to be invoked, which consequently performs an update on its constraints object with the new dimensions. Since the form content is registered with the constraints object, it is notified of the change via the validateNow() method.
If the form content derive from UIComponent, then its own draw() method will be invoked. Layout management logic for the form content can be executed when the draw() method is called. If the form content does not derive from UIComponent, then it can define a validateNow() method to reflow its own elements. The Window Demo contains several examples of symbols and SWF files that use the draw() method and the validateNow() method to maintain form layout.
The Window component also contains special logic to move the window that was pressed by the mouse cursor to the foreground. The logic näively assumes that all Window component instances exist in the same level, and bubbles the component in focus to the next highest depth.
private function onMouseDown() { var targetObj:Object = Mouse.getTopMostEntity(); while (targetObj != null && targetObj != _root) { if (targetObj == this) { swapDepths(_parent.getNextHighestDepth()); return; } targetObj = targetObj._parent; } }
This is one way of implementing such behavior. Another way is to create a WindowManager to maintain the z-indices of all window components on the Stage. This WindowManager approach is in fact more flexible than the way implemented by this sample Window component.