scaffold.libs_as.feathers.controls.Panel.as Maven / Gradle / Ivy
/*
Feathers
Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved.
This program is free software. You can redistribute and/or modify it in
accordance with the terms of the accompanying license agreement.
*/
package feathers.controls
{
import feathers.core.IFeathersControl;
import feathers.core.IFocusExtras;
import feathers.core.PropertyProxy;
import feathers.events.FeathersEventType;
import feathers.skins.IStyleProvider;
import starling.display.DisplayObject;
import starling.events.Event;
/**
* A container with layout, optional scrolling, a header, and an optional
* footer.
*
* The following example creates a panel with a horizontal layout and
* adds two buttons to it:
*
*
* var panel:Panel = new Panel();
* panel.title = "Is it time to party?";
*
* var layout:HorizontalLayout = new HorizontalLayout();
* layout.gap = 20;
* layout.padding = 20;
* panel.layout = layout;
*
* this.addChild( panel );
*
* var yesButton:Button = new Button();
* yesButton.label = "Yes";
* panel.addChild( yesButton );
*
* var noButton:Button = new Button();
* noButton.label = "No";
* panel.addChild( noButton );
*
* @see ../../../help/panel.html How to use the Feathers Panel component
*/
public class Panel extends ScrollContainer implements IFocusExtras
{
/**
* The default value added to the styleNameList
of the header.
*
* @see feathers.core.FeathersControl#styleNameList
*/
public static const DEFAULT_CHILD_STYLE_NAME_HEADER:String = "feathers-panel-header";
/**
* The default value added to the styleNameList
of the footer.
*
* @see feathers.core.FeathersControl#styleNameList
*/
public static const DEFAULT_CHILD_STYLE_NAME_FOOTER:String = "feathers-panel-footer";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollPolicy.AUTO
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_POLICY_AUTO:String = "auto";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollPolicy.ON
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_POLICY_ON:String = "on";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollPolicy.OFF
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_POLICY_OFF:String = "off";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollBarDisplayMode.FLOAT
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_BAR_DISPLAY_MODE_FLOAT:String = "float";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollBarDisplayMode.FIXED
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_BAR_DISPLAY_MODE_FIXED:String = "fixed";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollBarDisplayMode.NONE
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_BAR_DISPLAY_MODE_NONE:String = "none";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.RelativePosition.RIGHT
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const VERTICAL_SCROLL_BAR_POSITION_RIGHT:String = "right";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.RelativePosition.LEFT
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const VERTICAL_SCROLL_BAR_POSITION_LEFT:String = "left";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollInteractionMode.TOUCH
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const INTERACTION_MODE_TOUCH:String = "touch";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollInteractionMode.MOUSE
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const INTERACTION_MODE_MOUSE:String = "mouse";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollInteractionMode.TOUCH_AND_SCROLL_BARS
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const INTERACTION_MODE_TOUCH_AND_SCROLL_BARS:String = "touchAndScrollBars";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.Direction.VERTICAL
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const MOUSE_WHEEL_SCROLL_DIRECTION_VERTICAL:String = "vertical";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.Direction.HORIZONTAL
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const MOUSE_WHEEL_SCROLL_DIRECTION_HORIZONTAL:String = "horizontal";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.DecelerationRate.NORMAL
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const DECELERATION_RATE_NORMAL:Number = 0.998;
/**
* @private
* DEPRECATED: Replaced by feathers.controls.DecelerationRate.FAST
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const DECELERATION_RATE_FAST:Number = 0.99;
/**
* @copy feathers.controls.ScrollContainer#AUTO_SIZE_MODE_STAGE
*
* @see feathers.controls.ScrollContainer#autoSizeMode
*/
public static const AUTO_SIZE_MODE_STAGE:String = "stage";
/**
* @copy feathers.controls.ScrollContainer#AUTO_SIZE_MODE_CONTENT
*
* @see feathers.controls.ScrollContainer#autoSizeMode
*/
public static const AUTO_SIZE_MODE_CONTENT:String = "content";
/**
* The default IStyleProvider
for all Panel
* components.
*
* @default null
* @see feathers.core.FeathersControl#styleProvider
*/
public static var globalStyleProvider:IStyleProvider;
/**
* @private
*/
protected static const INVALIDATION_FLAG_HEADER_FACTORY:String = "headerFactory";
/**
* @private
*/
protected static const INVALIDATION_FLAG_FOOTER_FACTORY:String = "footerFactory";
/**
* @private
*/
protected static function defaultHeaderFactory():IFeathersControl
{
return new Header();
}
/**
* Constructor.
*/
public function Panel()
{
super();
}
/**
* The header sub-component.
*
* For internal use in subclasses.
*
* @see #headerFactory
* @see #createHeader()
*/
protected var header:IFeathersControl;
/**
* The footer sub-component.
*
* For internal use in subclasses.
*
* @see #footerFactory
* @see #createFooter()
*/
protected var footer:IFeathersControl;
/**
* The default value added to the styleNameList
of the
* header. This variable is protected
so that sub-classes
* can customize the header style name in their constructors instead of
* using the default style name defined by
* DEFAULT_CHILD_STYLE_NAME_HEADER
.
*
* To customize the header style name without subclassing, see
* customHeaderStyleName
.
*
* @see #customHeaderStyleName
* @see feathers.core.FeathersControl#styleNameList
*/
protected var headerStyleName:String = DEFAULT_CHILD_STYLE_NAME_HEADER;
/**
* The default value added to the styleNameList
of the
* footer. This variable is protected
so that sub-classes
* can customize the footer style name in their constructors instead of
* using the default style name defined by
* DEFAULT_CHILD_STYLE_NAME_FOOTER
.
*
* To customize the footer style name without subclassing, see
* customFooterStyleName
.
*
* @see #customFooterStyleName
* @see feathers.core.FeathersControl#styleNameList
*/
protected var footerStyleName:String = DEFAULT_CHILD_STYLE_NAME_FOOTER;
/**
* @private
*/
override protected function get defaultStyleProvider():IStyleProvider
{
return Panel.globalStyleProvider;
}
/**
* @private
*/
protected var _title:String = null;
/**
* The panel's title to display in the header.
*
* By default, this value is passed to the title
* property of the header, if that property exists. However, if the
* header is not a feathers.controls.Header
instance,
* changing the value of titleField
will allow the panel to
* pass its title to a different property on the header instead.
*
* In the following example, a custom header factory is provided to
* the panel:
*
*
* panel.title = "Settings";
*
* @default null
*
* @see #headerTitleField
* @see #headerFactory
*/
public function get title():String
{
return this._title;
}
/**
* @private
*/
public function set title(value:String):void
{
if(this._title == value)
{
return;
}
this._title = value;
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
protected var _headerTitleField:String = "title";
/**
* A property of the header that should be used to display the panel's
* title.
*
* By default, this value is passed to the title
* property of the header, if that property exists. However, if the
* header is not a feathers.controls.Header
instance,
* changing the value of titleField
will allow the panel to
* pass the title to a different property name instead.
*
* In the following example, a Button
is used as a
* custom header, and the title is passed to its label
* property:
*
*
* panel.headerFactory = function():IFeathersControl
* {
* return new Button();
* };
* panel.titleField = "label";
*
* @default "title"
*
* @see #title
* @see #headerFactory
*/
public function get headerTitleField():String
{
return this._headerTitleField;
}
/**
* @private
*/
public function set headerTitleField(value:String):void
{
if(this._headerTitleField == value)
{
return;
}
this._headerTitleField = value;
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
protected var _headerFactory:Function;
/**
* A function used to generate the panel's header sub-component.
* The header must be an instance of IFeathersControl
, but
* the default is an instance of Header
. This factory can
* be used to change properties on the header when it is first
* created. For instance, if you are skinning Feathers components
* without a theme, you might use this factory to set skins and other
* styles on the header.
*
* The function should have the following signature:
* function():IFeathersControl
*
* In the following example, a custom header factory is provided to
* the panel:
*
*
* panel.headerFactory = function():IFeathersControl
* {
* var header:Header = new Header();
* var closeButton:Button = new Button();
* closeButton.label = "Close";
* closeButton.addEventListener( Event.TRIGGERED, closeButton_triggeredHandler );
* header.rightItems = new <DisplayObject>[ closeButton ];
* return header;
* };
*
* @default null
*
* @see feathers.controls.Header
* @see #headerProperties
*/
public function get headerFactory():Function
{
return this._headerFactory;
}
/**
* @private
*/
public function set headerFactory(value:Function):void
{
if(this._headerFactory == value)
{
return;
}
this._headerFactory = value;
this.invalidate(INVALIDATION_FLAG_HEADER_FACTORY);
//hack because the super class doesn't know anything about the
//header factory
this.invalidate(INVALIDATION_FLAG_SIZE);
}
/**
* @private
*/
protected var _customHeaderStyleName:String;
/**
* A style name to add to the panel's header sub-component. Typically
* used by a theme to provide different styles to different panels.
*
* In the following example, a custom header style name is passed to
* the panel:
*
*
* panel.customHeaderStyleName = "my-custom-header";
*
* In your theme, you can target this sub-component style name to
* provide different styles than the default (this example assumes that the
* header is a Header
, but it can be any
* IFeathersControl
):
*
*
* getStyleProviderForClass( Header ).setFunctionForStyleName( "my-custom-header", setCustomHeaderStyles );
*
* @default null
*
* @see #DEFAULT_CHILD_STYLE_NAME_HEADER
* @see feathers.core.FeathersControl#styleNameList
* @see #headerFactory
* @see #headerProperties
*/
public function get customHeaderStyleName():String
{
return this._customHeaderStyleName;
}
/**
* @private
*/
public function set customHeaderStyleName(value:String):void
{
if(this._customHeaderStyleName == value)
{
return;
}
this._customHeaderStyleName = value;
this.invalidate(INVALIDATION_FLAG_HEADER_FACTORY);
//hack because the super class doesn't know anything about the
//header factory
this.invalidate(INVALIDATION_FLAG_SIZE);
}
/**
* @private
*/
protected var _headerProperties:PropertyProxy;
/**
* An object that stores properties for the container's header
* sub-component, and the properties will be passed down to the header
* when the container validates. Any Feathers component may be used as
* the container's header, so the available properties depend on which
* type of component is returned by headerFactory
.
*
* By default, the headerFactory
will return a
* Header
instance. If you aren't using a different type of
* component as the container's header, you can refer to
* feathers.controls.Header
* for a list of available properties. Otherwise, refer to the
* appropriate documentation for details about which properties are
* available on the component that you're using as the header.
*
* If the subcomponent has its own subcomponents, their properties
* can be set too, using attribute @
notation. For example,
* to set the skin on the thumb which is in a SimpleScrollBar
,
* which is in a List
, you can use the following syntax:
* list.verticalScrollBarProperties.@thumbProperties.defaultSkin = new Image(texture);
*
* Setting properties in a headerFactory
function
* instead of using headerProperties
will result in better
* performance.
*
* In the following example, the header properties are customized:
*
*
* var closeButton:Button = new Button();
* closeButton.label = "Close";
* closeButton.addEventListener( Event.TRIGGERED, closeButton_triggeredHandler );
* panel.headerProperties.rightItems = new <DisplayObject>[ closeButton ];
*
* @default null
*
* @see #headerFactory
* @see feathers.controls.Header
*/
public function get headerProperties():Object
{
if(!this._headerProperties)
{
this._headerProperties = new PropertyProxy(childProperties_onChange);
}
return this._headerProperties;
}
/**
* @private
*/
public function set headerProperties(value:Object):void
{
if(this._headerProperties == value)
{
return;
}
if(!value)
{
value = new PropertyProxy();
}
if(!(value is PropertyProxy))
{
var newValue:PropertyProxy = new PropertyProxy();
for(var propertyName:String in value)
{
newValue[propertyName] = value[propertyName];
}
value = newValue;
}
if(this._headerProperties)
{
this._headerProperties.removeOnChangeCallback(childProperties_onChange);
}
this._headerProperties = PropertyProxy(value);
if(this._headerProperties)
{
this._headerProperties.addOnChangeCallback(childProperties_onChange);
}
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
protected var _footerFactory:Function;
/**
* A function used to generate the panel's footer sub-component.
* The footer must be an instance of IFeathersControl
, and
* by default, there is no footer. This factory can be used to change
* properties on the footer when it is first created. For instance, if
* you are skinning Feathers components without a theme, you might use
* this factory to set skins and other styles on the footer.
*
* The function should have the following signature:
* function():IFeathersControl
*
* In the following example, a custom footer factory is provided to
* the panel:
*
*
* panel.footerFactory = function():IFeathersControl
* {
* return new ScrollContainer();
* };
*
* @default null
*
* @see feathers.core.FeathersControl
* @see #footerProperties
*/
public function get footerFactory():Function
{
return this._footerFactory;
}
/**
* @private
*/
public function set footerFactory(value:Function):void
{
if(this._footerFactory == value)
{
return;
}
this._footerFactory = value;
this.invalidate(INVALIDATION_FLAG_FOOTER_FACTORY);
//hack because the super class doesn't know anything about the
//header factory
this.invalidate(INVALIDATION_FLAG_SIZE);
}
/**
* @private
*/
protected var _customFooterStyleName:String;
/**
* A style name to add to the panel's footer sub-component. Typically
* used by a theme to provide different styles to different panels.
*
* In the following example, a custom footer style name is passed to
* the panel:
*
*
* panel.customFooterStyleName = "my-custom-footer";
*
* In your theme, you can target this sub-component style name to
* provide different styles than the default (this example assumes that the
* footer is a ScrollContainer
, but it can be any
* IFeathersControl
):
*
*
* getStyleProviderForClass( ScrollContainer ).setFunctionForStyleName( "my-custom-footer", setCustomFooterStyles );
*
* @default null
*
* @see #DEFAULT_CHILD_STYLE_NAME_FOOTER
* @see feathers.core.FeathersControl#styleNameList
* @see #footerFactory
* @see #footerProperties
*/
public function get customFooterStyleName():String
{
return this._customFooterStyleName;
}
/**
* @private
*/
public function set customFooterStyleName(value:String):void
{
if(this._customFooterStyleName == value)
{
return;
}
this._customFooterStyleName = value;
this.invalidate(INVALIDATION_FLAG_FOOTER_FACTORY);
//hack because the super class doesn't know anything about the
//header factory
this.invalidate(INVALIDATION_FLAG_SIZE);
}
/**
* @private
*/
protected var _footerProperties:PropertyProxy;
/**
* An object that stores properties for the container's footer
* sub-component, and the properties will be passed down to the footer
* when the container validates. Any Feathers component may be used as
* the container's footer, so the available properties depend on which
* type of component is returned by footerFactory
. Refer to
* the appropriate documentation for details about which properties are
* available on the component that you're using as the footer.
*
* If the subcomponent has its own subcomponents, their properties
* can be set too, using attribute @
notation. For example,
* to set the skin on the thumb which is in a SimpleScrollBar
,
* which is in a List
, you can use the following syntax:
* list.verticalScrollBarProperties.@thumbProperties.defaultSkin = new Image(texture);
*
* Setting properties in a footerFactory
function
* instead of using footerProperties
will result in better
* performance.
*
* In the following example, the footer properties are customized:
*
*
* panel.footerProperties.verticalScrollPolicy = ScrollPolicy.OFF;
*
* @default null
*
* @see #footerFactory
*/
public function get footerProperties():Object
{
if(!this._footerProperties)
{
this._footerProperties = new PropertyProxy(childProperties_onChange);
}
return this._footerProperties;
}
/**
* @private
*/
public function set footerProperties(value:Object):void
{
if(this._footerProperties == value)
{
return;
}
if(!value)
{
value = new PropertyProxy();
}
if(!(value is PropertyProxy))
{
var newValue:PropertyProxy = new PropertyProxy();
for(var propertyName:String in value)
{
newValue[propertyName] = value[propertyName];
}
value = newValue;
}
if(this._footerProperties)
{
this._footerProperties.removeOnChangeCallback(childProperties_onChange);
}
this._footerProperties = PropertyProxy(value);
if(this._footerProperties)
{
this._footerProperties.addOnChangeCallback(childProperties_onChange);
}
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
private var _focusExtrasBefore:Vector. = new [];
/**
* @inheritDoc
*/
public function get focusExtrasBefore():Vector.
{
return this._focusExtrasBefore;
}
/**
* @private
*/
private var _focusExtrasAfter:Vector. = new [];
/**
* @inheritDoc
*/
public function get focusExtrasAfter():Vector.
{
return this._focusExtrasAfter;
}
/**
* Quickly sets all outer padding properties to the same value. The
* outerPadding
getter always returns the value of
* outerPaddingTop
, but the other padding values may be
* different.
*
* In the following example, the outer padding is set to 20 pixels:
*
*
* panel.outerPadding = 20;
*
* @default 0
*
* @see #outerPaddingTop
* @see #outerPaddingRight
* @see #outerPaddingBottom
* @see #outerPaddingLeft
* @see feathers.controls.Scroller#padding
*/
public function get outerPadding():Number
{
return this._outerPaddingTop;
}
/**
* @private
*/
public function set outerPadding(value:Number):void
{
this.outerPaddingTop = value;
this.outerPaddingRight = value;
this.outerPaddingBottom = value;
this.outerPaddingLeft = value;
}
/**
* @private
*/
protected var _outerPaddingTop:Number = 0;
/**
* The minimum space, in pixels, between the panel's top edge and the
* panel's header.
*
* Note: The paddingTop
property applies to the
* middle content only, and it does not affect the header. Use
* outerPaddingTop
if you want to include padding above
* the header. outerPaddingTop
and paddingTop
* may be used simultaneously to define padding around the outer edges
* of the panel and additional padding around its middle content.
*
* In the following example, the top padding is set to 20 pixels:
*
*
* panel.outerPaddingTop = 20;
*
* @default 0
*
* @see feathers.controls.Scroller#paddingTop
*/
public function get outerPaddingTop():Number
{
return this._outerPaddingTop;
}
/**
* @private
*/
public function set outerPaddingTop(value:Number):void
{
if(this._outerPaddingTop == value)
{
return;
}
this._outerPaddingTop = value;
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
protected var _outerPaddingRight:Number = 0;
/**
* The minimum space, in pixels, between the panel's right edge and the
* panel's header, middle content, and footer.
*
* Note: The paddingRight
property applies to the middle
* content only, and it does not affect the header or footer. Use
* outerPaddingRight
if you want to include padding around
* the header and footer too. outerPaddingRight
and
* paddingRight
may be used simultaneously to define
* padding around the outer edges of the panel plus additional padding
* around its middle content.
*
* In the following example, the right outer padding is set to 20 pixels:
*
*
* panel.outerPaddingRight = 20;
*
* @default 0
*
* @see feathers.controls.Scroller#paddingRight
*/
public function get outerPaddingRight():Number
{
return this._outerPaddingRight;
}
/**
* @private
*/
public function set outerPaddingRight(value:Number):void
{
if(this._outerPaddingRight == value)
{
return;
}
this._outerPaddingRight = value;
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
protected var _outerPaddingBottom:Number = 0;
/**
* The minimum space, in pixels, between the panel's bottom edge and the
* panel's footer.
*
* Note: The paddingBottom
property applies to the
* middle content only, and it does not affect the footer. Use
* outerPaddingBottom
if you want to include padding below
* the footer. outerPaddingBottom
and paddingBottom
* may be used simultaneously to define padding around the outer edges
* of the panel and additional padding around its middle content.
*
* In the following example, the bottom outer padding is set to 20 pixels:
*
*
* panel.outerPaddingBottom = 20;
*
* @default 0
*
* @see feathers.controls.Scroller#paddingBottom
*/
public function get outerPaddingBottom():Number
{
return this._outerPaddingBottom;
}
/**
* @private
*/
public function set outerPaddingBottom(value:Number):void
{
if(this._outerPaddingBottom == value)
{
return;
}
this._outerPaddingBottom = value;
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
protected var _outerPaddingLeft:Number = 0;
/**
* The minimum space, in pixels, between the panel's left edge and the
* panel's header, middle content, and footer.
*
* Note: The paddingLeft
property applies to the middle
* content only, and it does not affect the header or footer. Use
* outerPaddingLeft
if you want to include padding around
* the header and footer too. outerPaddingLeft
and
* paddingLeft
may be used simultaneously to define padding
* around the outer edges of the panel and additional padding around its
* middle content.
*
* In the following example, the left outer padding is set to 20 pixels:
*
*
* scroller.outerPaddingLeft = 20;
*
* @default 0
*
* @see feathers.controls.Scroller#paddingLeft
*/
public function get outerPaddingLeft():Number
{
return this._outerPaddingLeft;
}
/**
* @private
*/
public function set outerPaddingLeft(value:Number):void
{
if(this._outerPaddingLeft == value)
{
return;
}
this._outerPaddingLeft = value;
this.invalidate(INVALIDATION_FLAG_STYLES);
}
/**
* @private
*/
protected var _ignoreHeaderResizing:Boolean = false;
/**
* @private
*/
protected var _ignoreFooterResizing:Boolean = false;
/**
* @private
*/
override protected function draw():void
{
var headerFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_HEADER_FACTORY);
var footerFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_FOOTER_FACTORY);
var stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
if(headerFactoryInvalid)
{
this.createHeader();
}
if(footerFactoryInvalid)
{
this.createFooter();
}
if(headerFactoryInvalid || stylesInvalid)
{
this.refreshHeaderStyles();
}
if(footerFactoryInvalid || stylesInvalid)
{
this.refreshFooterStyles();
}
super.draw();
}
/**
* @inheritDoc
*/
override protected function autoSizeIfNeeded():Boolean
{
var needsWidth:Boolean = this._explicitWidth !== this._explicitWidth; //isNaN
var needsHeight:Boolean = this._explicitHeight !== this._explicitHeight; //isNaN
if(!needsWidth && !needsHeight)
{
return false;
}
if(this._autoSizeMode == AUTO_SIZE_MODE_STAGE)
{
return this.setSizeInternal(this.stage.stageWidth, this.stage.stageHeight, false);
}
var oldIgnoreHeaderResizing:Boolean = this._ignoreHeaderResizing;
this._ignoreHeaderResizing = true;
var oldIgnoreFooterResizing:Boolean = this._ignoreFooterResizing;
this._ignoreFooterResizing = true;
var oldHeaderWidth:Number = this.header.width;
var oldHeaderHeight:Number = this.header.height;
this.header.width = this._explicitWidth;
this.header.maxWidth = this._maxWidth;
this.header.height = NaN;
this.header.validate();
if(this.footer)
{
var oldFooterWidth:Number = this.footer.width;
var oldFooterHeight:Number = this.footer.height;
this.footer.width = this._explicitWidth;
this.footer.maxWidth = this._maxWidth;
this.footer.height = NaN;
this.footer.validate();
}
var newWidth:Number = this._explicitWidth;
var newHeight:Number = this._explicitHeight;
if(needsWidth)
{
newWidth = Math.max(this.header.width, this._viewPort.width + this._rightViewPortOffset + this._leftViewPortOffset);
if(this.footer)
{
newWidth = Math.max(newWidth, this.footer.width);
}
if(this.originalBackgroundWidth === this.originalBackgroundWidth) //!isNaN
{
newWidth = Math.max(newWidth, this.originalBackgroundWidth);
}
}
if(needsHeight)
{
newHeight = this._viewPort.height + this._bottomViewPortOffset + this._topViewPortOffset;
if(this.originalBackgroundHeight === this.originalBackgroundHeight) //!isNaN
{
newHeight = Math.max(newHeight, this.originalBackgroundHeight);
}
}
this.header.width = oldHeaderWidth;
this.header.height = oldHeaderHeight;
if(this.footer)
{
this.footer.width = oldFooterWidth;
this.footer.height = oldFooterHeight;
}
this._ignoreHeaderResizing = oldIgnoreHeaderResizing;
this._ignoreFooterResizing = oldIgnoreFooterResizing;
return this.setSizeInternal(newWidth, newHeight, false);
}
/**
* Creates and adds the header
sub-component and
* removes the old instance, if one exists.
*
* Meant for internal use, and subclasses may override this function
* with a custom implementation.
*
* @see #header
* @see #headerFactory
* @see #customHeaderStyleName
*/
protected function createHeader():void
{
if(this.header)
{
this.header.removeEventListener(FeathersEventType.RESIZE, header_resizeHandler);
var displayHeader:DisplayObject = DisplayObject(this.header);
this._focusExtrasBefore.splice(this._focusExtrasBefore.indexOf(displayHeader), 1);
this.removeRawChild(displayHeader, true);
this.header = null;
}
var factory:Function = this._headerFactory != null ? this._headerFactory : defaultHeaderFactory;
var headerStyleName:String = this._customHeaderStyleName != null ? this._customHeaderStyleName : this.headerStyleName;
this.header = IFeathersControl(factory());
this.header.styleNameList.add(headerStyleName);
this.header.addEventListener(FeathersEventType.RESIZE, header_resizeHandler);
displayHeader = DisplayObject(this.header);
this.addRawChild(displayHeader);
this._focusExtrasBefore.push(displayHeader);
}
/**
* Creates and adds the footer
sub-component and
* removes the old instance, if one exists.
*
* Meant for internal use, and subclasses may override this function
* with a custom implementation.
*
* @see #footer
* @see #footerFactory
* @see #customFooterStyleName
*/
protected function createFooter():void
{
if(this.footer)
{
this.footer.removeEventListener(FeathersEventType.RESIZE, footer_resizeHandler);
var displayFooter:DisplayObject = DisplayObject(this.footer);
this._focusExtrasAfter.splice(this._focusExtrasAfter.indexOf(displayFooter), 1);
this.removeRawChild(displayFooter, true);
this.footer = null;
}
if(this._footerFactory == null)
{
return;
}
var footerStyleName:String = this._customFooterStyleName != null ? this._customFooterStyleName : this.footerStyleName;
this.footer = IFeathersControl(this._footerFactory());
this.footer.styleNameList.add(footerStyleName);
this.footer.addEventListener(FeathersEventType.RESIZE, footer_resizeHandler);
displayFooter = DisplayObject(this.footer);
this.addRawChild(displayFooter);
this._focusExtrasAfter.push(displayFooter);
}
/**
* @private
*/
protected function refreshHeaderStyles():void
{
if(Object(this.header).hasOwnProperty(this._headerTitleField))
{
this.header[this._headerTitleField] = this._title;
}
for(var propertyName:String in this._headerProperties)
{
var propertyValue:Object = this._headerProperties[propertyName];
this.header[propertyName] = propertyValue;
}
}
/**
* @private
*/
protected function refreshFooterStyles():void
{
for(var propertyName:String in this._footerProperties)
{
var propertyValue:Object = this._footerProperties[propertyName];
this.footer[propertyName] = propertyValue;
}
}
/**
* @private
*/
override protected function calculateViewPortOffsets(forceScrollBars:Boolean = false, useActualBounds:Boolean = false):void
{
super.calculateViewPortOffsets(forceScrollBars);
this._leftViewPortOffset += this._outerPaddingLeft;
this._rightViewPortOffset += this._outerPaddingRight;
var oldIgnoreHeaderResizing:Boolean = this._ignoreHeaderResizing;
this._ignoreHeaderResizing = true;
var oldHeaderWidth:Number = this.header.width;
var oldHeaderHeight:Number = this.header.height;
if(useActualBounds)
{
this.header.width = this.actualWidth - this._outerPaddingLeft - this._outerPaddingRight;
}
else
{
this.header.width = this._explicitWidth - this._outerPaddingLeft - this._outerPaddingRight;
}
this.header.maxWidth = this._maxWidth - this._outerPaddingLeft - this._outerPaddingRight;
this.header.height = NaN;
this.header.validate();
this._topViewPortOffset += this.header.height + this._outerPaddingTop;
this.header.width = oldHeaderWidth;
this.header.height = oldHeaderHeight;
this._ignoreHeaderResizing = oldIgnoreHeaderResizing;
if(this.footer)
{
var oldIgnoreFooterResizing:Boolean = this._ignoreFooterResizing;
this._ignoreFooterResizing = true;
var oldFooterWidth:Number = this.footer.width;
var oldFooterHeight:Number = this.footer.height;
if(useActualBounds)
{
this.footer.width = this.actualWidth - this._outerPaddingLeft - this._outerPaddingRight;
}
else
{
this.header.width = this._explicitWidth - this._outerPaddingLeft - this._outerPaddingRight;
}
this.footer.maxWidth = this._maxWidth - this._outerPaddingLeft - this._outerPaddingRight;
this.footer.height = NaN;
this.footer.validate();
this._bottomViewPortOffset += this.footer.height + this._outerPaddingBottom;
this.footer.width = oldFooterWidth;
this.footer.height = oldFooterHeight;
this._ignoreFooterResizing = oldIgnoreFooterResizing;
}
else
{
this._bottomViewPortOffset += this._outerPaddingBottom;
}
}
/**
* @private
*/
override protected function layoutChildren():void
{
super.layoutChildren();
var oldIgnoreHeaderResizing:Boolean = this._ignoreHeaderResizing;
this._ignoreHeaderResizing = true;
this.header.x = this._outerPaddingLeft;
this.header.y = this._outerPaddingTop;
this.header.width = this.actualWidth - this._outerPaddingLeft - this._outerPaddingRight;
this.header.height = NaN;
this.header.validate();
this._ignoreHeaderResizing = oldIgnoreHeaderResizing;
if(this.footer)
{
var oldIgnoreFooterResizing:Boolean = this._ignoreFooterResizing;
this._ignoreFooterResizing = true;
this.footer.x = this._outerPaddingLeft;
this.footer.width = this.actualWidth - this._outerPaddingLeft - this._outerPaddingRight;
this.footer.height = NaN;
this.footer.validate();
this.footer.y = this.actualHeight - this.footer.height - this._outerPaddingBottom;
this._ignoreFooterResizing = oldIgnoreFooterResizing;
}
}
/**
* @private
*/
protected function header_resizeHandler(event:Event):void
{
if(this._ignoreHeaderResizing)
{
return;
}
this.invalidate(INVALIDATION_FLAG_SIZE);
}
/**
* @private
*/
protected function footer_resizeHandler(event:Event):void
{
if(this._ignoreFooterResizing)
{
return;
}
this.invalidate(INVALIDATION_FLAG_SIZE);
}
}
}