Last active
August 29, 2015 14:20
-
-
Save kheftel-old/4c52f210f083f9503a45 to your computer and use it in GitHub Desktop.
Starling Auto-Size Button Labels with Feathers 1.3.1 - uses Starling TextField to allow button labels to automatically resize to fit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package { | |
import starling.display.Sprite; | |
public class app extends Sprite | |
{ | |
function app() | |
{ | |
var btn:Button = new Button(); | |
btn.nameList.add('buttonAutoScale'); | |
btn.label = 'Click Me!'; | |
btn.width = 100; | |
btn.height = 100; | |
addChild(btn); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package feathers.controls.text | |
{ | |
import flash.geom.Matrix; | |
import flash.geom.Point; | |
import flash.text.TextFieldAutoSize; | |
import feathers.core.FeathersControl; | |
import feathers.core.ITextRenderer; | |
import starling.core.RenderSupport; | |
import starling.events.Event; | |
import starling.text.TextField; | |
import starling.utils.HAlign; | |
import starling.utils.VAlign; | |
/** | |
* Renders text that autosizes to fill an area. Uses a Starling <code>starling.text.TextField</code>. | |
* | |
* Note: width and height must be explicitly set for this to work properly! | |
* | |
* @see http://wiki.starling-framework.org/feathers/text-renderers | |
* @see starling.text.TextField | |
*/ | |
public class AutoSizeTextRenderer extends FeathersControl implements ITextRenderer | |
{ | |
/** | |
* @private | |
*/ | |
private static const HELPER_POINT:Point = new Point(); | |
/** | |
* @private | |
*/ | |
private static const HELPER_MATRIX:Matrix = new Matrix(); | |
/** | |
* Constructor. | |
*/ | |
public function AutoSizeTextRenderer() | |
{ | |
this.isQuickHitAreaEnabled = true; | |
this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); | |
} | |
/** | |
* The TextField instance used to render the text. | |
*/ | |
protected var textField:TextField; | |
/** | |
* @private | |
*/ | |
protected var _text:String = ""; | |
public function get vAlign():String | |
{ | |
return _vAlign; | |
} | |
public function set vAlign(value:String):void | |
{ | |
_vAlign = value; | |
} | |
public function get hAlign():String | |
{ | |
return _hAlign; | |
} | |
public function set hAlign(value:String):void | |
{ | |
_hAlign = value; | |
} | |
public function get italic():Boolean | |
{ | |
return _italic; | |
} | |
public function set italic(value:Boolean):void | |
{ | |
_italic = value; | |
} | |
public function get fontSize():Number | |
{ | |
return _fontSize; | |
} | |
public function set fontSize(value:Number):void | |
{ | |
_fontSize = value; | |
} | |
public function get fontName():String | |
{ | |
return _fontName; | |
} | |
public function set fontName(value:String):void | |
{ | |
_fontName = value; | |
} | |
public function get color():uint | |
{ | |
return _color; | |
} | |
public function set color(value:uint):void | |
{ | |
_color = value; | |
} | |
public function get bold():Boolean | |
{ | |
return _bold; | |
} | |
public function set bold(value:Boolean):void | |
{ | |
_bold = value; | |
} | |
public function get autoScale():Boolean | |
{ | |
return _autoScale; | |
} | |
/** | |
* @inheritDoc | |
* | |
* <p>In the following example, the text is changed:</p> | |
* | |
* <listing version="3.0"> | |
* textRenderer.text = "Lorem ipsum";</listing> | |
* | |
* @default "" | |
*/ | |
public function get text():String | |
{ | |
return this._text; | |
} | |
/** | |
* @private | |
*/ | |
public function set text(value:String):void | |
{ | |
if(this._text == value) | |
{ | |
return; | |
} | |
if(value === null) | |
{ | |
//flash.text.TextField won't accept a null value - not sure about starling.text.TextField | |
value = ""; | |
} | |
this._text = value; | |
this.invalidate(INVALIDATION_FLAG_DATA); | |
} | |
/** | |
* @inheritDoc | |
*/ | |
public function get baseline():Number | |
{ | |
return explicitHeight; | |
} | |
/** | |
* @private | |
*/ | |
private var _border:Boolean = false; | |
/** | |
* Same as the TextField property with the same name. | |
* | |
* @default false | |
* | |
* @see starling.text.TextField#border | |
*/ | |
public function get border():Boolean | |
{ | |
return this._border; | |
} | |
/** | |
* @private | |
*/ | |
public function set border(value:Boolean):void | |
{ | |
if(this._border == value) | |
{ | |
return; | |
} | |
this._border = value; | |
this.invalidate(INVALIDATION_FLAG_STYLES); | |
} | |
/** | |
* @private | |
*/ | |
protected var _nativeFilters:Array = null; | |
protected var _autoScale:Boolean = true; | |
protected var _bold:Boolean = false; | |
protected var _color:uint; | |
protected var _fontName:String; | |
protected var _fontSize:Number; | |
protected var _italic:Boolean = false; | |
protected var _hAlign:String = HAlign.CENTER; | |
protected var _vAlign:String = VAlign.CENTER; | |
/** | |
* Native filters to pass to the <code>flash.text.TextField</code> | |
* before creating the texture snapshot. | |
* | |
* <p>In the following example, the native filters are changed:</p> | |
* | |
* <listing version="3.0"> | |
* renderer.nativeFilters = [ new GlowFilter() ];</listing> | |
* | |
* @default null | |
*/ | |
public function get nativeFilters():Array | |
{ | |
return this._nativeFilters; | |
} | |
/** | |
* @private | |
*/ | |
public function set nativeFilters(value:Array):void | |
{ | |
if(this._nativeFilters == value) | |
{ | |
return; | |
} | |
this._nativeFilters = value; | |
this.invalidate(INVALIDATION_FLAG_STYLES); | |
} | |
/** | |
* @inheritDoc | |
*/ | |
public function measureText(result:Point = null):Point | |
{ | |
if(!result) | |
{ | |
result = new Point(); | |
} | |
if(!this.textField) | |
{ | |
result.x = result.y = 0; | |
return result; | |
} | |
var needsWidth:Boolean = isNaN(this.explicitWidth); | |
var needsHeight:Boolean = isNaN(this.explicitHeight); | |
if(!needsWidth && !needsHeight) | |
{ | |
result.x = this.explicitWidth; | |
result.y = this.explicitHeight; | |
return result; | |
} | |
else | |
throw new ArgumentError('you must set width/height explicitly to use AutoSizeTextRenderer'); | |
} | |
/** | |
* @private | |
*/ | |
override protected function initialize():void | |
{ | |
if(!this.textField) | |
{ | |
this.textField = new TextField(10, 10, ""); | |
this.textField.touchable = false; | |
addChild(this.textField); | |
} | |
} | |
/** | |
* @private | |
*/ | |
override protected function draw():void | |
{ | |
var sizeInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE); | |
this.commit(); | |
sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid; | |
this.layout(sizeInvalid); | |
} | |
/** | |
* @private | |
*/ | |
protected function commit():void | |
{ | |
const stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES); | |
const dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA); | |
const stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE); | |
trace('styles: ' + stylesInvalid + ', data: ' + dataInvalid + ', state: ' + stateInvalid); | |
if(stylesInvalid) | |
{ | |
this.textField.autoScale = this._autoScale; | |
this.textField.bold = this._bold; | |
this.textField.border = this._border; | |
this.textField.color = this._color; | |
this.textField.fontName = this._fontName; | |
this.textField.fontSize = this._fontSize; | |
this.textField.italic = this._italic; | |
this.textField.hAlign = this._hAlign; | |
this.textField.vAlign = this._vAlign; | |
this.textField.nativeFilters = this._nativeFilters; | |
} | |
if(dataInvalid || stylesInvalid || stateInvalid) | |
{ | |
this.textField.text = this._text; | |
} | |
} | |
/** | |
* @private | |
*/ | |
protected function layout(sizeInvalid:Boolean):void | |
{ | |
var stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES); | |
var dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA); | |
if(sizeInvalid) | |
{ | |
this.textField.width = this.actualWidth; | |
this.textField.height = this.actualHeight; | |
} | |
} | |
/** | |
* this component always requires dimensions to be set explicitly | |
*/ | |
protected function autoSizeIfNeeded():Boolean | |
{ | |
const needsWidth:Boolean = isNaN(this.explicitWidth); | |
const needsHeight:Boolean = isNaN(this.explicitHeight); | |
if(needsWidth || needsHeight) | |
throw new ArgumentError('width/height must be set explicitly to use AutoSizeTextRenderer'); | |
return false; | |
} | |
/** | |
* @private | |
*/ | |
protected function addedToStageHandler(event:Event):void | |
{ | |
//we need to invalidate in order to get a fresh snapshot | |
this.invalidate(INVALIDATION_FLAG_SIZE); | |
} | |
/** | |
* @private | |
*/ | |
protected function enterFrameHandler(event:Event):void | |
{ | |
this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class theme extends DisplayListwatcher | |
{ | |
function theme() | |
{ | |
setInitializerForClass(Button, buttonInitializer, 'buttonAutoScale'); | |
} | |
private function initializeButton(b:Button):void | |
{ | |
b.labelFactory = function():ITextRenderer { | |
var r:AutoSizeTextRenderer = new AutoSizeTextRenderer(); | |
r.fontName = 'Verdana'; | |
r.fontSize = 20; | |
r.width = b.width - b.paddingRight - b.paddingLeft; | |
r.height = b.height - b.paddingTop - b.paddingBottom; | |
r.color = 0xFFFFFF; | |
r.nativeFilters = [new DropShadowFilter(2, 45, 0x021725, .48, 2, 2)]; | |
return r; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment