You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ha...@apache.org on 2017/03/16 13:37:35 UTC
[15/42] flex-asjs git commit: And here’s TLF…
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/ParagraphFormattedElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/ParagraphFormattedElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/ParagraphFormattedElement.as
new file mode 100644
index 0000000..aff7df7
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/ParagraphFormattedElement.as
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.flex.textLayout.elements {
+
+
+
+
+ /** The ParagraphFormattedElement class is an abstract base class for FlowElement classes that have paragraph properties.
+ *
+ * <p>You cannot create a ParagraphFormattedElement object directly. Invoking <code>new ParagraphFormattedElement()</code>
+ * throws an error exception.</p>
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see ContainerFormattedElement
+ * @see ParagraphElement
+ *
+ */
+ public class ParagraphFormattedElement extends FlowGroupElement implements IParagraphFormattedElement
+ {
+ /** @private TODO: DELETE THIS CLASS */
+ public override function shallowCopy(startPos:int = 0, endPos:int = -1):IFlowElement
+ {
+ return super.shallowCopy(startPos, endPos) as ParagraphFormattedElement;
+ }
+ override public function get className():String{
+ return "ParagraphFormattedElement";
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpanElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpanElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpanElement.as
new file mode 100644
index 0000000..57887f2
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpanElement.as
@@ -0,0 +1,608 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+ import org.apache.flex.text.engine.GroupElement;
+ import org.apache.flex.text.engine.TextElement;
+
+ import org.apache.flex.textLayout.container.IContainerController;
+ import org.apache.flex.textLayout.debug.Debugging;
+ import org.apache.flex.textLayout.debug.assert;
+ import org.apache.flex.textLayout.events.ModelChange;
+ import org.apache.flex.textLayout.formats.FormatValue;
+ import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+ import org.apache.flex.textLayout.formats.TextLayoutFormat;
+ import org.apache.flex.textLayout.formats.WhiteSpaceCollapse;
+
+ import org.apache.flex.textLayout.utils.CharacterUtil;
+
+
+
+ [DefaultProperty("mxmlChildren")]
+
+ /**
+ * The SpanElement class represents a run of text that has a single set of formatting attributes applied. SpanElement
+ * objects contain the text in a paragraph. A simple paragraph (ParagraphElement) includes one or more SpanElement objects.
+ *
+ * <p>A ParagraphElement will have a single SpanElement object if all the text in the paragraph shares the same set of
+ * attributes. It has multiple SpanElement objects if the text in the paragraph has multiple formats.</p>
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see FlowElement
+ * @see ParagraphElement
+ * @see TextFlow
+ */
+ public class SpanElement extends FlowLeafElement implements ISpanElement
+ {
+
+ /** Constructor - creates a SpanElement object to hold a run of text in a paragraph.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+
+ public function SpanElement()
+ {
+ super();
+ }
+ override public function get className():String
+ {
+ return "SpanElement";
+ }
+
+ /** @private */
+ override public function createContentElement():void
+ {
+ if (_blockElement && _blockElement.textBlock)
+ return;
+
+ calculateComputedFormat(); // BEFORE creating the element
+ _blockElement = new TextElement(_text,null);
+ CONFIG::debug { Debugging.traceFTECall(_blockElement,null,"new TextElement()"); }
+ CONFIG::debug { Debugging.traceFTEAssign(_blockElement, "text", _text); }
+ super.createContentElement();
+ }
+
+ /** @private */
+ public override function shallowCopy(startPos:int = 0, endPos:int = -1):IFlowElement
+ {
+ if (endPos == -1)
+ endPos = textLength;
+
+ // Note to callers: If you are calling this function outside a try/catch, do ensure that the
+ // state of the model is coherent before the call.
+ var retFlow:SpanElement = super.shallowCopy(startPos, endPos) as SpanElement;
+
+ var startSpan:int = 0;
+ var endSpan:int = startSpan + textLength;
+
+ var leafElStartPos:int = startSpan >= startPos ? startSpan : startPos;
+ var leafElEndPos:int = endSpan < endPos ? endSpan : endPos;
+ if (leafElEndPos == textLength && hasParagraphTerminator)
+ --leafElEndPos;
+
+ if (leafElStartPos > leafElEndPos)
+ throw RangeError(GlobalSettings.resourceStringFunction("badShallowCopyRange"));
+
+ if (((leafElStartPos != endSpan) && CharacterUtil.isLowSurrogate(_text.charCodeAt(leafElStartPos))) ||
+ ((leafElEndPos != 0) && CharacterUtil.isHighSurrogate(_text.charCodeAt(leafElEndPos-1))))
+ throw RangeError(GlobalSettings.resourceStringFunction("badSurrogatePairCopy"));
+
+ if (leafElStartPos != leafElEndPos)
+ retFlow.replaceText(0, retFlow.textLength, _text.substring(leafElStartPos, leafElEndPos));
+
+ return retFlow;
+ }
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "span"; }
+
+ /** @private */
+ public override function get text():String
+ {
+ // test textLength cause this is a property and the debugger may run this calculation in intermediate states
+ if (textLength == 0)
+ return "";
+
+ return hasParagraphTerminator ? _text.substr(0,textLength-1) : _text;
+ }
+ /**
+ * Receives the String of text that this SpanElement object holds.
+ *
+ * <p>The text of a span does not include the carriage return (CR) at the end of the paragraph
+ * but it is included in the value of <code>textLength</code>.</p>
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+
+//TODO this is only override because we temporarily added a setter to FlowLeafElement
+ override public function set text(textValue:String):void
+ {
+ //original code stripped breaking and tab characters. new code moved to collapseWhitevar newLineTabPattern:RegExp = /[\n\r\t]/g;
+ replaceText(0,textLength, textValue);
+ }
+
+ /** @private */
+ public override function getText(relativeStart:int=0, relativeEnd:int=-1, paragraphSeparator:String="\n"):String
+ {
+ if (relativeEnd == -1)
+ relativeEnd = textLength;
+
+ if (textLength && relativeEnd == textLength && hasParagraphTerminator)
+ --relativeEnd; // don't include terminator
+ return _text ? _text.substring(relativeStart, relativeEnd) : "";
+ }
+
+ [RichTextContent]
+ /**
+ * Sets text based on content within span tags; always deletes existing children.
+ * This property is intended for use during MXML compiled import in Flex. Flash Professional ignores this property.
+ * When TLF markup elements have other
+ * TLF markup elements as children, the children are assigned to this property.
+ *
+ * @throws TypeError If array element is not a SpecialCharacterElement or a String.
+ * @param array - an array of elements within span tags. Each element of array must be a SpecialCharacterElement or a String.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+ public function get mxmlChildren():Array
+ {
+ return [ text ];
+ }
+ public function set mxmlChildren(array:Array):void
+ {
+ /* NOTE: all FlowElement implementers and overrides of mxmlChildren must specify [RichTextContent] metadata */
+
+ var str:String = ElementHelper.getSpanText(array);
+ replaceText(0,textLength, str);
+ }
+
+
+ /**
+ * Specifies whether this SpanElement object terminates the paragraph. The SpanElement object that terminates a
+ * paragraph has an extra, hidden character at the end. This character is added automatically by the component and is
+ * included in the value of the <code>textLength</code> property.
+ *
+ * @private */
+
+ public function get hasParagraphTerminator():Boolean
+ {
+ var p:IParagraphElement = getParagraph();
+ return (p && p.getLastLeaf() == this);
+ }
+
+ /** @private */
+ CONFIG::debug public function verifyParagraphTerminator():void
+ {
+ assert(_text && _text.length && _text.charAt(_text.length-1) == ElementConstants.kParagraphTerminator,
+ "attempting to remove para terminator when it doesn't exist");
+ }
+
+
+ /**
+ * Makes a shallow copy of this SpanElement between 2 character positions
+ * and returns it as a FlowElement. Unlike deepCopy, shallowCopy does
+ * not copy any of the children of this SpanElement.
+ *
+ */
+
+ // If I have a sequence of different sorts of spaces (e.g., en quad, hair space), would I want them converted down to one space? Probably not.
+ // For now, u0020 is the only space character we consider for eliminating duplicates, though u00A0 (non-breaking space) is potentially eligible.
+ private static const _dblSpacePattern:RegExp = /[\u0020]{2,}/g;
+ // Tab, line feed, and carriage return
+//TODO regex
+ private static const _newLineTabPattern:RegExp = /foo/g;
+ // private static const _newLineTabPattern:RegExp = /[\u0009\u000a\u000d]/g;
+ private static const _tabPlaceholderPattern:RegExp = /\uE000/g;
+
+ // static private const anyPrintChar:RegExp = /[^\s]/g;
+ // Consider only tab, line feed, carriage return, and space as characters used for pretty-printing.
+ // While debatable, this is consistent with what CSS does.
+//TODO regex
+ static private const anyPrintChar:RegExp = /foo/g;
+// static private const anyPrintChar:RegExp = /[^\u0009\u000a\u000d\u0020]/g;
+
+ /** @private */
+ public override function applyWhiteSpaceCollapse(collapse:String):void
+ {
+ var ffc:ITextLayoutFormat = this.formatForCascade;
+ var wsc:* = ffc ? ffc.whiteSpaceCollapse : undefined;
+ if (wsc !== undefined && wsc != FormatValue.INHERIT)
+ collapse = wsc;
+
+ var origTxt:String = text;
+ var tempTxt:String = origTxt;
+
+ if (!collapse /* null == default value == COLLAPSE */ || collapse == WhiteSpaceCollapse.COLLAPSE)
+ {
+ // The span was added automatically when a String was passed to replaceChildren.
+ // If it contains only whitespace, we remove the text.
+ if (impliedElement && parent != null)
+ {
+ // var matchArray:Array = tempTxt.search(anyPrintChar);
+ if (tempTxt.search(anyPrintChar) == -1)
+ {
+ parent.removeChild(this);
+ return;
+ }
+ }
+
+ // For now, replace the newlines and tabs inside the element with a space.
+ // This is necessary for support of compiled mxml files that have newlines and tabs, because
+ // these are most likely not intended to be part of the text content, but only there so the
+ // text can be conveniently edited in the mxml file. Later on we need to add standalone elements
+ // for <br/> and <tab/>. Note that tab character is not supported in HTML.
+ tempTxt = tempTxt.replace(_newLineTabPattern, " ");
+
+ // Replace sequences of 2 or more whitespace characters with single space
+ tempTxt = tempTxt.replace(_dblSpacePattern, " ");
+ }
+
+ // Replace tab placeholders (used for tabs that are expected to survive whitespace collapse) with '\t'
+ tempTxt = tempTxt.replace(_tabPlaceholderPattern, '\t');
+ if (tempTxt != origTxt)
+ replaceText(0, textLength, tempTxt);
+
+ super.applyWhiteSpaceCollapse(collapse);
+ }
+
+ /**
+ * Updates the text in text span based on the specified start and end positions. To insert text, set the end position
+ * equal to the start position. To append text to the existing text in the span, set the start position and the
+ * end position equal to the length of the existing text.
+ *
+ * <p>The replaced text includes the start character and up to but not including the end character.</p>
+ *
+ * @param relativeStartPosition The index position of the beginning of the text to be replaced,
+ * relative to the start of the span. The first character in the span is at position 0.
+ * @param relativeEndPosition The index one position after the last character of the text to be replaced,
+ * relative to the start of the span. Set this value equal to <code>relativeStartPos</code>
+ * for an insert.
+ * @param textValue The replacement text or the text to add, as the case may be.
+ *
+ * @throws RangeError The <code>relativeStartPosition</code> or <code>relativeEndPosition</code> specified is out of
+ * range or a surrogate pair is being split as a result of the replace.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+
+ public function replaceText(relativeStartPosition:int, relativeEndPosition:int, textValue:String):void
+ {
+ // Note to callers: If you are calling this function outside a try/catch, do ensure that the
+ // state of the model is coherent before the call.
+ if (relativeStartPosition < 0 || relativeEndPosition > textLength || relativeEndPosition < relativeStartPosition)
+ throw RangeError(GlobalSettings.resourceStringFunction("invalidReplaceTextPositions"));
+
+
+ if ((relativeStartPosition != 0 && relativeStartPosition != textLength && CharacterUtil.isLowSurrogate(_text.charCodeAt(relativeStartPosition))) ||
+ (relativeEndPosition != 0 && relativeEndPosition != textLength && CharacterUtil.isHighSurrogate(_text.charCodeAt(relativeEndPosition-1))))
+ throw RangeError (GlobalSettings.resourceStringFunction("invalidSurrogatePairSplit"));
+
+ if (hasParagraphTerminator)
+ {
+ CONFIG::debug { assert(textLength > 0,"invalid span"); }
+ if (relativeStartPosition == textLength)
+ relativeStartPosition--;
+ if (relativeEndPosition == textLength)
+ relativeEndPosition--;
+ }
+
+ if (relativeEndPosition != relativeStartPosition)
+ modelChanged(ModelChange.TEXT_DELETED,this,relativeStartPosition,relativeEndPosition-relativeStartPosition);
+
+ replaceTextInternal(relativeStartPosition,relativeEndPosition,textValue);
+
+ if (textValue && textValue.length)
+ modelChanged(ModelChange.TEXT_INSERTED,this,relativeStartPosition,textValue.length);
+ }
+ private function replaceTextInternal(startPos:int, endPos:int, textValue:String):void
+ {
+ var textValueLength:int = textValue == null ? 0 : textValue.length;
+ var deleteTotal:int = endPos-startPos;
+ var deltaChars:int = textValueLength - deleteTotal;
+ if (_blockElement)
+ {
+ (_blockElement as TextElement).replaceText(startPos,endPos,textValue);
+ _text = _blockElement.rawText;
+ CONFIG::debug { Debugging.traceFTECall(null,_blockElement as TextElement,"replaceText",startPos,endPos,textValue); }
+ }
+ else if (_text)
+ {
+ if (textValue)
+ _text = _text.slice(0, startPos) + textValue + _text.slice(endPos, _text.length);
+ else
+ _text = _text.slice(0, startPos) + _text.slice(endPos, _text.length);
+ }
+ else
+ _text = textValue;
+
+ if (deltaChars != 0)
+ {
+ updateLengths(getAbsoluteStart() + startPos, deltaChars, true);
+ deleteContainerText(endPos,deleteTotal);
+
+ if (textValueLength != 0)
+ {
+ var enclosingContainer:IContainerController = getEnclosingController(startPos);
+ if (enclosingContainer)
+ enclosingContainer.setTextLength(enclosingContainer.textLength + textValueLength);
+ }
+ }
+
+ CONFIG::debug {
+ assert(textLength == (_text ? _text.length : 0),"span textLength doesn't match the length of the text property, text property length is " + _text.length.toString() + " textLength property is " + textLength.toString());
+ assert(_blockElement == null || _blockElement.rawText == _text,"mismatched text");
+ }
+ }
+
+ /** @private */
+ public function addParaTerminator():void
+ {
+ CONFIG::debug
+ {
+ // TODO: Is this assert valid? Do we prevent users from adding para terminators themselves?
+ if (_blockElement && _blockElement.rawText && _blockElement.rawText.length)
+ assert(_blockElement.rawText.charAt(_blockElement.rawText.length-1) != ElementConstants.kParagraphTerminator,"adding para terminator twice");
+ }
+
+ if(_text && _text.substr(-1) == ElementConstants.kParagraphTerminator)// terminator exists. Bail out.
+ return;
+ replaceTextInternal(textLength,textLength,ElementConstants.kParagraphTerminator);
+
+ CONFIG::debug
+ {
+ // TODO: Is this assert valid? Do we prevent users from adding para terminators themselves?
+ if (_blockElement)
+ assert(_blockElement.rawText.charAt(_blockElement.rawText.length-1) == ElementConstants.kParagraphTerminator,"adding para terminator failed");
+ }
+
+ modelChanged(ModelChange.TEXT_INSERTED,this,textLength-1,1);
+ }
+ /** @private */
+ public function removeParaTerminator():void
+ {
+ CONFIG::debug
+ {
+ assert(_text && _text.length && _text.charAt(_text.length-1) == ElementConstants.kParagraphTerminator,
+ "attempting to remove para terminator when it doesn't exist");
+ }
+ if(!_text || _text.substr(-1) != ElementConstants.kParagraphTerminator)// no terminator exists. Bail out.
+ return;
+
+ replaceTextInternal(textLength-1,textLength,"");
+ modelChanged(ModelChange.TEXT_DELETED,this,textLength > 0 ? textLength-1 : 0,1);
+ }
+ // ****************************************
+ // Begin tree modification support code
+ // ****************************************
+
+ /**
+ * Splits this SpanElement object at the specified position and returns a new SpanElement object for the content
+ * that follows the specified position.
+ *
+ * <p>This method throws an error if you attempt to split a surrogate pair. In Unicode UTF-16, a surrogate pair is a pair of
+ * 16-bit code units (a high code unit and a low code unit) that represent one of the abstract Unicode characters
+ * that cannot be represented in a single 16-bit word. The 16-bit high code unit is in the range of D800 to DBFF. The
+ * 16-bit low code unit is in the range of DC00 to DFFF.</p>
+ *
+ * @param relativePosition - relative position in the span to create the split
+ * @return - the newly created span.
+ * @throws RangeError <code>relativePosition</code> is less than 0 or greater than textLength or a surrogate pair is being split.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @private
+ */
+
+ public override function splitAtPosition(relativePosition:int):IFlowElement
+ {
+ // Note to callers: If you are calling this function outside a try/catch, do ensure that the
+ // state of the model is coherent before the call.
+ if (relativePosition < 0 || relativePosition > textLength)
+ throw RangeError(GlobalSettings.resourceStringFunction("invalidSplitAtPosition"));
+
+ if ((relativePosition < textLength) && CharacterUtil.isLowSurrogate(String(text).charCodeAt(relativePosition)))
+ throw RangeError (GlobalSettings.resourceStringFunction("invalidSurrogatePairSplit"));
+
+ var newSpan:ISpanElement = new SpanElement();
+ // clone styling information
+ newSpan.id = this.id;
+ newSpan.typeName = this.typeName;
+
+ if (parent)
+ {
+ var newBlockElement:TextElement;
+ var newSpanLength:int = textLength - relativePosition;
+ if (_blockElement)
+ {
+ // optimized version leverages player APIs
+ // TODO: Jeff to add split on TextElement so we don't have to go find a group every time
+ var group:GroupElement = parent.createContentAsGroup(getElementRelativeStart(parent));
+
+ var elementIndex:int = group.getElementIndex(_blockElement);
+
+ CONFIG::debug { assert(elementIndex == parent.getChildIndex(this),"bad group index"); }
+ CONFIG::debug { assert(elementIndex != -1 && elementIndex < group.elementCount,"bad span split"); }
+ //trace("GROUP BEFORE: " + group.rawText);
+ //trace("BLOCK BEFORE: " + group.block.content.rawText);
+ //trace("calling group.splitTextElement("+elementIndex.toString()+","+relativePosition.toString()+")");
+ group.splitTextElement(elementIndex, relativePosition);
+ CONFIG::debug { Debugging.traceFTECall(null,group,"splitTextElement",elementIndex,relativePosition); }
+
+ //trace("GROUP AFTER: " + group.rawText);
+ //trace("BLOCK AFTER: " + group.block.content.rawText);
+
+ // no guarantee on how the split works
+ _blockElement = group.getElementAt(elementIndex);
+ _text = _blockElement.rawText;
+ CONFIG::debug { Debugging.traceFTECall(_blockElement,group,"getElementAt",elementIndex); }
+ newBlockElement = group.getElementAt(elementIndex+1) as TextElement;
+ CONFIG::debug { Debugging.traceFTECall(newBlockElement,group,"getElementAt",elementIndex+1); }
+ }
+ else if (relativePosition < textLength)
+ {
+ newSpan.text = _text.substr(relativePosition);
+ _text = _text.substring(0, relativePosition);
+ }
+
+ // Split this span at the offset, into two equivalent spans
+ modelChanged(ModelChange.TEXT_DELETED,this,relativePosition,newSpanLength);
+ newSpan.quickInitializeForSplit(this, newSpanLength, newBlockElement);
+
+ setTextLength(relativePosition);
+
+ // slices it in, sets the parent and the start
+ parent.addChildAfterInternal(this,newSpan);
+
+ var p:IParagraphElement = this.getParagraph();
+ p.updateTerminatorSpan(this,newSpan);
+
+ parent.modelChanged(ModelChange.ELEMENT_ADDED,newSpan,newSpan.parentRelativeStart,newSpan.textLength);
+ }
+ else
+ {
+ // this version also works if para is non-null but may not be as efficient.
+ newSpan.format = format;
+
+ // could be we are splitting
+ if (relativePosition < textLength)
+ {
+ newSpan.text = String(this.text).substr(relativePosition);
+ replaceText(relativePosition,textLength,null);
+ }
+ }
+
+ return newSpan;
+ }
+
+ /** @private */
+ public override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+ {
+ if (this.textLength == 1 && !bindableElement)
+ {
+ var p:IParagraphElement = getParagraph();
+ if (p && p.getLastLeaf() == this)
+ {
+ var prevLeaf:IFlowLeafElement = getPreviousLeaf(p);
+ if (prevLeaf)
+ {
+ if (!TextLayoutFormat.isEqual(this.format, prevLeaf.format))
+ this.format = prevLeaf.format;
+ }
+ }
+ }
+ super.normalizeRange(normalizeStart,normalizeEnd);
+ }
+
+ /** @private */
+ public override function mergeToPreviousIfPossible():Boolean
+ {
+ if (parent && !bindableElement)
+ {
+ var myidx:int = parent.getChildIndex(this);
+ if (myidx != 0)
+ {
+ var sib:SpanElement = parent.getChildAt(myidx-1) as SpanElement;
+
+ // If the element we're checking for merge has only the terminator, and the previous element
+ // is not a Span, then we always merge with the previous span (NOT the previous sib).
+ // We just remove this span, and add the terminator to the previous span.
+ if (!sib && this.textLength == 1 && this.hasParagraphTerminator)
+ {
+ var p:IParagraphElement = getParagraph();
+ if (p)
+ {
+ var prevLeaf:IFlowLeafElement = getPreviousLeaf(p) as SpanElement;
+ if (prevLeaf)
+ {
+ parent.removeChildAt(myidx);
+ return true;
+ }
+ }
+ }
+
+ if (sib == null)
+ return false;
+
+
+ // If this has an active event mirror do not merge
+ if (this.hasActiveEventMirror())
+ return false;
+ var thisIsSimpleTerminator:Boolean = textLength == 1 && hasParagraphTerminator;
+ // if sib has an active event mirror still merge if this is a simple terminator span
+ if (sib.hasActiveEventMirror() && !thisIsSimpleTerminator)
+ return false;
+
+ // always merge if this is just a terminator
+ if (thisIsSimpleTerminator || equalStylesForMerge(sib))
+ {
+ CONFIG::debug { assert(this.parent == sib.parent, "Should never merge two spans with different parents!"); }
+ CONFIG::debug { assert(TextLayoutFormat.isEqual(this.formatForCascade,sib.formatForCascade) || (this.textLength == 1 && this.hasParagraphTerminator), "Bad merge!"); }
+
+ // Merge the spans
+ var siblingInsertPosition:int = sib.textLength;
+ sib.replaceText(siblingInsertPosition, siblingInsertPosition, this.text);
+ parent.removeChildAt(myidx);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // ****************************************
+ // Begin debug support code
+ // ****************************************
+
+ /** @private */
+ CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+ {
+ // debugging function that asserts if the flow element tree is in an invalid state
+
+ var rslt:int = super.debugCheckFlowElement(depth,"text:"+String(text).substr(0,32)+" "+extraData);
+
+ assert(_blockElement == null || _blockElement.rawText == _text,"debugCheckFlowElement: mismatched text");
+ var textLen:int = textLength;
+ if (_text)
+ rslt += assert(textLen == _text.length,"span is different than its textElement, span text length is " + _text.length.toString() + " expecting " + textLen.toString());
+ else
+ rslt += assert(textLen == 0,"span is different than its textElement, span text length is null expecting " + textLen.toString());
+ rslt += assert(this != getParagraph().getLastLeaf() || (_text.length >= 1 && _text.substr(_text.length-1,1) == ElementConstants.kParagraphTerminator),"last span in paragraph must end with terminator");
+ return rslt;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpecialCharacterElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpecialCharacterElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpecialCharacterElement.as
new file mode 100644
index 0000000..d63a065
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SpecialCharacterElement.as
@@ -0,0 +1,96 @@
+// //////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+ import org.apache.flex.textLayout.formats.TextLayoutFormat;
+ import org.apache.flex.textLayout.formats.WhiteSpaceCollapse;
+ import org.apache.flex.textLayout.debug.assert;
+
+ /** The SpecialCharacterElement class is an abstract base class for elements that represent special characters.
+ *
+ * <p>You cannot create a SpecialCharacterElement object directly. Invoking <code>new SpecialCharacterElement()</code>
+ * throws an error exception.</p>
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see BreakElement
+ * @see TabElement
+ */
+ public class SpecialCharacterElement extends SpanElement implements ISpecialCharacterElement
+ {
+ /**
+ * Base class - invoking <code>new SpecialCharacterElement()</code> throws an error exception.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+ public function SpecialCharacterElement()
+ {
+ super();
+ // blockElement = new TextElement(null, null);
+
+ // Set WhiteSpaceCollapse.PRESERVE to prevent merging with a sibling span with WhiteSpaceCollapse.COLLAPSE setting
+ // (during normalization). Otherwise the '\t' will be removed during the call to applyWhiteSpaceCollapse (following normalization).
+ // Once applyWhiteSpaceCollapse has been called, we can allow merging.
+ whiteSpaceCollapse = WhiteSpaceCollapse.PRESERVE;
+ }
+ override public function get className():String{
+ return "SpecialCharacterElement";
+ }
+
+ /**
+ * @private
+ * @flexjsignorecoercion org.apache.flex.textLayout.elements.ISpanElement
+ */
+ public override function mergeToPreviousIfPossible():Boolean
+ {
+ if (parent)
+ {
+ var myidx:int = parent.getChildIndex(this);
+ if (myidx != 0)
+ {
+ var sib:ISpanElement = parent.getChildAt(myidx - 1) as ISpanElement;
+ if (sib != null && (sib is SpanElement) && TextLayoutFormat.isEqual(sib.format, format))
+ {
+ CONFIG::debug
+ {
+ assert(this.parent == sib.parent, "Should never merge two spans with different parents!"); }
+
+ // Merge them in the Player's TextBlock structure
+ var siblingInsertPosition:int = sib.textLength;
+ sib.replaceText(siblingInsertPosition, siblingInsertPosition, this.text);
+ parent.replaceChildren(myidx, myidx + 1);
+ return true;
+ }
+ }
+ // make a span and replace ourself
+ var newSib:ISpanElement = ElementHelper.getSpan();
+ newSib.text = this.text;
+ newSib.format = format;
+ parent.replaceChildren(myidx, myidx + 1, newSib);
+ newSib.normalizeRange(0, newSib.textLength);
+ return false;
+ }
+ return false;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElement.as
new file mode 100644
index 0000000..816d1e3
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElement.as
@@ -0,0 +1,95 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+
+
+
+
+ /**
+ * The SubParagraphGroupElement is a grouping element for FlowLeafElements and other classes that extend SubParagraphGroupElementBase.
+ *
+ * @see org.apache.flex.textLayout.elements.SubParagraphGroupElement
+ * @see org.apache.flex.textLayout.elements.SubParagraphGroupElementBase
+ * @see org.apache.flex.textLayout.elements.FlowLeafElement
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public final class SubParagraphGroupElement extends SubParagraphGroupElementBase implements ISubParagraphGroupElement
+ {
+ /** Constructor.
+ * For information on using this class, see <a href='http://blogs.adobe.com/tlf/2011/01/tlf-2-0-changes-subparagraphgroupelements-and-typename-applied-to-textfieldhtmlimporter-and-cssformatresolver.html'>TLF 2.0 SubParagraphGroupElement and typeName</a>.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public function SubParagraphGroupElement()
+ { super(); }
+ override public function get className():String{
+ return "SubParagraphGroupElement";
+ }
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "g"; }
+
+ /** @private Lowest level of precedence. */
+ public override function get precedence():uint
+ { return kMinSPGEPrecedence; }
+
+ /** @private */
+ override public function get allowNesting():Boolean
+ { return true; }
+
+ /** @private */
+ public override function mergeToPreviousIfPossible():Boolean
+ {
+ if (parent && !bindableElement && !hasActiveEventMirror())
+ {
+ var myidx:int = parent.getChildIndex(this);
+ if (myidx != 0)
+ {
+ var sib:SubParagraphGroupElement = parent.getChildAt(myidx-1) as SubParagraphGroupElement;
+ // if only one element has an event mirror use that event mirror
+ // for the merged element; if both have active mirrors, do not merge
+ if (sib == null || sib.hasActiveEventMirror())
+ return false;
+
+ if (equalStylesForMerge(sib))
+ {
+ parent.removeChildAt(myidx);
+ if (numChildren > 0)
+ sib.replaceChildren(sib.numChildren,sib.numChildren,this.mxmlChildren);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElementBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElementBase.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElementBase.as
new file mode 100644
index 0000000..7e22474
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/SubParagraphGroupElementBase.as
@@ -0,0 +1,387 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+ import org.apache.flex.events.IEventDispatcher;
+ import org.apache.flex.text.engine.ContentElement;
+ import org.apache.flex.text.engine.GroupElement;
+ import org.apache.flex.textLayout.debug.Debugging;
+ import org.apache.flex.textLayout.debug.assert;
+ import org.apache.flex.textLayout.events.FlowElementEventDispatcher;
+ import org.apache.flex.textLayout.events.ModelChange;
+
+
+
+
+
+ /**
+ * The SubParagraphGroupElementBase class groups FlowLeafElements together. A SubParagraphGroupElementBase is a child of a
+ * ParagraphElement object and it can contain one or more FlowLeafElement objects as children.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see FlowLeafElement
+ * @see LinkElement
+ * @see ParagraphElement
+ * @see TCYElement
+ */
+ public class SubParagraphGroupElementBase extends FlowGroupElement implements ISubParagraphGroupElementBase
+ {
+ private var _groupElement:GroupElement;
+
+ /** Maximum precedence value @private */
+ public static const kMaxSPGEPrecedence:uint = 1000;
+ /** Minimum precedence value @private */
+ public static const kMinSPGEPrecedence:uint = 0;
+
+ /** @private the event dispatcher that acts as an event mirror */
+ public var _eventMirror:FlowElementEventDispatcher = null;
+
+ /** Constructor - creates a new SubParagraphGroupElementBase instance.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+
+ public function SubParagraphGroupElementBase()
+ { super(); }
+
+ /** @private */
+ override public function createContentElement():void
+ {
+ if (_groupElement)
+ return;
+
+ calculateComputedFormat(); // BEFORE creating the element
+ _groupElement = new GroupElement(null);
+ CONFIG::debug { Debugging.traceFTECall(_groupElement,null,"new GroupElement",null); }
+ for (var i:int = 0; i < numChildren; i++)
+ {
+ var child:IFlowElement = getChildAt(i);
+ child.createContentElement();
+ }
+ if (parent)
+ parent.insertBlockElement(this, _groupElement);
+ }
+
+ /** @private */
+ override public function releaseContentElement():void
+ {
+ if (_groupElement == null)
+ return;
+ for (var i:int = 0; i < numChildren; i++)
+ {
+ var child:IFlowElement = getChildAt(i);
+ child.releaseContentElement();
+ }
+ _groupElement = null;
+ _computedFormat = null;
+ }
+
+ /**
+ * @public getter to return the precedence value of this SubParagraphGroupElementBase
+ * Precedence is used to determine which SPGE element will be the container element
+ * when two or more SPGEs of the same textLength are inside one another.
+ *
+ * Precedence is used to determine which SubParagraphGroupElementBase is the owner when two or
+ * more elements have the same text and are embedded within each other.
+ *
+ * Note: model permits any order and does not enforce precedence. This is only a feature used by the EditManager
+ *
+ * Example: SPGEs A(precedence 900), B(precedence 400), C(precedence 600)
+ * Editing Result when all wrap SpanElement "123"
+ *
+ * <A><C><B>123</B></C></A>
+ *
+ * If two or more SPGE's have the same precedence value, then the alphabetic order is used:
+ * Example: SPGE A(precedence 400), B(precedence 400), C(precedence 600)
+ *
+ * <C><A><B>123</B></A></C>
+ *
+ * Current values for SubParagraphGroupElementBase are:
+ * LinkElement - 800
+ * TCYElement - 100
+ *
+ * If the value is not overriden by descendents of SPGE, then value is kMaxSPGEPrecedence;
+ * @private
+ */
+ public function get precedence():uint
+ { return kMaxSPGEPrecedence; }
+
+
+ /** @private */
+ public function get groupElement():GroupElement
+ { return _groupElement; }
+
+ /** @private
+ * Gets the EventDispatcher associated with this FlowElement. Use the functions
+ * of EventDispatcher such as <code>setEventHandler()</code> and <code>removeEventHandler()</code>
+ * to capture events that happen over this FlowLeafElement object. The
+ * event handler that you specify will be called after this FlowElement object does
+ * the processing it needs to do.
+ *
+ * Note that the event dispatcher will only dispatch FlowElementMouseEvent events.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see org.apache.flex.events.EventDispatcher
+ * @see org.apache.flex.textLayout.events.FlowElementMouseEvent
+ */
+ public override function getEventMirror():IEventDispatcher
+ {
+ if (!_eventMirror)
+ _eventMirror = new FlowElementEventDispatcher(this);
+ return _eventMirror;
+ }
+
+ /** @private
+ * Checks whether an event dispatcher is attached, and if so, if the event dispatcher
+ * has any active listeners.
+ */
+ public override function hasActiveEventMirror():Boolean
+ { return _eventMirror && (_eventMirror._listenerCount != 0); }
+
+
+ /** @private This is done so that the TextContainerManager can discover EventMirrors in a TextFlow. */
+ public override function appendElementsForDelayedUpdate(tf:ITextFlow, changeType:String):void
+ {
+ if (changeType == ModelChange.ELEMENT_ADDED)
+ {
+ if (this.hasActiveEventMirror())
+ {
+ tf.incInteractiveObjectCount();
+ getParagraph().incInteractiveChildrenCount() ;
+ }
+ }
+ else if (changeType == ModelChange.ELEMENT_REMOVAL)
+ {
+ if (this.hasActiveEventMirror())
+ {
+ tf.decInteractiveObjectCount();
+ getParagraph().decInteractiveChildrenCount() ;
+ }
+ }
+ super.appendElementsForDelayedUpdate(tf,changeType);
+ }
+
+ /** @private */
+ public override function createContentAsGroup(pos:int=0):GroupElement
+ { return groupElement; }
+
+ /** @private */
+ public override function removeBlockElement(child:IFlowElement, block:ContentElement):void
+ {
+ var idx:int = this.getChildIndex(child);
+ groupElement.replaceElements(idx,idx+1,null);
+ CONFIG::debug { Debugging.traceFTECall(null,groupElement,"replaceElements",idx,idx+1,null); }
+ }
+
+ /** @private */
+ public override function insertBlockElement(child:IFlowElement, block:ContentElement):void
+ {
+ if (groupElement)
+ {
+ var idx:int = this.getChildIndex(child);
+ var gc:Vector.<ContentElement> = new Vector.<ContentElement>();
+ CONFIG::debug { Debugging.traceFTECall(gc,null,"new Vector.<ContentElement>()"); }
+ gc.push(block);
+ CONFIG::debug { Debugging.traceFTECall(null,gc,"push",block); }
+ groupElement.replaceElements(idx,idx,gc);
+ CONFIG::debug { Debugging.traceFTECall(null,groupElement,"replaceElements",idx,idx,gc); }
+ }
+ else
+ {
+ child.releaseContentElement();
+
+ var para:IParagraphElement = getParagraph();
+ if (para)
+ para.createTextBlock();
+ }
+ }
+
+
+ /** @private */
+ public override function hasBlockElement():Boolean
+ { return groupElement != null; }
+
+ /** @private */
+ override public function setParentAndRelativeStart(newParent:IFlowGroupElement,newStart:int):void
+ {
+ if (newParent == parent)
+ return;
+
+ // remove textElement from the parent content
+ if (parent && parent.hasBlockElement() && groupElement)
+ parent.removeBlockElement(this,groupElement);
+ if (newParent && !newParent.hasBlockElement() && groupElement)
+ newParent.createContentElement();
+
+ super.setParentAndRelativeStart(newParent,newStart);
+
+ // Update the FTE ContentElement structure. If the parent has FTE elements, then create FTE elements for the leaf node
+ // if it doesn't already have them, and add them in. If the parent does not have FTE elements, release the leaf's FTE
+ // elements also so they match.
+ if (parent && parent.hasBlockElement())
+ {
+ if (!groupElement)
+ createContentElement();
+ else
+ parent.insertBlockElement(this,groupElement);
+ }
+ }
+
+ /** @private */
+ public override function replaceChildren(beginChildIndex:int,endChildIndex:int,...rest):void
+ {
+
+ var applyParams:Array = [beginChildIndex, endChildIndex];
+//TODO fix super
+ super.replaceChildren.apply(this, applyParams.concat(rest));
+
+ var p:IParagraphElement = this.getParagraph();
+ if (p)
+ p.ensureTerminatorAfterReplace();
+ }
+
+ /** @private */
+ public override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+ {
+ var idx:int = findChildIndexAtPosition(normalizeStart);
+ if (idx != -1 && idx < numChildren)
+ {
+ var child:IFlowElement = getChildAt(idx);
+ normalizeStart = normalizeStart-child.parentRelativeStart;
+
+ CONFIG::debug { assert(normalizeStart >= 0, "bad normalizeStart in normalizeRange"); }
+ for (;;)
+ {
+ // watch out for changes in the length of the child
+ var origChildEnd:int = child.parentRelativeStart+child.textLength;
+ child.normalizeRange(normalizeStart,normalizeEnd-child.parentRelativeStart);
+ var newChildEnd:int = child.parentRelativeStart+child.textLength;
+ normalizeEnd += newChildEnd-origChildEnd; // adjust
+
+ // no zero length children
+ if (child.textLength == 0 && !child.bindableElement)
+ replaceChildren(idx,idx+1);
+ else if (child.mergeToPreviousIfPossible())
+ {
+ var prevElement:IFlowElement = this.getChildAt(idx-1);
+ // possibly optimize the start to the length of prevelement before the merge
+ prevElement.normalizeRange(0,prevElement.textLength);
+ }
+ else
+ idx++;
+
+ if (idx == numChildren)
+ break;
+
+ // next child
+ child = getChildAt(idx);
+
+ if (child.parentRelativeStart > normalizeEnd)
+ break;
+
+ normalizeStart = 0; // for the next child
+ }
+ }
+ ElementHelper.normalizeSubParagraphRange(this);
+ }
+
+ /** @private
+ * SubParagraphGroupElement allow deep nesting, but LinkElements and TCYElements do not allow nesting (you can't have a link inside another
+ * link no matter how many group elements are in between). This function is called only from within the class hierarchy to find out whether
+ * a sub-class allows nesting or not. */
+ public function get allowNesting():Boolean
+ {
+ return false;
+ }
+
+ /** A LinkElement cannot be nested in another LinkElement, regardless of what elements are in between in the hierarchy.
+ * Likewise a TCYElemen may not be nested. This function checks an incoming element to see if any of its children would
+ * be disallowed if added to this. */
+ private function checkForNesting(element:SubParagraphGroupElementBase):Boolean
+ {
+ if (element)
+ {
+ if (!element.allowNesting)
+ {
+ if (this.className == element.className || this.getParentByType(element.className))
+ return false;
+ }
+ for (var i:int = element.numChildren - 1; i >= 0; --i)
+ if (!checkForNesting(element.getChildAt(i) as SubParagraphGroupElementBase))
+ return false;
+ }
+ return true;
+ }
+
+ /** @private */
+ public override function canOwnFlowElement(elem:IFlowElement):Boolean
+ {
+ // Only allow sub-paragraph group elements (with restrictions) and leaf elements
+ if (elem is IFlowLeafElement)
+ return true;
+
+ if (elem is SubParagraphGroupElementBase && checkForNesting(elem as SubParagraphGroupElementBase))
+ return true;
+
+ return false;
+ }
+
+ /** Helper function for determination of where text should be inserted. In the case of LinkElements,
+ * text inserted before the LinkElement and text inserted after the LinkElement should not become
+ * par of the link. However, for most other SubParagraphGroupElementBase, inserted text should become
+ * part of the SubParagraphGroupElementBase.
+ * @private
+ * */
+ public function acceptTextBefore():Boolean
+ { return true; }
+
+ /** Helper function for determination of where text should be inserted. In the case of LinkElements,
+ * text inserted before the LinkElement and text inserted after the LinkElement should not become
+ * par of the link. However, for most other SubParagraphGroupElementBase, inserted text should become
+ * part of the SubParagraphGroupElementBase.
+ * @private
+ * */
+ public function acceptTextAfter():Boolean
+ { return true; }
+
+ /** @private */
+ CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+ {
+ // debugging function that asserts if the flow element tree is in an invalid state
+ var rslt:int = super.debugCheckFlowElement(depth," fte:"+getDebugIdentity(groupElement)+" "+extraData);
+ rslt += assert(getParagraph() != null && (parent is IParagraphElement || parent is SubParagraphGroupElementBase), "SubParagraphGroupElementBase must be nested in a pargraph");
+
+ //groupElement can be null if the Paragraph is overset or not yet composed. Don't check elementCount - Watson 2283828
+ if(this.groupElement)
+ rslt += assert(this.groupElement.elementCount == this.numChildren,"Bad element count in SubParagraphGroupElementBase");
+
+ if (parent is IParagraphElement)
+ rslt += assert(this.groupElement != IParagraphElement(parent).getTextBlock().content,"Bad group");
+ return rslt;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TCYElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TCYElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TCYElement.as
new file mode 100644
index 0000000..3139c0b
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TCYElement.as
@@ -0,0 +1,141 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+ import org.apache.flex.text.engine.TextRotation;
+ import org.apache.flex.textLayout.debug.Debugging;
+ import org.apache.flex.textLayout.formats.BlockProgression;
+
+ /**
+ * The TCYElement (Tatechuuyoko - ta-tae-chu-yo-ko) class is a subclass of SubParagraphGroupElementBase that causes
+ * text to draw horizontally within a vertical line. Traditionally, it is used to make small
+ * blocks of non-Japanese text or numbers, such as dates, more readable. TCY can be applied to
+ * horizontal text, but has no effect on drawing style unless and until it is turned vertically.
+ *
+ * TCY blocks which contain no text will be removed from the text flow during the normalization process.
+ * <p>
+ * In the example below, the image on the right shows TCY applied to the number 57, while the
+ * image on the left has no TCY formatting.</p>
+ * <p><img src="../../../images/textLayout_TCYElement.png" alt="TCYElement" border="0"/>
+ * </p>
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see TextFlow
+ * @see ParagraphElement
+ * @see SpanElement
+ */
+ public final class TCYElement extends SubParagraphGroupElementBase implements ITCYElement
+ {
+ /** Constructor - creates a new TCYElement instance.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public function TCYElement()
+ {
+ super();
+ }
+ override public function get className():String{
+ return "TCYElement";
+ }
+
+ /** @private */
+ override public function createContentElement():void
+ {
+ super.createContentElement();
+ updateTCYRotation();
+ }
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "tcy"; }
+
+ /** @private */
+ public override function get precedence():uint { return 100; }
+
+ /** @private */
+ public override function mergeToPreviousIfPossible():Boolean
+ {
+ if (parent && !bindableElement)
+ {
+ var myidx:int = parent.getChildIndex(this);
+ if (myidx != 0)
+ {
+ var prevEl:TCYElement = parent.getChildAt(myidx - 1) as TCYElement;
+ if(prevEl)
+ {
+ while(this.numChildren > 0)
+ {
+ var xferEl:IFlowElement = this.getChildAt(0);
+ replaceChildren(0, 1);
+ prevEl.replaceChildren(prevEl.numChildren, prevEl.numChildren, xferEl);
+ }
+ parent.replaceChildren(myidx, myidx + 1);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /** @private */
+ public override function acceptTextBefore():Boolean
+ {
+ return false;
+ }
+
+ /** @private */
+ public override function setParentAndRelativeStart(newParent:IFlowGroupElement,newStart:int):void
+ {
+ super.setParentAndRelativeStart(newParent,newStart);
+ updateTCYRotation();
+ }
+
+ /** @private */
+ public override function formatChanged(notifyModelChanged:Boolean = true):void
+ {
+ super.formatChanged(notifyModelChanged);
+ updateTCYRotation();
+ }
+
+
+ /** @private */
+ private function updateTCYRotation():void
+ {
+ var contElement:IContainerFormattedElement = getAncestorWithContainer();
+ if (groupElement)
+ {
+ groupElement.textRotation = (contElement && contElement.computedFormat.blockProgression == BlockProgression.RL) ? TextRotation.ROTATE_270 : TextRotation.ROTATE_0;
+ CONFIG::debug { Debugging.traceFTEAssign(groupElement,"textRotation",groupElement.textRotation); }
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TabElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TabElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TabElement.as
new file mode 100644
index 0000000..2879cae
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TabElement.as
@@ -0,0 +1,69 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+
+
+
+ /**
+ * The TabElement class represents a <tab/> in the text flow. You assign tab stops as an array of TabStopFormat objects to the
+ * <code>ParagraphElement.tabStops</code> property.
+ *
+ * <p><strong>Note</strong>:This class exists primarily to support <tab/> in MXML markup. You can add tab characters (\t) directly
+ * into the text like this:</p>
+ *
+ * <listing version="3.0" >
+ * spanElement1.text += '\t';
+ * </listing>
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see org.apache.flex.textLayout.formats.TabStopFormat
+ * @see FlowElement#tabStops
+ * @see SpanElement
+ */
+
+ public final class TabElement extends SpecialCharacterElement
+ {
+ /** Constructor - creates a new TabElement instance.
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+ public function TabElement()
+ {
+ super();
+ this.text = '\t';
+ }
+ override public function get className():String{
+ return "TabElement";
+ }
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "tab"; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBlockContainer.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBlockContainer.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBlockContainer.as
new file mode 100644
index 0000000..5f3f39c
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBlockContainer.as
@@ -0,0 +1,50 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+ import org.apache.flex.core.UIBase;
+ import org.apache.flex.textLayout.compose.ITextFlowTableBlock;
+
+ /**
+ * The sprite that contains the table cells.
+ **/
+ public class TableBlockContainer extends UIBase
+ {
+//TODO this should probably be an interface to support multiple UI implementations.
+// It's probably not going to work with either SVG or Canvas without hacks.
+
+ public function TableBlockContainer()
+ {
+ super();
+ }
+
+ /**
+ * A reference to the TextFlowTableBlock
+ **/
+ public var userData:ITextFlowTableBlock;
+ public function getTableWidth():Number
+ {
+ if(!userData)
+ return NaN;
+ if(!userData.parentTable)
+ return NaN;
+ return userData.parentTable.width;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBodyElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBodyElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBodyElement.as
new file mode 100644
index 0000000..4268118
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableBodyElement.as
@@ -0,0 +1,63 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+
+
+
+
+ /**
+ * <p> TableBodyElement is an item in a TableElement. It most commonly contains one or more TableRowElement objects,
+ * A TableBodyElement always appears within a TableElement.</p>
+ *
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public final class TableBodyElement extends TableFormattedElement
+ {
+ override public function get className():String{
+ return "TableBodyElement";
+ }
+ public var height:Number;
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "tbody"; }
+
+ /** @private */
+ public override function canOwnFlowElement(elem:IFlowElement):Boolean
+ {
+ return (elem is ITableRowElement);
+ }
+
+ /** @private if its in a numbered list expand the damage to all list items - causes the numbers to be regenerated */
+ public override function modelChanged(changeType:String, elem:IFlowElement, changeStart:int, changeLen:int, needNormalize:Boolean = true, bumpGeneration:Boolean = true):void
+ {
+ super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableCellElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableCellElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableCellElement.as
new file mode 100644
index 0000000..45f0de5
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableCellElement.as
@@ -0,0 +1,457 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+ import org.apache.flex.textLayout.container.ContainerUtil;
+ import org.apache.flex.textLayout.factory.TLFFactory;
+ import org.apache.flex.textLayout.factory.ITLFFactory;
+ import org.apache.flex.reflection.getDefinitionByName;
+ import org.apache.flex.reflection.getQualifiedClassName;
+
+ import org.apache.flex.textLayout.compose.ITextFlowLine;
+ import org.apache.flex.textLayout.container.IContainerController;
+ import org.apache.flex.textLayout.events.DamageEvent;
+ import org.apache.flex.textLayout.formats.BlockProgression;
+
+
+
+
+ /**
+ * TableCellElement is an item in a TableElement. It most commonly contains one or more ParagraphElement objects.
+ *
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public final class TableCellElement extends TableFormattedElement implements ITableCellElement
+ {
+ private var _width:Number;
+ private var _height:Number;
+
+ private var _parcelIndex:int;
+ private var _container:CellContainer;
+ private var _enableIME:Boolean = true;
+ private var _damaged:Boolean = true;
+ private var _controller:IContainerController;
+
+ private var _rowSpan:uint = 1;
+ private var _columnSpan:uint = 1;
+ private var _rowIndex:int = -1;
+ private var _colIndex:int = -1;
+ private var _includeDescentInCellBounds:Boolean;
+
+ public function TableCellElement()
+ {
+ super();
+ _controller = ContainerUtil.getController(container, NaN, NaN);
+ }
+ override public function get className():String{
+ return "TableCellElement";
+ }
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "td"; }
+
+ /** @private */
+ public override function canOwnFlowElement(elem:IFlowElement):Boolean
+ {// Table cells have no TLF children. Instead it contains its own TextFlow.
+ return (elem is IFlowElement);
+ }
+
+ public function isDamaged():Boolean {
+ return _damaged || (_textFlow && _textFlow.flowComposer.isPotentiallyDamaged(_textFlow.textLength));
+ }
+
+ private var _savedPaddingTop:Number = 0;
+ private var _savedPaddingBottom:Number = 0;
+ private var _savedPaddingLeft:Number = 0;
+ private var _savedPaddingRight:Number = 0;
+
+ public function compose():Boolean {
+
+ var pt:Number = getEffectivePaddingTop();
+ var pb:Number = getEffectivePaddingBottom();
+ var pl:Number = getEffectivePaddingLeft();
+ var pr:Number = getEffectivePaddingRight();
+
+ if(pt != _savedPaddingTop)
+ {
+ _controller.paddingTop = _savedPaddingTop = pt;
+ }
+ if(pb != _savedPaddingBottom)
+ {
+ _controller.paddingBottom = _savedPaddingBottom = pb;
+ }
+ if(pl != _savedPaddingLeft)
+ {
+ _controller.paddingLeft = _savedPaddingLeft = pl;
+ }
+ if(pr != _savedPaddingRight)
+ {
+ _controller.paddingRight = _savedPaddingRight = pr;
+ }
+
+ var table:ITableElement = this.table;
+
+ _damaged = false;
+
+ var compWidth:Number = 0;
+ for(var i:int=0;i<columnSpan;i++)
+ {
+ if (table && table.getColumnAt(colIndex+i)) {
+ compWidth += table.getColumnAt(colIndex+i).columnWidth;
+ }
+
+ }
+ width = compWidth;
+
+ if (_textFlow && _textFlow.flowComposer) {
+ return _textFlow.flowComposer.compose();
+ }
+
+ return false;
+ }
+
+ public function update():Boolean
+ {
+ if(_textFlow && _textFlow.flowComposer){
+ return _textFlow.flowComposer.updateAllControllers();
+ }
+ return false;
+ }
+
+ public function get parcelIndex():int
+ {
+ return _parcelIndex;
+ }
+
+ public function set parcelIndex(value:int):void
+ {
+ _parcelIndex = value;
+ }
+
+ public function get rowIndex():int
+ {
+ return _rowIndex;
+ }
+
+ public function set rowIndex(value:int):void
+ {
+ _rowIndex = value;
+ }
+
+ public function get colIndex():int
+ {
+ return _colIndex;
+ }
+
+ public function set colIndex(value:int):void
+ {
+ _colIndex = value;
+ }
+
+ protected var _textFlow:ITextFlow;
+
+ public function get textFlow():ITextFlow {
+
+ if (_textFlow == null) {
+ var tf:ITextFlow = getTextFlow();
+ var tlfFactory:ITLFFactory;
+ if(tf)
+ tlfFactory = tf.tlfFactory;
+
+ var flow:ITextFlow = ElementHelper.getDefaultTextFlow(tlfFactory);
+
+ if (table && table.getTextFlow() && table.getTextFlow().interactionManager) {
+ flow.interactionManager = _textFlow.interactionManager.copy(true);
+ }
+ else if(table && table.getTextFlow() && table.getTextFlow().interactionManager) {
+ var im:Class = getDefinitionByName(getQualifiedClassName(table.getTextFlow().interactionManager)) as Class;
+ flow.interactionManager = new im();
+ }
+ else {
+ flow.normalize();
+ }
+
+ _textFlow = flow;
+
+ }
+
+ return _textFlow;
+ }
+
+ public function set textFlow(value:ITextFlow):void
+ {
+ if (_textFlow) {
+ _textFlow.removeEventListener(DamageEvent.DAMAGE, handleCellDamage);
+ _textFlow.flowComposer.removeAllControllers();
+ }
+
+ _textFlow = value;
+ _textFlow.parentElement = this;
+ _textFlow.flowComposer.addController(_controller);
+ _textFlow.addEventListener(DamageEvent.DAMAGE, handleCellDamage);
+
+ }
+
+ public function get controller():IContainerController {
+ return _controller;
+ }
+
+ private function handleCellDamage(ev:DamageEvent):void{
+ damage();
+ }
+
+ public function get enableIME():Boolean
+ {
+ return _enableIME;
+ }
+
+ public function set enableIME(value:Boolean):void
+ {
+ _enableIME = value;
+ }
+
+ public function get container():CellContainer{
+ if(!_container){
+ _container = new CellContainer(enableIME);
+ _container.cellElement = this;
+ }
+
+ return _container;
+ }
+
+ /**
+ * Gets the width.
+ **/
+ public function get width():Number
+ {
+ return _width;
+ }
+
+ /**
+ * @private
+ **/
+ public function set width(value:Number):void
+ {
+ if(_width != value) {
+ _damaged = true;
+ }
+
+ _width = value;
+
+ _controller.setCompositionSize(_width, _controller.compositionHeight);
+ }
+
+ /**
+ * Returns the height of the cell.
+ **/
+ public function get height():Number
+ {
+ //return getRowHeight(); not sure if we should always use row height
+ return _height;
+ }
+
+ /**
+ * @private
+ **/
+ public function set height(value:Number):void
+ {
+ if (_height != value) {
+ _damaged = true;
+ }
+
+ _height = value;
+
+ _controller.setCompositionSize(_controller.compositionWidth, _height);
+ }
+
+ public function getComposedHeight():Number
+ {
+ var descent:Number = 0;
+ if(!includeDescentInCellBounds)
+ {
+ if(_textFlow.flowComposer && _textFlow.flowComposer.numLines)
+ {
+ var lastLine:ITextFlowLine = _textFlow.flowComposer.getLineAt(_textFlow.flowComposer.numLines-1);
+ if(lastLine)
+ descent = lastLine.descent;
+ }
+ }
+ return (_controller.getContentBounds().height - descent);
+ }
+
+ public function getRowHeight():Number
+ {
+ return getRow() ? getRow().composedHeight : NaN;
+ }
+
+ public function get rowSpan():uint
+ {
+ return _rowSpan;
+ }
+
+ public function set rowSpan(value:uint):void
+ {
+ if(value >= 1)
+ _rowSpan = value;
+ }
+
+ public function get columnSpan():uint
+ {
+ return _columnSpan;
+ }
+
+ public function set columnSpan(value:uint):void
+ {
+ if(value >= 1)
+ _columnSpan = value;
+ }
+
+ public function updateCompositionShapes():void{
+ _controller.updateCompositionShapes();
+ }
+
+ /**
+ * Return the row that this cell is part of or null
+ * if not part of a row.
+ **/
+ public function getRow():ITableRowElement
+ {
+ return table ? table.getRowAt(rowIndex) : null;
+ }
+
+ /**
+ * Returns the next cell in the table or null if not part of a
+ * table or no cells exist after this cell.
+ **/
+ public function getNextCell():ITableCellElement {
+ return table ? table.getNextCell(this) : null;
+ }
+
+ /**
+ * Returns the previous cell in the table or null if not part of a
+ * table or no cells exist before this cell.
+ **/
+ public function getPreviousCell():ITableCellElement {
+ return table ? table.getPreviousCell(this) : null;
+ }
+
+ public function get x():Number
+ {
+ return container.x;
+ }
+
+ public function set x(value:Number):void
+ {
+ container.x = value;
+ }
+
+ public function get y():Number
+ {
+ return container.y;
+ }
+
+ public function set y(value:Number):void
+ {
+ container.y = value;
+ }
+
+ public function damage():void
+ {
+ if (table) {
+ table.hasCellDamage = true;
+ }
+
+ _damaged = true;
+ }
+
+ /**
+ * Adds in the table cell spacing, border stroke width.
+ * We may be able to set this value when the format changes.
+ * For now we just want to get it to work.
+ **/
+ public function getTotalPaddingWidth():Number {
+ var paddingAmount:Number = 0;
+
+ // no textflow is no padding
+ if (!textFlow) {
+ return 0;
+ }
+
+ if (table && table.cellSpacing!=undefined) {
+ paddingAmount += table.cellSpacing;
+ }
+
+ if (textFlow.computedFormat.blockProgression == BlockProgression.RL) {
+ paddingAmount += Math.max(getEffectivePaddingTop() + getEffectivePaddingBottom(), getEffectiveBorderTopWidth() + getEffectiveBorderBottomWidth());
+ }
+ else {
+ paddingAmount += Math.max(getEffectivePaddingLeft() + getEffectivePaddingRight(), getEffectiveBorderLeftWidth() + getEffectiveBorderRightWidth());
+ }
+
+ return paddingAmount;
+ }
+
+ /**
+ * Adds in the table cell spacing, border stroke height.
+ * We may be able to set this value when the format changes.
+ **/
+ public function getTotalPaddingHeight():Number {
+ var paddingAmount:Number = 0;
+
+ // no textflow is no padding
+ if (!textFlow) {
+ return 0;
+ }
+
+ if (table && table.cellSpacing!=undefined) {
+ paddingAmount += table.cellSpacing;
+ }
+
+ if (textFlow.computedFormat.blockProgression == BlockProgression.RL) {
+ paddingAmount += Math.max(getEffectivePaddingLeft() + getEffectivePaddingRight(), getEffectiveBorderLeftWidth() + getEffectiveBorderRightWidth());
+ }
+ else {
+ paddingAmount += Math.max(getEffectivePaddingTop() + getEffectivePaddingBottom(), getEffectiveBorderTopWidth() + getEffectiveBorderBottomWidth());
+ }
+
+ return paddingAmount;
+ }
+
+ public function get includeDescentInCellBounds():Boolean
+ {
+ return _includeDescentInCellBounds;
+ }
+
+ public function set includeDescentInCellBounds(value:Boolean):void
+ {
+ _includeDescentInCellBounds = value;
+ }
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColElement.as
new file mode 100644
index 0000000..449d1a3
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColElement.as
@@ -0,0 +1,116 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+ import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+
+
+
+
+ /**
+ * <p> TableColElement is an item in a TableElement. It only contains the information of the column formats,
+ * A TableColElement always appears within a TableElement, TableColGroupElement.</p>
+ *
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public final class TableColElement extends TableFormattedElement implements ITableColElement
+ {
+ // public var height:Number;
+ private var _x:Number;
+ private var _colIndex:int;
+
+ public function TableColElement(format:ITextLayoutFormat=null)
+ {
+ super();
+ if(format)
+ this.format = format;
+ }
+
+ override public function get className():String{
+ return "TableColElement";
+ }
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "col"; }
+
+ /** @private */
+ public override function canOwnFlowElement(elem:IFlowElement):Boolean
+ {
+ return false;
+ }
+
+ /** @private if its in a numbered list expand the damage to all list items - causes the numbers to be regenerated */
+ public override function modelChanged(changeType:String, elem:IFlowElement, changeStart:int, changeLen:int, needNormalize:Boolean = true, bumpGeneration:Boolean = true):void
+ {
+ super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
+ }
+
+ /**
+ * Get a Vector of cells or null if the column contains no cells
+ **/
+ public function get cells():Vector.<ITableCellElement> {
+
+ if (!table) {
+ return null;
+ }
+
+ return table.getCellsForColumn(this);
+ }
+
+ /**
+ * Returns the number of cells in this column.
+ **/
+ public function get numCells():int {
+
+ if (!table) {
+ return 0;
+ }
+
+ return table.getCellsForColumn(this).length;
+ }
+
+ public function get x():Number
+ {
+ return _x;
+ }
+
+ public function set x(x:Number):void
+ {
+ this._x = x;
+ }
+
+ public function get colIndex():int
+ {
+ return _colIndex;
+ }
+
+ public function set colIndex(colIndex:int):void
+ {
+ this._colIndex = colIndex;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColGroupElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColGroupElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColGroupElement.as
new file mode 100644
index 0000000..92f3770
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableColGroupElement.as
@@ -0,0 +1,63 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+
+
+
+
+ /**
+ * <p> TableColGroupElement is an item in a TableElement. It most commonly contains one or more ParagraphElement objects,
+ * A TableRowElement always appears within a TableElement.</p>
+ *
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public final class TableColGroupElement extends TableFormattedElement
+ {
+ override public function get className():String{
+ return "TableColGroupElement";
+ }
+ public var height:Number;
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "colgroup"; }
+
+ /** @private */
+ public override function canOwnFlowElement(elem:IFlowElement):Boolean
+ {
+ return (elem is ITableColElement);
+ }
+
+ /** @private if its in a numbered list expand the damage to all list items - causes the numbers to be regenerated */
+ public override function modelChanged(changeType:String, elem:IFlowElement, changeStart:int, changeLen:int, needNormalize:Boolean = true, bumpGeneration:Boolean = true):void
+ {
+ super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableDataCellElement.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableDataCellElement.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableDataCellElement.as
new file mode 100644
index 0000000..c31435b
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/elements/TableDataCellElement.as
@@ -0,0 +1,126 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.textLayout.elements
+{
+
+
+
+
+
+ /**
+ * <p> TableDataCellElement is an item in a TableRowElement. It most commonly contains one or more IParagraphElement objects,
+ * A TableDataCellElement always appears within a TableRowElement.</p>
+ *
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ */
+ public final class TableDataCellElement extends TableFormattedElement
+ {
+ public var x:Number;
+ public var y:Number;
+ public var width:Number;
+ public var height:Number;
+ private var _parcelIndex:int;
+
+ private var _rowIndex:int;
+ private var _colIndex:int;
+
+ override public function get className():String{
+ return "TableDataCellElement";
+ }
+
+ /** @private */
+ override protected function get abstract():Boolean
+ { return false; }
+
+ /** @private */
+ public override function get defaultTypeName():String
+ { return "td"; }
+
+ /** @private if its in a numbered list expand the damage to all list items - causes the numbers to be regenerated */
+ public override function modelChanged(changeType:String, elem:IFlowElement, changeStart:int, changeLen:int, needNormalize:Boolean = true, bumpGeneration:Boolean = true):void
+ {
+ super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
+ }
+
+ /** @private ListItems must begin with zero or more divs with a paragraph */
+ public function normalizeNeedsInitialParagraph():Boolean
+ {
+ var p:FlowGroupElement = this;
+ while (p)
+ {
+ p = p.getChildAt(0) as FlowGroupElement;
+ if (p is IParagraphElement)
+ return false;
+ if (!(p is IDivElement))
+ return true;
+ }
+ return true;
+ }
+
+ /** @private */
+ public override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+ {
+ super.normalizeRange(normalizeStart,normalizeEnd);
+
+ // A TableDataCellElement must have a Paragraph at the start.
+ // note not all browsers behave this way.
+ if (normalizeNeedsInitialParagraph())
+ {
+ var p:IParagraphElement = ElementHelper.getParagraph();
+ replaceChildren(0,0,p);
+ p.normalizeRange(0,p.textLength);
+ }
+ }
+
+ public function get parcelIndex():int
+ {
+ return _parcelIndex;
+ }
+
+ public function set parcelIndex(value:int):void
+ {
+ _parcelIndex = value;
+ }
+
+ public function get rowIndex():int
+ {
+ return _rowIndex;
+ }
+
+ public function set rowIndex(value:int):void
+ {
+ _rowIndex = value;
+ }
+
+ public function get colIndex():int
+ {
+ return _colIndex;
+ }
+
+ public function set colIndex(value:int):void
+ {
+ _colIndex = value;
+ }
+
+ }
+}