| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 mx.containers.utilityClasses.BoxLayout; |
| import mx.controls.Label; |
| import mx.core.Container; |
| import mx.core.IFlexModuleFactory; |
| import mx.core.IInvalidating; |
| import mx.core.IUIComponent; |
| import mx.core.mx_internal; |
| import mx.styles.IStyleManager2; |
| import mx.styles.StyleManager; |
| |
| use namespace mx_internal; |
| |
| include "../styles/metadata/GapStyles.as"; |
| |
| //-------------------------------------- |
| // Styles |
| //-------------------------------------- |
| |
| /** |
| * Number of pixels between the label and child components. |
| * The default value is 14. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="indicatorGap", type="Number", format="Length", inherit="yes")] |
| |
| /** |
| * Width of the form labels. |
| * The default is the length of the longest label in the form. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="labelWidth", type="Number", format="Length", inherit="yes")] |
| |
| /** |
| * Number of pixels between the container's bottom border |
| * and the bottom edge of its content area. |
| * The default value is 16. |
| * |
| * @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 the top edge of its content area. |
| * The default value is 16. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="paddingTop", type="Number", format="Length", inherit="no")] |
| |
| //-------------------------------------- |
| // Excluded APIs |
| //-------------------------------------- |
| |
| [Exclude(name="focusIn", kind="event")] |
| [Exclude(name="focusOut", kind="event")] |
| |
| [Exclude(name="focusBlendMode", kind="style")] |
| [Exclude(name="focusSkin", kind="style")] |
| [Exclude(name="focusThickness", kind="style")] |
| |
| [Exclude(name="focusInEffect", kind="effect")] |
| [Exclude(name="focusOutEffect", kind="effect")] |
| |
| //-------------------------------------- |
| // Other metadata |
| //-------------------------------------- |
| |
| [IconFile("Form.png")] |
| |
| [Alternative(replacement="spark.components.Form", since="4.5")] |
| |
| /** |
| * The Form container lets you control the layout of a form, |
| * mark form fields as required or optional, handle error messages, |
| * and bind your form data to the Flex data model to perform |
| * data checking and validation. |
| * It also lets you use style sheets to configure the appearance |
| * of your forms. |
| * |
| * <p>The following table describes the components you use to create forms in Flex:</p> |
| * <table class="innertable"> |
| * <tr> |
| * <th>Component</th> |
| * <th>Tag</th> |
| * <th>Description</th> |
| * </tr> |
| * <tr> |
| * <td>Form</td> |
| * <td><code><mx:Form></code></td> |
| * <td>Defines the container for the entire form, including the overall form layout. |
| * Use the FormHeading control and FormItem container to define content. |
| * You can also insert other types of components in a Form container.</td> |
| * </tr> |
| * <tr> |
| * <td>FormHeading</td> |
| * <td><code><mx:FormHeading></code></td> |
| * <td>Defines a heading within your form. You can have multiple FormHeading controls within a single Form container.</td> |
| * </tr> |
| * <tr> |
| * <td>FormItem</td> |
| * <td><code><mx:FormItem></code></td> |
| * <td>Contains one or more form children arranged horizontally or vertically. Children can be controls or other containers. |
| * A single Form container can hold multiple FormItem containers.</td> |
| * </tr> |
| * </table> |
| * |
| * @mxml |
| * |
| * <p>The <code><mx:Form></code> tag inherits all the tag |
| * attributes of its superclass and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <mx:Form |
| * <strong>Styles</strong> |
| * horizontalGap="8" |
| * indicatorGap="14" |
| * labelWidth="<i>Calculated</i>" |
| * paddingBottom="16" |
| * paddingTop="16" |
| * verticalGap="6" |
| * > |
| * ... |
| * <i>child tags</i> |
| * ... |
| * </mx:Form> |
| * </pre> |
| * |
| * @includeExample examples/FormExample.mxml |
| * |
| * @see mx.containers.FormHeading |
| * @see mx.containers.FormItem |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class Form extends Container |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function Form() |
| { |
| super(); |
| |
| showInAutomationHierarchy = true; |
| |
| layoutObject.target = this; |
| layoutObject.direction = BoxDirection.VERTICAL; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| mx_internal var layoutObject:BoxLayout = new BoxLayout(); |
| |
| /** |
| * @private |
| */ |
| private var measuredLabelWidth:Number; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function set moduleFactory(moduleFactory:IFlexModuleFactory):void |
| { |
| super.moduleFactory = moduleFactory; |
| |
| styleManager.registerInheritingStyle("labelWidth"); |
| styleManager.registerSizeInvalidatingStyle("labelWidth"); |
| styleManager.registerInheritingStyle("indicatorGap"); |
| styleManager.registerSizeInvalidatingStyle("indicatorGap"); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // maxLabelWidth |
| //---------------------------------- |
| |
| [Bindable("updateComplete")] |
| |
| /** |
| * The maximum width, in pixels, of the labels of the FormItems containers in this Form. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get maxLabelWidth():Number |
| { |
| var n:int = numChildren; |
| for (var i:int = 0; i < n; i++) |
| { |
| var child:DisplayObject = getChildAt(i); |
| if (child is FormItem) |
| { |
| var itemLabel:Label = FormItem(child).itemLabel; |
| if (itemLabel) |
| return itemLabel.width; |
| } |
| } |
| |
| return 0; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods: DisplayObjectContainer |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Discard the cached measuredLabelWidth if a child |
| * is added or removed. |
| */ |
| override public function addChild(child:DisplayObject):DisplayObject |
| { |
| invalidateLabelWidth(); |
| |
| return super.addChild(child); |
| } |
| |
| /** |
| * @private |
| */ |
| override public function addChildAt(child:DisplayObject, |
| index:int):DisplayObject |
| { |
| invalidateLabelWidth(); |
| |
| return super.addChildAt(child, index); |
| } |
| |
| /** |
| * @private |
| */ |
| override public function removeChild(child:DisplayObject):DisplayObject |
| { |
| invalidateLabelWidth(); |
| |
| return super.removeChild(child); |
| } |
| |
| /** |
| * @private |
| */ |
| override public function removeChildAt(index:int):DisplayObject |
| { |
| invalidateLabelWidth(); |
| |
| return super.removeChildAt(index); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods: UIComponent |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Calculates the preferred, minimum and maximum sizes of the Form. |
| * For more information about the <code>measure</code> method, |
| * see the <code>UIComponent.measure()</code> method. |
| * <p>The <code>Form.measure()</code> method sets the |
| * <code>measuredWidth</code> property to the width of the |
| * largest child, plus the values of the <code>paddingLeft</code> |
| * and <code>paddingRight</code> style properties and the |
| * width of the border.</p> |
| * |
| * <p>The <code>measuredHeight</code> property is set to the sum |
| * of the <code>measuredHeight</code>S of all children, |
| * plus <code>verticalGap</code> space between each child. |
| * The <code>paddingTop</code> and <code>paddingBottom</code> |
| * style properties and the height of the border are also added.</p> |
| * |
| * <p>The <code>measuredMinWidth</code> property is set to the largest |
| * minimum width of the children. |
| * If the child has a percentage value for <code>width</code>, |
| * the <code>minWidth</code> property is used, otherwise the |
| * <code>measuredWidth</code> property is used. |
| * The values of the <code>paddingLeft</code> and |
| * <code>paddingRight</code> style properties and the width |
| * of the border are also added.</p> |
| * |
| * <p>The <code>measuredMinHeight</code> property is set to the same value |
| * as that of the <code>measuredHeight</code> property.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function measure():void |
| { |
| super.measure(); |
| |
| layoutObject.measure(); |
| |
| calculateLabelWidth(); |
| } |
| |
| /** |
| * Responds to size changes by setting the positions |
| * and sizes of this container's children. |
| * For more information about the <code>updateDisplayList()</code> method, |
| * see the <code>UIComponent.updateDisplayList()</code> method. |
| * |
| * <p>The <code>Form.updateDisplayList()</code> method |
| * positions the children in a vertical column, |
| * spaced by the <code>verticalGap</code> style property. |
| * The <code>paddingLeft</code>, <code>paddingRight</code>, |
| * <code>paddingTop</code> and <code>paddingBottom</code> |
| * style properties are applied.</p> |
| * |
| * <p>If a child has a percentage width, |
| * it is stretched horizontally to the specified |
| * percentage of the Form container; otherwise, it is set |
| * to its <code>measuredWidth</code> property. |
| * Each child is set to its <code>measuredHeight</code> property.</p> |
| * |
| * <p>This method calls the <code>super.updateDisplayList()</code> |
| * method before doing anything else.</p> |
| * |
| * @param unscaledWidth Specifies the width of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleX</code> property of the component. |
| * |
| * @param unscaledHeight Specifies the height of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleY</code> property of the component. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function updateDisplayList(unscaledWidth:Number, |
| unscaledHeight:Number):void |
| { |
| super.updateDisplayList(unscaledWidth, unscaledHeight); |
| |
| layoutObject.updateDisplayList(unscaledWidth, unscaledHeight); |
| } |
| |
| /** |
| * @private |
| */ |
| override public function styleChanged(styleProp:String):void |
| { |
| // Check to see if this is one of the style properties |
| // that is known to affect layout. |
| if (!styleProp || |
| styleProp == "styleName" || |
| styleManager.isSizeInvalidatingStyle(styleProp)) |
| { |
| invalidateLabelWidth(); |
| } |
| |
| super.styleChanged(styleProp); |
| } |
| |
| /** |
| * @private |
| * */ |
| override public function invalidateSize():void |
| { |
| super.invalidateSize(); |
| invalidateLabelWidth(); |
| } |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| internal function invalidateLabelWidth():void |
| { |
| // We only need to invalidate the label width |
| // after we've been initialized. |
| if (!isNaN(measuredLabelWidth) && initialized) |
| { |
| measuredLabelWidth = NaN; |
| |
| // Need to invalidate the size of all children |
| // to make sure they respond to the label width change. |
| var n:int = numChildren; |
| for (var i:int = 0; i < n; i++) |
| { |
| var child:IUIComponent = IUIComponent(getChildAt(i)); |
| if (child is IInvalidating) |
| IInvalidating(child).invalidateSize(); |
| } |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| internal function calculateLabelWidth():Number |
| { |
| // See if we've already calculated it. |
| if (!isNaN(measuredLabelWidth)) |
| return measuredLabelWidth; |
| |
| var labelWidth:Number = 0; |
| var labelWidthSet:Boolean = false; |
| |
| // Determine best label width. |
| var n:int = numChildren; |
| for (var i:int = 0; i < n; i++) |
| { |
| var child:DisplayObject = getChildAt(i); |
| |
| if (child is FormItem && FormItem(child).includeInLayout) |
| { |
| labelWidth = Math.max(labelWidth, |
| FormItem(child).getPreferredLabelWidth()); |
| // only set measuredLabelWidth yet if we have at least one FormItem child |
| labelWidthSet = true; |
| } |
| } |
| |
| if (labelWidthSet) |
| measuredLabelWidth = labelWidth; |
| |
| return labelWidth; |
| } |
| } |
| |
| } |