| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 helpers |
| { |
| |
| import flash.display.DisplayObject; |
| import flash.display.Graphics; |
| import flash.display.Shape; |
| import flash.display.Sprite; |
| import flash.events.Event; |
| import flash.events.MouseEvent; |
| import flash.events.TextEvent; |
| import flash.geom.Point; |
| import flash.geom.Rectangle; |
| import flash.text.StyleSheet; |
| import flash.text.TextField; |
| import flash.text.TextFieldAutoSize; |
| import flash.text.TextFieldType; |
| import flash.text.TextFormat; |
| import flash.text.TextLineMetrics; |
| import flash.text.engine.ElementFormat; |
| import flash.text.engine.FontDescription; |
| import flash.text.engine.FontLookup; |
| import flash.text.engine.FontMetrics; |
| import flash.text.engine.FontPosture; |
| import flash.text.engine.FontWeight; |
| import flash.text.engine.Kerning; |
| import flash.text.engine.LineJustification; |
| import flash.text.engine.SpaceJustifier; |
| import flash.text.engine.TextBlock; |
| import flash.text.engine.TextElement; |
| import flash.text.engine.TextLine; |
| |
| import flashx.textLayout.compose.ISWFContext; |
| import flashx.textLayout.compose.TextLineRecycler; |
| import flashx.textLayout.container.TextContainerManager; |
| import flashx.textLayout.conversion.ConversionType; |
| import flashx.textLayout.conversion.ITextExporter; |
| import flashx.textLayout.conversion.ITextImporter; |
| import flashx.textLayout.conversion.TextConverter; |
| import flashx.textLayout.edit.EditingMode; |
| import flashx.textLayout.elements.Configuration; |
| import flashx.textLayout.elements.LinkElement; |
| import flashx.textLayout.elements.TextFlow; |
| import flashx.textLayout.events.FlowElementMouseEvent; |
| import flashx.textLayout.events.StatusChangeEvent; |
| import flashx.textLayout.factory.TextFlowTextLineFactory; |
| import flashx.textLayout.formats.ITextLayoutFormat; |
| import flashx.textLayout.formats.LeadingModel; |
| import flashx.textLayout.formats.LineBreak; |
| import flashx.textLayout.formats.TextDecoration; |
| import flashx.textLayout.formats.TextLayoutFormat; |
| |
| import mx.core.FTETextField; |
| import mx.core.FlexGlobals; |
| import mx.core.IFlexModuleFactory; |
| import mx.core.IFontContextComponent; |
| import mx.core.mx_internal; |
| |
| use namespace mx_internal; |
| |
| use namespace mx_internal; |
| |
| /** |
| * FTETextField is a Sprite which displays text by using the new |
| * Flash Text Engine to implement the old TextField API. |
| * |
| * @see flash.text.TextField |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public class FTETextField41 extends Sprite |
| { |
| // Current slot count: 21 |
| // (1 for every type except 2 for Number) |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class initialization |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private static function initClass():void |
| { |
| var format:TextLayoutFormat; |
| var config:Configuration; |
| |
| // Create an importer for plain text. |
| plainTextImporter = |
| TextConverter.getImporter(TextConverter.PLAIN_TEXT_FORMAT); |
| |
| // Create an exporter for plain text. |
| plainTextExporter = |
| TextConverter.getExporter(TextConverter.PLAIN_TEXT_FORMAT); |
| |
| // Create an importer for TEXT_FIELD_HTML_FORMAT that collapses whitespace. |
| // Note: We have to make a copy of the textFlowInitialFormat, |
| // which has various formats set to "inherit", |
| // and then modify it and set it back. |
| config = new Configuration(); |
| format = new TextLayoutFormat(config.textFlowInitialFormat); |
| format.whiteSpaceCollapse = "collapse"; |
| config.textFlowInitialFormat = format; |
| collapsingHTMLImporter = |
| TextConverter.getImporter(TextConverter.TEXT_FIELD_HTML_FORMAT, config); |
| collapsingHTMLImporter.throwOnError = false; |
| |
| // Create an importer for TEXT_FIELD_HTML_FORMAT that preserves whitespace. |
| // Note: We have to make a copy of the textFlowInitialFormat, |
| // which has various formats set to "inherit", |
| // and then modify it and set it back. |
| config = new Configuration(); |
| format = new TextLayoutFormat(config.textFlowInitialFormat); |
| format.whiteSpaceCollapse = "preserve"; |
| config.textFlowInitialFormat = format; |
| preservingHTMLImporter = |
| TextConverter.getImporter(TextConverter.TEXT_FIELD_HTML_FORMAT, config); |
| preservingHTMLImporter.throwOnError = false; |
| |
| // Create an exporter for TEXT_FIELD_HTML_FORMAT. |
| htmlExporter = |
| TextConverter.getExporter(TextConverter.TEXT_FIELD_HTML_FORMAT); |
| |
| if ("recreateTextLine" in staticTextBlock) |
| recreateTextLine = staticTextBlock["recreateTextLine"]; |
| } |
| |
| initClass(); |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class constants |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * TextField has fixed 2-pixel padding. |
| */ |
| mx_internal static const PADDING_LEFT:Number = 2; |
| mx_internal static const PADDING_TOP:Number = 2; |
| mx_internal static const PADDING_RIGHT:Number = 2; |
| mx_internal static const PADDING_BOTTOM:Number = 2; |
| |
| /** |
| * @private |
| * This regular expression is used to replace LF with CR |
| * when the text property is set. |
| */ |
| private static const ALL_LINEFEEDS:RegExp = /\n/g; |
| |
| /** |
| * @private |
| * Masks for bits inside the 'flags' var |
| * which store the state of Boolean TextField properties. |
| */ |
| private static const FLAG_BACKGROUND:uint = 1 << 0; |
| private static const FLAG_BORDER:uint = 1 << 1; |
| private static const FLAG_CONDENSE_WHITE:uint = 1 << 2; |
| private static const FLAG_EMBED_FONTS:uint = 1 << 3; |
| private static const FLAG_MULTILINE:uint = 1 << 4; |
| private static const FLAG_WORD_WRAP:uint = 1 << 5; |
| |
| /** |
| * @private |
| * Masks for bits inside the 'flags' var |
| * which control what work validateNow() needs to do. |
| */ |
| private static const FLAG_TEXT_SET:uint = 1 << 6; |
| private static const FLAG_HTML_TEXT_SET:uint = 1 << 7; |
| private static const FLAG_TEXT_LINES_INVALID:uint = 1 << 8; |
| private static const FLAG_GRAPHICS_INVALID:uint = 1 << 9; |
| |
| /** |
| * @private |
| * Masks for bits inside the 'flags' var |
| * tracking misc boolean variables. |
| */ |
| private static const FLAG_EFFECTIVE_CONDENSE_WHITE:uint = 1 << 10; |
| private static const FLAG_VALIDATE_IN_PROGRESS:uint = 1 << 11; |
| private static const FLAG_HAS_SCROLL_RECT:uint = 1 << 12; |
| |
| // TODO (gosmith): Does TextField maintain |
| // an internal vs. external concept of scrollRect? |
| |
| /** |
| * @private |
| */ |
| private static const ALL_INVALIDATION_FLAGS:uint = |
| FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID; |
| |
| /** |
| * @private |
| * If htmlText is set, composeHtmlText is called each time the text lines |
| * are invalidated. The setters for many of the properties invalidate |
| * the text lines. So although _htmlText is set to null, if there is no |
| * styleSheet, to indicate to the htmlText getter that it needs to import |
| * the html from the textFlow, we need the orginal htmlText for the cases |
| * where we need to regenerate the html text lines. |
| */ |
| private var explicitHTMLText:String = null; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Used for initializing _defaultTextFormat. |
| */ |
| private static var textField:TextField = new TextField(); |
| |
| /** |
| * @private |
| */ |
| private static var plainTextImporter:ITextImporter; |
| |
| /** |
| * @private |
| */ |
| private static var plainTextExporter:ITextExporter; |
| |
| /** |
| * @private |
| */ |
| private static var collapsingHTMLImporter:ITextImporter; |
| |
| /** |
| * @private |
| */ |
| private static var preservingHTMLImporter:ITextImporter; |
| |
| /** |
| * @private |
| */ |
| private static var htmlExporter:ITextExporter; |
| |
| /** |
| * @private |
| */ |
| private static var factory:TextFlowTextLineFactory = |
| new TextFlowTextLineFactory(); |
| |
| // We can re-use single instances of a few FTE classes over and over, |
| // since they just serve as a factory for the TextLines that we care about. |
| |
| /** |
| * @private |
| */ |
| private static var staticTextBlock:TextBlock = new TextBlock(); |
| |
| /** |
| * @private |
| */ |
| private static var staticTextElement:TextElement = new TextElement(); |
| |
| /** |
| * @private |
| */ |
| private static var staticSpaceJustifier:SpaceJustifier = |
| new SpaceJustifier(); |
| |
| /** |
| * @private |
| * A reference to the recreateTextLine() method in staticTextBlock, |
| * if it exists. This method was added in player 10.1. |
| * It allows better performance by making it possible to reuse |
| * existing TextLines instead of having to create new ones. |
| */ |
| private static var recreateTextLine:Function; |
| |
| /** |
| * @private |
| * This is the max textLine.x + textLine.textWidth of all the composed |
| * lines. It is used to determine whether the text must be clipped. |
| */ |
| private var clipWidth:Number; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private static function rint(x:Number):Number |
| { |
| var i:Number = Math.round(x); |
| if (i - 0.5 == x && i & 1) |
| --i; |
| return i; |
| } |
| |
| /** |
| * @private |
| */ |
| private static function cloneTextFormat( |
| textFormat:TextFormat):TextFormat |
| { |
| var newTextFormat:TextFormat = new TextFormat( |
| textFormat.font, textFormat.size, textFormat.color, |
| textFormat.bold, textFormat.italic, textFormat.underline, |
| textFormat.url, textFormat.target, textFormat.align, |
| textFormat.leftMargin, textFormat.rightMargin, textFormat.indent, |
| textFormat.leading); |
| |
| newTextFormat.blockIndent = textFormat.blockIndent; |
| newTextFormat.bullet = textFormat.bullet; |
| newTextFormat.kerning = textFormat.kerning; |
| newTextFormat.letterSpacing = textFormat.letterSpacing; |
| newTextFormat.tabStops = textFormat.tabStops; |
| |
| return newTextFormat; |
| } |
| |
| /** |
| * @private |
| */ |
| private static function applyTextFormat(src:TextFormat, dst:TextFormat):void |
| { |
| if (src.align != null) |
| dst.align = src.align; |
| |
| if (src.blockIndent != null) |
| dst.blockIndent = src.blockIndent; |
| |
| if (src.bold != null) |
| dst.bold = src.bold; |
| |
| if (src.bullet != null) |
| dst.bullet = src.bullet; |
| |
| if (src.color != null) |
| dst.color = src.color; |
| |
| if (src.font != null) |
| dst.font = src.font; |
| |
| if (src.indent != null) |
| dst.indent = src.indent; |
| |
| if (src.italic != null) |
| dst.italic = src.italic; |
| |
| if (src.kerning != null) |
| dst.kerning != src.kerning; |
| |
| if (src.leading != null) |
| dst.leading = src.leading; |
| |
| if (src.leftMargin != null) |
| dst.leftMargin = src.leftMargin; |
| |
| if (src.letterSpacing != null) |
| dst.letterSpacing = src.letterSpacing; |
| |
| if (src.rightMargin != null) |
| dst.rightMargin = src.rightMargin; |
| |
| if (src.size != null) |
| dst.size = src.size; |
| |
| if (src.tabStops != null) |
| dst.tabStops = src.tabStops; |
| |
| if (src.target != null) |
| dst.target = src.target; |
| |
| if (src.underline != null) |
| dst.underline = src.underline; |
| |
| if (src.url != null) |
| dst.url = src.url; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function FTETextField41() |
| { |
| super(); |
| |
| // The mouse should not be aware of the TextLines. |
| // Otherwise, FTETextField will dispatch mouseOver and mouseOut |
| // events over each line, thich TextField doesn't do. |
| mouseChildren = false; |
| |
| // Use a static TextField to initialize the defaultTextFormat. |
| // This should be faster than creating a TextFormat object |
| // and filling it out. |
| // It will also take care of setting the 'font' field, |
| // which is platform-dependent. |
| _defaultTextFormat = textField.defaultTextFormat; |
| |
| addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Apps are likely to create thousands of instances of FTETextField, |
| * so in order to minimize memory usage we store flags as 1 bit |
| * inside a uint instead of making each one a 4-byte Boolean var. |
| */ |
| private var flags:uint = 0; |
| |
| /** |
| * @private |
| * When we render the text using FTE, |
| * this object represents the formatting for FTE. |
| * Every time the defaultTextFormat is set, |
| * this object is released because it is invalid. |
| * It is regenerated just in time to render the text. |
| */ |
| private var elementFormat:ElementFormat; |
| |
| /** |
| * @private |
| * When we render the htmlText using TLF, |
| * this object represents the formatting for TLF. |
| * Every time the defaultTextFormat is set, |
| * this object is released because it is invalid. |
| * It is regenerated just in time to render the htmlText. |
| */ |
| private var hostFormat:ITextLayoutFormat; |
| |
| /** |
| * @private |
| * When we render the htmlText using TLF, |
| * this object represents the rich text to be displayed. |
| * It is created by using TLF's HTML importer to import the htmlText. |
| */ |
| private var textFlow:TextFlow; |
| |
| /** |
| * @private |
| * When we render the htmlText using TLF, |
| * this object composes the textFlow |
| * (with the hostFormat applied to it) |
| * to create TextLines in this Sprite. |
| */ |
| private var textContainerManager:TextContainerManager; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden properties: DisplayObject |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // height |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _height:Number = 100; |
| |
| /** |
| * @private |
| */ |
| override public function get height():Number |
| { |
| // If we're autosizing, _height may be invalid. |
| // For example, the 'text' may have been set |
| // but the TextLines for that text haven't |
| // been created yet. |
| if (autoSize != TextFieldAutoSize.NONE) |
| validateNow(); |
| |
| return _height; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set height(value:Number):void |
| { |
| // TextField ignores NaN and negative values. |
| if (isNaN(value) || value < 0) |
| return; |
| |
| if (value == _height) |
| return; |
| |
| _height = value; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // scrollRect |
| //---------------------------------- |
| |
| /* |
| * Workaround for a Flash Player problem. |
| * Don't read the <code>scrollRect</code> property if its value has not been set, |
| * because this will cause a large memory allocation. |
| * And ignore attempts to reset the scrollRect property to null |
| * (its default value) if we've never set it. |
| */ |
| |
| /** |
| * @private |
| */ |
| override public function get scrollRect():Rectangle |
| { |
| return testFlag(FLAG_HAS_SCROLL_RECT) ? super.scrollRect : null; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set scrollRect(value:Rectangle):void |
| { |
| if (!testFlag(FLAG_HAS_SCROLL_RECT) && !value) |
| return; |
| setFlag(FLAG_HAS_SCROLL_RECT); |
| super.scrollRect = value; |
| } |
| |
| //---------------------------------- |
| // width |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _width:Number = 100; |
| |
| /** |
| * @private |
| */ |
| override public function get width():Number |
| { |
| // If we're autosizing, _width may be invalid. |
| // For example, the 'text' may have been set |
| // but the TextLines for that text haven't |
| // been created yet. |
| if (autoSize != TextFieldAutoSize.NONE) |
| validateNow(); |
| |
| return _width; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set width(value:Number):void |
| { |
| // TextField ignores NaN and negative values. |
| if (isNaN(value) || value < 0) |
| return; |
| |
| if (value == _width) |
| return; |
| |
| _width = value; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties: TextField |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // alwaysShowSelection |
| //---------------------------------- |
| |
| /** |
| * This property is not implemented in FTETextField |
| * because FTETextField does not support selection. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#alwaysShowSelection |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get alwaysShowSelection():Boolean |
| { |
| throw new Error(notImplemented("alwaysShowSelection")); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set alwaysShowSelection(value:Boolean):void |
| { |
| throw new Error(notImplemented("alwaysShowSelection")); |
| } |
| |
| //---------------------------------- |
| // antiAliasType |
| //---------------------------------- |
| |
| /** |
| * This property has no effect in FTETextField |
| * because FTE uses a newer font renderer than TextField. |
| * Getting it will always return <code>null</code> |
| * and setting it will do nothing. |
| * |
| * @see flash.text.TextField#antiAliasType |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get antiAliasType():String |
| { |
| return null; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set antiAliasType(value:String):void |
| { |
| } |
| |
| //---------------------------------- |
| // autoSize |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _autoSize:String = TextFieldAutoSize.NONE; |
| |
| /** |
| * @copy flash.text.TextField#autoSize |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get autoSize():String |
| { |
| return _autoSize; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set autoSize(value:String):void |
| { |
| // TextField throws this RTE when invalid values are set. |
| if (value != TextFieldAutoSize.NONE && |
| value != TextFieldAutoSize.LEFT && |
| value != TextFieldAutoSize.CENTER && |
| value != TextFieldAutoSize.RIGHT) |
| { |
| var message:String = getErrorMessage("badParameter", "autoSize"); |
| throw new ArgumentError(message); |
| } |
| |
| if (value == autoSize) |
| return; |
| |
| _autoSize = value; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // background |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#background |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get background():Boolean |
| { |
| return testFlag(FLAG_BACKGROUND); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set background(value:Boolean):void |
| { |
| if (value == background) |
| return; |
| |
| setFlagToValue(FLAG_BACKGROUND, value); |
| |
| // The border and background need to be redrawn. |
| setFlag(FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // backgroundColor |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _backgroundColor:uint = 0xFFFFFF; |
| |
| /** |
| * @copy flash.text.TextField#backgroundColor |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get backgroundColor():uint |
| { |
| return _backgroundColor; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set backgroundColor(value:uint):void |
| { |
| if (value == _backgroundColor) |
| return; |
| |
| _backgroundColor = value; |
| |
| // The border and background need to be redrawn. |
| setFlag(FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // border |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#border |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get border():Boolean |
| { |
| return testFlag(FLAG_BORDER); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set border(value:Boolean):void |
| { |
| if (value == border) |
| return; |
| |
| setFlagToValue(FLAG_BORDER,value); |
| |
| // The border and background need to be redrawn. |
| setFlag(FLAG_GRAPHICS_INVALID); |
| |
| // The border increases the width and height by 1 pixel, so if there |
| // is a scrollRect, it has to be modified as well. |
| if (testFlag(FLAG_TEXT_SET | FLAG_HTML_TEXT_SET)) |
| setFlag(FLAG_TEXT_LINES_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // borderColor |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _borderColor:uint = 0x000000; |
| |
| /** |
| * @copy flash.text.TextField#borderColor |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get borderColor():uint |
| { |
| return _borderColor; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set borderColor(value:uint):void |
| { |
| if (value == _borderColor) |
| return; |
| |
| _borderColor = value; |
| |
| // The border and background need to be redrawn. |
| setFlag(FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // bottomScrollV |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support scrolling. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#bottomScrollV |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get bottomScrollV():int |
| { |
| throw new Error(notImplemented("bottomScrollV")); |
| } |
| |
| //---------------------------------- |
| // caretIndex |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support editing. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#caretIndex |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get caretIndex():int |
| { |
| throw new Error(notImplemented("caretIndex")); |
| } |
| |
| //---------------------------------- |
| // condenseWhite |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#condenseWhite |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get condenseWhite():Boolean |
| { |
| return testFlag(FLAG_CONDENSE_WHITE); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set condenseWhite(value:Boolean):void |
| { |
| setFlagToValue(FLAG_CONDENSE_WHITE, value); |
| |
| // Note: There is nothing else to do immediately; |
| // the new value doesn't have any effect |
| // until 'htmlText' is set later. |
| } |
| |
| //---------------------------------- |
| // defaultTextFormat |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the defaultTextFormat property. |
| * This variable is initialized in the constructor |
| * to a TextFormat instance filled with default values. |
| * The setter applies non-null incoming formats |
| * to the object stored here. |
| * The getter returns a copy of the object stored here. |
| * Note that No field of this TextFormat will ever be null. |
| */ |
| mx_internal var _defaultTextFormat:TextFormat; |
| |
| /** |
| * @copy flash.text.TextField#defaultTextFormat |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get defaultTextFormat():TextFormat |
| { |
| // TextField returns a new TextFormat instance each time |
| // you access defaultTextFormat; the proof is that |
| // textField.defaultTextFormat != textField.defaultTextFormat |
| // is true. |
| return cloneTextFormat(_defaultTextFormat); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set defaultTextFormat(value:TextFormat):void |
| { |
| // TextField throws this RTE if a null value is set. |
| if (!value) |
| { |
| var message:String = getErrorMessage("nullParameter", "format"); |
| throw new TypeError(message); |
| } |
| |
| // Apply non-null formats in the incoming TextFormat |
| // to the defaultTextFormat. |
| applyTextFormat(value, _defaultTextFormat); |
| |
| // These FTE and TLF formatting objects are now invalid |
| // and must be recreated when needed. |
| elementFormat = null; |
| hostFormat = null; |
| |
| // Note: Setting this does NOT cause already-rendered text |
| // to change its format. |
| // If establishes the formatting for text set or added later. |
| } |
| |
| //---------------------------------- |
| // displayAsPassword |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support editing. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#displayAsPassword |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get displayAsPassword():Boolean |
| { |
| throw new Error(notImplemented("displayAsPassword")); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set displayAsPassword(value:Boolean):void |
| { |
| throw new Error(notImplemented("displayAsPassword")); |
| } |
| |
| //---------------------------------- |
| // embedFonts |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#embedFonts |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get embedFonts():Boolean |
| { |
| return testFlag(FLAG_EMBED_FONTS); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set embedFonts(value:Boolean):void |
| { |
| if (value == embedFonts) |
| return; |
| |
| setFlagToValue(FLAG_EMBED_FONTS, value); |
| |
| // These FTE and TLF formatting objects are now invalid |
| // and must be recreated when needed. |
| elementFormat = null; |
| hostFormat = null; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // gridFitType |
| //---------------------------------- |
| |
| /** |
| * This property has no effect in FTETextField |
| * because FTE uses a newer font renderer than TextField. |
| * Getting it will always return <code>null</code> |
| * and setting it will do nothing. |
| * |
| * @see flash.text.TextField#gridFitType |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get gridFitType():String |
| { |
| return null; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set gridFitType(value:String):void |
| { |
| } |
| |
| //---------------------------------- |
| // htmlText |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _htmlText:String = null; |
| |
| /** |
| * @copy flash.text.TextField#htmlText |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get htmlText():String |
| { |
| // When you set the htmlText and then get it, |
| // what you get is not necessarily what you set. |
| // The easiest way to handle this is to make sure |
| // that the text is composed (which will null out _htmlText |
| // if there is no styleSheet) and then execute the code |
| // below to export HTML from the TextFlow. |
| validateNow(); |
| |
| // When 'text' is set, _htmlText is nulled out |
| // to indicate that it is invalid |
| // and must be recalculated. |
| if (_htmlText == null) |
| { |
| // We can optimize the default case |
| // that there is no text or hmtlText. |
| if (_text == "") |
| { |
| _htmlText = ""; |
| } |
| else |
| { |
| // Import the plain text into a TextFlow, |
| // and then export the TextFlow into HTML. |
| if (!textFlow) |
| textFlow = plainTextImporter.importToFlow(_text); |
| _htmlText = String(htmlExporter.export( |
| textFlow, ConversionType.STRING_TYPE)); |
| } |
| } |
| |
| return _htmlText; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set htmlText(value:String):void |
| { |
| // TextField throws this RTE if a null value is set. |
| // It seems like this should say |
| // "Parameter htmlText must be non-null", |
| // but that's not what TextField does. |
| if (value == null) |
| { |
| var message:String = getErrorMessage("nullParameter", "text"); |
| throw new TypeError(message); |
| } |
| |
| // Note: We don't return early if value == _htmlText |
| // because the defaultTextFormat may have changed |
| // in which case we need to recompose. |
| |
| // Remember the value of condenseWhite at the time |
| // that htmlText is set, because it could be changed |
| // before the TextLines are rendered. |
| setFlagToValue(FLAG_EFFECTIVE_CONDENSE_WHITE, |
| testFlag(FLAG_CONDENSE_WHITE)); |
| |
| _htmlText = value; |
| explicitHTMLText = value; |
| |
| // _text is now invalid and will get regenerated on demand. |
| _text = null; |
| |
| clearFlag(FLAG_TEXT_SET); |
| |
| setFlag(FLAG_HTML_TEXT_SET | |
| FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| |
| // NOTE: With hmtlText, what you set is NOT what you get. |
| // You can set incomplete (or no) markup |
| // and get back complete markup. |
| } |
| |
| //---------------------------------- |
| // length |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#length |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get length():int |
| { |
| return text.length; |
| } |
| |
| //---------------------------------- |
| // maxChars |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support editing. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#maxChars |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get maxChars():int |
| { |
| throw new Error(notImplemented("maxChars")); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set maxChars(value:int):void |
| { |
| throw new Error(notImplemented("maxChars")); |
| } |
| |
| //---------------------------------- |
| // maxScrollH |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support scrolling. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#maxScrollH |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get maxScrollH():int |
| { |
| throw new Error(notImplemented("maxScrollH")); |
| } |
| |
| //---------------------------------- |
| // maxScrollV |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support scrolling. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#maxScrollV |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get maxScrollV():int |
| { |
| throw new Error(notImplemented("maxScrollV")); |
| } |
| |
| //---------------------------------- |
| // mouseWheelEnabled |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support scrolling. |
| * Getting it will always return <code>false</code> |
| * and setting it will do nothing. |
| * |
| * @see flash.text.TextField#mouseWheelEnabled |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get mouseWheelEnabled():Boolean |
| { |
| return false; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set mouseWheelEnabled(value:Boolean):void |
| { |
| } |
| |
| //---------------------------------- |
| // multiline |
| //---------------------------------- |
| |
| /** |
| * This property has no effect in FTETextField |
| * because FTETextField does not support editing. |
| * However, you can get and set it. |
| * |
| * @see flash.text.TextField#multiline |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get multiline():Boolean |
| { |
| return testFlag(FLAG_MULTILINE); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set multiline(value:Boolean):void |
| { |
| setFlagToValue(FLAG_MULTILINE, value); |
| } |
| |
| //---------------------------------- |
| // numLines |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#numLines |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get numLines():int |
| { |
| validateNow(); |
| |
| // All the of the children of this Sprite are TextLines, |
| // so the number of lines is the number of children. |
| // TextContainerManager can create Shapes as well, |
| // but only when using TLF's backgroundColor and backgroundAlpha |
| // formatting on spans, which FTETextField doesn't use. |
| return numChildren; |
| } |
| |
| //---------------------------------- |
| // restrict |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support scrolling. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#restrict |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get restrict():String |
| { |
| throw new Error(notImplemented("restrict")); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set restrict(value:String):void |
| { |
| throw new Error(notImplemented("restrict")); |
| } |
| |
| //---------------------------------- |
| // scrollH |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support scrolling. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#scrollH |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get scrollH():int |
| { |
| throw new Error(notImplemented("scrollH")); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set scrollH(value:int):void |
| { |
| throw new Error(notImplemented("scrollH")); |
| } |
| |
| //---------------------------------- |
| // scrollV |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support scrolling. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#scrollV |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get scrollV():int |
| { |
| throw new Error(notImplemented("scrollV")); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set scrollV(value:int):void |
| { |
| throw new Error(notImplemented("scrollV")); |
| } |
| |
| //---------------------------------- |
| // selectable |
| //---------------------------------- |
| |
| /** |
| * Setting this property has no effect in FTETextField |
| * because FTETextField does not support selection. |
| * If you get it, it will always be <code>false</code>. |
| * |
| * @see flash.text.TextField#selectable |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get selectable():Boolean |
| { |
| return false; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set selectable(value:Boolean):void |
| { |
| } |
| |
| //---------------------------------- |
| // selectionBeginIndex |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support selection. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#selectionBeginIndex |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get selectionBeginIndex():int |
| { |
| throw new Error(notImplemented("selectionBeginIndex")); |
| } |
| |
| //---------------------------------- |
| // selectionEndIndex |
| //---------------------------------- |
| |
| /** |
| * This property has not been implemented in FTETextField |
| * because FTETextField does not support selection. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#selectionEndIndex |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get selectionEndIndex():int |
| { |
| throw new Error(notImplemented("selectionEndIndex")); |
| } |
| |
| //---------------------------------- |
| // sharpness |
| //---------------------------------- |
| |
| /** |
| * This property has no effect in FTETextField. |
| * because FTE uses a newer font renderer than TextField. |
| * Getting it will always return <code>NaN</code> |
| * and setting it will do nothing. |
| * |
| * @see flash.text.TextField#sharpness |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get sharpness():Number |
| { |
| return NaN; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set sharpness(value:Number):void |
| { |
| } |
| |
| //---------------------------------- |
| // styleSheet |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _styleSheet:StyleSheet = null; |
| |
| /** |
| * @copy flash.text.TextField#styleSheet |
| * |
| * @see flash.text.StyleSheet |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get styleSheet():StyleSheet |
| { |
| // Note: TextField does NOT return a copy of the StyleSheet. |
| return _styleSheet; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set styleSheet(value:StyleSheet):void |
| { |
| // TextField allows a null value to be set; |
| // in fact, this is the default. |
| |
| // Note: We don't return early if value == _styleSheet |
| // because the same StyleSheet instance could be coming |
| // in again but might have new values in it. |
| |
| _styleSheet = value; |
| |
| if (textFlow && textFlow.formatResolver) |
| textFlow.formatResolver = null; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // text |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _text:String = ""; |
| |
| /** |
| * @copy flash.text.TextField#text |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get text():String |
| { |
| // When 'htmlText' is set, _text is nulled out |
| // to indicate that it is invalid |
| // and must be rexported from the TextFlow. |
| if (_text == null) |
| { |
| // If we don't already have a TextFlow, |
| // create one by importing the htmlText. |
| if (!textFlow) |
| textFlow = htmlImporter.importToFlow(_htmlText); |
| |
| // Export plain text from the TextFlow. |
| _text = String(plainTextExporter.export( |
| textFlow, ConversionType.STRING_TYPE)); |
| |
| // Convert the LF characters that TLF exports |
| // into CR characters. |
| _text = _text.replace(ALL_LINEFEEDS, "\r"); |
| } |
| |
| return _text; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set text(value:String):void |
| { |
| // TextField throws this RTE if a null value is set. |
| if (value == null) |
| { |
| var message:String = getErrorMessage("nullParameter", "text"); |
| throw new TypeError(message); |
| } |
| |
| // Note: We don't return early if value == _text |
| // because the defaultTextFormat may have changed |
| // in which case we need to recompose. |
| |
| // TextField turns all LF characters into CR characters, |
| // including treating the Windows line-ending-sequence |
| // CR+LF as two CRs. |
| _text = value.replace(ALL_LINEFEEDS, "\r"); |
| |
| // _htmlText is now invalid and will get regenerated on demand |
| _htmlText = null; |
| explicitHTMLText = null; |
| |
| clearFlag(FLAG_HTML_TEXT_SET); |
| |
| setFlag(FLAG_TEXT_SET | |
| FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // textColor |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#textColor |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get textColor():uint |
| { |
| // textColor is not an independent format in TextField; |
| // getting textColor simply returns the color |
| // in the defaultTextFormat. |
| return uint(_defaultTextFormat.color); |
| } |
| |
| /** |
| * @private |
| * Setting the textColor changes the color in the defaultTextFormat |
| * and redraws the text in the new color. |
| */ |
| public function set textColor(value:uint):void |
| { |
| if (value == textColor) |
| return; |
| |
| _defaultTextFormat.color = value; |
| |
| // These FTE and TLF formatting objects are now invalid |
| // and must be recreated when needed. |
| elementFormat = null; |
| hostFormat = null; |
| |
| setFlag(FLAG_TEXT_LINES_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // textHeight |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _textHeight:Number = 0; |
| |
| /** |
| * @copy flash.text.TextField#textHeight |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get textHeight():Number |
| { |
| validateNow(); |
| |
| return _textHeight; |
| } |
| |
| //---------------------------------- |
| // textWidth |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _textWidth:Number = 0; |
| |
| /** |
| * @copy flash.text.TextField#textWidth |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get textWidth():Number |
| { |
| validateNow(); |
| |
| return _textWidth; |
| } |
| |
| //---------------------------------- |
| // thickness |
| //---------------------------------- |
| |
| /** |
| * This property has no effect in FTETextField |
| * because FTE uses a newer font renderer than TextField. |
| * Getting it will always return <code>NaN</code> |
| * and setting it will do nothing. |
| * |
| * @see flash.text.TextField#thickness |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get thickness():Number |
| { |
| return NaN; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set thickness(value:Number):void |
| { |
| } |
| |
| //---------------------------------- |
| // type |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#type |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get type():String |
| { |
| return TextFieldType.DYNAMIC; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set type(value:String):void |
| { |
| var message:String; |
| |
| // TextField throws this RTE when invalid values are set. |
| if (value != TextFieldType.DYNAMIC && |
| value != TextFieldType.INPUT) |
| { |
| message = getErrorMessage("badParameter", "type"); |
| throw new ArgumentError(message); |
| } |
| |
| if (value == TextFieldType.INPUT) |
| { |
| message = getErrorMessage("unsupportedTypeInFTETextField"); |
| throw new Error(message); |
| } |
| } |
| |
| //---------------------------------- |
| // useRichTextClipboard |
| //---------------------------------- |
| |
| /** |
| * This property is not implemented in FTETextField |
| * because FTETextField does not support selection |
| * or clipboard operations. |
| * Accessing it will throw a runtime error. |
| * |
| * @see flash.text.TextField#useRichTextClipboard |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get useRichTextClipboard():Boolean |
| { |
| throw new Error(notImplemented("useRichTextClipboard")); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set useRichTextClipboard(value:Boolean):void |
| { |
| throw new Error(notImplemented("useRichTextClipboard")); |
| } |
| |
| //---------------------------------- |
| // wordWrap |
| //---------------------------------- |
| |
| /** |
| * @copy flash.text.TextField#wordWrap |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get wordWrap():Boolean |
| { |
| return testFlag(FLAG_WORD_WRAP); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set wordWrap(value:Boolean):void |
| { |
| if (value == wordWrap) |
| return; |
| |
| setFlagToValue(FLAG_WORD_WRAP, value); |
| |
| // These FTE and TLF formatting objects are now invalid |
| // and must be recreated when needed. |
| elementFormat = null; |
| hostFormat = null; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // direction |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the direction property. |
| */ |
| private var _direction:String = "ltr"; |
| |
| /** |
| * The directionality of the text displayed by the FTETextField. |
| * |
| * <p>The allowed values are <code>"ltr"</code> for left-to-right text, |
| * as in Latin-style scripts, |
| * and <code>"rtl"</code> for right-to-left text, |
| * as in Arabic and Hebrew.</p> |
| * |
| * <p><strong>Note:</strong> This property does not exist in the |
| * flash.text.TextField API.</p> |
| * |
| * @default "ltr" |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get direction():String |
| { |
| return _direction; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set direction(value:String):void |
| { |
| if (value != "ltr" && value != "rtl") |
| { |
| var message:String = getErrorMessage("badParameter", "direction"); |
| throw new ArgumentError(message); |
| } |
| |
| if (value == _direction) |
| return; |
| |
| _direction = value; |
| |
| // These FTE and TLF formatting objects are now invalid |
| // and must be recreated when needed. |
| elementFormat = null; |
| hostFormat = null; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // fontContext |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the fontContext property. |
| */ |
| private var _fontContext:ISWFContext; |
| |
| /** |
| * The ISWFContext instance that FTETextField |
| * uses for creating TextLine objects. |
| * |
| * <p>Set this if you need lines to be created in a different |
| * SWF context than the one containing the TLF code.</p> |
| * |
| * <p><strong>Note:</strong> This property does not exist in the |
| * flash.text.TextField API.</p> |
| * |
| * @default null |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get fontContext():ISWFContext |
| { |
| return _fontContext; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set fontContext(value:ISWFContext):void |
| { |
| // FTETextField allows a null value to be set; |
| // in fact, this is the default. |
| |
| if (value == _fontContext) |
| return; |
| |
| _fontContext = value; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //---------------------------------- |
| // locale |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the locale property. |
| */ |
| private var _locale:String = "en"; |
| |
| /** |
| * The locale of the text displayed by FTETextField. |
| * |
| * <p>FTE and TLF use this locale to map Unicode characters |
| * to font glyphs and to find fallback fonts.</p> |
| */ |
| public function get locale():String |
| { |
| return _locale; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set locale(value:String):void |
| { |
| if (value == _locale) |
| return; |
| |
| _locale = value; |
| |
| // These FTE and TLF formatting objects are now invalid |
| // and must be recreated when needed. |
| elementFormat = null; |
| hostFormat = null; |
| |
| // The TextLines may need to be recreated |
| // and the border and background may need to be redrawn. |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties: Private helpers |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // htmlImporter |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private function get htmlImporter():ITextImporter |
| { |
| // Note that which importer we return depends on the value |
| // of condenseWhite was at the time that htmlText was set, |
| // not on the current value of condenseWhite, |
| // since it could change between htmlText being set |
| // and the TextLines being composed. |
| return testFlag(FLAG_EFFECTIVE_CONDENSE_WHITE) ? |
| collapsingHTMLImporter : |
| preservingHTMLImporter; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods: TextField |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param newText n/a |
| * |
| * @see flash.text.TextField#appendText() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function appendText(newText:String):void |
| { |
| throw new Error(notImplemented("appendText()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param charIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getCharBoundaries() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getCharBoundaries(charIndex:int):Rectangle |
| { |
| throw new Error(notImplemented("getCharBoundaries()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param x n/a |
| * @param y n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getCharIndexAtPoint() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getCharIndexAtPoint(x:Number, y:Number):int |
| { |
| throw new Error(notImplemented("getCharIndexAtPoint()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param charIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getFirstCharInParagraph() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getFirstCharInParagraph(charIndex:int):int |
| { |
| throw new Error(notImplemented("getFirstCharInParagraph()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param x n/a |
| * |
| * @param y n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getLineIndexAtPoint() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getLineIndexAtPoint(x:Number, y:Number):int |
| { |
| throw new Error(notImplemented("getLineIndexAtPoint()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param charIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getLineIndexOfChar() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getLineIndexOfChar(charIndex:int):int |
| { |
| throw new Error(notImplemented("getLineIndexOfChar()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param lineIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getLineLength() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getLineLength(lineIndex:int):int |
| { |
| throw new Error(notImplemented("getLineLength()")); |
| } |
| |
| /** |
| * @copy flash.text.TextField#getLineMetrics() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getLineMetrics(lineIndex:int):TextLineMetrics |
| { |
| validateNow(); |
| |
| // TextField throws this RTE when invalid values are set. |
| if (lineIndex < 0 || lineIndex >= numChildren) |
| { |
| var message:String = getErrorMessage("badIndex"); |
| throw new RangeError(message); |
| } |
| |
| // The nth line is the nth child. |
| var textLine:TextLine = TextLine(getChildAt(lineIndex)); |
| |
| // Convert textLine.x to the global coordinate space. The new point |
| // x is relative to textLine.x. |
| var x:Number = Math.round(textLine.localToGlobal(new Point(0, 0)).x); |
| var width:Number = Math.round(textLine.textWidth); |
| |
| // TextField computes ascent and descent differently than FTE does. |
| // Adding FTE's ascent and descent produces |
| // a reasonable approximation of TextField's ascent. |
| // TextField's ascent, descent, and leading are always rounded. |
| // Rounding FTE's ascent and descent separately, then adding, |
| // produces a "TextField ascent" of 12 + 3 or 15 for Arial 12 |
| // (Flex's default font) on Windows, exactly matching a real |
| // TextField's ascent in this most-common case. |
| var ascent:Number = Math.round(textLine.ascent) + Math.round(textLine.descent) |
| var descent:Number = Math.round(textLine.descent); |
| var leading:Number = Math.round(Number(_defaultTextFormat.leading)); |
| |
| var height:Number = ascent + descent + leading; |
| |
| return new TextLineMetrics(x, width, height, ascent, descent, leading); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param lineIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getLineOffset() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getLineOffset(lineIndex:int):int |
| { |
| throw new Error(notImplemented("getLineOffset()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param lineIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getLineText() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getLineText(lineIndex:int):String |
| { |
| throw new Error(notImplemented("getLineText()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param charIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getParagraphLength() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getParagraphLength(charIndex:int):int |
| { |
| throw new Error(notImplemented("getParagraphLength()")); |
| } |
| |
| /** |
| * This method has been implemented in FTETextField |
| * to simply return a copy of the <code>defaultTextFormat</code>, |
| * because FTETextField does not support formatting a range. |
| * |
| * @param beginIndex n/a |
| * |
| * @param endIndex n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getTextFormat() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getTextFormat(beginIndex:int = -1, |
| endIndex:int = -1):TextFormat |
| { |
| // TextField returns a new TextFormat instance each time |
| // you call getTextFormat(); the proof is that |
| // textField.getTextFormat() != textField.getTextFormat() |
| // is true. |
| return cloneTextFormat(_defaultTextFormat); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param value n/a |
| * |
| * @see flash.text.TextField#replaceSelectedText() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function replaceSelectedText(value:String):void |
| { |
| throw new Error(notImplemented("replaceSelectedText()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param beginIndex n/a |
| * |
| * @param endIndex n/a |
| * |
| * @param newText n/a |
| * |
| * @see flash.text.TextField#replaceText() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function replaceText(beginIndex:int, endIndex:int, |
| newText:String):void |
| { |
| throw new Error(notImplemented("replaceText()")); |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because FTETextField does not support selection. |
| * It will throw a runtime error if called. |
| * |
| * @param beginIndex n/a |
| * |
| * @param endIndex n/a |
| * |
| * @see flash.text.TextField#setSelection() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function setSelection(beginIndex:int, endIndex:int):void |
| { |
| throw new Error(notImplemented("setSelection()")); |
| } |
| |
| /** |
| * This method has no effect on a FTETextField if <code>beginIndex</code> |
| * or <code>endIndex</code> does not equal -1 |
| * because FTETextField does not support formatting a range. |
| * |
| * @param format n/a |
| * |
| * @param beginIndex n/a |
| * |
| * @param endIndex n/a |
| * |
| * @see flash.text.TextField#setTextFormat() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function setTextFormat(format:TextFormat, |
| beginIndex:int = -1, |
| endIndex:int = -1):void |
| { |
| if (beginIndex == -1 && endIndex == -1) |
| { |
| defaultTextFormat = format; |
| |
| // The format changed. Some of the attributes such as indent |
| // and blockIndent require the text to be regenerated. |
| setFlag(FLAG_TEXT_LINES_INVALID | FLAG_GRAPHICS_INVALID); |
| |
| validateNow(); |
| } |
| } |
| |
| /** |
| * This method has not been implemented in FTETextField |
| * because very few components use it in TextField. |
| * It will throw a runtime error if called. |
| * |
| * @param id n/a |
| * |
| * @return n/a |
| * |
| * @see flash.text.TextField#getImageReference() |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function getImageReference(id:String):DisplayObject |
| { |
| throw new Error(notImplemented("getImageReference()")); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private function testFlag(mask:uint):Boolean |
| { |
| return (flags & mask) != 0; |
| } |
| |
| /** |
| * @private |
| */ |
| private function setFlag(mask:uint):void |
| { |
| flags |= mask; |
| } |
| |
| /** |
| * @private |
| */ |
| private function clearFlag(mask:uint):void |
| { |
| flags &= ~mask; |
| } |
| |
| /** |
| * @private |
| */ |
| private function setFlagToValue(mask:uint, value:Boolean):void |
| { |
| if (value) |
| flags |= mask; |
| else |
| flags &= ~mask; |
| } |
| |
| /** |
| * @private |
| * This method will cause a 'render' event later, |
| * in response to which validateNow() will get called. |
| */ |
| private function invalidate():void |
| { |
| if (stage) |
| stage.invalidate(); |
| |
| addEventListener(Event.RENDER, renderHandler); |
| } |
| |
| /** |
| * @private |
| * This method is the workhorse of FTETextField. |
| * It puts it into a state where all properties are consistent |
| * with each other and where it is rendering what the properties |
| * specify. |
| */ |
| private function validateNow():void |
| { |
| // TODO (gosmith): When do we get recursive validateNow()? |
| if (!testFlag(ALL_INVALIDATION_FLAGS) || |
| testFlag(FLAG_VALIDATE_IN_PROGRESS)) |
| { |
| return; |
| } |
| |
| setFlag(FLAG_VALIDATE_IN_PROGRESS); |
| |
| if (testFlag(FLAG_TEXT_LINES_INVALID)) |
| { |
| // Remove the previous TextLines |
| // (and recycle them, if supported by the player). |
| removeTextLines(); |
| |
| // Determine the composition width and height. |
| var compositionWidth:Number = NaN; |
| var compositionHeight:Number = NaN; |
| if (_autoSize == TextFieldAutoSize.NONE) |
| { |
| compositionWidth = _width; |
| compositionHeight = _height; |
| } |
| else if (wordWrap) |
| { |
| compositionWidth = _width; |
| } |
| |
| if (testFlag(FLAG_HTML_TEXT_SET)) |
| { |
| if (!hostFormat) |
| createHostFormat(); |
| |
| composeHTMLText(compositionWidth, compositionHeight); |
| } |
| else |
| { |
| if (!elementFormat) |
| createElementFormat(); |
| |
| composeText(compositionWidth, compositionHeight); |
| } |
| |
| var origX:Number = x; |
| var origWidth:Number = _width; |
| var origHeight:Number = _height; |
| |
| if (_autoSize != TextFieldAutoSize.NONE) |
| { |
| _height = _textHeight + PADDING_TOP + PADDING_BOTTOM; |
| if (!wordWrap) |
| { |
| _width = _textWidth + PADDING_LEFT + PADDING_RIGHT; |
| |
| var blockIndent:Number = Number(_defaultTextFormat.blockIndent); |
| var indent:Number = Number(_defaultTextFormat.indent); |
| var leftMargin:Number = Number(_defaultTextFormat.leftMargin); |
| var rightMargin:Number = Number(_defaultTextFormat.rightMargin); |
| |
| // Factor in indents and margins if the combined total |
| // is positive. |
| if (blockIndent + indent + leftMargin > 0) |
| _width += blockIndent + indent + leftMargin; |
| |
| // Right margin seems to always be considered but if its |
| // negative the width can't get smaller than the text width. |
| _width += rightMargin; |
| if (rightMargin > 0) |
| { |
| clipWidth = _width; |
| } |
| else |
| { |
| if (_width - PADDING_LEFT - PADDING_RIGHT < _textWidth ) |
| _width = _textWidth + PADDING_LEFT + PADDING_RIGHT; |
| // force clipping |
| clipWidth = origWidth + 1; |
| } |
| |
| // adjust x for CENTER and RIGHT cases |
| if (_autoSize == TextFieldAutoSize.RIGHT) |
| x += origWidth - _width; |
| else if (_autoSize == TextFieldAutoSize.CENTER) |
| x += (origWidth - _width) / 2; |
| } |
| if (_height != origHeight || _width != origWidth || x != origX) |
| setFlag(FLAG_GRAPHICS_INVALID); |
| } |
| |
| if (clipWidth > origWidth || _textHeight > origHeight) |
| { |
| // need to clip |
| //trace("clip", "_textWidth", _textWidth, "origWidth", origWidth); |
| var r:Rectangle = scrollRect; |
| if (!r) |
| r = new Rectangle(); |
| r.left = 0; |
| r.top = 0; |
| r.right = _width; |
| r.bottom = _height; |
| |
| // Expand scrollRect by one pixel so the bottom and right |
| // borders are not cliped. See note below. |
| if (testFlag(FLAG_GRAPHICS_INVALID) && border) |
| { |
| r.width++; |
| r.height++; |
| } |
| |
| scrollRect = r; |
| } |
| else |
| { |
| // don't need to clip |
| //trace("don't clip", "_textWidth", _textWidth, "origWidth", origWidth); |
| scrollRect = null; |
| } |
| } |
| |
| // Draw the border and background last, |
| // once the width and height are known. |
| if (testFlag(FLAG_GRAPHICS_INVALID)) |
| { |
| var g:Graphics = graphics; |
| g.clear(); |
| // First draw the background, then draw the border. |
| // This is because TextField actually does something strange --- it expands itselft 1 pixel right and down when drawing a border |
| // and fill without the stroke with the required stroking path does not match the "background sans border" behavior of TextField. |
| |
| // Width/Height rounding differences between TextField and FTETextField... |
| // For width or height of the form E.5 where E is a positive even integer, Flash 10 on Windows seems to |
| // "round to even", i.e., round the dimension down to E rather than up to E+1. However we currently just |
| // round consistently up to E+1 using Math.round() here since for now are willing to live with this difference. |
| var w:Number = rint(_width); |
| var h:Number = rint(_height); |
| |
| // Even if no background is requested, we fill the bounds |
| // with alpha=0 pixels so that mouse events are generated. |
| g.beginFill(backgroundColor, background ? 1.0 : 0.0); |
| g.drawRect(0, 0, w, h); |
| g.endFill(); |
| |
| if (border) |
| { |
| g.lineStyle(1, borderColor); |
| g.drawRect(0.5, 0.5, _width, _height); // TextField actually expands by a pixel down and to the right when it has a border! |
| } |
| } |
| |
| clearFlag(ALL_INVALIDATION_FLAGS | FLAG_VALIDATE_IN_PROGRESS); |
| } |
| |
| /** |
| * @private |
| */ |
| private function createElementFormat():void |
| { |
| var fontDescription:FontDescription = new FontDescription(); |
| |
| fontDescription.fontLookup = embedFonts ? |
| FontLookup.EMBEDDED_CFF : |
| FontLookup.DEVICE; |
| |
| fontDescription.fontName = _defaultTextFormat.font; |
| |
| fontDescription.fontPosture = _defaultTextFormat.italic ? |
| FontPosture.ITALIC : |
| FontPosture.NORMAL; |
| |
| fontDescription.fontWeight = _defaultTextFormat.bold ? |
| FontWeight.BOLD : |
| FontWeight.NORMAL; |
| |
| elementFormat = new ElementFormat(); |
| |
| elementFormat.color = uint(_defaultTextFormat.color); |
| |
| elementFormat.fontDescription = fontDescription; |
| |
| elementFormat.fontSize = Number(_defaultTextFormat.size); |
| |
| elementFormat.kerning = _defaultTextFormat.kerning ? |
| Kerning.AUTO : |
| Kerning.OFF; |
| |
| elementFormat.locale = locale; |
| |
| elementFormat.trackingRight = Number(_defaultTextFormat.letterSpacing); |
| } |
| |
| /** |
| * @private |
| */ |
| private function createHostFormat():void |
| { |
| hostFormat = new FTETextFieldHostFormat(this); |
| } |
| |
| /** |
| * @private |
| */ |
| private function removeTextLines():void |
| { |
| var n:int = numChildren; |
| for (var i:int = 0; i < n; i++) |
| { |
| // Repeatedly removing the 0th child is supposed |
| // to be the fastest way to remove all children. |
| var textLine:TextLine = TextLine(removeChildAt(0)); |
| |
| // TLF provides a TextLine cache, |
| // for use with recreateTextLine(). |
| TextLineRecycler.addLineForReuse(textLine); |
| } |
| |
| _textWidth = 0; |
| _textHeight = 0; |
| clipWidth = 0; |
| } |
| |
| /** |
| * @private |
| */ |
| private function composeText(compositionWidth:Number, |
| compositionHeight:Number):void |
| { |
| var innerWidth:Number = |
| compositionWidth - PADDING_LEFT - PADDING_RIGHT; |
| var innerHeight:Number = |
| compositionHeight - PADDING_TOP - PADDING_BOTTOM; |
| |
| // FTE's emBox's top gives the ascent and its bottom gives the descent. |
| // TextField computes ascent and descent differently than FTE does. |
| // Adding FTE's ascent and descent produces |
| // a reasonable approximation of TextField's ascent. |
| // TextField's ascent, descent, and leading are always rounded. |
| // Rounding FTE's ascent and descent separately, then adding, |
| // produces a "TextField ascent" of 12 + 3 or 15 for Arial 12 |
| // (Flex's default font) on Windows, exactly matching a real |
| // TextField's ascent in this most-common case. |
| var emBox:Rectangle = elementFormat.getFontMetrics().emBox; |
| var ascent:int = Math.round(-emBox.top) + Math.round(emBox.bottom); |
| var descent:int = Math.round(emBox.bottom); |
| var leading:Number = Math.round(Number(_defaultTextFormat.leading)); |
| |
| // Break the text into paragraphs at CR characters. |
| // (Each LF character has already been turned into a CR.) |
| // We could use split(), but that would create a temporary Array. |
| var paragraphY:int = 0; |
| var n:int = text.length; |
| var i:int = 0; |
| do |
| { |
| var j:int = text.indexOf("\r", i); |
| if (j == -1) |
| j = n; |
| var paragraphText:String = i == 0 && j == n ? |
| text : |
| text.substring(i, j); |
| |
| // Use an FTE TextBlock to compose TextLines |
| // for one paragraph of the text, keeping track |
| // of how far down we've composed. |
| paragraphY = createTextLines(innerWidth, innerHeight, |
| paragraphText, paragraphY, |
| ascent, descent); |
| |
| // TextField puts the same leading between paragraphs |
| // as between lines in a paragraph. |
| paragraphY += leading; |
| |
| i = j + 1; |
| } |
| while (j < n); |
| |
| // At this point, all TextLines have been composed |
| // and have the correct spacing, but are all left-aligned |
| // starting at (0, 0). |
| // This method will adjust their x and y so that they |
| // are correctly aligned and inset by the left and top padding and |
| // indent and margins. |
| alignTextLines(innerWidth); |
| |
| _textWidth = Math.round(_textWidth); |
| _textHeight = Math.round( |
| numChildren * (ascent + descent) + |
| (numChildren - 1) * Number(_defaultTextFormat.leading)); |
| |
| clipWidth = Math.round(clipWidth); |
| } |
| |
| /** |
| * @private |
| * Stuffs the specified paragraph text and formatting info into a TextBlock |
| * and uses it to create as many TextLines as fit into the bounds. |
| * Returns true if all the text was composed into textLines. |
| */ |
| private function createTextLines(innerWidth:Number, |
| innerHeight:Number, |
| paragraphText:String, |
| paragraphY:int, |
| ascent:int, descent:int):int |
| { |
| // Set the TextBlock's content. |
| // Note: If there is no text, we do what TLF does and compose |
| // a paragraph terminator character, so that a TextLine |
| // gets created and we can measure it. |
| // It will have a width of 0 but a height equal |
| // to the font's ascent plus descent. |
| staticTextElement.text = paragraphText.length > 0 ? |
| paragraphText : |
| "\u2029"; |
| staticTextElement.elementFormat = elementFormat; |
| staticTextBlock.content = staticTextElement; |
| |
| // And its bidiLevel. |
| staticTextBlock.bidiLevel = direction == "ltr" ? 0 : 1; |
| |
| // And its justifier. |
| staticSpaceJustifier.lineJustification = |
| _defaultTextFormat.align == "justify" ? |
| LineJustification.ALL_BUT_LAST : |
| LineJustification.UNJUSTIFIED;; |
| staticTextBlock.textJustifier = staticSpaceJustifier; |
| |
| // Then create and add TextLines using this TextBlock. |
| paragraphY = createTextLinesFromTextBlock( |
| innerWidth, innerHeight, |
| staticTextBlock, paragraphY, |
| ascent, descent); |
| |
| // Cleans up and sets the validity of the lines associated |
| // with the TextBlock to TextLineValidity.INVALID. |
| var firstLine:TextLine = staticTextBlock.firstLine; |
| var lastLine:TextLine = staticTextBlock.lastLine; |
| if (firstLine) |
| staticTextBlock.releaseLines(firstLine, lastLine); |
| |
| return paragraphY; |
| } |
| |
| /** |
| * @private |
| * Compose into textLines. bounds on input is size of composition |
| * area and on output is the size of the composed content. |
| * The caller must call releaseLinesFromTextBlock() to release the |
| * textLines from the TextBlock. |
| * |
| * Returns true if all the text was composed into textLines. |
| */ |
| private function createTextLinesFromTextBlock(innerWidth:Number, |
| innerHeight:Number, |
| textBlock:TextBlock, |
| paragraphY:int, |
| ascent:int, |
| descent:int):int |
| { |
| if (innerWidth < 0 || innerHeight < 0) |
| return paragraphY; |
| |
| var blockIndent:Number = Number(_defaultTextFormat.blockIndent); |
| var indent:Number = Number(_defaultTextFormat.indent); |
| var leftMargin:Number = Number(_defaultTextFormat.leftMargin); |
| var rightMargin:Number = Number(_defaultTextFormat.rightMargin); |
| |
| var maxLineWidthBeforeIndent:Number = |
| wordWrap ? innerWidth : TextLine.MAX_LINE_WIDTH; |
| var maxLineWidth:Number = maxLineWidthBeforeIndent; |
| |
| var n:int = 0; |
| var nextTextLine:TextLine; |
| var nextY:int = paragraphY; |
| var textLine:TextLine; |
| |
| // TextField seems to do this. You can see it with wordWrap and |
| // indent > width or when rightMargin > width. In the former case, |
| // the first line is visually empty but contains a character which is |
| // clipped and the second line starts with the second letter. |
| // The clipped first line serves as a placeholder so that the rest |
| // of the lines which may be visible are composed. |
| var fitSomething:Boolean = true; |
| |
| // Generate TextLines, stopping when we run out of text |
| // or reach the bottom of the requested bounds. |
| // In this loop the lines are positioned within the rectangle |
| // (0, 0, innerWidth, innerHeight), with left alignment. |
| while (true) |
| { |
| // Adjust the compose width for indents and margins. |
| if (n <= 1) |
| { |
| var totalIndent:Number = blockIndent + leftMargin; |
| if (n == 0) |
| totalIndent += indent; |
| |
| if (totalIndent < 0) |
| totalIndent = 0; |
| else if (totalIndent > _width - PADDING_LEFT - PADDING_RIGHT) |
| totalIndent = _width - PADDING_LEFT - PADDING_RIGHT; |
| |
| if (!wordWrap) |
| rightMargin = 0; |
| |
| maxLineWidth = |
| maxLineWidthBeforeIndent - totalIndent - rightMargin; |
| |
| // Stay within the bounds to avoid exception. Since |
| // fitSomething is true it is okay if maxLineWidth is < 0. |
| if (maxLineWidth > TextLine.MAX_LINE_WIDTH) |
| maxLineWidth = TextLine.MAX_LINE_WIDTH; |
| } |
| |
| var recycleLine:TextLine = TextLineRecycler.getLineForReuse(); |
| if (recycleLine) |
| { |
| if (fontContext) |
| { |
| nextTextLine = fontContext.callInContext( |
| textBlock["recreateTextLine"], textBlock, |
| [ recycleLine, textLine, maxLineWidth, 0.0, fitSomething ]); |
| } |
| else |
| { |
| nextTextLine = recreateTextLine( |
| recycleLine, textLine, maxLineWidth, 0.0, fitSomething); |
| } |
| } |
| else |
| { |
| if (fontContext) |
| { |
| nextTextLine = fontContext.callInContext( |
| textBlock.createTextLine, textBlock, |
| [ textLine, maxLineWidth, 0.0, fitSomething ]); |
| } |
| else |
| { |
| nextTextLine = textBlock.createTextLine( |
| textLine, maxLineWidth, 0.0, fitSomething); |
| } |
| } |
| |
| if (!nextTextLine) |
| break; |
| |
| // Determine the natural baseline position for this line. |
| // Note: The y coordinate of a TextLine is the location |
| // of its baseline, not of its "top". |
| if (n == 0) |
| nextY += ascent; |
| else |
| nextY += descent + _defaultTextFormat.leading + ascent; |
| |
| // We'll keep this line. |
| textLine = nextTextLine; |
| n++; |
| |
| // Assign its location based on left/top alignment. |
| // Its x position is 0 by default. |
| textLine.y = nextY; |
| |
| // Adjust for positive indent/left margin. Do it here rather |
| // than at the end when alignment is done so the first |
| // line of each paragraph is indented properly. |
| textLine.x = totalIndent; |
| |
| if (_defaultTextFormat.underline) |
| { |
| // FTE doesn't render underlines, |
| // but it can tell us where to draw them. |
| // You can't draw in a TextLine but it can have children, |
| // so we create a child Shape to draw them in. |
| |
| var fontMetrics:FontMetrics = elementFormat.getFontMetrics(); |
| |
| var shape:Shape = new Shape(); |
| var g:Graphics = shape.graphics; |
| g.lineStyle(fontMetrics.underlineThickness, |
| elementFormat.color, elementFormat.alpha); |
| g.moveTo(0, fontMetrics.underlineOffset); |
| g.lineTo(textLine.textWidth, fontMetrics.underlineOffset); |
| |
| textLine.addChild(shape); |
| } |
| |
| addChild(textLine); |
| } |
| |
| return nextY + descent; |
| } |
| |
| /** |
| * @private |
| * Returns with _textWidth and clipWidth set. |
| */ |
| private function alignTextLines(innerWidth:Number):void |
| { |
| // This is only the case when we are auto sizing. In this case |
| // we don't want to do any alignment. |
| if (isNaN(innerWidth)) |
| innerWidth = 0; |
| |
| var rightMargin:Number = Number(_defaultTextFormat.rightMargin); |
| |
| var align:String = _defaultTextFormat.align; |
| var leftAligned:Boolean = |
| align == "left" && direction == "ltr" || |
| align == "right" && direction == "rtl" || |
| align == "justify"; |
| var centerAligned:Boolean = align == "center"; |
| var rightAligned:Boolean = |
| align == "left" && direction == "rtl" || |
| align == "right" && direction == "ltr"; |
| |
| // Calculate loop constants for horizontal alignment. |
| var leftOffset:Number = PADDING_LEFT; |
| var centerOffset:Number = leftOffset + innerWidth / 2; |
| var rightOffset:Number = leftOffset + innerWidth; |
| |
| // Reposition each line if necessary. |
| // based on the horizontal alignment, |
| // and adjusting for the padding. |
| var n:int = numChildren; |
| for (var i:int = 0; i < n; i++) |
| { |
| var textLine:TextLine = TextLine(getChildAt(i)); |
| |
| _textWidth = Math.max(_textWidth, textLine.textWidth); |
| |
| var width:Number = textLine.x + textLine.textWidth + rightMargin; |
| |
| // Only align if there is width to do so. |
| if (leftAligned || width >= innerWidth) |
| textLine.x += leftOffset; |
| else if (centerAligned) |
| textLine.x += centerOffset - width / 2; |
| else if (rightAligned) |
| textLine.x += rightOffset - width; |
| |
| clipWidth = Math.max(clipWidth, textLine.x + textLine.textWidth); |
| |
| textLine.y += PADDING_TOP; |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function composeHTMLText(compositionWidth:Number, |
| compositionHeight:Number):void |
| { |
| textFlow = htmlImporter.importToFlow(explicitHTMLText); |
| |
| // Unless there is a styleSheet, _htmlText is now invalid |
| // and needs to be regenerated on demand, |
| // because with htmlText what-you-set-is-not-what-you-get. |
| if (!styleSheet) |
| _htmlText = null; |
| |
| if (!textFlow) |
| return; |
| |
| textFlow.addEventListener(MouseEvent.CLICK, linkClickHandler); |
| |
| textFlow.addEventListener( |
| StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, |
| inlineGraphicStatusChangeHandler); |
| |
| if (!textContainerManager) |
| textContainerManager = new FTETextFieldTextContainerManager(this); |
| |
| textContainerManager.compositionWidth = compositionWidth; |
| textContainerManager.compositionHeight = compositionHeight; |
| |
| textContainerManager.editingMode = EditingMode.READ_ONLY; |
| |
| textContainerManager.hostFormat = hostFormat; |
| |
| textContainerManager.swfContext = fontContext; |
| |
| textContainerManager.setTextFlow(textFlow) |
| |
| // Add a formatResolver if there is a style sheet. Force a flow |
| // composer to be created, if there isn't one, so the format resolver |
| // will be used. |
| if (_styleSheet && !textFlow.formatResolver) |
| { |
| textFlow.formatResolver = new FTETextFieldStyleResolver(_styleSheet); |
| textContainerManager.beginInteraction(); |
| textContainerManager.endInteraction(); |
| } |
| |
| textContainerManager.updateContainer(); |
| |
| var bounds:Rectangle = textContainerManager.getContentBounds(); |
| |
| _textWidth = Math.round(bounds.width); |
| _textHeight = Math.round(bounds.height); |
| |
| // TLF takes care of clipping so none should be needed here. |
| clipWidth = _textWidth; |
| } |
| |
| /** |
| * @private |
| * Provides RTE messages. |
| * FTETextField is deliberately kept independent |
| * of the rest of the Flex framework. |
| * Therefore it doesn't have access to localized resource strings |
| * in the ResourceManager and simply has hard-coded English Strings. |
| * However, framework subclasses such as UIFTETextField override |
| * this method to provide localized messages from ResourceManager. |
| */ |
| mx_internal function getErrorMessage(key:String, param:String = null):String |
| { |
| var message:String = ""; |
| |
| switch (key) |
| { |
| case "badParameter": |
| { |
| // This message matches the one in Flash Player. |
| message = "Parameter " + param + " must be one of the accepted values."; |
| break; |
| } |
| |
| case "nullParameter": |
| { |
| // This message matches the one in Flash Player. |
| message = "Parameter " + param + " must be non-null."; |
| break; |
| } |
| |
| case "badIndex": |
| { |
| // This message matches the one in Flash Player. |
| message = "The supplied index is out of bounds."; |
| break; |
| } |
| |
| case "notImplementedInFTETextField": |
| { |
| message = "'" + param + "' is not implemented in FTETextField."; |
| break; |
| } |
| |
| case "unsupportedTypeInFTETextField": |
| { |
| message = "FTETextField does not support setting type to \"input\"."; |
| break; |
| } |
| } |
| |
| return message; |
| } |
| |
| /** |
| * @private |
| */ |
| private function notImplemented(name:String):String |
| { |
| return getErrorMessage("notImplementedInFTETextField", name); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Event handlers |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private function addedToStageHandler(event:Event):void |
| { |
| invalidate(); |
| } |
| |
| /** |
| * @private |
| */ |
| private function renderHandler(event:Event):void |
| { |
| validateNow(); |
| |
| removeEventListener(Event.RENDER, renderHandler); |
| } |
| |
| /** |
| * @private |
| */ |
| private function linkClickHandler(event:FlowElementMouseEvent):void |
| { |
| // Need to remove the event: portion of the href if it has one. |
| // Only dispatch the event if it has the event portion. |
| var href:String = LinkElement(event.flowElement).href; |
| if (href.indexOf("event:") == 0) |
| { |
| var textEvent:TextEvent = new TextEvent(TextEvent.LINK); |
| textEvent.text = href.substring(6); |
| dispatchEvent(textEvent); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function inlineGraphicStatusChangeHandler( |
| event:StatusChangeEvent):void |
| { |
| setFlag(FLAG_TEXT_LINES_INVALID | |
| FLAG_GRAPHICS_INVALID); |
| |
| invalidate(); |
| } |
| } |
| |
| } |
| |
| import flash.display.Sprite; |
| import flash.text.engine.FontLookup; |
| import flash.text.engine.FontPosture; |
| import flash.text.engine.FontWeight; |
| import flash.text.StyleSheet; |
| import flash.text.engine.Kerning; |
| |
| import flashx.textLayout.container.TextContainerManager; |
| import flashx.textLayout.elements.FlowElement; |
| import flashx.textLayout.elements.IConfiguration; |
| import flashx.textLayout.elements.IFormatResolver; |
| import flashx.textLayout.formats.ITextLayoutFormat; |
| import flashx.textLayout.elements.LinkElement; |
| import flashx.textLayout.elements.ParagraphElement; |
| import flashx.textLayout.elements.SpanElement; |
| import flashx.textLayout.elements.TextFlow; |
| import flashx.textLayout.formats.LeadingModel; |
| import flashx.textLayout.formats.LineBreak; |
| import flashx.textLayout.formats.TextDecoration; |
| import flashx.textLayout.formats.TextLayoutFormat; |
| |
| import mx.core.FTETextField; |
| import mx.core.mx_internal; |
| |
| use namespace mx_internal; |
| |
| /** |
| * @private |
| */ |
| class FTETextFieldTextContainerManager extends TextContainerManager |
| { |
| /** |
| * @private |
| */ |
| public function FTETextFieldTextContainerManager(container:Sprite, configuration:IConfiguration = null) |
| { |
| super(container, configuration); |
| } |
| |
| /** |
| * @private |
| */ |
| override public function drawBackgroundAndSetScrollRect(scrollX:Number, scrollY:Number):Boolean |
| { |
| return true; |
| } |
| } |
| import helpers.FTETextField41 |
| /** |
| * @private |
| */ |
| class FTETextFieldHostFormat extends TextLayoutFormat |
| { |
| public function FTETextFieldHostFormat(textField:FTETextField41) |
| { |
| super(); |
| |
| this.textField = textField; |
| } |
| |
| private var textField:FTETextField41; |
| |
| public override function get color():* |
| { |
| return textField._defaultTextFormat.color; |
| } |
| |
| public override function get direction():* |
| { |
| return textField.direction; |
| } |
| |
| public override function get fontFamily():* |
| { |
| return textField._defaultTextFormat.font; |
| } |
| |
| public override function get fontLookup():* |
| { |
| return textField.embedFonts ? |
| FontLookup.EMBEDDED_CFF : |
| FontLookup.DEVICE; |
| } |
| |
| public override function get fontSize():* |
| { |
| return textField._defaultTextFormat.size; |
| } |
| |
| public override function get fontStyle():* |
| { |
| return textField._defaultTextFormat.italic ? |
| FontPosture.ITALIC : |
| FontPosture.NORMAL; |
| } |
| |
| public override function get fontWeight():* |
| { |
| return textField._defaultTextFormat.bold ? |
| FontWeight.BOLD : |
| FontWeight.NORMAL; |
| } |
| |
| public override function get kerning():* |
| { |
| return textField._defaultTextFormat.kerning ? |
| Kerning.AUTO : |
| Kerning.OFF; |
| } |
| |
| public override function get leadingModel():* |
| { |
| return LeadingModel.APPROXIMATE_TEXT_FIELD; |
| } |
| |
| public override function get lineBreak():* |
| { |
| return textField.wordWrap ? |
| LineBreak.TO_FIT : |
| LineBreak.EXPLICIT; |
| } |
| |
| public override function get lineHeight():* |
| { |
| return textField._defaultTextFormat.leading; |
| } |
| |
| public override function get locale():* |
| { |
| return textField.locale; |
| } |
| |
| public override function get paddingBottom():* |
| { |
| return FTETextField.PADDING_BOTTOM; |
| } |
| |
| public override function get paddingLeft():* |
| { |
| return FTETextField.PADDING_LEFT; |
| } |
| |
| public override function get paddingRight():* |
| { |
| return FTETextField.PADDING_RIGHT; |
| } |
| |
| public override function get paddingTop():* |
| { |
| return FTETextField.PADDING_TOP; |
| } |
| |
| public override function get paragraphEndIndent():* |
| { |
| return textField._defaultTextFormat.rightMargin; |
| } |
| |
| public override function get paragraphStartIndent():* |
| { |
| return textField._defaultTextFormat.leftMargin; |
| } |
| |
| public override function get textAlign():* |
| { |
| return textField._defaultTextFormat.align; |
| } |
| |
| public override function get textAlignLast():* |
| { |
| return textField._defaultTextFormat.align; |
| } |
| |
| public override function get textDecoration():* |
| { |
| return textField._defaultTextFormat.underline ? |
| TextDecoration.UNDERLINE : |
| TextDecoration.NONE; |
| } |
| |
| public override function get textIndent():* |
| { |
| return textField._defaultTextFormat.indent; |
| } |
| |
| public override function get trackingRight():* |
| { |
| return textField._defaultTextFormat.letterSpacing; |
| } |
| } |
| |
| /** |
| * @private |
| * To attach TextField styling via a style sheet to a TextFlow. |
| */ |
| |
| class FTETextFieldStyleResolver implements IFormatResolver |
| { |
| //-------------------------------------------------------------------------- |
| // |
| // Class variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Map of TextField StyleSheet CSS properties to their equivalent |
| * TLF properties. This is only the styles which have different names. |
| */ |
| private static const textFieldToTLFStyleMap:Object = |
| { |
| "leading": "lineHeight", |
| "letterSpacing": "trackingRight", |
| "marginLeft": "paragraphStartIndent", |
| "marginRight": "paragraphEndIndent" |
| }; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| public function FTETextFieldStyleResolver(styleSheet:StyleSheet):void |
| { |
| _styleSheet = styleSheet; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * The TextField style sheet that will be used to create the TLF style |
| * objects. |
| */ |
| private var _styleSheet:StyleSheet; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // IFormatResolver |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Given a FlowElement or ContainerController object, return any format |
| * settings for it. |
| * |
| * Return format settings for the specified object. |
| */ |
| public function resolveFormat(elem:Object):ITextLayoutFormat |
| { |
| var attr:TextLayoutFormat = null; |
| |
| // ContainerController will inherit via the container so it is not |
| // handled here. Map HTML <body> to TextFlow, HTML <p> to |
| // ParagraphElement and HTML <span> to SpanElement. |
| if (elem is FlowElement) |
| { |
| if (elem is TextFlow) |
| attr = addStyleAttributes(attr, "body"); |
| else if (elem is ParagraphElement) |
| attr = addStyleAttributes(attr, "p"); |
| else if (elem is SpanElement) |
| attr = addStyleAttributes(attr, "span"); |
| |
| // Apply class selector over any format from above. |
| if (elem.styleName != null) |
| attr = addStyleAttributes(attr, "." + elem.styleName); |
| } |
| |
| return attr; |
| } |
| |
| /** |
| * Given a FlowElement or ContainerController object and the name of a |
| * format property, return the format value or undefined if |
| * the value is not found. |
| * |
| * Return the value of the specified format for the specified object. |
| */ |
| public function resolveUserFormat(elem:Object,userStyle:String):* |
| { |
| var flowElem:FlowElement = elem as FlowElement; |
| var attr:TextLayoutFormat; |
| |
| // support non-tlf styles |
| if (flowElem) |
| { |
| if (flowElem.styleName) |
| { |
| attr = addStyleAttributes(null, "." + flowElem.styleName); |
| } |
| else if (flowElem is LinkElement) |
| { |
| if (userStyle == "linkNormalFormat") |
| attr = addStyleAttributes(null, "a:link"); |
| |
| else if (userStyle == "linkHoverFormat") |
| attr = addStyleAttributes(null, "a:hover"); |
| |
| else if (userStyle == "linkActiveFormat") |
| attr = addStyleAttributes(null, "a:active"); |
| } |
| else |
| { |
| attr = addStyleAttributes(null, userStyle); |
| } |
| } |
| |
| return attr != null ? attr : undefined; |
| } |
| |
| /** |
| * Invalidates any cached formatting information for a TextFlow so that |
| * formatting must be recomputed. |
| */ |
| public function invalidateAll(tf:TextFlow):void |
| { |
| } |
| |
| /** |
| * Invalidates cached formatting information on this element because, for |
| * example, the parent changed, or the id or the styleName changed. |
| */ |
| public function invalidate(target:Object):void |
| { |
| } |
| |
| /** |
| * Return the format resolver for the copy of the TextFlow. |
| */ |
| public function getResolverForNewFlow(oldFlow:TextFlow,newFlow:TextFlow):IFormatResolver |
| { |
| return this; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Look up the styleSelector in the TextField style sheet and build the |
| * object of corresponding TLF styles and values. Return null if the |
| * styleSelector is not found in the style sheet. |
| */ |
| private function addStyleAttributes( |
| attr:TextLayoutFormat, |
| styleSelector:String):TextLayoutFormat |
| { |
| var foundStyle:Object = _styleSheet.getStyle(styleSelector); |
| if (foundStyle != null) |
| { |
| for (var p:* in foundStyle) |
| { |
| var propStyle:Object = foundStyle[p]; |
| |
| if (attr == null) |
| attr = new TextLayoutFormat(); |
| |
| if (textFieldToTLFStyleMap[p]) |
| { |
| // different name, same values |
| var tlfProp:String = textFieldToTLFStyleMap[p]; |
| attr[tlfProp] = propStyle; |
| } |
| else if (p == "color") |
| { |
| // convert from "#000000" to "0x000000" format |
| var color:String = String(propStyle); |
| if (color && color.charAt(0) == "#") |
| attr.color = "0x"+color.substring(1); |
| } |
| else if (p == "display") |
| { |
| // TODO(cframpto): if we decide to support this. |
| } |
| else if (p == "kerning") |
| { |
| // convert from true/false to on/off |
| if (Boolean(propStyle)) |
| attr.kerning = flash.text.engine.Kerning.ON; |
| else |
| attr.kerning = flash.text.engine.Kerning.OFF; |
| } |
| else |
| { |
| // same name, same values |
| attr[p] = propStyle; |
| } |
| } |
| } |
| |
| return attr; |
| } |
| } |