Examining Component Architecture

 < Day Day Up > 

To get a better sense of the component architecture and best practices, we are going to look at how the CheckBox component is built. Before we actually start building a component, we need to think about the following issues:

  • Visual look and feel. All components are based on movie clips and in almost all cases, begin their life as a movie clip by using Convert to Symbol. This is where the drawing tools, ActionScript 2.0 code, and other elements of Flash enable us to create the look and feel of the component.

  • Class hierarchy. From what classes does this component need to inherit? All components, of course, inherit from the MovieClip class and the UIObject class, but there might be other classes that provide useful properties and methods . It is essential that a component developer understand all the prebuilt classes available for inheritance. It has the potential to save a lot of work! For example, the View class enables components to inherit methods that help manage the creation of child objects. The View class automatically handles all the code associated with the creation and destruction of child objects. Last, the Accordion component utilizes the View class and is a good component to examine to understand how the View class works.

    The UIComponent class is essential for those components that interact with users. The superclass of the UIComponent class is the UIObject class. The superclass of the UIObject class is the MovieClip class. The UIObject class offers a draw method that greatly helps with the initial component layout of subobjects. It also helps with end- user interactions, such as focus, clicking, and dragging. It can be important to consider if we need to build any custom classes that might be useful for other components.

    The version 2 component architecture also offers classes useful for specific tasks . One such class is the Focus Manager , which keeps track of where the focus of the user is. The Depth Manager automatically handles component depth. These classes are available in the package mx.managers.

  • API definition. We need to consider the properties, events, and methods that will be unique to the component that we are building.

  • Skinning and style. It is a best practice to divide all the visual aspects of a component into visual movie clips that can be attached at runtime. This enables the user of the component to easily go in and make changes to the appropriate clip.

Creating the Visual Look and Feel of a Component

All components are stored in FLA files in a separate Library. It is now possible to "hide" the FLA file from the Flash developer by using SWC files or compiled clips. Luckily, Macromedia has included all the FLA files for each component so that we can see how they were built.

Under the hood, the Components panel in Flash is really a separate FLA file. When a developer drags a component from the Components panel to the Stage, in reality, it is the same action as dragging a component from the Library of another FLA file.

Work through the following step sequence:

  1. Open the file StandardsComponents.fla in C:\Program Files\Macromedia\Flash MX 2004\en\First Run\ComponentFLA\StandardComponents.fla. Then open the Library and the Library folder "Flash UI Components 2," as shown in Figure 9.11:

    Figure 9.11. The visual component symbols available in StandardComponents.fla.

    graphics/09fig11.gif

  2. Open the CheckBox symbol in the Library and move the playhead to Frame 2. You will see all the different possible states of the check box represented visually, as shown in Figure 9.12:

    Figure 9.12. All the visual components of the CheckBox component are located in the CheckBox symbol.

    graphics/09fig12.jpg

    In Flash, it is now possible to associate a class directly with a visual control by using the Class field in the Convert to Symbol dialog box.

  3. Right-click the CheckBox component in the Library, and choose Properties. Click the Advanced button and your screen should resemble Figure 9.13:

    Figure 9.13. Notice that the CheckBox class is being imported from mx.controls.CheckBox.

    graphics/09fig13.gif

  4. Be sure the Library is open. Right-click the Checkbox component, and choose Component Definition. Here you see the visual controls, or parameters, of the component that are available in the Component Inspector and/or Property Inspector. You can also specify a custom UI for your component, indicate whether this component appears in the Components panel and/or the Actions panel, and set up the help for the component. See Figure 9.14:

    Figure 9.14. The Component Definition panel.

    graphics/09fig14.jpg

    Component parameters can also now be defined directly in class files, and Flash will use the class file to populate the parameters file.

  5. Open the CheckBox symbol in the Library and move the playhead to Frame 2. Note the stop action on Frame 1. You will see a simple button on the Stage, right above all the Checkbox assets. All the CheckBox assets are assembled dynamically using the Draw method.

    The Button component has been physically dragged onto the Stage because the Checkbox component needs to use the Button class. This is a common technique in component development. It is even possible to drag classes (such as UIObject ) onto the Stage, which ensures that all base classes are imported.

The only reason that we need to use the symbols you saw in the previous step sequence is that they need to be exported for ActionScript. Thus, for example, we could use attachMovie() to bring them in dynamically (in the version 2 component architecture there are other ways to achieve this as well). It is a best practice to place them in Frame 2 (with a stop action on Frame 1) so that they are still exported but not physically rendered until we need them. This makes the application initialize faster because the components are not rendered until they are needed, thus saving processing power and CPU resources. See Figure 9.15.

Figure 9.15. A simple Button component on Frame 2 of the Checkbox component.

graphics/09fig15.jpg

Examining the Class Files of a Component

Now that we have examined the visual creation of the Checkbox component, we need to examine the class files that define the APIs of the component. In this section, we walk through the CheckBox class as an example of a component created with best practices in mind.

  1. Let's start by examining the CheckBox class. Open c:\Program Files\Macromedia\Flash MX 2004\en\first run\classes\mx\controls\CheckBox.as. The class definition of the component is extending the Button component, as shown in the following code:

     class mx.controls.CheckBox extends Button{       function CheckBox ()       {       } } 
  2. Open c:\Program Files\Macromedia\Flash MX 2004\en\first run\classes\mx\controls\Button.as and examine its inheritance structure. We can see all properties and methods of the Button class are inherited from the Simple Button class:

     class mx.controls.Button extends SimpleButton { } 
  3. Open the Simple Button class (c:\Program Files\Macromedia\Flash MX 2004\en\first run\classes\mx\controls\SimpleButton.as) and examine its inheritance structure. We can see that the simple button inherits from the UIComponent class:

     class mx.controls.SimpleButton extends UIComponent{ } Remember that the UIComponent class extends the UIObject class: class mx.core.UIComponent extends UIObject{ } 

    Note that the UIObject class extends the MovieClip class:

     class mx.core.UIObject extends MovieClip { } 

    While every component can define unique events, events are inherited along the prototype chain. Because the Checkbox component was subclassed from the UIObject and UIComponent classes, typical events are available. They include load , change , move , and draw .

  4. Move back to the CheckBox.as file, and you will see the following code:

     static var symbolName:String = "CheckBox"; static var symbolOwner:Object = mx.controls.CheckBox; 

    The preceding code enables developers to use createClassObject to create instances of this component dynamically through this new method. It is a best practice to define these static variables at the beginning of every component class definition so that advanced developers will be able to use this method.

    After this code, you will see all the private properties in use. It is essential to declare these properties before they are used. The following are examples of the properties declared. Note the __ denotes that they can be accessed only from within the class:

     var __selected:Boolean = false; var __labelPlacement:String = "right"; 
  5. It is also important to declare all movie clips used within the component (if any). The next step is to define all of the getter/setter methods that will be used with the component. Within the CheckBox class, you will see getter/setter methods such as toggle , which indicates whether the check box functions like a toggle switch ( true ) or a push button ( false ).

 function set toggle(v) { } function get toggle() { } 

You will also see metatags being used within the class definition. Metatags give Flash more information about the code you write. For example, the following code is used by the Component Inspector to display the component parameters:

 [Inspectable(defaultValue="CheckBox")] 

Another common metatag is bindable, which indicates that this component can be used with the new visual databindings, as shown in the following code:

 [Bindable("writeonly")] 

Almost all components will extend the UIObject or UIComponent classes. This provides a common framework that developers can use to create components.

Note that we must build the class file with certain methods: init , createChildren , draw , and size . These methods are called automatically by the component framework and ensure that components behave in a consistent manner. We also do not have to worry about any synchronicity issues if we use this framework.

The order in which the methods are called is shown in Figure 9.16:

Figure 9.16. The method load order in the component framework.

graphics/09fig16.gif

All components should have an init method, which sets all the initial values for the properties and calls the init method of the superclass, as shown in the following code:

 function init ()        {              super.init();        } 

The createChildren method is called after the init method by the component framework and this is where all objects should be created from classes. We can use movie clip methods to do this or we can use the new createClassObject method available in the component framework:

 function createChildren ()        {              this.createTextField ("fontText", 1, 20, 20, 20, 20);              this.createClassObject ("comboBox", "chooser_cb", 1);        } 

The draw method is where all components and text fields should be populated . The component framework includes a new drawing API that makes drawing easier. See the following code:

 function draw ()        {              this.beginFill (0x000000);              this.drawRect (0,0, height, width);              this.endFill();        } 

Finally it's a best practice to create a size method that will redraw the component in case the component is resized. This functionality is automatically handled by the superclass simply by calling the invalidate method:

 function size ()        {              super.invalidate();        } 

Components enable easy encapsulation, reuse of code, and control of visual elements. It can be very efficient to build custom components that you can use across different applications.

Consider the following step sequence:

  1. The first step in component development is to decide what class our component will actually extend. The UIObject class is the base class for all graphical components. It can have shape, draw itself, and be invisible. UIObject handles most of the component events, such as load and change . UIObject provides alternate read-only variables for determining the position and size of a movie clip. You can use the move() and setSize() methods to alter the position and size of an object.

    The UIComponent class extends the UIObject class and is the base for all components that have user interaction. For example, the UIComponent class controls all interaction with the keyboard and mouse.

    Other components can be extended as well. For example, if we need a component that has all the same functionality of an alert but does more, we can extend the alert component rather than building that functionality ourselves .

  2. The second step in component development is to define a class in an external ActionScript file. The external ActionScript class extends another class, adds methods, adds getters and setters, and defines events and event handlers for the component.

  3. The next step is to define the symbolName property, which preserves the component's naming structure. This property is always static and a type of String . It is simply the name of the ActionScript class.

  4. The next step is to define the symbol owner, which is the fully qualified package name of the class and is used in the createChildren() method of the component. This property is static as well but has a data type of Object .

  5. The next step is to define the class name of the component in a String data type. A class constructor needs to be defined as well.

    So far the class structure of our component should look as follows :

     //declare the class and identify parent class class myPackage.MyComponent extends UIObject { //identify the symbol name that this class is bound to static var symbolName:String = "MyComponent"; //identify the fully-qual'd package name of the symbol owner static var symbolOwner:Object = Object(myPackage.MyComponent); //provide the className variable var className:String = "MyComponent"; function MyComponent() {} } 
  6. The next step is to define an init method for the component. This method is executed as soon as the class is instantiated and is usually called by the superclass. By calling this method, the width , height , and clip parameters are all defined. Usually the init method on the superclass, which is, in this example, UIObject , is called as shown in the following code:

     function init(Void):Void { super.init(); } 
  7. The next step is to define any objects that the component will use. For example, your component would likely contain text boxes. These can be defined in the physical asset of the component or in createChildren() . This method enables us to use methods of the UIObject class that will automatically bring assets from the Library into our component. These could include text boxes, other components, movie clips, and so on. These methods of the UIOBject class are fully described in the Flash documentation and it is much better to use these rather than the traditional attachMovie() or createTextField() .

    An example createChildren() method that creates a text field might look like this:

     function createChidren() :Void { componentLabel = createLabel("textBoxLabel", 10); } 

    The UIObject class also offers drawing capabilities similar to the drawing API of a movie clip, but it is much easier to implement. This is defined in a draw method. An example is the drawRect method, which will draw a rectangle for us:

     function draw () :Void beginFill(bgColor);      drawRect(0,0,width,height); endFill(); } 

    It also makes sense to set up the physical layout of your component interface in the draw method. For example, if you created a text field or a combo box, or a movie clip in the createChildren method, it would make sense to define the physical look and feel in the draw method, like so:

     function draw () :Void {       textBoxLabel.text = myText;       textBoxLabel.setSize (textBoxLabel.textWidth + 1, textBoxLabel.textHeight +1 } 
  8. The next step is to set a size method of the component. This is automatically called whenever the component is resized, and if you use the invalidate() method, this will automatically call the draw method.

     function size () :Void {        invalidate(); } 

    After the method creation has been completed, you define your getter/setters that retrieve the component properties. If you designate that the property is Inspectable , as shown in the following code, it will appear in the Property Inspector:

     [Inspectable]      function set text(newText:String):Void      {        _text = newText;        invalidate();      };      function get text():String      {        return _text;      } 
  9. Next, you need to create a visual movie clip symbol with any physical assets the component will use, and to link that physical movie clip with the class that you created. Remember that the physical assets should be placed on Frame 2 of the movie clip with a stop action in Frame 1 of the clip.

    To define the physical area of the component on the Stage, you can create a movie clip on a layer in Frame 1 and assign the movie clip an instance name of boundingBox_mc . This will define the physical boundaries of the component. After the physical look and feel of the component has been set up, you need to link the class to the physical movie clip in the Component Definition menu.

  10. Right-click the component and choose Component Definition. In the Class field, enter the name of your class. The component will read the class and pull out all the parameters that you specified. To easily distribute the component, you can export all assets into an SWC file, which is basically a file in pkzip format.

 < Day Day Up > 


Object-Oriented Programming with ActionScript 2.0
Object-Oriented Programming with ActionScript 2.0
ISBN: 0735713804
EAN: 2147483647
Year: 2004
Pages: 162

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net