Not yet rated

Problem

Creating a component by just extending sprite and adding elements used to pop up timing issues which is very common in Fash if the architecture is not right.

Solution

I have tried to build a core component class architecture; which can be extended for developing any form of liquid UIs and components. This will eliminate the timing issues and will work flawlessly with high performance.

Detailed explanation

/**
 * Component.as
 * Flash Player 9.0.28.0
 */
package com.core
{
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.events.Event;

    public class Component extends Sprite
    {    
        // ------------------------------------------
        // PROPERTIES
        // isSuspended starts as true as the component is off stage
        protected var _isSuspended:Boolean = true;
    

        protected var _width:Number = 0;
        protected var _height:Number = 0;
       
        public static const DRAW:String = "draw";

        /**
         * Constructor
         */
        public function Component():void
        {
            super();
           
            if (stage) {
                resume();
            }else {
                init();
            }
        }
       
       
        ///////////////////////////////////
        // PROTECTED METHODS
        ///////////////////////////////////
        protected function init():void
        {
          // concrete classes that override this function should call super.init()
          addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
          addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage, false, 0, true);
         
          // initialise component here.
          // no need to call draw() as it will be called when component is added to the stage.
        }
       
        /**
         * Overriden in subclasses to create child display objects.
         */
        protected function createChildren():void
        {
            // defining component elements
        }
       
        protected function invalidate():void
        {
            if(!hasEventListener(Event.ENTER_FRAME))
                addEventListener(Event.ENTER_FRAME, onInvalidate, false, 0, true);
        }
       
        protected function draw():void
        {
            // concrete classes should override this function
            // redraw component state
            dispatchEvent(new Event(Component.DRAW));
        }
       
       
        ///////////////////////////////////
        // PUBLIC METHODS
        ///////////////////////////////////
        public function destroy():void
        {
            // concrete classes that override this function should call super.destroy()
            // remove all listeners here
            suspend();
            removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
        }
       
        public function suspend():void
        {
          // concrete classes that override this function should call super.suspend()
          // suspend all processes
          removeEventListener(Event.ENTER_FRAME, onInvalidate);
          this._isSuspended = true;
        }
       
        public function resume():void
        {
          // concrete classes that override this function should call super.resume()
          // resume all processes
          this._isSuspended = false;
          createChildren();
          invalidate();
        }
       
        public function get isSuspended():Boolean
        {
            return _isSuspended;
        }
       
        /**
         * Moves the component to the specified position.
         * @param xpos the x position to move the component
         * @param ypos the y position to move the component
         */
        public function move(xpos:Number, ypos:Number):void
        {
            x = Math.round(xpos);
            y = Math.round(ypos);
        }
       
        /**
         * Sets the size of the component.
         * @param w The width of the component.
         * @param h The height of the component.
         */
        public function setSize(w:Number, h:Number):void
        {
            _width = w;
            _height = h;
            invalidate();
            dispatchEvent(new Event(Event.RESIZE));
        }
       
       
        ///////////////////////////////////
        // getter/setters
        ///////////////////////////////////
       
        /**
         * Sets/gets the width of the component.
         */
        override public function set width(w:Number):void
        {
            _width = w;
            invalidate();
            dispatchEvent(new Event(Event.RESIZE));
        }
        override public function get width():Number
        {
            return _width;
        }
       
        /**
         * Sets/gets the height of the component.
         */
        override public function set height(h:Number):void
        {
            _height = h;
            invalidate();
            dispatchEvent(new Event(Event.RESIZE));
        }
        override public function get height():Number
        {
            return _height;
        }
       
        /**
         * Overrides the setter for x to always place the component on a whole pixel.
         */
        override public function set x(value:Number):void
        {
            super.x = Math.round(value);
        }
       
        /**
         * Overrides the setter for y to always place the component on a whole pixel.
         */
        override public function set y(value:Number):void
        {
            super.y = Math.round(value);
        }
       
       
        ///////////////////////////////////
        // EVENTS
        ///////////////////////////////////
        private function onInvalidate(e:Event):void
        {
            removeEventListener(Event.ENTER_FRAME, onInvalidate);
            draw();
        }

        private function onAddedToStage(e:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
            resume();
        }

        private function onRemovedFromStage(e:Event):void
        {
            suspend();
        }
       
    }
}


package com.view.ui.components
{
    import com.core.Component;

    
    /**
     * MyComponent.as
     */
    public class MyComponent extends Component
    {
        private var _source:String;
       
        public function MyComponent()
        {
            super();
        }
       
        override protected function createChildren():void
        {
            //declare and add all elements of the component here
        }
       
        override protected function draw():void
        {
            super.draw();
           
            //set the positions of the elements added
            //this gets called on resizing the component
           
        }
       
        public function set source( value:String ):void
        {
            _source = value;
           
            invalidate(); // call this function if you want to redraw the component based on the source.
        }
    }
}

+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes