Advertisement
Guest User

StageTextTextEditor older version

a guest
Mar 20th, 2020
94
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.                 stageTextViewPort.x = Math.round(starlingViewPort.x + (HELPER_POINT.x * Starling.contentScaleFactor));
  817.                 stageTextViewPort.y = Math.round(starlingViewPort.y + (HELPER_POINT.y * Starling.contentScaleFactor));
  818.                 this.stageText.viewPort = stageTextViewPort;
  819.             }
  820.  
  821.             if(this.textSnapshot)
  822.             {
  823.                 this.textSnapshot.x = Math.round(HELPER_MATRIX.tx) - HELPER_MATRIX.tx;
  824.                 this.textSnapshot.y = Math.round(HELPER_MATRIX.ty) - HELPER_MATRIX.ty;
  825.             }
  826.  
  827.             super.render(support, parentAlpha);
  828.         }
  829.  
  830.         /**
  831.          * @inheritDoc
  832.          */
  833.         public function setFocus(position:Point = null):void
  834.         {
  835.             if(this.stageText && this._stageTextIsComplete)
  836.             {
  837.                 if(position)
  838.                 {
  839.                     const positionX:Number = position.x;
  840.                     const positionY:Number = position.y;
  841.                     if(positionX < 0)
  842.                     {
  843.                         this._pendingSelectionStartIndex = this._pendingSelectionEndIndex = 0;
  844.                     }
  845.                     else
  846.                     {
  847.                         this._pendingSelectionStartIndex = this._measureTextField.getCharIndexAtPoint(positionX, positionY);
  848.                         if(this._pendingSelectionStartIndex < 0)
  849.                         {
  850.                             if(this._multiline)
  851.                             {
  852.                                 const lineIndex:int = int(positionY / this._measureTextField.getLineMetrics(0).height);
  853.                                 try
  854.                                 {
  855.                                     this._pendingSelectionStartIndex = this._measureTextField.getLineOffset(lineIndex) + this._measureTextField.getLineLength(lineIndex);
  856.                                     if(this._pendingSelectionStartIndex != this._text.length)
  857.                                     {
  858.                                         this._pendingSelectionStartIndex--;
  859.                                     }
  860.                                 }
  861.                                 catch(error:Error)
  862.                                 {
  863.                                     //we may be checking for a line beyond the
  864.                                     //end that doesn't exist
  865.                                     this._pendingSelectionStartIndex = this._text.length;
  866.                                 }
  867.                             }
  868.                             else
  869.                             {
  870.                                 this._pendingSelectionStartIndex = this._text.length;
  871.                             }
  872.                         }
  873.                         else
  874.                         {
  875.                             const bounds:Rectangle = this._measureTextField.getCharBoundaries(this._pendingSelectionStartIndex);
  876.                             const boundsX:Number = bounds.x;
  877.                             if(bounds && (boundsX + bounds.width - positionX) < (positionX - boundsX))
  878.                             {
  879.                                 this._pendingSelectionStartIndex++;
  880.                             }
  881.                         }
  882.                         this._pendingSelectionEndIndex = this._pendingSelectionStartIndex;
  883.                     }
  884.                 }
  885.                 else
  886.                 {
  887.                     this._pendingSelectionStartIndex = this._pendingSelectionEndIndex = -1;
  888.                 }
  889.                 this.stageText.visible = true;
  890.                 this.stageText.assignFocus();
  891.             }
  892.             else
  893.             {
  894.                 this._isWaitingToSetFocus = true;
  895.             }
  896.         }
  897.  
  898.         /**
  899.          * @inheritDoc
  900.          */
  901.         public function clearFocus():void
  902.         {
  903.             if(!this._stageTextHasFocus)
  904.             {
  905.                 return;
  906.             }
  907.             Starling.current.nativeStage.focus = Starling.current.nativeStage;
  908.             this.dispatchEventWith(FeathersEventType.FOCUS_OUT);
  909.         }
  910.  
  911.         /**
  912.          * @inheritDoc
  913.          */
  914.         public function selectRange(startIndex:int, endIndex:int):void
  915.         {
  916.             if(this._stageTextIsComplete && this.stageText)
  917.             {
  918.                 this._pendingSelectionStartIndex = -1;
  919.                 this._pendingSelectionEndIndex = -1;
  920.                 this.stageText.selectRange(startIndex, endIndex);
  921.             }
  922.             else
  923.             {
  924.                 this._pendingSelectionStartIndex = startIndex;
  925.                 this._pendingSelectionEndIndex = endIndex;
  926.             }
  927.         }
  928.  
  929.         /**
  930.          * @inheritDoc
  931.          */
  932.         public function measureText(result:Point = null):Point
  933.         {
  934.             if(!result)
  935.             {
  936.                 result = new Point();
  937.             }
  938.  
  939.             if(!this._measureTextField)
  940.             {
  941.                 result.x = result.y = 0;
  942.                 return result;
  943.             }
  944.  
  945.             const needsWidth:Boolean = isNaN(this.explicitWidth);
  946.             const needsHeight:Boolean = isNaN(this.explicitHeight);
  947.             if(!needsWidth && !needsHeight)
  948.             {
  949.                 result.x = this.explicitWidth;
  950.                 result.y = this.explicitHeight;
  951.                 return result;
  952.             }
  953.  
  954.  
  955.             const stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  956.             const dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  957.  
  958.             if(stylesInvalid || dataInvalid)
  959.             {
  960.                 this.refreshMeasureProperties();
  961.             }
  962.  
  963.             result = this.measure(result);
  964.  
  965.             return result;
  966.         }
  967.  
  968.         /**
  969.          * @private
  970.          */
  971.         override protected function draw():void
  972.         {
  973.             var sizeInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE);
  974.  
  975.             this.commit();
  976.  
  977.             sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid;
  978.  
  979.             this.layout(sizeInvalid);
  980.         }
  981.  
  982.         /**
  983.          * @private
  984.          */
  985.         protected function commit():void
  986.         {
  987.             const stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE);
  988.             const stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  989.             const dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  990.  
  991.             if(stylesInvalid || dataInvalid)
  992.             {
  993.                 this.refreshMeasureProperties();
  994.             }
  995.  
  996.             const oldIgnoreStageTextChanges:Boolean = this._ignoreStageTextChanges;
  997.             this._ignoreStageTextChanges = true;
  998.             if(stylesInvalid)
  999.             {
  1000.                 this.refreshStageTextProperties();
  1001.             }
  1002.  
  1003.             if(dataInvalid)
  1004.             {
  1005.                 if(this.stageText.text != this._text)
  1006.                 {
  1007.                     if(this._pendingSelectionStartIndex < 0)
  1008.                     {
  1009.                         this._pendingSelectionStartIndex = this.stageText.selectionActiveIndex;
  1010.                         this._pendingSelectionEndIndex = this.stageText.selectionAnchorIndex;
  1011.                     }
  1012.                     this.stageText.text = this._text;
  1013.                 }
  1014.             }
  1015.             this._ignoreStageTextChanges = oldIgnoreStageTextChanges;
  1016.  
  1017.             if(stylesInvalid || stateInvalid)
  1018.             {
  1019.                 this.stageText.editable = this._isEditable && this._isEnabled;
  1020.             }
  1021.         }
  1022.  
  1023.         /**
  1024.          * @private
  1025.          */
  1026.         protected function measure(result:Point = null):Point
  1027.         {
  1028.             if(!result)
  1029.             {
  1030.                 result = new Point();
  1031.             }
  1032.  
  1033.             const needsWidth:Boolean = isNaN(this.explicitWidth);
  1034.             const needsHeight:Boolean = isNaN(this.explicitHeight);
  1035.  
  1036.             this._measureTextField.autoSize = TextFieldAutoSize.LEFT;
  1037.  
  1038.             var newWidth:Number = this.explicitWidth;
  1039.             if(needsWidth)
  1040.             {
  1041.                 newWidth = Math.max(this._minWidth, Math.min(this._maxWidth, this._measureTextField.width));
  1042.             }
  1043.  
  1044.             this._measureTextField.width = newWidth;
  1045.             var newHeight:Number = this.explicitHeight;
  1046.             if(needsHeight)
  1047.             {
  1048.                 newHeight = Math.max(this._minHeight, Math.min(this._maxHeight, this._measureTextField.height));
  1049.             }
  1050.  
  1051.             this._measureTextField.autoSize = TextFieldAutoSize.NONE;
  1052.  
  1053.             //put the width and height back just in case we measured without
  1054.             //a full validation
  1055.             this._measureTextField.width = this.actualWidth;
  1056.             this._measureTextField.height = this.actualHeight;
  1057.  
  1058.             result.x = newWidth;
  1059.             result.y = newHeight;
  1060.  
  1061.             return result;
  1062.         }
  1063.  
  1064.         /**
  1065.          * @private
  1066.          */
  1067.         protected function layout(sizeInvalid:Boolean):void
  1068.         {
  1069.             const stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE);
  1070.             const stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  1071.             const dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  1072.             const positionInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_POSITION);
  1073.             const skinInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SKIN);
  1074.  
  1075.             if(positionInvalid || sizeInvalid || stylesInvalid || skinInvalid || stateInvalid)
  1076.             {
  1077.                 this.refreshViewPort();
  1078.                 const viewPort:Rectangle = this.stageText.viewPort;
  1079.                 const textureRoot:ConcreteTexture = this.textSnapshot ? this.textSnapshot.texture.root : null;
  1080.                 this._needsNewTexture = this._needsNewTexture || !this.textSnapshot || viewPort.width != textureRoot.width || viewPort.height != textureRoot.height;
  1081.             }
  1082.  
  1083.             if(!this._stageTextHasFocus && (stylesInvalid || dataInvalid || sizeInvalid || this._needsNewTexture))
  1084.             {
  1085.                 const hasText:Boolean = this._text.length > 0;
  1086.                 if(hasText)
  1087.                 {
  1088.                     this.refreshSnapshot();
  1089.                 }
  1090.                 if(this.textSnapshot)
  1091.                 {
  1092.                     this.textSnapshot.visible = !this._stageTextHasFocus;
  1093.                     this.textSnapshot.alpha = hasText ? 1 : 0;
  1094.                     if(!this._stageTextHasFocus)
  1095.                     {
  1096.                         this.stageText.visible = false;
  1097.                     }
  1098.                 }
  1099.             }
  1100.  
  1101.             this.doPendingActions();
  1102.         }
  1103.  
  1104.         /**
  1105.          * If the component's dimensions have not been set explicitly, it will
  1106.          * measure its content and determine an ideal size for itself. If the
  1107.          * <code>explicitWidth</code> or <code>explicitHeight</code> member
  1108.          * variables are set, those value will be used without additional
  1109.          * measurement. If one is set, but not the other, the dimension with the
  1110.          * explicit value will not be measured, but the other non-explicit
  1111.          * dimension will still need measurement.
  1112.          *
  1113.          * <p>Calls <code>setSizeInternal()</code> to set up the
  1114.          * <code>actualWidth</code> and <code>actualHeight</code> member
  1115.          * variables used for layout.</p>
  1116.          *
  1117.          * <p>Meant for internal use, and subclasses may override this function
  1118.          * with a custom implementation.</p>
  1119.          */
  1120.         protected function autoSizeIfNeeded():Boolean
  1121.         {
  1122.             const needsWidth:Boolean = isNaN(this.explicitWidth);
  1123.             const needsHeight:Boolean = isNaN(this.explicitHeight);
  1124.             if(!needsWidth && !needsHeight)
  1125.             {
  1126.                 return false;
  1127.             }
  1128.  
  1129.             this.measure(HELPER_POINT);
  1130.             return this.setSizeInternal(HELPER_POINT.x, HELPER_POINT.y, false);
  1131.         }
  1132.  
  1133.         /**
  1134.          * @private
  1135.          */
  1136.         protected function refreshMeasureProperties():void
  1137.         {
  1138.             this._measureTextField.displayAsPassword = this._displayAsPassword;
  1139.             this._measureTextField.maxChars = this._maxChars;
  1140.             this._measureTextField.restrict = this._restrict;
  1141.             this._measureTextField.multiline = this._measureTextField.wordWrap = this._multiline;
  1142.  
  1143.             const format:TextFormat = this._measureTextField.defaultTextFormat;
  1144.             format.color = this._color;
  1145.             format.font = this._fontFamily;
  1146.             format.italic = this._fontPosture == FontPosture.ITALIC;
  1147.             format.size = this._fontSize;
  1148.             format.bold = this._fontWeight == FontWeight.BOLD;
  1149.             var alignValue:String = this._textAlign;
  1150.             if(alignValue == TextFormatAlign.START)
  1151.             {
  1152.                 alignValue = TextFormatAlign.LEFT;
  1153.             }
  1154.             else if(alignValue == TextFormatAlign.END)
  1155.             {
  1156.                 alignValue = TextFormatAlign.RIGHT;
  1157.             }
  1158.             format.align = alignValue;
  1159.             this._measureTextField.defaultTextFormat = format;
  1160.             this._measureTextField.setTextFormat(format);
  1161.             this._measureTextField.text = this._text;
  1162.         }
  1163.  
  1164.         /**
  1165.          * @private
  1166.          */
  1167.         protected function refreshStageTextProperties():void
  1168.         {
  1169.             if(this.stageText.multiline != this._multiline)
  1170.             {
  1171.                 if(this.stageText)
  1172.                 {
  1173.                     this.disposeStageText();
  1174.                 }
  1175.                 this.createStageText();
  1176.             }
  1177.  
  1178.             this.stageText.autoCapitalize = this._autoCapitalize;
  1179.             this.stageText.autoCorrect = this._autoCorrect;
  1180.             this.stageText.color = this._color;
  1181.             this.stageText.displayAsPassword = this._displayAsPassword;
  1182.             this.stageText.fontFamily = this._fontFamily;
  1183.             this.stageText.fontPosture = this._fontPosture;
  1184.  
  1185.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1186.             var globalScaleX:Number = matrixToScaleX(HELPER_MATRIX);
  1187.             var globalScaleY:Number = matrixToScaleY(HELPER_MATRIX);
  1188.             var smallerGlobalScale:Number = globalScaleX;
  1189.             if(globalScaleY < globalScaleX)
  1190.             {
  1191.                 smallerGlobalScale = globalScaleY;
  1192.             }
  1193.             this.stageText.fontSize = this._fontSize * Starling.contentScaleFactor * smallerGlobalScale;
  1194.  
  1195.             this.stageText.fontWeight = this._fontWeight;
  1196.             this.stageText.locale = this._locale;
  1197.             this.stageText.maxChars = this._maxChars;
  1198.             this.stageText.restrict = this._restrict;
  1199.             this.stageText.returnKeyLabel = this._returnKeyLabel;
  1200.             this.stageText.softKeyboardType = this._softKeyboardType;
  1201.             this.stageText.textAlign = this._textAlign;
  1202.         }
  1203.  
  1204.         /**
  1205.          * @private
  1206.          */
  1207.         protected function doPendingActions():void
  1208.         {
  1209.             if(this._isWaitingToSetFocus)
  1210.             {
  1211.                 this._isWaitingToSetFocus = false;
  1212.                 this.setFocus();
  1213.             }
  1214.             if(this._pendingSelectionStartIndex >= 0)
  1215.             {
  1216.                 const startIndex:int = this._pendingSelectionStartIndex;
  1217.                 const endIndex:int = (this._pendingSelectionEndIndex < 0) ? this._pendingSelectionStartIndex : this._pendingSelectionEndIndex;
  1218.                 this._pendingSelectionStartIndex = -1;
  1219.                 this._pendingSelectionEndIndex = -1;
  1220.                 this.selectRange(startIndex, endIndex);
  1221.             }
  1222.         }
  1223.  
  1224.         /**
  1225.          * @private
  1226.          */
  1227.         protected function texture_onRestore():void
  1228.         {
  1229.             this.refreshSnapshot();
  1230.             if(this.textSnapshot)
  1231.             {
  1232.                 this.textSnapshot.visible = !this._stageTextHasFocus;
  1233.                 this.textSnapshot.alpha = this._text.length > 0 ? 1 : 0;
  1234.                 if(!this._stageTextHasFocus)
  1235.                 {
  1236.                     this.stageText.visible = false;
  1237.                 }
  1238.             }
  1239.         }
  1240.  
  1241.         /**
  1242.          * @private
  1243.          */
  1244.         protected function refreshSnapshot():void
  1245.         {
  1246.             const viewPort:Rectangle = this.stageText.viewPort;
  1247.             if(viewPort.width == 0 || viewPort.height == 0)
  1248.             {
  1249.                 return;
  1250.             }
  1251.  
  1252.             //StageText sucks because it requires that the BitmapData's width
  1253.             //and height exactly match its view port width and height.
  1254.             var bitmapData:BitmapData = new BitmapData(viewPort.width, viewPort.height, true, 0x00ff00ff);
  1255.             this.stageText.drawViewPortToBitmapData(bitmapData);
  1256.  
  1257.             var newTexture:Texture;
  1258.             if(!this.textSnapshot || this._needsNewTexture)
  1259.             {
  1260.                 newTexture = Texture.fromBitmapData(bitmapData, false, false, Starling.contentScaleFactor);
  1261.                 newTexture.root.onRestore = texture_onRestore;
  1262.             }
  1263.             if(!this.textSnapshot)
  1264.             {
  1265.                 this.textSnapshot = new Image(newTexture);
  1266.                 this.addChild(this.textSnapshot);
  1267.             }
  1268.             else
  1269.             {
  1270.                 if(this._needsNewTexture)
  1271.                 {
  1272.                     this.textSnapshot.texture.dispose();
  1273.                     this.textSnapshot.texture = newTexture;
  1274.                     this.textSnapshot.readjustSize();
  1275.                 }
  1276.                 else
  1277.                 {
  1278.                     //this is faster, if we haven't resized the bitmapdata
  1279.                     const existingTexture:Texture = this.textSnapshot.texture;
  1280.                     existingTexture.root.uploadBitmapData(bitmapData);
  1281.                 }
  1282.             }
  1283.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1284.             this.textSnapshot.scaleX = 1 / matrixToScaleX(HELPER_MATRIX);
  1285.             this.textSnapshot.scaleY = 1 / matrixToScaleY(HELPER_MATRIX);
  1286.             bitmapData.dispose();
  1287.             this._needsNewTexture = false;
  1288.         }
  1289.  
  1290.         /**
  1291.          * @private
  1292.          */
  1293.         protected function refreshViewPort():void
  1294.         {
  1295.             const starlingViewPort:Rectangle = Starling.current.viewPort;
  1296.             var stageTextViewPort:Rectangle = this.stageText.viewPort;
  1297.             if(!stageTextViewPort)
  1298.             {
  1299.                 stageTextViewPort = new Rectangle();
  1300.             }
  1301.             if(!this.stageText.stage)
  1302.             {
  1303.                 this.stageText.stage = Starling.current.nativeStage;
  1304.             }
  1305.  
  1306.             HELPER_POINT.x = HELPER_POINT.y = 0;
  1307.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1308.             var globalScaleX:Number = matrixToScaleX(HELPER_MATRIX);
  1309.             var globalScaleY:Number = matrixToScaleY(HELPER_MATRIX);
  1310.             MatrixUtil.transformCoords(HELPER_MATRIX, 0, 0, HELPER_POINT);
  1311.             this._oldGlobalX = HELPER_POINT.x;
  1312.             this._oldGlobalY = HELPER_POINT.y;
  1313.             stageTextViewPort.x = Math.round(starlingViewPort.x + HELPER_POINT.x * Starling.contentScaleFactor);
  1314.             stageTextViewPort.y = Math.round(starlingViewPort.y + HELPER_POINT.y * Starling.contentScaleFactor);
  1315.             var viewPortWidth:Number = Math.round(this.actualWidth * Starling.contentScaleFactor * globalScaleX);
  1316.             if(viewPortWidth < 1 || isNaN(viewPortWidth))
  1317.             {
  1318.                 viewPortWidth = 1;
  1319.             }
  1320.             var viewPortHeight:Number = Math.round(this.actualHeight * Starling.contentScaleFactor * globalScaleY);
  1321.             if(viewPortHeight < 1 || isNaN(viewPortHeight))
  1322.             {
  1323.                 viewPortHeight = 1;
  1324.             }
  1325.             stageTextViewPort.width = viewPortWidth;
  1326.             stageTextViewPort.height = viewPortHeight;
  1327.             this.stageText.viewPort = stageTextViewPort;
  1328.  
  1329.             this._measureTextField.width = this.actualWidth;
  1330.             this._measureTextField.height = this.actualHeight;
  1331.         }
  1332.  
  1333.         /**
  1334.          * @private
  1335.          */
  1336.         protected function disposeContent():void
  1337.         {
  1338.             if(this._measureTextField)
  1339.             {
  1340.                 Starling.current.nativeStage.removeChild(this._measureTextField);
  1341.                 this._measureTextField = null;
  1342.             }
  1343.  
  1344.             if(this.stageText)
  1345.             {
  1346.                 this.disposeStageText();
  1347.             }
  1348.  
  1349.             if(this.textSnapshot)
  1350.             {
  1351.                 //avoid the need to call dispose(). we'll create a new snapshot
  1352.                 //when the renderer is added to stage again.
  1353.                 this.textSnapshot.texture.dispose();
  1354.                 this.removeChild(this.textSnapshot, true);
  1355.                 this.textSnapshot = null;
  1356.             }
  1357.         }
  1358.  
  1359.         /**
  1360.          * @private
  1361.          */
  1362.         protected function disposeStageText():void
  1363.         {
  1364.             if(!this.stageText)
  1365.             {
  1366.                 return;
  1367.             }
  1368.             this.stageText.removeEventListener(flash.events.Event.CHANGE, stageText_changeHandler);
  1369.             this.stageText.removeEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
  1370.             this.stageText.removeEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
  1371.             this.stageText.removeEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
  1372.             this.stageText.removeEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
  1373.             this.stageText.removeEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1374.             this.stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
  1375.             this.stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
  1376.             this.stageText.stage = null;
  1377.             this.stageText.dispose();
  1378.             this.stageText = null;
  1379.         }
  1380.  
  1381.         /**
  1382.          * Creates and adds the <code>stageText</code> instance.
  1383.          *
  1384.          * <p>Meant for internal use, and subclasses may override this function
  1385.          * with a custom implementation.</p>
  1386.          */
  1387.         protected function createStageText():void
  1388.         {
  1389.             this._stageTextIsComplete = false;
  1390.             var StageTextType:Class;
  1391.             var initOptions:Object;
  1392.             try
  1393.             {
  1394.                 StageTextType = Class(getDefinitionByName("flash.text.StageText"));
  1395.                 const StageTextInitOptionsType:Class = Class(getDefinitionByName("flash.text.StageTextInitOptions"));
  1396.                 initOptions = new StageTextInitOptionsType(this._multiline);
  1397.             }
  1398.             catch(error:Error)
  1399.             {
  1400.                 StageTextType = StageTextField;
  1401.                 initOptions = { multiline: this._multiline };
  1402.             }
  1403.             this.stageText = new StageTextType(initOptions);
  1404.             this.stageText.visible = false;
  1405.             this.stageText.addEventListener(flash.events.Event.CHANGE, stageText_changeHandler);
  1406.             this.stageText.addEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
  1407.             this.stageText.addEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
  1408.             this.stageText.addEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
  1409.             this.stageText.addEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
  1410.             this.stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
  1411.             this.stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
  1412.             this.stageText.addEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1413.             this.invalidate();
  1414.         }
  1415.  
  1416.         /**
  1417.          * @private
  1418.          */
  1419.         protected function addedToStageHandler(event:starling.events.Event):void
  1420.         {
  1421.             if(this._measureTextField && !this._measureTextField.parent)
  1422.             {
  1423.                 Starling.current.nativeStage.addChild(this._measureTextField);
  1424.             }
  1425.             else if(!this._measureTextField)
  1426.             {
  1427.                 this._measureTextField = new TextField();
  1428.                 this._measureTextField.visible = false;
  1429.                 this._measureTextField.mouseEnabled = this._measureTextField.mouseWheelEnabled = false;
  1430.                 this._measureTextField.autoSize = TextFieldAutoSize.LEFT;
  1431.                 this._measureTextField.multiline = false;
  1432.                 this._measureTextField.wordWrap = false;
  1433.                 this._measureTextField.embedFonts = false;
  1434.                 this._measureTextField.defaultTextFormat = new TextFormat(null, 11, 0x000000, false, false, false);
  1435.                 Starling.current.nativeStage.addChild(this._measureTextField);
  1436.             }
  1437.  
  1438.             this.createStageText();
  1439.         }
  1440.  
  1441.         /**
  1442.          * @private
  1443.          */
  1444.         protected function removedFromStageHandler(event:starling.events.Event):void
  1445.         {
  1446.             this.disposeContent();
  1447.         }
  1448.  
  1449.         /**
  1450.          * @private
  1451.          */
  1452.         protected function stageText_changeHandler(event:flash.events.Event):void
  1453.         {
  1454.             if(this._ignoreStageTextChanges)
  1455.             {
  1456.                 return;
  1457.             }
  1458.             this.text = this.stageText.text;
  1459.         }
  1460.  
  1461.         /**
  1462.          * @private
  1463.          */
  1464.         protected function stageText_completeHandler(event:flash.events.Event):void
  1465.         {
  1466.             this.stageText.removeEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1467.             this.invalidate();
  1468.  
  1469.             this._stageTextIsComplete = true;
  1470.         }
  1471.  
  1472.         /**
  1473.          * @private
  1474.          */
  1475.         protected function stageText_focusInHandler(event:FocusEvent):void
  1476.         {
  1477.             this._stageTextHasFocus = true;
  1478.             if(this.textSnapshot)
  1479.             {
  1480.                 this.textSnapshot.visible = false;
  1481.             }
  1482.             this.invalidate(INVALIDATION_FLAG_SKIN);
  1483.             this.dispatchEventWith(FeathersEventType.FOCUS_IN);
  1484.         }
  1485.  
  1486.         /**
  1487.          * @private
  1488.          */
  1489.         protected function stageText_focusOutHandler(event:FocusEvent):void
  1490.         {
  1491.             this._stageTextHasFocus = false;
  1492.             //since StageText doesn't expose its scroll position, we need to
  1493.             //set the selection back to the beginning to scroll there. it's a
  1494.             //hack, but so is everything about StageText.
  1495.             //in other news, why won't 0,0 work here?
  1496.             this.stageText.selectRange(1, 1);
  1497.  
  1498.             this.invalidate(INVALIDATION_FLAG_DATA);
  1499.             this.invalidate(INVALIDATION_FLAG_SKIN);
  1500.             this.dispatchEventWith(FeathersEventType.FOCUS_OUT);
  1501.         }
  1502.  
  1503.         /**
  1504.          * @private
  1505.          */
  1506.         protected function stageText_keyDownHandler(event:KeyboardEvent):void
  1507.         {
  1508.             if(!this._multiline && (event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT))
  1509.             {
  1510.                 event.preventDefault();
  1511.                 this.dispatchEventWith(FeathersEventType.ENTER);
  1512.             }
  1513.             else if(event.keyCode == Keyboard.BACK)
  1514.             {
  1515.                 //even a listener on the stage won't detect the back key press that
  1516.                 //will close the application if the StageText has focus, so we
  1517.                 //always need to prevent it here
  1518.                 event.preventDefault();
  1519.                 Starling.current.nativeStage.focus = Starling.current.nativeStage;
  1520.             }
  1521.         }
  1522.  
  1523.         /**
  1524.          * @private
  1525.          */
  1526.         protected function stageText_keyUpHandler(event:KeyboardEvent):void
  1527.         {
  1528.             if(!this._multiline && (event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT))
  1529.             {
  1530.                 event.preventDefault();
  1531.             }
  1532.         }
  1533.  
  1534.         /**
  1535.          * @private
  1536.          */
  1537.         protected function stageText_softKeyboardActivateHandler(event:SoftKeyboardEvent):void
  1538.         {
  1539.             this.dispatchEventWith(FeathersEventType.SOFT_KEYBOARD_ACTIVATE, true);
  1540.         }
  1541.  
  1542.         /**
  1543.          * @private
  1544.          */
  1545.         protected function stageText_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
  1546.         {
  1547.             this.dispatchEventWith(FeathersEventType.SOFT_KEYBOARD_DEACTIVATE, true);
  1548.         }
  1549.     }
  1550. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement