Welcome to my website. I am always posting links to photo albums, art, technology and other creations. Everything that you will see on my numerous personal sites is powered by the formVistaTM Website Management Engine.

icon.linkedin.jpgicon.twitter.jpg

  • Subscribe to this RSS Feed
  • Integrating Thunderbird and Firefox Under Linux
    12/05/2007 10:13PM
    Here's a quick how-to on getting Firefox to start new mail messages with Thunderbird and getting Thunderbird to open links in Firefox under Linux.

    For Thunderbird:
    All you need to do is edit the prefs.js file in your .mozilla-thunderbird/blahblah.defaults/ (or similarly named) directory.  Add the following (specifying your path to Firefox):
    user_pref("network.protocol-handler.app.http", "/usr/bin/firefox" );
    user_pref("network.protocol-handler.app.https", "/usr/bin/firefox" );


    For Firefox:
    Edit the prefs.js file in your .mozilla/firefox/blahblah.defaults/ directory.  Add the following:
    user_pref("network.protocol-handler.app.mailto","/usr/bin/thunderbird");



  • An Excellent Tutorial on How to Create Custom Components with Action Script 2.0
    11/29/2007 7:22AM
    Flash MX and MX 2004 include the v2 Flash component architecture and enable you to develop your own custom components.

    Here's an excellent article that goes through, step-by-step, on how to write your own class files, component movie clips and export to .swc.

    Creating Components with Flash MX 2004

    by Joey Lott (www.person13.com)

    Don't let the idea of writing a custom component intimidate you. Although components may appear very complex, they are really just fancy movie clips. You know how to work with movie clips, and so even if you don't yet know it, you also know how to write a custom component. There is only one caveat: You do need to be familiar with writing ActionScript 2.0 classes. If you don't yet know how to write an ActionScript 2.0 class, then you'll want to make sure to read the ActionScript 2.0 primer series at www.person13.com/arcticles.

    In this article we'll discuss the following:

    * Benefits of components.
    * Creating a component movie clip.
    * Writing a basic component class.
    * Linking a component class with a movie clip symbol.
    * Exporting a compiled clip.

    One thing that you may notice is not included in the preceding list is a discussion of extending the v2 component framework. The much-hyped v2 framework is not something I am going to discuss in this article for several reasons. One reason is that I think you'll find a benefit in understanding how to create a component from scratch, without relying heavily on the architecture built by Macromedia that can obfuscate the fundamental principals. Additionally, I don't find too much to champion about the v2 framework. While it definitely provides some nice functionality such as style and focus management, it also adds significant overhead in terms of kilobytes to your .swf. For example, if you add the Macromedia ProgressBar component to a Flash document and export the .swf, the file is 27KB. If you extend the v2 framework, you can be assured that your components will also have a minimum filesize that approximates that of the Macromedia ProgressBar.

    I will note, however, that even if you do want to extend the v2 framework, this article will still cover all the basic concepts that you will want to know. Once you've understood the principals in this article you will be prepared to then utilize the v2 framework.

    Benefits of Components

    Before you start learning how to create components, it is likely beneficial to first investigate the potential benefits of components. Although a component is really just a fancy movie clip, a component can be so much more. It is an example of the whole being greater than the sum of its parts.

    Consider the basic UI components included with Flash. You could create a custom combobox or button control for each time you need one. You could create the artwork and write a bunch of ActionScript code on the main timeline, and accomplish something very similar. But it sure is a lot simpler to just drag and drop and set a few parameters. That simple example illustrates many of the benefits of components. Namely, the component contains reusable functionality, encapsulated in such a way that you need only to drag an instance onto the stage in order to utilize it. Additionally, components allow you to set parameters either by way of a graphical interface (the Component Inspector panel) or by way of an API. This means that with a component you can still utilize the power of interfacing via ActionScript, but you also allow for the flexibility of being able to just hand over the component to a developer who is more comfortable setting parameters with the Component Inspector panel.

    Not only are components encapsulated functionality, but they also make distributing that functionality pretty simple. If you want to let someone else use the component you've built, all you need to do is package it, send it to them, and with a few clicks, they'll have it installed. Furthermore, if you package your component as an .swc file, then the code is relatively protected (although typically some decompiler does exist that can reconstitute the original ActionScript code.)

    Creating a Component Movie Clip

    With few exceptions you attach or load all artwork into a component at runtime. That means that you will be handling just about everything with ActionScript code. Therefore, a component movie clip is really quite simple. However, there are a few things you need to keep in mind:

    * A component will only actually render artwork that fits within the boundaries of artwork that is defined within the movie clip at authoring time. This might seem somewhat strange. What that means in practical terms is that if you don't define any authoring time artwork within the component movie clip then none of the artwork you attach or load will be displayed. The solution is to define a rectangular movie clip instance on the first frame of the timeline within the movie clip symbol. I typically call the instance mcBoundingBox. And mcBoundingBox should be made to the dimensions into which all the component artwork will fit.

    * In order to be able to correctly export an .swc file (which you'll see how to do a bit later) the component symbol needs to contain instances of all other symbols that are attached via code. Otherwise the other symbols are not exported into the .swc. Therefore, the suggested way to accomplish this is to create a second frame in the component movie clip's timeline, and add instances of all the symbols you will attach with code.

    * Since you're component movie clip symbol will have two frames - the first containing the mcBoundingBox instance, and the second containing instances of all the other symbols you want to be able to attach - you should make sure to place a stop() action on the first frame.

    Writing a Component Class

    A component consists of at least one movie clip symbol and an associated ActionScript class. You already know how to make movie clip symbols (at least I assume you do) so what we want to discuss in this part of the article is how to create the ActionScript class. If you've already learned how to write a basic ActionScript 2.0 class, then this part is actually very simple.

    Component classes should extend the MovieClip class. By extending MovieClip, you ensure that the component inherits all the properties and methods of the MovieClip class. That means that you'll be able to use ActionScript to do things like control placement on the stage, set visibility and alpha, etc. It also means that you can use methods like createEmptyMovieClip() and attachMovie() within the class to add nested elements to the component. Your class can extend MovieClip either directly or indirectly. For example, you may want to create a base class for your components that provides common functionality to all of them. That class should then extend MovieClip, and all your component classes should extend the base class.

    There are a handful of special methods that component classes can (and probably should) implement. We'll take a look at some of those in a bit. But first, let's just create a basic class example.

    class com.person13.SampleComponent extends MovieClip {


    // You have to declare the class member in order to reference it within
    // the code. In this case, mcBoundingBox is the name we have given to
    // the authoring time bounding box movie clip that we created in the
    // associated component symbol.

    private var mcBoundingBox:MovieClip;



    function SampleComponent() {
    // It can be useful to have the constructor simply call other methods
    // rather than placing a lot of code within it directly. This allows
    // you to organize your code well. You'll see in later examples how
    // this can be beneficial.

    init();

    }


    private function init():Void {


    // Typically you want to set the bounding box to be invisible and
    // set its dimensions to 0. The bounding box's authoring time dimensions
    // determine the renderable area within the component, but it can
    // be hidden during runtime.
    mcBoundingBox._visible = false;
    mcBoundingBox._width = 0;
    mcBoundingBox._height = 0;

    }



    }

    The preceding class demonstrates the basics of a component class. You should make sure to extend MovieClip and hide the bounding box instance. The code thus far doesn't do too much, but I want to show you the code a piece at a time so that a) you don't get overwhelmed unnecessarily and b) you can see and understand what each part does.

    As you can see indicated in the comments in the preceding code, I recommend you call other methods from within the constructor rather than placing a bunch of functionality within the constructor itself. I typically use a set of methods that I call from within the constructor method in the following order:

    * init() - This is the method within which any initialization code can appear. I typically scale the instance too 100% for reasons you'll read later. It's also where I usually hide the bounding box (as you've already seen) and initialize the class to be able to dispatch events (something you'll see more of in a short while.)

    * createChildren() - This is the method I use to attach and create all movie clips and text fields and the like. It typically contains some attachMovie() and/or createEmptyMovieClip() methods at the very least.

    * draw() - The draw() method is one in which I programmatically draw anything that needs to be drawn. Not all components necessarily need to draw anything. But for those that do, the draw() method is where I place that code.

    * arrange() - The arrange() method is where I place the code that places the artwork at the correct coordinates. Typically the arrange() method gets called at different times throughout the component's existence. Each time the component is resized, for example, I'll probably want to rearrange the elements.

    You'll get a chance to see more of all this kind of implementation shortly.

    Linking a component class with a movie clip symbol.

    Once you've defined the basic movie clip symbol and the component class, you next should associate them with one another. When an instance of a movie clip is created - whether by dragging an instance onto the stage or by attaching an instance with code - Flash typically associates the symbol with the MovieClip class. But you want to tell Flash to associate the symbol with your custom class so that the instances will be able to access the functionality you have built into your class.

    You can associate a class with a movie clip symbol by setting the ActionScript 2.0 class value in the symbol's linkage settings. To get to the movie clip's linkage settings right-click/command-click on the symbol in the library, and choose Linkage. From the linkage settings you need to do several things:

    * Check the Export for ActionScript option.

    * Give the symbol a linkage identifier.

    * Specify the class in the AS 2.0 Class field. You must provide the fully-qualified class name. That means that if the class is in the com.person13 package, for example, you need to include that package name.

    You'll also need to set the ActionScript 2.0 class value within the symbol's component definition. You can access the component definition by right-clicking/command-clicking on the symbol in the library and choosing the Component Definition option. Enter the fully-qualified class name in the AS 2.0 Class field.

    Once you've done those two things you have associated the class with the symbol. Then, when you create an instance of the symbol Flash will automatically make it an instance of the class instead of making it an instance of MovieClip by default.

    Adding Parameters

    Although you may want to create components that can only be controlled via their API, in most cases you will want to allow the component instances to be configured from the Component Inspector panel - even by someone who doesn't know how to write any ActionScript code. That is one of the many benefits of components.

    If you created components in Flash MX then you will recall that you defined parameters within the Component Definition dialog box. However, that portion of the dialog box remains for legacy support only. When you create a component in Flash MX 2004 with an ActionScript 2.0 class you should define the parameters using special metatags within the class file. The metatag approach has many benefits over the previous way of defining parameters. One of the biggest advantages is that it is much more efficient than trying to add parameter values in the silly dialog boxes like you used to have to do.

    The [Inspectable] metatag tells Flash to make a property a parameter for the component. If you place the [Inspectable] metatag just before any property (including getter and setter methods) within the class, that property will be automatically made into a parameter. I don't typically advocate defining public properties except by way of getter and setter methods. So all the examples I'll show you work with getter and setter methods. But you could just as well place [Inspectable] on the line before you define any public property within a class and it would work in the same way.

    The following example shows how the [Inspectable] tag can be placed just before a getter or setter method to make it a parameter.

    [Inspectable]
    public function set value(nValue:Number):Void {
    _nValue = nValue;

    }

    If you have a pair of methods - one getter and one setter - for the same property, you only need to place the [Inspectable] metatag prior to one of them.

    The [Inspectable] metatag allows you to specify some additional information as a list of name-value pairs within parentheses. You can consult the Flash Help panel for a complete list of [Inspectable] information, but three of the most important are:

    * defaultValue - The default value that Flash should use. This is the value that will get displayed in the Component Inspector panel for the parameter when the component instance is first dragged onto the stage.

    [Inspectable(defaultValue=10)]

    * type - The type of value. This determines how the user can interact with the parameter value in Flash. The default value is Default, which allows the user to enter a value by typing it into the field in the Component Inspector. You can also specify things like Boolean (which then gives the user a choice between true and false) and Color (which prompts the user with a color selector.)

    [Inspectable(type=Color)]

    * enumeration - A list of values from which the user can select. This is used when the type is Array. The enumeration options should be a quote-enclosed comma-delimited list.

    [Inspectable(type=Array, enumeration="a,b,c,d,e,f,g")]

    When you update the parameters for a class by adding, removing, or modifying [Inspectable] metatags, you must open the Component Definition dialog box and click OK again for Flash to update with the new information.

    Handling Resizing

    One thing that you'll almost certainly need to do is set up your component to correctly handle resizing. By default, when you resize a component instance - either at authoring time with the Property inspector or at runtime with the _width and _height properties - Flash will simply scale the component. However, in most cases that will not be what you want. For example, later in the article you'll get a chance to create a sample scroll bar component. A scroll bar consists of several parts, including the up and down scroll arrow buttons, the scroll track, and the scroll thumb bar. If you adjust the size of the scroll bar you don't want the up and down scroll arrow buttons to scale. They should remain the same size while the scroll track should scale to fill the rest of the area between. Figure 1 shows a comparison between the two scenarios.

    Figure 1: The scroll bars are both resized to 150 pixels in height. However, the one on the left is resize correctly such that the up and down scroll arrow buttons are not distorted. The scroll bar on the right was simply scaled uniformly.

    Therefore, you will likely want to handle resizing intelligently. There are two types of resizing that can occur - authoring time resizing caused by a change in the values in the Property inspector, and runtime resizing caused by adjusting the various properties of the component instance. Each of these should be handled differently, so let's look at them separately.

    First, let's look at authoring time resizing. Authoring time resizing really only affects live preview appearance, and it doesn't actually have any effect on the runtime appearance. But live preview appearance can be just as important. If you are creating authoring time instance of your component, you'll want to be able to see what the changes you are making will have on the component. When you set the values for width and height in the Property inspector, it really just scales the instance of the movie clip or component. In order to be able to detect and handle resizing you should implement a setSize() method in your component class. Unlike many of the other methods I've mentioned previously in this article (init(), draw(), etc.) the setSize() method name is something that is hardcoded into Flash. When the authoring time dimensions of a component instance change Flash will automatically look for and call the setSize() method of the associated component class, and it passes the method two parameters - the first specifying the newly assigned width and the second specifying the newly assigned height. Within your setSize() method you will probably want to do at least two things:

    * Set the scaling of the instance back to 100.

    * Call the arrange() and possibly the draw() methods.

    Typically I also create __width and __height properties (each of those is with two underscores so as to differentiate them from the built-in _width and _height properties) within component classes. I use those properties to hold the actual dimensions for the component instance. Since you are going to scale the instance back to 100 percent, you'll lose the new width and height values that have been assigned to _width and _height (single underscore). So I recommend you assign the value of the first parameter to __width and the second parameter value to __height (both with double underscores) and then use __width and __height in your calculations within your other methods such as draw() and arrange(). This will likely be clearer to you when you get a chance to work through the sample component later in the article.

    So you can get an idea of what your setSize() method implementation might look like, consider the following:

    private function setSize(nW:Number, nH:Number):Void {
    _xscale = 100;
    _yscale = 100;
    if(nW != null) {
    __width = nW;
    }
    if(nH != null) {
    __height = nH;
    }
    arrange();
    }

    You should also make sure to set the scaling and the __width and __height properties in your class's init() method. In that case you'll be assigning the value of _width to __width, and the value of _height to __height. So make sure you do those assignments before you set the scaling back to 100. For example:

    private function init():Void {
    __width = _width;
    __height = _height;
    _xscale = 100;
    _yscale = 100;
    mcBoundingBox._visible = false;
    mcBoundingBox._width = 0;
    mcBoundingBox._height = 0;
    }

    The next thing you need to be able to handle is runtime resizing. If you've used any of the v2 components then you'll notice that they have width and height properties for resizing them rather than using the _width and _height properties built into the MovieClip superclass. If you try resizing a v2 component instance using the _width and _height properties then you'll see that they scale rather than resizing as you'd expect. The width and height properties are defined within the v2 framework as getter and setter methods so that the components can handle resizing intelligently. I recommend you do the same with your own components.

    Typically the way that I recommend implementing the width and height getter and setter methods is as follows:

    * In the setter methods simply call setSize().

    * In the getter methods return the value of __width or __height.

    For example, the following shows a height getter and setter method pair.

      public function set height(nHeight:Number):Void {
    setSize(null, nHeight);
    }

    public function get height():Number {
    return __height;
    }

    The only other consideration with resizing is, as I have already mentioned, that you use __width and __height (double underscores) in your other methods to calculate how you draw and arrange things. If you use the built-in _width and _height (single underscores) then it will just consistently draw and arrange things to the default size.

    Dispatching Events

    Another thing you'll want to be able to have your components do is dispatch events. If you haven't yet familiarized yourself with the listener model for the v2 components, you might want to do that before reading further. Just to refresh your memory, however, I'll summarize the details.

    You can add an object to a v2 component as a listener using the addEventListener() method. When an event occurs within the component, it automatically notifies all listeners that are registered to receive that type of event. Flash then calls the method of the listener object that has the same name as the event. For example, if you have a Button instance then you can register a listener object to handle click events. The following code demonstrates this:

    var oListener:Object = new Object();

    oListener.click = function(oEvent:Object):Void {
    trace(oEvent.target + " was clicked");

    };

    cbSubmitButton.addEventListener("click", oListener);

    The simplest way to enable your components to dispatch events to listeners is to use the same mechanism as the v2 components use. In the mx.events package (a package of classes that ships with Flash) you'll find an EventDispatcher class. You can call the class's static method, initialize(), from within your component class to set up the class to be able to register listeners and dispatch events. The initialize() method requires a parameter that references the object for which you want to enable the event dispatching. In the case of your component the value should be this. I typically recommend you call the mx.events.EventDispatcher.initialize() method from within your class's init() method. For example (line shown in bold):

    private function init():Void {
    __width = _width;
    __height = _height;
    _xscale = 100;
    _yscale = 100;
    mx.events.EventDispatcher.initialize(this);
    mcBoundingBox._visible = false;
    mcBoundingBox._width = 0;
    mcBoundingBox._height = 0;
    }

    Then, to dispatch an event, you can use the dispatchEvent() method that your class will automatically "inherit" (in quotes because it is not really inheritance) from EventDispatcher. And the class will also "inherit" the addEventListener() and removeEventListener() methods so that you can register listener object with instances of the class. The only thing is that you must make sure to declare dispatchEvent(), addEventListener(), and removeEventListener() as a class member along with the other class members as follows:

    private var dispatchEvent:Function;
    public var addEventListener:Function;
    public var removeEventListener:Function;

    That simply lets the class know that the method exists. If you don't add that line of code to the class then Flash will give you an error when you try to compile.

    The dispatchEvent() method requires one parameter - an object with at least two parameters: type and target. The type property should be a string specifying the name of the event. The target property should be a reference to the object dispatching the event. In most cases that will be this. The following is an example of how to dispatch an event.

    dispatchEvent({type: "click", target: this});

    As with much of what has been discussed so far, don't worry too much if you don't feel you quite "get" it yet. It will likely be much clearer to you when you get a chance to work through an example.

    Exporting a compiled clip

    Once you've created your component symbol and class, you will likely want to export it as a compiled clip into an .swc file. An .swc is a zip format that contains all the necessary elements of your component - including live preview. After you've exported the .swc file you can place it in the appropriate directory so that it will show up in your Components panel so that you can utilize the component in your other Flash applications. You can also package it as an .mxp so that you can distribute it to other developers.

    Exporting a .swc file is really extraordinarily simple. All you need to do is select the component movie clip symbol from the library, right-click/command-click, and choose Export SWC from the menu. Flash will prompt you as to where you want to save it. Choose a location, and then save the .swc file.

    In order to add the component to your Components panel select the .swc file and copy it to the appropriate directory on your computer. On Windows XP that directory is likely something like: C:\Documents and Settings\[User Name]\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Components. I don't use a Macintosh, so I don't know what the directory on Mac is, but you can probably figure it out based on the Windows XP information. Once you've added a copy of the .swc file to that directory you can reload the Components panel. To do so, open the Components panel, select the panel menu, and choose Reload. Once it reloads you should see the component added to the list.

    Note: You should save the .swc file into a subdirectory within the Components directory.

    In order to package the component in an .mxp file you need to make sure you have the latest Extension Manager. You then need to create an .mxi file. The .mxi format is just XML. The following listing is an example you can adapt.

    <macromedia-extension
    name="com.person13.SampleScrollBar"
    version="1.0"
    type="flashcomponent">

    <!-- Describe the author -->

    <author name="Joey Lott" />

    <!-- List the required/compatible products -->

    <products>
    <product name="Flash" version="7" primary="true" />
    </products>

    <!-- Describe the extension -->

    <description>
    <![CDATA[
    Window component.
    ]]>
    </description>

    <!-- Describe where the extension shows in the UI of the product -->

    <ui-access>
    <![CDATA[
    Components panel.
    ]]>
    </ui-access>

    <!-- Describe the files that comprise the extension. Make sure that you save
    The .mxi in the same directory as the .swc file(s)
    -->

    <files>
    <file name="SampleScrollBar.swc" destination="$flash/Components/" />
    </files>

    </macromedia-extension>

    You can then open the Extension Manager to package the component. Choose File > Package Extension. From the dialog box choose the .mxi file and click OK. Then select the name and location to which you will save the .mxp file. Export the .mxp. You can then distribute the .mxp. Anyone who has the Extension Manager will be able to install your component with a few clicks.

    Making a Sample Component

    Thus far you've read a lot of theory. How about putting it into practice? In this exercise you'll create a sample scroll bar component. The scroll bar component will be fairly simple so that the principals involved in creating a component are highlighted. You can feel free to later modify the code to provide more functionality to the scroll bar.

    1. Download the SampleScrollBar.zip file.

    2. Extract the files from the .zip. It should create the following:

    /StarterFiles
    - SampleScrollBar_starter.fla
    - com/person13/SampleScrollBar.as

    /CompletedFiles
    - SampleScrollBar.fla
    - com.person13/SampleScrollBar.as

    The StarterFiles directory contains the files you should use to get started. The .fla is there because it contains the artwork to get started. The CompletedFiles directory is provided so you can see the working example.

    3. Open StarterFiles/SampleScrollBar_starter.fla, and open the document's library.

    4. In the library you'll find several movie clip symbols. ScrollUp, ScrollDown, ScrollTrack, and ScrollThumb have already been set for export and given linkage identifiers. ScrollBar has not been set for export yet. So open the symbol's linkage settings, and check the Export for ActionScript option. Give it a linkage identifier of ScrollBar. And set the AS 2.0 Class field to com.person13.SampleScrollBar.

    5. Open the ScrollBar symbol in editing mode. You'll see that two layers and several keyframes have already been created for you. Add a stop() action to the keyframe in the Actions layer.

    6. Drag an instance of BoundingBox onto the stage on the first frame of the Assets layer. Name the instance mcBoundingBox, resize it to 15 pixels by 100 pixels, and set the x and y coordinates to 0 and 0.

    7. On the second frame of the Assets layer add instances of ScrollUp, ScrollDown, ScrollTrack, and ScrollThumb.

    8. Save the .fla file, and next open the com/person13/SampleScrollBar.as file.

    9. SampleScrollBar.as has been left intentionally blank. Add the following code to the class file:

    class com.person13.SampleScrollBar extends MovieClip {


    // The BoundingBox instance created at authoring time within the symbol.
    private var mcBoundingBox:MovieClip;

    // The instances of the other movie clip symbol assets that you will create programmatically.
    private var _mcScrollUp:MovieClip;
    private var _mcScrollTrack:MovieClip;
    private var _mcScrollDown:MovieClip;
    private var _mcScrollThumb:MovieClip;

    // The interval identifier used with setInterval() and clearInterval()
    private var _nInterval:Number;

    // The pixel offset based on where you click on the scroll thumb bar.
    private var _nOffset:Number;

    // The __width and __height properties we use to store the dimensions of the instance.
    private var __width:Number;
    private var __height:Number;

    // The previous scroll value. This is used to make sure that the component only dispatches events
    // when the value has actually changed.
    private var _nPrevScroll:Number;

    // The minimum and maximum scroll values. Default to 0 and 100.
    private var _nMax:Number = 100;
    private var _nMin:Number = 0;

    // The placement of the scroll thumb bar.
    private var _nScrollPosition:Number = 0;

    // The dispatchEvent() method that gets added by EventDispatcher.
    private var dispatchEvent:Function;


    // The getter and setter methods for min and max.
    [Inspectable(defaultValue=0)]
    public function set min(nMin:Number):Void {
    _nMin = nMin;
    }

    public function get min():Number {
    return _nMin;
    }

    [Inspectable(defaultValue=100)]
    public function set max(nMax:Number):Void {
    _nMax = nMax;
    }

    public function get max():Number {
    return _nMax;
    }

    // The getter and setter methods for scrollPosition. When the scrollPosition is set, assign the value
    // to the private property, and then call arrange(). When the value is gotten, calculate the value
    // based on the thumb bar's _y coordinate and the min and max values.
    [Inspectable(defaultValue=0,type=Number)]
    public function set scrollPosition(nScrollPosition:Number):Void {
    _nScrollPosition = nScrollPosition;
    arrange();
    }

    public function get scrollPosition():Number {
    var nVal:Number = (_mcScrollThumb._y - _mcScrollTrack._y) / (_mcScrollTrack._height - _mcScrollThumb._height) * (_nMax - _nMin) + _nMin;
    return Math.round(nVal);
    }

    // The getter and setter methods for height. No need to define width because this simple scroll bar
    // can only be vertical.
    public function set height(nHeight:Number):Void {
    setSize(null, nHeight);
    }

    public function get height():Number {
    return __height;
    }

    // The setSize() method is automatically called when the authoring time instance is resized.
    public function setSize(nW:Number, nH:Number):Void {
    _xscale = 100;
    _yscale = 100;
    __width = nW;
    __height = nH;
    arrange();
    }

    // The constructor.
    function SampleScrollBar() {
    init();
    createChildren();
    arrange();
    }

    // Basic init() method as outlined in article.
    private function init():Void {
    __width = _width;
    __height = _height;
    _xscale = 100;
    _yscale = 100;
    mx.events.EventDispatcher.initialize(this);
    mcBoundingBox._visible = false;
    mcBoundingBox._width = 0;
    mcBoundingBox._height = 0;
    }

    // The createChildren() method istantiates the up and down scroll arrow buttons, the scroll track, and the
    // scroll thumb bar. Although in a completely abstracted example we might define classes for
    // each of those elements, in this case we just assign the onPress(), onRelease(), and onReleaseOutside()
    // methods to each of them within the createChildren() method.
    private function createChildren():Void {
    attachMovie("ScrollUp", "_mcScrollUp", getNextHighestDepth());
    attachMovie("ScrollTrack", "_mcScrollTrack", getNextHighestDepth());
    attachMovie("ScrollDown", "_mcScrollDown", getNextHighestDepth());
    attachMovie("ScrollThumb", "_mcScrollThumb", getNextHighestDepth());
    _mcScrollThumb.onPress = function():Void {
    this._parent._nOffset = this._ymouse;
    this._parent._nInterval = setInterval(this._parent, "scroll", 10);
    };
    _mcScrollThumb.onRelease = function():Void {
    clearInterval(this._parent._nInterval);
    };
    _mcScrollThumb.onReleaseOutside = _mcScrollThumb.onRelease;
    _mcScrollUp.onPress = function():Void {
    this._parent._nInterval = setInterval(this._parent, "nudge", 10, -1);
    };
    _mcScrollUp.onRelease = function():Void {
    clearInterval(this._parent._nInterval);
    };
    _mcScrollUp.onReleaseOutside = _mcScrollUp.onRelease;
    _mcScrollDown.onPress = function():Void {
    this._parent._nInterval = setInterval(this._parent, "nudge", 10, 1);
    };
    _mcScrollDown.onRelease = function():Void {
    clearInterval(this._parent._nInterval);
    };
    _mcScrollDown.onReleaseOutside = _mcScrollDown.onRelease;
    }

    // Arrange all the elements. This method gets called when the instance is first created as well
    // as every time it is resized.
    private function arrange():Void {

    // Set the height of the scroll track to be the height of the entire instance (given by __height)
    // minus the default heights of the up and down arrow buttons.
    _mcScrollTrack._height = __height - _mcScrollUp._height - _mcScrollDown._height;

    // Place the scroll track just below the up arrow button.
    _mcScrollTrack._y = _mcScrollUp._height;

    // Place the down arrow button just below the scroll track.
    _mcScrollDown._y = _mcScrollTrack._y + _mcScrollTrack._height;

    // Place the scroll thumb bar one pixel to the right so it appears within the scroll track.
    _mcScrollThumb._x = 1;

    // Determine the vertical placement of the scroll thumb bar based on _nScrollPosition.
    var nY:Number = ((_nScrollPosition - _nMin)/(_nMax - _nMin)) * (_mcScrollDown._y - _mcScrollThumb._height);
    if(nY > _mcScrollDown._y - _mcScrollThumb._height) {
    nY = _mcScrollDown._y - _mcScrollThumb._height;
    }
    else if(nY < _mcScrollTrack._y) {
    nY = _mcScrollTrack._y;
    }
    _mcScrollThumb._y = nY;
    }

    // This method is called at an interval when the thumb bar is dragged by the user.
    private function scroll():Void {

    // Determine the vertical placement of the thumb bar based on the value of _ymouse minus
    // the offset. Also, calculate the maximum and minimum values in the range. If the mouse is
    // outside those values then use the corresponding maximum or minimum value so that the thumb
    // bar does not leave the scroll track.
    var nY:Number = _ymouse - _nOffset;
    var nUpper:Number = _mcScrollTrack._y;
    var nLower:Number = _mcScrollDown._y - _mcScrollThumb._height;
    if(nY > nUpper && nY < nLower) {
    _mcScrollThumb._y = _ymouse - _nOffset;
    }
    else if(nY < nUpper) {
    _mcScrollThumb._y = nUpper;
    }
    else if(nY > nLower) {
    _mcScrollThumb._y = nLower;
    }

    // Dispatch an event by calling the custom dispatchScrollEvent() method (defined later.)
    dispatchScrollEvent();
    updateAfterEvent();
    }

    // This method is called whenever the up or down arrow buttons are pressed. The functionality
    // is very similar to the scroll() method. See the comments in the scroll() method for details.
    private function nudge(nIncrement:Number):Void {
    var nUpper:Number = _mcScrollTrack._y;
    var nLower:Number = _mcScrollDown._y - _mcScrollThumb._height;
    _mcScrollThumb._y += nIncrement;
    if(_mcScrollThumb._y < nUpper) {
    _mcScrollThumb._y = nUpper;
    }
    else if(_mcScrollThumb._y > nLower) {
    _mcScrollThumb._y = nLower;
    }
    dispatchScrollEvent();
    updateAfterEvent()
    }

    // If the current value differs from the previous value, dispatch a scroll event.
    private function dispatchScrollEvent():Void {
    if(_mcScrollThumb._y != _nPrevScroll) {
    dispatchEvent({type: "scroll", target: this});
    _nPrevScroll = _mcScrollThumb._y;
    }
    }

    }

    10. Save the .as file and return to the .fla.

    11. Select the ScrollBar symbol from the library and open the Component Definition dialog box.

    12. Enter the value of com.person13.SampleScrollBar to the AS 2.0 Class field and click OK.

    13. Select the ScrollBar symbol and choose the Export SWC option. Export the file to the Components/UI Components directory as discussed earlier in this article.

    14. Open a new .fla document.

    15. Open the Components panel and reload it. The ScrollBar component should appear in the panel.

    16. Drag an instance of ScrollBar from the Components panel to the stage on the main timeline. Name the instance csbScroller.

    14. Open the Component Inspector panel. You should see the properties max, min, and scrollPosition. Set the values to 200, -200, and 100.

    15. Using the Property inspector resize the component instance to 200 pixels in height.

    16. Add a new layer to the main timeline and add the following actions to the keyframe in that layer:

    var oListener:Object = new Object();

    oListener.scroll = function(oEvent:Object):Void {
    trace(oEvent.target.scrollPosition);

    };

    csbScroller.addEventListener("scroll", oListener);

    17. Test the movie. You should see the scrollPosition value write to the Output panel as you scroll the scroll bar.

    Conclusion

    Components are a rather powerful and sometimes confusing subject. Hopefully this article has helped you get started writing components. It is not intended to be an exhaustive reference on the subject, however. Please do email me with your feedback and with an corrections you might have. And, as usual, thanks for reading.

  • Thunderbird not able to save to Sent or Drafts folder with an IMAP account
    11/20/2007 4:00PM
    I'm migrating my workstation to CentOS 5.  I've decided it's time to retire my old Mozilla suite install and upgrade to the latest of Firefox and Thunderbird.

    If you are using an IMAP account, Thunderbird has an annoying bug whereby it hangs when attempting to copy a sent message to the Sent, or Drafts folder on the server.

    Click on the Read More link for the fix . . . 
    After quite a bit of searching and trial and error I discovered that by making a small change in the default setting for your account you can get Thunderbird to copy both sent messages and drafts to the server.

    Open up the account settings:

    Edit/Account Settings

    And click on "Copies and Folders" for the account in question.  Under "When sending messages, automatically:" click on the radio button next to "Other" and then simply choose the name of the Sent folder on the server.

    Do the same for the Drafts and you should be all set.
  • Mysterious Yellow Form Fields
    10/30/2007 9:26AM
    If you have ever noticed mysterious yellow form fields on websites, or in my case, had a client call and wonder why there are random yellow form fields on a site that you designed when you know you didn't design it that way, this article should help.

    It's the Google Tool bar in IE, and there is an elegant fix for it that allows you to either disable completely the highlighted fields or customize them and display a special message to Google Toolbar users.
    I discovered this fix on Jon Jensen's blog.  Click here for Jon's full explaination and fix.

    For those who just want the fix without the "blah, blah, blah", here it is:

    1. Add the following javascript to the <head> tag of your HTML document: 
      <script type="text/javascript"><!--
      if(window.attachEvent)
      window.attachEvent("onload",setListeners);

      function setListeners(){
      inputList = document.getElementsByTagName("INPUT");
      for(i=0;i<inputList.length;i++){
      inputList[i].attachEvent("onpropertychange",restoreStyles);
      inputList[i].style.backgroundColor = "";
      }
      selectList = document.getElementsByTagName("SELECT");
      for(i=0;i<selectList.length;i++){
      selectList[i].attachEvent("onpropertychange",restoreStyles);
      selectList[i].style.backgroundColor = "";
      }
      }

      function restoreStyles(){
      if(event.srcElement.style.backgroundColor != "" && event.srcElement.style.backgroundColor != "#a0d0ff"){
      event.srcElement.style.backgroundColor = "#CHANGE_TO_CUSTOM_COLOR"; /* color of choice for AutoFill */
      document.all['googleblurb'].style.display = "block";
      }
      }//-->

      </script>
    2. Change the background color setting in the 5th to the last line where it says #CHANGE_TO_CUSTOM_COLOR" to a color that you would like to use instead of the default Google Toolbar bright yellow.
    3. Add the following above your form, which will render only if the user has the Google Toolbar installed
      <div id="googleblurb" style="display:none;">
        You can use the AutoFill function on the Google toolbar to fill out
        the highlighted fields on this form.
        <a href="http://toolbar.google.com/autofill_help.html"
        title="AutoFill Help Page">Learn more</a>.
      </div>
    4. Done!  Now when the page loads for a user with the Google Toolbar, they'll see the highlighted forms in a custom color and a custom message explaining to them why they are highlighted.


  • Flash CS3: Enabling Type Annotation Warnings for Compile-Time Checking
    10/23/2007 1:13PM
    Most ActionScript 2.0 and 3.0 programmers type all variables in their code.

    In CS3, to enable the type checking during compilation you must do the following:
    1. Using a text editor open the following file in the Flash CS3 installation folder: /en/Configuration/ActionScript 3.0/EnabledWarnings.xml
    2. Locate the following line: <warning id="1008" enabled="false" label="kWarning_NoTypeDecl">Missing type declaration.</warning>
    3. Change enabled="false" to enabled="true"
    4. Save the file
    Attached is the updated configuration file
    Attachment: EnabledWarnings.xml 5505 bytes
Advanced Search

Categories

Archives