| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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.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><mx:Panel></code> tag inherits all of the tag |
| * attributes of its superclass and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <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" |
| * > |
| * ... |
| * <i>child tags</i> |
| * ... |
| * </mx:Panel> |
| * </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)); |
| } |
| } |
| |
| } |