All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.feathers.controls.renderers.DefaultGroupedListHeaderOrFooterRenderer.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.renderers
{
	import feathers.controls.GroupedList;
	import feathers.controls.ImageLoader;
	import feathers.core.FeathersControl;
	import feathers.core.IFeathersControl;
	import feathers.core.ITextRenderer;
	import feathers.core.IValidating;
	import feathers.core.PropertyProxy;
	import feathers.layout.HorizontalAlign;
	import feathers.layout.VerticalAlign;
	import feathers.skins.IStyleProvider;

	import starling.display.DisplayObject;

	/**
	 * The default renderer used for headers and footers in a GroupedList
	 * control.
	 *
	 * @see feathers.controls.GroupedList
	 */
	public class DefaultGroupedListHeaderOrFooterRenderer extends FeathersControl implements IGroupedListHeaderRenderer, IGroupedListFooterRenderer
	{
		/**
		 * @private
		 * DEPRECATED: Replaced by feathers.layout.HorizontalAlign.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 HORIZONTAL_ALIGN_LEFT:String = "left"; /** * @private * DEPRECATED: Replaced by feathers.layout.HorizontalAlign.CENTER. * *

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 HORIZONTAL_ALIGN_CENTER:String = "center"; /** * @private * DEPRECATED: Replaced by feathers.layout.HorizontalAlign.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 HORIZONTAL_ALIGN_RIGHT:String = "right"; /** * @private * DEPRECATED: Replaced by feathers.layout.HorizontalAlign.JUSTIFY. * *

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 HORIZONTAL_ALIGN_JUSTIFY:String = "justify"; /** * @private * DEPRECATED: Replaced by feathers.layout.VerticalAlign.TOP. * *

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_ALIGN_TOP:String = "top"; /** * @private * DEPRECATED: Replaced by feathers.layout.VerticalAlign.MIDDLE. * *

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_ALIGN_MIDDLE:String = "middle"; /** * @private * DEPRECATED: Replaced by feathers.layout.VerticalAlign.BOTTOM. * *

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_ALIGN_BOTTOM:String = "bottom"; /** * @private * DEPRECATED: Replaced by feathers.layout.VerticalAlign.JUSTIFY. * *

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_ALIGN_JUSTIFY:String = "justify"; /** * The default value added to the styleNameList of the * content label. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_CONTENT_LABEL:String = "feathers-header-footer-renderer-content-label"; /** * The default IStyleProvider for all DefaultGroupedListHeaderOrFooterRenderer * components. * * @default null * @see feathers.core.FeathersControl#styleProvider */ public static var globalStyleProvider:IStyleProvider; /** * @private */ protected static function defaultImageLoaderFactory():ImageLoader { return new ImageLoader(); } /** * Constructor. */ public function DefaultGroupedListHeaderOrFooterRenderer() { super(); } /** * The value added to the styleNameList of the content * label text renderer. * * @see feathers.core.FeathersControl#styleNameList */ protected var contentLabelStyleName:String = DEFAULT_CHILD_STYLE_NAME_CONTENT_LABEL; /** * @private */ protected var contentImage:ImageLoader; /** * @private */ protected var contentLabel:ITextRenderer; /** * @private */ protected var content:DisplayObject; /** * @private */ override protected function get defaultStyleProvider():IStyleProvider { return DefaultGroupedListHeaderOrFooterRenderer.globalStyleProvider; } /** * @private */ protected var _data:Object; /** * @inheritDoc */ public function get data():Object { return this._data; } /** * @private */ public function set data(value:Object):void { if(this._data == value) { return; } this._data = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _groupIndex:int = -1; /** * @inheritDoc */ public function get groupIndex():int { return this._groupIndex; } /** * @private */ public function set groupIndex(value:int):void { this._groupIndex = value; } /** * @private */ protected var _layoutIndex:int = -1; /** * @inheritDoc */ public function get layoutIndex():int { return this._layoutIndex; } /** * @private */ public function set layoutIndex(value:int):void { this._layoutIndex = value; } /** * @private */ protected var _owner:GroupedList; /** * @inheritDoc */ public function get owner():GroupedList { return this._owner; } /** * @private */ public function set owner(value:GroupedList):void { if(this._owner == value) { return; } this._owner = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _factoryID:String; /** * @inheritDoc */ public function get factoryID():String { return this._factoryID; } /** * @private */ public function set factoryID(value:String):void { this._factoryID = value; } /** * @private */ protected var _horizontalAlign:String = HorizontalAlign.LEFT; [Inspectable(type="String",enumeration="left,center,right,justify")] /** * The location where the renderer's content is aligned horizontally * (on the x-axis). * *

In the following example, the horizontal alignment is changed to * right:

* * * renderer.horizontalAlign = HorizontalAlign.RIGHT; * * @default feathers.layout.HorizontalAlign.LEFT * * @see feathers.layout.HorizontalAlign#LEFT * @see feathers.layout.HorizontalAlign#CENTER * @see feathers.layout.HorizontalAlign#RIGHT * @see feathers.layout.HorizontalAlign#JUSTIFY */ public function get horizontalAlign():String { return this._horizontalAlign; } /** * @private */ public function set horizontalAlign(value:String):void { if(this._horizontalAlign == value) { return; } this._horizontalAlign = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _verticalAlign:String = VerticalAlign.MIDDLE; [Inspectable(type="String",enumeration="top,middle,bottom,justify")] /** * The location where the renderer's content is aligned vertically (on * the y-axis). * *

In the following example, the vertical alignment is changed to * bottom:

* * * renderer.verticalAlign = VerticalAlign.BOTTOM; * * @default feathers.layout.VerticalAlign.MIDDLE * * @see feathers.layout.VerticalAlign#TOP * @see feathers.layout.VerticalAlign#MIDDLE * @see feathers.layout.VerticalAlign#BOTTOM * @see feathers.layout.VerticalAlign#JUSTIFY */ public function get verticalAlign():String { return _verticalAlign; } /** * @private */ public function set verticalAlign(value:String):void { if(this._verticalAlign == value) { return; } this._verticalAlign = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _contentField:String = "content"; /** * The field in the item that contains a display object to be positioned * in the content position of the renderer. If you wish to display a * texture in the content position, it's better for performance to use * contentSourceField instead. * *

All of the content fields and functions, ordered by priority:

*
    *
  1. contentSourceFunction
  2. *
  3. contentSourceField
  4. *
  5. contentLabelFunction
  6. *
  7. contentLabelField
  8. *
  9. contentFunction
  10. *
  11. contentField
  12. *
* *

In the following example, the content field is customized:

* * * renderer.contentField = "header"; * * @default "content" * * @see #contentSourceField * @see #contentFunction * @see #contentSourceFunction * @see #contentLabelField * @see #contentLabelFunction */ public function get contentField():String { return this._contentField; } /** * @private */ public function set contentField(value:String):void { if(this._contentField == value) { return; } this._contentField = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _contentFunction:Function; /** * A function that returns a display object to be positioned in the * content position of the renderer. If you wish to display a texture in * the content position, it's better for performance to use * contentSourceFunction instead. * *

The function is expected to have the following signature:

*
function( item:Object ):DisplayObject
* *

All of the content fields and functions, ordered by priority:

*
    *
  1. contentSourceFunction
  2. *
  3. contentSourceField
  4. *
  5. contentLabelFunction
  6. *
  7. contentLabelField
  8. *
  9. contentFunction
  10. *
  11. contentField
  12. *
* *

In the following example, the content function is customized:

* * * renderer.contentFunction = function( item:Object ):DisplayObject * { * if(item in cachedContent) * { * return cachedContent[item]; * } * var content:DisplayObject = createContentForHeader( item ); * cachedContent[item] = content; * return content; * }; * * @default null * * @see #contentField * @see #contentSourceField * @see #contentSourceFunction * @see #contentLabelField * @see #contentLabelFunction */ public function get contentFunction():Function { return this._contentFunction; } /** * @private */ public function set contentFunction(value:Function):void { if(this._contentFunction == value) { return; } this._contentFunction = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _contentSourceField:String = "source"; /** * The field in the data that contains a starling.textures.Texture * or a URL that points to a bitmap to be used as the renderer's * content. The renderer will automatically manage and reuse an internal * ImageLoader sub-component and this value will be passed * to the source property. The ImageLoader may * be customized by changing the contentLoaderFactory. * *

Using an content source will result in better performance than * passing in an ImageLoader or Image through * contentField or contentFunction because the * renderer can avoid costly display list manipulation.

* *

All of the content fields and functions, ordered by priority:

*
    *
  1. contentSourceFunction
  2. *
  3. contentSourceField
  4. *
  5. contentLabelFunction
  6. *
  7. contentLabelField
  8. *
  9. contentFunction
  10. *
  11. contentField
  12. *
* *

In the following example, the content source field is customized:

* * * renderer.contentSourceField = "texture"; * * @default "source" * * @see feathers.controls.ImageLoader#source * @see #contentLoaderFactory * @see #contentSourceFunction * @see #contentField * @see #contentFunction * @see #contentLabelField * @see #contentLabelFunction */ public function get contentSourceField():String { return this._contentSourceField; } /** * @private */ public function set contentSourceField(value:String):void { if(this._contentSourceField == value) { return; } this._contentSourceField = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _contentSourceFunction:Function; /** * A function used to generate a starling.textures.Texture * or a URL that points to a bitmap to be used as the renderer's * content. The renderer will automatically manage and reuse an internal * ImageLoader sub-component and this value will be passed * to the source property. The ImageLoader may * be customized by changing the contentLoaderFactory. * *

Using an content source will result in better performance than * passing in an ImageLoader or Image through * contentField or contentFunction because the * renderer can avoid costly display list manipulation.

* *

The function is expected to have the following signature:

*
function( item:Object ):Object
* *

The return value is a valid value for the source * property of an ImageLoader component.

* *

All of the content fields and functions, ordered by priority:

*
    *
  1. contentSourceFunction
  2. *
  3. contentSourceField
  4. *
  5. contentLabelFunction
  6. *
  7. contentLabelField
  8. *
  9. contentFunction
  10. *
  11. contentField
  12. *
* *

In the following example, the content source function is customized:

* * * renderer.contentSourceFunction = function( item:Object ):Object * { * return "http://www.example.com/thumbs/" + item.name + "-thumb.png"; * }; * * @default null * * @see feathers.controls.ImageLoader#source * @see #contentLoaderFactory * @see #contentSourceField * @see #contentField * @see #contentFunction * @see #contentLabelField * @see #contentLabelFunction */ public function get contentSourceFunction():Function { return this._contentSourceFunction; } /** * @private */ public function set contentSourceFunction(value:Function):void { if(this.contentSourceFunction == value) { return; } this._contentSourceFunction = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _contentLabelField:String = "label"; /** * The field in the item that contains a string to be displayed in a * renderer-managed Label in the content position of the * renderer. The renderer will automatically reuse an internal * Label and swap the text when the data changes. This * Label may be skinned by changing the * contentLabelFactory. * *

Using an content label will result in better performance than * passing in a Label through a contentField * or contentFunction because the renderer can avoid * costly display list manipulation.

* *

All of the content fields and functions, ordered by priority:

*
    *
  1. contentTextureFunction
  2. *
  3. contentTextureField
  4. *
  5. contentLabelFunction
  6. *
  7. contentLabelField
  8. *
  9. contentFunction
  10. *
  11. contentField
  12. *
* *

In the following example, the content label field is customized:

* * * renderer.contentLabelField = "text"; * * @default "label" * * @see #contentLabelFactory * @see #contentLabelFunction * @see #contentField * @see #contentFunction * @see #contentSourceField * @see #contentSourceFunction */ public function get contentLabelField():String { return this._contentLabelField; } /** * @private */ public function set contentLabelField(value:String):void { if(this._contentLabelField == value) { return; } this._contentLabelField = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _contentLabelFunction:Function; /** * A function that returns a string to be displayed in a * renderer-managed Label in the content position of the * renderer. The renderer will automatically reuse an internal * Label and swap the text when the data changes. This * Label may be skinned by changing the * contentLabelFactory. * *

Using an content label will result in better performance than * passing in a Label through a contentField * or contentFunction because the renderer can avoid * costly display list manipulation.

* *

The function is expected to have the following signature:

*
function( item:Object ):String
* *

All of the content fields and functions, ordered by priority:

*
    *
  1. contentTextureFunction
  2. *
  3. contentTextureField
  4. *
  5. contentLabelFunction
  6. *
  7. contentLabelField
  8. *
  9. contentFunction
  10. *
  11. contentField
  12. *
* *

In the following example, the content label function is customized:

* * * renderer.contentLabelFunction = function( item:Object ):String * { * return item.category + " > " + item.subCategory; * }; * * @default null * * @see #contentLabelFactory * @see #contentLabelField * @see #contentField * @see #contentFunction * @see #contentSourceField * @see #contentSourceFunction */ public function get contentLabelFunction():Function { return this._contentLabelFunction; } /** * @private */ public function set contentLabelFunction(value:Function):void { if(this._contentLabelFunction == value) { return; } this._contentLabelFunction = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _contentLoaderFactory:Function = defaultImageLoaderFactory; /** * A function that generates an ImageLoader that uses the result * of contentSourceField or contentSourceFunction. * Useful for transforming the ImageLoader in some way. For * example, you might want to scale it for current screen density or * apply pixel snapping. * *

In the following example, a custom content loader factory is passed * to the renderer:

* * * renderer.contentLoaderFactory = function():ImageLoader * { * var loader:ImageLoader = new ImageLoader(); * loader.scaleFactor = 2; * return loader; * }; * * @default function():ImageLoader { return new ImageLoader(); } * * @see feathers.controls.ImageLoader * @see #contentSourceField * @see #contentSourceFunction */ public function get contentLoaderFactory():Function { return this._contentLoaderFactory; } /** * @private */ public function set contentLoaderFactory(value:Function):void { if(this._contentLoaderFactory == value) { return; } this._contentLoaderFactory = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _contentLabelFactory:Function; /** * A function that generates an ITextRenderer that uses the result * of contentLabelField or contentLabelFunction. * Can be used to set properties on the ITextRenderer. * *

In the following example, a custom content label factory is passed * to the renderer:

* * * renderer.contentLabelFactory = function():ITextRenderer * { * var renderer:TextFieldTextRenderer = new TextFieldTextRenderer(); * renderer.textFormat = new TextFormat( "Source Sans Pro", 16, 0x333333 ); * renderer.embedFonts = true; * return renderer; * }; * * @default null * * @see feathers.core.ITextRenderer * @see feathers.core.FeathersControl#defaultTextRendererFactory * @see #contentLabelField * @see #contentLabelFunction */ public function get contentLabelFactory():Function { return this._contentLabelFactory; } /** * @private */ public function set contentLabelFactory(value:Function):void { if(this._contentLabelFactory == value) { return; } this._contentLabelFactory = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _customContentLabelStyleName:String; /** * A style name to add to the renderer's label text renderer * sub-component. Typically used by a theme to provide different styles * to different renderers. * *

In the following example, a custom label style name is passed to * the renderer:

* * * renderer.customContentLabelStyleName = "my-custom-header-or-footer-renderer-label"; * *

In your theme, you can target this sub-component style name to * provide different styles than the default:

* * * getStyleProviderForClass( BitmapFontTextRenderer ).setFunctionForStyleName( "my-custom-header-or-footer-label", setCustomHeaderOrFooterLabelStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_CONTENT_LABEL * @see feathers.core.FeathersControl#styleNameList * @see #contentLabelFactory */ public function get customContentLabelStyleName():String { return this._customContentLabelStyleName; } /** * @private */ public function set customContentLabelStyleName(value:String):void { if(this._customContentLabelStyleName == value) { return; } this._customContentLabelStyleName = value; this.invalidate(INVALIDATION_FLAG_TEXT_RENDERER); } /** * @private */ protected var _contentLabelProperties:PropertyProxy; /** * An object that stores properties for the content label text renderer * sub-component, and the properties will be passed down to the * text renderer when this component validates. The available properties * depend on which ITextRenderer implementation is returned * by contentLabelFactory. Refer to * feathers.core.ITextRenderer * for a list of available text renderer implementations. * *

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

In the following example, a custom content label properties are * customized:

* * * renderer.contentLabelProperties.textFormat = new TextFormat( "Source Sans Pro", 16, 0x333333 ); * renderer.contentLabelProperties.embedFonts = true; * * @default null * * @see feathers.core.ITextRenderer * @see #contentLabelField * @see #contentLabelFunction */ public function get contentLabelProperties():Object { if(!this._contentLabelProperties) { this._contentLabelProperties = new PropertyProxy(contentLabelProperties_onChange); } return this._contentLabelProperties; } /** * @private */ public function set contentLabelProperties(value:Object):void { if(this._contentLabelProperties == 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._contentLabelProperties) { this._contentLabelProperties.removeOnChangeCallback(contentLabelProperties_onChange); } this._contentLabelProperties = PropertyProxy(value); if(this._contentLabelProperties) { this._contentLabelProperties.addOnChangeCallback(contentLabelProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var originalBackgroundWidth:Number = NaN; /** * @private */ protected var originalBackgroundHeight:Number = NaN; /** * @private */ protected var currentBackgroundSkin:DisplayObject; /** * @private */ protected var _backgroundSkin:DisplayObject; /** * A background to behind the component's content. * *

In the following example, the header renderers is given a * background skin:

* * * renderer.backgroundSkin = new Image( texture ); * * @default null */ public function get backgroundSkin():DisplayObject { return this._backgroundSkin; } /** * @private */ public function set backgroundSkin(value:DisplayObject):void { if(this._backgroundSkin == value) { return; } if(this._backgroundSkin && this._backgroundSkin != this._backgroundDisabledSkin) { this.removeChild(this._backgroundSkin); } this._backgroundSkin = value; if(this._backgroundSkin && this._backgroundSkin.parent != this) { this._backgroundSkin.visible = false; this.addChildAt(this._backgroundSkin, 0); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _backgroundDisabledSkin:DisplayObject; /** * A background to display when the component is disabled. * *

In the following example, the header renderers is given a * disabled background skin:

* * * renderer.backgroundDisabledSkin = new Image( texture ); * * @default null */ public function get backgroundDisabledSkin():DisplayObject { return this._backgroundDisabledSkin; } /** * @private */ public function set backgroundDisabledSkin(value:DisplayObject):void { if(this._backgroundDisabledSkin == value) { return; } if(this._backgroundDisabledSkin && this._backgroundDisabledSkin != this._backgroundSkin) { this.removeChild(this._backgroundDisabledSkin); } this._backgroundDisabledSkin = value; if(this._backgroundDisabledSkin && this._backgroundDisabledSkin.parent != this) { this._backgroundDisabledSkin.visible = false; this.addChildAt(this._backgroundDisabledSkin, 0); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * Quickly sets all padding properties to the same value. The * padding getter always returns the value of * paddingTop, but the other padding values may be * different. * *

In the following example, the padding is set to 20 pixels:

* * * renderer.padding = 20; * * @default 0 */ public function get padding():Number { return this._paddingTop; } /** * @private */ public function set padding(value:Number):void { this.paddingTop = value; this.paddingRight = value; this.paddingBottom = value; this.paddingLeft = value; } /** * @private */ protected var _paddingTop:Number = 0; /** * The minimum space, in pixels, between the component's top edge and * the component's content. * *

In the following example, the top padding is set to 20 pixels:

* * * renderer.paddingTop = 20; * * @default 0 */ public function get paddingTop():Number { return this._paddingTop; } /** * @private */ public function set paddingTop(value:Number):void { if(this._paddingTop == value) { return; } this._paddingTop = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _paddingRight:Number = 0; /** * The minimum space, in pixels, between the component's right edge * and the component's content. * *

In the following example, the right padding is set to 20 pixels:

* * * renderer.paddingRight = 20; * * @default 0 */ public function get paddingRight():Number { return this._paddingRight; } /** * @private */ public function set paddingRight(value:Number):void { if(this._paddingRight == value) { return; } this._paddingRight = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _paddingBottom:Number = 0; /** * The minimum space, in pixels, between the component's bottom edge * and the component's content. * *

In the following example, the bottom padding is set to 20 pixels:

* * * renderer.paddingBottom = 20; * * @default 0 */ public function get paddingBottom():Number { return this._paddingBottom; } /** * @private */ public function set paddingBottom(value:Number):void { if(this._paddingBottom == value) { return; } this._paddingBottom = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _paddingLeft:Number = 0; /** * The minimum space, in pixels, between the component's left edge * and the component's content. * *

In the following example, the left padding is set to 20 pixels:

* * * renderer.paddingLeft = 20; * * @default 0 */ public function get paddingLeft():Number { return this._paddingLeft; } /** * @private */ public function set paddingLeft(value:Number):void { if(this._paddingLeft == value) { return; } this._paddingLeft = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ override public function dispose():void { //the content may have come from outside of this class. it's up //to that code to dispose of the content. in fact, if we disposed //of it here, we might screw something up! if(this.content) { this.content.removeFromParent(); } //however, we need to dispose these, if they exist, since we made //them here. if(this.contentImage) { this.contentImage.dispose(); this.contentImage = null; } if(this.contentLabel) { DisplayObject(this.contentLabel).dispose(); this.contentLabel = null; } super.dispose(); } /** * Uses the content fields and functions to generate content for a * specific group header or footer. * *

All of the content fields and functions, ordered by priority:

*
    *
  1. contentTextureFunction
  2. *
  3. contentTextureField
  4. *
  5. contentLabelFunction
  6. *
  7. contentLabelField
  8. *
  9. contentFunction
  10. *
  11. contentField
  12. *
*/ protected function itemToContent(item:Object):DisplayObject { if(this._contentSourceFunction != null) { var source:Object = this._contentSourceFunction(item); this.refreshContentSource(source); return this.contentImage; } else if(this._contentSourceField != null && item && item.hasOwnProperty(this._contentSourceField)) { source = item[this._contentSourceField]; this.refreshContentSource(source); return this.contentImage; } else if(this._contentLabelFunction != null) { var labelResult:Object = this._contentLabelFunction(item); if(labelResult is String) { this.refreshContentLabel(labelResult as String); } else { this.refreshContentLabel(labelResult.toString()); } return DisplayObject(this.contentLabel); } else if(this._contentLabelField != null && item && item.hasOwnProperty(this._contentLabelField)) { labelResult = item[this._contentLabelField]; if(labelResult is String) { this.refreshContentLabel(labelResult as String); } else { this.refreshContentLabel(labelResult.toString()); } return DisplayObject(this.contentLabel); } else if(this._contentFunction != null) { return this._contentFunction(item) as DisplayObject; } else if(this._contentField != null && item && item.hasOwnProperty(this._contentField)) { return item[this._contentField] as DisplayObject; } else if(item is String) { this.refreshContentLabel(item as String); return DisplayObject(this.contentLabel); } else if(item) { this.refreshContentLabel(item.toString()); return DisplayObject(this.contentLabel); } return null; } /** * @private */ override protected function draw():void { var dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA); var stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES); var stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE); var sizeInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE); if(stylesInvalid || stateInvalid) { this.refreshBackgroundSkin(); } if(dataInvalid) { this.commitData(); } if(dataInvalid || stylesInvalid) { this.refreshContentLabelStyles(); } if(dataInvalid || stateInvalid) { this.refreshEnabled(); } sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid; if(dataInvalid || stylesInvalid || sizeInvalid) { this.layout(); } if(sizeInvalid || stylesInvalid || stateInvalid) { if(this.currentBackgroundSkin) { this.currentBackgroundSkin.width = this.actualWidth; this.currentBackgroundSkin.height = this.actualHeight; } } } /** * If the component's dimensions have not been set explicitly, it will * measure its content and determine an ideal size for itself. If the * explicitWidth or explicitHeight member * variables are set, those value will be used without additional * measurement. If one is set, but not the other, the dimension with the * explicit value will not be measured, but the other non-explicit * dimension will still need measurement. * *

Calls setSizeInternal() to set up the * actualWidth and actualHeight member * variables used for layout.

* *

Meant for internal use, and subclasses may override this function * with a custom implementation.

*/ 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.content) { return this.setSizeInternal(0, 0, false); } if(this.contentLabel) { //special case for label to allow word wrap var labelMaxWidth:Number = this._explicitWidth; if(needsWidth) { labelMaxWidth = this._maxWidth; } this.contentLabel.maxWidth = labelMaxWidth - this._paddingLeft - this._paddingRight; } if(this._horizontalAlign == HorizontalAlign.JUSTIFY) { this.content.width = this._explicitWidth - this._paddingLeft - this._paddingRight; } if(this._verticalAlign == VerticalAlign.JUSTIFY) { this.content.height = this._explicitHeight - this._paddingTop - this._paddingBottom; } if(this.content is IValidating) { IValidating(this.content).validate(); } var newWidth:Number = this._explicitWidth; var newHeight:Number = this._explicitHeight; if(needsWidth) { newWidth = this.content.width + this._paddingLeft + this._paddingRight; if(this.originalBackgroundWidth === this.originalBackgroundWidth && //!isNaN this.originalBackgroundWidth > newWidth) { newWidth = this.originalBackgroundWidth; } } if(needsHeight) { newHeight = this.content.height + this._paddingTop + this._paddingBottom; if(this.originalBackgroundHeight === this.originalBackgroundHeight && //!isNaN this.originalBackgroundHeight > newHeight) { newHeight = this.originalBackgroundHeight; } } return this.setSizeInternal(newWidth, newHeight, false); } /** * @private */ protected function refreshBackgroundSkin():void { this.currentBackgroundSkin = this._backgroundSkin; if(!this._isEnabled && this._backgroundDisabledSkin) { if(this._backgroundSkin) { this._backgroundSkin.visible = false; } this.currentBackgroundSkin = this._backgroundDisabledSkin; } else if(this._backgroundDisabledSkin) { this._backgroundDisabledSkin.visible = false; } if(this.currentBackgroundSkin) { if(this.originalBackgroundWidth !== this.originalBackgroundWidth) //isNaN { this.originalBackgroundWidth = this.currentBackgroundSkin.width; } if(this.originalBackgroundHeight !== this.originalBackgroundHeight) //isNaN { this.originalBackgroundHeight = this.currentBackgroundSkin.height; } this.currentBackgroundSkin.visible = true; } } /** * @private */ protected function commitData():void { if(this._owner) { var newContent:DisplayObject = this.itemToContent(this._data); if(newContent != this.content) { if(this.content) { this.content.removeFromParent(); } this.content = newContent; if(this.content) { this.addChild(this.content); } } } else { if(this.content) { this.content.removeFromParent(); this.content = null; } } } /** * @private */ protected function refreshContentSource(source:Object):void { if(!this.contentImage) { this.contentImage = this._contentLoaderFactory(); } this.contentImage.source = source; } /** * @private */ protected function refreshContentLabel(label:String):void { if(label !== null) { if(!this.contentLabel) { var factory:Function = this._contentLabelFactory != null ? this._contentLabelFactory : FeathersControl.defaultTextRendererFactory; this.contentLabel = ITextRenderer(factory()); var contentLabelStyleName:String = this._customContentLabelStyleName != null ? this._customContentLabelStyleName : this.contentLabelStyleName; FeathersControl(this.contentLabel).styleNameList.add(contentLabelStyleName); } this.contentLabel.text = label; } else if(this.contentLabel) { DisplayObject(this.contentLabel).removeFromParent(true); this.contentLabel = null; } } /** * @private */ protected function refreshEnabled():void { if(this.content is IFeathersControl) { IFeathersControl(this.content).isEnabled = this._isEnabled; } } /** * @private */ protected function refreshContentLabelStyles():void { if(!this.contentLabel) { return; } for(var propertyName:String in this._contentLabelProperties) { var propertyValue:Object = this._contentLabelProperties[propertyName]; this.contentLabel[propertyName] = propertyValue; } } /** * @private */ protected function layout():void { if(!this.content) { return; } if(this.contentLabel) { this.contentLabel.maxWidth = this.actualWidth - this._paddingLeft - this._paddingRight; } switch(this._horizontalAlign) { case HorizontalAlign.CENTER: { this.content.x = this._paddingLeft + (this.actualWidth - this._paddingLeft - this._paddingRight - this.content.width) / 2; break; } case HorizontalAlign.RIGHT: { this.content.x = this.actualWidth - this._paddingRight - this.content.width; break; } case HorizontalAlign.JUSTIFY: { this.content.x = this._paddingLeft; this.content.width = this.actualWidth - this._paddingLeft - this._paddingRight; break; } default: //left { this.content.x = this._paddingLeft; } } switch(this._verticalAlign) { case VerticalAlign.TOP: { this.content.y = this._paddingTop; break; } case VerticalAlign.BOTTOM: { this.content.y = this.actualHeight - this._paddingBottom - this.content.height; break; } case VerticalAlign.JUSTIFY: { this.content.y = this._paddingTop; this.content.height = this.actualHeight - this._paddingTop - this._paddingBottom; break; } default: //middle { this.content.y = this._paddingTop + (this.actualHeight - this._paddingTop - this._paddingBottom - this.content.height) / 2; } } } /** * @private */ protected function contentLabelProperties_onChange(proxy:PropertyProxy, name:String):void { this.invalidate(INVALIDATION_FLAG_STYLES); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy