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

scaffold.libs_as.feathers.controls.Label.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.FeathersControl;
	import feathers.core.IFeathersControl;
	import feathers.core.ITextBaselineControl;
	import feathers.core.ITextRenderer;
	import feathers.core.IToolTip;
	import feathers.core.PropertyProxy;
	import feathers.skins.IStyleProvider;

	import flash.geom.Point;

	import starling.display.DisplayObject;

	/**
	 * Displays text using a text renderer.
	 *
	 * @see ../../../help/label.html How to use the Feathers Label component
	 * @see ../../../help/text-renderers.html Introduction to Feathers text renderers
	 */
	public class Label extends FeathersControl implements ITextBaselineControl, IToolTip
	{
		/**
		 * @private
		 */
		private static const HELPER_POINT:Point = new Point();

		/**
		 * An alternate style name to use with Label to allow a
		 * theme to give it a larger style meant for headings. If a theme does
		 * not provide a style for a heading label, the theme will automatically
		 * fall back to using the default style for a label.
		 *
		 * 

An alternate style name should always be added to a component's * styleNameList before the component is initialized. If * the style name is added later, it will be ignored.

* *

In the following example, the heading style is applied to a label:

* * * var label:Label = new Label(); * label.text = "Very Important Heading"; * label.styleNameList.add( Label.ALTERNATE_STYLE_NAME_HEADING ); * this.addChild( label ); * * @see feathers.core.FeathersControl#styleNameList */ public static const ALTERNATE_STYLE_NAME_HEADING:String = "feathers-heading-label"; /** * An alternate style name to use with Label to allow a * theme to give it a smaller style meant for less-important details. If * a theme does not provide a style for a detail label, the theme will * automatically fall back to using the default style for a label. * *

An alternate style name should always be added to a component's * styleNameList before the component is initialized. If * the style name is added later, it will be ignored.

* *

In the following example, the detail style is applied to a label:

* * * var label:Label = new Label(); * label.text = "Less important, detailed text"; * label.styleNameList.add( Label.ALTERNATE_STYLE_NAME_DETAIL ); * this.addChild( label ); * * @see feathers.core.FeathersControl#styleNameList */ public static const ALTERNATE_STYLE_NAME_DETAIL:String = "feathers-detail-label"; /** * An alternate style name to use with Label to allow a * theme to give it a tool tip style for use with the tool tip manager. * If a theme does not provide a style for a tool tip label, the theme * will automatically fall back to using the default style for a label. * *

An alternate style name should always be added to a component's * styleNameList before the component is initialized. If * the style name is added later, it will be ignored.

* * @see feathers.core.FeathersControl#styleNameList */ public static const ALTERNATE_STYLE_NAME_TOOL_TIP:String = "feathers-tool-tip"; /** * The default IStyleProvider for all Label * components. * * @default null * @see feathers.core.FeathersControl#styleProvider */ public static var globalStyleProvider:IStyleProvider; /** * Constructor. */ public function Label() { super(); this.isQuickHitAreaEnabled = true; } /** * The text renderer. * * @see #createTextRenderer() * @see #textRendererFactory */ protected var textRenderer:ITextRenderer; /** * @private */ override protected function get defaultStyleProvider():IStyleProvider { return Label.globalStyleProvider; } /** * @private */ protected var _text:String = null; /** * The text displayed by the label. * *

In the following example, the label's text is updated:

* * * label.text = "Hello World"; * * @default null */ public function get text():String { return this._text; } /** * @private */ public function set text(value:String):void { if(this._text == value) { return; } this._text = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _wordWrap:Boolean = false; /** * Determines if the text wraps to the next line when it reaches the * width (or max width) of the component. * *

In the following example, the label's text is wrapped:

* * * label.wordWrap = true; * * @default false */ public function get wordWrap():Boolean { return this._wordWrap; } /** * @private */ public function set wordWrap(value:Boolean):void { if(this._wordWrap == value) { return; } this._wordWrap = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * The baseline measurement of the text, in pixels. */ public function get baseline():Number { if(!this.textRenderer) { return this.scaledActualHeight; } return this.scaleY * (this.textRenderer.y + this.textRenderer.baseline); } /** * @private */ protected var _textRendererFactory:Function; /** * A function used to instantiate the label's text renderer * sub-component. By default, the label will use the global text * renderer factory, FeathersControl.defaultTextRendererFactory(), * to create the text renderer. The text renderer must be an instance of * ITextRenderer. This factory can be used to change * properties on the text renderer when it is first created. For * instance, if you are skinning Feathers components without a theme, * you might use this factory to style the text renderer. * *

The factory should have the following function signature:

*
function():ITextRenderer
* *

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

* * * label.textRendererFactory = function():ITextRenderer * { * return new TextFieldTextRenderer(); * } * * @default null * * @see feathers.core.ITextRenderer * @see feathers.core.FeathersControl#defaultTextRendererFactory */ public function get textRendererFactory():Function { return this._textRendererFactory; } /** * @private */ public function set textRendererFactory(value:Function):void { if(this._textRendererFactory == value) { return; } this._textRendererFactory = value; this.invalidate(INVALIDATION_FLAG_TEXT_RENDERER); } /** * @private */ protected var _textRendererProperties:PropertyProxy; /** * An object that stores properties for the label's text renderer * sub-component, and the properties will be passed down to the text * renderer when the label validates. The available properties * depend on which ITextRenderer implementation is returned * by textRendererFactory. 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);
* *

Setting properties in a textRendererFactory function * instead of using textRendererProperties will result in * better performance.

* *

In the following example, the label's text renderer's properties * are updated (this example assumes that the label text renderer is a * TextFieldTextRenderer):

* * * label.textRendererProperties.textFormat = new TextFormat( "Source Sans Pro", 16, 0x333333 ); * label.textRendererProperties.embedFonts = true; * * @default null * * @see #textRendererFactory * @see feathers.core.ITextRenderer */ public function get textRendererProperties():Object { if(!this._textRendererProperties) { this._textRendererProperties = new PropertyProxy(textRendererProperties_onChange); } return this._textRendererProperties; } /** * @private */ public function set textRendererProperties(value:Object):void { if(this._textRendererProperties == value) { return; } if(value && !(value is PropertyProxy)) { value = PropertyProxy.fromObject(value); } if(this._textRendererProperties) { this._textRendererProperties.removeOnChangeCallback(textRendererProperties_onChange); } this._textRendererProperties = PropertyProxy(value); if(this._textRendererProperties) { this._textRendererProperties.addOnChangeCallback(textRendererProperties_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; /** * The default background to display behind the label's text. * *

In the following example, the label is given a background skin:

* * * label.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.currentBackgroundSkin == this._backgroundSkin) { this.removeChild(this._backgroundSkin); this.currentBackgroundSkin = null; } this._backgroundSkin = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _backgroundDisabledSkin:DisplayObject; /** * A background to display when the label is disabled. * *

In the following example, the label is given a disabled background skin:

* * * label.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.currentBackgroundSkin == this._backgroundDisabledSkin) { this.removeChild(this._backgroundDisabledSkin); this.currentBackgroundSkin = null; } this._backgroundDisabledSkin = value; 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:

* * * label.padding = 20; * * @default 0 * * @see #paddingTop * @see #paddingRight * @see #paddingBottom * @see #paddingLeft */ 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 label's top edge and the * label's text. * *

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

* * * label.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 label's right edge and * the label's text. * *

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

* * * label.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 label's bottom edge and * the label's text. * *

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

* * * label.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 label's left edge and the * label's text. * *

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

* * * label.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 protected function draw():void { var dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA); var stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES); var sizeInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE); var stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE); var textRendererInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_TEXT_RENDERER); if(sizeInvalid || stylesInvalid || stateInvalid) { this.refreshBackgroundSkin(); } if(textRendererInvalid) { this.createTextRenderer(); } if(textRendererInvalid || dataInvalid || stateInvalid) { this.refreshTextRendererData(); } if(textRendererInvalid || stateInvalid) { this.refreshEnabled(); } if(textRendererInvalid || stylesInvalid || stateInvalid) { this.refreshTextRendererStyles(); } sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid; this.layoutChildren(); } /** * 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 var needsMinWidth:Boolean = this._explicitMinWidth !== this._explicitMinWidth; //isNaN var needsMinHeight:Boolean = this._explicitMinHeight !== this._explicitMinHeight; //isNaN if(!needsWidth && !needsHeight && !needsMinWidth && !needsMinHeight) { return false; } this.textRenderer.minWidth = this._explicitMinWidth - this._paddingLeft - this._paddingRight; this.textRenderer.maxWidth = this._maxWidth - this._paddingLeft - this._paddingRight; this.textRenderer.width = this._explicitWidth - this._paddingLeft - this._paddingRight; this.textRenderer.minHeight = this._explicitMinHeight - this._paddingTop - this._paddingBottom; this.textRenderer.maxHeight = this._maxHeight - this._paddingTop - this._paddingBottom; this.textRenderer.height = this._explicitHeight - this._paddingTop - this._paddingBottom; this.textRenderer.measureText(HELPER_POINT); if(this.currentBackgroundSkin is IFeathersControl) { var feathersBackground:IFeathersControl = IFeathersControl(this.currentBackgroundSkin); feathersBackground.validate(); } //minimum dimensions var newMinWidth:Number = this._explicitMinWidth; if(needsMinWidth) { if(this._text) { newMinWidth = HELPER_POINT.x; } else { newMinWidth = 0; } newMinWidth += this._paddingLeft + this._paddingRight; var backgroundMinWidth:Number = 0; if(this.currentBackgroundSkin is IFeathersControl) { backgroundMinWidth = IFeathersControl(this.currentBackgroundSkin).minWidth; } else if(this.originalBackgroundWidth === this.originalBackgroundWidth) //!isNaN { backgroundMinWidth = this.originalBackgroundWidth; } if(backgroundMinWidth > newMinWidth) { newMinWidth = backgroundMinWidth; } } var newMinHeight:Number = this._explicitMinHeight; if(needsMinHeight) { if(this._text) { newMinHeight = HELPER_POINT.y; } else { newMinHeight = 0; } newMinHeight += this._paddingTop + this._paddingBottom; var backgroundMinHeight:Number = 0; if(this.currentBackgroundSkin is IFeathersControl) { backgroundMinHeight = IFeathersControl(this.currentBackgroundSkin).minHeight; } else if(this.originalBackgroundHeight === this.originalBackgroundHeight) //!isNaN { backgroundMinHeight = this.originalBackgroundHeight; } if(backgroundMinHeight > newMinHeight) { newMinHeight = backgroundMinHeight; } } var newWidth:Number = this._explicitWidth; if(needsWidth) { if(this._text) { newWidth = HELPER_POINT.x; } else { newWidth = 0; } newWidth += this._paddingLeft + this._paddingRight; if(this.originalBackgroundWidth === this.originalBackgroundWidth && this.originalBackgroundWidth > newWidth) //!isNaN { newWidth = this.originalBackgroundWidth; } } var newHeight:Number = this._explicitHeight; if(needsHeight) { if(this._text) { newHeight = HELPER_POINT.y; } else { newHeight = 0; } newHeight += this._paddingTop + this._paddingBottom; if(this.originalBackgroundHeight === this.originalBackgroundHeight && this.originalBackgroundHeight > newHeight) //!isNaN { newHeight = this.originalBackgroundHeight; } } return this.saveMeasurements(newWidth, newHeight, newMinWidth, newMinHeight); } /** * Creates and adds the textRenderer 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 #textRenderer * @see #textRendererFactory */ protected function createTextRenderer():void { if(this.textRenderer) { this.removeChild(DisplayObject(this.textRenderer), true); this.textRenderer = null; } var factory:Function = this._textRendererFactory != null ? this._textRendererFactory : FeathersControl.defaultTextRendererFactory; this.textRenderer = ITextRenderer(factory()); this.addChild(DisplayObject(this.textRenderer)); } /** * Choose the appropriate background skin based on the control's current * state. */ protected function refreshBackgroundSkin():void { var newCurrentBackgroundSkin:DisplayObject = this._backgroundSkin; if(!this._isEnabled && this._backgroundDisabledSkin) { newCurrentBackgroundSkin = this._backgroundDisabledSkin; } if(this.currentBackgroundSkin != newCurrentBackgroundSkin) { if(this.currentBackgroundSkin) { this.removeChild(this.currentBackgroundSkin); } this.currentBackgroundSkin = newCurrentBackgroundSkin; if(this.currentBackgroundSkin) { this.addChildAt(this.currentBackgroundSkin, 0); } } if(this.currentBackgroundSkin) { //force it to the bottom this.setChildIndex(this.currentBackgroundSkin, 0); if(this.originalBackgroundWidth !== this.originalBackgroundWidth) //isNaN { this.originalBackgroundWidth = this.currentBackgroundSkin.width; } if(this.originalBackgroundHeight !== this.originalBackgroundHeight) //isNaN { this.originalBackgroundHeight = this.currentBackgroundSkin.height; } } } /** * Positions and sizes children based on the actual width and height * values. */ protected function layoutChildren():void { if(this.currentBackgroundSkin) { this.currentBackgroundSkin.x = 0; this.currentBackgroundSkin.y = 0; this.currentBackgroundSkin.width = this.actualWidth; this.currentBackgroundSkin.height = this.actualHeight; } this.textRenderer.x = this._paddingLeft; this.textRenderer.y = this._paddingTop; this.textRenderer.width = this.actualWidth - this._paddingLeft - this._paddingRight; this.textRenderer.height = this.actualHeight - this._paddingTop - this._paddingBottom; this.textRenderer.validate(); } /** * @private */ protected function refreshEnabled():void { this.textRenderer.isEnabled = this._isEnabled; } /** * @private */ protected function refreshTextRendererData():void { this.textRenderer.text = this._text; this.textRenderer.visible = this._text && this._text.length > 0; } /** * @private */ protected function refreshTextRendererStyles():void { this.textRenderer.wordWrap = this._wordWrap; for(var propertyName:String in this._textRendererProperties) { var propertyValue:Object = this._textRendererProperties[propertyName]; this.textRenderer[propertyName] = propertyValue; } } /** * @private */ protected function textRendererProperties_onChange(proxy:PropertyProxy, propertyName:String):void { this.invalidate(INVALIDATION_FLAG_STYLES); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy