Master the Time-saving Power of Flash Components, Part 2

n Flash, components have the power to save you a great deal of time and frustration. These pluggable, self-contained units?consisting of handy combinations of graphics and/or code?are just dropped into place as needed to fulfill a role in your application. You can use them over and over.

While pre-built components are often just what you need, knowing how to build your own, custom components is a skill that no one should eschew. This two-part article series is designed to show you everything you need to know to build custom components that can work in multiple versions of the Flash player.

In part 1, I covered the basic heavy-lifting of creating the component. In this follow-up, I’ll show you how to really extend the usefulness of that component to get the biggest bang for the buck.

In part 1, I started with a hard-coded MovieClip. From there, the clip was converted to accept a user-defined parameter, allowing the user to modify the values of the component remotely. I then added a Live Preview file for immediate visual feedback during adjustments, a plain text description about the functionality of the component, and a custom icon.

In this article, I will:

  • Add a custom user interface for the component to the Properties pane
  • Enhance the component with a custom class when it is initialized
  • Make the code friendlier, and better insulated, by defining best-practices “getter” and “setter” wrappers
  • Use XML to enhance the Reference panel description, and add the custom actions to the Action panel
  • Package the component for distribution with the Extension Manager.
Author’s Note: The material from which this article was derived will be presented in a session called “Authoring Components” at the FlashForward 2005 conference in San Francisco, April 6-8.

To download the souce code for this article:

The first article covers steps 1 through 5, sequentially. Picking up where we left off, then is …

Step 6: Add a Custom User Interface to the Properties Panel
Depending on how complex a component is, you may never need, or want, to define a custom user interface. In most cases, the scrolling list of component variables in the Properties Panel is enough. However, there may be times where you want to go beyond simple text input for your parameter settings. You may, for example, want to simplify number input by using sliders. Or, you may want to provide instant feedback in your custom user interface without relying on the Live Preview function we covered in Part 1. For example, our example custom interface will immediately display the alpha value of our component background, even when Live Preview is disabled.

Although this tutorial example doesn’t need a custom interface, I want to demonstrate the process. However, I don’t want to complicate the code by having to script additional interface widgets. So, for demonstration purposes, I will simply add a custom UI that will allow the user to enter the single parameter value required.

To improve the default Parameters panel Flash automatically creates for you, I will show what the Stamper looks like in the custom interface, as well. The Stamper is designed to automatically “stamp” your movie with a copyright symbol in the lower right corner. Since it may or may not be easy to see the results in your artwork, it’s helpful to see what the stamp will look like while you adjust parameters. This technique is sometimes used instead of a Live Preview, because authoring with Live Preview enabled can affect performance. This is a judgment call, especially when the preview is as small as ours, and you can always enable, or disable, the Live Preview feature.

Figure 1. Custom UI: This is what the custom user interface looks like before…
Figure 2. Custom UI: This is what the custom user interface will look like when you’re finished.

I’ll start by duplicating the Live Preview file. This will provide the Stamper with artwork pieces that I can update dynamically within the UI. However, I need to change the dimensions of the movie to match that of the Properties panel. Use 406 x 72 pixels. When necessary, you can use any dimensions and display the movie in the Component Parameters Panel. (This is a separate window, not the “parameters” tab in the Properties panel.)

In addition to the foreground copyright symbol MovieClip, and the white background MovieClip, I want to add two things (see Figure 2):

  • First, a gradient background behind the artwork. This can just be a shape, and will show what the copyright symbol background will look like on a variety of colors.
  • Second, is a text input box for the alpha value itself. Create a text element on stage and give it an instance name (not a text variable name) of “alphaVal.” (You may choose to use a variable in your own work, but this example uses an instance name.) Add a descriptive static text label that says “Background Alpha:”

Now move on to the scripting. Add the following code to the first frame of your file:

fscommand("allowscale", "false");_root.uiStampBack.onLoad = function() {	alphaVal.text = xch.sBackAlpha;	cuiBack._alpha = xch.sBackAlpha;};alphaVal.onChanged = function() {	cBackAlpha = parseInt(this.text);	_root.cuiBack._alpha = cBackAlpha;	xch.sBackAlpha = cBackAlpha;};

The first line just prevents the file from being scaled while being viewed within the Flash UI panel.

The second segment is an initialization routine. Just as in the Live Preview file, it can automatically send information to, and receive information from, my component through the xch object. As before, this is automatic and I need only to reference the object. So, when this custom user interface is first displayed I want the most current alpha value from the component to appear in the field, and update the visual representation, in the user interface.

You may remember that the alpha variable in the component was called “sBackAlpha.” So, I’ll RECEIVE that from the xch object and put it into my text field using the .text property and its instance name. I’ll also set the sample background MovieClip to this value at the same time. Finally, because I only want to do this once, I’ll use the onLoad event handler for this clip’s instance name. This keeps the code centralized and efficient.

alphaVal.onChanged = function() {	cBackAlpha = parseInt(this.text);	_root.cuiBack._alpha = cBackAlpha;	xch.sBackAlpha = cBackAlpha;};

The third segment of code, repeated above for clarity, is used to SEND the user input back to the component. (Here, the xch object is on the left side of the assignment operator.) I’ll use the onChanged eventHandler for this TextField’s instance name so the xch object is only updated when the content of the text field is changed.

When that happens, the value from the input field needs to be converted into an integer, and put into the “cBackAlpha” variable. At the same time, I’ll update the background to show the change, and send the data, through the xch object, back to the component variable, “sBackAlpha.”

That’s all there is to the custom user interface code. Save the file into the common directory (again, just for convenience), and test the movie to get a quick SWF. The last thing to do is add the custom UI SWF to the “Component Definition…” window. Open this dialog, as before, from the Library, and select the “Custom UI” Set button. Choose the external SWF option, so you can freely modify the file if problems are found, and browse to the SWF you just created.

Finally, to be sure the most current version is used, delete any previous versions of the component from the Stage, and drag a new version in from the Library. Now, any time you select that Stage instance of your component, the Properties panel parameters tab interface will be replaced by the new custom interface. When you modify the component, both the UI and the Live Preview (if enabled) on Stage will reflect the changes.

Step 7: Enhance the Component with a Custom Class
So far, to keep things simple, I’ve added the bare minimum of ActionScript to the component to make it function. However, I’m not taking advantage of some of the best features of components. So, I’m going to add some additional code that will integrate my component more fully into the Flash object model. Here again, I’ll show the code and then discuss it.

(For clarity, I’ve numbered the lines, but be sure not to include these numbers in your file if you’re following along. Alternately, you can get the code here.)

 1    #initclip 2    function FMAStamper() { 3        this.swapDepths(1000); 4        this.stampBack._alpha = this.sBackAlpha; 5        this._x = Stage.width - 20; 6        this._y = Stage.height - 20; 7    } 8    Object.registerClass("stamper", FMAStamper); 9    FMAStamper.prototype = new MovieClip();10    #endinitclip

The first new item is that all the code appears within the #initclip/#endinitclip structure. This allows you to execute code only when the component is initialized. This is great for initializing variables or otherwise doing things that you only want to do once.

First, define a function for this component, and call it “FMAStamper.” (It’s good practice to name your variables with names a user probably won’t choose for his/her own code.) Inside this new function the existing code is unchanged.

Now, register this function as a custom class, associating it with the Linkage ID you gave the component. This more tightly integrates the component into the Flash Object Model and allows you to easily instantiate the component programmatically. Again, you must select the component in the library, and use the “Linkage…” option. You must give the component the same Linkage ID as you register with the class, above. You have likely already used Linkage IDs with MovieClips or sounds, or other assets you want to introduce with ActionScript.

Finally, in doing the above, Flash will change the type of this component from MovieClip to the new class. However, I still want to be able to control it the same way all MovieClips are controlled. So, I must inherit all the MovieClip properties, methods, eventHandlers, etc., by using line 9. This creates a MovieClip prototype within the custom class and grants access again to all the MovieClip goodies.

Step 8: Add Getter and Setter Wrappers
The ActionScript that I’ve written so far is fine for a fully self-contained component. However, the existing model doesn’t allow you to use ActionScript to easily query, or change, any of the component’s settings. For example, if you wanted to change the background alpha of the component remotely, you would have to already know the name of the variable “sBackAlpha” and change that variable value directly. To begin with, this is inconvenient. You will have to remember the name of that variable, and no one else would ever know what it is, making this component decidedly less useful.

Additionally, it’s not good practice to directly expose your core variables to the outside world. The best way to handle this is to both insulate your code and provide a user-friendly way for users to access your parameters. Do this by creating “getter” and “setter” wrappers. This is not a requirement, just good coding practice. These are just function constructs that “wrap” around your variable assignments and other executions, using familiar syntax that allow users to get, and set, values where appropriate. This way, users don’t have to know or remember obscure variable names.

To do this, set up functions that are available throughout the life of the component instance. Set them up as prototypes of the custom class you’ve created.

FMAStamper.prototype.setBackgroundAlpha = function(whichAlpha) {    this.sBackAlpha = whichAlpha;};FMAStamper.prototype.getBackgroundAlpha = function() {    return this.sBackAlpha};

An instruction might read something like:

myStamper.setBackgroundAlpha(25)

The component must be updated after every remote change. So, make a minor change by defining one last function to do the update, and move anything that happens after the component’s initialization to the update function. At runtime, the component only needs to move to level 1000 once, and it only needs to be positioned in the lower right hand corner of the stage once. But, the alpha value must be updated every time it is called. The final script shows this change. (Note the call to update() at initialization and in the setter, and don’t forget to omit line numbers if you’re copying from these notes.)

 1    #initclip 2    function FMAStamper() { 3        this.swapDepths(1000); 4        this._x = Stage.width - 20; 5        this._y = Stage.height - 20; 6        this.update(); 7    } 8    Object.registerClass("stamper", FMAStamper); 9    FMAStamper.prototype = new MovieClip();10    FMAStamper.prototype.setBackgroundAlpha = function(whichAlpha) {11        this.sBackAlpha = whichAlpha;12        this.update();13    };14    FMAStamper.prototype.getBackgroundAlpha = function() {15        return this.sBackAlpha16    };17    FMAStamper.prototype.update = function() {18        this.stampBack._alpha = this.sBackAlpha;19    }; 20    #endinitclip

Step 9: Enhance the Reference and Actions Panels with XML
Now that you’ve gone to the trouble of writing familiar syntax for users to modify this component on the fly, you have to tell them about it. By changing the component’s description text from plain text to XML, you can enhance the Reference Panel info to reflect your component, and add your custom actions to the Actions Panel.

To do this, create a well-formed XML document based on the template provided by Macromedia. Space limitations prevent me from going over this in great detail, but I’ll explain enough to get your started. Also, check the Related Resources links in the left-hand column of this article page for some links with more detail. Listing 1 is an excerpt from the finished file.

The “actionspanel” node of this XML document is for adding Actions to the Actions panel. Inside this node, you add as many folders as necessary. These create the expandable entries in the Actions Panel that are preceeded by “notebook” icons. So, a simple object with methods and properties would have three folders: The object, its methods, and its properties.

Above, I’m using one of my methods, setBackgroundAlpha, as an example. Following the sample file, I’ve created a folder for the component, an enclosed folder listing its methods and, within that, each method I want to list. (Again, I’m showing only one to keep the display concise.) A unique name and id is associated with each entry, as well as which version of Flash the action is intended for. You can also add tool tip text for rollover help. The method listing also needs the syntax, the object it is a child of, and the type of action it is (procedure, function, event, etc.) If any of this isn’t immediately obvious from having used the Actions panel, you can find out more about each option in the Related Resources (see left column).

You can also add color syntax instructions and even code hints that come up when you’re using the actions in the Actions panel. For example, it can remind you to use an integer with .setBackgroundAlpha(). Those options have been omitted here, but are included in the source files.

The second major node is for the Reference panel. Here you can add the same formatting used by the rest of the Reference panel, for clarity and uniformity. This includes sections like usage, parameters, what the action returns (if anything), syntax examples, and so on. It also lets you use the CSS styles the Reference panel uses, like “titleStyle,” “subTitle,” and “codeStyle” so everything will look consistent with Flash’s own documentation.

When the XML is complete and well-formed, you can place this document in the Flash Configuration directory that I discussed in part 1 of this article. However, instead of placing this file in the “Components” folder, it goes in the “ActionsPanel/CustomActions” folder.

Step 10: Packaging the Component with the Extension Manager
You’ve already seen how to manually install your component for testing, but that’s not a practical way of distributing your work to others. Instead, you can package the assets into an .mxp file that the Extension Manager can install and uninstall for you.

The Macromedia Extension Manager is a utility that intelligently installs application-specific extensions?such as actions, components, and other enhancements?to Macromedia Studio applications such as Flash, Dreamweaver, Fireworks, and Freehand.

To package your component, the first thing you want to do is go back to the “Component Definition…” window and, when you’re sure you’re finished testing, switch your Live Preview and Custom UI files to embedded. This means you only have to distribute one FLA file, rather than also including multiple external SWF files.

Figure 3. Tidy Library: This is what your tidied Library should look like before packaging your extension. Note that all the necessary parts are enclosed in one folder (in this case ‘FMA Stamper’). This lone, organized folder will appear in the end-user’s file when dragging in your component from their Components palette.

The next thing is to clean up your Library. The component will be installed along with any parent and sibling folders. So, it’s nice to tidy that arrangement up so the user gets one new folder in his/her library. I start with a parent folder, and then inside that I include the component, the FCustomIcons folder (with icon) if desired, and any assets required. For example, the Stamper requires two MovieClips. I put those into an “art” folder.

Once you’ve tidied up (see Figure 3), create an instruction file for the Extension Manager so it knows which files to include in the .mxp bundle. This is called an MXI file. It is a simple XML file that includes name and version information about your component, compatible/required products, descriptions about the component and where it can be found inside Flash, and paths to any files you may be including. In this example, shown in Listing 2), you will include the FLA and XML files you created.

As you can see, this file contains environment variables that tell the Extension Manager where to install your files. You can learn more about the MXI file used by the Extension Manager by consulting Macromedia’s reference, “The MXI File Format.” You’ll find a link in the Related Resources section (see left column).

Once the MXI file is complete and well-formed, you can open the file in the Extension Manager. Use the “Package Extension…” command from the File menu. This will prompt you to save the newly packaged extension as an .mxp file that the Extension Manager can use to install the package where you’ve directed.

Adding Component at Runtime
The last item related to the example is adding the component to a movie at runtime. This is accomplished the same way you would add any MovieClip dynamically, with one exception: You must set the values of the component parameters with a property list in an optional third parameter of attachMovie().

Earlier, when you learned about registering your component class using its Linkage ID, you added a Linkage ID of “stamper” to your component. So, to add Stamper to your movie dynamically, your code would look like this:

attachMovie("stamper","myStamper",1000, {sBackAlpha: 50})

The first value is the aforementioned Linkage ID, the second is the new name of this instance, and the third is the level in which the new instance should appear. There’s nothing new so far. The last value, however, is the property list that sets the parameters of the component. You only have one parameter, so it’s quite simple.

What’s Next?
I hope this has been clear and that you now feel as though you can develop your own components. If you think about it, send me along examples of your work. I’m interested in hearing about your success and how you’ve implemented this technique.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: