////////////////////////////////////////////////////////////////////////////////
//
//  ADOBE SYSTEMS INCORPORATED
//  Copyright 2004-2007 Adobe Systems Incorporated
//  All Rights Reserved.
//
//  NOTICE: Adobe permits you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////

package mx.containers
{

import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextLineMetrics;
import flash.utils.getQualifiedClassName;
import mx.automation.IAutomationObject;
import mx.containers.utilityClasses.BoxLayout;
import mx.containers.utilityClasses.CanvasLayout;
import mx.containers.utilityClasses.ConstraintColumn;
import mx.containers.utilityClasses.ConstraintRow;
import mx.containers.utilityClasses.IConstraintLayout;
import mx.containers.utilityClasses.Layout;
import mx.controls.Button;
import mx.core.Container;
import mx.core.ContainerLayout;
import mx.core.EdgeMetrics;
import mx.core.EventPriority;
import mx.core.IFlexDisplayObject;
import mx.core.IFlexModuleFactory;
import mx.core.IFontContextComponent;
import mx.core.IUIComponent;
import mx.core.IUITextField;
import mx.core.UIComponent;
import mx.core.UIComponentCachePolicy;
import mx.core.UITextField;
import mx.core.UITextFormat;
import mx.core.mx_internal;
import mx.effects.EffectManager;
import mx.events.CloseEvent;
import mx.events.SandboxMouseEvent;
import mx.managers.ISystemManager;
import mx.styles.ISimpleStyleClient;
import mx.styles.IStyleClient;
import mx.styles.StyleProxy;

use namespace mx_internal;

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

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

/**
 *  Alpha of the title bar, control bar and sides of the Panel.
 *
 *  The default value for the Halo theme is <code>0.4</code>.
 *  The default value for the Spark theme is <code>0.5</code>.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="borderAlpha", type="Number", inherit="no", theme="halo, spark")]

/**
 *  Thickness of the bottom border of the Panel control.
 *  If this style is not set and the Panel control contains a ControlBar
 *  control, the bottom border thickness equals the thickness of the top border
 *  of the panel; otherwise the bottom border thickness equals the thickness
 *  of the left border.
 *
 *  @default NaN
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="borderThicknessBottom", type="Number", format="Length", inherit="no", theme="halo")]

/**
 *  Thickness of the left border of the Panel.
 *
 *  @default 10
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="borderThicknessLeft", type="Number", format="Length", inherit="no", theme="halo")]

/**
 *  Thickness of the right border of the Panel.
 *
 *  @default 10
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="borderThicknessRight", type="Number", format="Length", inherit="no", theme="halo")]

/**
 *  Thickness of the top border of the Panel.
 *
 *  @default 2
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="borderThicknessTop", type="Number", format="Length", inherit="no", theme="halo")]

/**
 *  Name of the CSS style declaration that specifies styles to apply to 
 *  any control bar child subcontrol.
 * 
 *  @default null
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="controlBarStyleName", type="String", inherit="no")]

/**
 *  Radius of corners of the window frame.
 *
 *  The default value for the Halo theme is <code>4</code>.
 *  The default value for the Spark theme is <code>0</code>.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="cornerRadius", type="Number", format="Length", inherit="no", theme="halo, spark")]

/**
 *  Boolean property that controls the visibility
 *  of the Panel container's drop shadow.
 *
 *  @default true
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="dropShadowEnabled", type="Boolean", inherit="no", theme="halo")]

/**
 *  Array of two colors used to draw the footer
 *  (area for the ControlBar container) background. 
 *  The first color is the top color. 
 *  The second color is the bottom color.
 *  The default values are <code>null</code>, which
 *  makes the control bar background the same as
 *  the panel background.
 *
 *  @default null
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="footerColors", type="Array", arrayType="uint", format="Color", inherit="yes", theme="halo")]

/**
 *  Array of two colors used to draw the header.
 *  The first color is the top color.
 *  The second color is the bottom color.
 *  The default values are <code>null</code>, which
 *  makes the header background the same as the
 *  panel background.
 *
 *  @default null
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerColors", type="Array", arrayType="uint", format="Color", inherit="yes", theme="halo")]

/**
 *  Height of the header.
 *  The default value is based on the style of the title text.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerHeight", type="Number", format="Length", inherit="no")]

/**
 *  Alphas used for the highlight fill of the header.
 *
 *  @default [0.3,0]
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="highlightAlphas", type="Array", arrayType="Number", inherit="no", theme="halo")]

/**
 *  Number of pixels between the container's lower border
 *  and 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 top border
 *  and 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")]

/**
 *  Flag to enable rounding for the bottom two corners of the container.
 *  Does not affect the upper two corners, which are normally round. 
 *  To configure the upper corners to be square, 
 *  set <code>cornerRadius</code> to 0.
 *
 *  @default false
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="roundedBottomCorners", type="Boolean", inherit="no", theme="halo")]

/**
 *  Direction of drop shadow.
 *  Possible values are <code>"left"</code>, <code>"center"</code>,
 *  and <code>"right"</code>.
 *
 *  @default "center"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="shadowDirection", type="String", enumeration="left,center,right", inherit="no", theme="halo")]

/**
 *  Distance of drop shadow.
 *  Negative values move the shadow above the panel.
 *
 *  @default 2
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="shadowDistance", type="Number", format="Length", inherit="no", theme="halo")]

/**
 *  Style declaration name for the status in the title bar.
 *
 *  @default "windowStatus"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
 
[Style(name="statusStyleName", type="String", inherit="no")]

/**
 *  The title background skin.
 *
 *  The default value for the Halo theme is <code>mx.skins.halo.TitleBackground</code>.
 *  The default value for the Spark theme is <code>mx.core.UIComponent</code>.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="titleBackgroundSkin", type="Class", inherit="no")]

/**
 *  Style declaration name for the text in the title bar.
 *  The default value is <code>"windowStyles"</code>,
 *  which causes the title to have boldface text.
 *
 *  @default "windowStyles"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="titleStyleName", type="String", inherit="no")]

//--------------------------------------
//  Effects
//--------------------------------------

/**
 *  Specifies the effect to play after a Resize effect finishes playing.
 *  To disable the default Dissolve effect, so that the children are hidden
 *  instantaneously, set the value of the
 *  <code>resizeEndEffect</code> property to <code>"none"</code>.  
 *
 *  @default "Dissolve"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Effect(name="resizeEndEffect", event="resizeEnd")]

/**
 *  Specifies the effect to play before a Resize effect begins playing.
 *  To disable the default Dissolve effect, so that the children are hidden
 *  instantaneously, set the value of the
 *  <code>resizeStartEffect</code> property to <code>"none"</code>.  
 *
 *  @default "Dissolve"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Effect(name="resizeStartEffect", event="resizeStart")]

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

[AccessibilityClass(implementation="mx.accessibility.PanelAccImpl")]

[IconFile("Panel.png")]

[Alternative(replacement="spark.components.Panel", since="4.0")]

/**
 *  A Halo Panel container consists of a title bar, a caption, a border,
 *  and a  content area for its children.
 *  Typically, you use Panel containers to wrap top-level application modules.
 *  For example, you could include a shopping cart in a Panel container.
 * 
 *  <p><b>Note:</b> Adobe recommends that, when possible, you use the 
 *  Spark Panel container instead of the Halo Panel container.</p>
 *
 *  <p>The Panel container has the following default sizing characteristics:</p>
 *     <table class="innertable">
 *        <tr>
 *           <th>Characteristic</th>
 *           <th>Description</th>
 *        </tr>
 *        <tr>
 *           <td>Default size</td>
 *           <td>Height is large enough to hold all of its children at the default height of the children, 
 *               plus any vertical gaps between the children, the top and bottom padding, the top and bottom borders, 
 *               and the title bar.<br/>
 *               Width is the larger of the default width of the widest child plus the left and right padding of the 
 *               container, or the width of the title text, plus the border.</td>
 *        </tr>
 *        <tr>
 *           <td>Padding</td>
 *           <td>4 pixels for the top, bottom, left, and right values.</td>
 *        </tr>
 *     </table>
 *
 *  @mxml
 *  
 *  <p>The <code>&lt;mx:Panel&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *  
 *  <pre>
 *  &lt;mx:Panel
 *   <strong>Properties</strong>
 *   layout="vertical|horizontal|absolute"
 *   status=""
 *   title=""
 *   titleIcon="null"
 *  
 *   <strong>Styles</strong>
 *   borderAlpha="0.4"
 *   borderThicknessBottom="NaN"
 *   borderThicknessLeft="10"
 *   borderThicknessRight="10"
 *   borderThicknessTop="2"
 *   controlBarStyleName="null"
 *   cornerRadius="4"
 *   dropShadowEnabled="true|false"
 *   footerColors="null"
 *   headerColors="null"
 *   headerHeight="<i>Based on style of title</i>"
 *   highlightAlphas="[0.3,0]"
 *   horizontalAlign="left|center|right"
 *   horizontalGap="8"
 *   modalTransparency="0.5"
 *   modalTransparencyBlur="3"
 *   modalTransparencyColor="#DDDDDD"
 *   modalTransparencyDuration="100"
 *   paddingBottom="0"
 *   paddingTop="0"
 *   roundedBottomCorners="false|true"
 *   shadowDirection="center|left|right"
 *   shadowDistance="2"
 *   statusStyleName="windowStatus"
 *   titleBackgroundSkin="TitleBackground"
 *   titleStyleName="windowStyles"
 *   verticalAlign="top|middle|bottom"
 *   verticalGap="6"
 *  
 *   <strong>Effects</strong>
 *   resizeEndEffect="Dissolve"
 *   resizeStartEffect="Dissolve"
 *   &gt;
 *      ...
 *      <i>child tags</i>
 *      ...
 *  &lt;/mx:Panel&gt;
 *  </pre>
 *  
 *  @includeExample examples/SimplePanelExample.mxml
 *
 *  @see spark.components.Panel
 *  @see mx.containers.ControlBar
 *  @see mx.containers.VBox
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class Panel extends Container
    implements IConstraintLayout, IFontContextComponent
{
    include "../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Class constants
    //
    //--------------------------------------------------------------------------

    /**
     *  @private 
     */
    private static const HEADER_PADDING:Number = 14;

    //--------------------------------------------------------------------------
    //
    //  Class mixins
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Placeholder for mixin by PanelAccImpl.
     */
    mx_internal static var createAccessibilityImplementation:Function;

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

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

        // If the user hasn't explicitly set a resizeStartEffect
        // or resizeEndEffect for this Panel, then we want to use
        // the Dissolve effect (which is specified in the Panel's
        // style sheet). Unfortunately, there's no automated mechanism
        // to hook up the EffectManager, so I need to do that here.
        // Also see the comment in defaults.css.
        addEventListener("resizeStart", EffectManager.eventHandler,
                         false, EventPriority.EFFECT);
        addEventListener("resizeEnd", EffectManager.eventHandler,
                         false, EventPriority.EFFECT);

        layoutObject = new BoxLayout();
        layoutObject.target = this;
        
        showInAutomationHierarchy = true;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private var layoutObject:Layout;

    /**
     *  @private
     *  Is there a close button? Panel itself never has one,
     *  but its subclass TitleWindow can set this flag to true.
     */
    mx_internal var _showCloseButton:Boolean = false;

    /**
     *  @private
     *  A reference to this Panel container's title bar skin.
     *  This is a child of the titleBar.
     */
    mx_internal var titleBarBackground:IFlexDisplayObject;

    /**
     *  @private
     *  A reference to this Panel container's title icon.
     */
    mx_internal var titleIconObject:Object = null;

    /**
     *  @private
     *  A reference to this Panel container's close button, if any.
     *  This is a sibling of the titleBar, not its child.
     */
    mx_internal var closeButton:Button; 

    /**
     *  @private
     *  true until the component has finished initializing
     */
    private var initializing:Boolean = true;

    /**
     *  @private
     */
    private var panelViewMetrics:EdgeMetrics;

    /**
     *  @private
     *  Horizontal location where the user pressed the mouse button
     *  on the titlebar to start dragging, relative to the original
     *  horizontal location of the Panel.
     */
    private var regX:Number;
    
    /**
     *  @private
     *  Vertical location where the user pressed the mouse button
     *  on the titlebar to start dragging, relative to the original
     *  vertical location of the Panel.
     */
    private var regY:Number;

    /**
     *  @private
     */
    private var checkedForAutoSetRoundedCorners:Boolean;
    
    /** 
     *  @private
     */
    private var autoSetRoundedCorners:Boolean;

    /** 
     *  @private
     */
    private var inCreateComponentsFromDescriptors:Boolean;

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

    //----------------------------------
    //  baselinePosition
    //----------------------------------

    /**
     *  @private
     *  The baselinePosition of a Panel is calculated for its title.
     */
    override public function get baselinePosition():Number
    {
        if (!validateBaselinePosition())
            return NaN;

        return titleBar.y + titleTextField.y + titleTextField.baselinePosition;
    }

    //----------------------------------
    //  cacheAsBitmap
    //----------------------------------

    /**
     *  @private
     */
    override public function set cacheAsBitmap(value:Boolean):void
    {
        super.cacheAsBitmap = value;

        // If we got cached, create the content pane so the content area of
        // this panel gets cached with an opaque background.
        if (cacheAsBitmap && !contentPane
                && cachePolicy != UIComponentCachePolicy.OFF
                && getStyle("backgroundColor"))
        {
            createContentPane();
            invalidateDisplayList();
        }
    }

    //----------------------------------
    //  enabled
    //----------------------------------

    [Inspectable(category="General", enumeration="true,false", defaultValue="true")]

    /**
     *  @private
     */
    override public function set enabled(value:Boolean):void
    {
        super.enabled = value;

        if (titleTextField)
            titleTextField.enabled = value;

        if (statusTextField)
            statusTextField.enabled = value;
        
        if (controlBar)
            controlBar.enabled = value;
        
        if (closeButton)
            closeButton.enabled = value;
    }

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

    //----------------------------------
    //  _closeButtonStyleFilters
    //----------------------------------

   
    private static var _closeButtonStyleFilters:Object = 
    {
        "closeButtonUpSkin" : "closeButtonUpSkin", 
        "closeButtonOverSkin" : "closeButtonOverSkin",
        "closeButtonDownSkin" : "closeButtonDownSkin",
        "closeButtonDisabledSkin" : "closeButtonDisabledSkin",
        "closeButtonSkin" : "closeButtonSkin",
        "repeatDelay" : "repeatDelay",
        "repeatInterval" : "repeatInterval"
    };
    
    /**
     *  The set of styles to pass from the Panel to the close button.
     *  @see mx.styles.StyleProxy
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function get closeButtonStyleFilters():Object
    {
        return _closeButtonStyleFilters;
    }

    //----------------------------------
    //  constraintColumns
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the constraintColumns property.
     */
    private var _constraintColumns:Array = [];

    [ArrayElementType("mx.containers.utilityClasses.ConstraintColumn")]
    [Inspectable(arrayType="mx.containers.utilityClasses.ConstraintColumn")]
    
    /**
     *  @copy mx.containers.utilityClasses.IConstraintLayout#constraintColumns
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get constraintColumns():Array
    {
        return _constraintColumns;
    }
    
    /**
     *  @private
     */
    public function set constraintColumns(value:Array):void
    {
        if (value != _constraintColumns)
        {
            var n:int = value.length;
            for (var i:int = 0; i < n; i++)
            {
                ConstraintColumn(value[i]).container = this;
            }
            _constraintColumns = value;

            invalidateSize();
            invalidateDisplayList();
        }
    }

    //----------------------------------
    //  constraintRows
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the constraintRows property.
     */
    private var _constraintRows:Array = [];
    
    [ArrayElementType("mx.containers.utilityClasses.ConstraintRow")]
    [Inspectable(arrayType="mx.containers.utilityClasses.ConstraintRow")]
    
    /**
     *  @copy mx.containers.utilityClasses.IConstraintLayout#constraintRows
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get constraintRows():Array
    {
        return _constraintRows;
    }
    
    /**
     *  @private
     */
    public function set constraintRows(value:Array):void
    {
        if (value != _constraintRows)
        {
            var n:int = value.length;
            for (var i:int = 0; i < n; i++)
            {
                ConstraintRow(value[i]).container = this;
            }
            _constraintRows = value;

            invalidateSize();
            invalidateDisplayList();
        }
    }        
       
    //----------------------------------
    //  controlBar
    //----------------------------------

    /**
     *  A reference to this Panel container's control bar, if any.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var controlBar:IUIComponent;
    
    /**
     *  Proxy to the controlBar property which is protected and can't be accessed externally
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal function get _controlBar():IUIComponent
    {
        return controlBar;
    }
        
    //----------------------------------
    //  fontContext
    //----------------------------------
    
    /**
     *  @inheritDoc 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get fontContext():IFlexModuleFactory
    {
        return moduleFactory;
    }

    /**
     *  @private
     */
    public function set fontContext(moduleFactory:IFlexModuleFactory):void
    {
        this.moduleFactory = moduleFactory;
    }
        
    //----------------------------------
    //  layout
    //----------------------------------

    /**
     *  @private
     *  Storage for the layout property.
     */
    private var _layout:String = ContainerLayout.VERTICAL;

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

    /**
     *  Specifies the layout mechanism used for this container. 
     *  Panel containers can use <code>"vertical"</code>, <code>"horizontal"</code>, 
     *  or <code>"absolute"</code> positioning. 
     *  Vertical positioning lays out the child components vertically from
     *  the top of the container to the bottom in the specified order.
     *  Horizontal positioning lays out the child components horizontally
     *  from the left of the container to the right in the specified order.
     *  Absolute positioning does no automatic layout and requires you to
     *  explicitly define the location of each child component. 
     *
     *  @default "vertical"
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get layout():String
    {
        return _layout;
    }

    /**
     *  @private
     */
    public function set layout(value:String):void
    {
        if (_layout != value)
        {
            _layout = value;

            if (layoutObject)
                // Set target to null for cleanup.
                layoutObject.target = null;

            if (_layout == ContainerLayout.ABSOLUTE)
                layoutObject = new CanvasLayout();
            else
            {
                layoutObject = new BoxLayout();

                if (_layout == ContainerLayout.VERTICAL)
                    BoxLayout(layoutObject).direction
                        = BoxDirection.VERTICAL;
                else
                    BoxLayout(layoutObject).direction
                        = BoxDirection.HORIZONTAL;
            }

            if (layoutObject)
                layoutObject.target = this;

            invalidateSize();
            invalidateDisplayList();

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

    //----------------------------------
    //  status
    //----------------------------------

    /**
     *  @private
     *  Storage for the status property.
     */
    private var _status:String = "";
    
    /**
     *  @private
     */
    private var _statusChanged:Boolean = false;
    
    [Bindable("statusChanged")]
    [Inspectable(category="General", defaultValue="")]

    /**
     *  Text in the status area of the title bar.
     *
     *  @default ""
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get status():String
    {
        return _status;
    }

    /**
     *  @private
     */
    public function set status(value:String):void
    {
        _status = value;
        _statusChanged = true;
        
        invalidateProperties();
        
        dispatchEvent(new Event("statusChanged"));
    }
    
    //----------------------------------
    //  statusTextField
    //----------------------------------

    /**
     *  The UITextField sub-control that displays the status.
     *  The status field is a child of the <code>titleBar</code> sub-control.
     * 
     *  @see #titleBar
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var statusTextField:IUITextField;

    //----------------------------------
    //  title
    //----------------------------------

    /**
     *  @private
     *  Storage for the title property.
     */ 
    private var _title:String = "";
    
    /**
     *  @private
     */
    private var _titleChanged:Boolean = false;

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

    /**
     *  Title or caption displayed in the title bar.
     *
     *  @default ""
     *
     *  @tiptext Gets or sets the title/caption displayed in the title bar
     *  @helpid 3991
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get title():String
    {
        return _title;
    }

    /**
     *  @private
     */
    public function set title(value:String):void
    {
        _title = value;
        _titleChanged = true;
        
        invalidateProperties();
        invalidateSize();
        invalidateViewMetricsAndPadding();
        
        dispatchEvent(new Event("titleChanged"));
    }
    
    //----------------------------------
    //  titleBar
    //----------------------------------

    /**
     *  The TitleBar sub-control that displays the Panel container's title bar.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var titleBar:UIComponent;

    //----------------------------------
    //  titleIcon
    //----------------------------------

    /**
     *  @private
     *  Storage for the titleIcon property.
     */ 
    private var _titleIcon:Class;
    
    /**
     *  @private
     */
    private var _titleIconChanged:Boolean = false;

    [Bindable("titleIconChanged")]
    [Inspectable(category="General", defaultValue="", format="EmbeddedFile")]

    /**
     *  The icon displayed in the title bar.
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get titleIcon():Class
    {
        return _titleIcon;
    }

    /**
     *  @private
     */
    public function set titleIcon(value:Class):void
    {
        _titleIcon = value;
        _titleIconChanged = true;
        
        invalidateProperties();
        invalidateSize();
        
        dispatchEvent(new Event("titleIconChanged"));
    }

    //----------------------------------
    //  titleTextField
    //----------------------------------

    /**
     *  The UITextField sub-control that displays the title.
     *  The title field is a child of the <code>titleBar</code> sub-control.
     * 
     *  @see #titleBar
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var titleTextField:IUITextField;

    //----------------------------------
    //  usePadding
    //----------------------------------

    /**
     *  @private
     */
    override mx_internal function get usePadding():Boolean
    {
        // We use margins for all layouts except absolute.
        return layout != ContainerLayout.ABSOLUTE;
    }

    //----------------------------------
    //  viewMetrics
    //----------------------------------

    //--------------------------------------------------------------------------
    //
    //  Overridden methods: DisplayObjectContainer
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override public function getChildIndex(child:DisplayObject):int
    {
        // This override of getChildIndex() fixes a bug #116637.
        // The FocusManager incorrectly calls this function for the controlBar
        // with isContentAPI as true.  But it's really our fault, because we
        // first add the controlBar as a child (so it gets into the
        // FocusManager's list of focusable objects) and then abduct it.  This,
        // in combination with the contentPane, leads to a runtime error.
        // Simply returning numChildren (meaning "after last child") is
        // harmless and resolves the issue.
        if (controlBar && child == controlBar)
            return numChildren;
        else
            return super.getChildIndex(child);
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden methods: UIComponent
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override protected function initializeAccessibility():void
    {
        if (Panel.createAccessibilityImplementation != null)
            Panel.createAccessibilityImplementation(this);
    }

    /**
     *  @private
     *  Create child objects.
     */
    override protected function createChildren():void
    {
        super.createChildren();

        // Create the title bar over the top of the floating border.
        if (!titleBar)
        {
            titleBar = new UIComponent();
            titleBar.visible = false;
        
            titleBar.addEventListener(MouseEvent.MOUSE_DOWN,
                                      titleBar_mouseDownHandler);

            rawChildren.addChild(titleBar);
        }

        // Create the titleBarBackground as a child of the titleBar.
        if (!titleBarBackground)
        {
            var titleBarBackgroundClass:Class =
                getStyle("titleBackgroundSkin");
            if (titleBarBackgroundClass)
            {
                titleBarBackground = new titleBarBackgroundClass();

                var backgroundUIComponent:IStyleClient =
                    titleBarBackground as IStyleClient;     
                if (backgroundUIComponent)
                {
                    backgroundUIComponent.setStyle("backgroundImage",
                                                   undefined);
                }

                var backgroundStyleable:ISimpleStyleClient =
                    titleBarBackground as ISimpleStyleClient;
                if (backgroundStyleable)
                    backgroundStyleable.styleName = this;

                titleBar.addChild(DisplayObject(titleBarBackground));
            }
        }

        createTitleTextField(-1);
        createStatusTextField(-1);
        
        // Create the closeButton as a child of the titleBar.
        if (!closeButton)
        {
            closeButton = new Button();
            closeButton.styleName = new StyleProxy(this, closeButtonStyleFilters);

            closeButton.upSkinName = "closeButtonUpSkin";
            closeButton.overSkinName = "closeButtonOverSkin";
            closeButton.downSkinName = "closeButtonDownSkin";
            closeButton.disabledSkinName = "closeButtonDisabledSkin";
            closeButton.skinName = "closeButtonSkin";
            closeButton.explicitWidth = closeButton.explicitHeight = 16;
            
            closeButton.focusEnabled = false;
            closeButton.visible = false;
            closeButton.enabled = enabled;
            
            closeButton.addEventListener(MouseEvent.CLICK,
                                          closeButton_clickHandler);

            // Add the close button on top of the title/status.
            titleBar.addChild(closeButton);
            closeButton.owner = this;
        }
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();

        if (hasFontContextChanged())
        {
            // Re-create the text fields in case the new font
            // is in a  different SWF then the current one.
            var childIndex:int;
            if (titleTextField)
            {
                childIndex = titleBar.getChildIndex(DisplayObject(titleTextField));
                removeTitleTextField();
                createTitleTextField(childIndex);
                
                _titleChanged = true;
            }
            
            if (statusTextField)
            {
                childIndex = titleBar.getChildIndex(DisplayObject(statusTextField));
                removeStatusTextField();
                createStatusTextField(childIndex);
                
                _statusChanged = true;
            }
        }
      
        if (_titleChanged)
        {
            _titleChanged = false;
            titleTextField.text = _title;
            
            // Don't call layoutChrome() if we  haven't initialized,
            // because it causes commit/measure/layout ordering problems
            // for children of the control bar.
            if (initialized)
                layoutChrome(unscaledWidth, unscaledHeight);
        }

        if (_titleIconChanged)
        {
            _titleIconChanged = false;

            if (titleIconObject)
            {
                titleBar.removeChild(DisplayObject(titleIconObject));
                titleIconObject = null;
            }

            if (_titleIcon)
            {
                titleIconObject = new _titleIcon();
                titleBar.addChild(DisplayObject(titleIconObject));
            }

            // Don't call layoutChrome() if we  haven't initialized,
            // because it causes commit/measure/layout ordering problems
            // for children of the control bar.
            if (initialized)
                layoutChrome(unscaledWidth, unscaledHeight);
        }
        
        if (_statusChanged)
        {
            _statusChanged = false;
            statusTextField.text = _status;
            
            // Don't call layoutChrome() if we  haven't initialized,
            // because it causes commit/measure/layout ordering problems
            // for children of the control bar.
            if (initialized)
                layoutChrome(unscaledWidth, unscaledHeight);
        }
    }
    
    /**
     *  Calculates the default mininum and maximum sizes
     *  of the Panel container.
     *  For more information
     *  about the <code>measure()</code> method, see the <code>
     *  UIComponent.measure()</code> method.
     *
     *  <p>The <code>measure()</code> method first calls
     *  <code>VBox.measure()</code> method, and then ensures that the
     *  <code>measuredWidth</code> and
     *  <code>measuredMinWidth</code> properties are wide enough
     *  to display the title and the ControlBar.</p>
     * 
     *  @see mx.core.UIComponent#measure()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */ 
    override protected function measure():void
    {
        super.measure();

        layoutObject.measure();

        var textSize:Rectangle = measureHeaderText();
        var textWidth:Number = textSize.width;
        var textHeight:Number = textSize.height;
        
        var bm:EdgeMetrics = EdgeMetrics.EMPTY;
        textWidth += bm.left + bm.right;    
        
        var offset:Number = 5;
        textWidth += offset * 2;

        if (titleIconObject)
            textWidth += titleIconObject.width;
        
        if (closeButton)
            textWidth += closeButton.getExplicitOrMeasuredWidth() + 6;

        measuredMinWidth = Math.max(textWidth, measuredMinWidth);
        measuredWidth = Math.max(textWidth, measuredWidth);
        
        if (controlBar && controlBar.includeInLayout)
        {
            var controlWidth:Number = controlBar.getExplicitOrMeasuredWidth() +
                                      bm.left + bm.right;
            
            measuredWidth =
                Math.max(measuredWidth, controlWidth);
        }
    }       
    
    /**
     *  @private
     *  Draw by making everything visible, then laying out.
     */
    override protected function updateDisplayList(unscaledWidth:Number,
                                                  unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);

        layoutObject.updateDisplayList(unscaledWidth, unscaledHeight);

        if (border)
            border.visible = true;
        titleBar.visible = true;            
    }

    /**
     *  @private
     */
    override public function styleChanged(styleProp:String):void
    {
        var allStyles:Boolean = !styleProp || styleProp == "styleName";
        
        super.styleChanged(styleProp);
        
        if (allStyles || styleProp == "titleStyleName")
        {
            if (titleTextField)
            {
                var titleStyleName:String = getStyle("titleStyleName");
                titleTextField.styleName = titleStyleName;
            }
        }
        
        if (allStyles || styleProp == "statusStyleName")
        {
            if (statusTextField)
            {
                var statusStyleName:String = getStyle("statusStyleName");
                statusTextField.styleName = statusStyleName;
            }
        }
        
        if (allStyles || styleProp == "controlBarStyleName")
        {
            if (controlBar && controlBar is ISimpleStyleClient)
            {
                var controlBarStyleName:String = getStyle("controlBarStyleName");
                ISimpleStyleClient(controlBar).styleName = controlBarStyleName;
            }
        }
        
        if (allStyles || styleProp == "titleBackgroundSkin")
        {
            if (titleBar)
            {
                var titleBackgroundSkinClass:Class =
                    getStyle("titleBackgroundSkin");
                
                if (titleBackgroundSkinClass)
                {
                    // Remove existing background
                    if (titleBarBackground)
                    {
                        titleBar.removeChild(DisplayObject(titleBarBackground));
                        titleBarBackground = null;
                    }
                    
                    titleBarBackground = new titleBackgroundSkinClass();

                    var backgroundUIComponent:IStyleClient =
                        titleBarBackground as IStyleClient;         
                    if (backgroundUIComponent)
                    {
                        backgroundUIComponent.setStyle("backgroundImage",
                                                       undefined);
                    }

                var backgroundStyleable:ISimpleStyleClient =
                    titleBarBackground as ISimpleStyleClient;
                if (backgroundStyleable)
                    backgroundStyleable.styleName = this;

                    titleBar.addChildAt(DisplayObject(titleBarBackground), 0);
                }
            }
        }
    }
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods: Container
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override protected function layoutChrome(unscaledWidth:Number,
                                             unscaledHeight:Number):void
    {
        super.layoutChrome(unscaledWidth, unscaledHeight);
        
        // Special case for the default borderSkin to inset the chrome content
        // by the borderThickness when borderStyle is "solid", "inset" or "outset". 
        // We use getQualifiedClassName to avoid bringing in a dependency on 
        // mx.skins.halo.PanelSkin. 
        var em:EdgeMetrics = EdgeMetrics.EMPTY;
        var bt:Number = getStyle("borderThickness"); 
        if (getQualifiedClassName(border) == "mx.skins.halo::PanelSkin" &&
            getStyle("borderStyle") != "default" && bt) 
        {
            em = new EdgeMetrics(bt, bt, bt, bt);
        }
        
        // Remove the borderThickness from the border metrics,
        // since the header and control bar overlap any solid border.
        var bm:EdgeMetrics = em;      
        
        var x:Number = bm.left;
        var y:Number = bm.top;
        
        var headerHeight:Number = getHeaderHeight();
        if (headerHeight > 0 && height >= headerHeight)
        {
            var titleBarWidth:Number = unscaledWidth - bm.left - bm.right;
            
            showTitleBar(true);
            titleBar.mouseChildren = true;
            titleBar.mouseEnabled = true;
            
            // Draw an invisible rect in the tileBar. This ensures we
            // will get clicks, even if the background is transparent 
            // and there is no title.
            var g:Graphics = titleBar.graphics;
            g.clear();
            g.beginFill(0xFFFFFF, 0);
            g.drawRect(0, 0, titleBarWidth, headerHeight);
            g.endFill();
            
            // Also draw an invisible unfilled rect whose height
            // is the height of the entire Panel, not just the headerHeight.
            // This is for accessibility; the titlebar of the Panel
            // has an AccessibilityImplementation (see PanelAccImpl)
            // which makes it act like a grouping (ROLE_SYSTEM_GROUPING)
            // for the controls inside the panel.
            // Drawing this rect makes the accLocation rect of the grouping
            // enclose the controls inside the grouping,
            // even though it is a sibling of them, not their parent.
            // (This is because the Player doesn't support Sprites
            // with AccessibilityImplementations inside other Sprites
            // with AccessibilityImplementations; the accessible objects
            // in a Flash SWF are a flat list, not a hierarchy.)
            // This rectangle must be unfilled because the titleBar is
            // actually on top of the content area and would otherwise
            // block mouse events to the controls in the Panel.
            g.lineStyle(0, 0x000000, 0);
            g.drawRect(0, 0, titleBarWidth, unscaledHeight);
            
            // Position the titleBar.
            titleBar.move(x, y);
            titleBar.setActualSize(titleBarWidth, headerHeight);

            // Position the titleBarBackground within the titleBar.
            if (titleBarBackground)
            {
                titleBarBackground.move(0, 0);
                IFlexDisplayObject(titleBarBackground).setActualSize(
                    titleBarWidth, headerHeight);
            }

            // Set the close button next to the upper-right corner,
            // offset by the border thickness.
            closeButton.visible = _showCloseButton;
            if (_showCloseButton)
            {
                closeButton.setActualSize(
                    closeButton.getExplicitOrMeasuredWidth(),
                    closeButton.getExplicitOrMeasuredHeight());

                closeButton.move(
                    unscaledWidth - x - bm.right - 10 -
                    closeButton.getExplicitOrMeasuredWidth(),
                    (headerHeight -
                    closeButton.getExplicitOrMeasuredHeight()) / 2);
            }

            var leftOffset:Number = 10;
            var rightOffset:Number = 10;
            var h:Number;
            var offset:Number;

            // Set the position of the title icon.
            if (titleIconObject)
            {
                h = titleIconObject.height;
                offset = (headerHeight - h) / 2;
                titleIconObject.move(leftOffset, offset);
                leftOffset += titleIconObject.width + 4;
            }

            // Set the position of the title text. 
            h = titleTextField.getUITextFormat().measureText(titleTextField.text).height;
            offset = (headerHeight - h) / 2;

            var borderWidth:Number = bm.left + bm.right;            
            titleTextField.move(leftOffset, offset - 1);
            titleTextField.setActualSize(Math.max(0,
                                   unscaledWidth - leftOffset -
                                   rightOffset - borderWidth),
                                   h + UITextField.TEXT_HEIGHT_PADDING);

            // Set the position of the status text.
            h = statusTextField.text != "" ? statusTextField.getUITextFormat().measureText(statusTextField.text).height : 0;
            offset = (headerHeight - h) / 2;
            var statusX:Number = unscaledWidth - rightOffset - 4 -
                                 borderWidth - statusTextField.textWidth;
            if (_showCloseButton)
                statusX -= (closeButton.getExplicitOrMeasuredWidth() + 4);
            statusTextField.move(statusX, offset - 1);
            statusTextField.setActualSize(
                statusTextField.textWidth + 8,
                statusTextField.textHeight + UITextField.TEXT_HEIGHT_PADDING);

            // Make sure the status text isn't too long.
            // We do simple clipping here.
            var minX:Number = titleTextField.x + titleTextField.textWidth + 8;
            if (statusTextField.x < minX)
            {
                // Show as much as we can.
                statusTextField.width = Math.max(statusTextField.width -
                                        (minX - statusTextField.x), 0);
                statusTextField.x = minX;
            }
        }
        else
        {
            if (titleBar)
            {
                showTitleBar(false);                
                titleBar.mouseChildren = false;
                titleBar.mouseEnabled = false;
            }
        }
        
        if (controlBar)
        {
            var cx:Number = controlBar.x;
            var cy:Number = controlBar.y;
            var cw:Number = controlBar.width;
            var ch:Number = controlBar.height;

            controlBar.setActualSize(
                unscaledWidth - (bm.left + bm.right),
                controlBar.getExplicitOrMeasuredHeight());

            controlBar.move(
                bm.left,
                unscaledHeight - bm.bottom -
                controlBar.getExplicitOrMeasuredHeight());

            if (controlBar.includeInLayout)
                // Hide the control bar if it is spilling out.
                controlBar.visible = controlBar.y >= bm.top;

            // If the control bar's position or size changed, redraw.  This
            // fixes a refresh bug (when the control bar vacates some space,
            // the new space appears blank).
            if (cx != controlBar.x ||
                cy != controlBar.y ||
                cw != controlBar.width ||
                ch != controlBar.height)
            {
                invalidateDisplayList();
            }
        }
    }

    /**
     *  @private
     */
    override public function createComponentsFromDescriptors(
                                recurse:Boolean = true):void
    {
        inCreateComponentsFromDescriptors = true;
        super.createComponentsFromDescriptors();
        
        if (numChildren == 0)
        {
            setControlBar(null);
            inCreateComponentsFromDescriptors = false;
            return;
        }
        
        // If the last content child is a ControlBar, change it
        // from being a content child to a chrome child;
        // i.e., move it to the rawChildren collection.
        var lastChild:IUIComponent = IUIComponent(getChildAt(numChildren - 1));
        if (lastChild is ControlBar)
        {
            var oldChildDocument:Object = lastChild.document;
            
            if (contentPane)
            {
                contentPane.removeChild(DisplayObject(lastChild));
            }
            else
            {
                super.removeChild(DisplayObject(lastChild));
            }       
            // Restore the original document. Otherwise, when we re-add the child when the Panel is
            // a custom component, the child will use the custom component as the document instead of
            // using the document in which the child was declared.
            lastChild.document = oldChildDocument;
            rawChildren.addChild(DisplayObject(lastChild));
            setControlBar(lastChild);
        }
        else
        {
            setControlBar(null);
        }
        
        inCreateComponentsFromDescriptors = false;        
    }

    /**
     *  @private
     * 
     *  Container implements addChild in terms of addChildAt. 
     */
    override public function addChildAt(child:DisplayObject,
                                        index:int):DisplayObject
    {
        // Special case for adding the control bar.
        super.addChildAt(child, index);
        if (!inCreateComponentsFromDescriptors &&
            child is ControlBar)
            createComponentsFromDescriptors();
        
        return child;
    }
    
    /**
     *  @private
     * 
     *  Container implements removeChildAt in terms of removeChild.
     */
    override public function removeChild(child:DisplayObject):DisplayObject
    {
        // If the control bar is the last child.
        if (!inCreateComponentsFromDescriptors &&
            child is ControlBar && numChildren > 0 &&
            child == getChildAt(numChildren - 1))
        {
            rawChildren.removeChild(child);
            createComponentsFromDescriptors();
            return child;
        }
        
        return super.removeChild(child);
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Creates the title text field child
     *  and adds it as a child of this component.
     * 
     *  @param childIndex The index of where to add the child.
     *  If -1, the text field is appended to the end of the list.
     */
    mx_internal function createTitleTextField(childIndex:int):void
    {
        // Create the titleTextField as a child of the titleBar.
        if (!titleTextField)
        {
            titleTextField = IUITextField(createInFontContext(UITextField));
            titleTextField.selectable = false;
    
            if (childIndex == -1)
                titleBar.addChild(DisplayObject(titleTextField));
            else 
                titleBar.addChildAt(DisplayObject(titleTextField), childIndex);

            var titleStyleName:String = getStyle("titleStyleName"); 
            titleTextField.styleName = titleStyleName;
            titleTextField.text = title;
            titleTextField.enabled = enabled;
        }
    }

    /**
     *  @private
     *  Removes the title text field from this component.
     */
    mx_internal function removeTitleTextField():void
    {
        if (titleBar && titleTextField)
        {
            titleBar.removeChild(DisplayObject(titleTextField));
            titleTextField = null;
        }
    }
    
    /**
     *  @private
     *  Creates the status text field child
     *  and adds it as a child of this component.
     * 
     *  @param childIndex The index of where to add the child.
     *  If -1, the text field is appended to the end of the list.
     */
    mx_internal function createStatusTextField(childIndex:int):void
    {
        // Create the statusTextField as a child of the titleBar.
        if (titleBar && !statusTextField)
        {
            statusTextField = IUITextField(createInFontContext(UITextField));
            statusTextField.selectable = false;
            
            if (childIndex == -1)
                titleBar.addChild(DisplayObject(statusTextField));                
            else 
                titleBar.addChildAt(DisplayObject(statusTextField), childIndex);

            var statusStyleName:String = getStyle("statusStyleName");
            statusTextField.styleName = statusStyleName;
            statusTextField.text = status;
            statusTextField.enabled = enabled;
        }
    }
    
    /**
     *  @private
     *  Removes the status text field from this component.
     */
    mx_internal function removeStatusTextField():void
    {
        if (titleBar && statusTextField)
        {
            titleBar.removeChild(DisplayObject(statusTextField));
            statusTextField = null;
        }
    }

    /**
     *  @private.
     *  Returns a Rectangle containing the largest piece of header
     *  text (can be either the title or status, whichever is bigger).
     */
    private function measureHeaderText(useDummyString:Boolean = false):Rectangle
    {
        var textWidth:Number = 20;
        var textHeight:Number = 14;

        var textFormat:UITextFormat;
        var metrics:TextLineMetrics;
        
        if (titleTextField && titleTextField.text)
        {
            titleTextField.validateNow();
            textFormat = titleTextField.getUITextFormat();
            metrics = textFormat.measureText(titleTextField.text, false);
            textWidth = metrics.width;
            textHeight = metrics.height;
        }
        else
        {
            if (useDummyString)
            {
                if (titleTextField)
                {
                    textFormat = titleTextField.getUITextFormat();
                    metrics = textFormat.measureText("Wj", false);
                    textWidth = metrics.width;
                    textHeight = metrics.height;
                }
            }
        }
        
        if (statusTextField && statusTextField.text)
        {
            statusTextField.validateNow();
            textFormat = statusTextField.getUITextFormat();
            metrics = textFormat.measureText(statusTextField.text, false);
            textWidth = Math.max(textWidth, metrics.width);
            textHeight = Math.max(textHeight, metrics.height);
        }

        return new Rectangle(0, 0, Math.round(textWidth), Math.round(textHeight));
    }
    
    /**
     *  Returns the height of the header.
     * 
     *  @return The height of the header, in pixels.     
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function getHeaderHeight():Number
    {
        var headerHeight:Number = getStyle("headerHeight");
        
        if (isNaN(headerHeight))
            headerHeight = measureHeaderText().height + HEADER_PADDING;
        
        return headerHeight;
    }
    
    /**
     *  @private
     *  Proxy to getHeaderHeight() for PanelSkin
     *  since we can't change its function signature
     */
    mx_internal function getHeaderHeightProxy(useDummyString:Boolean = false):Number
    {
        var headerHeight:Number = getStyle("headerHeight");
        
        if (isNaN(headerHeight))
            headerHeight = measureHeaderText(useDummyString).height + HEADER_PADDING;
        
        return headerHeight;
    }

    /**
     *  @private
     */
    private function showTitleBar(show:Boolean):void
    {
        titleBar.visible = show;
        
        var n:int = titleBar.numChildren;
        for (var i:int = 0; i < n; i++)
        {
            var child:DisplayObject = titleBar.getChildAt(i);
            child.visible = show;
        }               
    }   

    /**
     *  @private
     */
    private function setControlBar(newControlBar:IUIComponent):void
    {
        if (newControlBar == controlBar)
            return;
            
        controlBar = newControlBar;     
        
        // If roundedBottomCorners is set locally, don't auto-set
        // it when the controlbar is added/removed.
        if (!checkedForAutoSetRoundedCorners)
        {
            checkedForAutoSetRoundedCorners = true;
            autoSetRoundedCorners = styleDeclaration ? 
                    styleDeclaration.getStyle("roundedBottomCorners") === undefined : 
                    true;
        }
        
        if (autoSetRoundedCorners)
            setStyle("roundedBottomCorners", controlBar != null);

        var controlBarStyleName:String = getStyle("controlBarStyleName");
        
        if (controlBarStyleName && controlBar is ISimpleStyleClient)
            ISimpleStyleClient(controlBar).styleName = controlBarStyleName;
        
        if (controlBar)
            controlBar.enabled = enabled;
        if (controlBar is IAutomationObject)
            IAutomationObject(controlBar).showInAutomationHierarchy = false;

        invalidateViewMetricsAndPadding();
        invalidateSize();
        invalidateDisplayList();
    }
    
    /**
     *  Called when the user starts dragging a Panel
     *  that has been popped up by the PopUpManager.
     *
     *  @param event The MouseEvent dispatched when the 
     *  user clicks on the container.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function startDragging(event:MouseEvent):void
    {
        regX = event.stageX - x;
        regY = event.stageY - y;

        var sbRoot:DisplayObject = systemManager.getSandboxRoot();
        sbRoot.addEventListener(
            MouseEvent.MOUSE_MOVE, systemManager_mouseMoveHandler, true);

        sbRoot.addEventListener(
            MouseEvent.MOUSE_UP, systemManager_mouseUpHandler, true);

        sbRoot.addEventListener(
            SandboxMouseEvent.MOUSE_UP_SOMEWHERE, stage_mouseLeaveHandler);

        // add the mouse shield so we can drag over untrusted applications.
        systemManager.deployMouseShields(true);
    }

    /**
     *  Called when the user stops dragging a Panel
     *  that has been popped up by the PopUpManager.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function stopDragging():void
    {
        var sbRoot:DisplayObject = systemManager.getSandboxRoot();
        sbRoot.removeEventListener(
            MouseEvent.MOUSE_MOVE, systemManager_mouseMoveHandler, true);

        sbRoot.removeEventListener(
            MouseEvent.MOUSE_UP, systemManager_mouseUpHandler, true);

        sbRoot.removeEventListener(
            SandboxMouseEvent.MOUSE_UP_SOMEWHERE, stage_mouseLeaveHandler);

        regX = NaN;
        regY = NaN;

        systemManager.deployMouseShields(false);
    }

    /**
     *  @private
     *  Some other components which use a Panel as an internal
     *  subcomponent need access to the title bar,
     *  but can't access the titleBar var because it is protected
     *  and therefore available only to subclasses.
     */
    mx_internal function getTitleBar():UIComponent
    {
        return titleBar;
    }

    /**
     *  @private
     *  Some other components which use a Panel as an internal
     *  subcomponent need access to the UITextField that displays the title,
     *  but can't access the titleTextField var because it is protected
     *  and therefore available only to subclasses.
     */
    mx_internal function getTitleTextField():IUITextField
    {
        return titleTextField;
    }

    /**
     *  @private
     *  Some other components which use a Panel as an internal
     *  subcomponent need access to the UITextField that displays the status,
     *  but can't access the statusTextField var because it is protected
     *  and therefore available only to subclasses.
     */
    mx_internal function getStatusTextField():IUITextField
    {
        return statusTextField;
    }

    /**
     *  @private
     *  Some other components which use a Panel as an internal
     *  subcomponent need access to the control bar,
     *  but can't access the controlBar var because it is protected
     *  and therefore available only to subclasses.
     */
    mx_internal function getControlBar():IUIComponent
    {
        return controlBar;
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private function titleBar_mouseDownHandler(event:MouseEvent):void
    {
        // A mouseDown on the closeButton will bubble up to the titleBar,
        // but it shouldn't start a drag; it should simply start the
        // normal mouse/Button interaction.
        if (event.target == closeButton)
            return;

        if (enabled && isPopUp && isNaN(regX))
            startDragging(event);
    }

    /**
     *  @private
     */
    private function systemManager_mouseMoveHandler(event:MouseEvent):void
    {
        // during a drag, only the Panel should get mouse move events
        // (e.g., prevent objects 'beneath' it from getting them -- see bug 187569)
        // we don't check the target since this is on the systemManager and the target
        // changes a lot -- but this listener only exists during a drag.
        event.stopImmediatePropagation();
        
        if (isNaN(regX) || isNaN(regY))
        {
            // trace("all the mouse moves were not turned off");
            return;
        }
        
        // trace("systemManager_mouseMoveHandler " + event);
        move(event.stageX - regX, event.stageY - regY);
    }

    /**
     *  @private
     */
    private function systemManager_mouseUpHandler(event:MouseEvent):void
    {
        // trace("systemManager_mouseUpHandler: " + event);
        if (!isNaN(regX))
            stopDragging();
    }

    /**
     *  @private
     */
    private function stage_mouseLeaveHandler(event:Event):void
    {
        // trace("stage_mouseLeaveHandler: " + event);
        if (!isNaN(regX))
            stopDragging();
    }

    /**
     *  @private
     */
    private function closeButton_clickHandler(event:MouseEvent):void
    {
        dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
    }
}

}
