| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 UnitTest.Tests |
| { |
| import UnitTest.ExtendedClasses.VellumTestCase; |
| import UnitTest.Fixtures.TestConfig; |
| import UnitTest.Fixtures.TestEditManager; |
| |
| import flash.display.Sprite; |
| import flash.events.*; |
| import flash.text.engine.FontPosture; |
| import flash.text.engine.FontWeight; |
| import flash.ui.Keyboard; |
| import flash.utils.getQualifiedClassName; |
| |
| import flashx.textLayout.container.ContainerController; |
| import flashx.textLayout.conversion.ITextImporter; |
| import flashx.textLayout.conversion.TextConverter; |
| import flashx.textLayout.edit.EditManager; |
| import flashx.textLayout.elements.*; |
| import flashx.textLayout.events.FlowOperationEvent; |
| import flashx.textLayout.events.SelectionEvent; |
| import flashx.textLayout.events.StatusChangeEvent; |
| import flashx.textLayout.formats.*; |
| import flashx.textLayout.operations.FlowOperation; |
| import flashx.textLayout.operations.UndoOperation; |
| import flashx.textLayout.tlf_internal; |
| import flashx.undo.UndoManager; |
| |
| import org.flexunit.asserts.assertTrue; |
| import org.flexunit.asserts.fail; |
| |
| use namespace tlf_internal; |
| |
| |
| public class GeneralFunctionsTest extends VellumTestCase |
| { |
| public static const childParentTable:Array = |
| [ |
| [ "child\parent", TextFlow, DivElement, ParagraphElement, LinkElement, TCYElement, SpanElement, InlineGraphicElement, BreakElement, TabElement, ListElement, ListItemElement, SubParagraphGroupElement ], |
| [ TextFlow, "no", "no", "no", "no", "no", "no", "no", "no", "no", "no", "no", "no" ], |
| [ DivElement, "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes", "yes", "no" ], |
| [ ParagraphElement, "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes", "yes", "no" ], |
| [ LinkElement, "no", "no", "yes", "no", "yes", "no", "no", "no", "no", "no", "no", "yes" ], |
| [ TCYElement, "no", "no", "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes" ], |
| [ SpanElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ], |
| [ InlineGraphicElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ], |
| [ BreakElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ], |
| [ TabElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ], |
| [ ListElement, "yes", "yes", "no", "no", "no", "no", "no", "no", "no", "yes", "yes", "no" ], |
| [ ListItemElement, "no", "no", "no", "no", "no", "no", "no", "no", "no", "yes", "no", "no" ], |
| [ SubParagraphGroupElement, "no", "no", "yes", "yes", "yes", "no", "no", "no", "no", "no", "no", "yes" ] |
| ]; |
| |
| private static const customResourceDict:Object = |
| { |
| invalidFlowElementConstruct_custom: "Attempted construct of invalid FlowElement subclass", |
| badMXMLChildrenArgument_custom: "Bad element of type {0} passed to mxmlChildren", |
| malformedTag: "Malformed tag </p/>", |
| XMLParserFailure: "TypeError: Error #1090: XML parser failure: element is malformed." |
| }; |
| |
| /** |
| * pick up the actual operation |
| */ |
| private var flowOp:FlowOperation; |
| private var SelectionChanged:Boolean; |
| private var ilgStatus:String; |
| |
| public function GeneralFunctionsTest() |
| { |
| super("", "EventOverrideTest", TestConfig.getInstance()); |
| |
| metaData = {}; |
| // Note: These must correspond to a Watson product area (case-sensitive) |
| metaData.productArea = "Editing"; |
| } |
| |
| |
| [Before] |
| override public function setUpTest():void |
| { |
| super.setUpTest(); |
| } |
| |
| [After] |
| override public function tearDownTest():void |
| { |
| super.tearDownTest(); |
| } |
| |
| |
| [Test] |
| public function setSelectionRangeTest():void //KJT test selection range and change event |
| { |
| var startIndx:int = 800; |
| var endIndx:int = 933; |
| //trace('CALL SET SELECTION'); |
| |
| SelManager.textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE, selChange, false, 0, true); |
| SelManager.selectRange(startIndx, endIndx); |
| |
| assertTrue("beginning index should be 800, but is " + SelManager.anchorPosition, |
| SelManager.anchorPosition == 800); |
| assertTrue("end index should be 933, but is " + SelManager.activePosition, |
| SelManager.activePosition == 933); |
| assertTrue("SelectionChanged returned false", SelectionChanged == true); |
| } |
| |
| [Test] |
| /** |
| * Select 40 characters and replaces them with new text |
| */ |
| public function replaceSelectionTest():void |
| { |
| var startIndx:int = 10; |
| var endIndx:int = 50; |
| |
| var attributes:TextLayoutFormat = new TextLayoutFormat(); |
| attributes.fontWeight = FontWeight.BOLD; |
| attributes.lineThrough = true; |
| |
| SelManager.selectRange(startIndx, endIndx); |
| SelManager.applyLeafFormat(attributes); |
| |
| SelManager.insertText("New"); |
| SelManager.flushPendingOperations(); |
| |
| var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(startIndx); |
| var attributesNew:ITextLayoutFormat = leaf.format; |
| assertTrue("Invalid point format after block deletion", TextLayoutFormat.isEqual(attributes, attributesNew)); |
| } |
| |
| [Test] |
| /** |
| * Select 40 characters and delete them. |
| */ |
| public function backSpaceSelectionTest():void |
| { |
| var startIndx:int = 10; |
| var endIndx:int = 50; |
| |
| var attributes:TextLayoutFormat = new TextLayoutFormat(); |
| attributes.fontWeight = FontWeight.BOLD; |
| attributes.lineThrough = true; |
| |
| SelManager.selectRange(startIndx, endIndx); |
| SelManager.applyLeafFormat(attributes); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| SelManager.deletePreviousCharacter(); |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("deleting the selection should have removed " + (endIndx - startIndx) + |
| " characters. It actually removed " + (initLength - endLength), |
| endLength == initLength - (endIndx - startIndx)); |
| |
| SelManager.insertText("New"); |
| SelManager.flushPendingOperations(); |
| |
| var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(startIndx); |
| var attributesNew:ITextLayoutFormat = leaf.format; |
| assertTrue("Invalid point format after block deletion", TextLayoutFormat.isEqual(attributes, attributesNew)); |
| } |
| |
| [Test] |
| /** |
| * Set the cursor position back ten characters and delete the first ten characters. |
| */ |
| public function backSpaceInsertionPointTest():void |
| { |
| var n:int = 10; |
| SelManager.selectRange(n, n); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| SelManager.deletePreviousCharacter(); |
| } |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("should have removed " + n + " characters. Actually removed " + |
| (initLength - endLength), endLength == initLength - n); |
| } |
| |
| [Test] |
| /** |
| * Set the cursor position back nine characters and delete the first ten characters. |
| * Ensure that only nine characters are deleted. |
| */ |
| public function backSpaceLowerLimitTest():void |
| { |
| var n:int = 9; |
| SelManager.selectRange(n, n); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| for (var i:int = 0; i <= n; i++) |
| { |
| SelManager.deletePreviousCharacter(); |
| } |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("should have removed " + n + " characters. Actually removed " + |
| (initLength - endLength), endLength == initLength - n); |
| } |
| |
| [Test] |
| /** |
| * Select 40 characters and delete them. |
| */ |
| public function deleteSelectionTest():void |
| { |
| var startIndx:int = 10; |
| var endIndx:int = 50; |
| |
| SelManager.selectRange(startIndx, endIndx); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| SelManager.deleteNextCharacter(); |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("should have removed " + (endIndx - startIndx) + " characters. Actually removed " + |
| (initLength - endLength), endLength == initLength - (endIndx - startIndx)); |
| } |
| |
| [Test] |
| /** |
| * Delete the first ten characters. |
| */ |
| public function deleteInsertionPointTest():void |
| { |
| var n:int = 10; |
| SelManager.selectRange(0, 0); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| SelManager.deleteNextCharacter(); |
| } |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("should have removed " + n + " characters. Actually removed " + |
| (initLength - endLength), endLength == initLength - n); |
| } |
| |
| [Test] |
| /** |
| * Set the cursor position back nine characters and delete the first ten characters. |
| * Ensure that only nine characters are deleted. |
| */ |
| public function deleteUpperLimitTest():void |
| { |
| var n:int = 9; |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| SelManager.selectRange(initLength - (n + 1), initLength - (n + 1)); |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| SelManager.deleteNextCharacter(); |
| } |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("should have removed " + n + " characters. Actually removed " + |
| (initLength - endLength), endLength == initLength - n); |
| } |
| |
| [Test] |
| /** |
| * Splits the paragraph after the first fifty characters. |
| * Verifies that there is one more line in the textFlow than it started with. |
| * Verifies that the first leaf has only 50 characters in it. |
| */ |
| public function splitParagraphInsertionPointTest():void |
| { |
| var insertPoint:int = 50; |
| |
| SelManager.selectRange(insertPoint, insertPoint); |
| |
| var initLines:int = SelManager.textFlow.flowComposer.numLines; |
| SelManager.splitParagraph(); |
| var endLines:int = SelManager.textFlow.flowComposer.numLines; |
| |
| assertTrue("expected one additional line after splitting the paragraph. Actually found " + |
| (endLines - initLines), initLines = endLines - 1); |
| |
| var lengthFirst:int = SelManager.textFlow.getFirstLeaf().textLength; |
| |
| assertTrue("expected the first paragraph would have " + insertPoint + |
| " characters. Actually found " + lengthFirst, lengthFirst = insertPoint); |
| } |
| |
| [Test] |
| /** |
| * 1. Sets attributes before (A, B), after (B', C) and at (B'', D) at split point. |
| * Splits paragraphs, adds new text and verifies that it has attributes (A, B'', C, D) |
| * 2. Tests special case for splitting a paragraph at the end of a link; point format is reset in this case |
| */ |
| public function splitParagraphFormatTest():void |
| { |
| var insertPoint:int = 50; |
| |
| var attributes:TextLayoutFormat = new TextLayoutFormat(); |
| |
| attributes.fontWeight = FontWeight.BOLD; |
| attributes.lineThrough = true; |
| SelManager.selectRange(insertPoint - 5, insertPoint); |
| SelManager.applyLeafFormat(attributes); |
| |
| attributes.fontWeight = undefined; |
| attributes.textDecoration = TextDecoration.UNDERLINE; |
| attributes.fontSize = 72; |
| SelManager.selectRange(insertPoint, insertPoint + 5); |
| SelManager.applyLeafFormat(attributes); |
| |
| attributes.textDecoration = TextDecoration.UNDERLINE; |
| attributes.lineThrough = true; |
| attributes.fontFamily = "Verdana"; |
| SelManager.selectRange(insertPoint, insertPoint); |
| SelManager.applyLeafFormat(attributes); |
| |
| SelManager.splitParagraph(); |
| |
| SelManager.insertText("New"); |
| SelManager.flushPendingOperations(); |
| |
| var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(insertPoint + 1); |
| attributes = new TextLayoutFormat(leaf.format); |
| |
| assertTrue("Invalid point format for start of a new paragraph", attributes.fontWeight = FontWeight.BOLD); |
| assertTrue("Invalid point format for start of a new paragraph", attributes.fontSize = 72); |
| assertTrue("Invalid point format for start of a new paragraph", attributes.fontFamily = "Verdana"); |
| assertTrue("Invalid point format for start of a new paragraph", attributes.textDecoration == TextDecoration.UNDERLINE && attributes.lineThrough); |
| |
| insertPoint = 40; |
| |
| SelManager.selectRange(insertPoint - 10, insertPoint); |
| SelManager.applyLink("http://www.google.com", "_self", false); |
| |
| SelManager.selectRange(insertPoint, insertPoint); |
| SelManager.splitParagraph(); |
| |
| SelManager.insertText("New"); |
| SelManager.flushPendingOperations(); |
| |
| leaf = SelManager.textFlow.findLeaf(insertPoint + 1); |
| attributes = new TextLayoutFormat(leaf.format); |
| assertTrue("Invalid point format for start of a new paragraph after a link", TextLayoutFormat.isEqual(attributes, TextLayoutFormat.emptyTextLayoutFormat)); |
| } |
| |
| [Test] |
| /** |
| * Selects the characters between the 10th and 50th characters and splits the paragraph. |
| * Verifies that there is one more line in the textFlow than it started with. |
| * Verifies that the first leaf has only 10 characters in it. |
| * Verifies that the final length has 39 less characters in it. |
| */ |
| public function splitParagraphSelectionTest():void |
| { |
| var startIndx:int = 10; |
| var endIndx:int = 50; |
| |
| |
| SelManager.selectRange(startIndx, endIndx); |
| |
| var initLength:int = SelManager.textFlow.textLength; |
| var initLines:int = SelManager.textFlow.flowComposer.numLines; |
| |
| SelManager.splitParagraph(); |
| |
| var endLength:int = SelManager.textFlow.textLength; |
| var endLines:int = SelManager.textFlow.flowComposer.numLines; |
| |
| assertTrue("expected one additional line after splitting the paragraph. Actually found " + |
| (endLines - initLines), initLines = endLines - 1); |
| |
| var lengthFirst:int = SelManager.textFlow.getFirstLeaf().textLength; |
| |
| assertTrue("expected the first paragraph would have " + startIndx + |
| " characters. Actually found " + lengthFirst, lengthFirst = startIndx); |
| assertTrue("expected the entire flow would have " + (initLength - (endIndx - startIndx) + 1) + |
| " characters. Actually found " + endLength, |
| endLength == initLength - (endIndx - startIndx) + 1); |
| } |
| |
| [Test] |
| /** |
| * Creates a selection area of six characters at the last index of the flow root |
| * then inserts " BOOGA" into the selection area and verifies the length of the |
| * flow root has increased by 6. |
| */ |
| public function insertTextTest():void //KJT |
| { |
| var textLength:uint = SelManager.textFlow.textLength; |
| SelManager.selectRange(textLength - 1, textLength + 5); |
| |
| SelManager.insertText(" BOOGA"); |
| SelManager.selectRange(textLength - 1, textLength + 5); |
| |
| assertTrue("expected to find " + (textLength + 6) + " characters. Actually found " + |
| SelManager.textFlow.textLength, SelManager.textFlow.textLength == textLength + 6); |
| } |
| |
| [Test] |
| /** |
| * Sets the insertion point at 50, then generates the "0" keyboard event |
| * and verifies that the selBegIdx is 49. |
| */ |
| public function arrowLeft():void |
| { |
| var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 0, Keyboard.LEFT); |
| SelManager.selectRange(50, 50); |
| SelManager.keyDownHandler(event); |
| |
| if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL) |
| { |
| // assertTrue("expected insertion point at position 87. Actually found + " + |
| // SelManager.anchorPosition, SelManager.anchorPosition == 87); |
| } |
| else |
| { |
| if (SelManager.textFlow.computedFormat.direction == Direction.LTR) |
| { |
| assertTrue("expected insertion point at position 49. Actually found + " + |
| SelManager.activePosition, SelManager.activePosition == 49); |
| } |
| else |
| { |
| assertTrue("expected insertion point at position 51. Actually found + " + |
| SelManager.activePosition, SelManager.activePosition == 51); |
| } |
| } |
| } |
| |
| [Test] |
| /** |
| * Sets the insertion point at 50, then generates the "0" keyboard event |
| * and verifies that the selBegIdx is 51. |
| */ |
| public function arrowRight():void |
| { |
| var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 0, Keyboard.RIGHT); |
| SelManager.selectRange(50, 50); |
| SelManager.keyDownHandler(event); |
| if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL) |
| { |
| // assertTrue("expected insertion point at position 11. Actually found + " + |
| // SelManager.anchorPosition, SelManager.anchorPosition == 11); |
| } |
| else |
| { |
| if (SelManager.textFlow.computedFormat.direction == Direction.LTR) |
| { |
| assertTrue("expected insertion point at position 51. Actually found " + |
| SelManager.activePosition, SelManager.activePosition == 51); |
| } |
| else |
| { |
| assertTrue("expected insertion point at position 49. Actually found " + |
| SelManager.activePosition, SelManager.activePosition == 49); |
| } |
| } |
| } |
| |
| [Test] |
| /** |
| * Sets the insertion point at 0, then generates the "40" keyboard event |
| * and verifies that the cursor is on the second line. |
| */ |
| public function arrowDown():void |
| { |
| var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 40); |
| SelManager.selectRange(0, 0); |
| SelManager.keyDownHandler(event); |
| if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.TB) |
| { |
| //NYI |
| } |
| else |
| { |
| var ap:int = SelManager.activePosition; |
| var index:int = SelManager.textFlow.findChildIndexAtPosition(ap); |
| assertTrue("expected index at 2. Actually found " + index, index == 2); |
| } |
| } |
| |
| [Test] |
| /** |
| * Sets the insertion point at the last char, then generates the "38" keyboard event |
| * and verifies that the cursor is on the second to last line. |
| */ |
| public function arrowUp():void |
| { |
| var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 38); |
| var lastChar:int = SelManager.absoluteEnd; |
| var lastLine:int = SelManager.textFlow.findChildIndexAtPosition(lastChar); |
| SelManager.selectRange(lastChar, lastChar); |
| SelManager.keyDownHandler(event); |
| if (SelManager.textFlow.computedFormat.blockProgression == BlockProgression.TB) |
| { |
| //NYI |
| } |
| else |
| { |
| var index:int = SelManager.textFlow.findChildIndexAtPosition(SelManager.activePosition); |
| assertTrue("expected index at " + (lastChar - 1) + |
| ". Actually found " + index, |
| index == (lastChar - 1) |
| ); |
| } |
| } |
| |
| [Test] |
| /** |
| * Tests the undo and redo stacks by applying typeface changes by undoing |
| * and redoing them. |
| */ |
| public function unDoOp():void //KJT |
| { |
| var ca:TextLayoutFormat = new TextLayoutFormat(); |
| ca.fontWeight = FontWeight.BOLD; |
| SelManager.applyLeafFormat(ca); |
| |
| SelManager.undo(); |
| Redo(); |
| |
| ca.fontStyle = FontPosture.ITALIC; |
| SelManager.applyLeafFormat(ca); |
| |
| SelManager.undo(); |
| SelManager.undo(); |
| } |
| |
| [Test] |
| /** |
| * Performs successive backspaces and one undo to see if all the deleted content |
| * is returned, then performs a redo to see if the content is correctly removed |
| * again. |
| */ |
| public function joinedBackspaceUndoTest():void |
| { |
| var n:int = 10; |
| SelManager.selectRange(10, 10); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8); |
| dispatchEvent(event); |
| } |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| SelManager.undo(); |
| |
| var undoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected text length before undo to be " + n + " less. Was actually " + |
| (endLength - initLength) + " less.", endLength == initLength - n); |
| assertTrue("expected text length after undo to be identical to the start, but it was off by " + |
| (undoLength - initLength), undoLength == initLength); |
| |
| Redo(); |
| |
| var redoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected redo length to equal undo length, but found " + |
| redoLength + " and " + endLength, redoLength == endLength); |
| } |
| |
| [Test] |
| /** |
| * Performs successive deletes and one undo to see if all the deleted content |
| * is returned, then performs a redo to see if the content is correctly removed |
| * again. |
| */ |
| public function joinedDeleteUndoTest():void |
| { |
| var n:int = 10; |
| SelManager.selectRange(10, 10); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 127, Keyboard.DELETE); |
| dispatchEvent(event); |
| } |
| SelManager.flushPendingOperations(); |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| SelManager.undo(); |
| |
| var undoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected text length before undo to be " + n + " less. Was actually " + |
| (endLength - initLength) + " less.", endLength == initLength - n); |
| assertTrue("expected text length after undo to be identical to the start, but it was off by " + |
| (undoLength - initLength), undoLength == initLength); |
| |
| Redo(); |
| |
| var redoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected redo length to equal undo length, but found " + |
| redoLength + " and " + endLength, redoLength == endLength); |
| } |
| |
| [Test] |
| /** |
| * Places a series of letter a's in and does one undo to see if all the a's |
| * are removed, then performs a redo to see if they're returned. |
| */ |
| public function joinedInsertUndoTest():void |
| { |
| var n:int = 10; |
| SelManager.selectRange(10, 10); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| var event:TextEvent = new TextEvent(TextEvent.TEXT_INPUT, false, false, "a"); |
| dispatchEvent(event); |
| } |
| |
| SelManager.flushPendingOperations(); |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| SelManager.undo(); |
| |
| var undoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected text length before undo to be " + n + " more. Was actually " + |
| (endLength - initLength) + " less.", endLength == initLength + n); |
| assertTrue("expected text length after undo to be identical to the start, but it was off by " + |
| (undoLength - initLength), undoLength == initLength); |
| Redo(); |
| |
| var redoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected redo length to equal undo length, but found " + |
| redoLength + " and " + endLength, redoLength == endLength); |
| } |
| |
| [Test] |
| /** |
| * Performs successive enters and one undo to see if all paragraph splits are |
| * undone, then performs a redo to see if they're all redone. |
| */ |
| public function joinedSplitParagraphUndoTest():void |
| { |
| var n:int = 10; |
| SelManager.selectRange(10, 10); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13); |
| dispatchEvent(event); |
| } |
| |
| var endLength:uint = SelManager.textFlow.textLength; |
| |
| SelManager.undo(); |
| |
| var undoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected text length before undo to be " + n + " more. Was actually " + |
| (endLength - initLength) + " less.", endLength == initLength + n); |
| assertTrue("expected text length after undo to be identical to the start, but it was off by " + |
| (undoLength - initLength), undoLength == initLength); |
| |
| Redo(); |
| |
| var redoLength:uint = SelManager.textFlow.textLength; |
| |
| assertTrue("expected redo length to equal undo length, but found " + |
| redoLength + " and " + endLength, redoLength == endLength); |
| } |
| |
| [Test] |
| /** |
| * Create a new undo manager with an undo limit of ten, then perform eleven |
| * undoable operations and see how many times it will let you undo. |
| */ |
| public function undoLimitTest():void |
| { |
| var undo:UndoManager = new UndoManager(); |
| var n:int = 10; |
| undo.undoAndRedoItemLimit = n; |
| |
| var newSM:EditManager = new EditManager(undo); |
| SelManager = newSM; |
| TestFrame.rootElement.getTextFlow().interactionManager = newSM; |
| |
| //SelManager.selectRange(n,n); |
| |
| for (var i:int = 0; i < n + 1; i++) |
| { |
| SelManager.selectRange(n, n + i); |
| var event:KeyboardEvent = (i % 2 == 0) ? |
| new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13) : |
| new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8); |
| dispatchEvent(event); |
| SelManager.selectRange(-1, -1); |
| } |
| |
| var u:int = 0; |
| while (undo.canUndo()) |
| { |
| SelManager.undo(); |
| u++; |
| } |
| |
| assertTrue("expected only " + n + " undos but found " + u, u == n); |
| } |
| |
| [Test] |
| public function undoRedoStackTest():void |
| { |
| var undo:UndoManager = new UndoManager(); |
| var n:int = 10; |
| undo.undoAndRedoItemLimit = n; |
| |
| var newSM:EditManager = new EditManager(undo); |
| SelManager = newSM; |
| TestFrame.rootElement.getTextFlow().interactionManager = newSM; |
| |
| //do n operations |
| for (var i:int = 0; i < n + 1; i++) |
| { |
| SelManager.selectRange(n, n + i); |
| var event:KeyboardEvent = (i % 2 == 0) ? |
| new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13) : |
| new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 8); |
| dispatchEvent(event); |
| SelManager.selectRange(-1, -1); |
| } |
| var testManager:TestEditManager = new TestEditManager(undo); |
| var stackItemNum:int = testManager.UndoRedoEntireStack(undo); |
| |
| assertTrue("expected only " + n + " undos but found " + stackItemNum, stackItemNum == n); |
| } |
| |
| [Test] |
| /** |
| * Select a section of text that spans paragraphs then delete it and see if the |
| * size of the flow goes down by the appropriate amount. |
| */ |
| public function transParagraphDeleteTest():void |
| { |
| var startLength:int = TestFrame.rootElement.textLength; |
| |
| var flow1:FlowElement; |
| var flow2:FlowElement; |
| |
| var start:int = 0; |
| var finish:int = 0; |
| |
| var origParas:int = TestFrame.rootElement.numChildren; |
| |
| //Look for two back to back paragraphs. |
| for (var i:int = 0; i < TestFrame.rootElement.numChildren - 1; i++) |
| { |
| flow1 = TestFrame.rootElement.getChildAt(i); |
| flow2 = TestFrame.rootElement.getChildAt(i + 1); |
| |
| if (flow1 is ParagraphElement && flow2 is ParagraphElement) |
| { |
| finish = start + flow1.textLength + flow2.textLength / 2; |
| start = start + flow1.textLength / 2; |
| break; |
| } else |
| { |
| start = start + flow1.textLength; |
| } |
| } |
| |
| assertTrue("expected finish to be in the middle of the second para, but it's still 0", finish != 0); |
| |
| var para1:ParagraphElement = flow1 as ParagraphElement; |
| var para2:ParagraphElement = flow2 as ParagraphElement; |
| |
| var attrib1:ITextLayoutFormat = para1.computedFormat; |
| var pa:TextLayoutFormat = new TextLayoutFormat(); |
| if (attrib1.textAlign == TextAlign.CENTER) |
| pa.textAlign = TextAlign.LEFT; |
| else |
| pa.textAlign = TextAlign.CENTER; |
| |
| |
| SelManager.selectRange(para2.getAbsoluteStart(), para2.getAbsoluteStart() + 1); |
| |
| SelManager.applyParagraphFormat(pa); |
| |
| var attrib2:ITextLayoutFormat = para2.computedFormat; |
| assertTrue("para1 and para2 paraAttrs must be different for this test to work!", |
| !TextLayoutFormat.isEqual(attrib1, attrib2) |
| ); |
| |
| SelManager.selectRange(start, finish); |
| SelManager.deleteNextCharacter(); |
| var finishLength:int = TestFrame.rootElement.textLength; |
| |
| assertTrue("expected " + (finish - start) + " less characters but found " + |
| (startLength - finishLength) + " less", startLength - finishLength == finish - start); |
| |
| /* |
| * TODO: this tests current behavior. Proper behavior would be only one |
| * remaining paragraph. |
| */ |
| |
| assertTrue("number of paragraphs should have decreased!", origParas > TestFrame.rootElement.numChildren); |
| |
| var finalPara:ParagraphElement = TestFrame.rootElement.getChildAt(i) as ParagraphElement; |
| var finalAttrs:ITextLayoutFormat = finalPara.computedFormat; |
| |
| assertTrue("paragraph attributes changed and should be the same!", TextLayoutFormat.isEqual(attrib1, finalAttrs)); |
| } |
| |
| [Test] |
| /** |
| * Create an empty paragraph and select the 0 position in it. |
| * Then delete all the content on the flow and see if the position selected is 0. |
| */ |
| public function emptyParagraphTest():void |
| { |
| SelManager.selectRange(0, 0); |
| |
| var returnevent:KeyboardEvent = |
| new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13); |
| dispatchEvent(returnevent); |
| |
| SelManager.selectRange(0, 0); |
| assertTrue("did not start with selection at 0,0", SelManager.anchorPosition == 0 && SelManager.activePosition == 0); |
| SelManager.selectAll(); |
| SelManager.deleteNextCharacter(); |
| assertTrue("did not end with selection at 0,0 after delete all", SelManager.anchorPosition == 0 && SelManager.activePosition == 0); |
| } |
| |
| [Test] |
| public function splitUTF16Test():void |
| { |
| // remove all text |
| SelManager.selectAll(); |
| SelManager.deleteNextCharacter(); |
| |
| var a:uint = 0xD866; |
| var b:uint = 0xDDC1; |
| var c:uint = 0xD869; |
| var d:uint = 0xDED6; |
| var e:uint = 0xD8BF; |
| var f:uint = 0xDFFD; |
| |
| var y:String = String.fromCharCode(a, b, c, d, e, f); |
| SelManager.insertText(y); |
| SelManager.flushPendingOperations(); |
| |
| var begin:int = 0; |
| var end:int = SelManager.textFlow.textLength; |
| var middle:int = ((end - 1) - begin) / 2; |
| SelManager.selectRange(middle, middle); |
| |
| var gotRangeError:Boolean = false; |
| try |
| { |
| SelManager.splitParagraph(); |
| SelManager.flushPendingOperations(); |
| } |
| catch (e:RangeError) |
| { |
| gotRangeError = true; |
| } |
| /* See bug #1798067 */ |
| assertTrue("Spliting a surrogate pair did not throw an error", gotRangeError); |
| |
| SelManager.selectAll(); |
| |
| var charAttr:TextLayoutFormat = new TextLayoutFormat(); |
| charAttr.fontFamily = "Adobe Song Std L"; |
| |
| SelManager.applyLeafFormat(charAttr); |
| SelManager.flushPendingOperations(); |
| |
| //trace(begin + ", " + middle + ", " + end); |
| } |
| |
| [Test] |
| public function splitUTF32Test():void |
| { |
| // remove all text |
| SelManager.selectAll(); |
| SelManager.deleteNextCharacter(); |
| |
| var y:String = String.fromCharCode(0x00028023); |
| y = y + y + y; |
| |
| SelManager.insertText(y); |
| SelManager.flushPendingOperations(); |
| |
| var begin:int = 0; |
| var end:int = SelManager.textFlow.textLength; |
| var middle:int = ((end - 1) - begin) / 2; |
| SelManager.selectRange(middle, middle); |
| |
| SelManager.splitParagraph(); |
| SelManager.flushPendingOperations(); |
| |
| SelManager.selectAll(); |
| |
| var charAttr:TextLayoutFormat = new TextLayoutFormat(); |
| charAttr.fontFamily = "Adobe Song Std L"; |
| |
| SelManager.applyLeafFormat(charAttr); |
| SelManager.flushPendingOperations(); |
| |
| //trace(begin + ", " + middle + ", " + end); |
| } |
| |
| [Test] |
| /** |
| * Performs an operation, clear the selection manager and then make sure the operation doesn't undo |
| */ |
| public function undoWithModelChangeTest():void |
| { |
| var tf:TextFlow = SelManager.textFlow; |
| var selManager:EditManager = SelManager; |
| |
| selManager.selectAll(); |
| |
| var initLength:uint = SelManager.textFlow.textLength; |
| |
| |
| flowOp = null; |
| tf.addEventListener(FlowOperationEvent.FLOW_OPERATION_BEGIN, listenForOpBegin, false, 0, true); |
| |
| // now do an operation |
| var ca:TextLayoutFormat = new TextLayoutFormat(); |
| ca.color = 0xff; |
| selManager.applyFormatToElement(tf, ca); |
| |
| assertTrue("no begin operation event", flowOp != null); |
| assertTrue("textFlow characterFormat.color should be 0xff", tf.format && tf.format.color == 0xff); |
| |
| // clear the selection manager |
| tf.interactionManager = null; |
| // now I've got a hold of the operation. do an out of bounds model modification and then attempt an undo |
| tf.color = 0xff00; |
| assertTrue("textFlow characterFormat.color should be 0xff", tf.format.color == 0xff00); |
| |
| // now restore the interactionManager |
| tf.interactionManager = selManager; |
| // CONFIG::debug { trace("GeneralFunctionsTest.undoWithModelChangeTest: expect to see message regarding skipping undo due to mismatched generation numbers."); } |
| // try to do an undo |
| selManager.undo(); |
| |
| // it should be skipped |
| assertTrue("no begin operation event", flowOp != null); |
| assertTrue("wrong begin operation event", flowOp is UndoOperation); |
| assertTrue("textFlow characterFormat.color should be 0xff00", tf.format && tf.format.color == 0xff00); |
| |
| selManager.selectRange(0, 0); // prevent assert in tearDown |
| } |
| |
| [Test] |
| public function doubleClickTest():void |
| { |
| SelManager.selectRange(68, 68); |
| var mEvent:MouseEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK); |
| TestFrame.container["dispatchEvent"](mEvent); |
| |
| assertTrue("Double click failed to correctly select word", |
| SelManager.anchorPosition == 65 && |
| SelManager.activePosition == 72); |
| |
| SelManager.selectRange(955, 955); |
| mEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK); |
| TestFrame.container["dispatchEvent"](mEvent); |
| |
| assertTrue("Double click failed to correctly select word", |
| SelManager.anchorPosition == 954 && |
| SelManager.activePosition == 957); |
| } |
| |
| [Test] |
| public function doubleClickHyphenTest():void |
| { |
| SelManager.selectRange(24, 24); |
| var mEvent:MouseEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK); |
| TestFrame.container["dispatchEvent"](mEvent); |
| |
| assertTrue("Double click failed on a hyphen", |
| SelManager.anchorPosition == 24 && |
| SelManager.activePosition == 25); |
| |
| SelManager.selectRange(498, 498); |
| mEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK); |
| TestFrame.container["dispatchEvent"](mEvent); |
| |
| assertTrue("Double click failed on a hyphenated word", |
| SelManager.anchorPosition == 496 && |
| SelManager.activePosition == 502); |
| } |
| |
| [Test] |
| public function doubleClickPunctuationTest():void |
| { |
| SelManager.selectRange(951, 951); |
| var mEvent:MouseEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK); |
| TestFrame.container["dispatchEvent"](mEvent); |
| |
| assertTrue("Double click failed on a word next to punctuation", |
| SelManager.anchorPosition == 945 && |
| SelManager.activePosition == 952); |
| |
| SelManager.selectRange(1964, 1964); |
| mEvent = new MouseEvent(MouseEvent.DOUBLE_CLICK); |
| TestFrame.container["dispatchEvent"](mEvent); |
| |
| assertTrue("Double click failed on punctuation", |
| SelManager.anchorPosition == 1963 && |
| SelManager.activePosition == 1966); |
| } |
| |
| [Test] |
| public function replaceChildrenFlowTest():void |
| { |
| var caught:Boolean = false; |
| |
| try |
| { |
| SelManager.textFlow.replaceChildren(0, 0, new TextFlow()); |
| } |
| catch (err:ArgumentError) |
| { |
| caught = true; |
| } |
| |
| assertTrue("TextFlow.replaceChildren with a TextFlow argument should throw an error", caught); |
| } |
| |
| [Test] |
| public function resolveInlinesTest():void |
| { |
| var textFlow:TextFlow; |
| const markup:String = "<flow:TextFlow xmlns:flow='http://ns.adobe.com/textLayout/2008'><flow:p><flow:img source='placeholder'/></flow:p></flow:TextFlow>"; |
| |
| var config:Configuration = new Configuration(); |
| config.inlineGraphicResolverFunction = resolveInlines; |
| textFlow = TextConverter.importToFlow(markup, TextConverter.TEXT_LAYOUT_FORMAT, config); |
| |
| textFlow.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, graphicStatusChangeEvent); |
| |
| textFlow.flowComposer.addController(new ContainerController(new Sprite(), 400, 200)); |
| textFlow.flowComposer.updateAllControllers(); |
| |
| assertTrue("Inline Graphic resolution failed", ilgStatus == InlineGraphicElementStatus.READY); // |
| |
| } |
| |
| [Test] |
| public function nestingTest():void |
| { |
| var link1:LinkElement = new LinkElement(); |
| var tcy1:TCYElement = new TCYElement(); |
| var link2:LinkElement = new LinkElement(); |
| |
| var exceptionThrown:Boolean = false; |
| try |
| { |
| link1.addChild(link2); |
| } |
| catch (e:*) |
| { |
| exceptionThrown = true; |
| } |
| assertTrue("Should not be able to add a link child to a link", exceptionThrown); |
| |
| exceptionThrown = false; |
| link1.addChild(tcy1); |
| |
| try |
| { |
| tcy1.addChild(link2); |
| } |
| catch (e:*) |
| { |
| exceptionThrown = true; |
| } |
| assertTrue("Should not be able to add a link child to a TCY if the latter is contained in a link", exceptionThrown); |
| |
| exceptionThrown = false; |
| link1.removeChild(tcy1); |
| tcy1.addChild(link2); |
| |
| try |
| { |
| link1.addChild(tcy1); |
| } |
| catch (e:*) |
| { |
| exceptionThrown = true; |
| } |
| assertTrue("Should not be able to add a TCY child to a link if the former contains a link", exceptionThrown); |
| |
| } |
| |
| [Test] |
| /** |
| * Generate errors and make sure we get the right string |
| */ |
| public function errorThrowing():void |
| { |
| var exceptionThrown:Boolean; |
| |
| //use defaultResourceStringFunction to check the error message |
| // Invalid flowElement |
| try |
| { |
| new FlowGroupElement(); |
| } |
| catch (e:Error) |
| { |
| exceptionThrown = true; |
| var invalidFlowElementConstruct_message:String = e.message; |
| assertTrue("errorThrowing: Error thrown but message is incorrect", e.message == GlobalSettings.resourceStringFunction("invalidFlowElementConstruct")); |
| |
| } |
| assertTrue("errorThrowing: Expected error on new FlowGroupElement did not occur", exceptionThrown); |
| |
| // invalid mxmlchildren assignment |
| exceptionThrown = false; |
| try |
| { |
| var s:Sprite = new Sprite(); |
| new DivElement().mxmlChildren = [ s ]; |
| } |
| catch (e:Error) |
| { |
| exceptionThrown = true; |
| var badMXMLChildrenArgument_message:String = e.message; |
| assertTrue("errorThrowing: Error thrown but message is incorrect", e.message == GlobalSettings.resourceStringFunction("badMXMLChildrenArgument", [ getQualifiedClassName(s) ])); |
| } |
| assertTrue("errorThrowing: Expected error on bad MXMLChildren argument did not occur", exceptionThrown); |
| |
| //use customResourceStringFunction to check the error message |
| try |
| { |
| GlobalSettings.resourceStringFunction = customResourceStringFunction; |
| |
| //check Invalid flowElement and invalid mxmlchildren assignment |
| assertTrue("errorThrowing: Error thrown but message is incorrect", GlobalSettings.resourceStringFunction("invalidFlowElementConstruct_custom") == invalidFlowElementConstruct_message); |
| assertTrue("errorThrowing: Error thrown but message is incorrect", GlobalSettings.resourceStringFunction("badMXMLChildrenArgument_custom", [ getQualifiedClassName(s) ]) == badMXMLChildrenArgument_message); |
| |
| //use custom resource string function to test HTML importer error |
| exceptionThrown = false; |
| var textImporter:ITextImporter = TextConverter.getImporter(TextConverter.TEXT_FIELD_HTML_FORMAT); |
| var textFlow:TextFlow; |
| |
| var markup:String = '<p>Malformed tag next</p/>'; |
| textFlow = textImporter.importToFlow(markup); |
| |
| if (textImporter.errors) |
| { |
| exceptionThrown = true; |
| assertTrue("errorThrowing: Error thrown but message is incorrect", textImporter.errors == GlobalSettings.resourceStringFunction("malformedTag")); |
| } |
| assertTrue("errorThrowing: Expected error on importer did not occur", exceptionThrown); |
| |
| //use custom resource string function to test Text importer error |
| exceptionThrown = false; |
| markup = "<TextFlow columnCount='inherit'" |
| + "<span>Ethan Brand</span></a></p></TextFlow>"; |
| |
| textImporter = TextConverter.getImporter(TextConverter.TEXT_LAYOUT_FORMAT); |
| textFlow = textImporter.importToFlow(markup); |
| |
| if (textImporter.errors) |
| { |
| exceptionThrown = true; |
| assertTrue("errorThrowing: Error thrown but message is incorrect", textImporter.errors == GlobalSettings.resourceStringFunction("XMLParserFailure")); |
| } |
| assertTrue("errorThrowing: Expected error on XML Parser Failure did not occur", exceptionThrown); |
| } |
| finally |
| { |
| GlobalSettings.resourceStringFunction = GlobalSettings.defaultResourceStringFunction; |
| } |
| |
| } |
| |
| [Test] |
| /** |
| * Using above table for permitted child/parent relationships verify that canOwnFlowElement matches the table. |
| */ |
| public function AllNestingTest():void |
| { |
| var parentRow:Array = childParentTable[0].slice(1); |
| var childRow:Array; |
| var childClassName:String; |
| var childClass:Class; |
| var sliceParentTable:Array = childParentTable.slice(1); |
| |
| for each (childRow in sliceParentTable) |
| { |
| childClassName = "flashx.textLayout.elements." + childRow[0]; |
| childClass = childRow[0] as Class; |
| var childElement:FlowElement = new childClass as FlowElement; |
| assertTrue(childElement.defaultTypeName != null, "Bad defaultTypeName in " + childClassName); |
| |
| childRow = childRow.slice(1); |
| for (var idx:int = 0; idx < childRow.length; idx++) |
| { |
| var parentClass:Class = parentRow[idx] as Class |
| var parentElement:FlowElement = new parentClass as FlowElement; |
| |
| // trace(parentClass.toString(),childClass.toString(),childRow[idx]); |
| |
| if (parentElement is FlowGroupElement) |
| { |
| if (FlowGroupElement(parentElement).canOwnFlowElement(childElement)) |
| assertTrue("Bad canOwnFlowElement value for expected allowed " + parentClass.toString() + " " + childClass.toString(), childRow[idx] == "yes"); |
| else |
| assertTrue("Bad canOwnFlowElement value for expected not allowed " + parentClass.toString() + " " + childClass.toString(), childRow[idx] == "no"); |
| } |
| else |
| assertTrue("Bad canOwnFlowElement value for a non FlowGroupElement parent " + parentClass.toString() + " " + childClass.toString(), childRow[idx] == "no"); |
| } |
| } |
| |
| // Check for indirect nesting of SubParagraphGroupElements |
| var textFlow:TextFlow = new TextFlow(); |
| var paragraph:ParagraphElement = new ParagraphElement(); |
| textFlow.replaceChildren(0, 0, paragraph); |
| var parentGroup:SubParagraphGroupElement = new SubParagraphGroupElement(); |
| paragraph.replaceChildren(0, 0, parentGroup); |
| for each (childRow in sliceParentTable) |
| { |
| childClassName = "flashx.textLayout.elements." + childRow[0]; |
| childClass = childRow[0] as Class; |
| var spgeChildElement:SubParagraphGroupElementBase = new childClass as SubParagraphGroupElementBase; |
| if (spgeChildElement) |
| { |
| var groupElement:SubParagraphGroupElement = new SubParagraphGroupElement(); |
| groupElement.replaceChildren(0, 0, new SubParagraphGroupElement()); |
| |
| groupElement.replaceChildren(0, 0, spgeChildElement); |
| |
| assertTrue(parentGroup.canOwnFlowElement(groupElement), "Expected this nesting to work"); |
| |
| if (!spgeChildElement.allowNesting) |
| { |
| var nestingParent:SubParagraphGroupElementBase = new childClass as SubParagraphGroupElementBase; |
| parentGroup.replaceChildren(parentGroup.numChildren, parentGroup.numChildren, nestingParent); |
| var nestingGroup:SubParagraphGroupElement = new SubParagraphGroupElement(); |
| nestingParent.replaceChildren(nestingParent.numChildren, nestingParent.numChildren, nestingGroup); |
| assertTrue("Expected this nesting to fail because of nesting of Link or TCY", !nestingGroup.canOwnFlowElement(groupElement)); |
| } |
| } |
| } |
| } |
| |
| private function Redo():void // KJT |
| { |
| try |
| { |
| SelManager.redo(); |
| } |
| catch (e:Error) |
| { |
| fail("Redo operation failed."); |
| } |
| } |
| |
| private function dispatchEvent(event:Event):void |
| { |
| // assume containers support dispatchEvent. Otherwise we get an error |
| TestFrame.container["dispatchEvent"](event); |
| } |
| |
| private function resolveInlines(ilg:InlineGraphicElement):Object |
| { |
| return ilg.source == "placeholder" ? new Sprite() : ilg.source; |
| } |
| |
| |
| private function graphicStatusChangeEvent(e:StatusChangeEvent):void |
| { |
| ilgStatus = e.status; |
| } |
| |
| private function listenForOpBegin(opEvent:FlowOperationEvent):void |
| { |
| flowOp = opEvent.operation; |
| } |
| |
| tlf_internal static function customResourceStringFunction(resourceName:String, parameters:Array = null):String |
| { |
| var value:String = String(customResourceDict[resourceName]); |
| |
| if (value == null) |
| { |
| value = String(customResourceDict["missingStringResource"]); |
| parameters = [ resourceName ]; |
| } |
| |
| if (parameters) |
| value = customSubstitute(value, parameters); |
| |
| return value; |
| } |
| |
| |
| /** |
| * @private |
| * @param str |
| * @param rest |
| * @return |
| */ |
| tlf_internal static function customSubstitute(str:String, ...rest):String |
| { |
| if (str == null) |
| return ''; |
| |
| // Replace all of the parameters in the msg string. |
| var len:uint = rest.length; |
| var args:Array; |
| if (len == 1 && rest[0] is Array) |
| { |
| args = rest[0] as Array; |
| len = args.length; |
| } |
| else |
| { |
| args = rest; |
| } |
| |
| for (var i:int = 0; i < len; i++) |
| { |
| str = str.replace(new RegExp("\\{" + i + "\\}", "g"), args[i]); |
| } |
| |
| return str; |
| } |
| |
| /** |
| * selecting text from 10 to 20 |
| */ |
| private function selChange(e:Event):void //KJT selection change event method |
| { |
| SelectionChanged = true; |
| } |
| |
| } |
| } |