////////////////////////////////////////////////////////////////////////////////
//
//  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.html.beads.layouts
{
	import org.apache.flex.core.IBeadLayout;
	import org.apache.flex.core.IDocument;
	import org.apache.flex.core.ILayoutChild;
	import org.apache.flex.core.ILayoutParent;
	import org.apache.flex.core.IParentIUIBase;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.core.IUIBase;
	import org.apache.flex.core.UIBase;
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;
	import org.apache.flex.geom.Rectangle;
	import org.apache.flex.utils.CSSUtils;
    import org.apache.flex.utils.CSSContainerUtils;

    /**
     *  The OneFlexibleChildHorizontalLayout class is a simple layout
     *  bead.  It takes the set of children and lays them out
     *  horizontally in one row, separating them according to
     *  CSS layout rules for margin and padding styles. But it
     *  will size the one child to take up as much or little
     *  room as possible.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class OneFlexibleChildHorizontalLayout implements IBeadLayout, IDocument
	{
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function OneFlexibleChildHorizontalLayout()
		{
		}

        /**
         *  The id of the flexible child
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var flexibleChild:String;

        private var actualChild:ILayoutChild;

        // the strand/host container is also an ILayoutChild because
        // can have its size dictated by the host's parent which is
        // important to know for layout optimization
        private var host:ILayoutChild;

        /**
         *  @private
         *  The document.
         */
        private var document:Object;

        /**
         *  @copy org.apache.flex.core.IBead#strand
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function set strand(value:IStrand):void
		{
            host = value as ILayoutChild;
		}

        private var _maxWidth:Number;

        /**
         *  @copy org.apache.flex.core.IBead#maxWidth
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get maxWidth():Number
        {
            return _maxWidth;
        }

        /**
         *  @private
         */
        public function set maxWidth(value:Number):void
        {
            _maxWidth = value;
        }

        private var _maxHeight:Number;

        /**
         *  @copy org.apache.flex.core.IBead#maxHeight
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get maxHeight():Number
        {
            return _maxHeight;
        }

        /**
         *  @private
         */
        public function set maxHeight(value:Number):void
        {
            _maxHeight = value;
        }

        /**
         * @copy org.apache.flex.core.IBeadLayout#layout
         */
		public function layout():Boolean
		{
            var layoutParent:ILayoutParent = host.getBeadByType(ILayoutParent) as ILayoutParent;
            var contentView:IParentIUIBase = layoutParent ? layoutParent.contentView : IParentIUIBase(host);
            var padding:Rectangle = CSSContainerUtils.getPaddingMetrics(host);
            actualChild = document[flexibleChild];

            var ilc:ILayoutChild;
			var n:int = contentView.numElements;
			var marginLeft:Object;
			var marginRight:Object;
			var marginTop:Object;
			var marginBottom:Object;
			var margin:Object;
			maxHeight = 0;
			var verticalMargins:Array = new Array(n);

            var ww:Number = contentView.width - padding.right;
            var hh:Number = contentView.height;
            var xx:int = padding.left;
            var flexChildIndex:int;
            var ml:Number;
            var mr:Number;
            var mt:Number;
            var mb:Number;
            var lastmr:Number;
            var lastml:Number;
            var valign:Object;
            var hostSizedToContent:Boolean = host.isHeightSizedToContent();

            for (var i:int = 0; i < n; i++)
            {
                var child:IUIBase = contentView.getElementAt(i) as IUIBase;
                if (child == actualChild)
                {
                    flexChildIndex = i;
                    break;
                }
                margin = ValuesManager.valuesImpl.getValue(child, "margin");
                marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
                marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
                marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
                marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
                mt = CSSUtils.getTopValue(marginTop, margin, hh);
                mb = CSSUtils.getBottomValue(marginBottom, margin, hh);
                mr = CSSUtils.getRightValue(marginRight, margin, ww);
                ml = CSSUtils.getLeftValue(marginLeft, margin, ww);
                child.y = mt + padding.top;
                if (child is ILayoutChild)
                {
                    ilc = child as ILayoutChild;
                    if (!isNaN(ilc.percentHeight))
                        ilc.setHeight(contentView.height * ilc.percentHeight / 100, true);
                }
                maxHeight = Math.max(maxHeight, mt + child.height + mb);
                child.x = xx + ml;
                xx += child.width + ml + mr;
                lastmr = mr;
                valign = ValuesManager.valuesImpl.getValue(child, "vertical-align");
                verticalMargins[i] = { marginTop: mt, marginBottom: mb, valign: valign };
            }

            if (n > 0 && n > flexChildIndex)
            {
                for (i = n - 1; i > flexChildIndex; i--)
    			{
    				child = contentView.getElementAt(i) as IUIBase;
    				margin = ValuesManager.valuesImpl.getValue(child, "margin");
					marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
					marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
					marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
					marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
    				mt = CSSUtils.getTopValue(marginTop, margin, hh);
    				mb = CSSUtils.getTopValue(marginBottom, margin, hh);
                    mr = CSSUtils.getRightValue(marginRight, margin, ww);
                    ml = CSSUtils.getLeftValue(marginLeft, margin, ww);
                    child.y = mt + padding.top;
                    if (child is ILayoutChild)
                    {
                        ilc = child as ILayoutChild;
                        if (!isNaN(ilc.percentHeight))
                            ilc.setHeight(contentView.height * ilc.percentHeight / 100, true);
                    }
                    maxHeight = Math.max(maxHeight, mt + child.height + mb);
                    child.x = ww - child.width - mr;
    				ww -= child.width + ml + mr;
    				lastml = ml;
                    valign = ValuesManager.valuesImpl.getValue(child, "vertical-align");
                    verticalMargins[i] = { marginTop: mt, marginBottom: mb, valign: valign };
    			}

                child = contentView.getElementAt(flexChildIndex) as IUIBase;
                margin = ValuesManager.valuesImpl.getValue(child, "margin");
                marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
                marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
                marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
                marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
                mt = CSSUtils.getTopValue(marginTop, margin, hh);
                mb = CSSUtils.getTopValue(marginBottom, margin, hh);
                mr = CSSUtils.getRightValue(marginRight, margin, ww);
                ml = CSSUtils.getLeftValue(marginLeft, margin, ww);
                if (child is ILayoutChild)
                {
                    ilc = child as ILayoutChild;
                    if (!isNaN(ilc.percentHeight))
                        ilc.setHeight(contentView.height * ilc.percentHeight / 100, true);
                }
                maxHeight = Math.max(maxHeight, mt + child.height + mb);
                child.x = xx + ml;
                child.width = ww - xx - child.x;
                valign = ValuesManager.valuesImpl.getValue(child, "vertical-align");
                verticalMargins[flexChildIndex] = { marginTop: mt, marginBottom: mb, valign: valign };
            }
            if (hostSizedToContent)
                ILayoutChild(contentView).setHeight(maxHeight + padding.top + padding.bottom, true);

            for (i = 0; i < n; i++)
			{
				var obj:Object = verticalMargins[i]
				child = contentView.getElementAt(i) as IUIBase;
                setPositionAndHeight(child, obj.top, obj.marginTop, padding.top,
                    obj.bottom, obj.marginBottom, padding.bottom, maxHeight, obj.valign);
			}
            return true;
		}

        private function setPositionAndHeight(child:IUIBase, top:Number, mt:Number, pt:Number,
                                              bottom:Number, mb:Number, pb:Number, h:Number, valign:String):void
        {
            var heightSet:Boolean = false; // if we've set the height in a way that gens a change event
            var ySet:Boolean = false; // if we've set the y yet.

            var hh:Number = h;
            var ilc:ILayoutChild = child as ILayoutChild;
            if (!isNaN(top))
            {
                child.y = top + mt;
                ySet = true;
                hh -= top + mt;
            }
            else
            {
                hh -= mt;
            }
            if (!isNaN(bottom))
            {
                if (!isNaN(top))
                {
                    if (ilc)
                        ilc.setHeight(hh - bottom - mb, true);
                    else
                    {
                        child.height = hh - bottom - mb;
                        heightSet = true;
                    }
                }
                else
                {
                    child.y = h - bottom - mb - child.height - 1; // some browsers don't like going to the edge
                    ySet = true;
                }
            }
            if (ilc)
            {
                if (!isNaN(ilc.percentHeight))
                    ilc.setHeight(h * ilc.percentHeight / 100, true);
            }
            if (valign == "center")
                child.y = (h - child.height) / 2;
            else if (valign == "bottom")
                child.y = h - child.height - mb;
            else
                child.y = mt + pt;
            if (!heightSet)
                child.dispatchEvent(new Event("sizeChanged"));
        }

        public function setDocument(document:Object, id:String = null):void
        {
            this.document = document;
        }
    }

}

////////////////////////////////////////////////////////////////////////////////
//
//  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.html.beads.layouts
{
	import org.apache.flex.core.IBeadLayout;
	import org.apache.flex.core.IDocument;
	import org.apache.flex.core.ILayoutChild;
	import org.apache.flex.core.ILayoutParent;
	import org.apache.flex.core.IParentIUIBase;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.core.IUIBase;
	import org.apache.flex.core.UIBase;
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;
	import org.apache.flex.geom.Rectangle;
	import org.apache.flex.utils.CSSUtils;
    import org.apache.flex.utils.CSSContainerUtils;

    /**
     *  The OneFlexibleChildHorizontalLayout class is a simple layout
     *  bead.  It takes the set of children and lays them out
     *  horizontally in one row, separating them according to
     *  CSS layout rules for margin and padding styles. But it
     *  will size the one child to take up as much or little
     *  room as possible.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class OneFlexibleChildHorizontalLayout implements IBeadLayout, IDocument
	{
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function OneFlexibleChildHorizontalLayout()
		{
		}

        /**
         *  The id of the flexible child
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var flexibleChild:String;

        private var actualChild:ILayoutChild;

        // the strand/host container is also an ILayoutChild because
        // can have its size dictated by the host's parent which is
        // important to know for layout optimization
        private var host:ILayoutChild;

        /**
         *  @private
         *  The document.
         */
        private var document:Object;

        /**
         *  @copy org.apache.flex.core.IBead#strand
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function set strand(value:IStrand):void
		{
            host = value as ILayoutChild;
		}

        private var _maxWidth:Number;

        /**
         *  @copy org.apache.flex.core.IBead#maxWidth
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get maxWidth():Number
        {
            return _maxWidth;
        }

        /**
         *  @private
         */
        public function set maxWidth(value:Number):void
        {
            _maxWidth = value;
        }

        private var _maxHeight:Number;

        /**
         *  @copy org.apache.flex.core.IBead#maxHeight
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get maxHeight():Number
        {
            return _maxHeight;
        }

        /**
         *  @private
         */
        public function set maxHeight(value:Number):void
        {
            _maxHeight = value;
        }

        /**
         * @copy org.apache.flex.core.IBeadLayout#layout
         */
		public function layout():Boolean
		{
            var layoutParent:ILayoutParent = host.getBeadByType(ILayoutParent) as ILayoutParent;
            var contentView:IParentIUIBase = layoutParent ? layoutParent.contentView : IParentIUIBase(host);
            var padding:Rectangle = CSSContainerUtils.getPaddingMetrics(host);
            actualChild = document[flexibleChild];

            var ilc:ILayoutChild;
			var n:int = contentView.numElements;
			var marginLeft:Object;
			var marginRight:Object;
			var marginTop:Object;
			var marginBottom:Object;
			var margin:Object;
			maxHeight = 0;
			var verticalMargins:Array = new Array(n);

            var ww:Number = contentView.width - padding.right;
            var hh:Number = contentView.height;
            var xx:int = padding.left;
            var flexChildIndex:int;
            var ml:Number;
            var mr:Number;
            var mt:Number;
            var mb:Number;
            var lastmr:Number;
            var lastml:Number;
            var valign:Object;
            var hostSizedToContent:Boolean = host.isHeightSizedToContent();

            for (var i:int = 0; i < n; i++)
            {
                var child:IUIBase = contentView.getElementAt(i) as IUIBase;
                if (child == actualChild)
                {
                    flexChildIndex = i;
                    break;
                }
                margin = ValuesManager.valuesImpl.getValue(child, "margin");
                marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
                marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
                marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
                marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
                mt = CSSUtils.getTopValue(marginTop, margin, hh);
                mb = CSSUtils.getBottomValue(marginBottom, margin, hh);
                mr = CSSUtils.getRightValue(marginRight, margin, ww);
                ml = CSSUtils.getLeftValue(marginLeft, margin, ww);
                child.y = mt + padding.top;
                if (child is ILayoutChild)
                {
                    ilc = child as ILayoutChild;
                    if (!isNaN(ilc.percentHeight))
                        ilc.setHeight(contentView.height * ilc.percentHeight / 100, true);
                }
                maxHeight = Math.max(maxHeight, mt + child.height + mb);
                child.x = xx + ml;
                xx += child.width + ml + mr;
                lastmr = mr;
                valign = ValuesManager.valuesImpl.getValue(child, "vertical-align");
                verticalMargins[i] = { marginTop: mt, marginBottom: mb, valign: valign };
            }

            if (n > 0 && n > flexChildIndex)
            {
                for (i = n - 1; i > flexChildIndex; i--)
    			{
    				child = contentView.getElementAt(i) as IUIBase;
    				margin = ValuesManager.valuesImpl.getValue(child, "margin");
					marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
					marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
					marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
					marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
    				mt = CSSUtils.getTopValue(marginTop, margin, hh);
    				mb = CSSUtils.getTopValue(marginBottom, margin, hh);
                    mr = CSSUtils.getRightValue(marginRight, margin, ww);
                    ml = CSSUtils.getLeftValue(marginLeft, margin, ww);
                    child.y = mt + padding.top;
                    if (child is ILayoutChild)
                    {
                        ilc = child as ILayoutChild;
                        if (!isNaN(ilc.percentHeight))
                            ilc.setHeight(contentView.height * ilc.percentHeight / 100, true);
                    }
                    maxHeight = Math.max(maxHeight, mt + child.height + mb);
                    child.x = ww - child.width - mr;
    				ww -= child.width + ml + mr;
    				lastml = ml;
                    valign = ValuesManager.valuesImpl.getValue(child, "vertical-align");
                    verticalMargins[i] = { marginTop: mt, marginBottom: mb, valign: valign };
    			}

                child = contentView.getElementAt(flexChildIndex) as IUIBase;
                margin = ValuesManager.valuesImpl.getValue(child, "margin");
                marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
                marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
                marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
                marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
                mt = CSSUtils.getTopValue(marginTop, margin, hh);
                mb = CSSUtils.getTopValue(marginBottom, margin, hh);
                mr = CSSUtils.getRightValue(marginRight, margin, ww);
                ml = CSSUtils.getLeftValue(marginLeft, margin, ww);
                if (child is ILayoutChild)
                {
                    ilc = child as ILayoutChild;
                    if (!isNaN(ilc.percentHeight))
                        ilc.setHeight(contentView.height * ilc.percentHeight / 100, true);
                }
                child.x = xx + ml;
                child.width = ww - child.x;
                maxHeight = Math.max(maxHeight, mt + child.height + mb);
                valign = ValuesManager.valuesImpl.getValue(child, "vertical-align");
                verticalMargins[flexChildIndex] = { marginTop: mt, marginBottom: mb, valign: valign };
            }
            if (hostSizedToContent)
                ILayoutChild(contentView).setHeight(maxHeight + padding.top + padding.bottom, true);

            for (i = 0; i < n; i++)
			{
				var obj:Object = verticalMargins[i]
				child = contentView.getElementAt(i) as IUIBase;
                setPositionAndHeight(child, obj.top, obj.marginTop, padding.top,
                    obj.bottom, obj.marginBottom, padding.bottom, maxHeight, obj.valign);
			}
            return true;
		}

        private function setPositionAndHeight(child:IUIBase, top:Number, mt:Number, pt:Number,
                                              bottom:Number, mb:Number, pb:Number, h:Number, valign:String):void
        {
            var heightSet:Boolean = false; // if we've set the height in a way that gens a change event
            var ySet:Boolean = false; // if we've set the y yet.

            var hh:Number = h;
            var ilc:ILayoutChild = child as ILayoutChild;
            if (!isNaN(top))
            {
                child.y = top + mt;
                ySet = true;
                hh -= top + mt;
            }
            else
            {
                hh -= mt;
            }
            if (!isNaN(bottom))
            {
                if (!isNaN(top))
                {
                    if (ilc)
                        ilc.setHeight(hh - bottom - mb, true);
                    else
                    {
                        child.height = hh - bottom - mb;
                        heightSet = true;
                    }
                }
                else
                {
                    child.y = h - bottom - mb - child.height - 1; // some browsers don't like going to the edge
                    ySet = true;
                }
            }
            if (ilc)
            {
                if (!isNaN(ilc.percentHeight))
                    ilc.setHeight(h * ilc.percentHeight / 100, true);
            }
            if (valign == "center")
                child.y = (h - child.height) / 2;
            else if (valign == "bottom")
                child.y = h - child.height - mb;
            else
                child.y = mt + pt;
            if (!heightSet)
                child.dispatchEvent(new Event("sizeChanged"));
        }

        public function setDocument(document:Object, id:String = null):void
        {
            this.document = document;
        }
    }

}

fix the calculation

fix the calculation


////////////////////////////////////////////////////////////////////////////////
//
//  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.html.beads.layouts
{
	import org.apache.flex.core.IBeadLayout;
	import org.apache.flex.core.IBeadModel;
	import org.apache.flex.core.ILayoutChild;
	import org.apache.flex.core.ILayoutParent;
	import org.apache.flex.core.IParentIUIBase;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.core.IUIBase;
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;
	import org.apache.flex.utils.dbg.DOMPathUtil;

	/**
	 *  The VerticalLayout class is a simple layout
	 *  bead.  It takes the set of children and lays them out
	 *  vertically in one column, separating them according to
	 *  CSS layout rules for margin and horizontal-align styles.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10.2
	 *  @playerversion AIR 2.6
	 *  @productversion FlexJS 0.0
	 */
	public class VerticalLayout implements IBeadLayout
	{
		/**
		 *  Constructor.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
		 */
		public function VerticalLayout()
		{
		}

		// the strand/host container is also an ILayoutChild because
		// can have its size dictated by the host's parent which is
		// important to know for layout optimization
		private var host:ILayoutChild;

		/**
		 *  @copy org.apache.flex.core.IBead#strand
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
		 */
		public function set strand(value:IStrand):void
		{
			host = value as ILayoutChild;
		}

		public function layout():Boolean
		{
			var layoutParent:ILayoutParent = host.getBeadByType(ILayoutParent) as ILayoutParent;
			var contentView:IParentIUIBase = layoutParent ? layoutParent.contentView : IParentIUIBase(host);

			var n:int = contentView.numElements;
			var hasHorizontalFlex:Boolean;
			var hostSizedToContent:Boolean = host.isWidthSizedToContent();
			var flexibleHorizontalMargins:Array = [];
			var ilc:ILayoutChild;
			var marginLeft:Object;
			var marginRight:Object;
			var marginTop:Object;
			var marginBottom:Object;
			var margin:Object;
			var maxWidth:Number = 0;
			// asking for contentView.width can result in infinite loop if host isn't sized already
			var w:Number = hostSizedToContent ? 0 : contentView.width;

			for (var i:int = 0; i < n; i++)
			{
				var child:IUIBase = contentView.getElementAt(i) as IUIBase;
				if (child == null || !child.visible) continue;
				ilc = child as ILayoutChild;
				var left:Number = ValuesManager.valuesImpl.getValue(child, "left");
				var right:Number = ValuesManager.valuesImpl.getValue(child, "right");
				margin = ValuesManager.valuesImpl.getValue(child, "margin");
				if (margin is Array)
				{
					if (margin.length == 1)
						marginLeft = marginTop = marginRight = marginBottom = margin[0];
					else if (margin.length <= 3)
					{
						marginLeft = marginRight = margin[1];
						marginTop = marginBottom = margin[0];
					}
					else if (margin.length == 4)
					{
						marginLeft = margin[3];
						marginBottom = margin[2];
						marginRight = margin[1];
						marginTop = margin[0];
					}
				}
				else if (margin == null)
				{
					marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
					marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
					marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
					marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
				}
				else
				{
					marginLeft = marginTop = marginBottom = marginRight = margin;
				}
				var ml:Number;
				var mr:Number;
				var mt:Number;
				var mb:Number;
				var lastmb:Number;
				mt = Number(marginTop);
				if (isNaN(mt))
					mt = 0;
				mb = Number(marginBottom);
				if (isNaN(mb))
					mb = 0;
				var yy:Number;
				if (i == 0)
                {
                    if (ilc)
                        ilc.setY(mt);
                    else
    					child.y = mt;
                }
				else
                {
                    if (ilc)
                        ilc.setY(yy + Math.max(mt, lastmb));
                    else
    					child.y = yy + Math.max(mt, lastmb);
                }
				if (ilc)
				{
					if (!isNaN(ilc.percentHeight))
						ilc.setHeight(contentView.height * ilc.percentHeight / 100, !isNaN(ilc.percentWidth));
				}
				lastmb = mb;
				var marginObject:Object = {};
				flexibleHorizontalMargins[i] = marginObject;
				if (marginLeft == "auto")
				{
					ml = 0;
					marginObject.marginLeft = marginLeft;
					hasHorizontalFlex = true;
				}
				else
				{
					ml = Number(marginLeft);
					if (isNaN(ml))
					{
						ml = 0;
						marginObject.marginLeft = marginLeft;
					}
					else
						marginObject.marginLeft = ml;
				}
				if (marginRight == "auto")
				{
					mr = 0;
					marginObject.marginRight = marginRight;
					hasHorizontalFlex = true;
				}
				else
				{
					mr = Number(marginRight);
					if (isNaN(mr))
					{
						mr = 0;
						marginObject.marginRight = marginRight;
					}
					else
						marginObject.marginRight = mr;
				}
				if (!hostSizedToContent)
				{
					// if host is sized by parent,
					// we can position and size children horizontally now
					setPositionAndWidth(child, left, ml, right, mr, w);
				}
				else
				{
					if (!isNaN(left))
					{
						ml = left;
						marginObject.left = ml;
					}
					if (!isNaN(right))
					{
						mr = right;
						marginObject.right = mr;
					}
					maxWidth = Math.max(maxWidth, ml + child.width + mr);
				}
				yy = child.y + child.height;
			}
			if (hostSizedToContent)
			{
				for (i = 0; i < n; i++)
				{
					child = contentView.getElementAt(i) as IUIBase;
					if (child == null || !child.visible) continue;
					var obj:Object = flexibleHorizontalMargins[i];
					setPositionAndWidth(child, obj.left, obj.marginLeft,
						obj.right, obj.marginRight, maxWidth);
				}
			}
			if (hasHorizontalFlex)
			{
				for (i = 0; i < n; i++)
				{
					child = contentView.getElementAt(i) as IUIBase;
					if (child == null || !child.visible) continue;
					ilc = child as ILayoutChild;
					obj = flexibleHorizontalMargins[i];
					if (hasHorizontalFlex)
					{
                        if (ilc)
                        {
                            if (obj.marginLeft == "auto" && obj.marginRight == "auto")
                                ilc.setX(maxWidth - child.width / 2);
                            else if (obj.marginLeft == "auto")
                                ilc.setX(maxWidth - child.width - obj.marginRight);
                        }
                        else
                        {
        					if (obj.marginLeft == "auto" && obj.marginRight == "auto")
        						child.x = maxWidth - child.width / 2;
        					else if (obj.marginLeft == "auto")
        						child.x = maxWidth - child.width - obj.marginRight;
                        }
					}
				}
			}

			// Only return true if the contentView needs to be larger; that new
			// size is stored in the model.
			var sizeChanged:Boolean = true;

			host.dispatchEvent( new Event("layoutComplete") );

			return sizeChanged;
		}

		private function setPositionAndWidth(child:IUIBase, left:Number, ml:Number,
											 right:Number, mr:Number, w:Number):void
		{
			var widthSet:Boolean = false;

			var ww:Number = w;
			var ilc:ILayoutChild = child as ILayoutChild;
			if (!isNaN(left))
			{
                if (ilc)
                    ilc.setX(left + ml);
                else
    				child.x = left + ml;
				ww -= left + ml;
			}
			else
			{
                if (ilc)
                    ilc.setX(ml);
                else
    				child.x = ml;
				ww -= ml;
			}
			if (!isNaN(right))
			{
				if (!isNaN(left))
				{
					if (ilc)
						ilc.setWidth(ww - right - mr, true);
					else
					{
						child.width = ww - right - mr;
						widthSet = true;
					}
				}
				else
                {
                    if (ilc)
                        ilc.setX(w - right - mr - child.width);
                    else
    					child.x = w - right - mr - child.width;
                }
			}
			if (ilc)
			{
				if (!isNaN(ilc.percentWidth))
					ilc.setWidth(w * ilc.percentWidth / 100, true);
			}
			if (!widthSet)
				child.dispatchEvent(new Event("sizeChanged"));
		}

	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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.html.beads.layouts
{
	import org.apache.flex.core.IBeadLayout;
	import org.apache.flex.core.IBeadModel;
	import org.apache.flex.core.ILayoutChild;
	import org.apache.flex.core.ILayoutParent;
	import org.apache.flex.core.IParentIUIBase;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.core.IUIBase;
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;
	import org.apache.flex.utils.dbg.DOMPathUtil;
    import org.apache.flex.utils.CSSUtils;

	/**
	 *  The VerticalLayout class is a simple layout
	 *  bead.  It takes the set of children and lays them out
	 *  vertically in one column, separating them according to
	 *  CSS layout rules for margin and horizontal-align styles.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10.2
	 *  @playerversion AIR 2.6
	 *  @productversion FlexJS 0.0
	 */
	public class VerticalLayout implements IBeadLayout
	{
		/**
		 *  Constructor.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
		 */
		public function VerticalLayout()
		{
		}

		// the strand/host container is also an ILayoutChild because
		// can have its size dictated by the host's parent which is
		// important to know for layout optimization
		private var host:ILayoutChild;

		/**
		 *  @copy org.apache.flex.core.IBead#strand
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
		 */
		public function set strand(value:IStrand):void
		{
			host = value as ILayoutChild;
		}

		public function layout():Boolean
		{
			var layoutParent:ILayoutParent = host.getBeadByType(ILayoutParent) as ILayoutParent;
			var contentView:IParentIUIBase = layoutParent ? layoutParent.contentView : IParentIUIBase(host);

			var n:int = contentView.numElements;
			var hasHorizontalFlex:Boolean;
			var hostSizedToContent:Boolean = host.isWidthSizedToContent();
			var flexibleHorizontalMargins:Array = [];
			var ilc:ILayoutChild;
			var marginLeft:Object;
			var marginRight:Object;
			var marginTop:Object;
			var marginBottom:Object;
			var margin:Object;
			var maxWidth:Number = 0;
			// asking for contentView.width can result in infinite loop if host isn't sized already
			var w:Number = hostSizedToContent ? 0 : contentView.width;
            var h = contentView.height;

			for (var i:int = 0; i < n; i++)
			{
				var child:IUIBase = contentView.getElementAt(i) as IUIBase;
				if (child == null || !child.visible) continue;
				ilc = child as ILayoutChild;
				var left:Number = ValuesManager.valuesImpl.getValue(child, "left");
				var right:Number = ValuesManager.valuesImpl.getValue(child, "right");
				margin = ValuesManager.valuesImpl.getValue(child, "margin");
                marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
                marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
                marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
                marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
				var ml:Number = CSSUtils.getLeftValue(marginLeft, margin, w);
				var mr:Number = CSSUtils.getRightValue(marginRight, margin, w);
				var mt:Number = CSSUtils.getTopValue(marginTop, margin, h);
				var mb:Number = CSSUtils.getBottomValue(marginBottom, margin, h);
				var lastmb:Number;
				var yy:Number;
				if (i == 0)
                {
                    if (ilc)
                        ilc.setY(mt);
                    else
    					child.y = mt;
                }
				else
                {
                    if (ilc)
                        ilc.setY(yy + Math.max(mt, lastmb));
                    else
    					child.y = yy + Math.max(mt, lastmb);
                }
				if (ilc)
				{
					if (!isNaN(ilc.percentHeight))
						ilc.setHeight(contentView.height * ilc.percentHeight / 100, !isNaN(ilc.percentWidth));
				}
				lastmb = mb;
				var marginObject:Object = {};
				flexibleHorizontalMargins[i] = marginObject;
				if (marginLeft == "auto")
				{
					ml = 0;
					marginObject.marginLeft = marginLeft;
					hasHorizontalFlex = true;
				}
				else
				{
					ml = Number(marginLeft);
					if (isNaN(ml))
					{
						ml = 0;
						marginObject.marginLeft = marginLeft;
					}
					else
						marginObject.marginLeft = ml;
				}
				if (marginRight == "auto")
				{
					mr = 0;
					marginObject.marginRight = marginRight;
					hasHorizontalFlex = true;
				}
				else
				{
					mr = Number(marginRight);
					if (isNaN(mr))
					{
						mr = 0;
						marginObject.marginRight = marginRight;
					}
					else
						marginObject.marginRight = mr;
				}
				if (!hostSizedToContent)
				{
					// if host is sized by parent,
					// we can position and size children horizontally now
					setPositionAndWidth(child, left, ml, right, mr, w);
				}
				else
				{
					if (!isNaN(left))
					{
						ml = left;
						marginObject.left = ml;
					}
					if (!isNaN(right))
					{
						mr = right;
						marginObject.right = mr;
					}
					maxWidth = Math.max(maxWidth, ml + child.width + mr);
				}
				yy = child.y + child.height;
			}
			if (hostSizedToContent)
			{
				for (i = 0; i < n; i++)
				{
					child = contentView.getElementAt(i) as IUIBase;
					if (child == null || !child.visible) continue;
					var obj:Object = flexibleHorizontalMargins[i];
					setPositionAndWidth(child, obj.left, obj.marginLeft,
						obj.right, obj.marginRight, maxWidth);
				}
			}
			if (hasHorizontalFlex)
			{
				for (i = 0; i < n; i++)
				{
					child = contentView.getElementAt(i) as IUIBase;
					if (child == null || !child.visible) continue;
					ilc = child as ILayoutChild;
					obj = flexibleHorizontalMargins[i];
					if (hasHorizontalFlex)
					{
                        if (ilc)
                        {
                            if (obj.marginLeft == "auto" && obj.marginRight == "auto")
                                ilc.setX(maxWidth - child.width / 2);
                            else if (obj.marginLeft == "auto")
                                ilc.setX(maxWidth - child.width - obj.marginRight);
                        }
                        else
                        {
        					if (obj.marginLeft == "auto" && obj.marginRight == "auto")
        						child.x = maxWidth - child.width / 2;
        					else if (obj.marginLeft == "auto")
        						child.x = maxWidth - child.width - obj.marginRight;
                        }
					}
				}
			}

			// Only return true if the contentView needs to be larger; that new
			// size is stored in the model.
			var sizeChanged:Boolean = true;

			host.dispatchEvent( new Event("layoutComplete") );

			return sizeChanged;
		}

		private function setPositionAndWidth(child:IUIBase, left:Number, ml:Number,
											 right:Number, mr:Number, w:Number):void
		{
			var widthSet:Boolean = false;

			var ww:Number = w;
			var ilc:ILayoutChild = child as ILayoutChild;
			if (!isNaN(left))
			{
                if (ilc)
                    ilc.setX(left + ml);
                else
    				child.x = left + ml;
				ww -= left + ml;
			}
			else
			{
                if (ilc)
                    ilc.setX(ml);
                else
    				child.x = ml;
				ww -= ml;
			}
			if (!isNaN(right))
			{
				if (!isNaN(left))
				{
					if (ilc)
						ilc.setWidth(ww - right - mr, true);
					else
					{
						child.width = ww - right - mr;
						widthSet = true;
					}
				}
				else
                {
                    if (ilc)
                        ilc.setX(w - right - mr - child.width);
                    else
    					child.x = w - right - mr - child.width;
                }
			}
			if (ilc)
			{
				if (!isNaN(ilc.percentWidth))
					ilc.setWidth(w * ilc.percentWidth / 100, true);
			}
			if (!widthSet)
				child.dispatchEvent(new Event("sizeChanged"));
		}

	}
}

fix margin handling

fix margin 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.display.DisplayObject;
import flash.display.Loader;
import flash.display.LoaderInfo;

import flash.errors.IllegalOperationError;

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;

import flash.utils.ByteArray;

import flash.system.ApplicationDomain;
import flash.system.LoaderContext;

/**
 * Allows you to load an embeded SWF stored as a Byte Array then access any stored classes
 * within the SWF.
 * Embed your swf like:
 * [Embed(source="foo.swf", mimeType="application/octet-stream"]
 * Then, instantiate that class and pass it to load() as a ByteArray.
 *
 * An Event.COMPLETE will be dispatched upon the successful completion of a call to
 * {@link load}.  IOErrorEvent.IO_ERROR will be dispatched if there's a problem reading the
 * ByteArray.
 *
 * @deprecated Content packs are coming, and symbols can be embedded directly
 * by using [Embed(source="foo.swf#somesymbol")]
 */
public class EmbeddedSwfLoader extends EventDispatcher
{
    public function EmbeddedSwfLoader ()
    {
        _loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, dispatchEvent);
        _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
    }

    /**
     * Load the SWF from a Byte Array.  A CLASS_LOADED event will be dispatched on successful
     * completion of the load.  If any errors occur, a LOAD_ERROR event will be dispatched.
     */
    public function load (byteArray :ByteArray) :void
    {
        var context :LoaderContext = new LoaderContext();
        context.applicationDomain = ApplicationDomain.currentDomain;
        _loader.loadBytes(byteArray, context);
    }

    /**
     * Get the top-level display object defined in the loaded SWF.
     */
    public function getContent () :DisplayObject
    {
        checkLoaded();
        return _loader.content;
    }

    /**
     * Retrieves a class definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getClass (className :String) :Class
    {
        return getSymbol(className) as Class;
    }

    /**
     * Retrieves a Function definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getFunction (functionName :String) :Function
    {
        return getSymbol(functionName) as Function;
    }

    /**
     * Retrieves a symbol definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getSymbol (symbolName :String) :Object
    {
        checkLoaded();
        try {
            return _loader.contentLoaderInfo.applicationDomain.getDefinition(symbolName);
        } catch (e: Error) {
            throw new IllegalOperationError(symbolName + " definition not found");
        }
        return null;
    }

    /**
     * Checks if a symbol exists in the library.
     *
     * @throws IllegalOperationError when the swf has not completed loading.
     */
    public function isSymbol (className :String) :Boolean
    {
        checkLoaded();
        return _loader.contentLoaderInfo.applicationDomain.hasDefinition(className);
    }

    /**
     * Validate that the load operation is complete.
     */
    protected function checkLoaded () :void
    {
        var loaderInfo :LoaderInfo = _loader.contentLoaderInfo;
        if (loaderInfo.bytesTotal == 0 || loaderInfo.bytesLoaded != loaderInfo.bytesTotal) {

            throw new IllegalOperationError("SWF has not completed loading");
        }
    }

    protected var _loader :Loader;
}
}

//
// $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.display.DisplayObject;
import flash.display.Loader;
import flash.display.LoaderInfo;

import flash.errors.IllegalOperationError;

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;

import flash.utils.ByteArray;

import flash.system.ApplicationDomain;
import flash.system.LoaderContext;

/**
 * Allows you to load an embeded SWF stored as a Byte Array then access any stored classes
 * within the SWF.
 * Embed your swf like:
 * [Embed(source="foo.swf", mimeType="application/octet-stream"]
 * Then, instantiate that class and pass it to load() as a ByteArray.
 *
 * An Event.COMPLETE will be dispatched upon the successful completion of a call to
 * {@link load}.  IOErrorEvent.IO_ERROR will be dispatched if there's a problem reading the
 * ByteArray.
 *
 * @deprecated Content packs are coming, and symbols can be embedded directly
 * by using [Embed(source="foo.swf#somesymbol")]
 */
public class EmbeddedSwfLoader extends EventDispatcher
{
    public function EmbeddedSwfLoader ()
    {
        _loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, dispatchEvent);
        _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
    }

// This doesn't work. We cannot write parameters to the contentLoaderInfo.
// So: there is no way to pass parameters to content loaded using loadBytes,
// and there's no way to pass parameters to any other content without
// destroying caching (because you must append them to the url). Stupid flash.
//    /**
//     * Set a parameter accessible to the loaded content.
//     */
//    public function setParameter (name :String, val :String) :void
//    {
//        _loader.contentLoaderInfo.parameters[name] = val;
//    }

    /**
     * Load the SWF from a Byte Array.  A CLASS_LOADED event will be dispatched on successful
     * completion of the load.  If any errors occur, a LOAD_ERROR event will be dispatched.
     */
    public function load (byteArray :ByteArray) :void
    {
        var context :LoaderContext = new LoaderContext();
        context.applicationDomain = ApplicationDomain.currentDomain;
        _loader.loadBytes(byteArray, context);
    }

    /**
     * Get the top-level display object defined in the loaded SWF.
     */
    public function getContent () :DisplayObject
    {
        checkLoaded();
        return _loader.content;
    }

    /**
     * Retrieves a class definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getClass (className :String) :Class
    {
        return getSymbol(className) as Class;
    }

    /**
     * Retrieves a Function definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getFunction (functionName :String) :Function
    {
        return getSymbol(functionName) as Function;
    }

    /**
     * Retrieves a symbol definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getSymbol (symbolName :String) :Object
    {
        checkLoaded();
        try {
            return _loader.contentLoaderInfo.applicationDomain.getDefinition(symbolName);
        } catch (e: Error) {
            throw new IllegalOperationError(symbolName + " definition not found");
        }
        return null;
    }

    /**
     * Checks if a symbol exists in the library.
     *
     * @throws IllegalOperationError when the swf has not completed loading.
     */
    public function isSymbol (className :String) :Boolean
    {
        checkLoaded();
        return _loader.contentLoaderInfo.applicationDomain.hasDefinition(className);
    }

    /**
     * Validate that the load operation is complete.
     */
    protected function checkLoaded () :void
    {
        var loaderInfo :LoaderInfo = _loader.contentLoaderInfo;
        if (loaderInfo.bytesTotal == 0 || loaderInfo.bytesLoaded != loaderInfo.bytesTotal) {

            throw new IllegalOperationError("SWF has not completed loading");
        }
    }

    protected var _loader :Loader;
}
}

Document something that doesn't work.

Document something that doesn't work.

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


//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2009 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 com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;

import com.threerings.util.Log;
import com.threerings.util.Maps;
import com.threerings.util.maps.ForwardingMap;

/**
 * A {@link HashMap} that can be sent over the wire, bearing in mind that all keys and values must
 * be primitives or implement {@link Streamable}.
 */
public class StreamableHashMap extends ForwardingMap
    implements Streamable
{
    public function StreamableHashMap (keyClazz :Class = null)
    {
        if (keyClazz != null) {
            super(Maps.newMapOf(keyClazz));
        }
    }

    // documentation inherited from interface Streamable
    public function writeObject (out :ObjectOutputStream) :void
    {
        out.writeInt(size());
        forEach(function (key :Object, value :Object) :void {
            out.writeObject(key);
            out.writeObject(value);
        });
    }

    // documentation inherited from interface Streamable
    public function readObject (ins :ObjectInputStream) :void
    {
        var ecount :int = ins.readInt();
        if (ecount > 0) {
            // guess the type of map based on the first key
            var key :Object = ins.readObject();
            _source = Maps.newMapOf(ClassUtil.getClass(key));
            put(key, ins.readObject());
            // now read the rest
            for (var ii :int = 1; ii < ecount; ii++) {
                put(ins.readObject(), ins.readObject());
            }

        } else {
            // shit!
            Log.getLog(this).warning("Empty StreamableHashMap read, guessing DictionaryMap.");
            _source = Maps.newDictionaryMap();
        }
    }
}
}

//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2009 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 com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;

import com.threerings.util.Log;
import com.threerings.util.Maps;
import com.threerings.util.maps.ForwardingMap;

/**
 * A {@link HashMap} that can be sent over the wire, bearing in mind that all keys and values must
 * be primitives or implement {@link Streamable}.
 */
public class StreamableHashMap extends ForwardingMap
    implements Streamable
{
    public function StreamableHashMap (keyClazz :Class = null)
    {
        if (keyClazz != null) {
            super(Maps.newMapOf(keyClazz));
        }
    }

    // documentation inherited from interface Streamable
    public function writeObject (out :ObjectOutputStream) :void
    {
        out.writeInt(size());
        forEach(function (key :Object, value :Object) :void {
            out.writeObject(key);
            out.writeObject(value);
        });
    }

    // documentation inherited from interface Streamable
    public function readObject (ins :ObjectInputStream) :void
    {
        var ecount :int = ins.readInt();
        if (ecount > 0) {
            // guess the type of map based on the first key
            var key :Object = ins.readObject();
            _source = Maps.newMapOf(ClassUtil.getClass(key));
            put(key, ins.readObject());
            // now read the rest
            for (var ii :int = 1; ii < ecount; ii++) {
                put(ins.readObject(), ins.readObject());
            }

        } else {
            // shit!
            Log.getLog(this).warning("Empty StreamableHashMap read, guessing DictionaryMap.");
            _source = Maps.newMapOf(Object);
        }
    }
}
}

Use newMapOf().

Use newMapOf().

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


/**
 * 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.
 */

package org.apache.flex.core.graphics
{
    COMPILE::AS3
    {
        import flash.display.GradientType;
        import flash.display.InterpolationMethod;
        import flash.display.SpreadMethod;
        import flash.geom.Matrix;
        import flash.geom.Point;
        import flash.geom.Rectangle;
    }

	public class LinearGradient extends GradientBase implements IFill
	{
		COMPILE::AS3
		private static var commonMatrix:Matrix = new Matrix();

		private var _scaleX:Number;

		/**
		 *  The horizontal scale of the gradient transform, which defines the width of the (unrotated) gradient
		 */
		public function get scaleX():Number
		{
			return _scaleX;
		}

		public function set scaleX(value:Number):void
		{
			_scaleX = value;
		}

        COMPILE::AS3
		public function begin(s:GraphicShape,targetBounds:Rectangle, targetOrigin:Point):void
		{
			commonMatrix.identity();
			commonMatrix.createGradientBox(targetBounds.width,targetBounds.height,toRad(this.rotation),targetOrigin.x, targetOrigin.y);

			s.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios,
				commonMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);

		}

        COMPILE::AS3
		public function end(s:GraphicShape):void
		{
			s.graphics.endFill();
		}

        /**
         * addFillAttrib()
         *
         * @param value The GraphicShape object on which the fill must be added.
         * @return {string}
         * @flexjsignorecoercion Node
         */
        COMPILE::JS
        public function addFillAttrib(value:GraphicShape):String
        {
            //Create and add a linear gradient def
            var svgNS:String = value.element.namespaceURI;
            var grad:HTMLElement = document.createElementNS(svgNS, 'linearGradient') as HTMLElement;
            var gradientId:String = this.newId;
            grad.setAttribute('id', gradientId);

            //Set x1, y1, x2, y2 of gradient
            grad.setAttribute('x1', '0%');
            grad.setAttribute('y1', '0%');
            grad.setAttribute('x2', '100%');
            grad.setAttribute('y2', '0%');

            //Apply rotation to the gradient if rotation is a number
            if (rotation)
            {
                grad.setAttribute('gradientTransform', 'rotate(' + rotation + ' 0.5 0.5)');
            }

            //Process gradient entries and create a stop for each entry
            var entries:Array = entries;
            for (var i:int = 0; i < entries.length; i++)
            {
                var gradientEntry:GradientEntry = entries[i];
                var stop:HTMLElement = document.createElementNS(svgNS, 'stop') as HTMLElement;
                //Set Offset
                stop.setAttribute('offset', String(gradientEntry.ratio * 100) + '%');
                //Set Color
                var color:String = Number(gradientEntry.color).toString(16);
                if (color.length == 1) color = '00' + color;
                if (color.length == 2) color = '00' + color;
                if (color.length == 4) color = '00' + color;
                stop.setAttribute('stop-color', '#' + String(color));
                //Set Alpha
                stop.setAttribute('stop-opacity', String(gradientEntry.alpha));

                grad.appendChild(stop);
            }

            //Add defs element if not available already
            //Add newly created gradient to defs element
            var defs:Node = value.element.querySelector('defs') ||
                value.element.insertBefore(document.createElementNS(svgNS, 'defs'), value.element.firstChild);
            defs.appendChild(grad);

            //Return the fill attribute
            return 'fill:url(#' + gradientId + ')';
        }

	}
}

/**
 * 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.
 */

package org.apache.flex.core.graphics
{
    COMPILE::AS3
    {
        import flash.display.GradientType;
        import flash.display.InterpolationMethod;
        import flash.display.SpreadMethod;
        import flash.geom.Matrix;
        import flash.geom.Point;
        import flash.geom.Rectangle;
    }

	public class LinearGradient extends GradientBase implements IFill
	{
		COMPILE::AS3
		private static var commonMatrix:Matrix = new Matrix();

		private var _scaleX:Number;

		/**
		 *  The horizontal scale of the gradient transform, which defines the width of the (unrotated) gradient
		 */
		public function get scaleX():Number
		{
			return _scaleX;
		}

		public function set scaleX(value:Number):void
		{
			_scaleX = value;
		}

        COMPILE::AS3
		public function begin(s:GraphicShape,targetBounds:Rectangle, targetOrigin:Point):void
		{
			commonMatrix.identity();
			commonMatrix.createGradientBox(targetBounds.width,targetBounds.height,toRad(this.rotation),targetOrigin.x, targetOrigin.y);

			s.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios,
				commonMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);

		}

        COMPILE::AS3
		public function end(s:GraphicShape):void
		{
			s.graphics.endFill();
		}

        /**
         * addFillAttrib()
         *
         * @param value The GraphicShape object on which the fill must be added.
         * @return {string}
         * @flexjsignorecoercion Node
         */
        COMPILE::JS
        public function addFillAttrib(value:GraphicShape):String
        {
            //Create and add a linear gradient def
            var svgNS:String = value.element.namespaceURI;
            var grad:HTMLElement = document.createElementNS(svgNS, 'linearGradient') as HTMLElement;
            var gradientId:String = this.newId;
            grad.setAttribute('id', gradientId);

            //Set x1, y1, x2, y2 of gradient
            grad.setAttribute('x1', '0%');
            grad.setAttribute('y1', '0%');
            grad.setAttribute('x2', '100%');
            grad.setAttribute('y2', '0%');

            //Apply rotation to the gradient if rotation is a number
            if (rotation)
            {
                grad.setAttribute('gradientTransform', 'rotate(' + rotation + ' 0.5 0.5)');
            }

            //Process gradient entries and create a stop for each entry
            var entries:Array = this.entries;
            for (var i:int = 0; i < entries.length; i++)
            {
                var gradientEntry:GradientEntry = entries[i];
                var stop:HTMLElement = document.createElementNS(svgNS, 'stop') as HTMLElement;
                //Set Offset
                stop.setAttribute('offset', String(gradientEntry.ratio * 100) + '%');
                //Set Color
                var color:String = Number(gradientEntry.color).toString(16);
                if (color.length == 1) color = '00' + color;
                if (color.length == 2) color = '00' + color;
                if (color.length == 4) color = '00' + color;
                stop.setAttribute('stop-color', '#' + String(color));
                //Set Alpha
                stop.setAttribute('stop-opacity', String(gradientEntry.alpha));

                grad.appendChild(stop);
            }

            //Add defs element if not available already
            //Add newly created gradient to defs element
            var defs:Node = value.element.querySelector('defs') ||
                value.element.insertBefore(document.createElementNS(svgNS, 'defs'), value.element.firstChild);
            defs.appendChild(grad);

            //Return the fill attribute
            return 'fill:url(#' + gradientId + ')';
        }

	}
}

fix error

fix error


package asunit.runners {

	import asunit.events.TimeoutCommandEvent;
	import asunit.framework.Assert;
	import asunit.framework.Async;
	import asunit.framework.IResult;
	import asunit.framework.Result;
	import asunit.framework.IAsync;
	import asunit.framework.IRunner;
	import asunit.framework.IRunnerFactory;
	import asunit.framework.Method;
	import asunit.framework.TestFailure;
	import asunit.framework.TestIterator;
	import asunit.framework.TestSuccess;
	import asunit.framework.TestWarning;
	import asunit.util.ArrayIterator;
	import asunit.util.Iterator;
	import flash.display.Sprite;
	import org.swiftsuspenders.Injector;

	import p2.reflect.Reflection;
	import p2.reflect.ReflectionMetaData;
	import p2.reflect.ReflectionVariable;

	import flash.display.DisplayObjectContainer;
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;
	import flash.utils.getTimer;

    public class TestRunner extends EventDispatcher implements IRunner {

		/**
		 *
		 */
		//TODO: perhaps add a getter for this to IRunner
        public var result:IResult;

        // partially exposed for unit testing
        internal var currentTest:Object;
        internal var async:IAsync;
		/** Supplies dependencies to tests, e.g. IAsync, context Sprite. */
		internal var testInjector:Injector;

        protected var currentMethod:Method;
        protected var currentTestReflection:Reflection;
        protected var methodIsExecuting:Boolean = false;
        protected var methodPassed:Boolean = true;
        protected var methodTimeoutID:Number;
        protected var methodsToRun:TestIterator;
        protected var startTime:Number;
        protected var testMethodNameReceived:Boolean;
        protected var timer:Timer;
        protected var visualContext:DisplayObjectContainer;
        protected var visualInstances:Array;

        public function TestRunner(result:IResult = null) {
            async  = new Async();
            this.result = result ||= new Result();
            testInjector = new Injector();
			testInjector.mapValue(IAsync, async);
			testInjector.mapValue(Async, async);
            timer = new Timer(0, 1);
            timer.addEventListener(TimerEvent.TIMER, runNextMethod);
            visualInstances = [];
        }

        public function run(testOrSuite:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
            runMethodByName(testOrSuite, methodName, visualContext);
        }

        public function runMethodByName(test:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
            currentTestReflection  = Reflection.create(test);
            this.visualContext     = visualContext;
			testInjector.mapValue(Sprite, visualContext);
            currentMethod          = null;
            testMethodNameReceived = (methodName != null);

            try {
                currentTest = testInjector.instantiate(test);
            }
            catch(e:VerifyError) {
                warn("Unable to instantiate provided test case with: " + currentTestReflection.name);
                return;
            }

            async.addEventListener(TimeoutCommandEvent.CALLED,     onAsyncMethodCalled);
            async.addEventListener(TimeoutCommandEvent.TIMED_OUT,  onAsyncMethodTimedOut);

            startTime = getTimer();
            result.onTestStarted(currentTest);

            methodsToRun = createTestIterator(currentTest, methodName);

            if(methodsToRun.length == 0) {
                warn(">> We were unable to find any test methods in " + currentTestReflection.name + ". Did you set the --keep-as3-metadata flag?");
            }
            runNextMethod();
        }

        protected function createTestIterator(test:*, testMethodName:String):TestIterator {
            return new TestIterator(test, testMethodName);
        }

        protected function runNextMethod(e:TimerEvent = null):void {
            if (testCompleted) {
                onTestCompleted();
                return;
            }

            runMethod(methodsToRun.next());
        }

        protected function runMethod(method:Method):void {
            if (!method) return;
            currentMethod = method;
            methodPassed = true; // innocent until proven guilty by recordFailure()

            if (currentMethod.ignore) {
                result.onTestIgnored(currentMethod);
                onMethodCompleted();
                return;
            }

            // This is used to prevent async callbacks from triggering onMethodCompleted too early.
            methodIsExecuting = true;

            if (currentMethod.expects) {
                try {
                    var errorClass:Class = getDefinitionByName(currentMethod.expects) as Class;
                    Assert.assertThrows(errorClass, currentMethod.value);
                }
                catch(definitionError:ReferenceError) {
                    // NOTE: [luke] Added ReferenceError catch here b/c I had a bad class name in my expects.
                    // Does this look right?
                    recordFailure(new Error('Could not find Reference for: ' + currentMethod.expects));
                }
                catch (error:Error) {
                    recordFailure(error);
                }
            }
            else {
                try {
                    currentMethod.execute();
                }
                catch (error:Error) {
                    recordFailure(error);
                }
            }

            methodIsExecuting = false;

            if (async.hasPending) return;

            onMethodCompleted();
        }

        protected function onMethodCompleted():void {
            async.cancelPending();

            if (currentMethod.isTest && methodPassed && !currentMethod.ignore) {
                result.onTestSuccess(new TestSuccess(currentTest, currentMethod.name));
            }

            // Calling synchronously is faster but keeps adding to the call stack.
            runNextMethod();

            // green thread for runNextMethod()
            // This runs much slower in Flash Player 10.1.
            //timer.reset();
            //timer.start();
        }

        protected function onAsyncMethodCalled(event:TimeoutCommandEvent):void {
            try {
                event.command.execute();
            }
            catch (error:Error) {
                recordFailure(error);
            }
            onAsyncMethodCompleted(event);
        }

        protected function onAsyncMethodTimedOut(event:TimeoutCommandEvent):void {
            var error:IllegalOperationError = new IllegalOperationError("Timeout (" + event.command.duration + "ms) exceeded on an asynchronous operation.");
            recordFailure(error);
            onAsyncMethodCompleted(event);
        }

        protected function recordFailure(error:Error):void {
            methodPassed = false;
            result.onTestFailure(new TestFailure(currentTest, currentMethod.name, error));
        }

        protected function onAsyncMethodCompleted(event:Event = null):void {
            if (!methodIsExecuting && !async.hasPending) {
                onMethodCompleted();
            }
        }

        protected function onTestCompleted():void {
            async.removeEventListener(TimeoutCommandEvent.CALLED,      onAsyncMethodCalled);
            async.removeEventListener(TimeoutCommandEvent.TIMED_OUT,   onAsyncMethodTimedOut);
            async.cancelPending();

            result.onTestCompleted(currentTest);

            dispatchEvent(new Event(Event.COMPLETE));
        }

        protected function get testCompleted():Boolean {
            return (!methodsToRun.hasNext() && !async.hasPending);

        }
        protected function warn(message:String, method:Method=null):void {
            result.onWarning(new TestWarning(message, method));
        }
    }
}

package asunit.runners {

	import asunit.events.TimeoutCommandEvent;
	import asunit.framework.Assert;
	import asunit.framework.Async;
	import asunit.framework.IResult;
	import asunit.framework.Result;
	import asunit.framework.IAsync;
	import asunit.framework.IRunner;
	import asunit.framework.IRunnerFactory;
	import asunit.framework.Method;
	import asunit.framework.TestFailure;
	import asunit.framework.TestIterator;
	import asunit.framework.TestSuccess;
	import asunit.framework.TestWarning;
	import asunit.util.ArrayIterator;
	import asunit.util.Iterator;
	import flash.display.Sprite;
	import org.swiftsuspenders.Injector;

	import p2.reflect.Reflection;
	import p2.reflect.ReflectionMetaData;
	import p2.reflect.ReflectionVariable;

	import flash.display.DisplayObjectContainer;
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;
	import flash.utils.getTimer;

    public class TestRunner extends EventDispatcher implements IRunner {

		/**
		 *
		 */
		//TODO: perhaps add a getter for this to IRunner
        public var result:IResult;

        // partially exposed for unit testing
        internal var currentTest:Object;
        internal var async:IAsync;
		/** Supplies dependencies to tests, e.g. IAsync, context Sprite. */
		internal var testInjector:Injector;

        protected var currentMethod:Method;
        protected var currentTestReflection:Reflection;
        protected var methodIsExecuting:Boolean = false;
        protected var methodPassed:Boolean = true;
        protected var methodTimeoutID:Number;
        protected var methodsToRun:TestIterator;
        protected var startTime:Number;
        protected var testMethodNameReceived:Boolean;
        protected var timer:Timer;
        protected var visualContext:DisplayObjectContainer;
        protected var visualInstances:Array;

        public function TestRunner(result:IResult = null) {
            async  = new Async();
            this.result = result ||= new Result();
            testInjector = new Injector();
			testInjector.mapValue(IAsync, async);
			testInjector.mapValue(Async, async);
            timer = new Timer(0, 1);
            timer.addEventListener(TimerEvent.TIMER, runNextMethods);
            visualInstances = [];
        }

        public function runMethodByName(testOrSuite:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
            run(testOrSuite, methodName, visualContext);
        }

        public function run(test:Class, methodName:String=null, visualContext:DisplayObjectContainer=null):void {
			currentTestReflection  = Reflection.create(test);
            this.visualContext     = visualContext;
			testInjector.mapValue(Sprite, visualContext);
            currentMethod          = null;
            testMethodNameReceived = (methodName != null);

            try {
                currentTest = testInjector.instantiate(test);
            }
            catch(e:VerifyError) {
                warn("Unable to instantiate provided test case with: " + currentTestReflection.name);
                return;
            }

            async.addEventListener(TimeoutCommandEvent.CALLED,     onAsyncMethodCalled);
            async.addEventListener(TimeoutCommandEvent.TIMED_OUT,  onAsyncMethodTimedOut);

            startTime = getTimer();
            result.onTestStarted(currentTest);

            methodsToRun = createTestIterator(currentTest, methodName);

            if(methodsToRun.length == 0) {
                warn(">> We were unable to find any test methods in " + currentTestReflection.name + ". Did you set the --keep-as3-metadata flag?");
            }

            runNextMethods();
        }

        protected function createTestIterator(test:*, testMethodName:String):TestIterator {
            return new TestIterator(test, testMethodName);
        }

        protected function runNextMethods(e:TimerEvent = null):void {
			// Loop through as many as possible without hitting asynchronous tests.
			// This keeps the call stack small.
			while (methodsToRun.hasNext()) {
				var hasAsyncPending:Boolean = runMethod(methodsToRun.next());
				if (hasAsyncPending) return;
			}

			onTestCompleted();
        }

		/**
		 *
		 * @param	method
		 * @return	true if asynchronous calls are pending after calling the test method.
		 */
        protected function runMethod(method:Method):Boolean {
            if (!method) return false;
            currentMethod = method;
            methodPassed = true; // innocent until proven guilty by recordFailure()

            if (currentMethod.ignore) {
                result.onTestIgnored(currentMethod);
                onMethodCompleted();
                return false;
            }

            // This is used to prevent async callbacks from triggering onMethodCompleted too early.
            methodIsExecuting = true;

            if (currentMethod.expects) {
                try {
                    var errorClass:Class = getDefinitionByName(currentMethod.expects) as Class;
                    Assert.assertThrows(errorClass, currentMethod.value);
                }
                catch(definitionError:ReferenceError) {
                    // NOTE: [luke] Added ReferenceError catch here b/c I had a bad class name in my expects.
                    // Does this look right?
                    recordFailure(new Error('Could not find Reference for: ' + currentMethod.expects));
                }
                catch (error:Error) {
                    recordFailure(error);
                }
            }
            else {
                try {
                    currentMethod.execute();
                }
                catch (error:Error) {
                    recordFailure(error);
                }
            }

            methodIsExecuting = false;

            if (async.hasPending) return true;

            onMethodCompleted();
			return false;
        }

        protected function onMethodCompleted(wasAsync:Boolean = false):void {
            async.cancelPending();

            if (currentMethod.isTest && methodPassed && !currentMethod.ignore) {
                result.onTestSuccess(new TestSuccess(currentTest, currentMethod.name));
            }

            if (wasAsync)
				runNextMethods();

            // green thread for runNextMethods()
            // This runs much slower in Flash Player 10.1.
            //timer.reset();
            //timer.start();
        }

        protected function onAsyncMethodCalled(event:TimeoutCommandEvent):void {
            try {
                event.command.execute();
            }
            catch (error:Error) {
                recordFailure(error);
            }
            onAsyncMethodCompleted(event);
        }

        protected function onAsyncMethodTimedOut(event:TimeoutCommandEvent):void {
            var error:IllegalOperationError = new IllegalOperationError("Timeout (" + event.command.duration + "ms) exceeded on an asynchronous operation.");
            recordFailure(error);
            onAsyncMethodCompleted(event);
        }

        protected function recordFailure(error:Error):void {
            methodPassed = false;
            result.onTestFailure(new TestFailure(currentTest, currentMethod.name, error));
        }

        protected function onAsyncMethodCompleted(event:Event = null):void {
            if (!methodIsExecuting && !async.hasPending) {
                onMethodCompleted(true);
            }
        }

        protected function onTestCompleted():void {
            async.removeEventListener(TimeoutCommandEvent.CALLED,      onAsyncMethodCalled);
            async.removeEventListener(TimeoutCommandEvent.TIMED_OUT,   onAsyncMethodTimedOut);
            async.cancelPending();

            result.onTestCompleted(currentTest);

            dispatchEvent(new Event(Event.COMPLETE));
        }

        protected function get testCompleted():Boolean {
            return (!methodsToRun.hasNext() && !async.hasPending);

        }
        protected function warn(message:String, method:Method=null):void {
            result.onWarning(new TestWarning(message, method));
        }
    }
}

Call stacks for failures are now much shorter. Now using a while loop to iterate as far as possible before hitting async methods.


package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.MeshController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.enum.FrustumCulling;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractVisibleSceneNode implements ITaggable
	{
		public static const DEFAULT_MATERIAL	: Material	= new BasicMaterial();

		private var _ctrl				: MeshController;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: MeshVisibilityController;

		private var _cloned				: Signal;

		private var _tag				: uint = 1;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				var oldMaterial : Material = _material;

				_material = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _ctrl.geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			_ctrl.geometry = value;
		}

		public function get tag() : uint
		{
			return _tag;
		}

		public function set tag(value : uint) : void
		{
			if (_tag != value)
			{
				_tag = value;
				_properties.setProperty('tag', value);
			}
		}

        /**
         * Whether the mesh in inside the camera frustum or not.
         * @return
         *
         */
        public function get insideFrustum() : Boolean
        {
            return _visibility.insideFrustum;
        }

        override public function get computedVisibility() : Boolean
        {
            return scene
				? super.computedVisibility && _visibility.computedVisibility
				: super.computedVisibility;
        }

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get frame() : uint
		{
			return _ctrl.frame;
		}
		public function set frame(value : uint) : void
		{
			_ctrl.frame = value;
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null,
							 tag		: uint		= 1)
		{
			super();

			initializeMesh(geometry, material, name, tag);
		}

		override protected function initialize() : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(
				properties,
				'meshProperties',
				DataProviderUsage.EXCLUSIVE
			);

			super.initialize();
		}

		override protected function initializeSignals() : void
		{
			super.initializeSignals();

			_cloned = new Signal('Mesh.cloned');
		}

		override protected function initializeContollers() : void
		{
			super.initializeContollers();

			_ctrl = new MeshController();
			addController(_ctrl);

			_visibility = new MeshVisibilityController();
			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);
		}

		protected function initializeMesh(geometry	: Geometry,
										  material	: Material,
										  name		: String,
										  tag		: uint) : void
		{
			if (name)
				this.name = name;

			this.geometry	= geometry;
			this.material	= material || DEFAULT_MATERIAL;
			_tag			= tag;
		}

		public function cast(ray            : Ray,
                             maxDistance    : Number    = Number.POSITIVE_INFINITY,
                             tag            : uint      = 1) : Number
		{
			if (!(_tag & tag))
				return -1;

			return _ctrl.geometry.boundingBox.testRay(
				ray,
				getWorldToLocalTransform(),
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _ctrl.geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.MeshController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.enum.FrustumCulling;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractVisibleSceneNode implements ITaggable
	{
		private var _ctrl				: MeshController;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: MeshVisibilityController;

		private var _cloned				: Signal;

		private var _tag				: uint = 1;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				var oldMaterial : Material = _material;

				_material = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _ctrl.geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			_ctrl.geometry = value;
		}

		public function get tag() : uint
		{
			return _tag;
		}

		public function set tag(value : uint) : void
		{
			if (_tag != value)
			{
				_tag = value;
				_properties.setProperty('tag', value);
			}
		}

        /**
         * Whether the mesh in inside the camera frustum or not.
         * @return
         *
         */
        public function get insideFrustum() : Boolean
        {
            return _visibility.insideFrustum;
        }

        override public function get computedVisibility() : Boolean
        {
            return scene
				? super.computedVisibility && _visibility.computedVisibility
				: super.computedVisibility;
        }

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get frame() : uint
		{
			return _ctrl.frame;
		}
		public function set frame(value : uint) : void
		{
			_ctrl.frame = value;
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null,
							 tag		: uint		= 1)
		{
			super();

			initializeMesh(geometry, material, name, tag);
		}

		override protected function initialize() : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(
				properties,
				'meshProperties',
				DataProviderUsage.EXCLUSIVE
			);

			super.initialize();
		}

		override protected function initializeSignals() : void
		{
			super.initializeSignals();

			_cloned = new Signal('Mesh.cloned');
		}

		override protected function initializeContollers() : void
		{
			super.initializeContollers();

			_ctrl = new MeshController();
			addController(_ctrl);

			_visibility = new MeshVisibilityController();
			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);
		}

		protected function initializeMesh(geometry	: Geometry,
										  material	: Material,
										  name		: String,
										  tag		: uint) : void
		{
			if (name)
				this.name = name;

			this.geometry	= geometry;
			this.material	= material;
			_tag			= tag;
		}

		public function cast(ray            : Ray,
                             maxDistance    : Number    = Number.POSITIVE_INFINITY,
                             tag            : uint      = 1) : Number
		{
			if (!(_tag & tag))
				return -1;

			return _ctrl.geometry.boundingBox.testRay(
				ray,
				getWorldToLocalTransform(),
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _ctrl.geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}
	}
}

fix Mesh.initializeMesh() to stop using static reference to a default material to avoid memory leak: by default Mesh will now have a null material if none is provided


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mangui.basic {
    import org.mangui.hls.HLS;
    import org.mangui.hls.event.HLSEvent;

    import flash.display.Sprite;
    import flash.media.Video;

    public class Player extends Sprite {
        private var hls : HLS = null;
        private var video : Video = null;

        public function Player() {
            hls = new HLS();

            video = new Video(640, 480);
            addChild(video);
            video.x = 0;
            video.y = 0;
            video.smoothing = true;
            video.attachNetStream(hls.stream);
            hls.addEventListener(HLSEvent.MANIFEST_LOADED, manifestHandler);
            hls.load("http://domain.com/hls/m1.m3u8");
        }

        public function manifestHandler(event : HLSEvent) : void {
            hls.stream.play();
        };
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.basic {
    import org.mangui.hls.HLS;
    import org.mangui.hls.event.HLSEvent;

    import flash.display.Sprite;
    import flash.media.Video;

    public class Player extends Sprite {
        private var hls : HLS = null;
        private var video : Video = null;

        public function Player() {
            hls = new HLS();
            hls.stage = this.stage;
            video = new Video(640, 480);
            addChild(video);
            video.x = 0;
            video.y = 0;
            video.smoothing = true;
            video.attachNetStream(hls.stream);
            hls.addEventListener(HLSEvent.MANIFEST_LOADED, manifestHandler);
            hls.load("http://domain.com/hls/m1.m3u8");
        }

        public function manifestHandler(event : HLSEvent) : void {
            hls.stream.play(null, -1);
        };
    }
}

update basic/Player.as and set stage

update basic/Player.as and set stage