Advertisement
Guest User

Untitled

a guest
Mar 19th, 2020
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Feathers
  3. Copyright 2012-2015 Bowler Hat LLC. 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.     import feathers.core.FeathersControl;
  10.     import feathers.core.FocusManager;
  11.     import feathers.core.IMultilineTextEditor;
  12.     import feathers.events.FeathersEventType;
  13.     import feathers.skins.IStyleProvider;
  14.     import feathers.text.StageTextField;
  15.     import feathers.utils.display.stageToStarling;
  16.     import feathers.utils.geom.matrixToScaleX;
  17.     import feathers.utils.geom.matrixToScaleY;
  18.  
  19.     import flash.display.BitmapData;
  20.     import flash.events.Event;
  21.     import flash.events.FocusEvent;
  22.     import flash.events.KeyboardEvent;
  23.     import flash.events.SoftKeyboardEvent;
  24.     import flash.geom.Matrix;
  25.     import flash.geom.Matrix3D;
  26.     import flash.geom.Point;
  27.     import flash.geom.Rectangle;
  28.     import flash.geom.Vector3D;
  29.     import flash.system.Capabilities;
  30.     import flash.text.TextField;
  31.     import flash.text.TextFieldAutoSize;
  32.     import flash.text.TextFormat;
  33.     import flash.text.TextFormatAlign;
  34.     import flash.text.engine.FontPosture;
  35.     import flash.text.engine.FontWeight;
  36.     import flash.ui.Keyboard;
  37.     import flash.utils.getDefinitionByName;
  38.  
  39.     import starling.core.RenderSupport;
  40.     import starling.core.Starling;
  41.     import starling.display.DisplayObject;
  42.     import starling.display.Image;
  43.     import starling.events.Event;
  44.     import starling.textures.ConcreteTexture;
  45.     import starling.textures.Texture;
  46.     import starling.utils.MatrixUtil;
  47.     import starling.utils.SystemUtil;
  48.  
  49.     /**
  50.      * Dispatched when the text property changes.
  51.      *
  52.      * <p>The properties of the event object have the following values:</p>
  53.      * <table class="innertable">
  54.      * <tr><th>Property</th><th>Value</th></tr>
  55.      * <tr><td><code>bubbles</code></td><td>false</td></tr>
  56.      * <tr><td><code>currentTarget</code></td><td>The Object that defines the
  57.      *   event listener that handles the event. For example, if you use
  58.      *   <code>myButton.addEventListener()</code> to register an event listener,
  59.      *   myButton is the value of the <code>currentTarget</code>.</td></tr>
  60.      * <tr><td><code>data</code></td><td>null</td></tr>
  61.      * <tr><td><code>target</code></td><td>The Object that dispatched the event;
  62.      *   it is not always the Object listening for the event. Use the
  63.      *   <code>currentTarget</code> property to always access the Object
  64.      *   listening for the event.</td></tr>
  65.      * </table>
  66.      */
  67.     [Event(name = "change", type = "starling.events.Event")]
  68.  
  69.     /**
  70.      * Dispatched when the user presses the Enter key while the editor has
  71.      * focus. This event may not be dispatched on some platforms, depending on
  72.      * the value of <code>returnKeyLabel</code>. This issue may even occur when
  73.      * using the <em>default value</em> of <code>returnKeyLabel</code>!
  74.      *
  75.      * <p>The properties of the event object have the following values:</p>
  76.      * <table class="innertable">
  77.      * <tr><th>Property</th><th>Value</th></tr>
  78.      * <tr><td><code>bubbles</code></td><td>false</td></tr>
  79.      * <tr><td><code>currentTarget</code></td><td>The Object that defines the
  80.      *   event listener that handles the event. For example, if you use
  81.      *   <code>myButton.addEventListener()</code> to register an event listener,
  82.      *   myButton is the value of the <code>currentTarget</code>.</td></tr>
  83.      * <tr><td><code>data</code></td><td>null</td></tr>
  84.      * <tr><td><code>target</code></td><td>The Object that dispatched the event;
  85.      *   it is not always the Object listening for the event. Use the
  86.      *   <code>currentTarget</code> property to always access the Object
  87.      *   listening for the event.</td></tr>
  88.      * </table>
  89.      *
  90.      * @eventType feathers.events.FeathersEventType.ENTER
  91.      * @see #returnKeyLabel
  92.      */
  93.     [Event(name = "enter", type = "starling.events.Event")]
  94.  
  95.     /**
  96.      * Dispatched when the text editor receives focus.
  97.      *
  98.      * <p>The properties of the event object have the following values:</p>
  99.      * <table class="innertable">
  100.      * <tr><th>Property</th><th>Value</th></tr>
  101.      * <tr><td><code>bubbles</code></td><td>false</td></tr>
  102.      * <tr><td><code>currentTarget</code></td><td>The Object that defines the
  103.      *   event listener that handles the event. For example, if you use
  104.      *   <code>myButton.addEventListener()</code> to register an event listener,
  105.      *   myButton is the value of the <code>currentTarget</code>.</td></tr>
  106.      * <tr><td><code>data</code></td><td>null</td></tr>
  107.      * <tr><td><code>target</code></td><td>The Object that dispatched the event;
  108.      *   it is not always the Object listening for the event. Use the
  109.      *   <code>currentTarget</code> property to always access the Object
  110.      *   listening for the event.</td></tr>
  111.      * </table>
  112.      *
  113.      * @eventType feathers.events.FeathersEventType.FOCUS_IN
  114.      */
  115.     [Event(name = "focusIn", type = "starling.events.Event")]
  116.  
  117.     /**
  118.      * Dispatched when the text editor loses focus.
  119.      *
  120.      * <p>The properties of the event object have the following values:</p>
  121.      * <table class="innertable">
  122.      * <tr><th>Property</th><th>Value</th></tr>
  123.      * <tr><td><code>bubbles</code></td><td>false</td></tr>
  124.      * <tr><td><code>currentTarget</code></td><td>The Object that defines the
  125.      *   event listener that handles the event. For example, if you use
  126.      *   <code>myButton.addEventListener()</code> to register an event listener,
  127.      *   myButton is the value of the <code>currentTarget</code>.</td></tr>
  128.      * <tr><td><code>data</code></td><td>null</td></tr>
  129.      * <tr><td><code>target</code></td><td>The Object that dispatched the event;
  130.      *   it is not always the Object listening for the event. Use the
  131.      *   <code>currentTarget</code> property to always access the Object
  132.      *   listening for the event.</td></tr>
  133.      * </table>
  134.      *
  135.      * @eventType feathers.events.FeathersEventType.FOCUS_OUT
  136.      */
  137.     [Event(name = "focusOut", type = "starling.events.Event")]
  138.  
  139.     /**
  140.      * Dispatched when the soft keyboard is activated. Not all text editors will
  141.      * activate a soft keyboard.
  142.      *
  143.      * <p>The properties of the event object have the following values:</p>
  144.      * <table class="innertable">
  145.      * <tr><th>Property</th><th>Value</th></tr>
  146.      * <tr><td><code>bubbles</code></td><td>false</td></tr>
  147.      * <tr><td><code>currentTarget</code></td><td>The Object that defines the
  148.      *   event listener that handles the event. For example, if you use
  149.      *   <code>myButton.addEventListener()</code> to register an event listener,
  150.      *   myButton is the value of the <code>currentTarget</code>.</td></tr>
  151.      * <tr><td><code>data</code></td><td>null</td></tr>
  152.      * <tr><td><code>target</code></td><td>The Object that dispatched the event;
  153.      *   it is not always the Object listening for the event. Use the
  154.      *   <code>currentTarget</code> property to always access the Object
  155.      *   listening for the event.</td></tr>
  156.      * </table>
  157.      *
  158.      * @eventType feathers.events.FeathersEventType.SOFT_KEYBOARD_ACTIVATE
  159.      */
  160.     [Event(name = "softKeyboardActivate", type = "starling.events.Event")]
  161.  
  162.     /**
  163.      * Dispatched when the soft keyboard is deactivated. Not all text editors
  164.      * will activate a soft keyboard.
  165.      *
  166.      * <p>The properties of the event object have the following values:</p>
  167.      * <table class="innertable">
  168.      * <tr><th>Property</th><th>Value</th></tr>
  169.      * <tr><td><code>bubbles</code></td><td>false</td></tr>
  170.      * <tr><td><code>currentTarget</code></td><td>The Object that defines the
  171.      *   event listener that handles the event. For example, if you use
  172.      *   <code>myButton.addEventListener()</code> to register an event listener,
  173.      *   myButton is the value of the <code>currentTarget</code>.</td></tr>
  174.      * <tr><td><code>data</code></td><td>null</td></tr>
  175.      * <tr><td><code>target</code></td><td>The Object that dispatched the event;
  176.      *   it is not always the Object listening for the event. Use the
  177.      *   <code>currentTarget</code> property to always access the Object
  178.      *   listening for the event.</td></tr>
  179.      * </table>
  180.      *
  181.      * @eventType feathers.events.FeathersEventType.SOFT_KEYBOARD_DEACTIVATE
  182.      */
  183.     [Event(name = "softKeyboardDeactivate", type = "starling.events.Event")]
  184.  
  185.     /**
  186.      * Text that may be edited at runtime by the user with the
  187.      * <code>TextInput</code> component, rendered with the native
  188.      * <code>flash.text.StageText</code> class in Adobe AIR and the custom
  189.      * <code>feathers.text.StageTextField</code> class in Adobe Flash Player
  190.      * (<code>StageTextField</code> simulates <code>StageText</code> using
  191.      * <code>flash.text.TextField</code>). When not in focus, the
  192.      * <code>StageText</code> (or <code>StageTextField</code>) is drawn to
  193.      * <code>BitmapData</code> and uploaded to a texture on the GPU. Textures
  194.      * are managed internally by this component, and they will be automatically
  195.      * disposed when the component is disposed.
  196.      *
  197.      * <p>The following example shows how to use
  198.      * <code>StageTextTextEditor</code> with a <code>TextInput</code>:</p>
  199.      *
  200.      * <listing version="3.0">
  201.      * var input:TextInput = new TextInput();
  202.      * input.textEditorFactory = function():ITextEditor
  203.      * {
  204.      *     return new StageTextTextEditor();
  205.      * };
  206.      * this.addChild( input );</listing>
  207.      *
  208.      * @see feathers.controls.TextInput
  209.      * @see ../../../../help/text-editors.html Introduction to Feathers text editors
  210.      * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html flash.text.StageText
  211.      * @see feathers.text.StageTextField
  212.      */
  213.     public class StageTextTextEditor extends FeathersControl implements IMultilineTextEditor {
  214.         /**
  215.          * @private
  216.          */
  217.         private static var HELPER_MATRIX3D: Matrix3D;
  218.  
  219.         /**
  220.          * @private
  221.          */
  222.         private static var HELPER_POINT3D: Vector3D;
  223.  
  224.         /**
  225.          * @private
  226.          */
  227.         private static const HELPER_MATRIX: Matrix = new Matrix();
  228.  
  229.         /**
  230.          * @private
  231.          */
  232.         private static const HELPER_POINT: Point = new Point();
  233.  
  234.         /**
  235.          * The default <code>IStyleProvider</code> for all <code>StageTextTextEditor</code>
  236.          * components.
  237.          *
  238.          * @default null
  239.          * @see feathers.core.FeathersControl#styleProvider
  240.          */
  241.         public static var globalStyleProvider: IStyleProvider;
  242.  
  243.         /**
  244.          * Constructor.
  245.          */
  246.         public function StageTextTextEditor() {
  247.             this._stageTextIsTextField = /^(Windows|Mac OS|Linux) .*/.exec(Capabilities.os);
  248.             this.isQuickHitAreaEnabled = true;
  249.             this.addEventListener(starling.events.Event.REMOVED_FROM_STAGE, textEditor_removedFromStageHandler);
  250.         }
  251.  
  252.         /**
  253.          * @private
  254.          */
  255.         override protected function get defaultStyleProvider(): IStyleProvider {
  256.             return globalStyleProvider;
  257.         }
  258.  
  259.         /**
  260.          * The StageText instance. It's typed Object so that a replacement class
  261.          * can be used in browser-based Flash Player.
  262.          */
  263.         protected var stageText: Object;
  264.  
  265.         /**
  266.          * An image that displays a snapshot of the native <code>StageText</code>
  267.          * in the Starling display list when the editor doesn't have focus.
  268.          */
  269.         protected var textSnapshot: Image;
  270.  
  271.         /**
  272.          * @private
  273.          */
  274.         protected var _needsNewTexture: Boolean = false;
  275.  
  276.         /**
  277.          * @private
  278.          */
  279.         protected var _ignoreStageTextChanges: Boolean = false;
  280.  
  281.         /**
  282.          * @private
  283.          */
  284.         protected var _text: String = "";
  285.  
  286.         /**
  287.          * The text displayed by the input.
  288.          *
  289.          * <p>In the following example, the text is changed:</p>
  290.          *
  291.          * <listing version="3.0">
  292.          * textEditor.text = "Lorem ipsum";</listing>
  293.          *
  294.          * @default ""
  295.          */
  296.         public function get text(): String {
  297.             return this._text;
  298.         }
  299.  
  300.         /**
  301.          * @private
  302.          */
  303.         public function set text(value: String): void {
  304.             if (!value) {
  305.                 //don't allow null or undefined
  306.                 value = "";
  307.             }
  308.             if (this._text == value) {
  309.                 return;
  310.             }
  311.             this._text = value;
  312.             this.invalidate(INVALIDATION_FLAG_DATA);
  313.             this.dispatchEventWith(starling.events.Event.CHANGE);
  314.         }
  315.  
  316.         /**
  317.          * @private
  318.          */
  319.         protected var _measureTextField: TextField;
  320.  
  321.         /**
  322.          * @private
  323.          * This flag tells us if StageText is implemented by a TextField under
  324.          * the hood. We want to eliminate that damn TextField gutter to improve
  325.          * consistency across platforms.
  326.          */
  327.         protected var _stageTextIsTextField: Boolean = false;
  328.  
  329.         /**
  330.          * @private
  331.          */
  332.         protected var _stageTextHasFocus: Boolean = false;
  333.  
  334.         /**
  335.          * @private
  336.          */
  337.         protected var _isWaitingToSetFocus: Boolean = false;
  338.  
  339.         /**
  340.          * @private
  341.          */
  342.         protected var _pendingSelectionBeginIndex: int = -1;
  343.  
  344.         /**
  345.          * @inheritDoc
  346.          */
  347.         public function get selectionBeginIndex(): int {
  348.             if (this._pendingSelectionBeginIndex >= 0) {
  349.                 return this._pendingSelectionBeginIndex;
  350.             }
  351.             if (this.stageText) {
  352.                 return this.stageText.selectionAnchorIndex;
  353.             }
  354.             return 0;
  355.         }
  356.  
  357.         /**
  358.          * @private
  359.          */
  360.         protected var _pendingSelectionEndIndex: int = -1;
  361.  
  362.         /**
  363.          * @inheritDoc
  364.          */
  365.         public function get selectionEndIndex(): int {
  366.             if (this._pendingSelectionEndIndex >= 0) {
  367.                 return this._pendingSelectionEndIndex;
  368.             }
  369.             if (this.stageText) {
  370.                 return this.stageText.selectionActiveIndex;
  371.             }
  372.             return 0;
  373.         }
  374.  
  375.         /**
  376.          * @private
  377.          */
  378.         protected var _stageTextIsComplete: Boolean = false;
  379.  
  380.         /**
  381.          * @inheritDoc
  382.          */
  383.         public function get baseline(): Number {
  384.             if (!this._measureTextField) {
  385.                 return 0;
  386.             }
  387.             return this._measureTextField.getLineMetrics(0).ascent;
  388.         }
  389.  
  390.         /**
  391.          * @private
  392.          */
  393.         protected var _autoCapitalize: String = "none";
  394.  
  395.         /**
  396.          * Controls how a device applies auto capitalization to user input. This
  397.          * property is only a hint to the underlying platform, because not all
  398.          * devices and operating systems support this functionality.
  399.          *
  400.          * <p>In the following example, the auto capitalize behavior is changed:</p>
  401.          *
  402.          * <listing version="3.0">
  403.          * textEditor.autoCapitalize = AutoCapitalize.WORD;</listing>
  404.          *
  405.          * @default flash.text.AutoCapitalize.NONE
  406.          *
  407.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#autoCapitalize Full description of flash.text.StageText.autoCapitalize in Adobe's Flash Platform API Reference
  408.          */
  409.         public function get autoCapitalize(): String {
  410.             return this._autoCapitalize;
  411.         }
  412.  
  413.         /**
  414.          * @private
  415.          */
  416.         public function set autoCapitalize(value: String): void {
  417.             if (this._autoCapitalize == value) {
  418.                 return;
  419.             }
  420.             this._autoCapitalize = value;
  421.             this.invalidate(INVALIDATION_FLAG_STYLES);
  422.         }
  423.  
  424.         /**
  425.          * @private
  426.          */
  427.         protected var _autoCorrect: Boolean = false;
  428.  
  429.         /**
  430.          * Indicates whether a device auto-corrects user input for spelling or
  431.          * punctuation mistakes. This property is only a hint to the underlying
  432.          * platform, because not all devices and operating systems support this
  433.          * functionality.
  434.          *
  435.          * <p>In the following example, auto correct is enabled:</p>
  436.          *
  437.          * <listing version="3.0">
  438.          * textEditor.autoCorrect = true;</listing>
  439.          *
  440.          * @default false
  441.          *
  442.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#autoCorrect Full description of flash.text.StageText.autoCorrect in Adobe's Flash Platform API Reference
  443.          */
  444.         public function get autoCorrect(): Boolean {
  445.             return this._autoCorrect;
  446.         }
  447.  
  448.         /**
  449.          * @private
  450.          */
  451.         public function set autoCorrect(value: Boolean): void {
  452.             if (this._autoCorrect == value) {
  453.                 return;
  454.             }
  455.             this._autoCorrect = value;
  456.             this.invalidate(INVALIDATION_FLAG_STYLES);
  457.         }
  458.  
  459.         /**
  460.          * @private
  461.          */
  462.         protected var _color: uint = 0x000000;
  463.  
  464.         /**
  465.          * Specifies text color as a number containing three 8-bit RGB
  466.          * components.
  467.          *
  468.          * <p>In the following example, the text color is changed:</p>
  469.          *
  470.          * <listing version="3.0">
  471.          * textEditor.color = 0xff9900;</listing>
  472.          *
  473.          * @default 0x000000
  474.          *
  475.          * @see #disabledColor
  476.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#color Full description of flash.text.StageText.color in Adobe's Flash Platform API Reference
  477.          */
  478.         public function get color(): uint {
  479.             return this._color;
  480.         }
  481.  
  482.         /**
  483.          * @private
  484.          */
  485.         public function set color(value: uint): void {
  486.             if (this._color == value) {
  487.                 return;
  488.             }
  489.             this._color = value;
  490.             this.invalidate(INVALIDATION_FLAG_STYLES);
  491.         }
  492.  
  493.         /**
  494.          * @private
  495.          */
  496.         protected var _disabledColor: uint = 0x999999;
  497.  
  498.         /**
  499.          * Specifies text color when the component is disabled as a number
  500.          * containing three 8-bit RGB components.
  501.          *
  502.          * <p>In the following example, the text color is changed:</p>
  503.          *
  504.          * <listing version="3.0">
  505.          * textEditor.isEnabled = false;
  506.          * textEditor.disabledColor = 0xff9900;</listing>
  507.          *
  508.          * @default 0x999999
  509.          *
  510.          * @see #disabledColor
  511.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#color Full description of flash.text.StageText.color in Adobe's Flash Platform API Reference
  512.          */
  513.         public function get disabledColor(): uint {
  514.             return this._disabledColor;
  515.         }
  516.  
  517.         /**
  518.          * @private
  519.          */
  520.         public function set disabledColor(value: uint): void {
  521.             if (this._disabledColor == value) {
  522.                 return;
  523.             }
  524.             this._disabledColor = value;
  525.             this.invalidate(INVALIDATION_FLAG_STYLES);
  526.         }
  527.  
  528.         /**
  529.          * @private
  530.          */
  531.         protected var _displayAsPassword: Boolean = false;
  532.  
  533.         /**
  534.          * <p>This property is managed by the <code>TextInput</code>.</p>
  535.          *
  536.          * @copy feathers.controls.TextInput#displayAsPassword
  537.          *
  538.          * @see feathers.controls.TextInput#displayAsPassword
  539.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#displayAsPassword Full description of flash.text.StageText.displayAsPassword in Adobe's Flash Platform API Reference
  540.          */
  541.         public function get displayAsPassword(): Boolean {
  542.             return this._displayAsPassword;
  543.         }
  544.  
  545.         /**
  546.          * @private
  547.          */
  548.         public function set displayAsPassword(value: Boolean): void {
  549.             if (this._displayAsPassword == value) {
  550.                 return;
  551.             }
  552.             this._displayAsPassword = value;
  553.             this.invalidate(INVALIDATION_FLAG_STYLES);
  554.         }
  555.  
  556.         /**
  557.          * @private
  558.          */
  559.         protected var _isEditable: Boolean = true;
  560.  
  561.         /**
  562.          * <p>This property is managed by the <code>TextInput</code>.</p>
  563.          *
  564.          * @copy feathers.controls.TextInput#isEditable
  565.          *
  566.          * @see feathers.controls.TextInput#isEditable
  567.          */
  568.         public function get isEditable(): Boolean {
  569.             return this._isEditable;
  570.         }
  571.  
  572.         /**
  573.          * @private
  574.          */
  575.         public function set isEditable(value: Boolean): void {
  576.             if (this._isEditable == value) {
  577.                 return;
  578.             }
  579.             this._isEditable = value;
  580.             this.invalidate(INVALIDATION_FLAG_STYLES);
  581.         }
  582.  
  583.         /**
  584.          * @private
  585.          */
  586.         protected var _isSelectable: Boolean = true;
  587.  
  588.         /**
  589.          * <p>This property is managed by the <code>TextInput</code>.</p>
  590.          *
  591.          * @copy feathers.controls.TextInput#isSelectable
  592.          *
  593.          * @see feathers.controls.TextInput#isSelectable
  594.          */
  595.         public function get isSelectable(): Boolean {
  596.             return this._isEditable;
  597.         }
  598.  
  599.         /**
  600.          * @private
  601.          */
  602.         public function set isSelectable(value: Boolean): void {
  603.             if (this._isSelectable == value) {
  604.                 return;
  605.             }
  606.             this._isSelectable = value;
  607.             this.invalidate(INVALIDATION_FLAG_STYLES);
  608.         }
  609.  
  610.         /**
  611.          * @inheritDoc
  612.          *
  613.          * @default true
  614.          */
  615.         public function get setTouchFocusOnEndedPhase(): Boolean {
  616.             return true;
  617.         }
  618.  
  619.         /**
  620.          * @private
  621.          */
  622.         protected var _fontFamily: String = null;
  623.  
  624.         /**
  625.          * Indicates the name of the current font family. A value of null
  626.          * indicates the system default.
  627.          *
  628.          * <p>In the following example, the font family is changed:</p>
  629.          *
  630.          * <listing version="3.0">
  631.          * textEditor.fontFamily = "Source Sans Pro";</listing>
  632.          *
  633.          * @default null
  634.          *
  635.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#fontFamily Full description of flash.text.StageText.fontFamily in Adobe's Flash Platform API Reference
  636.          */
  637.         public function get fontFamily(): String {
  638.             return this._fontFamily;
  639.         }
  640.  
  641.         /**
  642.          * @private
  643.          */
  644.         public function set fontFamily(value: String): void {
  645.             if (this._fontFamily == value) {
  646.                 return;
  647.             }
  648.             this._fontFamily = value;
  649.             this.invalidate(INVALIDATION_FLAG_STYLES);
  650.         }
  651.  
  652.         /**
  653.          * @private
  654.          */
  655.         protected var _fontPosture: String = FontPosture.NORMAL;
  656.  
  657.         /**
  658.          * Specifies the font posture, using constants defined in the
  659.          * <code>flash.text.engine.FontPosture</code> class.
  660.          *
  661.          * <p>In the following example, the font posture is changed:</p>
  662.          *
  663.          * <listing version="3.0">
  664.          * textEditor.fontPosture = FontPosture.ITALIC;</listing>
  665.          *
  666.          * @default flash.text.engine.FontPosture.NORMAL
  667.          *
  668.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#fontPosture Full description of flash.text.StageText.fontPosture in Adobe's Flash Platform API Reference
  669.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/engine/FontPosture.html flash.text.engine.FontPosture
  670.          */
  671.         public function get fontPosture(): String {
  672.             return this._fontPosture;
  673.         }
  674.  
  675.         /**
  676.          * @private
  677.          */
  678.         public function set fontPosture(value: String): void {
  679.             if (this._fontPosture == value) {
  680.                 return;
  681.             }
  682.             this._fontPosture = value;
  683.             this.invalidate(INVALIDATION_FLAG_STYLES);
  684.         }
  685.  
  686.         /**
  687.          * @private
  688.          */
  689.         protected var _fontSize: int = 12;
  690.  
  691.         /**
  692.          * The size in pixels for the current font family.
  693.          *
  694.          * <p>In the following example, the font size is increased to 16 pixels:</p>
  695.          *
  696.          * <listing version="3.0">
  697.          * textEditor.fontSize = 16;</listing>
  698.          *
  699.          * @default 12
  700.          *
  701.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#fontSize Full description of flash.text.StageText.fontSize in Adobe's Flash Platform API Reference
  702.          */
  703.         public function get fontSize(): int {
  704.             return this._fontSize;
  705.         }
  706.  
  707.         /**
  708.          * @private
  709.          */
  710.         public function set fontSize(value: int): void {
  711.             if (this._fontSize == value) {
  712.                 return;
  713.             }
  714.             this._fontSize = value;
  715.             this.invalidate(INVALIDATION_FLAG_STYLES);
  716.         }
  717.  
  718.         /**
  719.          * @private
  720.          */
  721.         protected var _fontWeight: String = FontWeight.NORMAL;
  722.  
  723.         /**
  724.          * Specifies the font weight, using constants defined in the
  725.          * <code>flash.text.engine.FontWeight</code> class.
  726.          *
  727.          * <p>In the following example, the font weight is changed to bold:</p>
  728.          *
  729.          * <listing version="3.0">
  730.          * textEditor.fontWeight = FontWeight.BOLD;</listing>
  731.          *
  732.          * @default flash.text.engine.FontWeight.NORMAL
  733.          *
  734.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#fontWeight Full description of flash.text.StageText.fontWeight in Adobe's Flash Platform API Reference
  735.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/engine/FontWeight.html flash.text.engine.FontWeight
  736.          */
  737.         public function get fontWeight(): String {
  738.             return this._fontWeight;
  739.         }
  740.  
  741.         /**
  742.          * @private
  743.          */
  744.         public function set fontWeight(value: String): void {
  745.             if (this._fontWeight == value) {
  746.                 return;
  747.             }
  748.             this._fontWeight = value;
  749.             this.invalidate(INVALIDATION_FLAG_STYLES);
  750.         }
  751.  
  752.         /**
  753.          * @private
  754.          */
  755.         protected var _locale: String = "en";
  756.  
  757.         /**
  758.          * Indicates the locale of the text. <code>StageText</code> uses the
  759.          * standard locale identifiers. For example <code>"en"</code>,
  760.          * <code>"en_US"</code> and <code>"en-US"</code> are all English.
  761.          *
  762.          * <p>In the following example, the locale is changed to Russian:</p>
  763.          *
  764.          * <listing version="3.0">
  765.          * textEditor.locale = "ru";</listing>
  766.          *
  767.          * @default "en"
  768.          *
  769.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#locale Full description of flash.text.StageText.locale in Adobe's Flash Platform API Reference
  770.          */
  771.         public function get locale(): String {
  772.             return this._locale;
  773.         }
  774.  
  775.         /**
  776.          * @private
  777.          */
  778.         public function set locale(value: String): void {
  779.             if (this._locale == value) {
  780.                 return;
  781.             }
  782.             this._locale = value;
  783.             this.invalidate(INVALIDATION_FLAG_STYLES);
  784.         }
  785.  
  786.         /**
  787.          * @private
  788.          */
  789.         protected var _maxChars: int = 0;
  790.  
  791.         /**
  792.          * <p>This property is managed by the <code>TextInput</code>.</p>
  793.          *
  794.          * @copy feathers.controls.TextInput#maxChars
  795.          *
  796.          * @see feathers.controls.TextInput#maxChars
  797.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#maxChars Full description of flash.text.StageText.maxChars in Adobe's Flash Platform API Reference
  798.          */
  799.         public function get maxChars(): int {
  800.             return this._maxChars;
  801.         }
  802.  
  803.         /**
  804.          * @private
  805.          */
  806.         public function set maxChars(value: int): void {
  807.             if (this._maxChars == value) {
  808.                 return;
  809.             }
  810.             this._maxChars = value;
  811.             this.invalidate(INVALIDATION_FLAG_STYLES);
  812.         }
  813.  
  814.         /**
  815.          * @private
  816.          */
  817.         protected var _multiline: Boolean = false;
  818.  
  819.         /**
  820.          * Indicates whether the StageText object can display more than one line
  821.          * of text. This property is configurable after the text editor is
  822.          * created, unlike a regular <code>StageText</code> instance. The text
  823.          * editor will dispose and recreate its internal <code>StageText</code>
  824.          * instance if the value of the <code>multiline</code> property is
  825.          * changed after the <code>StageText</code> is initially created.
  826.          *
  827.          * <p>In the following example, multiline is enabled:</p>
  828.          *
  829.          * <listing version="3.0">
  830.          * textEditor.multiline = true;</listing>
  831.          *
  832.          * When setting this property to <code>true</code>, it is recommended
  833.          * that the text input's <code>verticalAlign</code> property is set to
  834.          * <code>TextInput.VERTICAL_ALIGN_JUSTIFY</code>.
  835.          *
  836.          * @default false
  837.          *
  838.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#multiline Full description of flash.text.StageText.multiline in Adobe's Flash Platform API Reference
  839.          */
  840.         public function get multiline(): Boolean {
  841.             return this._multiline;
  842.         }
  843.  
  844.         /**
  845.          * @private
  846.          */
  847.         public function set multiline(value: Boolean): void {
  848.             if (this._multiline == value) {
  849.                 return;
  850.             }
  851.             this._multiline = value;
  852.             this.invalidate(INVALIDATION_FLAG_STYLES);
  853.         }
  854.  
  855.         /**
  856.          * @private
  857.          */
  858.         protected var _restrict: String;
  859.  
  860.         /**
  861.          * <p>This property is managed by the <code>TextInput</code>.</p>
  862.          *
  863.          * @copy feathers.controls.TextInput#restrict
  864.          *
  865.          * @see feathers.controls.TextInput#restrict
  866.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#restrict Full description of flash.text.StageText.restrict in Adobe's Flash Platform API Reference
  867.          */
  868.         public function get restrict(): String {
  869.             return this._restrict;
  870.         }
  871.  
  872.         /**
  873.          * @private
  874.          */
  875.         public function set restrict(value: String): void {
  876.             if (this._restrict == value) {
  877.                 return;
  878.             }
  879.             this._restrict = value;
  880.             this.invalidate(INVALIDATION_FLAG_STYLES);
  881.         }
  882.  
  883.         /**
  884.          * @private
  885.          */
  886.         protected var _returnKeyLabel: String = "default";
  887.  
  888.         /**
  889.          * Indicates the label on the Return key for devices that feature a soft
  890.          * keyboard. The available values are constants defined in the
  891.          * <code>flash.text.ReturnKeyLabel</code> class. This property is only a
  892.          * hint to the underlying platform, because not all devices and
  893.          * operating systems support this functionality.
  894.          *
  895.          * <p>In the following example, the return key label is changed:</p>
  896.          *
  897.          * <listing version="3.0">
  898.          * textEditor.returnKeyLabel = ReturnKeyLabel.GO;</listing>
  899.          *
  900.          * @default flash.text.ReturnKeyLabel.DEFAULT
  901.          *
  902.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#returnKeyLabel Full description of flash.text.StageText.returnKeyLabel in Adobe's Flash Platform API Reference
  903.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/ReturnKeyLabel.html flash.text.ReturnKeyLabel
  904.          */
  905.         public function get returnKeyLabel(): String {
  906.             return this._returnKeyLabel;
  907.         }
  908.  
  909.         /**
  910.          * @private
  911.          */
  912.         public function set returnKeyLabel(value: String): void {
  913.             if (this._returnKeyLabel == value) {
  914.                 return;
  915.             }
  916.             this._returnKeyLabel = value;
  917.             this.invalidate(INVALIDATION_FLAG_STYLES);
  918.         }
  919.  
  920.         /**
  921.          * @private
  922.          */
  923.         protected var _softKeyboardType: String = "default";
  924.  
  925.         /**
  926.          * Controls the appearance of the soft keyboard. Valid values are
  927.          * defined as constants in the <code>flash.text.SoftKeyboardType</code>
  928.          * class. This property is only a hint to the underlying platform,
  929.          * because not all devices and operating systems support this
  930.          * functionality.
  931.          *
  932.          * <p>In the following example, the soft keyboard type is changed:</p>
  933.          *
  934.          * <listing version="3.0">
  935.          * textEditor.softKeyboardType = SoftKeyboardType.NUMBER;</listing>
  936.          *
  937.          * @default flash.text.SoftKeyboardType.DEFAULT
  938.          *
  939.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#softKeyboardType Full description of flash.text.StageText.softKeyboardType in Adobe's Flash Platform API Reference
  940.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/SoftKeyboardType.html flash.text.SoftKeyboardType
  941.          */
  942.         public function get softKeyboardType(): String {
  943.             return this._softKeyboardType;
  944.         }
  945.  
  946.         /**
  947.          * @private
  948.          */
  949.         public function set softKeyboardType(value: String): void {
  950.             if (this._softKeyboardType == value) {
  951.                 return;
  952.             }
  953.             this._softKeyboardType = value;
  954.             this.invalidate(INVALIDATION_FLAG_STYLES);
  955.         }
  956.  
  957.         /**
  958.          * @private
  959.          */
  960.         protected var _textAlign: String = TextFormatAlign.START;
  961.  
  962.         /**
  963.          * Indicates the paragraph alignment. Valid values are defined as
  964.          * constants in the <code>flash.text.TextFormatAlign</code> class.
  965.          *
  966.          * <p>In the following example, the text is centered:</p>
  967.          *
  968.          * <listing version="3.0">
  969.          * textEditor.textAlign = TextFormatAlign.CENTER;</listing>
  970.          *
  971.          * @default flash.text.TextFormatAlign.START
  972.          *
  973.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/StageText.html#textAlign Full description of flash.text.StageText.textAlign in Adobe's Flash Platform API Reference
  974.          * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextFormatAlign.html flash.text.TextFormatAlign
  975.          */
  976.         public function get textAlign(): String {
  977.             return this._textAlign;
  978.         }
  979.  
  980.         /**
  981.          * @private
  982.          */
  983.         public function set textAlign(value: String): void {
  984.             if (this._textAlign == value) {
  985.                 return;
  986.             }
  987.             this._textAlign = value;
  988.             this.invalidate(INVALIDATION_FLAG_STYLES);
  989.         }
  990.  
  991.         /**
  992.          * @private
  993.          */
  994.         protected var _lastGlobalScaleX: Number = 0;
  995.  
  996.         /**
  997.          * @private
  998.          */
  999.         protected var _lastGlobalScaleY: Number = 0;
  1000.  
  1001.         /**
  1002.          * @private
  1003.          */
  1004.         protected var _updateSnapshotOnScaleChange: Boolean = false;
  1005.  
  1006.         /**
  1007.          * Refreshes the texture snapshot every time that the text editor is
  1008.          * scaled. Based on the scale in global coordinates, so scaling the
  1009.          * parent will require a new snapshot.
  1010.          *
  1011.          * <p>Warning: setting this property to true may result in reduced
  1012.          * performance because every change of the scale requires uploading a
  1013.          * new texture to the GPU. Use with caution. Consider setting this
  1014.          * property to false temporarily during animations that modify the
  1015.          * scale.</p>
  1016.          *
  1017.          * <p>In the following example, the snapshot will be updated when the
  1018.          * text editor is scaled:</p>
  1019.          *
  1020.          * <listing version="3.0">
  1021.          * textEditor.updateSnapshotOnScaleChange = true;</listing>
  1022.          *
  1023.          * @default false
  1024.          */
  1025.         public function get updateSnapshotOnScaleChange(): Boolean {
  1026.             return this._updateSnapshotOnScaleChange;
  1027.         }
  1028.  
  1029.         /**
  1030.          * @private
  1031.          */
  1032.         public function set updateSnapshotOnScaleChange(value: Boolean): void {
  1033.             if (this._updateSnapshotOnScaleChange == value) {
  1034.                 return;
  1035.             }
  1036.             this._updateSnapshotOnScaleChange = value;
  1037.             this.invalidate(INVALIDATION_FLAG_DATA);
  1038.         }
  1039.  
  1040.         /**
  1041.          * @private
  1042.          */
  1043.         override public function dispose(): void {
  1044.             if (this._measureTextField) {
  1045.                 Starling.current.nativeStage.removeChild(this._measureTextField);
  1046.                 this._measureTextField = null;
  1047.             }
  1048.  
  1049.             if (this.stageText) {
  1050.                 this.disposeStageText();
  1051.             }
  1052.  
  1053.             if (this.textSnapshot) {
  1054.                 //avoid the need to call dispose(). we'll create a new snapshot
  1055.                 //when the renderer is added to stage again.
  1056.                 this.textSnapshot.texture.dispose();
  1057.                 this.removeChild(this.textSnapshot, true);
  1058.                 this.textSnapshot = null;
  1059.             }
  1060.  
  1061.             super.dispose();
  1062.         }
  1063.  
  1064.         /**
  1065.          * @private
  1066.          */
  1067.         override public function render(support: RenderSupport, parentAlpha: Number): void {
  1068.             if (this.textSnapshot && this._updateSnapshotOnScaleChange) {
  1069.                 this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1070.                 if (matrixToScaleX(HELPER_MATRIX) != this._lastGlobalScaleX || matrixToScaleY(HELPER_MATRIX) != this._lastGlobalScaleY) {
  1071.                     //the snapshot needs to be updated because the scale has
  1072.                     //changed since the last snapshot was taken.
  1073.                     this.invalidate(INVALIDATION_FLAG_SIZE);
  1074.                     this.validate();
  1075.                 }
  1076.             }
  1077.  
  1078.             //we'll skip this if the text field isn't visible to avoid running
  1079.             //that code every frame.
  1080.             if (this.stageText && this.stageText.visible) {
  1081.                 this.refreshViewPortAndFontSize();
  1082.             }
  1083.  
  1084.             if (this.textSnapshot) {
  1085.                 this.positionSnapshot();
  1086.             }
  1087.  
  1088.             super.render(support, parentAlpha);
  1089.         }
  1090.  
  1091.         /**
  1092.          * @inheritDoc
  1093.          */
  1094.         public function setFocus(position: Point = null): void {
  1095.             //setting the editable property of a StageText to false seems to be
  1096.             //ignored on Android, so this is the workaround
  1097.             if (!this._isEditable && SystemUtil.platform === "AND") {
  1098.                 return;
  1099.             }
  1100.             if (!this._isEditable && !this._isSelectable) {
  1101.                 return;
  1102.             }
  1103.             if (this.stage && !this.stageText.stage) {
  1104.                 this.stageText.stage = Starling.current.nativeStage;
  1105.             }
  1106.             if (this.stageText && this._stageTextIsComplete) {
  1107.                 if (position) {
  1108.                     var positionX: Number = position.x + 2;
  1109.                     var positionY: Number = position.y + 2;
  1110.                     if (positionX < 0) {
  1111.                         this._pendingSelectionBeginIndex = this._pendingSelectionEndIndex = 0;
  1112.                     } else {
  1113.                         this._pendingSelectionBeginIndex = this._measureTextField.getCharIndexAtPoint(positionX, positionY);
  1114.                         if (this._pendingSelectionBeginIndex < 0) {
  1115.                             if (this._multiline) {
  1116.                                 var lineIndex: int = int(positionY / this._measureTextField.getLineMetrics(0).height);
  1117.                                 try {
  1118.                                     this._pendingSelectionBeginIndex = this._measureTextField.getLineOffset(lineIndex) + this._measureTextField.getLineLength(lineIndex);
  1119.                                     if (this._pendingSelectionBeginIndex != this._text.length) {
  1120.                                         this._pendingSelectionBeginIndex--;
  1121.                                     }
  1122.                                 } catch (error: Error) {
  1123.                                     //we may be checking for a line beyond the
  1124.                                     //end that doesn't exist
  1125.                                     this._pendingSelectionBeginIndex = this._text.length;
  1126.                                 }
  1127.                             } else {
  1128.                                 this._pendingSelectionBeginIndex = this._measureTextField.getCharIndexAtPoint(positionX, this._measureTextField.getLineMetrics(0).ascent / 2);
  1129.                                 if (this._pendingSelectionBeginIndex < 0) {
  1130.                                     this._pendingSelectionBeginIndex = this._text.length;
  1131.                                 }
  1132.                             }
  1133.                         } else {
  1134.                             var bounds: Rectangle = this._measureTextField.getCharBoundaries(this._pendingSelectionBeginIndex);
  1135.                             var boundsX: Number = bounds.x;
  1136.                             if (bounds && (boundsX + bounds.width - positionX) < (positionX - boundsX)) {
  1137.                                 this._pendingSelectionBeginIndex++;
  1138.                             }
  1139.                         }
  1140.                         this._pendingSelectionEndIndex = this._pendingSelectionBeginIndex;
  1141.                     }
  1142.                 } else {
  1143.                     this._pendingSelectionBeginIndex = this._pendingSelectionEndIndex = -1;
  1144.                 }
  1145.                 this.stageText.visible = true;
  1146.                 this.stageText.assignFocus();
  1147.             } else {
  1148.                 this._isWaitingToSetFocus = true;
  1149.             }
  1150.         }
  1151.  
  1152.         /**
  1153.          * @inheritDoc
  1154.          */
  1155.         public function clearFocus(): void {
  1156.             if (!this._stageTextHasFocus) {
  1157.                 return;
  1158.             }
  1159.             //setting the focus to Starling.current.nativeStage doesn't work
  1160.             //here, so we need to use null. on Android, if we give focus to the
  1161.             //nativeStage, focus will be removed from the StageText, but the
  1162.             //soft keyboard will incorrectly remain open.
  1163.             Starling.current.nativeStage.focus = null;
  1164.         }
  1165.  
  1166.         /**
  1167.          * @inheritDoc
  1168.          */
  1169.         public function selectRange(beginIndex: int, endIndex: int): void {
  1170.             if (this._stageTextIsComplete && this.stageText) {
  1171.                 this._pendingSelectionBeginIndex = -1;
  1172.                 this._pendingSelectionEndIndex = -1;
  1173.                 this.stageText.selectRange(beginIndex, endIndex);
  1174.             } else {
  1175.                 this._pendingSelectionBeginIndex = beginIndex;
  1176.                 this._pendingSelectionEndIndex = endIndex;
  1177.             }
  1178.         }
  1179.  
  1180.         /**
  1181.          * @inheritDoc
  1182.          */
  1183.         public function measureText(result: Point = null): Point {
  1184.             if (!result) {
  1185.                 result = new Point();
  1186.             }
  1187.  
  1188.             var needsWidth: Boolean = this.explicitWidth !== this.explicitWidth; //isNaN
  1189.             var needsHeight: Boolean = this.explicitHeight !== this.explicitHeight; //isNaN
  1190.             if (!needsWidth && !needsHeight) {
  1191.                 result.x = this.explicitWidth;
  1192.                 result.y = this.explicitHeight;
  1193.                 return result;
  1194.             }
  1195.  
  1196.             //if a parent component validates before we're added to the stage,
  1197.             //measureText() may be called before initialization, so we need to
  1198.             //force it.
  1199.             if (!this._isInitialized) {
  1200.                 this.initializeInternal();
  1201.             }
  1202.  
  1203.             var stylesInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  1204.             var dataInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  1205.  
  1206.             if (stylesInvalid || dataInvalid) {
  1207.                 this.refreshMeasureProperties();
  1208.             }
  1209.  
  1210.             result = this.measure(result);
  1211.  
  1212.             return result;
  1213.         }
  1214.  
  1215.         /**
  1216.          * @private
  1217.          */
  1218.         override protected function initialize(): void {
  1219.             if (this._measureTextField && !this._measureTextField.parent) {
  1220.                 Starling.current.nativeStage.addChild(this._measureTextField);
  1221.             } else if (!this._measureTextField) {
  1222.                 this._measureTextField = new TextField();
  1223.                 this._measureTextField.visible = false;
  1224.                 this._measureTextField.mouseEnabled = this._measureTextField.mouseWheelEnabled = false;
  1225.                 this._measureTextField.autoSize = TextFieldAutoSize.LEFT;
  1226.                 this._measureTextField.multiline = false;
  1227.                 this._measureTextField.wordWrap = false;
  1228.                 this._measureTextField.embedFonts = false;
  1229.                 this._measureTextField.defaultTextFormat = new TextFormat(null, 11, 0x000000, false, false, false);
  1230.                 Starling.current.nativeStage.addChild(this._measureTextField);
  1231.             }
  1232.  
  1233.             this.createStageText();
  1234.         }
  1235.  
  1236.         /**
  1237.          * @private
  1238.          */
  1239.         override protected function draw(): void {
  1240.             var sizeInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE);
  1241.  
  1242.             this.commit();
  1243.  
  1244.             sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid;
  1245.  
  1246.             this.layout(sizeInvalid);
  1247.         }
  1248.  
  1249.         /**
  1250.          * @private
  1251.          */
  1252.         protected function commit(): void {
  1253.             var stateInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_STATE);
  1254.             var stylesInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  1255.             var dataInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  1256.  
  1257.             if (stylesInvalid || dataInvalid) {
  1258.                 this.refreshMeasureProperties();
  1259.             }
  1260.  
  1261.             var oldIgnoreStageTextChanges: Boolean = this._ignoreStageTextChanges;
  1262.             this._ignoreStageTextChanges = true;
  1263.             if (stateInvalid || stylesInvalid) {
  1264.                 this.refreshStageTextProperties();
  1265.             }
  1266.  
  1267.             if (dataInvalid) {
  1268.                 if (this.stageText.text != this._text) {
  1269.                     if (this._pendingSelectionBeginIndex < 0) {
  1270.                         this._pendingSelectionBeginIndex = this.stageText.selectionActiveIndex;
  1271.                         this._pendingSelectionEndIndex = this.stageText.selectionAnchorIndex;
  1272.                     }
  1273.                     this.stageText.text = this._text;
  1274.                 }
  1275.             }
  1276.             this._ignoreStageTextChanges = oldIgnoreStageTextChanges;
  1277.  
  1278.             if (stylesInvalid || stateInvalid) {
  1279.                 this.stageText.editable = this._isEditable && this._isEnabled;
  1280.             }
  1281.         }
  1282.  
  1283.         /**
  1284.          * @private
  1285.          */
  1286.         protected function measure(result: Point = null): Point {
  1287.             if (!result) {
  1288.                 result = new Point();
  1289.             }
  1290.  
  1291.             var needsWidth: Boolean = this.explicitWidth !== this.explicitWidth; //isNaN
  1292.             var needsHeight: Boolean = this.explicitHeight !== this.explicitHeight; //isNaN
  1293.  
  1294.             this._measureTextField.autoSize = TextFieldAutoSize.LEFT;
  1295.  
  1296.             var newWidth: Number = this.explicitWidth;
  1297.             if (needsWidth) {
  1298.                 newWidth = this._measureTextField.textWidth;
  1299.                 if (newWidth < this._minWidth) {
  1300.                     newWidth = this._minWidth;
  1301.                 } else if (newWidth > this._maxWidth) {
  1302.                     newWidth = this._maxWidth;
  1303.                 }
  1304.             }
  1305.  
  1306.             //the +4 is accounting for the TextField gutter
  1307.             this._measureTextField.width = newWidth + 4;
  1308.             var newHeight: Number = this.explicitHeight;
  1309.             if (needsHeight) {
  1310.                 //since we're measuring with TextField, but rendering with
  1311.                 //StageText, we're using height instead of textHeight here to be
  1312.                 //sure that the measured size is on the larger side, in case the
  1313.                 //rendered size is actually bigger than textHeight
  1314.                 //if only StageText had an API for text measurement, we wouldn't
  1315.                 //be in this mess...
  1316.                 newHeight = this._measureTextField.height;
  1317.                 if (newHeight < this._minHeight) {
  1318.                     newHeight = this._minHeight;
  1319.                 } else if (newHeight > this._maxHeight) {
  1320.                     newHeight = this._maxHeight;
  1321.                 }
  1322.             }
  1323.  
  1324.             this._measureTextField.autoSize = TextFieldAutoSize.NONE;
  1325.  
  1326.             //put the width and height back just in case we measured without
  1327.             //a full validation
  1328.             //the +4 is accounting for the TextField gutter
  1329.             this._measureTextField.width = this.actualWidth + 4;
  1330.             this._measureTextField.height = this.actualHeight;
  1331.  
  1332.             result.x = newWidth;
  1333.             result.y = newHeight;
  1334.  
  1335.             return result;
  1336.         }
  1337.  
  1338.         /**
  1339.          * @private
  1340.          */
  1341.         protected function layout(sizeInvalid: Boolean): void {
  1342.             var stateInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_STATE);
  1343.             var stylesInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES);
  1344.             var dataInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_DATA);
  1345.             var skinInvalid: Boolean = this.isInvalid(INVALIDATION_FLAG_SKIN);
  1346.  
  1347.             if (sizeInvalid || stylesInvalid || skinInvalid || stateInvalid) {
  1348.                 this.refreshViewPortAndFontSize();
  1349.                 this.refreshMeasureTextFieldDimensions()
  1350.                 var viewPort: Rectangle = this.stageText.viewPort;
  1351.                 var textureRoot: ConcreteTexture = this.textSnapshot ? this.textSnapshot.texture.root : null;
  1352.                 this._needsNewTexture = this._needsNewTexture || !this.textSnapshot ||
  1353.                     textureRoot.scale != Starling.contentScaleFactor ||
  1354.                     viewPort.width != textureRoot.width || viewPort.height != textureRoot.height;
  1355.             }
  1356.  
  1357.             if (!this._stageTextHasFocus && (stateInvalid || stylesInvalid || dataInvalid || sizeInvalid || this._needsNewTexture)) {
  1358.                 var hasText: Boolean = this._text.length > 0;
  1359.                 if (hasText) {
  1360.                     this.refreshSnapshot();
  1361.                 }
  1362.                 if (this.textSnapshot) {
  1363.                     this.textSnapshot.visible = !this._stageTextHasFocus;
  1364.                     this.textSnapshot.alpha = hasText ? 1 : 0;
  1365.                 }
  1366.                 this.stageText.visible = false;
  1367.             }
  1368.  
  1369.             this.doPendingActions();
  1370.         }
  1371.  
  1372.         /**
  1373.          * If the component's dimensions have not been set explicitly, it will
  1374.          * measure its content and determine an ideal size for itself. If the
  1375.          * <code>explicitWidth</code> or <code>explicitHeight</code> member
  1376.          * variables are set, those value will be used without additional
  1377.          * measurement. If one is set, but not the other, the dimension with the
  1378.          * explicit value will not be measured, but the other non-explicit
  1379.          * dimension will still need measurement.
  1380.          *
  1381.          * <p>Calls <code>setSizeInternal()</code> to set up the
  1382.          * <code>actualWidth</code> and <code>actualHeight</code> member
  1383.          * variables used for layout.</p>
  1384.          *
  1385.          * <p>Meant for internal use, and subclasses may override this function
  1386.          * with a custom implementation.</p>
  1387.          */
  1388.         protected function autoSizeIfNeeded(): Boolean {
  1389.             var needsWidth: Boolean = this.explicitWidth !== this.explicitWidth; //isNaN
  1390.             var needsHeight: Boolean = this.explicitHeight !== this.explicitHeight; //isNaN
  1391.             if (!needsWidth && !needsHeight) {
  1392.                 return false;
  1393.             }
  1394.  
  1395.             this.measure(HELPER_POINT);
  1396.             return this.setSizeInternal(HELPER_POINT.x, HELPER_POINT.y, false);
  1397.         }
  1398.  
  1399.         /**
  1400.          * @private
  1401.          */
  1402.         protected function refreshMeasureProperties(): void {
  1403.             var nativeScaleFactor: Number = 1;
  1404.             if (Starling.current.supportHighResolutions) {
  1405.                 nativeScaleFactor = Starling.current.nativeStage.contentsScaleFactor;
  1406.             }
  1407.  
  1408.             this._measureTextField.displayAsPassword = this._displayAsPassword;
  1409.             this._measureTextField.maxChars = this._maxChars;
  1410.             this._measureTextField.restrict = this._restrict;
  1411.             this._measureTextField.multiline = this._measureTextField.wordWrap = this._multiline;
  1412.  
  1413.             var format: TextFormat = this._measureTextField.defaultTextFormat;
  1414.             format.color = this._color;
  1415.             format.font = this._fontFamily;
  1416.             format.italic = this._fontPosture == FontPosture.ITALIC;
  1417.             format.size = this._fontSize * nativeScaleFactor;
  1418.             format.bold = this._fontWeight == FontWeight.BOLD;
  1419.             var alignValue: String = this._textAlign;
  1420.             if (alignValue == TextFormatAlign.START) {
  1421.                 alignValue = TextFormatAlign.LEFT;
  1422.             } else if (alignValue == TextFormatAlign.END) {
  1423.                 alignValue = TextFormatAlign.RIGHT;
  1424.             }
  1425.             format.align = alignValue;
  1426.             this._measureTextField.defaultTextFormat = format;
  1427.             this._measureTextField.setTextFormat(format);
  1428.             if (this._text.length == 0) {
  1429.                 this._measureTextField.text = " ";
  1430.             } else {
  1431.                 this._measureTextField.text = this._text;
  1432.             }
  1433.         }
  1434.  
  1435.         /**
  1436.          * @private
  1437.          */
  1438.         protected function refreshStageTextProperties(): void {
  1439.             if (this.stageText.multiline != this._multiline) {
  1440.                 if (this.stageText) {
  1441.                     this.disposeStageText();
  1442.                 }
  1443.                 this.createStageText();
  1444.             }
  1445.  
  1446.             this.stageText.autoCapitalize = this._autoCapitalize;
  1447.             this.stageText.autoCorrect = this._autoCorrect;
  1448.             if (this._isEnabled) {
  1449.                 this.stageText.color = this._color;
  1450.             } else {
  1451.                 this.stageText.color = this._disabledColor;
  1452.             }
  1453.             this.stageText.displayAsPassword = this._displayAsPassword;
  1454.             this.stageText.fontFamily = this._fontFamily;
  1455.             this.stageText.fontPosture = this._fontPosture;
  1456.             this.stageText.fontWeight = this._fontWeight;
  1457.             this.stageText.locale = this._locale;
  1458.             this.stageText.maxChars = this._maxChars;
  1459.             this.stageText.restrict = this._restrict;
  1460.             this.stageText.returnKeyLabel = this._returnKeyLabel;
  1461.             this.stageText.softKeyboardType = this._softKeyboardType;
  1462.             this.stageText.textAlign = this._textAlign;
  1463.         }
  1464.  
  1465.         /**
  1466.          * @private
  1467.          */
  1468.         protected function doPendingActions(): void {
  1469.             if (this._isWaitingToSetFocus) {
  1470.                 this._isWaitingToSetFocus = false;
  1471.                 this.setFocus();
  1472.             }
  1473.             if (this._pendingSelectionBeginIndex >= 0) {
  1474.                 var startIndex: int = this._pendingSelectionBeginIndex;
  1475.                 var endIndex: int = (this._pendingSelectionEndIndex < 0) ? this._pendingSelectionBeginIndex : this._pendingSelectionEndIndex;
  1476.                 this._pendingSelectionBeginIndex = -1;
  1477.                 this._pendingSelectionEndIndex = -1;
  1478.                 if (this.stageText.selectionAnchorIndex != startIndex || this.stageText.selectionActiveIndex != endIndex) {
  1479.                     //if the same range is already selected, don't try to do it
  1480.                     //again because on iOS, if the StageText is multiline, this
  1481.                     //will cause the clipboard menu to appear when it shouldn't.
  1482.                     this.selectRange(startIndex, endIndex);
  1483.                 }
  1484.             }
  1485.         }
  1486.  
  1487.         /**
  1488.          * @private
  1489.          */
  1490.         protected function texture_onRestore(): void {
  1491.             if (this.textSnapshot.texture.scale != Starling.contentScaleFactor) {
  1492.                 //if we've changed between scale factors, we need to recreate
  1493.                 //the texture to match the new scale factor.
  1494.                 this.invalidate(INVALIDATION_FLAG_SIZE);
  1495.             } else {
  1496.                 this.refreshSnapshot();
  1497.                 if (this.textSnapshot) {
  1498.                     this.textSnapshot.visible = !this._stageTextHasFocus;
  1499.                     this.textSnapshot.alpha = this._text.length > 0 ? 1 : 0;
  1500.                 }
  1501.                 if (!this._stageTextHasFocus) {
  1502.                     this.stageText.visible = false;
  1503.                 }
  1504.             }
  1505.         }
  1506.  
  1507.         /**
  1508.          * @private
  1509.          */
  1510.         protected function refreshSnapshot(): void {
  1511.             //StageText's stage property cannot be null when we call
  1512.             //drawViewPortToBitmapData()
  1513.             if (this.stage && !this.stageText.stage) {
  1514.                 this.stageText.stage = Starling.current.nativeStage;
  1515.             }
  1516.             if (!this.stageText.stage) {
  1517.                 //we need to keep a flag active so that the snapshot will be
  1518.                 //refreshed after the text editor is added to the stage
  1519.                 this.invalidate(INVALIDATION_FLAG_DATA);
  1520.                 return;
  1521.             }
  1522.             var viewPort: Rectangle = this.stageText.viewPort;
  1523.             if (viewPort.width == 0 || viewPort.height == 0) {
  1524.                 return;
  1525.             }
  1526.             var nativeScaleFactor: Number = 1;
  1527.             if (Starling.current.supportHighResolutions) {
  1528.                 nativeScaleFactor = Starling.current.nativeStage.contentsScaleFactor;
  1529.             }
  1530.             //StageText sucks because it requires that the BitmapData's width
  1531.             //and height exactly match its view port width and height.
  1532.             //(may be doubled on Retina Mac)
  1533.             try {
  1534.                 var bitmapData: BitmapData = new BitmapData(viewPort.width * nativeScaleFactor, viewPort.height * nativeScaleFactor, true, 0x00ff00ff);
  1535.                 this.stageText.drawViewPortToBitmapData(bitmapData);
  1536.             } catch (error: Error) {
  1537.                 //drawing stage text to the bitmap data at double size may fail
  1538.                 //on runtime versions less than 15, so fall back to using a
  1539.                 //snapshot that is half size. it's not ideal, but better than
  1540.                 //nothing.
  1541.                 bitmapData.dispose();
  1542.                 bitmapData = new BitmapData(viewPort.width, viewPort.height, true, 0x00ff00ff);
  1543.                 this.stageText.drawViewPortToBitmapData(bitmapData);
  1544.             }
  1545.  
  1546.             var newTexture: Texture;
  1547.             if (!this.textSnapshot || this._needsNewTexture) {
  1548.                 var scaleFactor: Number = Starling.contentScaleFactor;
  1549.                 //skip Texture.fromBitmapData() because we don't want
  1550.                 //it to create an onRestore function that will be
  1551.                 //immediately discarded for garbage collection.
  1552.                 newTexture = Texture.empty(bitmapData.width / scaleFactor, bitmapData.height / scaleFactor,
  1553.                     true, false, false, scaleFactor);
  1554.                 newTexture.root.uploadBitmapData(bitmapData);
  1555.                 newTexture.root.onRestore = texture_onRestore;
  1556.             }
  1557.             if (!this.textSnapshot) {
  1558.                 this.textSnapshot = new Image(newTexture);
  1559.                 this.addChild(this.textSnapshot);
  1560.             } else {
  1561.                 if (this._needsNewTexture) {
  1562.                     this.textSnapshot.texture.dispose();
  1563.                     this.textSnapshot.texture = newTexture;
  1564.                     this.textSnapshot.readjustSize();
  1565.                 } else {
  1566.                     //this is faster, if we haven't resized the bitmapdata
  1567.                     var existingTexture: Texture = this.textSnapshot.texture;
  1568.                     existingTexture.root.uploadBitmapData(bitmapData);
  1569.                 }
  1570.             }
  1571.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1572.             var globalScaleX: Number = matrixToScaleX(HELPER_MATRIX);
  1573.             var globalScaleY: Number = matrixToScaleY(HELPER_MATRIX);
  1574.             if (this._updateSnapshotOnScaleChange) {
  1575.                 this.textSnapshot.scaleX = 1 / globalScaleX;
  1576.                 this.textSnapshot.scaleY = 1 / globalScaleY;
  1577.                 this._lastGlobalScaleX = globalScaleX;
  1578.                 this._lastGlobalScaleY = globalScaleY;
  1579.             } else {
  1580.                 this.textSnapshot.scaleX = 1;
  1581.                 this.textSnapshot.scaleY = 1;
  1582.             }
  1583.             if (nativeScaleFactor > 1 && bitmapData.width == viewPort.width) {
  1584.                 //when we fall back to using a snapshot that is half size on
  1585.                 //older runtimes, we need to scale it up.
  1586.                 this.textSnapshot.scaleX *= nativeScaleFactor;
  1587.                 this.textSnapshot.scaleY *= nativeScaleFactor;
  1588.             }
  1589.             bitmapData.dispose();
  1590.             this._needsNewTexture = false;
  1591.         }
  1592.  
  1593.         /**
  1594.          * @private
  1595.          */
  1596.         protected function refreshViewPortAndFontSize(): void {
  1597.             HELPER_POINT.x = HELPER_POINT.y = 0;
  1598.             var desktopGutterPositionOffset: Number = 0;
  1599.             var desktopGutterDimensionsOffset: Number = 0;
  1600.             if (this._stageTextIsTextField) {
  1601.                 desktopGutterPositionOffset = 2;
  1602.                 desktopGutterDimensionsOffset = 4;
  1603.             }
  1604.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1605.             if (this._stageTextHasFocus || this._updateSnapshotOnScaleChange) {
  1606.                 var globalScaleX: Number = matrixToScaleX(HELPER_MATRIX);
  1607.                 var globalScaleY: Number = matrixToScaleY(HELPER_MATRIX);
  1608.                 var smallerGlobalScale: Number = globalScaleX;
  1609.                 if (globalScaleY < smallerGlobalScale) {
  1610.                     smallerGlobalScale = globalScaleY;
  1611.                 }
  1612.             } else {
  1613.                 globalScaleX = 1;
  1614.                 globalScaleY = 1;
  1615.                 smallerGlobalScale = 1;
  1616.             }
  1617.             if (this.is3D) {
  1618.                 HELPER_MATRIX3D = this.getTransformationMatrix3D(this.stage, HELPER_MATRIX3D);
  1619.                 HELPER_POINT3D = MatrixUtil.transformCoords3D(HELPER_MATRIX3D, -desktopGutterPositionOffset, -desktopGutterPositionOffset, 0, HELPER_POINT3D);
  1620.                 HELPER_POINT.setTo(HELPER_POINT3D.x, HELPER_POINT3D.y);
  1621.             } else {
  1622.                 MatrixUtil.transformCoords(HELPER_MATRIX, -desktopGutterPositionOffset, -desktopGutterPositionOffset, HELPER_POINT);
  1623.             }
  1624.             var nativeScaleFactor: Number = 1;
  1625.             if (Starling.current.supportHighResolutions) {
  1626.                 nativeScaleFactor = Starling.current.nativeStage.contentsScaleFactor;
  1627.             }
  1628.             var scaleFactor: Number = Starling.contentScaleFactor / nativeScaleFactor;
  1629.             var starlingViewPort: Rectangle = Starling.current.viewPort;
  1630.             var stageTextViewPort: Rectangle = this.stageText.viewPort;
  1631.             if (!stageTextViewPort) {
  1632.                 stageTextViewPort = new Rectangle();
  1633.             }
  1634.             var heightScaleFactor: Number = starlingViewPort.height/stage.stageHeight;
  1635.             stageTextViewPort.x = Math.round(starlingViewPort.x + HELPER_POINT.x * scaleFactor);
  1636.             stageTextViewPort.y = Math.round(starlingViewPort.y + HELPER_POINT.y * heightScaleFactor);
  1637.             var viewPortWidth: Number = Math.round((this.actualWidth + desktopGutterDimensionsOffset) * scaleFactor * globalScaleX);
  1638.             if (viewPortWidth < 1 ||
  1639.                 viewPortWidth !== viewPortWidth) //isNaN
  1640.             {
  1641.                 viewPortWidth = 1;
  1642.             }
  1643.             var viewPortHeight: Number = Math.round((this.actualHeight + desktopGutterDimensionsOffset) * heightScaleFactor * globalScaleY);
  1644.             if (viewPortHeight < 1 ||
  1645.                 viewPortHeight !== viewPortHeight) //isNaN
  1646.             {
  1647.                 viewPortHeight = 1;
  1648.             }
  1649.             stageTextViewPort.width = viewPortWidth;
  1650.             stageTextViewPort.height = viewPortHeight;
  1651.             this.stageText.viewPort = stageTextViewPort;
  1652.  
  1653.             //for some reason, we don't need to account for the native scale factor here
  1654.             scaleFactor = Starling.contentScaleFactor;
  1655.             //StageText's fontSize property is an int, so we need to
  1656.             //specifically avoid using Number here.
  1657.             var newFontSize: int = this._fontSize * scaleFactor * smallerGlobalScale;
  1658.             if (this.stageText.fontSize != newFontSize) {
  1659.                 //we need to check if this value has changed because on iOS
  1660.                 //if displayAsPassword is set to true, the new character
  1661.                 //will not be shown if the font size changes. instead, it
  1662.                 //immediately changes to a bullet. (Github issue #881)
  1663.                 this.stageText.fontSize = newFontSize;
  1664.             }
  1665.  
  1666.         }
  1667.  
  1668.         /**
  1669.          * @private
  1670.          */
  1671.         protected function refreshMeasureTextFieldDimensions(): void {
  1672.             //the +4 is accounting for the TextField gutter
  1673.             this._measureTextField.width = this.actualWidth + 4;
  1674.             this._measureTextField.height = this.actualHeight;
  1675.         }
  1676.  
  1677.         /**
  1678.          * @private
  1679.          */
  1680.         protected function positionSnapshot(): void {
  1681.             this.getTransformationMatrix(this.stage, HELPER_MATRIX);
  1682.             var desktopGutterPositionOffset: Number = 0;
  1683.             if (this._stageTextIsTextField) {
  1684.                 desktopGutterPositionOffset = 2;
  1685.             }
  1686.             this.textSnapshot.x = Math.round(HELPER_MATRIX.tx) - HELPER_MATRIX.tx - desktopGutterPositionOffset;
  1687.             this.textSnapshot.y = Math.round(HELPER_MATRIX.ty) - HELPER_MATRIX.ty - desktopGutterPositionOffset;
  1688.         }
  1689.  
  1690.         /**
  1691.          * @private
  1692.          */
  1693.         protected function disposeStageText(): void {
  1694.             if (!this.stageText) {
  1695.                 return;
  1696.             }
  1697.             this.stageText.removeEventListener(flash.events.Event.CHANGE, stageText_changeHandler);
  1698.             this.stageText.removeEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
  1699.             this.stageText.removeEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
  1700.             this.stageText.removeEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
  1701.             this.stageText.removeEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
  1702.             this.stageText.removeEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1703.             this.stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
  1704.             this.stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
  1705.             this.stageText.stage = null;
  1706.             this.stageText.dispose();
  1707.             this.stageText = null;
  1708.         }
  1709.  
  1710.         /**
  1711.          * Creates and adds the <code>stageText</code> instance.
  1712.          *
  1713.          * <p>Meant for internal use, and subclasses may override this function
  1714.          * with a custom implementation.</p>
  1715.          */
  1716.         protected function createStageText(): void {
  1717.             this._stageTextIsComplete = false;
  1718.             var StageTextType: Class;
  1719.             var initOptions: Object;
  1720.             try {
  1721.                 StageTextType = Class(getDefinitionByName("flash.text.StageText"));
  1722.                 var StageTextInitOptionsType: Class = Class(getDefinitionByName("flash.text.StageTextInitOptions"));
  1723.                 initOptions = new StageTextInitOptionsType(this._multiline);
  1724.             } catch (error: Error) {
  1725.                 StageTextType = StageTextField;
  1726.                 initOptions = {
  1727.                     multiline: this._multiline
  1728.                 };
  1729.             }
  1730.             this.stageText = new StageTextType(initOptions);
  1731.             this.stageText.visible = false;
  1732.             this.stageText.addEventListener(flash.events.Event.CHANGE, stageText_changeHandler);
  1733.             this.stageText.addEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
  1734.             this.stageText.addEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
  1735.             this.stageText.addEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
  1736.             this.stageText.addEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
  1737.             this.stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
  1738.             this.stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
  1739.             this.stageText.addEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1740.             this.invalidate();
  1741.         }
  1742.  
  1743.         /**
  1744.          * @private
  1745.          */
  1746.         protected function dispatchKeyFocusChangeEvent(event: KeyboardEvent): void {
  1747.             var starling: Starling = stageToStarling(this.stage);
  1748.             var focusEvent: FocusEvent = new FocusEvent(FocusEvent.KEY_FOCUS_CHANGE, true, false, null, event.shiftKey, event.keyCode);
  1749.             starling.nativeStage.dispatchEvent(focusEvent);
  1750.         }
  1751.  
  1752.         /**
  1753.          * @private
  1754.          */
  1755.         protected function textEditor_removedFromStageHandler(event: starling.events.Event): void {
  1756.             //remove this from the stage, if needed
  1757.             //it will be added back next time we receive focus
  1758.             this.stageText.stage = null;
  1759.         }
  1760.  
  1761.         /**
  1762.          * @private
  1763.          */
  1764.         protected function stageText_changeHandler(event: flash.events.Event): void {
  1765.             if (this._ignoreStageTextChanges) {
  1766.                 return;
  1767.             }
  1768.             this.text = this.stageText.text;
  1769.         }
  1770.  
  1771.         /**
  1772.          * @private
  1773.          */
  1774.         protected function stageText_completeHandler(event: flash.events.Event): void {
  1775.             this.stageText.removeEventListener(flash.events.Event.COMPLETE, stageText_completeHandler);
  1776.             this.invalidate();
  1777.  
  1778.             this._stageTextIsComplete = true;
  1779.         }
  1780.  
  1781.         /**
  1782.          * @private
  1783.          */
  1784.         protected function stageText_focusInHandler(event: FocusEvent): void {
  1785.             this._stageTextHasFocus = true;
  1786.             this.addEventListener(starling.events.Event.ENTER_FRAME, hasFocus_enterFrameHandler);
  1787.             if (this.textSnapshot) {
  1788.                 this.textSnapshot.visible = false;
  1789.             }
  1790.             this.invalidate(INVALIDATION_FLAG_SKIN);
  1791.             this.dispatchEventWith(FeathersEventType.FOCUS_IN);
  1792.         }
  1793.  
  1794.         /**
  1795.          * @private
  1796.          */
  1797.         protected function stageText_focusOutHandler(event: FocusEvent): void {
  1798.             this._stageTextHasFocus = false;
  1799.             //since StageText doesn't expose its scroll position, we need to
  1800.             //set the selection back to the beginning to scroll there. it's a
  1801.             //hack, but so is everything about StageText.
  1802.             //in other news, why won't 0,0 work here?
  1803.             this.stageText.selectRange(1, 1);
  1804.  
  1805.             this.invalidate(INVALIDATION_FLAG_DATA);
  1806.             this.invalidate(INVALIDATION_FLAG_SKIN);
  1807.             this.dispatchEventWith(FeathersEventType.FOCUS_OUT);
  1808.         }
  1809.  
  1810.         /**
  1811.          * @private
  1812.          */
  1813.         protected function hasFocus_enterFrameHandler(event: starling.events.Event): void {
  1814.             if (this._stageTextHasFocus) {
  1815.                 var target: DisplayObject = this;
  1816.                 do {
  1817.                     if (!target.hasVisibleArea) {
  1818.                         this.stageText.stage.focus = null;
  1819.                         break;
  1820.                     }
  1821.                     target = target.parent;
  1822.                 }
  1823.                 while (target)
  1824.             } else {
  1825.                 this.removeEventListener(starling.events.Event.ENTER_FRAME, hasFocus_enterFrameHandler);
  1826.             }
  1827.         }
  1828.  
  1829.         /**
  1830.          * @private
  1831.          */
  1832.         protected function stageText_keyDownHandler(event: KeyboardEvent): void {
  1833.             if (!this._multiline && (event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT)) {
  1834.                 event.preventDefault();
  1835.                 this.dispatchEventWith(FeathersEventType.ENTER);
  1836.             } else if (event.keyCode == Keyboard.BACK) {
  1837.                 //even a listener on the stage won't detect the back key press that
  1838.                 //will close the application if the StageText has focus, so we
  1839.                 //always need to prevent it here
  1840.                 event.preventDefault();
  1841.                 Starling.current.nativeStage.focus = Starling.current.nativeStage;
  1842.             }
  1843.             if (event.keyCode === Keyboard.TAB && FocusManager.isEnabledForStage(this.stage)) {
  1844.                 event.preventDefault();
  1845.                 this.dispatchKeyFocusChangeEvent(event);
  1846.             }
  1847.         }
  1848.  
  1849.         /**
  1850.          * @private
  1851.          */
  1852.         protected function stageText_keyUpHandler(event: KeyboardEvent): void {
  1853.             if (!this._multiline && (event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT)) {
  1854.                 event.preventDefault();
  1855.             }
  1856.             if (event.keyCode === Keyboard.TAB && FocusManager.isEnabledForStage(this.stage)) {
  1857.                 event.preventDefault();
  1858.             }
  1859.         }
  1860.  
  1861.         /**
  1862.          * @private
  1863.          */
  1864.         protected function stageText_softKeyboardActivateHandler(event: SoftKeyboardEvent): void {
  1865.             this.dispatchEventWith(FeathersEventType.SOFT_KEYBOARD_ACTIVATE, true);
  1866.         }
  1867.  
  1868.         /**
  1869.          * @private
  1870.          */
  1871.         protected function stageText_softKeyboardDeactivateHandler(event: SoftKeyboardEvent): void {
  1872.             this.dispatchEventWith(FeathersEventType.SOFT_KEYBOARD_DEACTIVATE, true);
  1873.         }
  1874.     }
  1875. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement