first commit

This commit is contained in:
2020-10-20 00:58:15 +02:00
commit 7f1b9bfca5
222 changed files with 56918 additions and 0 deletions

View 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();
}
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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);

View 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";
}
}
}

View 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
}
}

View 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();
}
}
}

View 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";
}
}
}

View 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;
}
}
}

View 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);
}
}
}