////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.core
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.system.ApplicationDomain;
    import flash.utils.getQualifiedClassName;

    import org.apache.flex.events.Event;
    import org.apache.flex.events.IEventDispatcher;
    import org.apache.flex.events.MouseEvent;
    import org.apache.flex.events.utils.MouseEventConverter;
    import org.apache.flex.utils.MXMLDataInterpreter;

    //--------------------------------------
    //  Events
    //--------------------------------------

    /**
     *  Dispatched at startup. Attributes and sub-instances of
     *  the MXML document have been created and assigned.
     *  The component lifecycle is different
     *  than the Flex SDK.  There is no creationComplete event.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="initialize", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup before the instances get created.
     *  Beads can call preventDefault and defer initialization.
     *  This event will be dispatched on every frame until no
     *  listeners call preventDefault(), then the initialize()
     *  method will be called.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="preinitialize", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="viewChanged", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="applicationComplete", type="org.apache.flex.events.Event")]

    /**
     *  The Application class is the main class and entry point for a FlexJS
     *  application.  This Application class is different than the
     *  Flex SDK's mx:Application or spark:Application in that it does not contain
     *  user interface elements.  Those UI elements go in the views.  This
     *  Application class expects there to be a main model, a controller, and
     *  an initial view.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    public class Application extends Sprite implements IStrand, IFlexInfo, IParent, IEventDispatcher
    {
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function Application()
        {
            super();
			if (stage)
			{
				stage.align = StageAlign.TOP_LEFT;
				stage.scaleMode = StageScaleMode.NO_SCALE;
                // should be opt-in
				//stage.quality = StageQuality.HIGH_16X16_LINEAR;
			}

            loaderInfo.addEventListener(flash.events.Event.INIT, initHandler);
        }

        /**
         *  The document property is used to provide
         *  a property lookup context for non-display objects.
         *  For Application, it points to itself.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var document:Object = this;

        private function initHandler(event:flash.events.Event):void
        {
			if (model is IBead) addBead(model as IBead);
			if (controller is IBead) addBead(controller as IBead);

            MouseEventConverter.setupAllConverters(stage);

            for each (var bead:IBead in beads)
                addBead(bead);

            dispatchEvent(new org.apache.flex.events.Event("beadsAdded"));

            if (dispatchEvent(new org.apache.flex.events.Event("preinitialize", false, true)))
                initialize();
            else
                addEventListener(flash.events.Event.ENTER_FRAME, enterFrameHandler);

        }

        private function enterFrameHandler(event:flash.events.Event):void
        {
            if (dispatchEvent(new org.apache.flex.events.Event("preinitialize", false, true)))
            {
                removeEventListener(flash.events.Event.ENTER_FRAME, enterFrameHandler);
                initialize();
            }
        }

        /**
         *  This method gets called when all preinitialize handlers
         *  no longer call preventDefault();
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        protected function initialize():void
        {

            MXMLDataInterpreter.generateMXMLInstances(this, null, MXMLDescriptor);

            dispatchEvent(new org.apache.flex.events.Event("initialize"));

            if (initialView)
            {
                initialView.applicationModel =  model;
                if (!isNaN(initialView.percentWidth) && !isNaN(initialView.percentHeight))
                    initialView.setWidthAndHeight(stage.stageWidth, stage.stageHeight);
                else if (!isNaN(initialView.percentWidth))
                    initialView.setWidth(stage.stageWidth);
                else if (!isNaN(initialView.percentHeight))
                    initialView.setHeight(stage.stageHeight);
        	    this.addElement(initialView);
                var bgColor:Object = ValuesManager.valuesImpl.getValue(this, "background-color");
                if (bgColor != null)
                {
                    var backgroundColor:uint = ValuesManager.valuesImpl.convertColor(bgColor);
                    graphics.beginFill(backgroundColor);
                    graphics.drawRect(0, 0, initialView.width, initialView.height);
                    graphics.endFill();
                }
                dispatchEvent(new org.apache.flex.events.Event("viewChanged"));
            }
            dispatchEvent(new org.apache.flex.events.Event("applicationComplete"));
        }

        /**
         *  The org.apache.flex.core.IValuesImpl that will
         *  determine the default values and other values
         *  for the application.  The most common choice
         *  is org.apache.flex.core.SimpleCSSValuesImpl.
         *
         *  @see org.apache.flex.core.SimpleCSSValuesImpl
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function set valuesImpl(value:IValuesImpl):void
        {
            ValuesManager.valuesImpl = value;
            ValuesManager.valuesImpl.init(this);
        }

        /**
         *  The initial view.
         *
         *  @see org.apache.flex.core.ViewBase
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var initialView:ViewBase;

        /**
         *  The data model (for the initial view).
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var model:Object;

        /**
         *  The controller.  The controller typically watches
         *  the UI for events and updates the model accordingly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var controller:Object;

        /**
         *  An array of data that describes the MXML attributes
         *  and tags in an MXML document.  This data is usually
         *  decoded by an MXMLDataInterpreter
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get MXMLDescriptor():Array
        {
            return null;
        }

        /**
         *  An method called by the compiler's generated
         *  code to kick off the setting of MXML attribute
         *  values and instantiation of child tags.
         *
         *  The call has to be made in the generated code
         *  in order to ensure that the constructors have
         *  completed first.
         *
         *  @param data The encoded data representing the
         *  MXML attributes.
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
    	public function generateMXMLAttributes(data:Array):void
        {
			MXMLDataInterpreter.generateMXMLProperties(this, data);
        }

        /**
         *  The array property that is used to add additional
         *  beads to an MXML tag.  From ActionScript, just
         *  call addBead directly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var beads:Array;

        private var _beads:Vector.<IBead>;

        /**
         *  @copy org.apache.flex.core.IStrand#addBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addBead(bead:IBead):void
        {
            if (!_beads)
                _beads = new Vector.<IBead>;
            _beads.push(bead);
            bead.strand = this;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#getBeadByType()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getBeadByType(classOrInterface:Class):IBead
        {
            for each (var bead:IBead in _beads)
            {
                if (bead is classOrInterface)
                    return bead;
            }
            return null;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#removeBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeBead(value:IBead):IBead
        {
            var n:int = _beads.length;
            for (var i:int = 0; i < n; i++)
            {
                var bead:IBead = _beads[i];
                if (bead == value)
                {
                    _beads.splice(i, 1);
                    return bead;
                }
            }
            return null;
        }

        private var _info:Object;

        /**
         *  An Object containing information generated
         *  by the compiler that is useful at startup time.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function info():Object
        {
            if (!_info)
            {
                var mainClassName:String = getQualifiedClassName(this);
                var initClassName:String = "_" + mainClassName + "_FlexInit";
                var c:Class = ApplicationDomain.currentDomain.getDefinition(initClassName) as Class;
                _info = c.info();
            }
            return _info;
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElement(c:Object, dispatchEvent:Boolean = true):void
        {
            if (c is IUIBase)
            {
                addChild(IUIBase(c).element as DisplayObject);
                IUIBase(c).addedToParent();
            }
            else
                addChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElementAt()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElementAt(c:Object, index:int, dispatchEvent:Boolean = true):void
        {
            if (c is IUIBase)
            {
                addChildAt(IUIBase(c).element as DisplayObject, index);
                IUIBase(c).addedToParent();
            }
            else
                addChildAt(c as DisplayObject, index);
        }

        /**
         *  @copy org.apache.flex.core.IParent#getElementAt()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getElementAt(index:int):Object
        {
            return getChildAt(index);
        }

        /**
         *  @copy org.apache.flex.core.IParent#getElementIndex()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getElementIndex(c:Object):int
        {
            if (c is IUIBase)
                return getChildIndex(IUIBase(c).element as DisplayObject);

            return getChildIndex(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#removeElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeElement(c:Object, dispatchEvent:Boolean = true):void
        {
            if (c is IUIBase)
            {
                removeChild(IUIBase(c).element as DisplayObject);
            }
            else
                removeChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#numElements
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get numElements():int
        {
            return numChildren;
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.core
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.system.ApplicationDomain;
    import flash.utils.getQualifiedClassName;

    import org.apache.flex.events.Event;
    import org.apache.flex.events.IEventDispatcher;
    import org.apache.flex.events.MouseEvent;
    import org.apache.flex.events.utils.MouseEventConverter;
    import org.apache.flex.utils.MXMLDataInterpreter;

    //--------------------------------------
    //  Events
    //--------------------------------------

    /**
     *  Dispatched at startup. Attributes and sub-instances of
     *  the MXML document have been created and assigned.
     *  The component lifecycle is different
     *  than the Flex SDK.  There is no creationComplete event.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="initialize", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup before the instances get created.
     *  Beads can call preventDefault and defer initialization.
     *  This event will be dispatched on every frame until no
     *  listeners call preventDefault(), then the initialize()
     *  method will be called.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="preinitialize", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="viewChanged", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="applicationComplete", type="org.apache.flex.events.Event")]

    /**
     *  The Application class is the main class and entry point for a FlexJS
     *  application.  This Application class is different than the
     *  Flex SDK's mx:Application or spark:Application in that it does not contain
     *  user interface elements.  Those UI elements go in the views.  This
     *  Application class expects there to be a main model, a controller, and
     *  an initial view.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    public class Application extends Sprite implements IStrand, IFlexInfo, IParent, IEventDispatcher
    {
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function Application()
        {
            super();
			if (stage)
			{
				stage.align = StageAlign.TOP_LEFT;
				stage.scaleMode = StageScaleMode.NO_SCALE;
                // should be opt-in
				//stage.quality = StageQuality.HIGH_16X16_LINEAR;
			}

            loaderInfo.addEventListener(flash.events.Event.INIT, initHandler);
        }

        /**
         *  The document property is used to provide
         *  a property lookup context for non-display objects.
         *  For Application, it points to itself.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var document:Object = this;

        private function initHandler(event:flash.events.Event):void
        {
			if (model is IBead) addBead(model as IBead);
			if (controller is IBead) addBead(controller as IBead);

            MouseEventConverter.setupAllConverters(stage);

            for each (var bead:IBead in beads)
                addBead(bead);

            dispatchEvent(new org.apache.flex.events.Event("beadsAdded"));

            if (dispatchEvent(new org.apache.flex.events.Event("preinitialize", false, true)))
                initialize();
            else
                addEventListener(flash.events.Event.ENTER_FRAME, enterFrameHandler);

        }

        private function enterFrameHandler(event:flash.events.Event):void
        {
            if (dispatchEvent(new org.apache.flex.events.Event("preinitialize", false, true)))
            {
                removeEventListener(flash.events.Event.ENTER_FRAME, enterFrameHandler);
                initialize();
            }
        }

        /**
         *  This method gets called when all preinitialize handlers
         *  no longer call preventDefault();
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        protected function initialize():void
        {

            MXMLDataInterpreter.generateMXMLInstances(this, null, MXMLDescriptor);

            dispatchEvent(new org.apache.flex.events.Event("initialize"));

            if (initialView)
            {
                initialView.applicationModel =  model;
        	    this.addElement(initialView);
                if (!isNaN(initialView.percentWidth) && !isNaN(initialView.percentHeight))
                    initialView.setWidthAndHeight(stage.stageWidth, stage.stageHeight, true);
                else if (!isNaN(initialView.percentWidth))
                    initialView.setWidth(stage.stageWidth);
                else if (!isNaN(initialView.percentHeight))
                    initialView.setHeight(stage.stageHeight);
                var bgColor:Object = ValuesManager.valuesImpl.getValue(this, "background-color");
                if (bgColor != null)
                {
                    var backgroundColor:uint = ValuesManager.valuesImpl.convertColor(bgColor);
                    graphics.beginFill(backgroundColor);
                    graphics.drawRect(0, 0, initialView.width, initialView.height);
                    graphics.endFill();
                }
                dispatchEvent(new org.apache.flex.events.Event("viewChanged"));
            }
            dispatchEvent(new org.apache.flex.events.Event("applicationComplete"));
        }

        /**
         *  The org.apache.flex.core.IValuesImpl that will
         *  determine the default values and other values
         *  for the application.  The most common choice
         *  is org.apache.flex.core.SimpleCSSValuesImpl.
         *
         *  @see org.apache.flex.core.SimpleCSSValuesImpl
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function set valuesImpl(value:IValuesImpl):void
        {
            ValuesManager.valuesImpl = value;
            ValuesManager.valuesImpl.init(this);
        }

        /**
         *  The initial view.
         *
         *  @see org.apache.flex.core.ViewBase
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var initialView:ViewBase;

        /**
         *  The data model (for the initial view).
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var model:Object;

        /**
         *  The controller.  The controller typically watches
         *  the UI for events and updates the model accordingly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var controller:Object;

        /**
         *  An array of data that describes the MXML attributes
         *  and tags in an MXML document.  This data is usually
         *  decoded by an MXMLDataInterpreter
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get MXMLDescriptor():Array
        {
            return null;
        }

        /**
         *  An method called by the compiler's generated
         *  code to kick off the setting of MXML attribute
         *  values and instantiation of child tags.
         *
         *  The call has to be made in the generated code
         *  in order to ensure that the constructors have
         *  completed first.
         *
         *  @param data The encoded data representing the
         *  MXML attributes.
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
    	public function generateMXMLAttributes(data:Array):void
        {
			MXMLDataInterpreter.generateMXMLProperties(this, data);
        }

        /**
         *  The array property that is used to add additional
         *  beads to an MXML tag.  From ActionScript, just
         *  call addBead directly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var beads:Array;

        private var _beads:Vector.<IBead>;

        /**
         *  @copy org.apache.flex.core.IStrand#addBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addBead(bead:IBead):void
        {
            if (!_beads)
                _beads = new Vector.<IBead>;
            _beads.push(bead);
            bead.strand = this;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#getBeadByType()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getBeadByType(classOrInterface:Class):IBead
        {
            for each (var bead:IBead in _beads)
            {
                if (bead is classOrInterface)
                    return bead;
            }
            return null;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#removeBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeBead(value:IBead):IBead
        {
            var n:int = _beads.length;
            for (var i:int = 0; i < n; i++)
            {
                var bead:IBead = _beads[i];
                if (bead == value)
                {
                    _beads.splice(i, 1);
                    return bead;
                }
            }
            return null;
        }

        private var _info:Object;

        /**
         *  An Object containing information generated
         *  by the compiler that is useful at startup time.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function info():Object
        {
            if (!_info)
            {
                var mainClassName:String = getQualifiedClassName(this);
                var initClassName:String = "_" + mainClassName + "_FlexInit";
                var c:Class = ApplicationDomain.currentDomain.getDefinition(initClassName) as Class;
                _info = c.info();
            }
            return _info;
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElement(c:Object, dispatchEvent:Boolean = true):void
        {
            if (c is IUIBase)
            {
                addChild(IUIBase(c).element as DisplayObject);
                IUIBase(c).addedToParent();
            }
            else
                addChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElementAt()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElementAt(c:Object, index:int, dispatchEvent:Boolean = true):void
        {
            if (c is IUIBase)
            {
                addChildAt(IUIBase(c).element as DisplayObject, index);
                IUIBase(c).addedToParent();
            }
            else
                addChildAt(c as DisplayObject, index);
        }

        /**
         *  @copy org.apache.flex.core.IParent#getElementAt()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getElementAt(index:int):Object
        {
            return getChildAt(index);
        }

        /**
         *  @copy org.apache.flex.core.IParent#getElementIndex()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getElementIndex(c:Object):int
        {
            if (c is IUIBase)
                return getChildIndex(IUIBase(c).element as DisplayObject);

            return getChildIndex(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#removeElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeElement(c:Object, dispatchEvent:Boolean = true):void
        {
            if (c is IUIBase)
            {
                removeChild(IUIBase(c).element as DisplayObject);
            }
            else
                removeChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#numElements
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get numElements():int
        {
            return numChildren;
        }
    }
}

fix percent size handling

fix percent size handling


//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.util {

import flash.events.Event;

/**
 * A handy event for simply dispatching a value associated with the event type.
 */
public class ValueEvent extends Event
{
    /**
     * Accessor: get the value.
     */
    public function get value () :Object
    {
        return _value;
    }

    /**
     * Construct the value event.
     */
    public function ValueEvent (type :String, value :Object)
    {
        super(type);
        _value = value;
    }

    override public function clone () :Event
    {
        return new ValueEvent(type, _value);
    }

    /** The value. */
    protected var _value :Object;
}
}

//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.util {

import flash.events.Event;

/**
 * A handy event for simply dispatching a value associated with the event type.
 */
public class ValueEvent extends Event
{
    /**
     * Accessor: get the value.
     */
    public function get value () :Object
    {
        return _value;
    }

    /**
     * Construct the value event.
     */
    public function ValueEvent (
        type :String, value :Object, bubbles :Boolean = false, cancelable :Boolean = false)
    {
        super(type, bubbles, cancelable);
        _value = value;
    }

    override public function clone () :Event
    {
        return new ValueEvent(type, _value, bubbles, cancelable);
    }

    /** The value. */
    protected var _value :Object;
}
}

Allow ValueEvents to be cancelable.

Allow ValueEvents to be cancelable.

git-svn-id: a1a4b28b82a3276cc491891159dd9963a0a72fae@4898 542714f4-19e9-0310-aa3c-eee0fc999fb1


#if __SWF_VERSION__ == 5
// create a _global object, since it doesn't have one, these are ver 6 values
_global = new_empty_object ();
_global.ASSetNative = ASSetNative;
_global.ASSetNativeAccessor = ASSetNativeAccessor;
_global.ASSetPropFlags = ASSetPropFlags;
_global.ASconstructor = ASconstructor;
_global.ASnative = ASnative;
_global.Accessibility = Accessibility;
_global.Array = Array;
_global.AsBroadcaster = AsBroadcaster;
_global.AsSetupError = AsSetupError;
_global.Boolean = Boolean;
_global.Button = Button;
_global.Camera = Camera;
_global.Color = Color;
_global.ContextMenu = ContextMenu;
_global.ContextMenuItem = ContextMenuItem;
_global.Date = Date;
_global.Error = Error;
_global.Function = Function;
_global.Infinity = Infinity;
_global.Key = Key;
_global.LoadVars = LoadVars;
_global.LocalConnection = LocalConnection;
_global.Math = Math;
_global.Microphone = Microphone;
_global.Mouse = Mouse;
_global.MovieClip = MovieClip;
_global.MovieClipLoader = MovieClipLoader;
_global.NaN = NaN;
_global.NetConnection = NetConnection;
_global.NetStream = NetStream;
_global.Number = Number;
_global.Object = Object;
_global.PrintJob = PrintJob;
_global.RemoteLSOUsage = RemoteLSOUsage;
_global.Selection = Selection;
_global.SharedObject = SharedObject;
_global.Sound = Sound;
_global.Stage = Stage;
_global.String = String;
_global.System = System;
_global.TextField = TextField;
_global.TextFormat = TextFormat;
_global.TextSnapshot = TextSnapshot;
_global.Video = Video;
_global.XML = XML;
_global.XMLNode = XMLNode;
_global.XMLSocket = XMLSocket;
_global.clearInterval = clearInterval;
_global.clearTimeout = clearTimeout;
_global.enableDebugConsole = enableDebugConsole;
_global.escape = escape;
_global.flash = flash;
_global.isFinite = isFinite;
_global.isNaN = isNaN;
_global.o = o;
_global.parseFloat = parseFloat;
_global.parseInt = parseInt;
_global.setInterval = setInterval;
_global.setTimeout = setTimeout;
_global.showRedrawRegions = showRedrawRegions;
_global.textRenderer = textRenderer;
_global.trace = trace;
_global.unescape = unescape;
_global.updateAfterEvent = updateAfterEvent;
#endif

function new_empty_object () {
  var hash = new Object ();
  ASSetPropFlags (hash, null, 0, 7);
  for (var prop in hash) {
    hash[prop] = "to-be-deleted";
    delete hash[prop];
  }
  return hash;
}

#if __SWF_VERSION__ >= 6
function hasOwnProperty (o, prop)
{
  if (o.hasOwnProperty != undefined)
    return o.hasOwnProperty (prop);

  o.hasOwnProperty = _global.Object.prototype.hasOwnProperty;
  var result = o.hasOwnProperty (prop);
  delete o.hasOwnProperty;
  return result;
}
#else
// this gets the same result as the above, with following limitations:
// - if there is a child __proto__[prop] with value that can't be changed, no
//   test can be done and false is returned
// - native properties that have value undefined by default get overwritten by
//   __proto__[prop]'s value (atleast in version 6 and 7) so their existance
//   won't be detected by this function
function hasOwnProperty (o, prop)
{
  if (o.__proto__ == undefined)
  {
    o.__proto__ = new_empty_object ();

    o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";
    if (o[prop] != o.__proto__[prop]) {
      result = true;
    } else {
      result = false;
    }

    o.__proto__ = "to-be-deleted";
    delete o.__proto__;
    if (o.__proto__ != undefined) {
      trace ("ERROR: Couldn't delete temporary __proto__");
      o.__proto__ = undefined;
    }

    return result;
  }

  if (hasOwnProperty (o.__proto__, prop))
  {
    var constant = false;
    var old = o.__proto__[prop];

    o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";
    if (o.__proto__[prop] != "safdlojasfljsaiofhiwjhefa") {
      constant = true;
      ASSetPropFlags (o.__proto__, prop, 0, 4);
      o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";
      if (o.__proto__[prop] != "safdlojasfljsaiofhiwjhefa") {
	if (o[prop] != o.__proto__[prop]) {
	  return true;
	} else {
	  trace ("ERROR: can't test property '" + prop +
	      "', __proto__ has superconstant version");
	  return false;
	}
      }
    }

    if (o[prop] != o.__proto__[prop]) {
      result = true;
    } else {
      result = false;
    }

    o.__proto__[prop] = old;
    if (o.__proto__[prop] != old)
      trace ("Error: Couldn't set __proto__[\"" + prop +
	  "\"] back to old value");
    if (constant)
      ASSetPropFlags (o.__proto__, prop, 4);

    return result;
  }
  else
  {
    o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";

    if (o[prop] != o.__proto__[prop]) {
      result = true;
    } else {
      result = false;
    }

    ASSetPropFlags (o, prop, 0, 4);
    o.__proto__[prop] = "to-be-deleted";
    delete o.__proto__[prop];
    if (o.__proto__[prop] != undefined)
      trace ("ERROR: Couldn't delete temporary __proto__[\"" + prop + "\"]");

    return result;
  }
}
#endif

function new_info () {
  return new_empty_object ();
}

function set_info (info, prop, id, value) {
  info[prop + "_-_" + id] = value;
}

function get_info (info, prop, id) {
  return info[prop + "_-_" + id];
}

function is_blaclisted (o, prop)
{
  if (prop == "mySecretId" || prop == "globalSecretId")
    return true;

  if (o == _global.Camera && prop == "names")
    return true;

  if (o == _global.Microphone && prop == "names")
    return true;

#if __SWF_VERSION__ < 6
  if (prop == "__proto__" && o[prop] == undefined)
    return true;
#endif

  return false;
}

function trace_properties_recurse (o, prefix, identifier, level)
{
  // to collect info about different properties
  var info = new_info ();

  // calculate indentation
  var indentation = "";
  for (var j = 0; j < level; j++) {
    indentation = indentation + "  ";
  }

  // mark the ones that are not hidden
  for (var prop in o)
  {
    // only get the ones that are not only in the __proto__
    if (is_blaclisted (o, prop) == false) {
      if (hasOwnProperty (o, prop) == true)
	set_info (info, prop, "hidden", false);
    }
  }

  // unhide everything
  ASSetPropFlags (o, null, 0, 1);

  var all = new Array ();
  var hidden = new Array ();
  for (var prop in o)
  {
    // only get the ones that are not only in the __proto__
    if (is_blaclisted (o, prop) == false) {
      if (hasOwnProperty (o, prop) == true) {
	all.push (prop);
	if (get_info (info, prop, "hidden") != false) {
	  set_info (info, prop, "hidden", true);
	  hidden.push (prop);
	}
      }
    }
  }
  all.sort ();

  // hide the ones that were already hidden
  ASSetPropFlags (o, hidden, 1, 0);

  if (all.length == 0) {
    trace (indentation + "no children");
    return nextSecretId;
  }

  for (var i = 0; i < all.length; i++)
  {
    var prop = all[i];

    // try changing value
    var old = o[prop];
    var val = "hello " + o[prop];
    o[prop] = val;
    if (o[prop] != val)
    {
      set_info (info, prop, "constant", true);

      // try changing value after removing constant propflag
      ASSetPropFlags (o, prop, 0, 4);
      o[prop] = val;
      if (o[prop] != val) {
	set_info (info, prop, "superconstant", true);
      } else {
	set_info (info, prop, "superconstant", false);
	o[prop] = old;
      }
      ASSetPropFlags (o, prop, 4);
    }
    else
    {
      set_info (info, prop, "constant", false);
      set_info (info, prop, "superconstant", false);
      o[prop] = old;
    }
  }

  for (var i = 0; i < all.length; i++)
  {
    var prop = all[i];

    // remove constant flag
    ASSetPropFlags (o, prop, 0, 4);

    // try deleting
    var old = o[prop];
    delete o[prop];
    if (hasOwnProperty (o, prop))
    {
      set_info (info, prop, "permanent", true);
    }
    else
    {
      set_info (info, prop, "permanent", false);
      o[prop] = old;
    }

    // put constant flag back, if it was set
    if (get_info (info, prop, "constant") == true)
      ASSetPropFlags (o, prop, 4);
  }

  for (var i = 0; i < all.length; i++) {
    var prop = all[i];

    // format propflags
    var flags = "";
    if (get_info (info, prop, "hidden") == true) {
      flags += "h";
    }
    if (get_info (info, prop, "superpermanent") == true) {
      flags += "P";
    } else if (get_info (info, prop, "permanent") == true) {
      flags += "p";
    }
    if (get_info (info, prop, "superconstant") == true) {
      flags += "C";
    } else if (get_info (info, prop, "constant") == true) {
      flags += "c";
    }
    if (flags != "")
      flags = " (" + flags + ")";

    var value = "";
    // add value depending on the type
    if (typeof (o[prop]) == "number" || typeof (o[prop]) == "boolean") {
      value += " : " + o[prop];
    } else if (typeof (o[prop]) == "string") {
      value += " : \"" + o[prop] + "\"";
    }

    // recurse if it's object or function and this is the place it has been
    // named after
    if (typeof (o[prop]) == "object" || typeof (o[prop]) == "function")
    {
      if (prefix + (prefix != "" ? "." : "") + identifier + "." + prop ==
	  o[prop]["mySecretId"])
      {
	trace (indentation + prop + flags + " = " + typeof (o[prop]));
	trace_properties_recurse (o[prop], prefix + (prefix != "" ? "." : "") +
	    identifier, prop, level + 1);
      }
      else
      {
	trace (indentation + prop + flags + " = " + o[prop]["mySecretId"]);
      }
    }
    else
    {
      trace (indentation + prop + flags + " = " + typeof (o[prop]) + value);
    }
  }
}

function generate_names (o, prefix, identifier)
{
  // mark the ones that are not hidden
  var nothidden = new Array ();
  for (var prop in o) {
    nothidden.push (prop);
  }

  // unhide everything
  ASSetPropFlags (o, null, 0, 1);

  var all = new Array ();
  for (var prop in o)
  {
    if (is_blaclisted (o, prop) == false) {
      // only get the ones that are not only in the __proto__
      if (hasOwnProperty (o, prop) == true) {
	all.push (prop);
      }
    }
  }
  all.sort ();

  // hide the ones that were already hidden
  ASSetPropFlags (o, null, 1, 0);
  ASSetPropFlags (o, nothidden, 0, 1);

  for (var i = 0; i < all.length; i++) {
    var prop = all[i];

    if (typeof (o[prop]) == "object" || typeof (o[prop]) == "function") {
      if (hasOwnProperty (o[prop], "mySecretId")) {
	all[i] = null; // don't recurse to it again
      } else {
	o[prop]["mySecretId"] = prefix + (prefix != "" ? "." : "") +
	  identifier + "." + prop;
      }
    }
  }

  for (var i = 0; i < all.length; i++) {
    var prop = all[i];

    if (prop != null) {
      if (typeof (o[prop]) == "object" || typeof (o[prop]) == "function")
	generate_names (o[prop], prefix + (prefix != "" ? "." : "") +
	    identifier, prop);
    }
  }
}

function trace_properties (o, prefix, identifier)
{
  _global["mySecretId"] = "_global";
  _global.Object["mySecretId"] = "_global.Object";
  generate_names (_global.Object, "_global", "Object");
  generate_names (_global, "", "_global");

  if (typeof (o) == "object" || typeof (o) == "function")
  {
    if (o["mySecretId"] == undefined) {
      o["mySecretId"] = prefix + (prefix != "" ? "." : "") + identifier;
      generate_names (o, prefix, identifier);
    }

    if (prefix + (prefix != "" ? "." : "") + identifier == o["mySecretId"])
    {
      trace (prefix + (prefix != "" ? "." : "") + identifier + " = " +
	  typeof (o));
    }
    else
    {
      trace (prefix + (prefix != "" ? "." : "") + identifier + " = " +
	  o["mySecretId"]);
    }
    trace_properties_recurse (o, prefix, identifier, 1);
  }
  else
  {
    var value = "";
    if (typeof (o) == "number" || typeof (o) == "boolean") {
      value += " : " + o;
    } else if (typeof (o) == "string") {
      value += " : \"" + o + "\"";
    }
    trace (prefix + (prefix != "" ? "." : "") + identifier + " = " +
	typeof (o) + value);
  }
}

#if __SWF_VERSION__ == 5
// create a _global object, since it doesn't have one, these are ver 6 values
_global = new_empty_object ();
_global.ASSetNative = ASSetNative;
_global.ASSetNativeAccessor = ASSetNativeAccessor;
_global.ASSetPropFlags = ASSetPropFlags;
_global.ASconstructor = ASconstructor;
_global.ASnative = ASnative;
_global.Accessibility = Accessibility;
_global.Array = Array;
_global.AsBroadcaster = AsBroadcaster;
_global.AsSetupError = AsSetupError;
_global.Boolean = Boolean;
_global.Button = Button;
_global.Camera = Camera;
_global.Color = Color;
_global.ContextMenu = ContextMenu;
_global.ContextMenuItem = ContextMenuItem;
_global.Date = Date;
_global.Error = Error;
_global.Function = Function;
_global.Infinity = Infinity;
_global.Key = Key;
_global.LoadVars = LoadVars;
_global.LocalConnection = LocalConnection;
_global.Math = Math;
_global.Microphone = Microphone;
_global.Mouse = Mouse;
_global.MovieClip = MovieClip;
_global.MovieClipLoader = MovieClipLoader;
_global.NaN = NaN;
_global.NetConnection = NetConnection;
_global.NetStream = NetStream;
_global.Number = Number;
_global.Object = Object;
_global.PrintJob = PrintJob;
_global.RemoteLSOUsage = RemoteLSOUsage;
_global.Selection = Selection;
_global.SharedObject = SharedObject;
_global.Sound = Sound;
_global.Stage = Stage;
_global.String = String;
_global.System = System;
_global.TextField = TextField;
_global.TextFormat = TextFormat;
_global.TextSnapshot = TextSnapshot;
_global.Video = Video;
_global.XML = XML;
_global.XMLNode = XMLNode;
_global.XMLSocket = XMLSocket;
_global.clearInterval = clearInterval;
_global.clearTimeout = clearTimeout;
_global.enableDebugConsole = enableDebugConsole;
_global.escape = escape;
_global.flash = flash;
_global.isFinite = isFinite;
_global.isNaN = isNaN;
_global.o = o;
_global.parseFloat = parseFloat;
_global.parseInt = parseInt;
_global.setInterval = setInterval;
_global.setTimeout = setTimeout;
_global.showRedrawRegions = showRedrawRegions;
_global.textRenderer = textRenderer;
_global.trace = trace;
_global.unescape = unescape;
_global.updateAfterEvent = updateAfterEvent;
#endif

function new_empty_object () {
  var hash = new Object ();
  ASSetPropFlags (hash, null, 0, 7);
  for (var prop in hash) {
    hash[prop] = "to-be-deleted";
    delete hash[prop];
  }
  return hash;
}

#if __SWF_VERSION__ >= 6
function hasOwnProperty (o, prop)
{
  if (o.hasOwnProperty != undefined)
    return o.hasOwnProperty (prop);

  o.hasOwnProperty = _global.Object.prototype.hasOwnProperty;
  var result = o.hasOwnProperty (prop);
  delete o.hasOwnProperty;
  return result;
}
#else
// this gets the same result as the above, with following limitations:
// - if there is a child __proto__[prop] with value that can't be changed, no
//   test can be done and false is returned
// - native properties that have value undefined by default get overwritten by
//   __proto__[prop]'s value (atleast in version 6 and 7) so their existance
//   won't be detected by this function
function hasOwnProperty (o, prop)
{
  if (o.__proto__ == undefined)
  {
    o.__proto__ = new_empty_object ();

    o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";
    if (o[prop] != o.__proto__[prop]) {
      result = true;
    } else {
      result = false;
    }

    ASSetPropFlags (o, "__proto__", 0, 2);
    o.__proto__ = "to-be-deleted";
    delete o.__proto__;
    if (o.__proto__ != undefined) {
      trace ("ERROR: Couldn't delete temporary __proto__");
      o.__proto__ = undefined;
    }

    return result;
  }

  if (hasOwnProperty (o.__proto__, prop))
  {
    var constant = false;
    var old = o.__proto__[prop];

    o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";
    if (o.__proto__[prop] != "safdlojasfljsaiofhiwjhefa") {
      constant = true;
      ASSetPropFlags (o.__proto__, prop, 0, 4);
      o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";
      if (o.__proto__[prop] != "safdlojasfljsaiofhiwjhefa") {
	if (o[prop] != o.__proto__[prop]) {
	  return true;
	} else {
	  trace ("ERROR: can't test property '" + prop +
	      "', __proto__ has superconstant version");
	  return false;
	}
      }
    }

    if (o[prop] != o.__proto__[prop]) {
      result = true;
    } else {
      result = false;
    }

    o.__proto__[prop] = old;
    if (o.__proto__[prop] != old)
      trace ("Error: Couldn't set __proto__[\"" + prop +
	  "\"] back to old value");
    if (constant)
      ASSetPropFlags (o.__proto__, prop, 4);

    return result;
  }
  else
  {
    o.__proto__[prop] = "safdlojasfljsaiofhiwjhefa";

    if (o[prop] != o.__proto__[prop]) {
      result = true;
    } else {
      result = false;
    }

    ASSetPropFlags (o, prop, 0, 4);
    o.__proto__[prop] = "to-be-deleted";
    delete o.__proto__[prop];
    if (o.__proto__[prop] != undefined)
      trace ("ERROR: Couldn't delete temporary __proto__[\"" + prop + "\"]");

    return result;
  }
}
#endif

function new_info () {
  return new_empty_object ();
}

function set_info (info, prop, id, value) {
  info[prop + "_-_" + id] = value;
}

function get_info (info, prop, id) {
  return info[prop + "_-_" + id];
}

function is_blaclisted (o, prop)
{
  if (prop == "mySecretId" || prop == "globalSecretId")
    return true;

  if (o == _global.Camera && prop == "names")
    return true;

  if (o == _global.Microphone && prop == "names")
    return true;

#if __SWF_VERSION__ < 6
  if (prop == "__proto__" && o[prop] == undefined)
    return true;
#endif

  return false;
}

function trace_properties_recurse (o, prefix, identifier, level)
{
  // to collect info about different properties
  var info = new_info ();

  // calculate indentation
  var indentation = "";
  for (var j = 0; j < level; j++) {
    indentation = indentation + "  ";
  }

  // mark the ones that are not hidden
  for (var prop in o)
  {
    // only get the ones that are not only in the __proto__
    if (is_blaclisted (o, prop) == false) {
      if (hasOwnProperty (o, prop) == true)
	set_info (info, prop, "hidden", false);
    }
  }

  // unhide everything
  ASSetPropFlags (o, null, 0, 1);

  var all = new Array ();
  var hidden = new Array ();
  for (var prop in o)
  {
    // only get the ones that are not only in the __proto__
    if (is_blaclisted (o, prop) == false) {
      if (hasOwnProperty (o, prop) == true) {
	all.push (prop);
	if (get_info (info, prop, "hidden") != false) {
	  set_info (info, prop, "hidden", true);
	  hidden.push (prop);
	}
      }
    }
  }
  all.sort ();

  // hide the ones that were already hidden
  ASSetPropFlags (o, hidden, 1, 0);

  if (all.length == 0) {
    trace (indentation + "no children");
    return nextSecretId;
  }

  for (var i = 0; i < all.length; i++)
  {
    var prop = all[i];

    // try changing value
    var old = o[prop];
    var val = "hello " + o[prop];
    o[prop] = val;
    if (o[prop] != val)
    {
      set_info (info, prop, "constant", true);

      // try changing value after removing constant propflag
      ASSetPropFlags (o, prop, 0, 4);
      o[prop] = val;
      if (o[prop] != val) {
	set_info (info, prop, "superconstant", true);
      } else {
	set_info (info, prop, "superconstant", false);
	o[prop] = old;
      }
      ASSetPropFlags (o, prop, 4);
    }
    else
    {
      set_info (info, prop, "constant", false);
      set_info (info, prop, "superconstant", false);
      o[prop] = old;
    }
  }

  for (var i = 0; i < all.length; i++)
  {
    var prop = all[i];

    // remove constant flag
    ASSetPropFlags (o, prop, 0, 4);

    // try deleting
    var old = o[prop];
    delete o[prop];
    if (hasOwnProperty (o, prop))
    {
      set_info (info, prop, "permanent", true);
    }
    else
    {
      set_info (info, prop, "permanent", false);
      o[prop] = old;
    }

    // put constant flag back, if it was set
    if (get_info (info, prop, "constant") == true)
      ASSetPropFlags (o, prop, 4);
  }

  for (var i = 0; i < all.length; i++) {
    var prop = all[i];

    // format propflags
    var flags = "";
    if (get_info (info, prop, "hidden") == true) {
      flags += "h";
    }
    if (get_info (info, prop, "superpermanent") == true) {
      flags += "P";
    } else if (get_info (info, prop, "permanent") == true) {
      flags += "p";
    }
    if (get_info (info, prop, "superconstant") == true) {
      flags += "C";
    } else if (get_info (info, prop, "constant") == true) {
      flags += "c";
    }
    if (flags != "")
      flags = " (" + flags + ")";

    var value = "";
    // add value depending on the type
    if (typeof (o[prop]) == "number" || typeof (o[prop]) == "boolean") {
      value += " : " + o[prop];
    } else if (typeof (o[prop]) == "string") {
      value += " : \"" + o[prop] + "\"";
    }

    // recurse if it's object or function and this is the place it has been
    // named after
    if (typeof (o[prop]) == "object" || typeof (o[prop]) == "function")
    {
      if (prefix + (prefix != "" ? "." : "") + identifier + "." + prop ==
	  o[prop]["mySecretId"])
      {
	trace (indentation + prop + flags + " = " + typeof (o[prop]));
	trace_properties_recurse (o[prop], prefix + (prefix != "" ? "." : "") +
	    identifier, prop, level + 1);
      }
      else
      {
	trace (indentation + prop + flags + " = " + o[prop]["mySecretId"]);
      }
    }
    else
    {
      trace (indentation + prop + flags + " = " + typeof (o[prop]) + value);
    }
  }
}

function generate_names (o, prefix, identifier)
{
  // mark the ones that are not hidden
  var nothidden = new Array ();
  for (var prop in o) {
    nothidden.push (prop);
  }

  // unhide everything
  ASSetPropFlags (o, null, 0, 1);

  var all = new Array ();
  for (var prop in o)
  {
    if (is_blaclisted (o, prop) == false) {
      // only get the ones that are not only in the __proto__
      if (hasOwnProperty (o, prop) == true) {
	all.push (prop);
      }
    }
  }
  all.sort ();

  // hide the ones that were already hidden
  ASSetPropFlags (o, null, 1, 0);
  ASSetPropFlags (o, nothidden, 0, 1);

  for (var i = 0; i < all.length; i++) {
    var prop = all[i];

    if (typeof (o[prop]) == "object" || typeof (o[prop]) == "function") {
      if (hasOwnProperty (o[prop], "mySecretId")) {
	all[i] = null; // don't recurse to it again
      } else {
	o[prop]["mySecretId"] = prefix + (prefix != "" ? "." : "") +
	  identifier + "." + prop;
      }
    }
  }

  for (var i = 0; i < all.length; i++) {
    var prop = all[i];

    if (prop != null) {
      if (typeof (o[prop]) == "object" || typeof (o[prop]) == "function")
	generate_names (o[prop], prefix + (prefix != "" ? "." : "") +
	    identifier, prop);
    }
  }
}

function trace_properties (o, prefix, identifier)
{
  _global["mySecretId"] = "_global";
  _global.Object["mySecretId"] = "_global.Object";
  generate_names (_global.Object, "_global", "Object");
  generate_names (_global, "", "_global");

  if (typeof (o) == "object" || typeof (o) == "function")
  {
    if (o["mySecretId"] == undefined) {
      o["mySecretId"] = prefix + (prefix != "" ? "." : "") + identifier;
      generate_names (o, prefix, identifier);
    }

    if (prefix + (prefix != "" ? "." : "") + identifier == o["mySecretId"])
    {
      trace (prefix + (prefix != "" ? "." : "") + identifier + " = " +
	  typeof (o));
    }
    else
    {
      trace (prefix + (prefix != "" ? "." : "") + identifier + " = " +
	  o["mySecretId"]);
    }
    trace_properties_recurse (o, prefix, identifier, 1);
  }
  else
  {
    var value = "";
    if (typeof (o) == "number" || typeof (o) == "boolean") {
      value += " : " + o;
    } else if (typeof (o) == "string") {
      value += " : \"" + o + "\"";
    }
    trace (prefix + (prefix != "" ? "." : "") + identifier + " = " +
	typeof (o) + value);
  }
}

set propflags to non-permanent before attempting to delete the property


package dorkbots.dorkbots_ui
{
	import flash.text.TextField;

	public class TruncateTextField
	{
		public function TruncateTextField ()
		{

		}

		public static function truncateText( textField:TextField, addElipsis:Boolean = true, minimizeLines:uint = 0, ellipsis:String = "\u2026" ):uint
		{
			var tempTextField:TextField;

			var characterRemoveCnt:uint = 0;

			if ( ! textOverflowing( textField ) ) return characterRemoveCnt;

			tempTextField = copyTextField( textField );

			while( textOverflowing( tempTextField, minimizeLines, ellipsis ) )
			{
				characterRemoveCnt++;
				tempTextField.text = tempTextField.text.substr( 0, tempTextField.text.length - 1 );
			}

			// Remove any empty spaces and periods at the end
			while(tempTextField.text.charAt(tempTextField.text.length - 1) == " " || tempTextField.text.charAt(tempTextField.text.length - 1) == ".")
			{
				characterRemoveCnt++;
				tempTextField.text = tempTextField.text.slice(0, -1);
				// just incase, because while loops make me nervous
				if (tempTextField.text.length <= 0) break;
			}

			tempTextField.appendText( ellipsis );

			if (tempTextField.numLines > 1)
			{
				// check again, for some reason, adding the ellipsis can increase number of lines
				while( textOverflowing( tempTextField, minimizeLines, ellipsis ) )
				{
					characterRemoveCnt++;
					tempTextField.text = tempTextField.text.substr( 0, tempTextField.text.length - ellipsis.length - 1 );
				}
			}

			tempTextField.appendText( ellipsis );

			textField.text = tempTextField.text;

			return characterRemoveCnt;
		}

		private static function textOverflowing( textField:TextField, minimizeLines:uint = 0, suffix:String = null ):Boolean
		{
			var margin:Number = 4; //Flash adds this to all textfields;

			var tempTextField:TextField = copyTextField( textField );

			if ( suffix ) tempTextField.appendText( suffix );

			if (minimizeLines > 0 && tempTextField.numLines > minimizeLines)
			{
				return true;
			}

			if ( tempTextField.textWidth > tempTextField.width - margin || tempTextField.textHeight > tempTextField.height - margin ) return true;

			return false;
		}

		private static function copyTextField( original:TextField ):TextField
		{
			var copy:TextField = new TextField();

			copy.width = original.width;
			copy.height = original.height;
			copy.multiline = original.multiline;
			copy.wordWrap = original.wordWrap;
			copy.embedFonts = original.embedFonts;
			copy.antiAliasType = original.antiAliasType;
			copy.autoSize = original.autoSize;
			copy.defaultTextFormat = original.getTextFormat();
			copy.text = original.text;

			return copy;
		}

		/**
		 * Truncate html text.
		 * @param value The original text value
		 * @param limit The maximum number of characters to show
		 * @param ellipses  Boolean value to show elipses at the end of truncation.
		 * @param moreLink  Boolean value to show a "[more]" with a TextEvent (TextEvent.LINK) at the end of truncation.
		 * This method is based on Michael Ritchie's work at http://thanksmister.com/2009/07/12/flex-truncating-html-text/
		 * */
		public static function truncateHTMLText(value:String, limit:int, ellipses:Boolean = true, moreLink:Boolean = true):String
		{
			if (!ellipses) limit += 3;
			if (!moreLink) limit += 6;

			if(limit <= 0) return "";

			var original:String = value;

			value = value.replace("[\\t\\n\\x0B\\f\\r\\u00A0]+", "");

			var isTag:Boolean = false;
			var count:int = 0;
			var position:int = 0;
			var limitLength:int = value.length - 1;
			var closeTag:Boolean = false;

			for(var i:int = 0; i < value.length; i++)
			{
				var c:String = value.charAt(i);
				if(isTag)
				{
					if(c == '>')
					{
						isTag = false;
						if(closeTag || i == limitLength)
						{
							position = i;
							break;
						}
						continue;
					}
					else
					{
						continue;
					}
				}
				else
				{
					if(c == '<')
					{
						isTag = true;
					}
					else
					{
						count++;
						if(i == limitLength || (count == limit))
						{
							if(((i+1) < limitLength) && ((i+2) < limitLength))
							{
								if(value.charAt(i+1) == '<' && value.charAt(i+2) == '/')
								{
									closeTag = true;
									continue;
								}
							}
							position = i;
							break;
						}
					}
				}
			}

			var result:String = value.substring(0, position + 1);
			var last:String = result.charAt(result.length - 1);
			var length:int = result.length;

			var nextChar:String = (length >= value.length) ? ' ' : value.charAt(length);

			if(last != ' ' && last != '>' && nextChar != ' ' && nextChar != '<')
			{
				result = result.substring(0, result.lastIndexOf(' ') + 1);
			}
			var lastStartTag:int = result.lastIndexOf('<');

			if(lastStartTag != -1)
			{
				var ch:String = result.charAt(lastStartTag + 1);
				if(ch != '/')
				{
					result = result.substring(0, lastStartTag);
				}
			}

			if(original.length == result.length) return original;

			if(result.length == 0) return result;

			// Remove any empty spaces and periods at the end
			while(result.charAt(result.length - 1) == " " || result.charAt(result.length - 1) == ".")
			{
				result = result.slice(0, -1);
				// just incase, because while loops make me nervous
				if (result.length <= 0) break;
			}

			var pattern:RegExp = new RegExp("(.*?)(\\s*\.\.\.\\s*)([\</[a-z]*?\>\\s*$]+)", "i");

			if(result.search(pattern) == -1 && ellipses) result += "...";

			if (moreLink)
			{
				return (result +  " [more]");
			}
			else
			{
				return result;
			}
		}
	}
}

package dorkbots.dorkbots_ui
{
	import flash.text.TextField;

	public class TruncateTextField
	{
		public function TruncateTextField ()
		{

		}

		public static function truncateText( textField:TextField, addEllipsis:Boolean = true, minimizeLines:uint = 0, ellipsis:String = "\u2026" ):uint
		{
			var tempTextField:TextField;

			var characterRemoveCnt:uint = 0;

			if ( ! textOverflowing( textField ) ) return characterRemoveCnt;

			tempTextField = copyTextField( textField );

			while( textOverflowing( tempTextField, minimizeLines, ellipsis ) )
			{
				characterRemoveCnt++;
				tempTextField.text = tempTextField.text.substr( 0, tempTextField.text.length - 1 );
			}

			// Remove any empty spaces and periods at the end
			var continueEndTidying:Boolean = true;
			while(continueEndTidying)
			{
				continueEndTidying = false;

				if (tempTextField.text.charAt(tempTextField.text.length - 1) == " ") continueEndTidying = true;
				// remove any periods if we are adding ellipsis
				if (addEllipsis && tempTextField.text.charAt(tempTextField.text.length - 1) == ".") continueEndTidying = true;

				if (continueEndTidying)
				{
					characterRemoveCnt++;
					tempTextField.text = tempTextField.text.slice(0, -1);
				}

				// just incase, because while loops make me nervous
				if (tempTextField.text.length <= 0) break;
			}

			// add ellipsis
			if (ellipsis)
			{
				tempTextField.appendText( ellipsis );

				if (tempTextField.numLines > 1)
				{
					// check again, for some reason, adding the ellipsis can increase number of lines
					while( textOverflowing( tempTextField, minimizeLines, ellipsis ) )
					{
						characterRemoveCnt++;
						tempTextField.text = tempTextField.text.substr( 0, tempTextField.text.length - ellipsis.length - 1 );
					}
				}

				tempTextField.appendText( ellipsis );
			}

			textField.text = tempTextField.text;

			return characterRemoveCnt;
		}

		private static function textOverflowing( textField:TextField, minimizeLines:uint = 0, suffix:String = null ):Boolean
		{
			var margin:Number = 4; //Flash adds this to all textfields;

			var tempTextField:TextField = copyTextField( textField );

			if ( suffix ) tempTextField.appendText( suffix );

			if (minimizeLines > 0 && tempTextField.numLines > minimizeLines)
			{
				return true;
			}

			if ( tempTextField.textWidth > tempTextField.width - margin || tempTextField.textHeight > tempTextField.height - margin ) return true;

			return false;
		}

		private static function copyTextField( original:TextField ):TextField
		{
			var copy:TextField = new TextField();

			copy.width = original.width;
			copy.height = original.height;
			copy.multiline = original.multiline;
			copy.wordWrap = original.wordWrap;
			copy.embedFonts = original.embedFonts;
			copy.antiAliasType = original.antiAliasType;
			copy.autoSize = original.autoSize;
			copy.defaultTextFormat = original.getTextFormat();
			copy.text = original.text;

			return copy;
		}

		/**
		 * Truncate html text.
		 * @param value The original text value
		 * @param limit The maximum number of characters to show
		 * @param ellipses  Boolean value to show elipses at the end of truncation.
		 * @param moreLink  Boolean value to show a "[more]" with a TextEvent (TextEvent.LINK) at the end of truncation.
		 * This method is based on Michael Ritchie's work at http://thanksmister.com/2009/07/12/flex-truncating-html-text/
		 * */
		public static function truncateHTMLText(value:String, limit:int, addEllipsis:Boolean = true, addMoreLink:Boolean = true):String
		{
			if (!addEllipsis) limit += 3;
			if (!addMoreLink) limit += 6;

			if(limit <= 0) return "";

			var original:String = value;

			value = value.replace("[\\t\\n\\x0B\\f\\r\\u00A0]+", "");

			var isTag:Boolean = false;
			var count:int = 0;
			var position:int = 0;
			var limitLength:int = value.length - 1;
			var closeTag:Boolean = false;

			for(var i:int = 0; i < value.length; i++)
			{
				var c:String = value.charAt(i);
				if(isTag)
				{
					if(c == '>')
					{
						isTag = false;
						if(closeTag || i == limitLength)
						{
							position = i;
							break;
						}
						continue;
					}
					else
					{
						continue;
					}
				}
				else
				{
					if(c == '<')
					{
						isTag = true;
					}
					else
					{
						count++;
						if(i == limitLength || (count == limit))
						{
							if(((i+1) < limitLength) && ((i+2) < limitLength))
							{
								if(value.charAt(i+1) == '<' && value.charAt(i+2) == '/')
								{
									closeTag = true;
									continue;
								}
							}
							position = i;
							break;
						}
					}
				}
			}

			var result:String = value.substring(0, position + 1);
			var last:String = result.charAt(result.length - 1);
			var length:int = result.length;

			var nextChar:String = (length >= value.length) ? ' ' : value.charAt(length);

			if(last != ' ' && last != '>' && nextChar != ' ' && nextChar != '<')
			{
				result = result.substring(0, result.lastIndexOf(' ') + 1);
			}
			var lastStartTag:int = result.lastIndexOf('<');

			if(lastStartTag != -1)
			{
				var ch:String = result.charAt(lastStartTag + 1);
				if(ch != '/')
				{
					result = result.substring(0, lastStartTag);
				}
			}

			if(original.length == result.length) return original;

			if(result.length == 0) return result;

			// Remove any empty spaces and periods at the end
			while(result.charAt(result.length - 1) == " " || result.charAt(result.length - 1) == ".")
			{
				result = result.slice(0, -1);
				// just incase, because while loops make me nervous
				if (result.length <= 0) break;
			}

			// Remove any empty spaces and periods at the end
			var continueEndTidying:Boolean = true;
			while(continueEndTidying)
			{
				continueEndTidying = false;

				if (result.charAt(result.length - 1) == " ") continueEndTidying = true;
				// remove any periods if we are adding ellipsis
				if (addEllipsis && result.charAt(result.length - 1) == ".") continueEndTidying = true;

				if (continueEndTidying)
				{
					result = result.slice(0, -1);
				}

				// just incase, because while loops make me nervous
				if (result.length <= 0) break;
			}

			var pattern:RegExp = new RegExp("(.*?)(\\s*\.\.\.\\s*)([\</[a-z]*?\>\\s*$]+)", "i");

			if(result.search(pattern) == -1 && addEllipsis) result += "...";

			if (addMoreLink)
			{
				return (result +  " [more]");
			}
			else
			{
				return result;
			}
		}
	}
}

comment updates

comment updates


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 */

package com.google.analytics
{

    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.GIFRequest;
    import com.google.analytics.core.as3_api;
    import com.google.analytics.core.ga_internal;
    import com.google.analytics.core.js_bridge;
    import com.google.analytics.debug.Layout;
    import com.google.analytics.events.MessageEvent;
    import com.google.analytics.external.HTMLDOM;
    import com.google.analytics.utils.Environment;
    import com.google.analytics.v4.Bridge;
    import com.google.analytics.v4.GoogleAnalyticsAPI;
    import com.google.analytics.v4.Tracker;

    import flash.display.DisplayObject;

    /**
    * @fileoverview Google Analytic Tracker Code (GATC)'s main component.
    */

    public class GATracker
    {
        private var _display:DisplayObject;
        private var _localInfo:Environment;
        private var _buffer:Buffer;
        private var _gifRequest:GIFRequest;
        private var _dom:HTMLDOM;

        /**
        * note:
        * the GATracker need to be instancied and added to the Stage
        * or at least being placed in a display list.
        *
        * We mainly use it for internal test and it's basically a factory.
        *
        */
        public function GATracker( display:DisplayObject )
        {
            _display   = display;
            debug.layout = new Layout( _display );
            debug.active = true;

            /* note:
               for unit testing and to avoid 2 different branches AIR/Flash
               here we will detect if we are in the Flash Player or AIR
               and pass the infos to the LocalInfo

               By default we will define "Flash" for our local tests
            */
            _dom        = new HTMLDOM();
            _localInfo  = new Environment( "", "", "", _dom );
            _buffer     = new Buffer( false );
            _gifRequest = new GIFRequest( _buffer, _localInfo );
        }

        /**
        * version of our source code (not version of the GA API)
        *
        * note:
        * each components will have also their own version
        */
        public static var version:String = "0.5.0." + "$Rev$ ".split( " " )[1];

        private function _onInfo( event:MessageEvent ):void
        {
            debug.info( event.message );
        }

        private function _onWarning( event:MessageEvent ):void
        {
            debug.warning( event.message );
        }

        /**
        * Factory method for returning a tracker object.
        *
        * @param {String} account Urchin Account to record metrics in.
        * @return {GoogleAnalyticsAPI}
        */
        as3_api function getTracker( account:String ):GoogleAnalyticsAPI
        {
            debug.info( "GATracker v" + version +"\naccount: " + account );

            config.addEventListener( MessageEvent.INFO, _onInfo );
            config.addEventListener( MessageEvent.WARNING, _onWarning );

            /* note:
               To be able to obtain the URL of the main SWF containing the GA API
               we need to be able to access the stage property of a DisplayObject,
               here we open the internal namespace to be able to set that reference
               at instanciation-time.

               We keep the implementation internal to be able to change it if required later.
            */
            use namespace ga_internal;
            _localInfo.url = _display.stage.loaderInfo.url;
            return new Tracker( account, _localInfo, _buffer, _gifRequest, null );
        }

        /**
        * @private
        */
        js_bridge function getTracker( account:String ):GoogleAnalyticsAPI
        {
            return new Bridge( account );
        }

    }
}

/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 */

package com.google.analytics
{

    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.GIFRequest;
    import com.google.analytics.core.as3_api;
    import com.google.analytics.core.ga_internal;
    import com.google.analytics.core.js_bridge;
    import com.google.analytics.debug.Layout;
    import com.google.analytics.events.MessageEvent;
    import com.google.analytics.external.HTMLDOM;
    import com.google.analytics.utils.Environment;
    import com.google.analytics.utils.Version;
    import com.google.analytics.v4.Bridge;
    import com.google.analytics.v4.GoogleAnalyticsAPI;
    import com.google.analytics.v4.Tracker;

    import flash.display.DisplayObject;

    /**
    * @fileoverview Google Analytic Tracker Code (GATC)'s main component.
    */

    public class GATracker
    {
        private var _display:DisplayObject;
        private var _localInfo:Environment;
        private var _buffer:Buffer;
        private var _gifRequest:GIFRequest;
        private var _dom:HTMLDOM;

        /**
        * note:
        * the GATracker need to be instancied and added to the Stage
        * or at least being placed in a display list.
        *
        * We mainly use it for internal test and it's basically a factory.
        *
        */
        public function GATracker( display:DisplayObject, debugmode:Boolean = false )
        {
            _display   = display;
            if( debugmode )
            {
                debug.layout = new Layout( _display );
                debug.active = debugmode;
            }

            /* note:
               for unit testing and to avoid 2 different branches AIR/Flash
               here we will detect if we are in the Flash Player or AIR
               and pass the infos to the LocalInfo

               By default we will define "Flash" for our local tests
            */
            _dom        = new HTMLDOM();
            _localInfo  = new Environment( "", "", "", _dom );
            _buffer     = new Buffer( false );
            _gifRequest = new GIFRequest( _buffer, _localInfo );
        }

        /**
        * version of our source code (not version of the GA API)
        *
        * note:
        * each components will have also their own version
        */
        public static var version:Version = new Version();
        include "version.properties"
        version.revision = "$Rev$ ".split( " " )[1];

        private function _onInfo( event:MessageEvent ):void
        {
            debug.info( event.message );
        }

        private function _onWarning( event:MessageEvent ):void
        {
            debug.warning( event.message );
        }

        /**
        * Factory method for returning a tracker object.
        *
        * @param {String} account Urchin Account to record metrics in.
        * @return {GoogleAnalyticsAPI}
        */
        as3_api function getTracker( account:String ):GoogleAnalyticsAPI
        {
            debug.info( "GATracker v" + version +"\naccount: " + account );

            config.addEventListener( MessageEvent.INFO, _onInfo );
            config.addEventListener( MessageEvent.WARNING, _onWarning );

            /* note:
               To be able to obtain the URL of the main SWF containing the GA API
               we need to be able to access the stage property of a DisplayObject,
               here we open the internal namespace to be able to set that reference
               at instanciation-time.

               We keep the implementation internal to be able to change it if required later.
            */
            use namespace ga_internal;
            _localInfo.url = _display.stage.loaderInfo.url;
            return new Tracker( account, _localInfo, _buffer, _gifRequest, null );
        }

        /**
        * @private
        */
        js_bridge function getTracker( account:String ):GoogleAnalyticsAPI
        {
            return new Bridge( account );
        }

    }
}

test rev

test rev


package aerys.minko.type.clone
{
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.AnimationController;
	import aerys.minko.scene.controller.TransformController;
	import aerys.minko.scene.controller.camera.CameraController;
	import aerys.minko.scene.controller.light.DirectionalLightController;
	import aerys.minko.scene.controller.light.LightController;
	import aerys.minko.scene.controller.light.PointLightController;
	import aerys.minko.scene.controller.light.SpotLightController;
	import aerys.minko.scene.controller.mesh.MeshController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.scene.controller.mesh.skinning.SkinningController;

	import avmplus.getQualifiedClassName;

	import flash.net.getClassByAlias;

	public final class CloneOptions
	{
		private var _clonedControllerTypes		: Vector.<Class>;
		private var _ignoredControllerTypes		: Vector.<Class>;
		private var _reassignedControllerTypes	: Vector.<Class>;
		private var _defaultControllerAction	: uint;

		public function get defaultControllerAction() : uint
		{
			return _defaultControllerAction;
		}
		public function set defaultControllerAction(v : uint) : void
		{
			if (v != ControllerCloneAction.CLONE
				&& v != ControllerCloneAction.IGNORE
				&& v != ControllerCloneAction.REASSIGN)
				throw new Error('Unknown action type.');

			_defaultControllerAction = v;
		}

		public function CloneOptions()
		{
			initialize();
		}

		private function initialize() : void
		{
			_clonedControllerTypes = new <Class>[];
			_ignoredControllerTypes = new <Class>[];
			_reassignedControllerTypes = new <Class>[];
			_defaultControllerAction = ControllerCloneAction.REASSIGN;
		}

		public static function get defaultOptions() : CloneOptions
		{
			var cloneOptions : CloneOptions = new CloneOptions();

			cloneOptions._clonedControllerTypes.push(
				AnimationController,
				SkinningController
			);
			cloneOptions._ignoredControllerTypes.push(
				MeshController,
				MeshVisibilityController,
				CameraController,
				TransformController,
                LightController,
                DirectionalLightController,
                SpotLightController,
                PointLightController
			);
			cloneOptions._defaultControllerAction = ControllerCloneAction.REASSIGN;

			return cloneOptions;
		}

		public static function get cloneAllOptions() : CloneOptions
		{
			var cloneOptions : CloneOptions = new CloneOptions();

			cloneOptions._ignoredControllerTypes.push(
				MeshController,
				MeshVisibilityController,
				CameraController,
				TransformController,
                LightController,
                DirectionalLightController,
                SpotLightController,
                PointLightController
			);
			cloneOptions._defaultControllerAction = ControllerCloneAction.CLONE;

			return cloneOptions;
		}

		public function setActionForControllerClass(controllerClass	: Class,
													action			: uint) : CloneOptions
		{
			var index : int = 0;

			if ((index = _clonedControllerTypes.indexOf(controllerClass)) >= 0)
				_clonedControllerTypes.slice(index, 1);
			else if ((index = _ignoredControllerTypes.indexOf(controllerClass)) >= 0)
				_ignoredControllerTypes.slice(index, 1);
			else if ((index = _reassignedControllerTypes.indexOf(controllerClass)) >= 0)
				_reassignedControllerTypes.slice(index, 1);

			switch (action)
			{
				case ControllerCloneAction.CLONE:
					_clonedControllerTypes.push(controllerClass);
					break;

				case ControllerCloneAction.IGNORE:
					_ignoredControllerTypes.push(controllerClass);
					break;

				case ControllerCloneAction.REASSIGN:
					_reassignedControllerTypes.push(controllerClass);
					break;

				default:
					throw new Error('Unknown action type.');
			}

			return this;
		}

		public function getActionForController(controller : AbstractController) : uint
		{
			var numControllersToClone		: uint = _clonedControllerTypes.length;
			var numControllersToIgnore		: uint = _ignoredControllerTypes.length;
			var numControllersToReassign	: uint = _reassignedControllerTypes.length;
			var controllerId				: uint;

			for (controllerId = 0; controllerId < numControllersToClone; ++controllerId)
				if (controller is _clonedControllerTypes[controllerId])
					return ControllerCloneAction.CLONE;

			for (controllerId = 0; controllerId < numControllersToIgnore; ++controllerId)
				if (controller is _ignoredControllerTypes[controllerId])
					return ControllerCloneAction.IGNORE;

			for (controllerId = 0; controllerId < numControllersToReassign; ++controllerId)
				if (controller is _reassignedControllerTypes[controllerId])
					return ControllerCloneAction.REASSIGN;

			return _defaultControllerAction;
		}

	}
}

package aerys.minko.type.clone
{
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.AnimationController;
	import aerys.minko.scene.controller.TransformController;
	import aerys.minko.scene.controller.camera.CameraController;
	import aerys.minko.scene.controller.light.DirectionalLightController;
	import aerys.minko.scene.controller.light.LightController;
	import aerys.minko.scene.controller.light.PointLightController;
	import aerys.minko.scene.controller.light.SpotLightController;
	import aerys.minko.scene.controller.mesh.MeshController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.scene.controller.mesh.skinning.SkinningController;

	public final class CloneOptions
	{
		private var _clonedControllerTypes		: Vector.<Class>;
		private var _ignoredControllerTypes		: Vector.<Class>;
		private var _reassignedControllerTypes	: Vector.<Class>;
		private var _defaultControllerAction	: uint;

		public function get defaultControllerAction() : uint
		{
			return _defaultControllerAction;
		}
		public function set defaultControllerAction(v : uint) : void
		{
			if (v != ControllerCloneAction.CLONE
				&& v != ControllerCloneAction.IGNORE
				&& v != ControllerCloneAction.REASSIGN)
				throw new Error('Unknown action type.');

			_defaultControllerAction = v;
		}

		public function CloneOptions()
		{
			initialize();
		}

		private function initialize() : void
		{
			_clonedControllerTypes = new <Class>[];
			_ignoredControllerTypes = new <Class>[];
			_reassignedControllerTypes = new <Class>[];
			_defaultControllerAction = ControllerCloneAction.REASSIGN;
		}

		public static function get defaultOptions() : CloneOptions
		{
			var cloneOptions : CloneOptions = new CloneOptions();

			cloneOptions._clonedControllerTypes.push(
				AnimationController,
				SkinningController
			);
			cloneOptions._ignoredControllerTypes.push(
				MeshController,
				MeshVisibilityController,
				CameraController,
				TransformController,
                LightController,
                DirectionalLightController,
                SpotLightController,
                PointLightController
			);
			cloneOptions._defaultControllerAction = ControllerCloneAction.REASSIGN;

			return cloneOptions;
		}

		public static function get cloneAllOptions() : CloneOptions
		{
			var cloneOptions : CloneOptions = new CloneOptions();

			cloneOptions._ignoredControllerTypes.push(
				MeshController,
				MeshVisibilityController,
				CameraController,
				TransformController,
                LightController,
                DirectionalLightController,
                SpotLightController,
                PointLightController
			);
			cloneOptions._defaultControllerAction = ControllerCloneAction.CLONE;

			return cloneOptions;
		}

		public function setActionForControllerClass(controllerClass	: Class,
													action			: uint) : CloneOptions
		{
			var index : int = 0;

			if ((index = _clonedControllerTypes.indexOf(controllerClass)) >= 0)
				_clonedControllerTypes.slice(index, 1);
			else if ((index = _ignoredControllerTypes.indexOf(controllerClass)) >= 0)
				_ignoredControllerTypes.slice(index, 1);
			else if ((index = _reassignedControllerTypes.indexOf(controllerClass)) >= 0)
				_reassignedControllerTypes.slice(index, 1);

			switch (action)
			{
				case ControllerCloneAction.CLONE:
					_clonedControllerTypes.push(controllerClass);
					break;

				case ControllerCloneAction.IGNORE:
					_ignoredControllerTypes.push(controllerClass);
					break;

				case ControllerCloneAction.REASSIGN:
					_reassignedControllerTypes.push(controllerClass);
					break;

				default:
					throw new Error('Unknown action type.');
			}

			return this;
		}

		public function getActionForController(controller : AbstractController) : uint
		{
			var numControllersToClone		: uint = _clonedControllerTypes.length;
			var numControllersToIgnore		: uint = _ignoredControllerTypes.length;
			var numControllersToReassign	: uint = _reassignedControllerTypes.length;
			var controllerId				: uint;

			for (controllerId = 0; controllerId < numControllersToClone; ++controllerId)
				if (controller is _clonedControllerTypes[controllerId])
					return ControllerCloneAction.CLONE;

			for (controllerId = 0; controllerId < numControllersToIgnore; ++controllerId)
				if (controller is _ignoredControllerTypes[controllerId])
					return ControllerCloneAction.IGNORE;

			for (controllerId = 0; controllerId < numControllersToReassign; ++controllerId)
				if (controller is _reassignedControllerTypes[controllerId])
					return ControllerCloneAction.REASSIGN;

			return _defaultControllerAction;
		}

	}
}

remove useless imports

remove useless imports


package dolly {

import dolly.core.dolly_internal;
import dolly.data.PropertyLevelCloneableClass;

import org.as3commons.reflect.Type;

use namespace dolly_internal;

public class CloningOfPropertyLevelCloneableClassTest {

	private var propertyLevelCloneable:PropertyLevelCloneableClass;
	private var propertyLevelCloneableType:Type;

	[Before]
	public function before():void {
		propertyLevelCloneable = new PropertyLevelCloneableClass();
		propertyLevelCloneable.property1 = "value 1";
		propertyLevelCloneable.writableField1 = "value 4";
		propertyLevelCloneableType = Type.forInstance(propertyLevelCloneable);
	}

	[After]
	public function after():void {
		propertyLevelCloneable = null;
		propertyLevelCloneableType = null;
	}

	/**
	 * Cloner.findingAllWritableFieldsForType() method will throw CloningError in this case
	 * because PropertyLevelCloneable class is not cloneable indeed.
	 */
	[Test(expects="dolly.core.errors.CloningError")]
	public function findingAllWritableFieldsForType():void {
		Cloner.findAllWritableFieldsForType(propertyLevelCloneableType);
	}

	/**
	 * Cloner.clone() method will throw CloningError in this case
	 * because PropertyLevelCloneable class is not cloneable indeed.
	 */
	[Test(expects="dolly.core.errors.CloningError")]
	public function cloningByCloner():void {
		Cloner.clone(propertyLevelCloneable);
	}

	/**
	 * Method clone() will throw CloningError in this case
	 * because PropertyLevelCloneable class is not cloneable indeed.
	 */
	[Test(expects="dolly.core.errors.CloningError")]
	public function cloningByCloneFunction():void {
		clone(propertyLevelCloneable);
	}

}
}

package dolly {

import dolly.core.dolly_internal;
import dolly.data.PropertyLevelCloneableClass;

import org.as3commons.reflect.Type;

use namespace dolly_internal;

public class CloningOfPropertyLevelCloneableClassTest {

	private var propertyLevelCloneable:PropertyLevelCloneableClass;
	private var propertyLevelCloneableType:Type;

	[Before]
	public function before():void {
		propertyLevelCloneable = new PropertyLevelCloneableClass();
		propertyLevelCloneable.property1 = "property1 value";
		propertyLevelCloneable.writableField1 = "writableField1 value";
		propertyLevelCloneableType = Type.forInstance(propertyLevelCloneable);
	}

	[After]
	public function after():void {
		propertyLevelCloneable = null;
		propertyLevelCloneableType = null;
	}

	/**
	 * Cloner.findingAllWritableFieldsForType() method will throw CloningError in this case
	 * because PropertyLevelCloneable class is not cloneable indeed.
	 */
	[Test(expects="dolly.core.errors.CloningError")]
	public function findingAllWritableFieldsForType():void {
		Cloner.findAllWritableFieldsForType(propertyLevelCloneableType);
	}

	/**
	 * Cloner.clone() method will throw CloningError in this case
	 * because PropertyLevelCloneable class is not cloneable indeed.
	 */
	[Test(expects="dolly.core.errors.CloningError")]
	public function cloningByCloner():void {
		Cloner.clone(propertyLevelCloneable);
	}

	/**
	 * Method clone() will throw CloningError in this case
	 * because PropertyLevelCloneable class is not cloneable indeed.
	 */
	[Test(expects="dolly.core.errors.CloningError")]
	public function cloningByCloneFunction():void {
		clone(propertyLevelCloneable);
	}

}
}

Change properties' values.

Change properties' values.