////////////////////////////////////////////////////////////////////////////////
//
//  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 mx.containers
{

import flash.display.DisplayObject;
import flash.events.Event;

import mx.containers.utilityClasses.BoxLayout;
import mx.containers.utilityClasses.Flex;
import mx.controls.FormItemLabel;
import mx.controls.Label;
import mx.core.Container;
import mx.core.EdgeMetrics;
import mx.core.IFlexDisplayObject;
import mx.core.IUIComponent;
import mx.core.mx_internal;
import mx.core.ScrollPolicy;
import mx.styles.CSSStyleDeclaration;

use namespace mx_internal;

//--------------------------------------
//  Styles
//--------------------------------------

include "../styles/metadata/GapStyles.as";

/**
 *  Horizontal alignment of children in the container.
 *  Possible values are <code>"left"</code>, <code>"center"</code>,
 *  and <code>"right"</code>.
 *
 *  @default "left"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="horizontalAlign", type="String", enumeration="left,center,right", inherit="no")]

/**
 *  Number of pixels between the label and child components of the form item.
 *
 *  @default 14
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="indicatorGap", type="Number", format="Length", inherit="yes")]

/**
 *  Specifies the skin to use for the required field indicator. 
 *
 *  The default value is the "mx.containers.FormItem.Required" symbol in the Assets.swf file.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="indicatorSkin", type="Class", inherit="no")]

/**
 *  Name of the CSS Style declaration to use for the styles for the
 *  FormItem's label.
 *  By default, the label uses the FormItem's inheritable styles or 
 *  those declared by FormItemLabel.  This style should be used instead 
 *  of FormItemLabel.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="labelStyleName", type="String", inherit="no")]

/**
 *  Width of the form labels.
 *  The default is the length of the longest label in the form.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="labelWidth", type="Number", format="Length", inherit="yes")]

/**
 *  Number of pixels between the container's bottom border
 *  and the bottom edge of its content area.
 *  
 *  @default 0
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="paddingBottom", type="Number", format="Length", inherit="no")]

/**
 *  Number of pixels between the container's right border
 *  and the right edge of its content area.
 *  
 *  @default 0
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="paddingRight", type="Number", format="Length", inherit="no")]

/**
 *  Number of pixels between the container's top border
 *  and the top edge of its content area.
 *  
 *  @default 0
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="paddingTop", type="Number", format="Length", inherit="no")]

//--------------------------------------
//  Excluded APIs
//--------------------------------------

[Exclude(name="focusIn", kind="event")]
[Exclude(name="focusOut", kind="event")]

[Exclude(name="focusBlendMode", kind="style")]
[Exclude(name="focusSkin", kind="style")]
[Exclude(name="focusThickness", kind="style")]

[Exclude(name="focusInEffect", kind="effect")]
[Exclude(name="focusOutEffect", kind="effect")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[IconFile("FormItem.png")]

[Alternative(replacement="spark.components.FormItem", since="4.5")]

/**
 *  The FormItem container defines a label and one or more children
 *  arranged horizontally or vertically.
 *  Children can be controls or other containers.
 *  A single Form container can hold multiple FormItem containers.
 *
 *  @mxml
 *
 *  <p>The <code>&lt;mx:FormItem&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass, except <code>paddingLeft</code>,
 *  and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;mx:FormItem
 *    <strong>Properties</strong>
 *    direction="vertical|horizontal"
 *    label=""
 *    required="false|true"
 *  
 *    <strong>Styles</strong>
 *    horizontalAlign="left|center|right"
 *    horizontalGap="8"
 *    indicatorGap="14"
 *    indicatorSkin="<i>'mx.containers.FormItem.Required' symbol in Assets.swf</i>"
 *    labelStyleName=""
 *    labelWidth="<i>Calculated</i>"
 *    paddingBottom="0"
 *    paddingRight="0"
 *    paddingTop="0"
 *    verticalGap="6"
 *    &gt;
 *    ...
 *      <i>child tags</i>
 *    ...
 *  &lt;/mx:FormItem&gt;
 *  </pre>
 *
 *  @see mx.containers.Form
 *  @see mx.containers.FormItemDirection
 *  @see mx.containers.FormHeading
 *  @see mx.controls.FormItemLabel
 *
 *  @includeExample examples/FormExample.mxml
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class FormItem extends Container
{
    include "../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function FormItem()
    {
        super();

        _horizontalScrollPolicy = ScrollPolicy.OFF;
        _verticalScrollPolicy = ScrollPolicy.OFF;
        
        verticalLayoutObject.target = this;
        verticalLayoutObject.direction = BoxDirection.VERTICAL;
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  A reference to the FormItemLabel subcomponent.
     */
    private var labelObj:Label;

    /**
     *  @private
     *  A reference to the "required" indicator.
     */
    private var indicatorObj:IFlexDisplayObject;

    /**
     *  @private
     */
    private var guessedRowWidth:Number;

    /**
     *  @private
     */
    private var guessedNumColumns:int;

    /**
     *  @private
     */
    private var numberOfGuesses:int = 0;
    
    /**
     *  @private
     *  We use the VBox algorithm when direction="vertical" and make a few adjustments
     */
    mx_internal var verticalLayoutObject:BoxLayout = new BoxLayout();

    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //-------------------------------------------------------------------------

    //----------------------------------
    //  label
    //----------------------------------

    /**
     *  @private
     *  Storage for the label property.
     */
    private var _label:String = "";
    
    private var labelChanged:Boolean = false;

    [Bindable("labelChanged")]
    [Inspectable(category="General", defaultValue="")]

    /**
     *  Text label for the FormItem. This label appears to the left of the 
     *  child components of the form item. The position of the label is 
     *  controlled by the <code>textAlign</code> style property. 
     *
     *  @default ""
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override public function get label():String
    {
        return _label;
    }

    /**
     *  @private
     */
    override public function set label(value:String):void
    {
        _label = value;
        labelChanged = true;

        invalidateProperties();
        invalidateSize();
        invalidateDisplayList();

        // Changing the label could affect the overall form label width
        // so we need to invalidate our parent's size here too
       if (parent is Form)
            Form(parent).invalidateLabelWidth();

        dispatchEvent(new Event("labelChanged"));
    }

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  direction
    //----------------------------------

    /**
     *  @private
     *  Storage for the direction property.
     */
    private var _direction:String = FormItemDirection.VERTICAL;

    [Bindable("directionChanged")]
    [Inspectable(category="General", enumeration="vertical,horizontal", defaultValue="vertical")]

    /**
     *  Direction of the FormItem subcomponents.
     *  Possible MXML values are <code>"vertical"</code>
     *  or <code>"horizontal"</code>.
     *  The default MXML value is <code>"vertical"</code>.
     *  Possible ActionScript values are <code>FormItemDirection.VERTICAL</code>
     *  or <code>FormItemDirection.HORIZONTAL</code>.
     *
     *  <p>When <code>direction</code> is <code>"vertical"</code>,
     *  the children of the  FormItem are stacked vertically
     *  to the right of the FormItem label.
     *  When <code>direction</code> is <code>"horizontal"</code>,
     *  the children are placed in a single row (if they fit),
     *  or in two equally-sized columns.</p>
     *
     *  <p>If you need more control over the layout of FormItem children,
     *  you can use a container such as Grid or Tile as the direct child
     *  of the FormItem and put the desired controls inside it.</p>
     *
     *  @default FormItemDirection.VERTICAL
     *  @see mx.containers.FormItemDirection
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get direction():String
    {
        return _direction;
    }

    /**
     *  @private
     */
    public function set direction(value:String):void
    {
        _direction = value;

        invalidateSize();
        invalidateDisplayList();

        dispatchEvent(new Event("directionChanged"));
    }

    //----------------------------------
    //  itemLabel
    //----------------------------------

    [Bindable("itemLabelChanged")]
    
    /**
     *  A read-only reference to the FormItemLabel subcomponent
     *  displaying the label of the FormItem.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get itemLabel():Label
    {
        return labelObj;
    }
    
    //----------------------------------
    //  required
    //----------------------------------

    /**
     *  @private
     *  Storage for the required property.
     */
    private var _required:Boolean = false;

    [Bindable("requiredChanged")]
    [Inspectable(category="General", defaultValue="false")]

    /**
     *  If <code>true</code>, display an indicator
     *  that the FormItem children require user input.
     *  If <code>false</code>, indicator is not displayed.
     *
     *  <p>This property controls the indicator display only.
     *  You must attach a validator to the children
     *  if you require input validation.</p>
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get required():Boolean
    {
        return _required;
    }

    /**
     *  @private
     */
    public function set required(value:Boolean):void
    {
        if (value != _required)
        {
            _required = value;
 
            invalidateDisplayList();

            dispatchEvent(new Event("requiredChanged"));
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden properties: UIComponent
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override public function set includeInLayout(value:Boolean):void
    {
        super.includeInLayout = value;
        if(value)
            invalidateSize();
    }
        
    //--------------------------------------------------------------------------
    //
    //  Overridden methods: UIComponent
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
        
        if (!labelObj)
        {
            labelObj = new FormItemLabel();
            
            var labelStyleName:String = getStyle("labelStyleName");
            if (labelStyleName)
            {
                var styleDecl:CSSStyleDeclaration =
                	styleManager.getMergedStyleDeclaration("." + labelStyleName);
            
                if (styleDecl)
                    labelObj.styleDeclaration = styleDecl;
            }
            
            rawChildren.addChild(labelObj);
            dispatchEvent(new Event("itemLabelChanged"));
        }
    }
    
    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();
        
        if (labelChanged)
        {
            labelObj.text = label;
            labelObj.validateSize();
            labelChanged = false;
        }
    }

    /**
     *  Calculates the preferred, minimum and maximum sizes of the FormItem.
     *  See the <code>UIComponent.measure()</code> method for more information
     *  about the <code>measure()</code> method.
     *
     *  <p>The <code>FormItem.measure()</code> method first determines
     *  the number of columns to use.
     *  If the <code>direction</code> property is
     *  <code>FormItemDirection.HORIZONTAL</code>,
     *  all controls will be placed in a single row if possible.
     *  If the controls cannot fit in a single row, they are split
     *  into two columns.  If that does not work, then use
     *  a single column. If <code>direction</code> is
     *  <code>FormItemDirection.VERTICAL</code>, the controls are 
     *  placed in a single column (like <code>VBox</code>).</p>
     *
     *  <p>A FormItem contains two areas: the label area
     *  and the controls area.
     *  The size of the label is the same
     *  regardless of the direction of the controls.
     *  The size of the control area depends on how many rows 
     *  and columns are used.</p>
     *
     *  <p>The width of the label area is determined by the
     *  <code>labelWidth</code> style property.
     *  If this property is <code>undefined</code> (which is the default),
     *  the width of the largest label in the parent Form container
     *  is used.</p>
     *
     *  <p>If all children are on a single row, the width of the
     *  control area is the sum of the widths of all the children
     *  plus <code>horizontalGap</code> space between the children.</p>
     *
     *  <p>If the children are on a single column,
     *  the width of the control area is the width of the widest child.</p>
     *
     *  <p>If the children are on multiple rows and columns,
     *  the width of the widest child is the column width,
     *  and the width of the control area is the column width
     *  multiplied by the number of columns plus the
     *  <code>horizontalGap</code> space between each column.</p>
     *
     *  <p><code>measuredWidth</code> is set to the
     *  width of the label area plus the width of the control area
     *  plus the value of the <code>indicatorGap</code> style property.
     *  The values of the <code>paddingLeft</code> and
     *  <code>paddingRight</code> style properties
     *  and the width of the border are also added.</p>
     *
     *  <p><code>measuredHeight</code> is set to the
     *  sum of the preferred heights of all rows of children,
     *  plus <code>verticalGap</code> space between each child.
     *  The <code>paddingTop</code> and <code>paddingBottom</code>
     *  style properties and the height of the border are also added.</p>
     *
     *  <p><code>measuredMinWidth</code> is set to the width of the
     *  label area plus the minimum width of the control area
     *  plus the value of the <code>indicatorGap</code> style property.
     *  The values of the <code>paddingLeft</code> and
     *  <code>paddingRight</code> style properties
     *  and the width of the border are also added.</p>
     *
     *  <p><code>measuredMinHeight</code> is set to the
     *  sum of the minimum heights of all rows of children,
     *  plus <code>verticalGap</code> space between each child.
     *  The <code>paddingTop</code> and <code>paddingBottom</code>
     *  style properties and the height of the border are also added.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override protected function measure():void
    {
        super.measure();
        
        if (direction == FormItemDirection.VERTICAL)
            measureVertical();
        else
            measureHorizontal();
    }
    
    private function measureVertical():void
    {
        // use VBox and then take into account label, indictor gap
        verticalLayoutObject.measure();
        
        // Need to include label and indictor gap for width
        var extraWidth:Number = calculateLabelWidth() + getStyle("indicatorGap");
        
        measuredMinWidth += extraWidth;
        measuredWidth += extraWidth;
        
        // need to include label for height
        var labelHeight:Number = labelObj.getExplicitOrMeasuredHeight();
        
        measuredMinHeight = Math.max(measuredMinHeight, labelHeight);
        measuredHeight = Math.max(measuredHeight, labelHeight);
    }
    
    private function measureHorizontal():void
    {   
        // Take a guess at the number of columns we are going to use.
        // Initially guessedRowWidth is NaN (which means we try to squeeze
        // it on one row), but after first call to updateDisplayList, it 
        // gets updated with the approximate width the children can have.
        // This lets use better estimate how many columns we can have
        // Check out updateDisplayList() for more info on this and what if 
        // our initial guess was wrong.
        var numColumns:int = guessedNumColumns =
            calcNumColumns(guessedRowWidth);

        var horizontalGap:Number = getStyle("horizontalGap");
        var verticalGap:Number = getStyle("verticalGap");
        var indicatorGap:Number = getStyle("indicatorGap");

        var tempMinWidth:Number = 0;
        var tempWidth:Number = 0;
        var tempMinHeight:Number = 0;
        var tempHeight:Number = 0;
        
        var minWidth:Number = 0;
        var minHeight:Number = 0;
        var preferredWidth:Number = 0;
        var preferredHeight:Number = 0;
        var maxPreferredWidth:Number = 0;

        var i:int;
        var col:int = 0;
        var child:IUIComponent;

        // If the children span multiple rows,
        // then updateDisplayList() (below) sets all column widths to the
        // preferredWidth of the largest child.
        
        // To find the max. preferred width, just loop through
        // all the children
        if (numColumns < numChildren)
        {
            for (i = 0; i < numChildren; i++)
            {
                child = getLayoutChildAt(i);
                
                if (!child.includeInLayout)
                    continue;

                maxPreferredWidth = Math.max(
                    maxPreferredWidth, child.getExplicitOrMeasuredWidth());
            }
        }
        
        var row:int = 0;

        // Now with the columnWidth (maxPreferredWidth) figured out,
        // figure out the number of rows needed and calculate the 
        // minWidth/height and the preferredWidth/Height
        for (i = 0; i < numChildren; i++)
        {
            child = getLayoutChildAt(i);
            
            if (!child.includeInLayout)
                continue;

            tempMinWidth += !isNaN(child.percentWidth) ?
                            child.minWidth :
                            child.getExplicitOrMeasuredWidth();

            tempWidth += (maxPreferredWidth > 0) ?
                         maxPreferredWidth :
                         child.getExplicitOrMeasuredWidth();

            // if on anything but 1st column
            if (col > 0)
            {
                tempMinWidth += horizontalGap;
                tempWidth += horizontalGap;
            }

            tempMinHeight = Math.max(tempMinHeight,
                                     !isNaN(child.percentHeight) ?
                                     child.minHeight :
                                     child.getExplicitOrMeasuredHeight());

            tempHeight = Math.max(tempHeight,
                                  child.getExplicitOrMeasuredHeight());

            col++;
        
            // if at the last column in the row
            if (col >= numColumns || i == (numChildren-1))
            {
                minWidth = Math.max(minWidth, tempMinWidth);
                preferredWidth = Math.max(preferredWidth, tempWidth);

                minHeight += tempMinHeight;
                preferredHeight += tempHeight;
                
                // if on anything but 1st row  
                if (row > 0)
                {
                    minHeight += verticalGap;
                    preferredHeight += verticalGap;
                }
                
                col = 0;
                row++;

                tempMinWidth = 0;
                tempWidth = 0;

                tempMinHeight = 0;
                tempHeight = 0;
            }
        }

        // Need to also account for label and indicator gap
        var labelWidth:Number = calculateLabelWidth() + indicatorGap;
        minWidth += labelWidth;
        preferredWidth += labelWidth;

        if (label != null && label != "")
        {
            minHeight = Math.max(minHeight,
                                 labelObj.getExplicitOrMeasuredHeight());

            preferredHeight = Math.max(preferredHeight,
                                       labelObj.getExplicitOrMeasuredHeight());
        }

        var vm:EdgeMetrics = viewMetricsAndPadding;

        minHeight += vm.top + vm.bottom;
        minWidth += vm.left + vm.right;

        preferredHeight += vm.top + vm.bottom;
        preferredWidth += vm.left + vm.right;

        measuredMinWidth = minWidth;
        measuredMinHeight = minHeight;

        measuredWidth = preferredWidth;
        measuredHeight = preferredHeight;
    }

    /**
     *  Responds to size changes by setting the positions and sizes
     *  of this container's children.
     *  See the <code>UIComponent.updateDisplayList()</code> method
     *  for more information about the <code>updateDisplayList()</code> method.
     *
     *  <p>See the <code>FormItem.measure()</code> method for more
     *  information on how the FormItem controls are positioned.</p>
     *
     *  <p>The label is aligned in the label area according to the <code>textAlign</code> style property.
     *  All labels in a form are aligned with each other.</p>
     *
     *  <p>If the <code>required</code> property is <code>true</code>,
     *  a symbol indicating the field is required is placed between
     *  the label and the controls.</p>
     *
     *  <p>The controls are positioned in columns, as described in the
     *  documentation for the <code>measure()</code> method.
     *  The  <code>horizontalAlign</code> style property
     *  determines where the controls are placed horizontally.</p>
     *
     *  <p>When the <code>direction</code> property is
     *  <code>"vertical"</code>, any child that has no <code>width</code>
     *  specified uses the <code>measuredWidth</code> rounded up
     *  to the nearest 1/4 width of the control area.
     *  This is done to avoid jagged right edges of controls.</p>
     *
     *  <p>This method calls the <code>super.updateDisplayList()</code>
     *  method before doing anything else.</p>
     *
     *  @param unscaledWidth Specifies the width of the component, in pixels,
     *  in the component's coordinates, regardless of the value of the
     *  <code>scaleX</code> property of the component.
     *
     *  @param unscaledHeight Specifies the height of the component, in pixels,
     *  in the component's coordinates, regardless of the value of the
     *  <code>scaleY</code> property of the component.   
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override protected function updateDisplayList(unscaledWidth:Number,
                                                  unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);

        if (direction == FormItemDirection.VERTICAL)
        {
            updateDisplayListVerticalChildren(unscaledWidth, unscaledHeight);
        }
        else
        {
            updateDisplayListHorizontalChildren(unscaledWidth, unscaledHeight);
        }
                
        // Position our label now that our children have been positioned.
        // Moving our children can affect the baselinePosition. (Bug 86725)
        var vm:EdgeMetrics = viewMetricsAndPadding;
        
        // we have x,y with respect to viewMetricsAndPadding here b/c
        // labelObj is added to rawChildren.  The children of FormItem
        // are added to a container object, so start at paddingLeft
        // and paddingTop (as the containerObj has border around it)
        var x:Number = vm.left;
        var y:Number = vm.top;
        
        var labelWidth:Number = calculateLabelWidth();
        
        var child:IUIComponent;
        var childBaseline:Number;

        // Position our label.
        if (numChildren > 0)
        {
            // Center label with first child
            child = getLayoutChildAt(0);
            childBaseline = child.baselinePosition;
            if (!isNaN(childBaseline))
                y += childBaseline - labelObj.baselinePosition;
        }

        // Set label size.
        labelObj.setActualSize(labelWidth, labelObj.getExplicitOrMeasuredHeight());
        labelObj.move(x, y);
 
        x += labelWidth;

        // Position the "required" indicator.
        displayIndicator(x, y);
    }
    
    private function updateDisplayListVerticalChildren(unscaledWidth:Number,
                                                       unscaledHeight:Number):void
    {
        // Need to include label and indictor gap for width
        var extraWidth:Number = calculateLabelWidth() + getStyle("indicatorGap");
        
        // a little bit of a hack, but need the target to have a good minWidth as well
        if (!isNaN(explicitMinWidth))
        	_explicitMinWidth -= extraWidth;
        else if (!isNaN(measuredMinWidth))
        	measuredMinWidth -= extraWidth;
        
        // Use the VBox algorithm and then shift everything to the left by
        // labeWidth + indicatorGap.  Also put where the label should go
        verticalLayoutObject.updateDisplayList(unscaledWidth - extraWidth, unscaledHeight);
        
        // reset minWidth from hack
        if (!isNaN(explicitMinWidth))
        	_explicitMinWidth += extraWidth;
        else if (!isNaN(measuredMinWidth))
        	measuredMinWidth += extraWidth;
        
        var n:Number = numChildren;
        var child:IUIComponent;
        
        for (var i:Number = 0; i < n; i++)
        {
            child = getLayoutChildAt(i);
            
            child.move(child.x + extraWidth, child.y);
        }
    }
    
    private function updateDisplayListHorizontalChildren(unscaledWidth:Number,
                                                         unscaledHeight:Number):void
    {
        // The layout algorithm is similar to BoxLayout, but it has to
        // figure out how many rows/columns to use
        var vm:EdgeMetrics = viewMetricsAndPadding;

        var labelWidth:Number = calculateLabelWidth();

        var indicatorGap:Number = getStyle("indicatorGap");
        var horizontalGap:Number = getStyle("horizontalGap");
        var verticalGap:Number = getStyle("verticalGap");
        var paddingLeft:Number = getStyle("paddingLeft");
        var paddingTop:Number = getStyle("paddingTop");
        var horizontalAlignValue:Number = getHorizontalAlignValue();

        var mw:Number = scaleX > 0 && scaleX != 1 ?
                        minWidth / Math.abs(scaleX) :
                        minWidth;
        var mh:Number = scaleY > 0 && scaleY != 1 ?
                        minHeight / Math.abs(scaleY) :
                        minHeight;

        var w:Number = Math.max(unscaledWidth, mw) - vm.left - vm.right;
        var h:Number = Math.max(unscaledHeight, mh) - vm.top - vm.bottom;
        
        var maxWidth:Number = 0;
                        
        var controlWidth:Number = w - labelWidth - indicatorGap;
        if (controlWidth < 0) 
            controlWidth = 0;
        
        var i:int;
        var child:IUIComponent;
        var childWidth:Number;
        var childHeight:Number;

        // Earlier, the measure function took a guess at the number
        // of columns, but that function didn't know the width of this
        // FormItem.  Now that we know the width, we may discover that the
        // guess was wrong.  In that case, call invalidateSize(), so that
        // we loop back and repeat the measurement phase again.
        //
        // It's possible that we might introduce an infinite loop - the
        // new guess might change the layout, so that the guess once again
        // is found to be wrong.  If we get back here a second time and
        // discover that the guess is still wrong, we'll just live with it.
        var numColumns:int = calcNumColumns(controlWidth);
        var col:int = 0;
        
        if (numColumns != guessedNumColumns && isNaN(explicitWidth))
        {
            if (numberOfGuesses < 2)
            {
                // try again where third one's a charm
                // we actually pick 3 for a real reason.
                // numColumns is either 1,2, or numChildren
                guessedRowWidth = controlWidth;
                numberOfGuesses++;
                invalidateSize();
                return;
            }
            else
            {
                // make best of what we got
                // we use our old guess b/c that's what we
                // measured() for
                numColumns = guessedNumColumns;
                numberOfGuesses = 0;
            }
        }
        else
        {
            numberOfGuesses = 0;
        }
        
        var left:Number = paddingLeft + labelWidth + indicatorGap;
        var top:Number = paddingTop;
        var x:Number = left;
        var y:Number = top;
        
        var wPref:Number;
        var hPref:Number;
        var percentWidth:Number;
        var percentHeight:Number;

        var numChildrenWithOwnSpace:int = numChildren;
        for (i = 0; i < numChildren; i++)
        {
            if (!IUIComponent(getChildAt(i)).includeInLayout)
                numChildrenWithOwnSpace--;
        }

        // Special case for single row - use the HBox layout algorithm.
        if (numColumns == numChildrenWithOwnSpace)
        {
            var excessSpace:Number = Flex.flexChildWidthsProportionally(
                this, controlWidth - (numChildrenWithOwnSpace - 1) * horizontalGap, h);

            left += (excessSpace * horizontalAlignValue);

            for (i = 0; i < numChildren; i++)
            {
                child = getLayoutChildAt(i);
                
                if (!child.includeInLayout)
                    continue;
                
                child.move(Math.floor(left), top);
                left += child.width + horizontalGap;
            }
        }
        else
        {
            // We need to determine the column width.  We do this by 
            // determining the widest child.  This time we take into
            // account percentages (in calcNumColumns we don't b/c we
            // don't know what controlWidth will be)
            for (i = 0; i < numChildren; i++)
            {
                child = getLayoutChildAt(i);
                
                if (!child.includeInLayout)
                    continue;
                
                wPref = child.getExplicitOrMeasuredWidth();
                percentWidth = child.percentWidth;
                
                childWidth = !isNaN(percentWidth) ? (percentWidth*controlWidth)/100 : wPref;
                childWidth = Math.max(child.minWidth, Math.min(child.maxWidth, childWidth));
                
                maxWidth = Math.max(maxWidth, childWidth);
            }
            
            // need to make sure we didn't overstep our bounds,
            // and we need to account for horizontalGap with maxWidth
            maxWidth = Math.min(maxWidth, Math.floor((controlWidth - 
                            ((numColumns-1) * horizontalGap))/numColumns))

            // Determine the left side for the columns:
            // (left over space * horizontalAlignValue)
            var widthSlop:Number = controlWidth -
                (numColumns * maxWidth + (numColumns - 1) * horizontalGap);
            if (widthSlop < 0)
                widthSlop = 0;

            left += (widthSlop * horizontalAlignValue);

            var rowPercentHeight:Number = 0;
            var rowMaxHeight:Number = 0;
            var totalPercentHeight:Number = 0;
            var heightSpaceForChildren:Number = h;
            var heightSpaceToDistribute:Number = heightSpaceForChildren;
            col = 0;

            // Place the children in columns
            // need to figure out spacePerPercent for height first.
            // Loop through all children and take into account
            // the fixed height and the percentage height for each row
            for (i = 0; i < numChildren; i++)
            {
                child = getLayoutChildAt(i);
                
                if (!child.includeInLayout)
                {
                    // need to make sure not done with the row b/c then need to do stuff
                    if (i == numChildren - 1)
                    {
                        heightSpaceToDistribute -= rowMaxHeight;
                    
                        // if not on last row, take into account verticalGap
                        if (i != (numChildren-1))
                            heightSpaceToDistribute -= verticalGap;
                        
                        // discount some of the percent height if there's fixed height in same row
                        if (rowMaxHeight > 0 && rowPercentHeight > 0)
                        {
                            rowPercentHeight = Math.max(0, rowPercentHeight - 
                                        (100*rowMaxHeight)/heightSpaceForChildren);
                        }
                        
                        totalPercentHeight += rowPercentHeight;
                        
                        rowMaxHeight = 0;
                        rowPercentHeight = 0;
                        col = 0;
                    }
                    continue;
                }
                
                if (!isNaN(child.percentHeight))
                {
                    rowPercentHeight = Math.max(rowPercentHeight,
                                child.percentHeight);
                }
                else
                {
                    rowMaxHeight = Math.max(rowMaxHeight,
                            child.getExplicitOrMeasuredHeight());
                }
             
                // if done with the row, sum up the height totals   
                if (++col >= numColumns || i == numChildren - 1)
                {
                    heightSpaceToDistribute -= rowMaxHeight;
                    
                    // if not on last row, take into account verticalGap
                    if (i != (numChildren-1))
                        heightSpaceToDistribute -= verticalGap;
                    
                    // discount some of the percent height if there's fixed height in same row
                    if (rowMaxHeight > 0 && rowPercentHeight > 0)
                    {
                        rowPercentHeight = Math.max(0, rowPercentHeight - 
                                    (100*rowMaxHeight)/heightSpaceForChildren);
                    }
                    
                    totalPercentHeight += rowPercentHeight;
                    
                    rowMaxHeight = 0;
                    rowPercentHeight = 0;
                    col = 0;
                }
            }
                
            var done:Boolean = false;
            
            // Continue as long as there are some remaining flexible children.
            // The "done" flag isn't strictly necessary, except that it catches
            // cases where round-off error causes totalPercent to not exactly
            // equal zero.
            
            // explicitHeightChildren is for storing explicitly set heights
            // because of a max/min problem.  By default, everything is set to 
            // -1, which means to look at the child's own height (may 
            // be explicitHeight or based on percentHeight).  If it's not
            // -1, then use the value in explicitHeightChildren as it's
            // either the max or min height the child can be.
            var explicitHeightChildren:Array = new Array(numChildren);
            for (i = 0; i < numChildren; i++)
            {
                explicitHeightChildren[i] = -1;
            }
            
            // We now do something a little tricky so that we can 
            // support partial filling of the space. If our total
            // percent < 100% then we can trim off some space.
            var unused:Number = heightSpaceToDistribute -
                                (heightSpaceForChildren * totalPercentHeight / 100);
            if (unused > 0)
                heightSpaceToDistribute -= unused;
            
            do
            {
                done = true; // we are optimistic
                
                // Space for flexible children is the total amount of space
                // available minus the amount of space consumed by non-flexible
                // components.Divide that space in proportion to the percent
                // of the child
                var heightSpacePerPercent:Number = heightSpaceToDistribute / totalPercentHeight;
                
                col = 0;
                x = left;
                y = top;
                var rowMaxChildHeight:Number = 0;
                
                // Attempt to divide out the space using our percent amounts,
                // if we hit its limit then that control becomes 'non-flexible'
                // and we run the whole space to distribute calculation again.
                for (i = 0; i < numChildren; i++)
                {
                    child = getLayoutChildAt(i);
                    
                    if (!child.includeInLayout)
                        continue;
                
                    wPref = child.getExplicitOrMeasuredWidth();
                    hPref = child.getExplicitOrMeasuredHeight();
                    percentWidth = child.percentWidth;
                    percentHeight = child.percentHeight;
                    
                    // childWidth can't exceed maxWidth (columnWidth) or it's own max/min widths
                    childWidth = Math.min(maxWidth, 
                        !isNaN(percentWidth) ? (percentWidth*controlWidth)/100 : wPref);
                    childWidth = Math.max(child.minWidth, Math.min(child.maxWidth, childWidth));
                    
                    // if the child has been explicitely sized b/c of a max/min issue
                    // from a previous run, then use that.  Otherwise, ask the child for
                    // it's height.
                    if (explicitHeightChildren[i] != -1)
                    {
                        childHeight = explicitHeightChildren[i];
                    }
                    else
                    {
                        childHeight = !isNaN(percentHeight) ?
                            percentHeight*heightSpacePerPercent : hPref;
                    
                        // If our flexiblity calc say grow/shrink more than we are
                        // allowed, then we grow/shrink whatever we can, remove
                        // ourselves from the array (with explicitHeightChildren)
                        // for the next pass, and start
                        // the loop over again so that the space that we weren't
                        // able to consume / release can be re-used by others.
                        if (childHeight < child.minHeight)
                        {
                            childHeight = child.minHeight;
                            totalPercentHeight -= child.percentHeight;
                            heightSpaceToDistribute -= childHeight;
                            
                            explicitHeightChildren[i] = childHeight;
                            done = false;
                            break;
                        }
                        else if (childHeight > child.maxHeight)
                        {
                            childHeight = child.maxHeight;
                            totalPercentHeight -= child.percentHeight;
                            heightSpaceToDistribute -= childHeight;
                            
                            explicitHeightChildren[i] = childHeight;
                            done = false;
                            break;
                        }
                    }
                    
                    // All is well, let's carry on...
                    
                    if (child.scaleX == 1 && child.scaleY == 1)
                    {
                        child.setActualSize(Math.floor(childWidth),
                                            Math.floor(childHeight));
                    }
                    else
                    {
                        child.setActualSize(childWidth, childHeight);
                    }
                    
                    // horizontal align all of controlWidth and also children within each column
                    var xOffset:Number = (maxWidth - child.width) * horizontalAlignValue;
                    child.move(Math.floor(x + xOffset), Math.floor(y));
                    
                    rowMaxChildHeight = Math.max(rowMaxChildHeight, child.height);
    
                    if (++col >= numColumns)
                    {
                        x = left;
                        col = 0;
                        y += rowMaxChildHeight + verticalGap;
                        rowMaxChildHeight = 0;
                    }
                    else
                    {
                        x += maxWidth + horizontalGap;
                    }
                }
            } 
            while (!done);
        }
    }
    
    /**
     *  @private
     */
    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged(styleProp);
            
        var allStyles:Boolean = styleProp == null || styleProp == "styleName";
   
        if (allStyles || styleProp == "labelStyleName")
        {
            if (labelObj)
            {
            	var labelStyleName:String = getStyle("labelStyleName");

	            if (labelStyleName)
	            {
	                var styleDecl:CSSStyleDeclaration =
	                	styleManager.getMergedStyleDeclaration("." + labelStyleName);
	            
	                if (styleDecl)
	                {
	                    labelObj.styleDeclaration = styleDecl;
	                    labelObj.regenerateStyleCache(true);
	                }
	            }
            } 
        }
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

     /**
     *  @private
     */
    internal function getPreferredLabelWidth():Number
    {
        if (!label || label == "")
            return 0;

        if (isNaN(labelObj.measuredWidth))
            labelObj.validateSize();
        
        var labelWidth:Number = labelObj.measuredWidth;

        if (isNaN(labelWidth))
            return 0;

        return labelWidth;
    }

    /**
     *  @private
     */
    private function calculateLabelWidth():Number
    {
        var labelWidth:Number = getStyle("labelWidth");

        // labelWidth of 0 is the same as NaN
        if (labelWidth == 0)
            labelWidth = NaN;

        if (isNaN(labelWidth) && parent is Form)
            labelWidth = Form(parent).calculateLabelWidth();

        if (isNaN(labelWidth))
            labelWidth = getPreferredLabelWidth();

        return labelWidth;
    }

    /**
     *  @private
     */
    private function calcNumColumns(w:Number):int
    {
        var totalWidth:Number = 0;
        var maxChildWidth:Number = 0;
        var horizontalGap:Number = getStyle("horizontalGap");

        if (direction != FormItemDirection.HORIZONTAL)
            return 1;

        var numChildrenWithOwnSpace:Number = numChildren;
        
        for (var i:int = 0; i < numChildren; i++)
        {
            var child:IUIComponent = getLayoutChildAt(i);
            
            if (!child.includeInLayout)
            {
                numChildrenWithOwnSpace--;
                continue;
            }
            
            var childWidth:Number = child.getExplicitOrMeasuredWidth();

            maxChildWidth = Math.max(maxChildWidth, childWidth);
            totalWidth += childWidth;
            if (i > 0)
                totalWidth += horizontalGap;
        }

        // See if everything can fit in a single row
        if (isNaN(w) || totalWidth <= w)
            return numChildrenWithOwnSpace;

        // if the width is enough to contain two children use two columns
        if (maxChildWidth*2 <= w)
            return 2;

        // Default is single column
        return 1;
    }

    /**
     *  @private
     */
    private function displayIndicator(xPos:Number, yPos:Number):void
    {
        if (required)
        {
            if (!indicatorObj)
            {
                var indicatorClass:Class = getStyle("indicatorSkin") as Class;
                indicatorObj = IFlexDisplayObject(new indicatorClass());
                rawChildren.addChild(DisplayObject(indicatorObj));
            }

            indicatorObj.x =
                xPos + ((getStyle("indicatorGap") - indicatorObj.width) / 2);
            
            if (labelObj)
            {
                indicatorObj.y = yPos +
                    (labelObj.getExplicitOrMeasuredHeight() -
                     indicatorObj.measuredHeight) / 2;
            }
        }
        else
        {
            if (indicatorObj)
            {
                rawChildren.removeChild(DisplayObject(indicatorObj));
                indicatorObj = null;
            }
        }
    }

    /**
     *  @private
     *  Returns a numeric value for the align setting.
     *  0 = left/top, 0.5 = center, 1 = right/bottom
     */
    mx_internal function getHorizontalAlignValue():Number
    {
        var horizontalAlign:String = getStyle("horizontalAlign");

        if (horizontalAlign == "center")
            return 0.5;

        else if (horizontalAlign == "right")
            return 1;

        // default = left
        return 0;
    }
    
}

}
