You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ma...@apache.org on 2013/11/18 01:05:18 UTC
git commit: [flex-sdk] [refs/heads/develop] - Tentative FIX of
FLEX-33166 Mobile TextInput with native StageTextInput cannot be included in
scrollable forms - tested on iPad - could not run mustella mobile tests
Updated Branches:
refs/heads/develop ce735d9d7 -> 48169122d
Tentative FIX of FLEX-33166 Mobile TextInput with native StageTextInput cannot be included in scrollable forms
- tested on iPad
- could not run mustella mobile tests
Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/48169122
Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/48169122
Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/48169122
Branch: refs/heads/develop
Commit: 48169122d33bff0063a39a952e188715cdfd38a2
Parents: ce735d9
Author: mamsellem <ma...@systar.com>
Authored: Mon Nov 18 01:05:05 2013 +0100
Committer: mamsellem <ma...@systar.com>
Committed: Mon Nov 18 01:05:05 2013 +0100
----------------------------------------------------------------------
.../src/MobileComponentsClasses.as | 1 +
.../supportClasses/IStyleableEditableText.as | 36 +
.../supportClasses/ScrollableStageText.as | 2208 ++++++++++++++++++
.../supportClasses/StyleableStageText.as | 2 +-
frameworks/projects/mobiletheme/defaults.css | 4 +-
.../mobiletheme/src/MobileThemeClasses.as | 2 +
.../skins/mobile/ScrollingStageTextAreaSkin.as | 49 +
.../skins/mobile/ScrollingStageTextInputSkin.as | 49 +
.../mobile/supportClasses/StageTextSkinBase.as | 16 +-
9 files changed, 2361 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as b/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
index 7da878a..bde526a 100644
--- a/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
+++ b/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
@@ -33,6 +33,7 @@ internal class MobileComponentsClasses
*/
import spark.preloaders.SplashScreen; SplashScreen;
import spark.components.supportClasses.StyleableStageText; StyleableStageText;
+ import spark.components.supportClasses.ScrollableStageText; ScrollableStageText;
import spark.components.supportClasses.StyleableTextField; StyleableTextField;
import spark.components.ActionBarDefaultButtonAppearance; ActionBarDefaultButtonAppearance;
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/IStyleableEditableText.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/IStyleableEditableText.as b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/IStyleableEditableText.as
new file mode 100644
index 0000000..62c3ce2
--- /dev/null
+++ b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/IStyleableEditableText.as
@@ -0,0 +1,36 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.supportClasses
+{
+import mx.core.IUIComponent;
+
+import spark.core.IEditableText;
+
+/**
+ * IStyleableEditableText defines the methods and properties of classes that implement styleable wrappers around native input text.
+ */
+public interface IStyleableEditableText extends IEditableText, IUIComponent
+{
+ function set styleName(value:Object):void ;
+
+ function commitStyles():void;
+
+}
+}
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
new file mode 100644
index 0000000..28ed07a
--- /dev/null
+++ b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
@@ -0,0 +1,2208 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.supportClasses
+{
+import flash.display.Bitmap;
+import flash.display.BitmapData;
+import flash.display.DisplayObject;
+import flash.display.PixelSnapping;
+import flash.events.Event;
+import flash.events.FocusEvent;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.events.SoftKeyboardEvent;
+import flash.geom.Matrix;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.system.Capabilities;
+import flash.text.AutoCapitalize;
+import flash.text.ReturnKeyLabel;
+import flash.text.SoftKeyboardType;
+import flash.text.StageText;
+import flash.text.TextFormatAlign;
+import flash.text.TextLineMetrics;
+import flash.ui.Keyboard;
+
+import flashx.textLayout.formats.LineBreak;
+
+import mx.core.FlexGlobals;
+import mx.core.LayoutDirection;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+import mx.managers.FocusManager;
+import mx.managers.SystemManager;
+import mx.utils.MatrixUtil;
+
+import spark.components.Application;
+import spark.core.ISoftKeyboardHintClient;
+import spark.events.TextOperationEvent;
+
+use namespace mx_internal;
+
+//--------------------------------------
+// Excluded APIs
+//--------------------------------------
+
+[Exclude(name="alpha", kind="property")]
+[Exclude(name="horizontalScrollPosition", kind="property")]
+[Exclude(name="isTruncated", kind="property")]
+[Exclude(name="lineBreak", kind="property")]
+[Exclude(name="selectable", kind="property")]
+[Exclude(name="verticalScrollPosition", kind="property")]
+
+//--------------------------------------
+// Events
+//--------------------------------------
+
+/**
+ * Dispatched after a user editing operation is complete.
+ *
+ * @eventType flash.events.Event.CHANGE
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Event(name="change", type="flash.events.Event")]
+
+/**
+ * Dispatched if the StageText is not multiline and the user presses the enter
+ * key.
+ *
+ * @eventType mx.events.FlexEvent.ENTER
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Event(name="enter", type="mx.events.FlexEvent")]
+
+/**
+ * Dispatched after the native text control gains focus. This happens when a
+ * user highlights the text field with a pointing device, keyboard navigation,
+ * or a touch gesture.
+ *
+ * <p>Note: Since <code>flash.text.StageText</code> is not an
+ * <code>InteractiveObject</code>, the <code>Stage.focus</code> property may
+ * not be used to determine if a native text field has focus.</p>
+ *
+ * @eventType flash.events.FocusEvent.FOCUS_IN
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Event(name="focusIn", type="flash.events.FocusEvent")]
+
+/**
+ * Dispatched after the native text control loses focus. This happens when a
+ * user highlights an object other than the text field with a pointing device,
+ * keyboard navigation, or a touch gesture.
+ *
+ * <p>Note: Since <code>flash.text.StageText</code> is not an
+ * <code>InteractiveObject</code>, the <code>Stage.focus</code> property may
+ * not be used to determine if a native text field has focus.</p>
+ *
+ * @eventType flash.events.FocusEvent.FOCUS_OUT
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Event(name="focusOut", type="flash.events.FocusEvent")]
+
+/**
+ * Dispatched when a soft keyboard is displayed.
+ *
+ * @eventType flash.events.SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Event(name="softKeyboardActivate", type="flash.events.SoftKeyboardEvent")]
+
+/**
+ * Dispatched immediately before a soft keyboard is displayed. If canceled by
+ * calling <code>preventDefault</code>, the soft keyboard will not open.
+ *
+ * @eventType flash.events.SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Event(name="softKeyboardActivating", type="flash.events.SoftKeyboardEvent")]
+
+/**
+ * Dispatched when a soft keyboard is lowered or hidden.
+ *
+ * @eventType flash.events.SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Event(name="softKeyboardDeactivate", type="flash.events.SoftKeyboardEvent")]
+
+//--------------------------------------
+// Styles
+//--------------------------------------
+
+/**
+ * Color of text in the component, including the component label.
+ *
+ * @default 0x000000
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Style(name="color", type="uint", format="Color", inherit="yes")]
+
+/**
+ * Name of the font to use.
+ * Unlike in a full CSS implementation,
+ * comma-separated lists are not supported.
+ * You can use any font family name.
+ * If you specify a generic font name,
+ * it is converted to an appropriate device font.
+ *
+ * @default "_sans"
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Style(name="fontFamily", type="String", inherit="yes")]
+
+/**
+ * Height of the text, in pixels.
+ *
+ * @default 24
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Style(name="fontSize", type="Number", format="Length", inherit="yes")]
+
+/**
+ * Determines whether the text is italic font.
+ * Recognized values are <code>"normal"</code> and <code>"italic"</code>.
+ *
+ * @default "normal"
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Style(name="fontStyle", type="String", enumeration="normal,italic", inherit="yes")]
+
+/**
+ * Determines whether the text is boldface.
+ * Recognized values are <code>"normal"</code> and <code>"bold"</code>.
+ *
+ * @default "normal"
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Style(name="fontWeight", type="String", enumeration="normal,bold", inherit="yes")]
+
+/**
+ * @copy spark.components.supportClasses.SkinnableTextBase#style:locale
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Style(name="locale", type="String", inherit="yes")]
+
+/**
+ * Alignment of text within a container.
+ * Possible values are <code>"start"</code>, <code>"end"</code>, <code>"left"</code>,
+ * <code>"right"</code>, or <code>"center"</code>.
+ *
+ * @default "start"
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+[Style(name="textAlign", type="String", enumeration="start,end,left,right,center", inherit="yes")]
+
+
+/**
+ * The ScrollableStageText class is a text primitive for use in ActionScript
+ * skins which is used to present the user with a native text input field.
+ * It cannot be used in MXML markup, is not compatible with effects, and
+ * is not compatible with transformations such as rotation, scale, and skew.
+ *
+ * <p>StageText allows for better text entry and manipulation experiences on mobile devices
+ * using native text fields.
+ * The native fields provide correct visuals, text spacing and reflow, selection behavior, and
+ * text entry assistance.
+ * This class can also be used on desktop platforms where it behaves as a wrapper around TextField.
+ * </p>
+ *
+ * The padding around native text controls may be different than the padding around
+ * TextField controls.
+ *
+ * <p>Similiar to other native applications, when you tap outside of the native text field, the
+ * text field gives up focus and the soft keyboard goes away.
+ * This differs from when you tap outside of a TextField and the focus stays in the TextField and
+ * the soft keyboard remains visible.</p>
+ *
+ * <p><b>Limitation of StageText-based controls:</b>
+ * <ul>
+ * <li>Native text input fields cannot be clipped by other Flex content and are rendered in a
+ * layer above the Stage.
+ * Because of this limitation, ScrollableStageText maintains a proxy bitmap that is a pixel copy of the native text input .
+ * This proxy is always displayed in place of the native text input, except when edition takes place.
+ * For this reason, the input text might be partially obscured during text edition.
+ * Flex popups and drop-downs will also be obscured by any visible native text fields.</li>
+ *
+ * <li>The native controls do not support embedded fonts.</li>
+ *
+ * <li>Links and html markup are not supported.</li>
+ *
+ * <li><code>text</code> is always selectable.</li>
+ *
+ * <li>Fractional alpha values are not supported.</li>
+ *
+ * <li>Keyboard events are not dispatched for most keys.
+ * This means that the tab key will not dispatch keyDown or keyUp events so focus
+ * cannot be removed from a StageText-based control with the tab key.</li>
+ *
+ * <li>StageText is currently not capable of measuring text.</li>
+ *
+ * <li>At this time StageText does not support programmatic control of scroll position. </li>
+ *
+ * <li>However, ScrollableStageText can be used in text input skins that are part of a scrolling of form.</li>
+ * </ul>
+ * </p>
+ *
+ * @see flash.text.StageText
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.12
+ */
+public class ScrollableStageText extends UIComponent implements IStyleableEditableText, ISoftKeyboardHintClient
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Class variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected static const isAndroid:Boolean = Capabilities.version.indexOf("AND") == 0;
+ protected static const isDesktop:Boolean = Capabilities.os.indexOf("Windows") != -1 || Capabilities.os.indexOf("Mac OS") != -1;
+ /**
+ * Text measuring behavior needs to be slightly different on Android
+ * devices to account for its native text being slightly taller. Without
+ * this adjustment, single-line text on Android will be clipped or will
+ * scroll vertically.
+ */
+ mx_internal static var androidHeightMultiplier:Number = 1.15;
+
+ protected static var supportedStyles:String = "textAlign fontFamily fontWeight fontStyle fontSize color locale";
+ /**
+ * StageText does not support setting its style-like properties to null or
+ * undefined to restore their default values. So, the first time we create
+ * a StageText, store its default values here.
+ */
+ protected static var defaultStyles:Object;
+
+ /**
+ * when set to true, displays the proxy images with a purple background, to help debugging proxy vs stageText usage.
+ */
+ mx_internal static var debugProxyImage:Boolean = false;
+
+ /**
+ * Constructor.
+ *
+ * <p><code>multiline</code> determines what happens when you press the Enter key.
+ * If it is <code>true</code>, the Enter key starts a new line.
+ * If it is <code>false</code>, it causes a <code>FlexEvent.ENTER</code>
+ * event to be dispatched.</p>
+ *
+ * @param multiline Set to <code>true</code> to allow more than one line of text to be input.
+ *
+ * @default false
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function ScrollableStageText(multiline:Boolean = false)
+ {
+ super();
+
+ _multiline = multiline;
+ stageText = StageTextPool.current.acquireStageText(this);
+ stageText.visible = false;
+
+ if (!defaultStyles)
+ {
+ defaultStyles = {};
+
+ defaultStyles["textAlign"] = stageText.textAlign;
+ defaultStyles["fontFamily"] = stageText.fontFamily;
+ defaultStyles["fontWeight"] = stageText.fontWeight;
+ defaultStyles["fontStyle"] = stageText.fontPosture;
+ defaultStyles["fontSize"] = stageText.fontSize;
+ defaultStyles["color"] = stageText.color;
+ defaultStyles["locale"] = stageText.locale;
+ }
+
+ _displayAsPassword = stageText.displayAsPassword;
+ _maxChars = stageText.maxChars;
+ _restrict = stageText.restrict;
+
+ // Flex's default for autoCorrect is now true, so we need to turn on
+ // autoCorrect on the runtime side during construction.
+ stageText.autoCorrect = _autoCorrect;
+
+ addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true);
+ addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler, false, 0, true);
+
+}
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * To be displayed when out of focus
+ */
+ protected var proxy:DisplayObject = null;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * The rectangle that defines the StageText's bounds in this object's
+ * parent's coordinate space.
+ */
+ private var localViewPort:Rectangle;
+ /**
+ * Flag indicating the position or size of the StageText needs to change.
+ */
+ private var invalidateViewPortFlag:Boolean = false;
+ /**
+ * Along with the text, need to save the selection, when the StageText is
+ * removed from the stage, so that when the StageText is restored, the
+ * selection can be restored.
+ */
+ private var savedSelectionAnchorIndex:int = 0;
+ private var savedSelectionActiveIndex:int = 0;
+ private var showProxy:Boolean = true;
+
+ /* if showProxy = true; proxy is visible, and StageText is not visible
+ * */
+ private var isEditing:Boolean = false;
+
+ /* indicates whether editing is in place
+ * */
+ private var isMouseDown:Boolean = false;
+
+ private var invalidateProxyFlag:Boolean = false;
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+
+ /**
+ * The runtime StageText object that this field uses for text display and
+ * editing.
+ */
+ protected var stageText:StageText;
+
+ /**
+ * Flag indicating one or more styles have changed. If invalidateStyleFlag
+ * is false, commitStyles is a no-op, so it is safe to call commitStyles
+ * whenever this object is measured or drawn.
+ */
+ protected var invalidateStyleFlag:Boolean = true;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // height
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ override public function get height():Number
+ {
+ if (!localViewPort)
+ return 0;
+
+ return localViewPort.height;
+ }
+
+ /**
+ * @private
+ */
+ override public function set height(value:Number):void
+ {
+ super.height = value;
+
+ if (value == height)
+ return;
+
+ if (!localViewPort)
+ localViewPort = new Rectangle();
+
+ localViewPort.height = Math.max(0, value);
+
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+
+ //----------------------------------
+ // visible
+ //----------------------------------
+
+ /**
+ * Storage for the visible property.
+ */
+ private var _visible:Boolean = true;
+
+ /**
+ * @private
+ */
+ override public function get visible():Boolean
+ {
+ return _visible;
+ }
+
+ /**
+ * @private
+ */
+ override public function set visible(value:Boolean):void
+ {
+ super.visible = value;
+
+ if (value == _visible)
+ return;
+
+ _visible = value;
+ invalidateProperties();
+ }
+
+ //----------------------------------
+ // width
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ override public function get width():Number
+ {
+ if (!localViewPort)
+ return 0;
+
+ return localViewPort.width;
+ }
+
+ /**
+ * @private
+ */
+ override public function set width(value:Number):void
+ {
+ super.width = value;
+
+ if (value == width)
+ return;
+
+ if (!localViewPort)
+ localViewPort = new Rectangle();
+
+ localViewPort.width = Math.max(0, value);
+
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+
+ //----------------------------------
+ // x
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ override public function get x():Number
+ {
+ if (!localViewPort)
+ return 0;
+
+ return localViewPort.x;
+ }
+
+ /**
+ * @private
+ */
+ override public function set x(value:Number):void
+ {
+ super.x = value;
+
+ if (value == x)
+ return;
+
+ if (!localViewPort)
+ localViewPort = new Rectangle();
+
+ localViewPort.x = value;
+
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+
+ //----------------------------------
+ // y
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ override public function get y():Number
+ {
+ if (!localViewPort)
+ return 0;
+
+ return localViewPort.y;
+ }
+
+ /**
+ * @private
+ */
+ override public function set y(value:Number):void
+ {
+ super.y = value;
+
+ if (value == y)
+ return;
+
+ if (!localViewPort)
+ localViewPort = new Rectangle();
+
+ localViewPort.y = value;
+
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+
+ //----------------------------------
+ // baselinePosition
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ override public function get baselinePosition():Number
+ {
+ return measureTextLineHeight();
+ }
+
+ //----------------------------------
+ // densityScale
+ //----------------------------------
+
+ private var _densityScale:Number;
+
+ /**
+ * The scale factor necessary to account for differences in the design
+ * resolution of the application (applicationDPI) and the resolution of the
+ * device the application is running on.
+ */
+ protected function get densityScale():Number
+ {
+ if (isNaN(_densityScale))
+ {
+ var application:Application = FlexGlobals.topLevelApplication as Application;
+ var sm:SystemManager = application ? application.systemManager as SystemManager : null;
+ _densityScale = sm ? sm.densityScale : 1.0;
+ }
+
+ return _densityScale;
+ }
+
+ //----------------------------------
+ // displayAsPassword
+ //----------------------------------
+
+ /**
+ * Storage for the displayAsPassword property.
+ * This is needed because clients may ask for this after the StageText has
+ * been disposed.
+ */
+ protected var _displayAsPassword:Boolean;
+
+ /**
+ * Specifies whether the text field is a password text field.
+ *
+ * @default false
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get displayAsPassword():Boolean
+ {
+ return _displayAsPassword;
+ }
+
+ public function set displayAsPassword(value:Boolean):void
+ {
+ if (stageText != null)
+ stageText.displayAsPassword = value;
+
+ _displayAsPassword = value;
+ }
+
+ //----------------------------------
+ // editable
+ //----------------------------------
+
+ /**
+ * Storage for the editable property.
+ */
+ protected var _editable:Boolean = true;
+
+ /**
+ * Flag that indicates whether the text in the field is editable.
+ *
+ * @default true
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get editable():Boolean
+ {
+ return _editable;
+ }
+
+ public function set editable(value:Boolean):void
+ {
+ _editable = value;
+ invalidateProperties();
+ }
+
+ //----------------------------------
+ // horizontalScrollPosition
+ //----------------------------------
+
+ /**
+ * @private
+ * The horizontal scroll position of the text. StageText doesn't support
+ * this currently. Even so, we need to have this to satisfy requirements
+ * of the IEditableText interface.
+ */
+ public function get horizontalScrollPosition():Number
+ {
+ // TODO: StageText doesn't support this yet
+ return 0;
+ }
+
+ public function set horizontalScrollPosition(value:Number):void
+ {
+ // TODO: StageText doesn't support this yet
+ }
+
+ //----------------------------------
+ // isTruncated
+ //----------------------------------
+
+ /**
+ * @private
+ * A flag that indicates whether the text has been truncated. StageText
+ * doesn't support this currently. Even so, we need to have this to satisfy
+ * requirements of the IEditableText interface.
+ */
+ public function get isTruncated():Boolean
+ {
+ // TODO: StageText doesn't support measuring text yet
+ return false;
+ }
+
+ //----------------------------------
+ // lineBreak
+ //----------------------------------
+
+ /**
+ * @private
+ * Controls word wrapping within the text. This property corresponds
+ * to the lineBreak style. StageText doesn't support this currently. Even
+ * so, we need to have this to satisfy requirements of the IEditableText
+ * interface.
+ */
+ public function get lineBreak():String
+ {
+ return LineBreak.TO_FIT;
+ }
+
+ public function set lineBreak(value:String):void
+ {
+ // StageText only supports LineBreak.TO_FIT
+ }
+
+ //----------------------------------
+ // maxChars
+ //----------------------------------
+
+ /**
+ * Storage for the maxChars property.
+ * This is needed because clients may ask for this after the StageText has
+ * been disposed.
+ */
+ protected var _maxChars:int;
+
+ /**
+ * @copy flash.text.StageText#maxChars
+ *
+ * @default 0
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get maxChars():int
+ {
+ return _maxChars;
+ }
+
+ public function set maxChars(value:int):void
+ {
+ if (stageText != null)
+ stageText.maxChars = value;
+ _maxChars = value;
+ }
+
+ //----------------------------------
+ // multiline
+ //----------------------------------
+
+ /**
+ * Storage for the multiline property.
+ * This is needed because clients may ask for this after the StageText has
+ * been disposed.
+ */
+ protected var _multiline:Boolean;
+
+ /**
+ * @copy flash.text.StageText#multiline
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get multiline():Boolean
+ {
+ return _multiline;
+ }
+
+ /**
+ * @private
+ * StageText doesn't support setting its multiline property after it has
+ * been created. This setter is only here to satisfy requirements of the
+ * IEditableText interface.
+ */
+ public function set multiline(value:Boolean):void
+ {
+ // Do nothing.
+ // multiline cannot be set on StageText after it is created.
+ }
+
+ //----------------------------------
+ // restrict
+ //----------------------------------
+
+ /**
+ * Storage for the restrict property.
+ * This is needed because clients may ask for this after the StageText has
+ * been disposed.
+ */
+ protected var _restrict:String;
+
+ /**
+ * @copy flash.text.StageText#restrict
+ *
+ * @default null
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get restrict():String
+ {
+ return _restrict;
+ }
+
+ public function set restrict(value:String):void
+ {
+ if (stageText != null)
+ stageText.restrict = value;
+ _restrict = value;
+ }
+
+ //----------------------------------
+ // selectable
+ //----------------------------------
+
+ /**
+ * @private
+ * @inheritDoc
+ */
+ public function get selectable():Boolean
+ {
+ return true;
+ }
+
+ public function set selectable(value:Boolean):void
+ {
+ // Text is always selectable in StageText
+ }
+
+ //----------------------------------
+ // selectionActivePosition
+ //----------------------------------
+
+ /**
+ * The active, or last clicked position, of the selection. If the
+ * implementation does not support selection anchor this is the last
+ * character of the selection.
+ *
+ * <p>This value can not be used as the source for data binding.</p>
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get selectionActivePosition():int
+ {
+ return stageText ? stageText.selectionActiveIndex : 0;
+ }
+
+ //----------------------------------
+ // selectionAnchorPosition
+ //----------------------------------
+
+ /**
+ * The anchor, or first clicked position, of the selection. If the
+ * implementation does not support selection anchor this is the first
+ * character of the selection.
+ *
+ * <p>This value can not be used as the source for data binding.</p>
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get selectionAnchorPosition():int
+ {
+ return stageText ? stageText.selectionAnchorIndex : 0;
+ }
+
+ //----------------------------------
+ // text
+ //----------------------------------
+
+ /**
+ * Storage for the text property.
+ * This is needed because clients may ask for this after the StageText has
+ * been disposed.
+ */
+ private var _text:String = "";
+
+ /**
+ * A string that is the current text in the text field.
+ * Lines are separated by the carriage return character ('\r', ASCII 13).
+ * This property contains unformatted text in the text field, without any formatting tags.
+ *
+ * <p>If there was a prior selection, it will be preserved.
+ * If the length of the old text was less than the length of the new text, the selection
+ * will be adjusted so that neither <code>selectionAnchorPosition</code> or
+ * <code>selectionActivePosition</code> is greater than the length of the new text.</p>
+ *
+ * @default ""
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get text():String
+ {
+ return _text;
+ }
+
+ public function set text(value:String):void
+ {
+ // This is to match legacy behavior. Setting text to null really just
+ // sets it to the empty string.
+ if (value == null)
+ value = "";
+
+ if (value != _text)
+ {
+ // Like TextField, preserve the selection when setting text. This is necessary so that
+ // if there is a binding to the text property, the insertion poiint doesn't reset after
+ // every character typed.
+ if (stageText != null)
+ {
+ var anchorIndex:int = stageText.selectionAnchorIndex;
+ var activeIndex:int = stageText.selectionActiveIndex;
+ stageText.text = value;
+ stageText.selectRange(anchorIndex, activeIndex);
+ }
+
+ _text = value;
+
+ dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ invalidateProxy();
+ }
+ }
+
+ //----------------------------------
+ // verticalScrollPosition
+ //----------------------------------
+
+ /**
+ * @private
+ * The vertical scroll position of the text. StageText doesn't support
+ * this currently. Even so, we need to have this to satisfy requirements
+ * of the IEditableText interface.
+ */
+ public function get verticalScrollPosition():Number
+ {
+ // TODO: StageText doesn't support this yet
+ return 0;
+ }
+
+ public function set verticalScrollPosition(value:Number):void
+ {
+ // TODO: StageText doesn't support this yet
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // ISoftKeyboardHint properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // autoCapitalize
+ //----------------------------------
+
+ /**
+ * Storage for the autoCapitalize property.
+ */
+ private var _autoCapitalize:String = AutoCapitalize.NONE;
+
+ /**
+ * @inheritDoc
+ *
+ * @default "none"
+ *
+ * @see flash.text.AutoCapitalize
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get autoCapitalize():String
+ {
+ return stageText ? stageText.autoCapitalize : _autoCapitalize;
+ }
+
+ public function set autoCapitalize(value:String):void
+ {
+ if (value == "")
+ value = AutoCapitalize.NONE;
+
+ if (stageText != null)
+ stageText.autoCapitalize = value;
+
+ _autoCapitalize = value;
+ }
+
+ //----------------------------------
+ // autoCorrect
+ //----------------------------------
+
+ /**
+ * Storage for the autoCorrect property.
+ */
+ private var _autoCorrect:Boolean = true;
+
+ /**
+ * @inheritDoc
+ *
+ * @default true
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get autoCorrect():Boolean
+ {
+ return stageText ? stageText.autoCorrect : _autoCorrect;
+ }
+
+ public function set autoCorrect(value:Boolean):void
+ {
+ if (stageText != null)
+ stageText.autoCorrect = value;
+
+ _autoCorrect = value;
+ }
+
+ //----------------------------------
+ // returnKeyLabel
+ //----------------------------------
+
+ /**
+ * Storage for the returnKeyLabel property.
+ */
+ private var _returnKeyLabel:String = ReturnKeyLabel.DEFAULT;
+
+ /**
+ * @inheritDoc
+ *
+ * @default "default"
+ *
+ * @see flash.text.ReturnKeyLabel
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get returnKeyLabel():String
+ {
+ return stageText ? stageText.returnKeyLabel : _returnKeyLabel;
+ }
+
+ public function set returnKeyLabel(value:String):void
+ {
+ if (value == "")
+ value = ReturnKeyLabel.DEFAULT;
+
+ if (stageText != null)
+ stageText.returnKeyLabel = value;
+
+ _returnKeyLabel = value;
+ }
+
+ //----------------------------------
+ // softKeyboardType
+ //----------------------------------
+
+ /**
+ * Storage for the softKeyboardType property.
+ */
+ private var _softKeyboardType:String = SoftKeyboardType.DEFAULT;
+
+ /**
+ * @inheritDoc
+ *
+ * @default "default"
+ *
+ * @see flash.text.SoftKeyboardType
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function get softKeyboardType():String
+ {
+ return stageText ? stageText.softKeyboardType : _softKeyboardType;
+ }
+
+ public function set softKeyboardType(value:String):void
+ {
+ if (value == "")
+ value = SoftKeyboardType.DEFAULT;
+
+ if (stageText != null)
+ stageText.softKeyboardType = value;
+
+ _softKeyboardType = value;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override public function move(x:Number, y:Number):void
+ {
+ super.move(x, y);
+
+ if (!localViewPort)
+ localViewPort = new Rectangle();
+
+ localViewPort.x = x;
+ localViewPort.y = y;
+
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ super.styleChanged(styleProp);
+
+ if (styleProp == null || styleProp == "styleName"
+ || supportedStyles.indexOf(styleProp) >= 0)
+ {
+ invalidateStyleFlag = true;
+ }
+ }
+
+ /**
+ * @private
+ */
+ override public function setActualSize(w:Number, h:Number):void
+ {
+ super.setActualSize(w, h);
+
+ if (!localViewPort)
+ localViewPort = new Rectangle();
+
+ localViewPort.width = Math.max(0, w);
+ localViewPort.height = Math.max(0, h);
+
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ commitStyles();
+
+ var minMetrics:TextLineMetrics = measureText("Wj");
+ var currentMetrics:TextLineMetrics = measureText(text);
+
+ measuredMinWidth = minMetrics.width;
+ measuredWidth = Math.max(measuredMinWidth, currentMetrics.width);
+
+ if (isAndroid)
+ {
+ // Android text heights are slightly different from Flex's.
+ measuredMinHeight = minMetrics.height * androidHeightMultiplier;
+ measuredHeight = Math.max(measuredMinHeight, currentMetrics.height * androidHeightMultiplier);
+ }
+ else
+ {
+ measuredMinHeight = minMetrics.height;
+ measuredHeight = Math.max(measuredMinHeight, currentMetrics.height);
+ }
+ }
+
+ /**
+ * @private
+ */
+ public function commitStyles():void
+ {
+ if (invalidateStyleFlag && stageText != null)
+ {
+ var textAlign:String = getStyle("textAlign");
+
+ if (textAlign)
+ {
+ var rtl:Boolean = getStyle("layoutDirection") == LayoutDirection.RTL;
+
+ if (textAlign == "start")
+ textAlign = rtl ? TextFormatAlign.RIGHT : TextFormatAlign.LEFT;
+ else if (textAlign == "end")
+ textAlign = rtl ? TextFormatAlign.LEFT : TextFormatAlign.RIGHT;
+
+ stageText.textAlign = textAlign;
+ }
+ else
+ {
+ stageText.textAlign = defaultStyles["textAlign"];
+ }
+
+ var fontFamily:String = getStyle("fontFamily");
+
+ if (fontFamily)
+ stageText.fontFamily = fontFamily;
+ else
+ stageText.fontFamily = defaultStyles["fontFamily"];
+
+ var fontPosture:String = getStyle("fontStyle");
+
+ if (fontPosture)
+ stageText.fontPosture = fontPosture;
+ else
+ stageText.fontPosture = defaultStyles["fontStyle"];
+
+ var fontWeight:String = getStyle("fontWeight");
+
+ if (fontWeight)
+ stageText.fontWeight = fontWeight;
+ else
+ stageText.fontWeight = defaultStyles["fontWeight"];
+
+ var fontSize:* = getStyle("fontSize");
+
+ if (fontSize != undefined)
+ stageText.fontSize = fontSize * densityScale;
+ else
+ stageText.fontSize = defaultStyles["fontSize"] * densityScale;
+
+ var color:* = getStyle("color");
+
+ if (color != undefined)
+ stageText.color = color;
+ else
+ stageText.color = defaultStyles["color"];
+
+ var locale:* = getStyle("locale");
+
+ if (locale != undefined)
+ stageText.locale = locale;
+ else
+ stageText.locale = defaultStyles["locale"];
+
+ invalidateStyleFlag = false;
+
+ invalidateProxy();
+ }
+ }
+
+
+ //----------------------------------
+ // completeEventPending
+ //----------------------------------
+
+
+
+ /**
+ * @private
+ */
+ override protected function commitProperties():void
+ {
+ super.commitProperties();
+
+ if (stageText != null)
+ stageText.editable = _editable;
+
+ if (invalidateViewPortFlag)
+ {
+ invalidateViewPortFlag = false;
+ updateViewPort();
+ }
+
+ if (invalidateProxyFlag && showProxy)
+ {
+ invalidateProxyFlag = false;
+ updateProxy();
+ }
+
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override public function setFocus():void
+ {
+ // if mouse is down, let SetFocus handle the focus, otherwise it's programmatic, so assign focus
+ if (isMouseDown)
+ {
+
+ return;
+ }
+ if (stageText != null)
+ {
+ stageText.assignFocus(); // will trigger stageTextfocusIn
+ //TODO what happens when setting focus to a component in a popup that is not visible yet
+ // else
+ // pendingFocusedStageText = stageText;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function appendText(text:String):void
+ {
+ if (stageText != null && text.length > 0)
+ {
+ if (stageText.text != null)
+ stageText.text += text;
+ else
+ stageText.text = text;
+
+ _text = stageText.text;
+
+ // Move the cursor to the end of the appended text.
+ stageText.selectRange(_text.length, _text.length);
+
+ dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+
+
+ invalidateProxy();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function insertText(text:String):void
+ {
+ if (stageText == null || text.length == 0)
+ return;
+
+ var origText:String = stageText.text;
+
+ var selectionActiveIndex:int = stageText.selectionActiveIndex;
+ var selectionAnchorIndex:int = stageText.selectionAnchorIndex;
+
+ var startIndex:int = origText.length;
+ var endIndex:int = startIndex;
+
+ if (selectionActiveIndex >= 0 && selectionAnchorIndex >= 0)
+ {
+ startIndex = Math.min(selectionActiveIndex, selectionAnchorIndex);
+ endIndex = Math.max(selectionActiveIndex, selectionAnchorIndex);
+ }
+ else if (selectionActiveIndex >= 0)
+ {
+ startIndex = selectionActiveIndex;
+ endIndex = selectionActiveIndex;
+ }
+ else if (selectionAnchorIndex >= 0)
+ {
+ startIndex = selectionAnchorIndex;
+ endIndex = selectionAnchorIndex;
+ }
+
+ var newText:String = "";
+
+ if (startIndex > 0)
+ newText += origText.substring(0, startIndex);
+
+ newText += text;
+
+ if (endIndex < origText.length)
+ newText += origText.substring(endIndex);
+
+ stageText.text = newText;
+
+ // Move the cursor to the end of the inserted text.
+ stageText.selectRange(startIndex + text.length, startIndex + text.length);
+
+ _text = stageText.text;
+
+ // TODO: scrollToRange so the insertion point is visible
+
+ dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+
+ invalidateProxy();
+ }
+
+ /**
+ * @private
+ * Scroll so the specified range is in view.
+ */
+ public function scrollToRange(anchorPosition:int, activePosition:int):void
+ {
+ // TODO: StageText doesn't support this yet
+ }
+
+ /**
+ * Selects all of the text.
+ *
+ * <p>On iOS, for non multiline StyleableStageText objects, this function
+ * is not supported and does nothing.</p>
+ *
+ * <p>For some devices or operating systems, the selection may only be
+ * visible when the StageText object has focus.</p>
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function selectAll():void
+ {
+ if (stageText != null && stageText.text != null)
+ {
+ stageText.selectRange(0, stageText.text.length);
+ invalidateProxy();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function selectRange(anchorIndex:int, activeIndex:int):void
+ {
+ if (stageText != null)
+ {
+ stageText.selectRange(anchorIndex, activeIndex);
+ invalidateProxy();
+ }
+ }
+
+
+ /**
+ * EDITING AND FOCUS MANAGEMENT
+ */
+
+ protected function startTextEdit():void
+ {
+ if (!isEditing)
+ {
+ isEditing = true;
+ showProxy = false;
+ proxy.visible = false;
+ updateViewPort();
+ stageText.visible = true;
+ }
+ }
+
+ protected function endTextEdit():void
+ {
+ if (isEditing)
+ {
+ isEditing = false;
+ invalidateProxy();
+ showProxy = true;
+ proxy.visible = true;
+ stageText.visible = false;
+
+ if (focusManager is FocusManager)
+ {
+ var fm:FocusManager = focusManager as FocusManager;
+ var lastFocus:Object = fm.lastFocus as Object;
+
+ if (lastFocus && lastFocus.hasOwnProperty("textDisplay") && lastFocus.textDisplay == this)
+ fm.lastFocus = null;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Proxy Management
+ //--------------------------------------------------------------------------
+
+ protected function createProxy():DisplayObject
+ {
+ var bm: DisplayObject ;
+ if (densityScale == 1)
+ {
+ bm = new Bitmap(null);
+ }
+ else
+ {
+ bm = new Bitmap(null, PixelSnapping.NEVER, true);
+ bm.scaleX = 1.0 / densityScale;
+ bm.scaleY = 1.0 / densityScale;
+ }
+ return bm;
+ }
+
+ private function invalidateProxy():void
+ {
+ invalidateProxyFlag = true;
+ invalidateProperties();
+ }
+
+ /**
+ * Replace the existing proxy image representing this StageText with a new
+ * one. Call this whenever the StageText's properties, contents, or
+ * geometry changes. This does nothing if there is no proxy image, so it is
+ * safe to call updateProxy even if the state of the proxy image is
+ * unknown.
+ */
+ protected function updateProxy():void
+ {
+ if (stageText == null)
+ return;
+ if (proxy != null)
+ {
+ var newImageData:BitmapData = captureBitmapData();
+ if (newImageData)
+ {
+ var oldImageData:BitmapData = Bitmap(proxy).bitmapData;
+ Bitmap(proxy).bitmapData = newImageData;
+ if (oldImageData)
+ oldImageData.dispose();
+ }
+ }
+ }
+
+ /** Dispose the proxy resources once it has been removed from the stage */
+ protected function disposeProxy():void
+ {
+ Bitmap(proxy).bitmapData.dispose();
+ }
+
+ /**
+ * If a StageText is visible, this will capture a bitmap copy of what it is
+ * displaying. This includes any text visible in the StageText and may
+ * include the text insertion cursor if it is visible at the time of the
+ * call.
+ */
+ mx_internal function captureBitmapData():BitmapData
+ {
+ if (!stageText || !stageText.stage || !localViewPort ||
+ localViewPort.width == 0 || localViewPort.height == 0)
+ return null; // The StageText is invisible.
+
+ if (stageText.viewPort.width == 0 || stageText.viewPort.height == 0)
+ updateViewPort(); // The StageText viewport is stale.
+
+ // Make sure any pending style changes get saved before replacing
+ // the StageText with a bitmap
+ commitStyles();
+
+ var bitmap:BitmapData = new BitmapData(stageText.viewPort.width,
+ stageText.viewPort.height, !debugProxyImage, debugProxyImage ? 0xFF00FF : 0x00FFFFFF);
+
+ stageText.drawViewPortToBitmapData(bitmap);
+
+ return bitmap;
+ }
+
+
+ protected function getGlobalViewPort():Rectangle
+ {
+ // We calculate the parent's concatenated matrix to deal with
+ // issues in the runtime where the concatenated matrix of the
+ // parent is out of sync. See SDK-31538.
+ var m:Matrix = MatrixUtil.getConcatenatedMatrix(parent, stage);
+ var globalTopLeft:Point = m.transformPoint(localViewPort.topLeft);
+
+ // Transform the bottom-right corner of the local rect
+ // instead of setting width/height to account for any
+ // transformations applied to ancestor objects.
+ var globalBottomRight:Point = m.transformPoint(localViewPort.bottomRight);
+ var globalRect:Rectangle = new Rectangle();
+
+ // StageText can't deal with upside-down or mirrored rectangles
+ // or non-integer values. Fix those here.
+ globalRect.x = Math.floor(Math.min(globalTopLeft.x, globalBottomRight.x));
+ globalRect.y = Math.floor(Math.min(globalTopLeft.y, globalBottomRight.y));
+ globalRect.width = Math.ceil(Math.abs(globalBottomRight.x - globalTopLeft.x));
+ globalRect.height = Math.ceil(Math.abs(globalBottomRight.y - globalTopLeft.y));
+
+ return globalRect;
+ }
+
+ /**
+ * Tell the StageText what rectangle it needs to render in. The StageText
+ * is not part of the normal display hierarchy, so its coordinates are
+ * always specified in global space.
+ */
+ protected function updateViewPort():void
+ {
+ if (parent && localViewPort && stageText != null)
+ {
+ if (stageText.stage)
+ {
+ var globalRect:Rectangle = getGlobalViewPort();
+
+ if (!globalRect.equals(stageText.viewPort))
+ {
+ stageText.viewPort = globalRect;
+ }
+ }
+ }
+ }
+
+ /**
+ * StageText does not have any provision for measuring text. To get
+ * approximate sizing, this uses UIComponent's text measurement method on a
+ * string with an ascender and a descender. Because platform rendering and
+ * UIComponent's rendering differ, the measurement should only be used as
+ * an approximation.
+ */
+ protected function measureTextLineHeight():Number
+ {
+ var lineMetrics:TextLineMetrics = measureText("Wj");
+
+ // Android text heights are slightly different from Flex's.
+ if (isAndroid)
+ return lineMetrics.height * androidHeightMultiplier;
+
+ return lineMetrics.height;
+ }
+
+ protected function restoreStageText():void
+ {
+ if (stageText != null)
+ {
+ // This has to happen here instead of waiting for commitProperties
+ // because this will cause stageText.text to get cleared. Subsequent
+ // change events would then copy that cleared text to the _text
+ // storage variable, making the change permanent.
+ stageText.editable = _editable;
+
+ // Restore the text and the selection.
+ stageText.text = _text;
+ stageText.selectRange(savedSelectionAnchorIndex, savedSelectionActiveIndex);
+ savedSelectionAnchorIndex = 0;
+ savedSelectionActiveIndex = 0;
+
+ stageText.displayAsPassword = _displayAsPassword;
+ stageText.maxChars = _maxChars;
+
+ stageText.restrict = _restrict;
+
+ // Soft keyboard hints
+ stageText.autoCapitalize = _autoCapitalize;
+ stageText.autoCorrect = _autoCorrect;
+ stageText.returnKeyLabel = _returnKeyLabel;
+ stageText.softKeyboardType = _softKeyboardType;
+
+ // Make sure styles are restored
+ invalidateStyleFlag = true;
+
+ // Make sure viewPort and enabled state are recalculated
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // event handlers
+ //
+ //--------------------------------------------------------------------------
+
+ protected function addedToStageHandler(event:Event):void
+ {
+
+ var needsRestore:Boolean = false;
+ if (stageText == null)
+ {
+ needsRestore = !StageTextPool.current.hasCachedStageText(this);
+ stageText = StageTextPool.current.acquireStageText(this);
+ stageText.visible = false;
+ }
+
+ proxy = createProxy();
+ addChild(proxy);
+ invalidateProxy();
+ // The "complete" handler must be registered before changes to the stage
+ // or viewPort. StageText on iOS dispatches complete events during the
+ // setting of these properties, unlike Android which does so some time
+ // afterward.
+ stageText.addEventListener(Event.COMPLETE, stageText_completeHandler);
+ stageText.stage = stage;
+
+ if (needsRestore)
+ {
+ restoreStageText();
+ }
+ else if (savedSelectionAnchorIndex > 0 || savedSelectionActiveIndex > 0)
+ {
+ // Even if the StageText has been retrieved from the cache, its
+ // selection is not preserved. Restore the selection if necessary.
+ if (savedSelectionAnchorIndex <= _text.length && savedSelectionActiveIndex <= _text.length)
+ stageText.selectRange(savedSelectionAnchorIndex, savedSelectionActiveIndex);
+ savedSelectionAnchorIndex = 0;
+ savedSelectionActiveIndex = 0;
+ }
+
+// if (deferredViewPortUpdate)
+// updateViewPort();
+
+ // always create proxy image
+
+ // register listeners
+ addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
+ addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
+ if (stageText != null)
+ {
+ stageText.addEventListener(Event.CHANGE, stageText_changeHandler);
+ stageText.addEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
+ stageText.addEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
+ stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
+ stageText.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
+ stageText.addEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
+ stageText.addEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
+ }
+
+ invalidateProperties();
+ }
+
+ protected function removedFromStageHandler(event:Event):void
+ {
+
+ if (stageText == null)
+ return;
+
+ // Text is saved in _text. Also need to save the selection so it can be restored.
+ savedSelectionAnchorIndex = stageText.selectionAnchorIndex;
+ savedSelectionActiveIndex = stageText.selectionActiveIndex;
+
+
+ stageText.stage = null;
+
+ removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
+
+ stageText.removeEventListener(Event.CHANGE, stageText_changeHandler);
+ stageText.removeEventListener(Event.COMPLETE, stageText_completeHandler);
+ stageText.removeEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
+ stageText.removeEventListener(FocusEvent.FOCUS_OUT, stageText_focusOutHandler);
+ stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, stageText_softKeyboardActivateHandler);
+ stageText.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, stageText_softKeyboardDeactivateHandler);
+ stageText.removeEventListener(KeyboardEvent.KEY_DOWN, stageText_keyDownHandler);
+ stageText.removeEventListener(KeyboardEvent.KEY_UP, stageText_keyUpHandler);
+
+ StageTextPool.current.releaseStageText(this, stageText);
+ stageText = null;
+
+ if (proxy != null)
+ {
+ // If a textImage exists, we need to get rid of it to keep it in
+ // sync with our proxy image state. disposeProxyImage does not do
+ // this. It only sets a flag and invalidates properties.
+ removeChild(proxy);
+ disposeProxy();
+ proxy = null;
+ }
+ }
+
+ private function mouseDownHandler(event:MouseEvent):void
+ {
+ isMouseDown = true;
+ }
+
+ private function mouseUpHandler(event:MouseEvent):void
+ {
+ isMouseDown = false;
+ setFocus();
+ }
+
+ protected function stageText_changeHandler(event:Event):void
+ {
+ var foundChange:Boolean = false;
+
+ if (stageText != null)
+ {
+ var oldText:String = _text;
+ var newText:String = stageText.text;
+
+ foundChange = newText != oldText;
+ _text = stageText.text;
+ }
+ if (foundChange)
+ dispatchEvent(new TextOperationEvent(event.type));
+ }
+
+ protected function stageText_completeHandler(event:Event):void
+ {
+ invalidateProxy();
+ invalidateViewPortFlag = true;
+ invalidateProperties();
+ }
+
+ private function stageText_focusInHandler(event:FocusEvent):void
+ {
+ startTextEdit();
+ }
+
+ private function stageText_focusOutHandler(event:FocusEvent):void
+ {
+ endTextEdit();
+ // Focus events are documented as bubbling. However, all events coming
+ // from StageText are set to not bubble. So we need to create an
+ // appropriate bubbling event here.
+ dispatchEvent(new FocusEvent(event.type, true, event.cancelable,
+ event.relatedObject, event.shiftKey, event.keyCode, event.direction));
+ }
+
+ private function stageText_keyDownHandler(event:KeyboardEvent):void
+ {
+ // Taps on the Enter key on soft keyboards may send us the Next keycode
+ if ((event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT)
+ && !_multiline)
+ {
+ dispatchEvent(new FlexEvent(FlexEvent.ENTER));
+ }
+
+ // Keyboard events are documented as bubbling. However, all events
+ // coming from StageText are set to not bubble. So we need to create an
+ // appropriate bubbling event here.
+ dispatchEvent(new KeyboardEvent(event.type, true, event.cancelable,
+ event.charCode, event.keyCode, event.keyLocation, event.ctrlKey,
+ event.altKey, event.shiftKey, event.controlKey, event.commandKey));
+
+ if ((event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT)
+ && !_multiline && !isDesktop)
+ {
+ event.preventDefault();
+ }
+ }
+
+ private function stageText_keyUpHandler(event:KeyboardEvent):void
+ {
+ // Keyboard events are documented as bubbling. However, all events
+ // coming from StageText are set to not bubble. So we need to create an
+ // appropriate bubbling event here.
+ dispatchEvent(new KeyboardEvent(event.type, true, event.cancelable,
+ event.charCode, event.keyCode, event.keyLocation, event.ctrlKey,
+ event.altKey, event.shiftKey, event.controlKey, event.commandKey));
+
+ if ((event.keyCode == Keyboard.ENTER || event.keyCode == Keyboard.NEXT)
+ && !_multiline && !isDesktop)
+ {
+ event.preventDefault();
+ }
+ }
+
+ private function stageText_softKeyboardActivateHandler(event:SoftKeyboardEvent):void
+ {
+ startTextEdit();
+ dispatchEvent(new SoftKeyboardEvent(event.type,
+ true, event.cancelable, this, event.triggerType));
+ }
+
+ private function stageText_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
+ {
+ endTextEdit();
+ dispatchEvent(new SoftKeyboardEvent(event.type,
+ true, event.cancelable, this, event.triggerType));
+ }
+
+}
+}
+
+import flash.events.TimerEvent;
+import flash.text.StageText;
+import flash.text.StageTextInitOptions;
+import flash.utils.Dictionary;
+import flash.utils.Timer;
+
+import spark.components.supportClasses.ScrollableStageText;
+
+class StageTextPool
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ private static const poolReserve:Number = 5;
+ private static const poolTimerInterval:Number = 10000;
+
+ //--------------------------------------------------------------------------
+ //
+ // Class variables
+ //
+ //--------------------------------------------------------------------------
+
+ private static var _current:StageTextPool;
+
+ internal static function get current():StageTextPool {
+ if (!_current ){
+ _current = new StageTextPool();
+ }
+ return _current;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ public function StageTextPool( ) {
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ private var map_StyleableStageText_to_StageText:Dictionary = new Dictionary(true);
+ private var map_StageText_to_StyleableStageText:Dictionary = new Dictionary(true);
+
+ private var multilinePool:Vector.<StageText> = new Vector.<StageText>();
+ private var multilinePoolTimer:Timer;
+
+ private var singleLinePool:Vector.<StageText> = new Vector.<StageText>();
+ private var singleLinePoolTimer:Timer;
+
+ private var cleanProperties:Object = null;
+
+ //--------------------------------------------------------------------------
+ //
+ // Class methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Acquires a StageText and removes it from the pool. If the host
+ * StyleableStageText2 has recently released a StageText and that StageText
+ * is still in the pool, that StageText will be returned.
+ */
+ public function acquireStageText(host:ScrollableStageText):StageText
+ {
+ var result:StageText = map_StyleableStageText_to_StageText[host];
+
+ if (!result)
+ {
+ if (host.multiline)
+ {
+ if (multilinePool.length == 0)
+ while (multilinePool.length < poolReserve)
+ multilinePool.push(new StageText(new StageTextInitOptions(true)));
+
+ result = multilinePool.pop();
+ }
+ else
+ {
+ if (singleLinePool.length == 0)
+ while (singleLinePool.length < poolReserve)
+ singleLinePool.push(new StageText(new StageTextInitOptions(false)));
+
+ result = singleLinePool.pop();
+ }
+
+ // The first time a StageText is acquired, it's guaranteed to have been
+ // newly-created. Take that opportunity to stash away the StageText's
+ // defaults for properties that StyleableStageText may not necessarily
+ // overwrite during its initialization. This is necessary because this
+ // object pool "recycles" StageTexts and we need to ensure that those
+ // StageTexts are clean when they are reused.
+ // While the "editable" property is set in commitProperties, there is a
+ // bug on Android devices where setting editable to false fails to make
+ // the StageText read-only if it's already false. So, make sure
+ // "editable" is one of the properties that gets restored to its
+ // default value.
+ if (!cleanProperties)
+ {
+ cleanProperties = {};
+
+ cleanProperties["autoCapitalize"] = result.autoCapitalize;
+ cleanProperties["autoCorrect"] = result.autoCorrect;
+ //cleanProperties["color"] = result.color; // Set in commitStyles
+ cleanProperties["displayAsPassword"] = result.displayAsPassword;
+ cleanProperties["editable"] = result.editable;
+ //cleanProperties["fontFamily"] = result.fontFamily; // Set in commitStyles
+ //cleanProperties["fontPosture"] = result.fontPosture; // Set in commitStyles
+ //cleanProperties["fontSize"] = result.fontSize; // Set in commitStyles
+ //cleanProperties["fontWeight"] = result.fontWeight; // Set in commitStyles
+ //cleanProperties["locale"] = result.locale; // Set in commitStyles
+ cleanProperties["maxChars"] = result.maxChars;
+ cleanProperties["restrict"] = result.restrict;
+ cleanProperties["returnKeyLabel"] = result.returnKeyLabel;
+ cleanProperties["softKeyboardType"] = result.softKeyboardType;
+ cleanProperties["text"] = result.text;
+ //cleanProperties["textAlign"] = result.textAlign; // Set in commitStyles
+ //cleanProperties["visible"] = result.visible; // Set in commitVisible
+ }
+ else
+ {
+ for (var prop:String in cleanProperties)
+ result[prop] = cleanProperties[prop];
+ }
+ }
+ else
+ {
+ var index:int;
+
+ if (host.multiline)
+ {
+ index = multilinePool.indexOf(result);
+ multilinePool.splice(index, 1);
+ }
+ else
+ {
+ index = singleLinePool.indexOf(result);
+ singleLinePool.splice(index, 1);
+ }
+ }
+
+ uncacheStageText(result);
+
+ return result;
+ }
+
+ /**
+ * Returns true if the StageText that would be returned by acquireStageText
+ * for the given StyleableStageText2 will be the same as the last StageText
+ * it released.
+ */
+ public function hasCachedStageText(host:ScrollableStageText):Boolean
+ {
+ return map_StyleableStageText_to_StageText[host] !== undefined;
+ }
+
+ /**
+ * Puts a StageText back into the pool and caches the StyleableStageText2/
+ * StageText pair so the same StageText may be returned if the
+ * StyleableStageText2 re-acquires it. If this causes the pool to grow
+ * larger than its reserve size, this starts a timer to check and reduce
+ * the size of the pool poolTimerInterval milliseconds later.
+ */
+ public function releaseStageText(host:ScrollableStageText, stageText:StageText):void
+ {
+ map_StyleableStageText_to_StageText[host] = stageText;
+ map_StageText_to_StyleableStageText[stageText] = host;
+
+ if (host.multiline)
+ {
+ multilinePool.push(stageText);
+
+ if (multilinePool.length > poolReserve)
+ {
+ if (!multilinePoolTimer)
+ {
+ multilinePoolTimer = new Timer(poolTimerInterval, 1);
+ multilinePoolTimer.addEventListener(TimerEvent.TIMER,
+ function (event:TimerEvent):void
+ {
+ shrinkPool(true);
+ multilinePoolTimer = null;
+ }, false, 0, true);
+ }
+
+ multilinePoolTimer.reset();
+ multilinePoolTimer.start();
+ }
+ }
+ else
+ {
+ singleLinePool.push(stageText);
+
+ if (singleLinePool.length > poolReserve)
+ {
+ if (!singleLinePoolTimer)
+ {
+ singleLinePoolTimer = new Timer(poolTimerInterval, 1);
+ singleLinePoolTimer.addEventListener(TimerEvent.TIMER,
+ function (event:TimerEvent):void
+ {
+ shrinkPool(false);
+ singleLinePoolTimer = null;
+ }, false, 0, true);
+ }
+
+ singleLinePoolTimer.reset();
+ singleLinePoolTimer.start();
+ }
+ }
+ }
+
+ /**
+ * Return the pool to its reserve size.
+ */
+ private function shrinkPool(multiline:Boolean):void
+ {
+ var oldStageText:StageText;
+
+ if (multiline)
+ {
+ while (multilinePool.length > poolReserve)
+ {
+ oldStageText = multilinePool.shift();
+ uncacheStageText(oldStageText);
+ oldStageText.dispose();
+ }
+ }
+ else
+ {
+ while (singleLinePool.length > poolReserve)
+ {
+ oldStageText = singleLinePool.shift();
+ uncacheStageText(oldStageText);
+ oldStageText.dispose();
+ }
+ }
+ }
+
+ /**
+ * Remove a StageText and its last known StyleableStageText2 host from the
+ * cache.
+ */
+ private function uncacheStageText(stageText:StageText):void
+ {
+ var host:ScrollableStageText = map_StageText_to_StyleableStageText[stageText];
+
+ delete map_StyleableStageText_to_StageText[host];
+ delete map_StageText_to_StyleableStageText[stageText];
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/StyleableStageText.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/StyleableStageText.as b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/StyleableStageText.as
index f3792b5..d43e979 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/StyleableStageText.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/StyleableStageText.as
@@ -324,7 +324,7 @@ use namespace mx_internal;
* @playerversion AIR 3.0
* @productversion Flex 4.6
*/
-public class StyleableStageText extends UIComponent implements IEditableText, ISoftKeyboardHintClient
+public class StyleableStageText extends UIComponent implements IStyleableEditableText, ISoftKeyboardHintClient
{
//--------------------------------------------------------------------------
//
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobiletheme/defaults.css
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobiletheme/defaults.css b/frameworks/projects/mobiletheme/defaults.css
index 850b296..caf628d 100644
--- a/frameworks/projects/mobiletheme/defaults.css
+++ b/frameworks/projects/mobiletheme/defaults.css
@@ -313,7 +313,7 @@ TextArea
paddingRight: 9;
paddingTop: 9;
showPromptWhenFocused: true;
- skinClass: ClassReference("spark.skins.mobile.StageTextAreaSkin");
+ skinClass: ClassReference("spark.skins.mobile.ScrollingStageTextAreaSkin");
}
TextArea VScrollBar
@@ -333,7 +333,7 @@ TextInput
paddingRight: 9;
paddingTop: 9;
showPromptWhenFocused: true;
- skinClass: ClassReference("spark.skins.mobile.StageTextInputSkin");
+ skinClass: ClassReference("spark.skins.mobile.ScrollingStageTextInputSkin");
}
ToggleSwitch
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobiletheme/src/MobileThemeClasses.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobiletheme/src/MobileThemeClasses.as b/frameworks/projects/mobiletheme/src/MobileThemeClasses.as
index 3ff2ebe..1f890cb 100644
--- a/frameworks/projects/mobiletheme/src/MobileThemeClasses.as
+++ b/frameworks/projects/mobiletheme/src/MobileThemeClasses.as
@@ -57,6 +57,8 @@ import spark.skins.mobile.SkinnableContainerSkin; SkinnableContainerSkin;
import spark.skins.mobile.SplitViewNavigatorSkin; SplitViewNavigatorSkin;
import spark.skins.mobile.StageTextAreaSkin; StageTextAreaSkin;
import spark.skins.mobile.StageTextInputSkin; StageTextInputSkin;
+ import spark.skins.mobile.ScrollingStageTextInputSkin; ScrollingStageTextInputSkin;
+import spark.skins.mobile.ScrollingStageTextAreaSkin; ScrollingStageTextAreaSkin
import spark.skins.mobile.TabbedViewNavigatorApplicationSkin; TabbedViewNavigatorApplicationSkin;
import spark.skins.mobile.TabbedViewNavigatorSkin; TabbedViewNavigatorSkin;
import spark.skins.mobile.TabbedViewNavigatorTabBarSkin; TabbedViewNavigatorTabBarSkin;
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as
new file mode 100644
index 0000000..bdf9edf
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.skins.mobile
+{
+import spark.components.supportClasses.IStyleableEditableText;
+import spark.components.supportClasses.ScrollableStageText;
+
+/**
+ * ActionScript-based skin for TextArea controls in mobile applications that uses a
+ * ScrollableStageText class for the text display.
+ * <p> and can be used in scrollable forms while allowing precise control of keyboard input.</p>
+ *
+ * @see spark.components.TextArea
+ * @see spark.components.supportClasses.ScrollableStageText
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.12
+ */
+public class ScrollingStageTextAreaSkin extends StageTextAreaSkin
+{
+ public function ScrollingStageTextAreaSkin()
+ {
+ super();
+ }
+
+ override protected function createTextDisplay():IStyleableEditableText
+ {
+ return new ScrollableStageText(multiline);
+ }
+}
+}
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as
new file mode 100644
index 0000000..d856d53
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.skins.mobile
+{
+import spark.components.supportClasses.IStyleableEditableText;
+import spark.components.supportClasses.ScrollableStageText;
+
+/**
+ * ActionScript-based skin for TextInput controls in mobile applications that uses a
+ * ScrollableStageText class for the text display
+ * <p> and can be used in scrollable forms while allowing precise control of keyboard input.</p>
+ *
+ * @see spark.components.TextInput
+ * @see spark.components.supportClasses.ScrollableStageText
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.12
+ */
+public class ScrollingStageTextInputSkin extends StageTextInputSkin
+{
+ public function ScrollingStageTextInputSkin()
+ {
+ super();
+ }
+
+ override protected function createTextDisplay():IStyleableEditableText
+ {
+ return new ScrollableStageText(multiline);
+ }
+}
+}
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/48169122/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/StageTextSkinBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/StageTextSkinBase.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/StageTextSkinBase.as
index fa0341c..9e4514d 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/StageTextSkinBase.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/StageTextSkinBase.as
@@ -26,6 +26,8 @@ import flash.geom.Point;
import mx.core.DPIClassification;
import mx.core.mx_internal;
+import spark.components.supportClasses.IStyleableEditableText;
+
import spark.components.supportClasses.SkinnableTextBase;
import spark.components.supportClasses.StyleableStageText;
import spark.components.supportClasses.StyleableTextField;
@@ -202,7 +204,7 @@ public class StageTextSkinBase extends MobileSkin
* @playerversion AIR 3.0
* @productversion Flex 4.6
*/
- public var textDisplay:StyleableStageText;
+ public var textDisplay:IStyleableEditableText;
[Bindable]
/**
@@ -230,11 +232,11 @@ public class StageTextSkinBase extends MobileSkin
if (!textDisplay)
{
- textDisplay = new StyleableStageText(multiline);
+ textDisplay = createTextDisplay();
textDisplay.editable = true;
textDisplay.styleName = this;
- this.addChild(textDisplay);
+ this.addChild(DisplayObject(textDisplay));
}
if (!border)
@@ -244,6 +246,14 @@ public class StageTextSkinBase extends MobileSkin
}
}
+ /** Could be overridden by subclasses
+ *
+ * @return instance of IStyleableEditableText
+ */
+ protected function createTextDisplay():IStyleableEditableText {
+ return new StyleableStageText(multiline);
+ }
+
/**
* @private
*/