first commit
This commit is contained in:
148
com/yahoo/astra/fl/containers/BorderPane.as
Executable file
148
com/yahoo/astra/fl/containers/BorderPane.as
Executable file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers
|
||||
{
|
||||
import com.yahoo.astra.fl.containers.layoutClasses.AdvancedLayoutPane;
|
||||
import com.yahoo.astra.layout.modes.BorderLayout;
|
||||
|
||||
import fl.core.InvalidationType;
|
||||
|
||||
/**
|
||||
* A container that arranges its children similar to a non-scrolling document
|
||||
* page. Top and bottom constraints define headers and footers. Left and
|
||||
* right constraints define sidebars, and a center constraint stetches the
|
||||
* main contents to fill the remaining space.
|
||||
*
|
||||
* <p>This layout container supports advanced options specified through the
|
||||
* <code>configuration</code> property.</p>
|
||||
*
|
||||
* <p><strong>Available Configuration Options</strong></p>
|
||||
* <dl>
|
||||
* <dt><strong><code>target</code></strong> : DisplayObject</dt>
|
||||
* <dd>A display object to be configured.</dd>
|
||||
* <dt><strong><code>constraint</code></strong> : String</dt>
|
||||
* <dd>The BorderConstraints value to be used on the target by the layout algorithm. The default
|
||||
* value is <code>BorderConstraints.CENTER</code>.</dd>
|
||||
* <dt><strong><code>maintainAspectRatio</code></strong> : Boolean</dt>
|
||||
* <dd>If true, the aspect ratio of the target will be maintained if it is resized.</dd>
|
||||
* <dt><strong><code>horizontalAlign</code></strong> : String</dt>
|
||||
* <dd>The horizontal alignment used when positioning the target. Used in combination with
|
||||
* <code>maintainAspectRatio</code>.</dd>
|
||||
* <dt><strong><code>verticalAlign</code></strong> : String</dt>
|
||||
* <dd>The vertical alignment used when positioning the target. Used in combination with
|
||||
* <code>maintainAspectRatio</code>.</dd>
|
||||
* <dt><strong><code>aspectRatio</code></strong> : Number</dt>
|
||||
* <dd>The desired aspect ratio to use with <code>maintainAspectRatio</code>. This value is optional.
|
||||
* If no aspect ratio is provided, it will be determined based on the target's original width and height.</dd>
|
||||
* <dt><strong><code>includeInLayout</code></strong> : Boolean</dt>
|
||||
* <dd>If <code>false</code>, the target will not be included in layout calculations. The default value is <code>true</code>.</dd>
|
||||
* </dl>
|
||||
*
|
||||
* @example The following code sets the configuration options for a BorderPane
|
||||
* <listing version="3.0">
|
||||
* pane.configuration = [
|
||||
* { target: headerSprite, constraint: BorderContstraints.TOP },
|
||||
* { target: contentSprite, constraint: BorderConstraints.CENTER,
|
||||
* maintainAspectRatio: true, horizontalAlign: "center",
|
||||
* verticalAlign: "middle" }
|
||||
* ];
|
||||
* </listing>
|
||||
*
|
||||
* @see com.yahoo.astra.layout.BorderConstraints
|
||||
* @see com.yahoo.astra.layout.HorizontalAlignment
|
||||
* @see com.yahoo.astra.layout.VerticalAlignment
|
||||
*
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class BorderPane extends AdvancedLayoutPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration An Array of optional configurations for the layout container's children.
|
||||
*/
|
||||
public function BorderPane(configuration:Array = null)
|
||||
{
|
||||
super(new BorderLayout(), configuration);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalGap property.
|
||||
*/
|
||||
private var _verticalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of vertical pixels between each item displayed by this
|
||||
* container.
|
||||
*/
|
||||
public function get verticalGap():Number
|
||||
{
|
||||
return this._verticalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set verticalGap(value:Number):void
|
||||
{
|
||||
this._verticalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalGap property.
|
||||
*/
|
||||
private var _horizontalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of horizontal pixels between each item displayed by this
|
||||
* container.
|
||||
*/
|
||||
public function get horizontalGap():Number
|
||||
{
|
||||
return this._horizontalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set horizontalGap(value:Number):void
|
||||
{
|
||||
this._horizontalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
var borderLayout:BorderLayout = this.layoutMode as BorderLayout;
|
||||
if(borderLayout)
|
||||
{
|
||||
borderLayout.horizontalGap = this.horizontalGap;
|
||||
borderLayout.verticalGap = this.verticalGap;
|
||||
}
|
||||
|
||||
super.draw();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
218
com/yahoo/astra/fl/containers/BoxPane.as
Executable file
218
com/yahoo/astra/fl/containers/BoxPane.as
Executable file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers
|
||||
{
|
||||
import com.yahoo.astra.fl.containers.layoutClasses.AdvancedLayoutPane;
|
||||
import com.yahoo.astra.layout.modes.BoxLayout;
|
||||
import com.yahoo.astra.layout.modes.HorizontalAlignment;
|
||||
import com.yahoo.astra.layout.modes.VerticalAlignment;
|
||||
|
||||
import fl.core.InvalidationType;
|
||||
|
||||
/**
|
||||
* A scrolling container that arranges its children one after the other
|
||||
* in a row or column.
|
||||
*
|
||||
* @example The following code configures a BoxPane container:
|
||||
* <listing version="3.0">
|
||||
* var pane:BoxPane = new BoxPane();
|
||||
* pane.direction = "vertical";
|
||||
* pane.verticalGap = 4;
|
||||
* pane.verticalAlign = VerticalAlignment.MIDDLE;
|
||||
* this.addChild( pane );
|
||||
* </listing>
|
||||
*
|
||||
* <p>This layout container supports advanced options specified through the
|
||||
* <code>configuration</code> property.</p>
|
||||
*
|
||||
* <p><strong>Available Configuration Options</strong></p>
|
||||
* <dl>
|
||||
* <dt><strong><code>target</code></strong> : DisplayObject</dt>
|
||||
* <dd>A display object to be configured.</dd>
|
||||
* <dt><strong><code>percentWidth</code></strong> : Number</dt>
|
||||
* <dd>The target's width will be updated based on a percentage of the width specified in the layout bounds.</dd>
|
||||
* <dt><strong><code>percentHeight</code></strong> : Number</dt>
|
||||
* <dd>The target's width will be updated based on a percentage of the width specified in the layout bounds.</dd>
|
||||
* <dt><strong><code>minWidth</code></strong> : Number</dt>
|
||||
* <dd>The minimum width value to allow when resizing. The default value is <code>0</code>.</dd>
|
||||
* <dt><strong><code>minHeight</code></strong> : Number</dt>
|
||||
* <dd>The minimum height value to allow when resizing. The default value is <code>0</code>.</dd>
|
||||
* <dt><strong><code>maxWidth</code></strong> : Number</dt>
|
||||
* <dd>The maximum width value to allow when resizing. The default value is <code>10000</code>.</dd>
|
||||
* <dt><strong><code>maxHeight</code></strong> : Number</dt>
|
||||
* <dd>The maximum height value to allow when resizing. The default value is <code>10000</code>.</dd>
|
||||
* <dt><strong><code>includeInLayout</code></strong> : Boolean</dt>
|
||||
* <dd>If <code>false</code>, the target will not be included in layout calculations. The default value is <code>true</code>.</dd>
|
||||
* </dl>
|
||||
* @see com.yahoo.astra.layout.modes.BoxLayout
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class BoxPane extends AdvancedLayoutPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration An Array of optional configurations for the layout container's children.
|
||||
*/
|
||||
public function BoxPane(configuration:Array = null)
|
||||
{
|
||||
super(new BoxLayout(), configuration);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the direction property.
|
||||
*/
|
||||
private var _direction:String = "horizontal";
|
||||
|
||||
/**
|
||||
* The direction in which children of this container are laid out. Valid
|
||||
* direction values include <code>"vertical"</code> or <code>"horizontal"</code>.
|
||||
*/
|
||||
public function get direction():String
|
||||
{
|
||||
return this._direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set direction(value:String):void
|
||||
{
|
||||
this._direction = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalGap property.
|
||||
*/
|
||||
private var _verticalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels appearing between children when the direction
|
||||
* is set to <code>"vertical"</code>.
|
||||
*/
|
||||
public function get verticalGap():Number
|
||||
{
|
||||
return this._verticalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set verticalGap(value:Number):void
|
||||
{
|
||||
this._verticalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalGap property.
|
||||
*/
|
||||
private var _horizontalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels appearing between children when the direction
|
||||
* is set to <code>"horizontal"</code>.
|
||||
*/
|
||||
public function get horizontalGap():Number
|
||||
{
|
||||
return this._horizontalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set horizontalGap(value:Number):void
|
||||
{
|
||||
this._horizontalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalAlign property.
|
||||
*/
|
||||
private var _verticalAlign:String = VerticalAlignment.TOP;
|
||||
|
||||
/**
|
||||
* The vertical alignment of children displayed in the container.
|
||||
*
|
||||
* @see com.yahoo.astra.layout.VerticalAlignment
|
||||
*/
|
||||
public function get verticalAlign():String
|
||||
{
|
||||
return this._verticalAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set verticalAlign(value:String):void
|
||||
{
|
||||
this._verticalAlign = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalAlign property.
|
||||
*/
|
||||
private var _horizontalAlign:String = HorizontalAlignment.LEFT;
|
||||
|
||||
/**
|
||||
* The horizontal alignment of children displayed in the container.
|
||||
*
|
||||
* @see com.yahoo.astra.layout.HorizontalAlignment
|
||||
*/
|
||||
public function get horizontalAlign():String
|
||||
{
|
||||
return this._horizontalAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set horizontalAlign(value:String):void
|
||||
{
|
||||
this._horizontalAlign = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
var boxLayout:BoxLayout = this.layoutMode as BoxLayout;
|
||||
if(boxLayout)
|
||||
{
|
||||
//pass the various properties to the layout mode
|
||||
boxLayout.direction = this.direction;
|
||||
boxLayout.horizontalAlign = this.horizontalAlign;
|
||||
boxLayout.verticalAlign = this.verticalAlign;
|
||||
boxLayout.horizontalGap = this.horizontalGap;
|
||||
boxLayout.verticalGap = this.verticalGap;
|
||||
}
|
||||
|
||||
super.draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
210
com/yahoo/astra/fl/containers/FlowPane.as
Executable file
210
com/yahoo/astra/fl/containers/FlowPane.as
Executable file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers
|
||||
{
|
||||
import com.yahoo.astra.fl.containers.layoutClasses.AdvancedLayoutPane;
|
||||
import com.yahoo.astra.layout.modes.FlowLayout;
|
||||
import com.yahoo.astra.layout.modes.HorizontalAlignment;
|
||||
import com.yahoo.astra.layout.modes.VerticalAlignment;
|
||||
|
||||
import fl.core.InvalidationType;
|
||||
|
||||
/**
|
||||
* A scrolling container that arranges its children using a flow algorithm
|
||||
* similar to the flow of text in a document or webpage.
|
||||
*
|
||||
* @example The following code configures a FlowPane container:
|
||||
* <listing version="3.0">
|
||||
* var pane:FlowPane = new FlowPane();
|
||||
* pane.direction = "horizontal";
|
||||
* pane.horizontalGap = 4;
|
||||
* pane.verticalGap = 2;
|
||||
* pane.horizontalAlign = HorizontalAlignment.CENTER;
|
||||
* pane.verticalAlign = VerticalAlignment.BOTTOM;
|
||||
* this.addChild( pane );
|
||||
* </listing>
|
||||
*
|
||||
* <p>This layout container supports advanced options specified through the
|
||||
* <code>configuration</code> property.</p>
|
||||
*
|
||||
* <dl>
|
||||
* <dt><strong><code>target</code></strong> : DisplayObject</dt>
|
||||
* <dd>A display object to be configured.</dd>
|
||||
* <dt><strong><code>includeInLayout</code></strong> : Boolean</dt>
|
||||
* <dd>If <code>false</code>, the target will not be included in layout calculations. The default value is <code>true</code>.</dd>
|
||||
* </dl>
|
||||
* @see com.yahoo.astra.layout.modes.FlowLayout
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class FlowPane extends AdvancedLayoutPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration An Array of optional configurations for the layout container's children.
|
||||
*/
|
||||
public function FlowPane(configuration:Array = null)
|
||||
{
|
||||
super(new FlowLayout(), configuration);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the direction property.
|
||||
*/
|
||||
private var _direction:String = "horizontal";
|
||||
|
||||
/**
|
||||
* The direction in which children of this container are laid out. Once
|
||||
* the edge of the container is reached, the children will begin
|
||||
* appearing on the next row or column. Valid direction values include
|
||||
* <code>"vertical"</code> or <code>"horizontal"</code>.
|
||||
*/
|
||||
public function get direction():String
|
||||
{
|
||||
return this._direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set direction(value:String):void
|
||||
{
|
||||
this._direction = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalGap property.
|
||||
*/
|
||||
private var _verticalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels appearing between the container's children
|
||||
* vertically.
|
||||
*/
|
||||
public function get verticalGap():Number
|
||||
{
|
||||
return this._verticalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set verticalGap(value:Number):void
|
||||
{
|
||||
this._verticalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalGap property.
|
||||
*/
|
||||
private var _horizontalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels appearing between the container's children
|
||||
* horizontally.
|
||||
*/
|
||||
public function get horizontalGap():Number
|
||||
{
|
||||
return this._horizontalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set horizontalGap(value:Number):void
|
||||
{
|
||||
this._horizontalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalAlign property.
|
||||
*/
|
||||
private var _verticalAlign:String = VerticalAlignment.TOP;
|
||||
|
||||
/**
|
||||
* The vertical alignment of children displayed in the container.
|
||||
*
|
||||
* @see com.yahoo.astra.layout.VerticalAlignment
|
||||
*/
|
||||
public function get verticalAlign():String
|
||||
{
|
||||
return this._verticalAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set verticalAlign(value:String):void
|
||||
{
|
||||
this._verticalAlign = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalAlign property.
|
||||
*/
|
||||
private var _horizontalAlign:String = HorizontalAlignment.LEFT;
|
||||
|
||||
/**
|
||||
* The horizontal alignment of children displayed in the container.
|
||||
*
|
||||
* @see com.yahoo.astra.layout.HorizontalAlignment
|
||||
*/
|
||||
public function get horizontalAlign():String
|
||||
{
|
||||
return this._horizontalAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set horizontalAlign(value:String):void
|
||||
{
|
||||
this._horizontalAlign = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
var flowLayout:FlowLayout = this.layoutMode as FlowLayout;
|
||||
if(flowLayout)
|
||||
{
|
||||
//pass the various properties to the layout mode
|
||||
flowLayout.direction = this.direction;
|
||||
flowLayout.horizontalAlign = this.horizontalAlign;
|
||||
flowLayout.verticalAlign = this.verticalAlign;
|
||||
flowLayout.horizontalGap = this.horizontalGap;
|
||||
flowLayout.verticalGap = this.verticalGap;
|
||||
}
|
||||
|
||||
super.draw();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
837
com/yahoo/astra/fl/containers/Form.as
Executable file
837
com/yahoo/astra/fl/containers/Form.as
Executable file
@ -0,0 +1,837 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers {
|
||||
import fl.core.UIComponent;
|
||||
|
||||
import com.yahoo.astra.containers.formClasses.FormEventObserver;
|
||||
import com.yahoo.astra.containers.formClasses.FormItem;
|
||||
import com.yahoo.astra.containers.formClasses.FormItemContainer;
|
||||
import com.yahoo.astra.containers.formClasses.FormLayoutStyle;
|
||||
import com.yahoo.astra.containers.formClasses.IForm;
|
||||
import com.yahoo.astra.containers.formClasses.IFormEventObserver;
|
||||
import com.yahoo.astra.events.FormLayoutEvent;
|
||||
import com.yahoo.astra.fl.containers.BoxPane;
|
||||
import com.yahoo.astra.fl.containers.layoutClasses.BaseLayoutPane;
|
||||
import com.yahoo.astra.layout.LayoutContainer;
|
||||
import com.yahoo.astra.layout.LayoutManager;
|
||||
import com.yahoo.astra.layout.modes.BoxLayout;
|
||||
import com.yahoo.astra.managers.IFormDataManager;
|
||||
import com.yahoo.astra.utils.NumberUtil;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.events.Event;
|
||||
import flash.text.TextField;
|
||||
import flash.text.TextFormat;
|
||||
|
||||
//--------------------------------------
|
||||
// Style
|
||||
//--------------------------------------
|
||||
/**
|
||||
*
|
||||
* The skin of required field indicator's skin.
|
||||
*
|
||||
* @default indicatorSkin
|
||||
*
|
||||
* @langversion 3.0
|
||||
* @playerversion Flash 9.0.28.0
|
||||
*/
|
||||
[Style(name="indicatorSkin", type="Class")]
|
||||
|
||||
/**
|
||||
*
|
||||
* The TextFormat object to use to render the instructionText fields in the Form.
|
||||
* @default TextFormat("_sans", 10, 0x000000, false, false, false, '', '', TextFormatAlign.LEFT, 0, 0, 0, 0).
|
||||
*
|
||||
* @langversion 3.0
|
||||
* @playerversion Flash 9.0.28.0
|
||||
*/
|
||||
[Style(name="instructionTextFormat", type="flash.text.TextFormat")]
|
||||
|
||||
/**
|
||||
*
|
||||
* The TextFormat object to use to render the formHeading field in the Form in the Form.
|
||||
* @default TextFormat("_sans", 11, 0x000000, bold, false, false, '', '', TextFormatAlign.LEFT, 0, 0, 0, 0).
|
||||
*
|
||||
* @langversion 3.0
|
||||
* @playerversion Flash 9.0.28.0
|
||||
*/
|
||||
[Style(name="headTextFormat", type="flash.text.TextFormat")]
|
||||
|
||||
/**
|
||||
* Color Object of error box Sprite(<code>showErrorMessageBox = true</code>) in the Form.
|
||||
* @default Color 0x666666;
|
||||
*
|
||||
* @langversion 3.0
|
||||
* @playerversion Flash 9.0.28.0
|
||||
*/
|
||||
[Style(name="errorBoxColor", type="Object")]
|
||||
|
||||
/**
|
||||
*
|
||||
* Alpha value of error box Sprite(<code>showErrorMessageBox = true</code>) in the Form.
|
||||
* @default .2
|
||||
*
|
||||
* @langversion 3.0
|
||||
* @playerversion Flash 9.0.28.0
|
||||
*/
|
||||
[Style(name="errorBoxAlpha", type="Number")]
|
||||
|
||||
/**
|
||||
*
|
||||
* The Form is a layout element containing multiple component items arranged vertically along with the definition for each items.
|
||||
* Similar to the <a href="http://livedocs.adobe.com/flex/3/html/help.html?content=layouts_08.html" target="_blank">Flex Form</a> container,
|
||||
* it is mainly used with nested <code>FormItem</code>s which are containers defined by a label and one or more children arranged horizontally or vertically.
|
||||
*
|
||||
* @example The following code shows a simple use of <code>Form</code>:
|
||||
* <listing version="3.0">
|
||||
*
|
||||
* import com.yahoo.astra.containers.formClasses.FormLayoutStyle;
|
||||
* import com.yahoo.astra.fl.containers.Form;
|
||||
* import fl.controls.TextInput;
|
||||
* import fl.controls.TextArea;
|
||||
* import fl.controls.Button;
|
||||
*
|
||||
* // Init input fields.
|
||||
* // Make sure that you have Form component and UIcomponents(TextInput,TextArea,Button) in your library.
|
||||
* var nameInput:TextInput = new TextInput();
|
||||
* var emailInput:TextInput = new TextInput();
|
||||
* var commentInput:TextArea = new TextArea();
|
||||
* nameInput.width = emailInput.width = commentInput.width = 200;
|
||||
* var submitButton:Button = new Button();
|
||||
* submitButton.label = "SUBMIT";
|
||||
*
|
||||
* var myForm:Form = new Form("Contact Us");
|
||||
* // additional parameters for Form
|
||||
* myForm.autoSize = true;
|
||||
* myForm.indicatorLocation = FormLayoutStyle.INDICATOR_LEFT;
|
||||
* myForm.verticalGap = 10;
|
||||
*
|
||||
* var myFormDataArr : Array = [
|
||||
* {label:"Name", items:nameInput},
|
||||
* {label:"Email", items:emailInput},
|
||||
* {label:"Message", items:commentInput,required:true},
|
||||
* {label:"", items:submitButton}];
|
||||
*
|
||||
* // define dataSource with data array.
|
||||
* myForm.dataSource = myFormDataArr;
|
||||
*
|
||||
* this.addChild(myForm);
|
||||
* </listing>
|
||||
*
|
||||
* @see http://developer.yahoo.com/flash/astra-flash/form
|
||||
* @see http://livedocs.adobe.com/flex/3/html/help.html?content=layouts_08.html
|
||||
* @see com.yahoo.astra.containers.formClasses.FormItem
|
||||
* @see com.yahoo.astra.managers.FormDataManager
|
||||
* @author kayoh
|
||||
*/
|
||||
public class Form extends VBoxPane implements IForm {
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param formHeadingString String for optional text field of <code>"FormHeading"</code>.
|
||||
*/
|
||||
public function Form(formHeadingString : String = null) {
|
||||
super();
|
||||
|
||||
formItemArr = [];
|
||||
|
||||
//EventObserver to dispatch/listen event from Form class.
|
||||
formEventObserver = new FormEventObserver();
|
||||
subscribeObserver(formEventObserver);
|
||||
|
||||
if(formHeadingString && !headFormItem) attachFormHeadingLabel(formHeadingString);
|
||||
|
||||
//Will show Form when the container settled right size.
|
||||
this.visible = false;
|
||||
this.addEventListener(Event.ENTER_FRAME, handler_enterFrame, false, 0, true);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var temp_adjusting_height : Number;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var formItemArr : Array = [];
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var gotRequiredField : Boolean = false;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var headingLabelField : TextField = null;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var subHeadLineTxtFieldArray : Array = [];
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var longestlabelWidth : Number = NaN;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var preferredheadLabelTextFormat : TextFormat = null;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var preferredLabelTextFormat : TextFormat = null;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var preferredInstructionTextFormat : TextFormat = null;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var dataManager : IFormDataManager = null;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var headFormItem : FormItem = null;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var loopCatcher : int = 0;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private var formEventObserver : FormEventObserver = null;
|
||||
|
||||
/**
|
||||
* Sets and gets dataManager for Form to collect and validate data.
|
||||
*
|
||||
* @see com.yahoo.astra.managers.FormDataManager
|
||||
*/
|
||||
public function get formDataManager() : IFormDataManager {
|
||||
return dataManager;
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set formDataManager(value : IFormDataManager) : void {
|
||||
dataManager = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the dataSource property.
|
||||
*/
|
||||
private var _dataSource : Object = null;
|
||||
|
||||
/**
|
||||
* <p>Gets and sets the data to be shown and validated in a <code>Form</code>.
|
||||
* In order to collect and validate data, <code>FormDataManager</code> must be set <strong>before</strong> setting of <code>dataSource</code> in the <code>Form</code>.</p>
|
||||
* <p><strong>Property Options:</strong></p>
|
||||
* <dl>
|
||||
* <dt><strong><code>label</code></strong> : String</dt>
|
||||
* <dd>The String for label text field.(e.g. lable:"State")</dd>
|
||||
* <dt><strong><code>items</code></strong> : Object or String(or Object or String Array)</dt>
|
||||
* <dd>The DisplayObject to be contained and to be shown in a FormItem. String value will be attached as a textfield object.If there is multiple items, nest them into an array.(e.g.items:[stateComboBox,"Zip Code",zipcodeInput])</dd>
|
||||
* <dt><strong><code>itemAlign</code></strong> : String</dt>
|
||||
* <dd>The alignment of multiple items in a FormItem. The default alignment is "horizontal"(<code>FormLayoutStyle.HORIZONTAL</code>)(e.g. itemAlign:FormLayoutStyle.VERTICAL)</dd>
|
||||
* <dt><strong><code>instructionText</code></strong> : String</dt>
|
||||
* <dd>The String for additional label text field bottom of the item(s).(e.g. instructionText:"we'll not spam you!")</dd>
|
||||
* <dt><strong><code>skin</code></strong> : DisplayObject</dt>
|
||||
* <dd>The DisplayObject to be applied as a background skin of the FormItem (e.g. skin:new myBeautifulSkinMC())</dd>
|
||||
* <dt><strong><code>labelTextFormat</code></strong> : TextFormat</dt>
|
||||
* <dd>The TextFormat to be applied to label of the FormItem (e.g. labelTextFormat:new TextFormat("Times", 12, 0xff0000))</dd>
|
||||
* <dt><strong><code>itemHorizontalGap</code></strong> : Number</dt>
|
||||
* <dd>The number of pixels in gaps between each items in a FormItems horizontaly.(e.g. itemHorizontalGap:8)</dd>
|
||||
* <dt><strong><code>itemVerticalGap</code></strong> : Number</dt>
|
||||
* <dd>The number of pixels in gaps between each items in a FormItems verticaly.(e.g. itemVerticalGap:8)</dd>
|
||||
* <dt><strong><code>id</code></strong> : String(or String Array)</dt>
|
||||
* <dd>The property of collected data.(e.g. id:"zip" will be saved in FormDataManager as <code>FormDataManager.collectedData</code>["zip"] = "94089")</dd>
|
||||
* <dt><strong><code>source</code></strong> : Object(or Object Array)</dt>
|
||||
* <dd>The actual input source contains user input data.(e.g. source:[stateComboBox, zipcodeInput])</dd>
|
||||
* <dt><strong><code>property</code></strong> : Object(or Object Array)</dt>
|
||||
* <dd>The additional property of <code>source</code>. If you defined <code>valuePaser</code> of FormDataManager as <code>FlValueParser</code>, don't need to set this property in general(e.g. source:[comboBox, textInput] , property:["abbreviation","text"]</dd>
|
||||
* <dt><strong><code>validator</code></strong> : Function(or Function Array)</dt>
|
||||
* <dd>The Function to validate the <code>source</code>.(e.g. validator:validator.isZip)</dd>
|
||||
* <dt><strong><code>validatorExtraParam</code></strong> : Object(or Object Array)</dt>
|
||||
* <dd>extra parameter(beside first parameter) of the validation.</dd>
|
||||
* <dt><strong><code>required</code></strong> : Boolean(or Boolean Array)</dt>
|
||||
* <dd>The Boolean to decide to show required filed indicator(~~) and apply validation(<code>validator</code>).(e.g. id:["stateComboBox", "zipcodeInput"], required:[false, true]) </dd>
|
||||
* <dt><strong><code>errorString</code></strong> : String</dt>
|
||||
* <dd>The String to show under the item(s) fail to validation when <code>showErrorMessageText</code> is set <code>true</code>. If there is existing <code>instructionText</code>, will be replaced by <code>errorString</code>.(e.g. errorString:"What kind of zipcode is that?.")</dd>
|
||||
* </dl>
|
||||
*
|
||||
*
|
||||
* @example The following code shows a use of <code>dataSource</code>:
|
||||
* <listing version="3.0">
|
||||
* // Download Adobe validator and add in the classpath
|
||||
* import com.adobe.as3Validators.as3DataValidation;
|
||||
* import com.yahoo.astra.fl.utils.FlValueParser;
|
||||
* // Init formDataManager with FlValueParser.
|
||||
* myForm.formDataManager = new FormDataManager(FlValueParser);
|
||||
* // Init validator to be used.
|
||||
* var validator : as3DataValidation = new as3DataValidation();
|
||||
* var myFormDataArr : Array = [
|
||||
* {label:"Name", items:nameInput, id:"name", source:nameInput},
|
||||
* {label:"Address", items:[addressInput_line_1,addressInput_line_2 ], id:["address_line_1", "address_line_2"], source:[addressInput_line_1,addressInput_line_2]},
|
||||
* {label:"Email", items:emailInput, id:"email", instructionText :"we'll not spam you!", source:emailInput, required:true, validator:validator.isEmail},
|
||||
* {label:"", items:submitButton}];
|
||||
* myForm.dataSource = new dataSource(myFormDataArr);
|
||||
* </listing>
|
||||
*
|
||||
* @default null
|
||||
*/
|
||||
public function get dataSource() : Object {
|
||||
return this._dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set dataSource(value : Object) : void {
|
||||
this._dataSource = value;
|
||||
buildFromdataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting string of optional text field on top of the Form.
|
||||
* @param value Text to be shown in the FormHeading text field.
|
||||
*/
|
||||
public function set formHeading(value : String) : void {
|
||||
if(!value) return;
|
||||
if(!headFormItem) attachFormHeadingLabel(value);
|
||||
headingLabelField.htmlText = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the showErrorMessageText property.
|
||||
*/
|
||||
private var _showErrorMessageText : Boolean = false;
|
||||
|
||||
/**
|
||||
* @copy com.yahoo.astra.containers.formClasses.FormItem#showErrorMessageText
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
public function get showErrorMessageText() : Boolean {
|
||||
return _showErrorMessageText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set showErrorMessageText(value : Boolean) : void {
|
||||
_showErrorMessageText = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the showErrorMessageBox property.
|
||||
*/
|
||||
private var _showErrorMessageBox : Boolean = false;
|
||||
|
||||
/**
|
||||
* Sets and gets to present the error result message box : a translucent gray box(alpha:.2 , color:0x666666) behind the item that failed to validate.<br>
|
||||
*
|
||||
* @example The following code shows a use of <code>showErrorMessageBox</code>:
|
||||
* <listing version="3.0">
|
||||
* myForm.setStyle("errorBoxColor", 0xff00ff);
|
||||
* myForm.setStyle("errorBoxAlpha", 1);
|
||||
* myForm.showErrorMessageBox = true;
|
||||
* </listing>
|
||||
* @see setStyle
|
||||
* @default false
|
||||
*/
|
||||
public function get showErrorMessageBox() : Boolean {
|
||||
return _showErrorMessageBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the showErrorMessageBox property.
|
||||
*/
|
||||
public function set showErrorMessageBox(value : Boolean) : void {
|
||||
_showErrorMessageBox = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the labelWidth property.
|
||||
*/
|
||||
private var _labelWidth : Number = NaN;
|
||||
|
||||
/**
|
||||
* @copy com.yahoo.astra.containers.formClasses.FormItem#labelWidth
|
||||
*
|
||||
* @default NaN;
|
||||
*/
|
||||
public function get labelWidth() : Number {
|
||||
return _labelWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set labelWidth(value : Number) : void {
|
||||
if(_labelWidth == value) return;
|
||||
_labelWidth = value;
|
||||
if(headFormItem) {
|
||||
if(headFormItem.labelItem) LayoutManager.update(headFormItem.labelItem, "preferredWidth", labelWidth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the itemVerticalGap property.
|
||||
*/
|
||||
private var _itemVerticalGap : Number = FormLayoutStyle.DEFAULT_FORMITEM_VERTICAL_GAP;
|
||||
|
||||
/**
|
||||
* @copy com.yahoo.astra.containers.formClasses.FormItem#itemVerticalGap
|
||||
*
|
||||
* @default FormLayoutStyle.DEFAULT_FORMITEM_VERTICAL_GAP(6 px)
|
||||
*/
|
||||
public function get itemVerticalGap() : Number {
|
||||
return _itemVerticalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set itemVerticalGap(value : Number) : void {
|
||||
_itemVerticalGap = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the itemHorizontalGap property.
|
||||
*/
|
||||
private var _itemHorizontalGap : Number = FormLayoutStyle.DEFAULT_FORMITEM_HORIZONTAL_GAP;
|
||||
|
||||
/**
|
||||
* @copy com.yahoo.astra.containers.formClasses.FormItem#itemHorizontalGap
|
||||
*
|
||||
* @default FormLayoutStyle.DEFAULT_FORMITEM_HORIZONTAL_GAP(6 px)
|
||||
*/
|
||||
public function get itemHorizontalGap() : Number {
|
||||
return _itemHorizontalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set itemHorizontalGap(value : Number) : void {
|
||||
_itemHorizontalGap = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalGap property.
|
||||
*/
|
||||
private var _horizontalGap : Number = FormLayoutStyle.DEFAULT_HORIZONTAL_GAP;
|
||||
|
||||
/**
|
||||
* @copy com.yahoo.astra.containers.formClasses.FormItem#horizontalGap
|
||||
*
|
||||
* @default FormLayoutStyle.DEFAULT_HORIZONTAL_GAP(6 px)
|
||||
*/
|
||||
override public function get horizontalGap() : Number {
|
||||
return _horizontalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override public function set horizontalGap(value : Number) : void {
|
||||
_horizontalGap = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalGap property.
|
||||
*/
|
||||
private var _verticalGap : Number = FormLayoutStyle.DEFAULT_VERTICAL_GAP;
|
||||
|
||||
/**
|
||||
* The number of pixels in gaps between FormItems.
|
||||
*
|
||||
* @param value Number of pixels.
|
||||
* @default FormLayoutStyle.DEFAULT_VERTICAL_GAP(6 px)
|
||||
*/
|
||||
override public function get verticalGap() : Number {
|
||||
return _verticalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override public function set verticalGap(value : Number) : void {
|
||||
if(_verticalGap == value) return;
|
||||
super.verticalGap = _verticalGap = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the indicatorLocation property.
|
||||
*/
|
||||
private var _indicatorLocation : String = FormLayoutStyle.DEFAULT_INDICATOR_LOCATION;
|
||||
|
||||
/**
|
||||
* @copy com.yahoo.astra.containers.formClasses.FormItem#indicatorLocation
|
||||
*
|
||||
* @default FormLayoutStyle.INDICATOR_LABEL_RIGHT
|
||||
*/
|
||||
public function get indicatorLocation() : String {
|
||||
return _indicatorLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set indicatorLocation(value : String) : void {
|
||||
_indicatorLocation = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the labelAlign property.
|
||||
*/
|
||||
private var _labelAlign : String = FormLayoutStyle.DEFAULT_LABELALIGN;
|
||||
|
||||
/**
|
||||
* @copy com.yahoo.astra.containers.formClasses.FormItem#labelAlign
|
||||
*
|
||||
* @default FormLayoutStyle.RIGHT
|
||||
*/
|
||||
public function get labelAlign() : String {
|
||||
return _labelAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set labelAlign(value : String) : void {
|
||||
_labelAlign = value;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
// Public Methods
|
||||
//--------------------------------------
|
||||
/**
|
||||
* Adds DisplayObject into the <code>Form</code>. If the data is provied by dataSource, <code>addItem</code> will not be used explicitly.
|
||||
* Also, if the <code>child</code> is not a <code>FormItem</code> instance, it will be attached to left edge of a <code>Form</code>.
|
||||
*
|
||||
* @param child DisplayObject to be contained.
|
||||
* @param required Optional parameter determines the requirement of the form.
|
||||
*/
|
||||
public function addItem(child : DisplayObject, required : Boolean = false) : void {
|
||||
if(child is FormItem) {
|
||||
var formItem : FormItem = child as FormItem;
|
||||
|
||||
formItem = child as FormItem;
|
||||
formItem.subscribeObserver(formEventObserver);
|
||||
|
||||
if(preferredLabelTextFormat) {
|
||||
notifyObserver(FormLayoutEvent.UPDATE_LABEL_FONT_CHANGE, preferredLabelTextFormat);
|
||||
}
|
||||
if(preferredInstructionTextFormat) {
|
||||
notifyObserver(FormLayoutEvent.UPDATE_INSTRUCTION_FONT_CHANGE, preferredInstructionTextFormat);
|
||||
}
|
||||
if(isNaN(labelWidth)) {
|
||||
|
||||
if(!isNaN(formItem.labelWidth)) findLongestLabelWidth(formItem.labelWidth);
|
||||
|
||||
if(longestlabelWidth > 0) {
|
||||
notifyObserver(FormLayoutEvent.UPDATE_LABEL_WIDTH, longestlabelWidth);
|
||||
}
|
||||
|
||||
formItem.addEventListener(FormLayoutEvent.LABEL_ADDED, handler_formItemLabelAdded, false, 0, true);
|
||||
} else {
|
||||
notifyObserver(FormLayoutEvent.UPDATE_LABEL_WIDTH, labelWidth);
|
||||
}
|
||||
|
||||
if(required) {
|
||||
formItem.required = true;
|
||||
gotRequiredField = true;
|
||||
}
|
||||
|
||||
if(gotRequiredField) notifyObserver(FormLayoutEvent.UPDATE_GOT_REQUIRED_ITEM, gotRequiredField);
|
||||
if(showErrorMessageText) notifyObserver(FormLayoutEvent.UPDATE_ERROR_MSG_TEXT, showErrorMessageText);
|
||||
if(showErrorMessageBox) notifyObserver(FormLayoutEvent.UPDATE_ERROR_MSG_BOX, showErrorMessageBox);
|
||||
|
||||
if(horizontalGap != FormLayoutStyle.DEFAULT_HORIZONTAL_GAP) {
|
||||
notifyObserver(FormLayoutEvent.UPDATE_HORIZONTAL_GAP, horizontalGap);
|
||||
}
|
||||
if(itemVerticalGap != FormLayoutStyle.DEFAULT_FORMITEM_VERTICAL_GAP) notifyObserver(FormLayoutEvent.UPDATE_ITEM_VERTICAL_GAP, itemVerticalGap);
|
||||
if(itemHorizontalGap != FormLayoutStyle.DEFAULT_FORMITEM_HORIZONTAL_GAP) notifyObserver(FormLayoutEvent.UPDATE_ITEM_HORIZONTAL_GAP, itemHorizontalGap);
|
||||
if(gotRequiredField && indicatorLocation) notifyObserver(FormLayoutEvent.UPDATE_INDICATOR_LOCATION, indicatorLocation);
|
||||
if(labelAlign != FormLayoutStyle.DEFAULT_LABELALIGN) notifyObserver(FormLayoutEvent.UPDATE_LABEL_ALIGN, labelAlign);
|
||||
this.addChild(formItem);
|
||||
} else {
|
||||
var container : FormItemContainer = new FormItemContainer();
|
||||
container.addItem(child);
|
||||
this.addChild(container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets additional items under the <cod>FormHeading</code> field.
|
||||
*
|
||||
* @example The following code shows a use of <code>subFormHeading</code>:
|
||||
* <listing version="3.0">
|
||||
* var myForm:Form = new Form("Contact Us.");
|
||||
* var asteriskMC : MovieClip = new indicatorSkin();
|
||||
* myForm.subFormHeading(asteriskMC, "is required field.");
|
||||
* </listing>
|
||||
*
|
||||
* @param args Elements to be contained in subFormHeading field. Either String or DisplayObjects will be accepted.
|
||||
*/
|
||||
public function subFormHeading(...args) : void {
|
||||
|
||||
if(args.length < 1) return;
|
||||
|
||||
if(!headFormItem) attachFormHeadingLabel("");
|
||||
|
||||
var subHeadLabel : LayoutContainer = new LayoutContainer(new BoxLayout());
|
||||
subHeadLineTxtFieldArray = [];
|
||||
|
||||
for (var i : int = 0;i < args.length; i++) {
|
||||
var obj : * = args[i];
|
||||
if(obj is String) {
|
||||
var subHeadLineTxtField : TextField = FormLayoutStyle.instructionTextField;
|
||||
if(preferredInstructionTextFormat) {
|
||||
subHeadLineTxtField.defaultTextFormat = preferredInstructionTextFormat;
|
||||
}
|
||||
|
||||
subHeadLineTxtField.htmlText = obj.toString();
|
||||
subHeadLabel.addChild(subHeadLineTxtField);
|
||||
subHeadLineTxtFieldArray.push(subHeadLineTxtField);
|
||||
} else {
|
||||
subHeadLabel.addChild(obj);
|
||||
}
|
||||
}
|
||||
headFormItem.itemContainer.addItem(subHeadLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a style property on this component instance.
|
||||
* Calling this method can result in decreased performance, so use it only when necessary.
|
||||
* <p><strong>Additional Styles for Form:</strong></p>
|
||||
* <dl>
|
||||
* <dt><strong><code>skin</code></strong> : Object</dt>
|
||||
* <dd>The skin of Form. Default is none.</code></dd>
|
||||
* <dt><strong><code>indicatorSkin</code></strong> : DisplayObjectContainer</dt>
|
||||
* <dd>The skin of required field indicator's skin. Default is asterisk(~~).</dd>
|
||||
* <dt><strong><code>errorBoxColor</code></strong> : Object</dt>
|
||||
* <dd>The color of <code>errorMessageBox</code>. Default is 0x6666.</code></dd>
|
||||
* <dt><strong><code>errorBoxAlpha</code></strong> : Number</dt>
|
||||
* <dd>The alpha of <code>errorMessageBox</code>. Default is .2</code></dd>
|
||||
* <dt><strong><code>textFormat</code></strong> : TextFormat</dt>
|
||||
* <dd>The text format of all the labels in the <code>Form</code>. Default is : "_sans", 11, 0x000000.</dd>
|
||||
* <dt><strong><code>instructionTextFormat</code></strong> : TextFormat</dt>
|
||||
* <dd>The text format of all the <code>instructionText</code> fields in the <code>Form</code>. Default is : "_sans", 10, 0x000000.</dd>
|
||||
* <dt><strong><code>headTextFormat</code></strong> : TextFormat</dt>
|
||||
* <dd>The text format of <code>formHeading</code> field in the <code>Form</code>. Default is : "_sans", 11, 0x000000, bold.</dd>
|
||||
* </dl>
|
||||
*
|
||||
* @example The following code shows a use of <code>setStyle</code>:
|
||||
* <listing version="3.0">
|
||||
* var myForm:Form = new Form();
|
||||
* myForm.setStyle("indicatorSkin", "myCustomIndicatorSkinMC");
|
||||
* myForm.setStyle("textFormat", new TextFormat("Times", 13, 0xFF0000));
|
||||
* </listing>
|
||||
*
|
||||
*
|
||||
* @param style The name of the style property.
|
||||
*
|
||||
* @param value The value of the style.
|
||||
*
|
||||
* @see com.yahoo.astra.containers.formClasses.FormLayoutStyle
|
||||
*/
|
||||
override public function setStyle(style : String, value : Object) : void {
|
||||
if(value && style == "textFormat") {
|
||||
longestlabelWidth = 0;
|
||||
preferredLabelTextFormat = value as TextFormat;
|
||||
return;
|
||||
}
|
||||
if(value && style == "instructionTextFormat") {
|
||||
preferredInstructionTextFormat = value as TextFormat;
|
||||
if(subHeadLineTxtFieldArray) {
|
||||
var subHeadLineTxtFieldArrayLeng : int = subHeadLineTxtFieldArray.length;
|
||||
for (var i : int = 0;i < subHeadLineTxtFieldArrayLeng; i++) {
|
||||
var subTextField : TextField = subHeadLineTxtFieldArray[i];
|
||||
subTextField.setTextFormat(preferredInstructionTextFormat);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(value && style == "headTextFormat") {
|
||||
preferredheadLabelTextFormat = value as TextFormat;
|
||||
if(headingLabelField) {
|
||||
headingLabelField.defaultTextFormat = preferredheadLabelTextFormat;
|
||||
this.formHeading = headingLabelField.text;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(style == "indicatorSkin" || style == "errorBoxAlpha" || style == "errorBoxColor") {
|
||||
FormLayoutStyle.defaultStyles[style] = value;
|
||||
}
|
||||
super.setStyle(style, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @see com.yahoo.astra.fl.containers.formClasses.FormItem#subscribeObserver
|
||||
*/
|
||||
public function subscribeObserver(formEventObserver : IFormEventObserver) : IFormEventObserver {
|
||||
return formEventObserver.subscribeObserver(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @see com.yahoo.astra.fl.containers.formClasses.FormItem#update
|
||||
*/
|
||||
public function update(target : String,value : Object = null) : void {
|
||||
/*
|
||||
* have no event to update in this class.
|
||||
*/
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Private Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private function notifyObserver(target : String, value : Object = null) : void {
|
||||
if(!formEventObserver) return;
|
||||
formEventObserver.setUpdate(target, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private function handler_enterFrame(e : Event) : void {
|
||||
if(NumberUtil.fuzzyEquals(this.height, temp_adjusting_height) || loopCatcher > 20) {
|
||||
this.removeEventListener(Event.ENTER_FRAME, handler_enterFrame);
|
||||
this.visible = true;
|
||||
loopCatcher = 0;
|
||||
// all adjustment for Form is done.
|
||||
this.dispatchEvent(new FormLayoutEvent(FormLayoutEvent.FORM_BUILD_FINISHED));
|
||||
return;
|
||||
}
|
||||
temp_adjusting_height = this.height;
|
||||
loopCatcher++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private function attachFormHeadingLabel(value : String) : void {
|
||||
headingLabelField = FormLayoutStyle.headTextField;
|
||||
if(preferredheadLabelTextFormat) headingLabelField.defaultTextFormat = preferredheadLabelTextFormat;
|
||||
headingLabelField.htmlText = value;
|
||||
|
||||
headFormItem = new FormItem(headingLabelField);
|
||||
headFormItem.isFormHeadingLabel = true;
|
||||
headFormItem.itemAlign = FormLayoutStyle.VERTICAL;
|
||||
this.addItem(headFormItem, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private function handler_formItemLabelAdded(e : FormLayoutEvent) : void {
|
||||
var formItem : FormItem = e.target as FormItem;
|
||||
findLongestLabelWidth(formItem.labelWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private function findLongestLabelWidth(labelWidth : Number = 0) : void {
|
||||
if(isNaN(longestlabelWidth)) longestlabelWidth = 0;
|
||||
if(labelWidth > longestlabelWidth) {
|
||||
longestlabelWidth = labelWidth;
|
||||
notifyObserver(FormLayoutEvent.UPDATE_LABEL_WIDTH, longestlabelWidth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private function buildFromdataSource() : void {
|
||||
var dataLength : int = dataSource.length;
|
||||
|
||||
for (var i : int = 0;i < dataLength; i++) {
|
||||
var curData : Object = dataSource[i];
|
||||
if(curData["label"] == undefined ) {
|
||||
/*
|
||||
* Item with no Label.
|
||||
*/
|
||||
var itemContainer : FormItemContainer = new FormItemContainer();
|
||||
if (curData["itemAlign"]) itemContainer.itemAlign = curData["itemAlign"];
|
||||
if(curData["items"] is Array) {
|
||||
var curItemDataLength : int = curData["items"].length;
|
||||
for (var j : int = 0;j < curItemDataLength; j++) {
|
||||
itemContainer.addItem(curData["items"][j]);
|
||||
}
|
||||
} else {
|
||||
itemContainer.addItem(curData["items"]);
|
||||
}
|
||||
this.addItem(itemContainer, curRequired);
|
||||
} else {
|
||||
var curLabel : String = (curData["label"]) ? curData["label"] : "";
|
||||
var curItmes : Object = (curData["items"]) ? curData["items"] : [];
|
||||
var curRequired : Boolean = false;
|
||||
if(curData["required"] is Array) {
|
||||
var reqLeng : int = curData["required"].length;
|
||||
for (var k : int = 0;k < reqLeng; k++) {
|
||||
var temp : Boolean = Boolean(curData["required"][k] as Boolean);
|
||||
curRequired ||= temp;
|
||||
}
|
||||
} else if(curData["required"] is String) {
|
||||
curRequired = (curData["required"] == "true") ? true : false;
|
||||
} else {
|
||||
curRequired = (curData["required"]) ? curData["required"] : false;
|
||||
}
|
||||
var curFormItem : FormItem = new FormItem(curLabel, curItmes);
|
||||
if (curData["errorString"]) curFormItem.errorString = curData["errorString"];
|
||||
if (curData["itemAlign"]) curFormItem.itemAlign = curData["itemAlign"];
|
||||
if (curData["instructionText"]) curFormItem.instructionText = curData["instructionText"];
|
||||
if (curData["itemHorizontalGap"]) curFormItem.itemHorizontalGap = curData["itemHorizontalGap"];
|
||||
if (curData["itemVerticalGap"]) curFormItem.itemVerticalGap = curData["itemVerticalGap"];
|
||||
if (curData["skin"]) curFormItem.skin = curData["skin"];
|
||||
if (curData["labelTextFormat"]) curFormItem.labelTextFormat = curData["labelTextFormat"];
|
||||
this.addItem(curFormItem, curRequired);
|
||||
}
|
||||
|
||||
var curId : Object = curData["id"];
|
||||
if(!curId ) continue;
|
||||
if(curId && !dataManager) {
|
||||
throw new Error("You must set formDataManager before set the dataSource.");
|
||||
}
|
||||
|
||||
if(curData["id"] is Array) {
|
||||
var curIdDataLength : int = curId.length;
|
||||
for (var l : int = 0;l < curIdDataLength; l++) {
|
||||
var curSource : Object = (curData["source"] is Array) ? curData["source"][l] : null;
|
||||
var curProperty : Object = (curData["property"] is Array) ? curData["property"][l] : null;
|
||||
var curValidator : Function = (curData["validator"] is Array) ? curData["validator"][l] : null;
|
||||
var validatorExtraParam : Object = (curData["validatorExtraParam"] is Array) ? curData["validatorExtraParam"][l] : null;
|
||||
var curRequiredArr : Boolean = (curData["required"] is Array) ? curData["required"][l] : false;
|
||||
var curTargetObj : DisplayObject = (curData["targetObj"] is Array) ? curData["targetObj"][l] as DisplayObject : curFormItem;
|
||||
var curEventFunction_success : Function = (curData["eventFunction_success"] is Array) ? curData["eventFunction_success"][l] as Function : null;
|
||||
var curEventFunction_fail : Function = (curData["eventFunction_fail"] is Array) ? curData["eventFunction_fail"][l] as Function : null;
|
||||
if(curFormItem) curFormItem.hasMultipleItems = true;
|
||||
dataManager.addItem( curData["id"][l], curSource, curProperty, curRequiredArr, curValidator, validatorExtraParam, curTargetObj, curEventFunction_success, curEventFunction_fail);
|
||||
39
com/yahoo/astra/fl/containers/HBoxPane.as
Executable file
39
com/yahoo/astra/fl/containers/HBoxPane.as
Executable file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers
|
||||
{
|
||||
/**
|
||||
* A scrolling container that arranges its children in a horizontal row.
|
||||
*
|
||||
* @example The following code configures an HBoxPane container:
|
||||
* <listing version="3.0">
|
||||
* var pane:HBoxPane = new HBoxPane();
|
||||
* pane.horizontalGap = 4;
|
||||
* pane.horizontalAlign = HorizontalAlignment.CENTER;
|
||||
* this.addChild( pane );
|
||||
* </listing>
|
||||
* @see com.yahoo.astra.layout.modes.BoxLayout
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class HBoxPane extends BoxPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration An Array of optional configurations for the layout container's children.
|
||||
*/
|
||||
public function HBoxPane(configuration:Array = null)
|
||||
{
|
||||
super(configuration);
|
||||
this.direction = "horizontal";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
22
com/yahoo/astra/fl/containers/IRendererContainer.as
Executable file
22
com/yahoo/astra/fl/containers/IRendererContainer.as
Executable file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers
|
||||
{
|
||||
|
||||
|
||||
|
||||
public interface IRendererContainer
|
||||
{
|
||||
function setRendererStyle(name:String, value:Object, column:uint=0):void
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
261
com/yahoo/astra/fl/containers/TilePane.as
Executable file
261
com/yahoo/astra/fl/containers/TilePane.as
Executable file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers
|
||||
{
|
||||
import com.yahoo.astra.fl.containers.layoutClasses.AdvancedLayoutPane;
|
||||
import com.yahoo.astra.layout.modes.HorizontalAlignment;
|
||||
import com.yahoo.astra.layout.modes.TileLayout;
|
||||
import com.yahoo.astra.layout.modes.VerticalAlignment;
|
||||
|
||||
import fl.core.InvalidationType;
|
||||
|
||||
/**
|
||||
* A scrolling container that arranges its children using a tiling
|
||||
* algorithm where the largest child determines the size of the tiles.
|
||||
*
|
||||
* @example The following code configures a TilePane container:
|
||||
* <listing version="3.0">
|
||||
* var pane:FlowPane = new TilePane();
|
||||
* pane.direction = "horizontal";
|
||||
* pane.horizontalGap = 4;
|
||||
* pane.verticalGap = 4;
|
||||
* pane.horizontalAlign = HorizontalAlignment.CENTER;
|
||||
* pane.verticalAlign = VerticalAlignment.MIDDLE;
|
||||
* this.addChild( pane );
|
||||
* </listing>
|
||||
*
|
||||
* <p>This layout container supports advanced options specified through the
|
||||
* <code>configuration</code> property.</p>
|
||||
*
|
||||
* <dl>
|
||||
* <dt><strong><code>target</code></strong> : DisplayObject</dt>
|
||||
* <dd>A display object to be configured.</dd>
|
||||
* <dt><strong><code>includeInLayout</code></strong> : Boolean</dt>
|
||||
* <dd>If <code>false</code>, the target will not be included in layout calculations. The default value is <code>true</code>.</dd>
|
||||
* </dl>
|
||||
* @see com.yahoo.astra.layout.modes.TileLayout
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class TilePane extends AdvancedLayoutPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration An Array of optional configurations for the layout container's children.
|
||||
*/
|
||||
public function TilePane(configuration:Array = null)
|
||||
{
|
||||
super(new TileLayout(), configuration);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the direction property.
|
||||
*/
|
||||
private var _direction:String = "horizontal";
|
||||
|
||||
/**
|
||||
* The direction in which children of this container are laid out. Once
|
||||
* the edge of the container is reached, the children will begin
|
||||
* appearing on the next row or column. Valid direction values include
|
||||
* <code>"vertical"</code> or <code>"horizontal"</code>.
|
||||
*/
|
||||
public function get direction():String
|
||||
{
|
||||
return this._direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set direction(value:String):void
|
||||
{
|
||||
this._direction = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalGap property.
|
||||
*/
|
||||
private var _verticalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels appearing between the container's children
|
||||
* vertically.
|
||||
*/
|
||||
public function get verticalGap():Number
|
||||
{
|
||||
return this._verticalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set verticalGap(value:Number):void
|
||||
{
|
||||
this._verticalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalGap property.
|
||||
*/
|
||||
private var _horizontalGap:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels appearing between the container's children
|
||||
* horizontally.
|
||||
*/
|
||||
public function get horizontalGap():Number
|
||||
{
|
||||
return this._horizontalGap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set horizontalGap(value:Number):void
|
||||
{
|
||||
this._horizontalGap = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the verticalAlign property.
|
||||
*/
|
||||
private var _verticalAlign:String = VerticalAlignment.TOP;
|
||||
|
||||
/**
|
||||
* The vertical alignment of children displayed in the container.
|
||||
*
|
||||
* @see com.yahoo.astra.layout.VerticalAlignment
|
||||
*/
|
||||
public function get verticalAlign():String
|
||||
{
|
||||
return this._verticalAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set verticalAlign(value:String):void
|
||||
{
|
||||
this._verticalAlign = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the horizontalAlign property.
|
||||
*/
|
||||
private var _horizontalAlign:String = HorizontalAlignment.LEFT;
|
||||
|
||||
/**
|
||||
* The horizontal alignment of children displayed in the container.
|
||||
*
|
||||
* @see com.yahoo.astra.layout.HorizontalAlignment
|
||||
*/
|
||||
public function get horizontalAlign():String
|
||||
{
|
||||
return this._horizontalAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set horizontalAlign(value:String):void
|
||||
{
|
||||
this._horizontalAlign = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the tileWidth property.
|
||||
*/
|
||||
private var _tileWidth:Number = NaN;
|
||||
|
||||
/**
|
||||
* The width of tiles displayed in the target. If NaN, the tile width
|
||||
* will be calculated based on the maximum width among the target's children.
|
||||
*/
|
||||
public function get tileWidth():Number
|
||||
{
|
||||
return this._tileWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set tileWidth(value:Number):void
|
||||
{
|
||||
this._tileWidth = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the tileHeight property.
|
||||
*/
|
||||
private var _tileHeight:Number = NaN;
|
||||
|
||||
/**
|
||||
* The height of tiles displayed in the target. If NaN, the tile height
|
||||
* will be calculated based on the maximum height among the target's children.
|
||||
*/
|
||||
public function get tileHeight():Number
|
||||
{
|
||||
return this._tileHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set tileHeight(value:Number):void
|
||||
{
|
||||
this._tileHeight = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
var tileLayout:TileLayout = this.layoutMode as TileLayout;
|
||||
|
||||
if(tileLayout)
|
||||
{
|
||||
//pass the various properties to the layout mode
|
||||
tileLayout.direction = this.direction;
|
||||
tileLayout.horizontalAlign = this.horizontalAlign;
|
||||
tileLayout.verticalAlign = this.verticalAlign;
|
||||
tileLayout.horizontalGap = this.horizontalGap;
|
||||
tileLayout.verticalGap = this.verticalGap;
|
||||
tileLayout.tileWidth = this.tileWidth;
|
||||
tileLayout.tileHeight = this.tileHeight;
|
||||
}
|
||||
|
||||
super.draw();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
38
com/yahoo/astra/fl/containers/VBoxPane.as
Executable file
38
com/yahoo/astra/fl/containers/VBoxPane.as
Executable file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers
|
||||
{
|
||||
/**
|
||||
* A scrolling container that arranges its children in a vertical column.
|
||||
*
|
||||
* @example The following code configures a VBoxPane container:
|
||||
* <listing version="3.0">
|
||||
* var pane:VBoxPane = new VBoxPane();
|
||||
* pane.verticalGap = 4;
|
||||
* pane.verticalAlign = VerticalAlignment.MIDDLE;
|
||||
* this.addChild( pane );
|
||||
* </listing>
|
||||
* @see com.yahoo.astra.layout.modes.BoxLayout
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class VBoxPane extends BoxPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration An Array of optional configurations for the layout container's children.
|
||||
*/
|
||||
public function VBoxPane(configuration:Array = null)
|
||||
{
|
||||
super(configuration);
|
||||
this.direction = "vertical";
|
||||
}
|
||||
}
|
||||
}
|
||||
282
com/yahoo/astra/fl/containers/layoutClasses/AdvancedLayoutPane.as
Executable file
282
com/yahoo/astra/fl/containers/layoutClasses/AdvancedLayoutPane.as
Executable file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers.layoutClasses
|
||||
{
|
||||
import com.yahoo.astra.layout.modes.BaseLayoutMode;
|
||||
import com.yahoo.astra.layout.modes.IAdvancedLayoutMode;
|
||||
import com.yahoo.astra.layout.modes.ILayoutMode;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
|
||||
/**
|
||||
* Adds support for padding and configurations to the BaseLayoutPane.
|
||||
*
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class AdvancedLayoutPane extends BaseLayoutPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param mode An instance of an ILayoutMode implementation.
|
||||
* @param configuration An Array of optional configurations for the layout container's children.
|
||||
*/
|
||||
public function AdvancedLayoutPane(mode:ILayoutMode = null, configuration:Array = null)
|
||||
{
|
||||
super(mode);
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the paddingLeft property.
|
||||
*/
|
||||
private var _paddingLeft:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels of extra spacing between the left edge of the
|
||||
* container and its children.
|
||||
*/
|
||||
public function get paddingLeft():Number
|
||||
{
|
||||
return this._paddingLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set paddingLeft(value:Number):void
|
||||
{
|
||||
if(this._paddingLeft != value)
|
||||
{
|
||||
this._paddingLeft = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the paddingRight property.
|
||||
*/
|
||||
private var _paddingRight:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels of extra spacing between the right edge of the
|
||||
* container and its children.
|
||||
*/
|
||||
public function get paddingRight():Number
|
||||
{
|
||||
return this._paddingRight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set paddingRight(value:Number):void
|
||||
{
|
||||
if(this._paddingRight != value)
|
||||
{
|
||||
this._paddingRight = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the paddingTop property.
|
||||
*/
|
||||
private var _paddingTop:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels of extra spacing between the top edge of the
|
||||
* container and its children.
|
||||
*/
|
||||
public function get paddingTop():Number
|
||||
{
|
||||
return this._paddingTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set paddingTop(value:Number):void
|
||||
{
|
||||
if(this._paddingTop != value)
|
||||
{
|
||||
this._paddingTop = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the paddingBottom property.
|
||||
*/
|
||||
private var _paddingBottom:Number = 0;
|
||||
|
||||
/**
|
||||
* The number of pixels of extra spacing between the bottom edge of the
|
||||
* container and its children.
|
||||
*/
|
||||
public function get paddingBottom():Number
|
||||
{
|
||||
return this._paddingBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set paddingBottom(value:Number):void
|
||||
{
|
||||
if(this._paddingBottom != value)
|
||||
{
|
||||
this._paddingBottom = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
* Flag indicating that the configuration property has changed.
|
||||
*/
|
||||
protected var configurationChanged:Boolean = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the configuration property.
|
||||
*/
|
||||
private var _configuration:Array;
|
||||
|
||||
/**
|
||||
* A list of settings used by the layout algorithm for specific children
|
||||
* of the container.
|
||||
*/
|
||||
public function get configuration():Array
|
||||
{
|
||||
return this._configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set configuration(value:Array):void
|
||||
{
|
||||
if(this._configuration && this._configuration.length > 0)
|
||||
{
|
||||
//go through the existing configuration and remove the old targets
|
||||
var oldConfigCount:int = this._configuration.length;
|
||||
for(var i:int = 0; i < oldConfigCount; i++)
|
||||
{
|
||||
var configItem:Object = this._configuration[i];
|
||||
var child:DisplayObject = configItem.target as DisplayObject;
|
||||
if(!child)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//remove from the display list
|
||||
this.removeChild(child);
|
||||
|
||||
//remove as a client
|
||||
if(this.layoutMode is IAdvancedLayoutMode)
|
||||
{
|
||||
var layoutWithClients:IAdvancedLayoutMode = IAdvancedLayoutMode(this.layoutMode)
|
||||
if(layoutWithClients.hasClient(child))
|
||||
{
|
||||
layoutWithClients.removeClient(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._configuration = value;
|
||||
|
||||
if(this._configuration && this._configuration.length > 0)
|
||||
{
|
||||
var configCount:int = this._configuration.length;
|
||||
for(i = 0; i < configCount; i++)
|
||||
{
|
||||
configItem = this._configuration[i];
|
||||
child = configItem.target as DisplayObject;
|
||||
if(!child || this.contains(child))
|
||||
{
|
||||
//if we have an invalid target or the child is already
|
||||
//on our display list, we can skip this part
|
||||
continue;
|
||||
}
|
||||
|
||||
//we'll add the target as a client later (because the layoutMode could change)
|
||||
//but it's safe to add it as a child now
|
||||
this.addChild(child);
|
||||
}
|
||||
}
|
||||
this.configurationChanged = true;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Flag that indicates if the layoutMode property has changed.
|
||||
*/
|
||||
protected var layoutModeChanged:Boolean = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override public function set layoutMode(value:ILayoutMode):void
|
||||
{
|
||||
super.layoutMode = value;
|
||||
this.layoutModeChanged = true;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
if(this.layoutMode is BaseLayoutMode)
|
||||
{
|
||||
var mode:BaseLayoutMode = BaseLayoutMode(this.layoutMode);
|
||||
|
||||
if((this.layoutModeChanged || this.configurationChanged) && this._configuration && this._configuration.length > 0)
|
||||
{
|
||||
//if the configuration has changed, add the configured targets as clients
|
||||
//of the layoutMode.
|
||||
var configCount:int = this._configuration.length;
|
||||
for(var i:int = 0; i < configCount; i++)
|
||||
{
|
||||
var configItem:Object = this._configuration[i];
|
||||
var child:DisplayObject = configItem.target as DisplayObject;
|
||||
mode.addClient(child, configItem);
|
||||
}
|
||||
}
|
||||
|
||||
//pass the padding values to the layout mode
|
||||
mode.paddingTop = this.paddingTop;
|
||||
mode.paddingRight = this.paddingRight;
|
||||
mode.paddingBottom = this.paddingBottom;
|
||||
mode.paddingLeft = this.paddingLeft;
|
||||
}
|
||||
|
||||
super.draw();
|
||||
|
||||
//clear the flags
|
||||
this.layoutModeChanged = false;
|
||||
this.configurationChanged = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
730
com/yahoo/astra/fl/containers/layoutClasses/BaseLayoutPane.as
Executable file
730
com/yahoo/astra/fl/containers/layoutClasses/BaseLayoutPane.as
Executable file
@ -0,0 +1,730 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.containers.layoutClasses
|
||||
{
|
||||
import com.yahoo.astra.fl.utils.UIComponentUtil;
|
||||
import com.yahoo.astra.layout.ILayoutContainer;
|
||||
import com.yahoo.astra.layout.LayoutContainer;
|
||||
import com.yahoo.astra.layout.LayoutManager;
|
||||
import com.yahoo.astra.layout.events.LayoutEvent;
|
||||
import com.yahoo.astra.layout.modes.ILayoutMode;
|
||||
import com.yahoo.astra.utils.NumberUtil;
|
||||
|
||||
import fl.containers.BaseScrollPane;
|
||||
import fl.controls.ScrollBar;
|
||||
import fl.controls.ScrollPolicy;
|
||||
import fl.core.InvalidationType;
|
||||
import fl.core.UIComponent;
|
||||
import fl.events.ComponentEvent;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.display.DisplayObjectContainer;
|
||||
import flash.display.Shape;
|
||||
import flash.display.Sprite;
|
||||
import flash.events.Event;
|
||||
import flash.geom.Rectangle;
|
||||
import flash.utils.getDefinitionByName;
|
||||
|
||||
/**
|
||||
* A variation on the ScrollPane container that accepts children
|
||||
* to be arranged using a layout algorithm.
|
||||
*
|
||||
* @see fl.containers.ScrollPane
|
||||
*
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class BaseLayoutPane extends BaseScrollPane
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Static Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* New invalidation type to capture when debug mode changes.
|
||||
*/
|
||||
protected static const INVALIDATION_TYPE_DEBUG_MODE:String = "debugModeInvalid";
|
||||
|
||||
/**
|
||||
* @private
|
||||
* New invalidation type to capture when something will affect the layout.
|
||||
*/
|
||||
protected static const INVALIDATION_TYPE_LAYOUT:String = "layoutInvalid";
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private static var defaultStyles:Object =
|
||||
{
|
||||
skin: Shape, //transparent background skin
|
||||
focusRectSkin: null,
|
||||
focusRectPadding: null,
|
||||
contentPadding: 0 //recommended to use padding properties of the layout mode, if available
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Static Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @copy fl.core.UIComponent#getStyleDefinition()
|
||||
*
|
||||
* @see fl.core.UIComponent#getStyle() UIComponent.getStyle()
|
||||
* @see fl.core.UIComponent#setStyle() UIComponent.setStyle()
|
||||
* @see fl.managers.StyleManager StyleManager
|
||||
*/
|
||||
public static function getStyleDefinition():Object
|
||||
{
|
||||
return mergeStyles(defaultStyles, BaseScrollPane.getStyleDefinition());
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Tell the LayoutManager which events from the Flash CS3 UIComponents
|
||||
* should trigger a layout update.
|
||||
*/
|
||||
private static function initializeLayoutEvents():void
|
||||
{
|
||||
LayoutManager.registerInvalidatingEvents(UIComponent, [ComponentEvent.MOVE, ComponentEvent.RESIZE]);
|
||||
|
||||
try
|
||||
{
|
||||
//if the UILoader component is available, register Event.COMPLETE
|
||||
var uiLoader:Class = getDefinitionByName("fl.containers.UILoader") as Class;
|
||||
if(uiLoader)
|
||||
{
|
||||
LayoutManager.registerInvalidatingEvents(uiLoader, [Event.COMPLETE]);
|
||||
}
|
||||
}
|
||||
catch(error:Error)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
initializeLayoutEvents();
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mode An instance of an ILayoutMode implementation.
|
||||
*/
|
||||
public function BaseLayoutPane(mode:ILayoutMode = null)
|
||||
{
|
||||
super();
|
||||
|
||||
this.layoutMode = mode;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* The generic container used for the children.
|
||||
*/
|
||||
protected var layoutContainer:ILayoutContainer;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Flag indicating that children added to the BaseLayoutPane
|
||||
* may actually be added to the layout container.
|
||||
*/
|
||||
private var _uiConfigured:Boolean = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the layoutMode property.
|
||||
*/
|
||||
private var _layoutMode:ILayoutMode;
|
||||
|
||||
/**
|
||||
* The algorithm used to layout children of this container (no default).
|
||||
*/
|
||||
public function get layoutMode():ILayoutMode
|
||||
{
|
||||
return this._layoutMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set layoutMode(value:ILayoutMode):void
|
||||
{
|
||||
this._layoutMode = value;
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Indicates whether the width has been explicitly set. If not, the
|
||||
* stored value will be NaN.
|
||||
*/
|
||||
protected var explicitWidth:Number = NaN;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override public function set width(value:Number):void
|
||||
{
|
||||
this.setSize(value, this.explicitHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Indicates whether the height has been explicitly set. If not, the
|
||||
* stored value will be NaN.
|
||||
*/
|
||||
protected var explicitHeight:Number = NaN;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override public function set height(value:Number):void
|
||||
{
|
||||
this.setSize(this.explicitWidth, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Overrode this because the original Adobe version led to infinite loops.
|
||||
*/
|
||||
override public function get horizontalPageScrollSize():Number
|
||||
{
|
||||
return (this._horizontalPageScrollSize == 0 && !isNaN(this.availableWidth)) ? this.availableWidth : this._horizontalPageScrollSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Overrode this because the original Adobe version led to infinite loops.
|
||||
*/
|
||||
override public function get verticalPageScrollSize():Number
|
||||
{
|
||||
return (this._verticalPageScrollSize == 0 && !isNaN(this.availableHeight)) ? this.availableHeight : this._verticalPageScrollSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, return the child count from the
|
||||
* ILayoutContainer instead.
|
||||
*/
|
||||
override public function get numChildren():int
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
return super.numChildren;
|
||||
}
|
||||
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
return container.numChildren;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the autoSize property.
|
||||
*/
|
||||
private var _autoSize:Boolean = false;
|
||||
|
||||
/**
|
||||
* If true, the container will automatically calculate the ideal width
|
||||
* and height for itself. Any attempts to set the width and height
|
||||
* values manually while autoSize is set to true will be ignored.
|
||||
*
|
||||
* <p>Note: If you want only one dimension to automatically resize,
|
||||
* autoSize must be false, and you should set the width or height
|
||||
* property to the value of <code>NaN</code>.
|
||||
*/
|
||||
public function get autoSize():Boolean
|
||||
{
|
||||
return this._autoSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set autoSize(value:Boolean):void
|
||||
{
|
||||
this._autoSize = value;
|
||||
this.invalidate(InvalidationType.SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Used for displaying debug data.
|
||||
*/
|
||||
protected var debugCanvas:Sprite;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the debug mode property.
|
||||
*/
|
||||
private var _debugMode:Boolean = false;
|
||||
|
||||
/**
|
||||
* If true, a simple border around the layout pane will identify
|
||||
* its bounds.
|
||||
*/
|
||||
public function get debugMode():Boolean
|
||||
{
|
||||
return this._debugMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set debugMode(value:Boolean):void
|
||||
{
|
||||
this._debugMode = value;
|
||||
this.invalidate(INVALIDATION_TYPE_DEBUG_MODE);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Public Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, then all children are added to the
|
||||
* ILayoutContainer instead.
|
||||
*/
|
||||
override public function addChild(child:DisplayObject):DisplayObject
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
return super.addChild(child);
|
||||
}
|
||||
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
child = container.addChild(child);
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, then all children are added to the
|
||||
* ILayoutContainer instead.
|
||||
*/
|
||||
override public function addChildAt(child:DisplayObject, index:int):DisplayObject
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
return super.addChildAt(child, index);
|
||||
}
|
||||
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
child = container.addChildAt(child, index);
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, then all children are removed from the
|
||||
* ILayoutContainer instead.
|
||||
*/
|
||||
override public function removeChild(child:DisplayObject):DisplayObject
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
return super.removeChild(child);
|
||||
}
|
||||
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
child = container.removeChild(child);
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, then all children are removed from the
|
||||
* ILayoutContainer instead.
|
||||
*/
|
||||
override public function removeChildAt(index:int):DisplayObject
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
return super.removeChildAt(index);
|
||||
}
|
||||
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
var child:DisplayObject = container.removeChildAt(index);
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, then all children are actually in the layoutContainer.
|
||||
*/
|
||||
override public function setChildIndex(child:DisplayObject, index:int):void
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
super.setChildIndex(child, index);
|
||||
return;
|
||||
}
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
container.setChildIndex(child, index);
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, then all children are actually in the layoutContainer.
|
||||
*/
|
||||
override public function getChildAt(index:int):DisplayObject
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
return super.getChildAt(index);
|
||||
}
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
return container.getChildAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the UI has been configured, then all children are actually in the layoutContainer.
|
||||
*/
|
||||
override public function getChildByName(name:String):DisplayObject
|
||||
{
|
||||
if(!this._uiConfigured)
|
||||
{
|
||||
return super.getChildByName(name);
|
||||
}
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
return container.getChildByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* <p>Setting the width or height of the container to the value of <code>NaN</code>
|
||||
* will cause it to automatically determine the ideal size for that
|
||||
* dimension. Additionally, the <code>autoSize</code> property can be
|
||||
* set to <code>true</code> to force both the width and height values to
|
||||
* be automatically calculated based on the content.
|
||||
*
|
||||
* @see autoSize
|
||||
*/
|
||||
override public function setSize(w:Number, h:Number):void
|
||||
{
|
||||
this.explicitWidth = w;
|
||||
this.explicitHeight = h;
|
||||
|
||||
//but we don't want NaN after this point. use the existing _width
|
||||
//and _height values with super.setSize() like Adobe already does.
|
||||
if(isNaN(w))
|
||||
{
|
||||
w = this._width;
|
||||
}
|
||||
if(isNaN(h))
|
||||
{
|
||||
h = this._height;
|
||||
}
|
||||
|
||||
super.setSize(w, h);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function configUI():void
|
||||
{
|
||||
//save the avatar because super.configUI() removes it
|
||||
if(this.numChildren > 0)
|
||||
{
|
||||
var avatar:DisplayObject = this.getChildAt(0);
|
||||
}
|
||||
|
||||
super.configUI();
|
||||
|
||||
//if there was no avatar, then we can setSize() with NaN as width and height (for autosize).
|
||||
//if the user dragged this component on stage, then the size is explicitly set because that's
|
||||
//all Flash CS3 can do. if they made it programmatically, then there is no avatar.
|
||||
if(!avatar)
|
||||
{
|
||||
this.setSize(NaN, NaN);
|
||||
}
|
||||
|
||||
if(!this.layoutContainer)
|
||||
{
|
||||
this.layoutContainer = new LayoutContainer();
|
||||
LayoutContainer(this.layoutContainer).autoMask = false;
|
||||
this.layoutContainer.addEventListener(LayoutEvent.LAYOUT_CHANGE, layoutChangeHandler);
|
||||
var container:DisplayObject = DisplayObject(this.layoutContainer);
|
||||
container.scrollRect = contentScrollRect;
|
||||
container.visible = false;
|
||||
this.addChild(container);
|
||||
}
|
||||
|
||||
if(!this.debugCanvas)
|
||||
{
|
||||
this.debugCanvas = new Sprite();
|
||||
this.addChild(this.debugCanvas);
|
||||
}
|
||||
|
||||
this._horizontalScrollPolicy = ScrollPolicy.AUTO;
|
||||
this._verticalScrollPolicy = ScrollPolicy.AUTO;
|
||||
|
||||
//now all children can be added to the ILayoutContainer
|
||||
this._uiConfigured = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
//fix for document class constructor/Event.RENDER bug in CS3 architecture
|
||||
DisplayObject(this.layoutContainer).visible = true;
|
||||
|
||||
//we have to draw all children once before layout
|
||||
//to get initial sizing
|
||||
this.redrawUIComponentChildren();
|
||||
|
||||
//ensure that we only update the layout if the dimensions have changed
|
||||
//or if one of the layout properties has changed. this is very, very expensive!
|
||||
if(this.isInvalid(InvalidationType.SIZE, INVALIDATION_TYPE_LAYOUT))
|
||||
{
|
||||
var oldWidth:Number = this.width;
|
||||
var oldHeight:Number = this.height;
|
||||
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
|
||||
this.layoutContainer.layoutMode = this.layoutMode;
|
||||
|
||||
//the first measurement will be based on explicit values or autosizing (with NaN)
|
||||
//this is the ideal sizing without scrollbars
|
||||
if(this.autoSize || isNaN(this.explicitWidth))
|
||||
{
|
||||
container.width = NaN;
|
||||
}
|
||||
else
|
||||
{
|
||||
container.width = this.explicitWidth;
|
||||
}
|
||||
if(this.autoSize || isNaN(this.explicitHeight))
|
||||
{
|
||||
container.height = NaN;
|
||||
}
|
||||
else
|
||||
{
|
||||
container.height = this.explicitHeight;
|
||||
}
|
||||
|
||||
this.layoutContainer.validateLayout();
|
||||
|
||||
//floor it because Flash CS3 components are pixel constrained and that may
|
||||
//cause the scrollbars to appear when they should not!
|
||||
this.setContentSize(Math.floor(this.layoutContainer.contentWidth), Math.floor(this.layoutContainer.contentHeight));
|
||||
|
||||
//determine if scrollbars are needed
|
||||
this.calculateAvailableSize();
|
||||
|
||||
var loopCount:int = 0;
|
||||
do
|
||||
{
|
||||
//scrollbars may be present now that we're working with available dimensions
|
||||
//instead of explicit values. we loop in case the scrollbars change again.
|
||||
|
||||
var oldAvailableWidth:Number = this.availableWidth;
|
||||
var oldAvailableHeight:Number = this.availableHeight;
|
||||
|
||||
container.width = this.availableWidth;
|
||||
container.height = this.availableHeight;
|
||||
this.layoutContainer.validateLayout();
|
||||
|
||||
//if the width and height haven't been set explicitly,
|
||||
//the layout pane will resize to fit its contents (no scrollbars, obviously).
|
||||
if(isNaN(this.explicitWidth) || this.autoSize)
|
||||
{
|
||||
var generatedWidth:Number = this.layoutContainer.contentWidth;
|
||||
if(this.vScrollBar)
|
||||
{
|
||||
generatedWidth += ScrollBar.WIDTH;
|
||||
}
|
||||
this._width = Math.round(generatedWidth);
|
||||
}
|
||||
|
||||
if(isNaN(this.explicitHeight) || this.autoSize)
|
||||
{
|
||||
var generatedHeight:Number = this.layoutContainer.contentHeight;
|
||||
if(this.hScrollBar)
|
||||
{
|
||||
generatedHeight += ScrollBar.WIDTH;
|
||||
}
|
||||
this._height = Math.round(generatedHeight);
|
||||
}
|
||||
|
||||
this.setContentSize(Math.floor(this.layoutContainer.contentWidth), Math.floor(this.layoutContainer.contentHeight));
|
||||
this.calculateAvailableSize();
|
||||
|
||||
loopCount++
|
||||
}
|
||||
while((!NumberUtil.fuzzyEquals(oldAvailableWidth, this.availableWidth, 10) || !NumberUtil.fuzzyEquals(oldAvailableHeight, this.availableHeight)) &&
|
||||
loopCount < 10)
|
||||
//if we've gone through this loop 10 times, it should be safe to assume that we need to kill an infinite loop
|
||||
|
||||
//draw again after layout to ensure proper sizing
|
||||
this.redrawUIComponentChildren();
|
||||
|
||||
//draw a transparent background so that the mouse scrollwheel works
|
||||
//when the skin is empty.
|
||||
this.graphics.clear();
|
||||
if(this.width > 0 && this.height > 0)
|
||||
{
|
||||
this.graphics.beginFill(0xff00ff, 0);
|
||||
this.graphics.drawRect(0, 0, this.width, this.height);
|
||||
this.graphics.endFill();
|
||||
}
|
||||
|
||||
//dispatch a resize event if we've grown or shrunk
|
||||
if(!NumberUtil.fuzzyEquals(oldWidth, this.width) || !NumberUtil.fuzzyEquals(oldHeight, this.height))
|
||||
{
|
||||
this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
|
||||
}
|
||||
}
|
||||
|
||||
if(this.debugMode && this.isInvalid(INVALIDATION_TYPE_DEBUG_MODE, InvalidationType.SIZE, INVALIDATION_TYPE_LAYOUT))
|
||||
{
|
||||
this.debugCanvas.graphics.clear();
|
||||
this.debugCanvas.graphics.lineStyle(1, 0xff00ff);
|
||||
this.debugCanvas.graphics.drawRect(0, 0, this.width, this.height);
|
||||
}
|
||||
this.debugCanvas.visible = this.debugMode;
|
||||
|
||||
super.draw();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Update the scrollRect of the ILayoutContainer
|
||||
*/
|
||||
override protected function drawLayout():void
|
||||
{
|
||||
super.drawLayout();
|
||||
|
||||
var container:DisplayObject = DisplayObject(this.layoutContainer);
|
||||
|
||||
this.contentScrollRect = container.scrollRect;
|
||||
this.contentScrollRect.width = this.availableWidth;
|
||||
this.contentScrollRect.height = this.availableHeight;
|
||||
|
||||
container.cacheAsBitmap = useBitmapScrolling;
|
||||
container.scrollRect = this.contentScrollRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Make sure the background isn't in the layout container
|
||||
*/
|
||||
override protected function drawBackground():void
|
||||
{
|
||||
var bg:DisplayObject = this.background;
|
||||
|
||||
this.background = UIComponentUtil.getDisplayObjectInstance(this, this.getStyleValue("skin"));
|
||||
this.background.width = this.width;
|
||||
this.background.height = this.height;
|
||||
super.addChildAt(this.background,0);
|
||||
|
||||
if(bg != null && bg != background)
|
||||
{
|
||||
super.removeChild(bg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Call drawNow() on any Flash UIComponent children this container holds.
|
||||
*/
|
||||
protected function redrawUIComponentChildren():void
|
||||
{
|
||||
var container:DisplayObjectContainer = DisplayObjectContainer(this.layoutContainer);
|
||||
for(var i:int = 0; i < container.numChildren; i++)
|
||||
{
|
||||
var child:UIComponent = container.getChildAt(i) as UIComponent;
|
||||
if(child)
|
||||
{
|
||||
child.drawNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Update the scrollRect of the ILayoutContainer
|
||||
*/
|
||||
override protected function setVerticalScrollPosition(scrollPos:Number, fireEvent:Boolean=false):void
|
||||
{
|
||||
var container:DisplayObject = DisplayObject(this.layoutContainer);
|
||||
|
||||
var contentScrollRect:Rectangle = container.scrollRect;
|
||||
contentScrollRect.y = scrollPos;
|
||||
container.scrollRect = contentScrollRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Update the scrollRect of the ILayoutContainer
|
||||
*/
|
||||
override protected function setHorizontalScrollPosition(scrollPos:Number, fireEvent:Boolean=false):void
|
||||
{
|
||||
var container:DisplayObject = DisplayObject(this.layoutContainer);
|
||||
|
||||
var contentScrollRect:Rectangle = container.scrollRect;
|
||||
contentScrollRect.x = scrollPos;
|
||||
container.scrollRect = contentScrollRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Custom calculation of the available size
|
||||
*/
|
||||
override protected function calculateAvailableSize():void
|
||||
{
|
||||
super.calculateAvailableSize();
|
||||
|
||||
//if we're autosizing, available dimensions are the same as the content
|
||||
if(isNaN(this.explicitWidth) || this.autoSize)
|
||||
{
|
||||
this.availableWidth = this.layoutContainer.contentWidth;
|
||||
this.hScrollBar = false;
|
||||
}
|
||||
if(isNaN(this.explicitHeight) || this.autoSize)
|
||||
{
|
||||
this.availableHeight = this.layoutContainer.contentHeight;
|
||||
this.vScrollBar = false;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Event Handlers
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the layout has changed, we're probably in Flash Player's
|
||||
* render phase. If the UIComponent initiated it, this control
|
||||
* is drawing and we don't need to redraw. If the layout container
|
||||
* initiated it, then we should draw immediately because we
|
||||
* may not get a render event...
|
||||
*/
|
||||
protected function layoutChangeHandler(event:LayoutEvent):void
|
||||
{
|
||||
this.invalidate(INVALIDATION_TYPE_LAYOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user