Advertisement
Guest User

Untitled

a guest
Mar 20th, 2020
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Feathers
  3. Copyright 2012-2013 Joshua Tynjala. All Rights Reserved.
  4.  
  5. This program is free software. You can redistribute and/or modify it in
  6. accordance with the terms of the accompanying license agreement.
  7. */
  8. package feathers.controls.text
  9. {
  10.     import feathers.core.FeathersControl;
  11.     import feathers.core.ITextEditor;
  12.     import feathers.events.FeathersEventType;
  13.     import feathers.text.StageTextField;
  14.     import feathers.utils.geom.matrixToScaleX;
  15.     import feathers.utils.geom.matrixToScaleY;
  16.  
  17.     import flash.display.BitmapData;
  18.     import flash.events.Event;
  19.     import flash.events.FocusEvent;
  20.     import flash.events.KeyboardEvent;
  21.     import flash.events.SoftKeyboardEvent;
  22.     import flash.geom.Matrix;
  23.     import flash.geom.Point;
  24.     import flash.geom.Rectangle;
  25.     import flash.text.TextField;
  26.     import flash.text.TextFieldAutoSize;
  27.     import flash.text.TextFormat;
  28.     import flash.text.TextFormatAlign;
  29.     import flash.text.engine.FontPosture;
  30.     import flash.text.engine.FontWeight;
  31.     import flash.ui.Keyboard;
  32.     import flash.utils.getDefinitionByName;
  33.  
  34.     import starling.core.RenderSupport;
  35.     import starling.core.Starling;
  36.     import starling.display.Image;
  37.     import starling.events.Event;
  38.     import starling.textures.ConcreteTexture;
  39.     import starling.textures.Texture;
  40.     import starling.utils.MatrixUtil;
  41.  
  42.     /**
  43.      * Dispatched when the text property changes.
  44.      */
  45.     [Event(name="change",type="starling.events.Event")]
  46.  
  47.     /**
  48.      * Dispatched when the user presses the Enter key while the editor has
  49.      * focus. This event may not be dispatched on some platforms, depending on
  50.      * the value of <code>returnKeyLabel</code>. This issue may even occur when
  51.      * using the <em>default value</em> of <code>returnKeyLabel</code>!
  52.      *
  53.      * @eventType feathers.events.FeathersEventType.ENTER
  54.      * @see #returnKeyLabel
  55.      * @see flash.text.ReturnKeyLabel
  56.      */
  57.     [Event(name="enter",type="starling.events.Event")]
  58.  
  59.     /**
  60.      * Dispatched when the text editor receives focus.
  61.      *
  62.      * @eventType feathers.events.FeathersEventType.FOCUS_IN
  63.      */
  64.     [Event(name="focusIn",type="starling.events.Event")]
  65.  
  66.     /**
  67.      * Dispatched when the text editor loses focus.
  68.      *
  69.      * @eventType feathers.events.FeathersEventType.FOCUS_OUT
  70.      */
  71.     [Event(name="focusOut",type="starling.events.Event")]
  72.  
  73.     /**
  74.      * Dispatched when the soft keyboard is activated. Not all text editors will
  75.      * activate a soft keyboard.
  76.      *
  77.      * @eventType feathers.events.FeathersEventType.SOFT_KEYBOARD_ACTIVATE
  78.      */
  79.     [Event(name="softKeyboardActivate",type="starling.events.Event")]
  80.  
  81.     /**
  82.      * Dispatched when the soft keyboard is deactivated. Not all text editors
  83.      * will activate a soft keyboard.
  84.      *
  85.      * @eventType feathers.events.FeathersEventType.SOFT_KEYBOARD_DEACTIVATE
  86.      */
  87.     [Event(name="softKeyboardDeactivate",type="starling.events.Event")]
  88.  
  89.     /**
  90.      * A Feathers text editor that uses the native <code>StageText</code> class
  91.      * in AIR, and the custom <code>StageTextField</code> class (that simulates
  92.      * <code>StageText</code>) in Flash Player.
  93.      *
  94.      * @see http://wiki.starling-framework.org/feathers/text-editors
  95.      * @see flash.text.StageText
  96.      * @see feathers.text.StageTextField
  97.      */
  98.     public class StageTextTextEditor extends FeathersControl implements ITextEditor
  99.     {
  100.         /**
  101.          * @private
  102.          */
  103.         private static const HELPER_MATRIX:Matrix = new Matrix();
  104.  
  105.         /**
  106.          * @private
  107.          */
  108.         private static const HELPER_POINT:Point = new Point();
  109.  
  110.         /**
  111.          * @private
  112.          */
  113.         protected static const INVALIDATION_FLAG_POSITION:String = "position";
  114.  
  115.         /**
  116.          * Constructor.
  117.          */
  118.         public function StageTextTextEditor()
  119.         {
  120.             this.isQuickHitAreaEnabled = true;
  121.             this.addEventListener(starling.events.Event.ADDED_TO_STAGE, addedToStageHandler);
  122.             this.addEventListener(starling.events.Event.REMOVED_FROM_STAGE, removedFromStageHandler);
  123.         }
  124.  
  125.         /**
  126.          * @private
  127.          */
  128.         override public function set x(value:Number):void
  129.         {
  130.             super.x = value;
  131.             //we need to know when the position changes to change the position
  132.             //of the StageText instance.
  133.             this.invalidate(INVALIDATION_FLAG_POSITION);
  134.         }
  135.  
  136.         /**
  137.          * @private
  138.          */
  139.         override public function set y(value:Number):void
  140.         {
  141.             super.y = value;
  142.             this.invalidate(INVALIDATION_FLAG_POSITION);
  143.         }
  144.  
  145.         /**
  146.          * The StageText instance. It's typed Object so that a replacement class
  147.          * can be used in browser-based Flash Player.
  148.          */
  149.         protected var stageText:Object;
  150.  
  151.         /**
  152.          * An image that displays a snapshot of the native <code>StageText</code>
  153.          * in the Starling display list when the editor doesn't have focus.
  154.          */
  155.         protected var textSnapshot:Image;
  156.  
  157.         /**
  158.          * @private
  159.          */
  160.         protected var _needsNewTexture:Boolean = false;
  161.  
  162.         /**
  163.          * @private
  164.          */
  165.         protected var _ignoreStageTextChanges:Boolean = false;
  166.  
  167.         /**
  168.          * @private
  169.          */
  170.         protected var _text:String = "";
  171.  
  172.         /**
  173.          * The text displayed by the input.
  174.          *
  175.          * <p>In the following example, the text is changed:</p>
  176.          *
  177.          * <listing version="3.0">
  178.          * textEditor.text = "Lorem ipsum";</listing>
  179.          *
  180.          * @default ""
  181.          */
  182.         public function get text():String
  183.         {
  184.             return this._text;
  185.         }
  186.  
  187.         /**
  188.          * @private
  189.          */
  190.         public function set text(value:String):void
  191.         {
  192.             if(!value)
  193.             {
  194.                 //don't allow null or undefined
  195.                 value = "";
  196.             }
  197.             if(this._text == value)
  198.             {
  199.                 return;
  200.             }
  201.             this._text = value;
  202.             this.invalidate(INVALIDATION_FLAG_DATA);
  203.             this.dispatchEventWith(starling.events.Event.CHANGE);
  204.         }
  205.  
  206.         /**
  207.          * @private
  208.          */
  209.         protected var _measureTextField:TextField;
  210.  
  211.         /**
  212.          * @private
  213.          */
  214.         protected var _stageTextHasFocus:Boolean = false;
  215.  
  216.         /**
  217.          * @private
  218.          */
  219.         protected var _isWaitingToSetFocus:Boolean = false;
  220.  
  221.         /**
  222.          * @private
  223.          */
  224.         protected var _pendingSelectionStartIndex:int = -1;
  225.  
  226.         /**
  227.          * @private
  228.          */
  229.         protected var _pendingSelectionEndIndex:int = -1;
  230.  
  231.         /**
  232.          * @private
  233.          */
  234.         protected var _stageTextIsComplete:Boolean = false;
  235.  
  236.         /**
  237.          * @private
  238.          */
  239.         protected var _oldGlobalX:Number = 0;
  240.  
  241.         /**
  242.          * @private
  243.          */
  244.         protected var _oldGlobalY:Number = 0;
  245.  
  246.         /**
  247.          * @private
  248.          */
  249.         protected var _autoCapitalize:String = "none";
  250.  
  251.         /**
  252.          * Same as the <code>StageText</code> property with the same name.
  253.          *
  254.          * <p>In the following example, the auto capitalize behavior is changed:</p>
  255.          *
  256.          * <listing version="3.0">
  257.          * textEditor.autoCapitalize = AutoCapitalize.WORD;</listing>
  258.          *
  259.          * @default flash.text.AutoCapitalize.NONE
  260.          */
  261.         public function get autoCapitalize():String
  262.         {
  263.             return this._autoCapitalize;
  264.         }
  265.  
  266.         /**
  267.          * @private
  268.          */
  269.         public function set autoCapitalize(value:String):void
  270.         {
  271.             if(this._autoCapitalize == value)
  272.             {
  273.                 return;
  274.             }
  275.             this._autoCapitalize = value;
  276.             this.invalidate(INVALIDATION_FLAG_STYLES);
  277.         }
  278.  
  279.         /**
  280.          * @private
  281.          */
  282.         protected var _autoCorrect:Boolean = false;
  283.  
  284.         /**
  285.          * Same as the <code>StageText</code> property with the same name.
  286.          *
  287.          * <p>In the following example, auto correct is enabled:</p>
  288.          *
  289.          * <listing version="3.0">
  290.          * textEditor.autoCorrect = true;</listing>
  291.          *
  292.          * @default false
  293.          */
  294.         public function get autoCorrect():Boolean
  295.         {
  296.             return this._autoCorrect;
  297.         }
  298.  
  299.         /**
  300.          * @private
  301.          */
  302.         public function set autoCorrect(value:Boolean):void
  303.         {
  304.             if(this._autoCorrect == value)
  305.             {
  306.                 return;
  307.             }
  308.             this._autoCorrect = value;
  309.             this.invalidate(INVALIDATION_FLAG_STYLES);
  310.         }
  311.  
  312.         /**
  313.          * @private
  314.          */
  315.         protected var _color:uint = 0x000000;
  316.  
  317.         /**
  318.          * Same as the <code>StageText</code> property with the same name.
  319.          *
  320.          * <p>In the following example, the text color is changed:</p>
  321.          *
  322.          * <listing version="3.0">
  323.          * textEditor.color = 0xff9900;</listing>
  324.          *
  325.          * @default 0x000000
  326.          */
  327.         public function get color():uint
  328.         {
  329.             return this._color as uint;
  330.         }
  331.  
  332.         /**
  333.          * @private
  334.          */
  335.         public function set color(value:uint):void
  336.         {
  337.             if(this._color == value)
  338.             {
  339.                 return;
  340.             }
  341.             this._color = value;
  342.             this.invalidate(INVALIDATION_FLAG_STYLES);
  343.         }
  344.  
  345.         /**
  346.          * @private
  347.          */
  348.         protected var _displayAsPassword:Boolean = false;
  349.  
  350.         /**
  351.          * Same as the <code>StageText</code> property with the same name.
  352.          *
  353.          * <p>In the following example, the text is displayed as a password:</p>
  354.          *
  355.          * <listing version="3.0">
  356.          * textEditor.displayAsPassword = true;</listing>
  357.          *
  358.          * @default false
  359.          */
  360.         public function get displayAsPassword():Boolean
  361.         {
  362.             return this._displayAsPassword;
  363.         }
  364.  
  365.         /**
  366.          * @private
  367.          */
  368.         public function set displayAsPassword(value:Boolean):void
  369.         {
  370.             if(this._displayAsPassword == value)
  371.             {
  372.                 return;
  373.             }
  374.             this._displayAsPassword = value;
  375.             this.invalidate(INVALIDATION_FLAG_STYLES);
  376.         }
  377.  
  378.         /**
  379.          * @private
  380.          */
  381.         protected var _isEditable:Boolean = true;
  382.  
  383.         /**
  384.          * Determines if the text input is editable. If the text input is not
  385.          * editable, it will still appear enabled.
  386.          *
  387.          * <p>In the following example, the text is not editable:</p>
  388.          *
  389.          * <listing version="3.0">
  390.          * textEditor.isEditable = false;</listing>
  391.          *
  392.          * @default true
  393.          */
  394.         public function get isEditable():Boolean
  395.         {
  396.             return this._isEditable;
  397.         }
  398.  
  399.         /**
  400.          * @private
  401.          */
  402.         public function set isEditable(value:Boolean):void
  403.         {
  404.             if(this._isEditable == value)
  405.             {
  406.                 return;
  407.             }
  408.             this._isEditable = value;
  409.             this.invalidate(INVALIDATION_FLAG_STYLES);
  410.         }
  411.  
  412.         /**
  413.          * @inheritDoc
  414.          *
  415.          * @default true
  416.          */
  417.         public function get setTouchFocusOnEndedPhase():Boolean
  418.         {
  419.             return true;
  420.         }
  421.  
  422.         /**
  423.          * @private
  424.          */
  425.         protected var _fontFamily:String = null;
  426.  
  427.         /**
  428.          * Same as the <code>StageText</code> property with the same name.
  429.          *
  430.          * <p>In the following example, the font family is changed:</p>
  431.          *
  432.          * <listing version="3.0">
  433.          * textEditor.fontFamily = "Source Sans Pro";</listing>
  434.          *
  435.          * @default null
  436.          */
  437.         public function get fontFamily():String
  438.         {
  439.             return this._fontFamily;
  440.         }
  441.  
  442.         /**
  443.          * @private
  444.          */
  445.         public function set fontFamily(value:String):void
  446.         {
  447.             if(this._fontFamily == value)
  448.             {
  449.                 return;
  450.             }
  451.             this._fontFamily = value;
  452.             this.invalidate(INVALIDATION_FLAG_STYLES);
  453.         }
  454.  
  455.         /**
  456.          * @private
  457.          */
  458.         protected var _fontPosture:String = FontPosture.NORMAL;
  459.  
  460.         /**
  461.          * Same as the <code>StageText</code> property with the same name.
  462.          *
  463.          * <p>In the following example, the font posture is changed:</p>
  464.          *
  465.          * <listing version="3.0">
  466.          * textEditor.fontPosture = FontPosture.ITALIC;</listing>
  467.          *
  468.          * @default flash.text.engine.FontPosture.NORMAL
  469.          */
  470.         public function get fontPosture():String
  471.         {
  472.             return this._fontPosture;
  473.         }
  474.  
  475.         /**
  476.          * @private
  477.          */
  478.         public function set fontPosture(value:String):void
  479.         {
  480.             if(this._fontPosture == value)
  481.             {
  482.                 return;
  483.             }
  484.             this._fontPosture = value;
  485.             this.invalidate(INVALIDATION_FLAG_STYLES);
  486.         }
  487.  
  488.         /**
  489.          * @private
  490.          */
  491.         protected var _fontSize:int = 12;
  492.  
  493.         /**
  494.          * Same as the <code>StageText</code> property with the same name.
  495.          *
  496.          * <p>In the following example, the font size is changed:</p>
  497.          *
  498.          * <listing version="3.0">
  499.          * textEditor.fontSize = 16;</listing>
  500.          *
  501.          * @default 12
  502.          */
  503.         public function get fontSize():int
  504.         {
  505.             return this._fontSize;
  506.         }
  507.  
  508.         /**
  509.          * @private
  510.          */
  511.         public function set fontSize(value:int):void
  512.         {
  513.             if(this._fontSize == value)
  514.             {
  515.                 return;
  516.             }
  517.             this._fontSize = value;
  518.             this.invalidate(INVALIDATION_FLAG_STYLES);
  519.         }
  520.  
  521.         /**
  522.          * @private
  523.          */
  524.         protected var _fontWeight:String = FontWeight.NORMAL;
  525.  
  526.         /**
  527.          * Same as the <code>StageText</code> property with the same name.
  528.          *
  529.          * <p>In the following example, the font weight is changed:</p>
  530.          *
  531.          * <listing version="3.0">
  532.          * textEditor.fontWeight = FontWeight.BOLD;</listing>
  533.          *
  534.          * @default flash.text.engine.FontWeight.NORMAL
  535.          */
  536.         public function get fontWeight():String
  537.         {
  538.             return this._fontWeight;
  539.         }
  540.  
  541.         /**
  542.          * @private
  543.          */
  544.         public function set fontWeight(value:String):void
  545.         {
  546.             if(this._fontWeight == value)
  547.             {
  548.                 return;
  549.             }
  550.             this._fontWeight = value;
  551.             this.invalidate(INVALIDATION_FLAG_STYLES);
  552.         }
  553.  
  554.         /**
  555.          * @private
  556.          */
  557.         protected var _locale:String = "en";
  558.  
  559.         /**
  560.          * Same as the <code>StageText</code> property with the same name.
  561.          *
  562.          * <p>In the following example, the locale is changed:</p>
  563.          *
  564.          * <listing version="3.0">
  565.          * textEditor.locale = "ru";</listing>
  566.          *
  567.          * @default "en"
  568.          */
  569.         public function get locale():String
  570.         {
  571.             return this._locale;
  572.         }
  573.  
  574.         /**
  575.          * @private
  576.          */
  577.         public function set locale(value:String):void
  578.         {
  579.             if(this._locale == value)
  580.             {
  581.                 return;
  582.             }
  583.             this._locale = value;
  584.             this.invalidate(INVALIDATION_FLAG_STYLES);
  585.         }
  586.  
  587.         /**
  588.          * @private
  589.          */
  590.         protected var _maxChars:int = 0;
  591.  
  592.         /**
  593.          * Same as the <code>StageText</code> property with the same name.
  594.          *
  595.          * <p>In the following example, the maximum character count is changed:</p>
  596.          *
  597.          * <listing version="3.0">
  598.          * textEditor.maxChars = 10;</listing>
  599.          *
  600.          * @default 0
  601.          */
  602.         public function get maxChars():int
  603.         {
  604.             return this._maxChars;
  605.         }
  606.  
  607.         /**
  608.          * @private
  609.          */
  610.         public function set maxChars(value:int):void
  611.         {
  612.             if(this._maxChars == value)
  613.             {
  614.                 return;
  615.             }
  616.             this._maxChars = value;
  617.             this.invalidate(INVALIDATION_FLAG_STYLES);
  618.         }
  619.  
  620.         /**
  621.          * @private
  622.          */
  623.         protected var _multiline:Boolean = false;
  624.  
  625.         /**
  626.          * Same as the <code>StageText</code> property with the same name,
  627.          * except it is configurable after the text renderer is created. The
  628.          * <code>StageText</code> instance will be disposed and recreated when
  629.          * this property changes after the <code>StageText</code> text was
  630.          * initially created.
  631.          *
  632.          * <p>In the following example, multiline is enabled:</p>
  633.          *
  634.          * <listing version="3.0">
  635.          * textEditor.multiline = true;</listing>
  636.          *
  637.          * @default false
  638.          */
  639.         public function get multiline():Boolean
  640.         {
  641.             return this._multiline;
  642.         }
  643.  
  644.         /**
  645.          * @private
  646.          */
  647.         public function set multiline(value:Boolean):void
  648.         {
  649.             if(this._multiline == value)
  650.             {
  651.                 return;
  652.             }
  653.             this._multiline = value;
  654.             this.invalidate(INVALIDATION_FLAG_STYLES);
  655.         }
  656.  
  657.         /**
  658.          * @private
  659.          */
  660.         protected var _restrict:String;
  661.  
  662.         /**
  663.          * Same as the <code>StageText</code> property with the same name.
  664.          *
  665.          * <p>In the following example, the text is restricted to numbers:</p>
  666.          *
  667.          * <listing version="3.0">
  668.          * textEditor.restrict = "0-9";</listing>
  669.          *
  670.          * @default null
  671.          */
  672.         public function get restrict():String
  673.         {
  674.             return this._restrict;
  675.         }
  676.  
  677.         /**
  678.          * @private
  679.          */
  680.         public function set restrict(value:String):void
  681.         {
  682.             if(this._restrict == value)
  683.             {
  684.                 return;
  685.             }
  686.             this._restrict = value;
  687.             this.invalidate(INVALIDATION_FLAG_STYLES);
  688.         }
  689.  
  690.         /**
  691.          * @private
  692.          */
  693.         protected var _returnKeyLabel:String = "default";
  694.  
  695.         /**
  696.          * Same as the <code>StageText</code> property with the same name.
  697.          *
  698.          * <p>In the following example, the return key label is changed:</p>
  699.          *
  700.          * <listing version="3.0">
  701.          * textEditor.returnKeyLabel = ReturnKeyLabel.GO;</listing>
  702.          *
  703.          * @default flash.text.ReturnKeyLabel.DEFAULT
  704.          */
  705.         public function get returnKeyLabel():String
  706.         {
  707.             return this._returnKeyLabel;
  708.         }
  709.  
  710.         /**
  711.          * @private
  712.          */
  713.         public function set returnKeyLabel(value:String):void
  714.         {
  715.             if(this._returnKeyLabel == value)
  716.             {
  717.                 return;
  718.             }
  719.             this._returnKeyLabel = value;
  720.             this.invalidate(INVALIDATION_FLAG_STYLES);
  721.         }
  722.  
  723.         /**
  724.          * @private
  725.          */
  726.         protected var _softKeyboardType:String = "default";
  727.  
  728.         /**
  729.          * Same as the <code>StageText</code> property with the same name.
  730.          *
  731.          * <p>In the following example, the soft keyboard type is changed:</p>
  732.          *
  733.          * <listing version="3.0">
  734.          * textEditor.softKeyboardType = SoftKeyboardType.NUMBER;</listing>
  735.          *
  736.          * @default flash.text.SoftKeyboardType.DEFAULT
  737.          */
  738.         public function get softKeyboardType():String
  739.         {
  740.             return this._softKeyboardType;
  741.         }
  742.  
  743.         /**
  744.          * @private
  745.          */
  746.         public function set softKeyboardType(value:String):void
  747.         {
  748.             if(this._softKeyboardType == value)
  749.             {
  750.                 return;
  751.             }
  752.             this._softKeyboardType = value;
  753.             this.invalidate(INVALIDATION_FLAG_STYLES);
  754.         }
  755.  
  756.         /**
  757.          * @private
  758.          */
  759.         protected var _textAlign:String = TextFormatAlign.START;
  760.  
  761.         /**
  762.          * Same as the <code>StageText</code> property with the same name.
  763.          *
  764.          * <p>In the following example, the text is centered:</p>
  765.          *
  766.          * <listing version="3.0">
  767.          * textEditor.textAlign = TextFormatAlign.CENTER;</listing>
  768.          *
  769.          * @default flash.text.TextFormatAlign.START
  770.          */
  771.         public function get textAlign():String
  772.         {
  773.             return this._textAlign;
  774.         }
  775.  
  776.         /**
  777.          * @private
  778.          */
  779.         public function set textAlign(value:String):void
  780.         {
  781.             if(this._textAlign == value)
  782.             {
  783.                 return;
  784.             }
  785.             this._textAlign = value;
  786.             this.invalidate(INVALIDATION_FLAG_STYLES);
  787.         }
  788.  
  789.         /**
  790.          * @private
  791.          */
  792.         override public function dispose():void
  793.         {
  794.             this.disposeContent();
  795.             super.dispose();
  796.         }
  797.  
  798.         /**
  799.          * @private
  800.          */
  801.         override public function render(support:RenderSupport, parentAlpha:Number):void
  802.         {
  803.             HELPER_POINT.x = HELPER_POINT.y = 0;
  804.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  805.             MatrixUtil.transformCoords(HELPER_MATRIX, 0, 0, HELPER_POINT);
  806.             if(HELPER_POINT.x != this._oldGlobalX || HELPER_POINT.y != this._oldGlobalY)
  807.             {
  808.                 this._oldGlobalX = HELPER_POINT.x;
  809.                 this._oldGlobalY = HELPER_POINT.y;
  810.                 const starlingViewPort:Rectangle = Starling.current.viewPort;
  811.                 var stageTextViewPort:Rectangle = this.stageText.viewPort;
  812.                 if(!stageTextViewPort)
  813.                 {
  814.                     stageTextViewPort = new Rectangle();
  815.                 }
  816.                 var heightScaleFactor: Number = starlingViewPort.height/stage.stageHeight;
  817.                 stageTextViewPort.x = Math.round(starlingViewPort.x + (HELPER_POINT.x * Starling.contentScaleFactor));
  818.                 stageTextViewPort.y = Math.round(starlingViewPort.y + (HELPER_POINT.y * Starling.heightScaleFactor));
  819.                 this.stageText.viewPort = stageTextViewPort;
  820.             }
  821.  
  822.             if(this.textSnapshot)
  823.             {
  824.                 this.textSnapshot.x = Math.round(HELPER_MATRIX.tx) - HELPER_MATRIX.tx;
  825.                 this.textSnapshot.y = Math.round(HELPER_MATRIX.ty) - HELPER_MATRIX.ty;
  826.             }
  827.  
  828.             super.render(support, parentAlpha);
  829.         }
  830.  
  831.         /**
  832.          * @inheritDoc
  833.          */
  834.         public function setFocus(position:Point = null):void
  835.         {
  836.             if(this.stageText && this._stageTextIsComplete)
  837.             {
  838.                 if(position)
  839.                 {
  840.                     const positionX:Number = position.x;
  841.                     const positionY:Number = position.y;
  842.                     if(positionX < 0)
  843.                     {
  844.                         this._pendingSelectionStartIndex = this._pendingSelectionEndIndex = 0;
  845.                     }
  846.                     else
  847.                     {
  848.                         this._pendingSelectionStartIndex = this._measureTextField.getCharIndexAtPoint(positionX, positionY);
  849.                         if(this._pendingSelectionStartIndex < 0)
  850.                         {
  851.                             if(this._multiline)
  852.                             {
  853.                                 const lineIndex:int = int(positionY / this._measureTextField.getLineMetrics(0).height);
  854.                                 try
  855.                                 {
  856.                                     this._pendingSelectionStartIndex = this._measureTextField.getLineOffset(lineIndex) + this._measureTextField.getLineLength(lineIndex);
  857.                                     if(this._pendingSelectionStartIndex != this._text.length)
  858.                                     {
  859.                                         this._pendingSelectionStartIndex--;
  860.                                     }
  861.                                 }
  862.                                 catch(error:Error)
  863.                                 {
  864.                                     //we may be checking for a line beyond the
  865.                                     //end that doesn't exist
  866.                                     this._pendingSelectionStartIndex = this._text.length;
  867.                                 }
  868.                             }
  869.                             else
  870.                             {
  871.                                 this._pendingSelectionStartIndex = this._text.length;
  872.                             }
  873.                         }
  874.                         else
  875.                         {
  876.                             const bounds:Rectangle = this._measureTextField.getCharBoundaries(this._pendingSelectionStartIndex);
  877.                             const boundsX:Number = bounds.x;
  878.                             if(bounds && (boundsX + bounds.width - positionX) < (positionX - boundsX))
  879.                             {
  880.                                 this._pendingSelectionStartIndex++;
  881.                             }
  882.                         }
  883.                         this._pendingSelectionEndIndex = this._pendingSelectionStartIndex;
  884.                     }
  885.                 }
  886.                 else
  887.                 {
  888.                     this._pendingSelectionStartIndex = this._pendingSelectionEndIndex = -1;
  889.                 }
  890.                 this.stageText.visible = true;
  891.                 this.stageText.assignFocus();
  892.             }
  893.             else
  894.             {
  895.                 this._isWaitingToSetFocus = true;
  896.             }
  897.         }
  898.  
  899.         /**
  900.          * @inheritDoc
  901.          */
  902.         public function clearFocus():void
  903.         {
  904.             if(!this._stageTextHasFocus)
  905.             {
  906.                 return;
  907.             }
  908.             Starling.current.nativeStage.focus = Starling.current.nativeStage;
  909.             this.dispatchEventWith(FeathersEventType.FOCUS_OUT);
  910.         }
  911.  
  912.         /**
  913.          * @inheritDoc
  914.          */
  915.         public function selectRange(startIndex:int, endIndex:int):void
  916.         {
  917.             if(this._stageTextIsComplete && this.stageText)
  918.             {
  919.                 this._pendingSelectionStartIndex = -1;
  920.                 this._pendingSelectionEndIndex = -1;
  921.                 this.stageText.selectRange(startIndex, endIndex);
  922.             }
  923.             else
  924.             {
  925.                 this._pendingSelectionStartIndex = startIndex;
  926.                 this._pendingSelectionEndIndex = endIndex;
  927.             }
  928.         }
  929.  
  930.         /**
  931.          * @inheritDoc
  932.          */
  933.         public function measureText(result:Point = null):Point
  934.         {
  935.             if(!result)
  936.             {
  937.                 result = new Point();
  938.             }
  939.  
  940.             if(!this._measureTextField)
  941.             {
  942.                 result.x = result.y = 0;
  943.                 return result;
  944.             }
  945.  
  946.             const needsWidth:Boolean = isNaN(this.explicitWidth);
  947.             const needsHeight:Boolean = isNaN(this.explicitHeight);
  948.             if(!needsWidth && !needsHeight)
  949.             {
  950.                 result.x = this.explicitWidth;
  951.                 result.y = this.explicitHeight;
  952.                 return result;
  953.             }
  954.  
  955.  
  956.             const stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  957.             const dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  958.  
  959.             if(stylesInvalid || dataInvalid)
  960.             {
  961.                 this.refreshMeasureProperties();
  962.             }
  963.  
  964.             result = this.measure(result);
  965.  
  966.             return result;
  967.         }
  968.  
  969.         /**
  970.          * @private
  971.          */
  972.         override protected function draw():void
  973.         {
  974.             var sizeInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE);
  975.  
  976.             this.commit();
  977.  
  978.             sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid;
  979.  
  980.             this.layout(sizeInvalid);
  981.         }
  982.  
  983.         /**
  984.          * @private
  985.          */
  986.         protected function commit():void
  987.         {
  988.             const stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE);
  989.             const stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  990.             const dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  991.  
  992.             if(stylesInvalid || dataInvalid)
  993.             {
  994.                 this.refreshMeasureProperties();
  995.             }
  996.  
  997.             const oldIgnoreStageTextChanges:Boolean = this._ignoreStageTextChanges;
  998.             this._ignoreStageTextChanges = true;
  999.             if(stylesInvalid)
  1000.             {
  1001.                 this.refreshStageTextProperties();
  1002.             }
  1003.  
  1004.             if(dataInvalid)
  1005.             {
  1006.                 if(this.stageText.text != this._text)
  1007.                 {
  1008.                     if(this._pendingSelectionStartIndex < 0)
  1009.                     {
  1010.                         this._pendingSelectionStartIndex = this.stageText.selectionActiveIndex;
  1011.                         this._pendingSelectionEndIndex = this.stageText.selectionAnchorIndex;
  1012.                     }
  1013.                     this.stageText.text = this._text;
  1014.                 }
  1015.             }
  1016.             this._ignoreStageTextChanges = oldIgnoreStageTextChanges;
  1017.  
  1018.             if(stylesInvalid || stateInvalid)
  1019.             {
  1020.                 this.stageText.editable = this._isEditable && this._isEnabled;
  1021.             }
  1022.         }
  1023.  
  1024.         /**
  1025.          * @private
  1026.          */
  1027.         protected function measure(result:Point = null):Point
  1028.         {
  1029.             if(!result)
  1030.             {
  1031.                 result = new Point();
  1032.             }
  1033.  
  1034.             const needsWidth:Boolean = isNaN(this.explicitWidth);
  1035.             const needsHeight:Boolean = isNaN(this.explicitHeight);
  1036.  
  1037.             this._measureTextField.autoSize = TextFieldAutoSize.LEFT;
  1038.  
  1039.             var newWidth:Number = this.explicitWidth;
  1040.             if(needsWidth)
  1041.             {
  1042.                 newWidth = Math.max(this._minWidth, Math.min(this._maxWidth, this._measureTextField.width));
  1043.             }
  1044.  
  1045.             this._measureTextField.width = newWidth;
  1046.             var newHeight:Number = this.explicitHeight;
  1047.             if(needsHeight)
  1048.             {
  1049.                 newHeight = Math.max(this._minHeight, Math.min(this._maxHeight, this._measureTextField.height));
  1050.             }
  1051.  
  1052.             this._measureTextField.autoSize = TextFieldAutoSize.NONE;
  1053.  
  1054.             //put the width and height back just in case we measured without
  1055.             //a full validation
  1056.             this._measureTextField.width = this.actualWidth;
  1057.             this._measureTextField.height = this.actualHeight;
  1058.  
  1059.             result.x = newWidth;
  1060.             result.y = newHeight;
  1061.  
  1062.             return result;
  1063.         }
  1064.  
  1065.         /**
  1066.          * @private
  1067.          */
  1068.         protected function layout(sizeInvalid:Boolean):void
  1069.         {
  1070.             const stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE);
  1071.             const stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  1072.             const dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  1073.             const positionInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_POSITION);
  1074.             const skinInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SKIN);
  1075.  
  1076.             if(positionInvalid || sizeInvalid || stylesInvalid || skinInvalid || stateInvalid)
  1077.             {
  1078.                 this.refreshViewPort();
  1079.                 const viewPort:Rectangle = this.stageText.viewPort;
  1080.                 const textureRoot:ConcreteTexture = this.textSnapshot ? this.textSnapshot.texture.root : null;
  1081.                 this._needsNewTexture = this._needsNewTexture || !this.textSnapshot || viewPort.width != textureRoot.width || viewPort.height != textureRoot.height;
  1082.             }
  1083.  
  1084.             if(!this._stageTextHasFocus && (stylesInvalid || dataInvalid || sizeInvalid || this._needsNewTexture))
  1085.             {
  1086.                 const hasText:Boolean = this._text.length > 0;
  1087.                 if(hasText)
  1088.                 {
  1089.                     this.refreshSnapshot();
  1090.                 }
  1091.                 if(this.textSnapshot)
  1092.                 {
  1093.                     this.textSnapshot.visible = !this._stageTextHasFocus;
  1094.                     this.textSnapshot.alpha = hasText ? 1 : 0;
  1095.                     if(!this._stageTextHasFocus)
  1096.                     {
  1097.                         this.stageText.visible = false;
  1098.                     }
  1099.                 }
  1100.             }
  1101.  
  1102.             this.doPendingActions();
  1103.         }
  1104.  
  1105.         /**
  1106.          * If the component's dimensions have not been set explicitly, it will
  1107.          * measure its content and determine an ideal size for itself. If the
  1108.          * <code>explicitWidth</code> or <code>explicitHeight</code> member
  1109.          * variables are set, those value will be used without additional
  1110.          * measurement. If one is set, but not the other, the dimension with the
  1111.          * explicit value will not be measured, but the other non-explicit
  1112.          * dimension will still need measurement.
  1113.          *
  1114.          * <p>Calls <code>setSizeInternal()</code> to set up the
  1115.          * <code>actualWidth</code> and <code>actualHeight</code> member
  1116.          * variables used for layout.</p>
  1117.          *
  1118.          * <p>Meant for internal use, and subclasses may override this function
  1119.          * with a custom implementation.</p>
  1120.          */
  1121.         protected function autoSizeIfNeeded():Boolean
  1122.         {
  1123.             const needsWidth:Boolean = isNaN(this.explicitWidth);
  1124.             const needsHeight:Boolean = isNaN(this.explicitHeight);
  1125.             if(!needsWidth && !needsHeight)
  1126.             {
  1127.                 return false;
  1128.             }
  1129.  
  1130.             this.measure(HELPER_POINT);
  1131.             return this.setSizeInternal(HELPER_POINT.x, HELPER_POINT.y, false);
  1132.         }
  1133.  
  1134.         /**
  1135.          * @private
  1136.          */
  1137.         protected function refreshMeasureProperties():void
  1138.         {
  1139.             this._measureTextField.displayAsPassword = this._displayAsPassword;
  1140.             this._measureTextField.maxChars = this._maxChars;
  1141.             this._measureTextField.restrict = this._restrict;
  1142.             this._measureTextField.multiline = this._measureTextField.wordWrap = this._multiline;
  1143.  
  1144.             const format:TextFormat = this._measureTextField.defaultTextFormat;
  1145.             format.color = this._color;
  1146.             format.font = this._fontFamily;
  1147.             format.italic = this._fontPosture == FontPosture.ITALIC;
  1148.             format.size = this._fontSize;
  1149.             format.bold = this._fontWeight == FontWeight.BOLD;
  1150.             var alignValue:String = this._textAlign;
  1151.             if(alignValue == TextFormatAlign.START)
  1152.             {
  1153.                 alignValue = TextFormatAlign.LEFT;
  1154.             }
  1155.             else if(alignValue == TextFormatAlign.END)
  1156.             {
  1157.                 alignValue = TextFormatAlign.RIGHT;
  1158.             }
  1159.             format.align = alignValue;
  1160.             this._measureTextField.defaultTextFormat = format;
  1161.             this._measureTextField.setTextFormat(format);
  1162.             this._measureTextField.text = this._text;
  1163.         }
  1164.  
  1165.         /**
  1166.          * @private
  1167.          */
  1168.         protected function refreshStageTextProperties():void
  1169.         {
  1170.             if(this.stageText.multiline != this._multiline)
  1171.             {
  1172.                 if(this.stageText)
  1173.                 {
  1174.                     this.disposeStageText();
  1175.                 }
  1176.                 this.createStageText();
  1177.             }
  1178.  
  1179.             this.stageText.autoCapitalize = this._autoCapitalize;
  1180.             this.stageText.autoCorrect = this._autoCorrect;
  1181.             this.stageText.color = this._color;
  1182.             this.stageText.displayAsPassword = this._displayAsPassword;
  1183.             this.stageText.fontFamily = this._fontFamily;
  1184.             this.stageText.fontPosture = this._fontPosture;
  1185.  
  1186.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1187.             var globalScaleX:Number = matrixToScaleX(HELPER_MATRIX);
  1188.             var globalScaleY:Number = matrixToScaleY(HELPER_MATRIX);
  1189.             var smallerGlobalScale:Number = globalScaleX;
  1190.             const starlingViewPort:Rectangle = Starling.current.viewPort;
  1191.             var heightScaleFactor: Number = starlingViewPort.height/stage.stageHeight;
  1192.  
  1193.             if(globalScaleY < globalScaleX)
  1194.             {
  1195.                 smallerGlobalScale = globalScaleY;
  1196.             }
  1197.             this.stageText.fontSize = this._fontSize * heightScaleFactor * smallerGlobalScale;
  1198.  
  1199.             this.stageText.fontWeight = this._fontWeight;
  1200.             this.stageText.locale = this._locale;
  1201.             this.stageText.maxChars = this._maxChars;
  1202.             this.stageText.restrict = this._restrict;
  1203.             this.stageText.returnKeyLabel = this._returnKeyLabel;
  1204.             this.stageText.softKeyboardType = this._softKeyboardType;
  1205.             this.stageText.textAlign = this._textAlign;
  1206.         }
  1207.  
  1208.         /**
  1209.          * @private
  1210.          */
  1211.         protected function doPendingActions():void
  1212.         {
  1213.             if(this._isWaitingToSetFocus)
  1214.             {
  1215.                 this._isWaitingToSetFocus = false;
  1216.                 this.setFocus();
  1217.             }
  1218.             if(this._pendingSelectionStartIndex >= 0)
  1219.             {
  1220.                 const startIndex:int = this._pendingSelectionStartIndex;
  1221.                 const endIndex:int = (this._pendingSelectionEndIndex < 0) ? this._pendingSelectionStartIndex : this._pendingSelectionEndIndex;
  1222.                 this._pendingSelectionStartIndex = -1;
  1223.                 this._pendingSelectionEndIndex = -1;
  1224.                 this.selectRange(startIndex, endIndex);
  1225.             }
  1226.         }
  1227.  
  1228.         /**
  1229.          * @private
  1230.          */
  1231.         protected function texture_onRestore():void
  1232.         {
  1233.             this.refreshSnapshot();
  1234.             if(this.textSnapshot)
  1235.             {
  1236.                 this.textSnapshot.visible = !this._stageTextHasFocus;
  1237.                 this.textSnapshot.alpha = this._text.length > 0 ? 1 : 0;
  1238.                 if(!this._stageTextHasFocus)
  1239.                 {
  1240.                     this.stageText.visible = false;
  1241.                 }
  1242.             }
  1243.         }
  1244.  
  1245.         /**
  1246.          * @private
  1247.          */
  1248.         protected function refreshSnapshot():void
  1249.         {
  1250.             const viewPort:Rectangle = this.stageText.viewPort;
  1251.             if(viewPort.width == 0 || viewPort.height == 0)
  1252.             {
  1253.                 return;
  1254.             }
  1255.  
  1256.             //StageText sucks because it requires that the BitmapData's width
  1257.             //and height exactly match its view port width and height.
  1258.             var bitmapData:BitmapData = new BitmapData(viewPort.width, viewPort.height, true, 0x00ff00ff);
  1259.             this.stageText.drawViewPortToBitmapData(bitmapData);
  1260.  
  1261.             var newTexture:Texture;
  1262.             if(!this.textSnapshot || this._needsNewTexture)
  1263.             {
  1264.                 newTexture = Texture.fromBitmapData(bitmapData, false, false, Starling.contentScaleFactor);
  1265.                 newTexture.root.onRestore = texture_onRestore;
  1266.             }
  1267.             if(!this.textSnapshot)
  1268.             {
  1269.                 this.textSnapshot = new Image(newTexture);
  1270.                 this.addChild(this.textSnapshot);
  1271.             }
  1272.             else
  1273.             {
  1274.                 if(this._needsNewTexture)
  1275.                 {
  1276.                     this.textSnapshot.texture.dispose();
  1277.                     this.textSnapshot.texture = newTexture;
  1278.                     this.textSnapshot.readjustSize();
  1279.                 }
  1280.                 else
  1281.                 {
  1282.                     //this is faster, if we haven't resized the bitmapdata
  1283.                     const existingTexture:Texture = this.textSnapshot.texture;
  1284.                     existingTexture.root.uploadBitmapData(bitmapData);
  1285.                 }
  1286.             }
  1287.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1288.             this.textSnapshot.scaleX = 1 / matrixToScaleX(HELPER_MATRIX);
  1289.             this.textSnapshot.scaleY = 1 / matrixToScaleY(HELPER_MATRIX);
  1290.             bitmapData.dispose();
  1291.             this._needsNewTexture = false;
  1292.         }
  1293.  
  1294.         /**
  1295.          * @private
  1296.          */
  1297.         protected function refreshViewPort():void
  1298.         {
  1299.             const starlingViewPort:Rectangle = Starling.current.viewPort;
  1300.             var stageTextViewPort:Rectangle = this.stageText.viewPort;
  1301.             if(!stageTextViewPort)
  1302.             {
  1303.                 stageTextViewPort = new Rectangle();
  1304.             }
  1305.             if(!this.stageText.stage)
  1306.             {
  1307.                 this.stageText.stage = Starling.current.nativeStage;
  1308.             }
  1309.  
  1310.             HELPER_POINT.x = HELPER_POINT.y = 0;
  1311.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1312.             var globalScaleX:Number = matrixToScaleX(HELPER_MATRIX);
  1313.             var globalScaleY:Number = matrixToScaleY(HELPER_MATRIX);
  1314.             MatrixUtil.transformCoords(HELPER_MATRIX, 0, 0, HELPER_POINT);
  1315.             this._oldGlobalX = HELPER_POINT.x;
  1316.             this._oldGlobalY = HELPER_POINT.y;
  1317.             var heightScaleFactor: Number = starlingViewPort.height/stage.stageHeight;
  1318.             stageTextViewPort.x = Math.round(starlingViewPort.x + HELPER_POINT.x * Starling.contentScaleFactor);
  1319.             stageTextViewPort.y = Math.round(starlingViewPort.y + HELPER_POINT.y * Starling.heightScaleFactor);
  1320.             var viewPortWidth:Number = Math.round(this.actualWidth * Starling.contentScaleFactor * globalScaleX);
  1321.             if(viewPortWidth < 1 || isNaN(viewPortWidth))
  1322.             {
  1323.                 viewPortWidth = 1;
  1324.             }
  1325.             var viewPortHeight:Number = Math.round(this.actualHeight * Starling.heightScaleFactor * globalScaleY);
  1326.             if(viewPortHeight < 1 || isNaN(viewPortHeight))
  1327.             {
  1328.                 viewPortHeight = 1;
  1329.             }
  1330.             stageTextViewPort.width = viewPortWidth;
  1331.             stageTextViewPort.height = viewPortHeight;
  1332.             this.stageText.viewPort = stageTextViewPort;
  1333.  
  1334.             this._measureTextField.width = this.actualWidth;
  1335.             this._measureTextField.height = this.actualHeight;
  1336.         }
  1337.  
  1338.         /**
  1339.          * @private
  1340.          */
  1341.         protected function disposeContent():void
  1342.         {
  1343.             if(this._measureTextField)
  1344.             {
  1345.                 Starling.current.nativeStage.removeChild(this._measureTextField);
  1346.                 this._measureTextField = null;
  1347.             }
  1348.  
  1349.             if(this.stageText)
  1350.             {
  1351.                 this.disposeStageText();
  1352.             }
  1353.  
  1354.             if(this.textSnapshot)
  1355.             {
  1356.                 //avoid the need to call dispose(). we'll create a new snapshot
  1357.                 //when the renderer is added to stage again.
  1358.                 this.textSnapshot.texture.dispose();
  1359.                 this.removeChild(this.textSnapshot, true);
  1360.                 this.textSnapshot = null;
  1361.             }
  1362.         }
  1363.  
  1364.         /**
  1365.          * @private
  1366.          */
  1367.         protected function disposeStageText():void
  1368.         {
  1369.             if(!this.stageText)
  1370.             {
  1371.                 return;
  1372.             }
  1373.             this.stageText.removeEventListener(flash.events.Event.CHANGE, stageText_changeHandler);
  1374.             this.stageText.removeEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
  1375.             this.stageText.removeEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
  1376.             this.stageText.removeEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
  1377.             this.stageText.removeEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
  1378.             this.stageText.removeEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1379.             this.stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
  1380.             this.stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
  1381.             this.stageText.stage = null;
  1382.             this.stageText.dispose();
  1383.             this.stageText = null;
  1384.         }
  1385.  
  1386.         /**
  1387.          * Creates and adds the <code>stageText</code> instance.
  1388.          *
  1389.          * <p>Meant for internal use, and subclasses may override this function
  1390.          * with a custom implementation.</p>
  1391.          */
  1392.         protected function createStageText():void
  1393.         {
  1394.             this._stageTextIsComplete = false;
  1395.             var StageTextType:Class;
  1396.             var initOptions:Object;
  1397.             try
  1398.             {
  1399.                 StageTextType = Class(getDefinitionByName("flash.text.StageText"));
  1400.                 const StageTextInitOptionsType:Class = Class(getDefinitionByName("flash.text.StageTextInitOptions"));
  1401.                 initOptions = new StageTextInitOptionsType(this._multiline);
  1402.             }
  1403.             catch(error:Error)
  1404.             {
  1405.                 StageTextType = StageTextField;
  1406.                 initOptions = { multiline: this._multiline };
  1407.             }
  1408.             this.stageText = new StageTextType(initOptions);
  1409.             this.stageText.visible = false;
  1410.             this.stageText.addEventListener(flash.events.Event.CHANGE, stageText_changeHandler);
  1411.             this.stageText.addEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
  1412.             this.stageText.addEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
  1413.             this.stageText.addEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
  1414.             this.stageText.addEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
  1415.             this.stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
  1416.             this.stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
  1417.             this.stageText.addEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1418.             this.invalidate();
  1419.         }
  1420.  
  1421.         /**
  1422.          * @private
  1423.          */
  1424.         protected function addedToStageHandler(event:starling.events.Event):void
  1425.         {
  1426.             if(this._measureTextField && !this._measureTextField.parent)
  1427.             {
  1428.                 Starling.current.nativeStage.addChild(this._measureTextField);
  1429.             }
  1430.             else if(!this._measureTextField)
  1431.             {
  1432.                 this._measureTextField = new TextField();
  1433.                 this._measureTextField.visible = false;
  1434.                 this._measureTextField.mouseEnabled = this._measureTextField.mouseWheelEnabled = false;
  1435.                 this._measureTextField.autoSize = TextFieldAutoSize.LEFT;
  1436.                 this._measureTextField.multiline = false;
  1437.                 this._measureTextField.wordWrap = false;
  1438.                 this._measureTextField.embedFonts = false;
  1439.                 this._measureTextField.defaultTextFormat = new TextFormat(null, 11, 0x000000, false, false, false);
  1440.                 Starling.current.nativeStage.addChild(this._measureTextField);
  1441.             }
  1442.  
  1443.             this.createStageText();
  1444.         }
  1445.  
  1446.         /**
  1447.          * @private
  1448.          */
  1449.         protected function removedFromStageHandler(event:starling.events.Event):void
  1450.         {
  1451.             this.disposeContent();
  1452.         }
  1453.  
  1454.         /**
  1455.          * @private
  1456.          */
  1457.         protected function stageText_changeHandler(event:flash.events.Event):void
  1458.         {
  1459.             if(this._ignoreStageTextChanges)
  1460.             {
  1461.                 return;
  1462.             }
  1463.             this.text = this.stageText.text;
  1464.         }
  1465.  
  1466.         /**
  1467.          * @private
  1468.          */
  1469.         protected function stageText_completeHandler(event:flash.events.Event):void
  1470.         {
  1471.             this.stageText.removeEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1472.             this.invalidate();
  1473.  
  1474.             this._stageTextIsComplete = true;
  1475.         }
  1476.  
  1477.         /**
  1478.          * @private
  1479.          */
  1480.         protected function stageText_focusInHandler(event:FocusEvent):void
  1481.         {
  1482.             this._stageTextHasFocus = true;
  1483.             if(this.textSnapshot)
  1484.             {
  1485.                 this.textSnapshot.visible = false;
  1486.             }
  1487.             this.invalidate(INVALIDATION_FLAG_SKIN);
  1488.             this.dispatchEventWith(FeathersEventType.FOCUS_IN);
  1489.         }
  1490.  
  1491.         /**
  1492.          * @private
  1493.          */
  1494.         protected function stageText_focusOutHandler(event:FocusEvent):void
  1495.         {
  1496.             this._stageTextHasFocus = false;
  1497.             //since StageText doesn't expose its scroll position, we need to
  1498.             //set the selection back to the beginning to scroll there. it's a
  1499.             //hack, but so is everything about StageText.
  1500.             //in other news, why won't 0,0 work here?
  1501.             this.stageText.selectRange(1, 1);
  1502.  
  1503.             this.invalidate(INVALIDATION_FLAG_DATA);
  1504.             this.invalidate(INVALIDATION_FLAG_SKIN);
  1505.             this.dispatchEventWith(FeathersEventType.FOCUS_OUT);
  1506.         }
  1507.  
  1508.         /**
  1509.          * @private
  1510.          */
  1511.         protected function stageText_keyDownHandler(event:KeyboardEvent):void
  1512.         {
  1513.             if(!this._multiline && (event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT))
  1514.             {
  1515.                 event.preventDefault();
  1516.                 this.dispatchEventWith(FeathersEventType.ENTER);
  1517.             }
  1518.             else if(event.keyCode == Keyboard.BACK)
  1519.             {
  1520.                 //even a listener on the stage won't detect the back key press that
  1521.                 //will close the application if the StageText has focus, so we
  1522.                 //always need to prevent it here
  1523.                 event.preventDefault();
  1524.                 Starling.current.nativeStage.focus = Starling.current.nativeStage;
  1525.             }
  1526.         }
  1527.  
  1528.         /**
  1529.          * @private
  1530.          */
  1531.         protected function stageText_keyUpHandler(event:KeyboardEvent):void
  1532.         {
  1533.             if(!this._multiline && (event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT))
  1534.             {
  1535.                 event.preventDefault();
  1536.             }
  1537.         }
  1538.  
  1539.         /**
  1540.          * @private
  1541.          */
  1542.         protected function stageText_softKeyboardActivateHandler(event:SoftKeyboardEvent):void
  1543.         {
  1544.             this.dispatchEventWith(FeathersEventType.SOFT_KEYBOARD_ACTIVATE, true);
  1545.         }
  1546.  
  1547.         /**
  1548.          * @private
  1549.          */
  1550.         protected function stageText_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
  1551.         {
  1552.             this.dispatchEventWith(FeathersEventType.SOFT_KEYBOARD_DEACTIVATE, true);
  1553.         }
  1554.     }
  1555. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement