You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by pi...@apache.org on 2014/11/28 01:20:41 UTC

[01/25] git commit: [flex-tlf] [refs/heads/develop] - Commit of table work

Repository: flex-tlf
Updated Branches:
  refs/heads/develop 222d745e8 -> 86fbe9325


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TableRowElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableRowElement.as b/textLayout/src/flashx/textLayout/elements/TableRowElement.as
index dca92d3..0a23abc 100644
--- a/textLayout/src/flashx/textLayout/elements/TableRowElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableRowElement.as
@@ -18,13 +18,18 @@
 ////////////////////////////////////////////////////////////////////////////////
 package flashx.textLayout.elements
 {
+	import flash.utils.getQualifiedClassName;
+	
 	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.edit.EditManager;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.formats.ITextLayoutFormat;
 	
 	use namespace tlf_internal;
 	
 	/** 
-	 * <p> TableRowElement is an item in a TableElement. It most commonly contains one or more TableDataCellElement objects, 
-	 * A TableRowElement always appears within a TableElement, TableBodyElement.</p>
+	 * TableRowElement is an item in a TableElement. It most commonly contains one or more TableCellElement objects, 
+	 * A TableRowElement always appears within a TableElement, TableBodyElement.
 	 *
 	 * 
 	 * @playerversion Flash 10
@@ -32,7 +37,7 @@ package flashx.textLayout.elements
 	 * @langversion 3.0
 	 *
 	 */
-	public final class TableRowElement extends TableFormattedElement
+	public class TableRowElement extends TableFormattedElement
 	{		
 		public var x:Number;
 		public var y:Number;
@@ -45,6 +50,19 @@ package flashx.textLayout.elements
 		public var columnIndex:Number = 0;
 		public var iMaxRowDepth:Number = 0;
 		public var beyondParcel:Boolean = false;
+		public var composedHeight:Number = 0;
+		public var totalHeight:Number = 0;// used to compute if a row will fit in parcel. Need a separate value for cells that span rows.
+		public var isMaxHeight:Boolean = false;
+		
+		public function TableRowElement(format:ITextLayoutFormat=null)
+		{
+			super();
+			
+			if (format) {
+				this.format = format;
+			}
+		}
+
 		
 		/** @private */
 		override protected function get abstract():Boolean
@@ -57,7 +75,7 @@ package flashx.textLayout.elements
 		/** @private */
 		tlf_internal override function canOwnFlowElement(elem:FlowElement):Boolean
 		{
-			return (elem is TableDataCellElement);
+			return (elem is TableCellElement);
 		}
 		
 		/** @private if its in a numbered list expand the damage to all list items - causes the numbers to be regenerated */
@@ -65,6 +83,102 @@ package flashx.textLayout.elements
 		{
 			super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
 		}
+		
+		/**
+		 * Returns a vector of table cell elements or null if the row contains no cells
+		 **/
+		public function getCells():Vector.<TableCellElement>
+		{
+			var table:TableElement = getTable();
+			
+			if(!table) {
+				return null;
+			}
+			
+			return table.getCellsForRow(this);
+		}
+		
+		/**
+		 * Get an array of cells or null if the row contains no cells
+		 **/
+		public function get cells():Array
+		{
+			var table:TableElement = getTable();
+			
+			if (!table) {
+				return null;
+			}
+			
+			return table.getCellsForRowArray(this);
+		}
+		
+		/**
+		 * Returns the number of cells in this row. 
+		 **/
+		public function get numCells():int
+		{
+			var table:TableElement = getTable();
+			
+			if (!table) {
+				return 0;
+			}
+			
+			return table.getCellsForRow(this).length;
+		}
+		
+		/**
+		 * Returns the cell at the specified index or null if out of range. 
+		 **/
+		public function getCellAt(index:int):TableCellElement
+		{
+			var cells:Vector.<TableCellElement> = getCells();
+			
+			if(!cells || index<0 || index>=cells.length)
+				return null;
+			return cells[index];
+		}
+		
+		/**
+		 * Adds a table cell to the row
+		 **/
+		public function addCell(cell:TableCellElement):TableCellElement
+		{
+			var table:TableElement = getTable();
+			var cellLength:int = numChildren;
+			
+			if (!table) {
+				throw new Error("Table must be set");
+			}
+			
+			cell.rowIndex = rowIndex;
+			
+			if (cell.colIndex==-1) {
+				cell.colIndex = cellLength;
+			}
+			
+			cells.push(cell);
+			//var selectable:Boolean = textFlow.interactionManager is SelectionManager;
+			//var editable:Boolean = textFlow.interactionManager is EditManager;
+			
+			return cell;
+		}
+		
+		/**
+		 * Adds a table cell to the row
+		 **/
+		public function addCellAt(index:int):TableCellElement
+		{
+			throw new Error("Add cell at is not implemented");
+		}
+		
+		/**
+		 * Get an estimate column count for this row.
+		 * This is temporary. TODO loop through cells and check for column span.
+		 **/
+		public function getColumnCount():int
+		{
+			return numCells || numChildren;
+		}
 
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TextFlow.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TextFlow.as b/textLayout/src/flashx/textLayout/elements/TextFlow.as
index a248665..6ccf576 100644
--- a/textLayout/src/flashx/textLayout/elements/TextFlow.as
+++ b/textLayout/src/flashx/textLayout/elements/TextFlow.as
@@ -284,6 +284,9 @@ package flashx.textLayout.elements
 		
 		// ILG count
 		private var _graphicObjectCount:int;
+		
+		// nested TextFlow support
+		private var _parentElement:FlowGroupElement;
 				
 		/** 
 		 * Constructor - creates a new TextFlow instance.
@@ -1180,6 +1183,29 @@ package flashx.textLayout.elements
 				_formatResolver.invalidateAll(this);
 			formatChanged(true);
 		}
+
+		/** The parent element is the element that the TextFlow is nested inside (such as a TableCellElement).
+		 * This property is for support of nested TextFlows to handle things like selection and editing.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 */		
+		public function get parentElement():FlowGroupElement
+		{
+			return _parentElement;
+		}
+
+		public function set parentElement(value:FlowGroupElement):void
+		{
+			_parentElement = value;
+		}
+		
+		public function nestedInTable():Boolean{
+			return parentElement && parentElement is TableCellElement;
+		}
+
 	} // end TextFlow class
 }
 import flash.utils.Dictionary;

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/factory/StringTextLineFactory.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/factory/StringTextLineFactory.as b/textLayout/src/flashx/textLayout/factory/StringTextLineFactory.as
index 355e6c5..7074f5c 100644
--- a/textLayout/src/flashx/textLayout/factory/StringTextLineFactory.as
+++ b/textLayout/src/flashx/textLayout/factory/StringTextLineFactory.as
@@ -463,7 +463,7 @@ package flashx.textLayout.factory
 				charPosition = line.getAtomTextBlockEndIndex(atomIndex);
 			}
 			
-			line.flushAtomData();
+			// line.flushAtomData(); // Warning: Now does nothing
 			return charPosition;
 		}
 		

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/factory/TextLineFactoryBase.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/factory/TextLineFactoryBase.as b/textLayout/src/flashx/textLayout/factory/TextLineFactoryBase.as
index c59999b..8092cd5 100644
--- a/textLayout/src/flashx/textLayout/factory/TextLineFactoryBase.as
+++ b/textLayout/src/flashx/textLayout/factory/TextLineFactoryBase.as
@@ -393,7 +393,7 @@ package flashx.textLayout.factory
 			// 4. Get the char index for this atom index
 			var nextTruncationPosition:int = line.getAtomTextBlockBeginIndex(atomIndex) + paraStart;
 			
-			line.flushAtomData();
+			//line.flushAtomData(); // Warning: Now does nothing
 			
 			return nextTruncationPosition;
 		} 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.as b/textLayout/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.as
index 5cd0474..679c7cb 100644
--- a/textLayout/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.as
+++ b/textLayout/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.as
@@ -31,7 +31,6 @@ package flashx.textLayout.operations
 
 	use namespace tlf_internal;
 	
-	[Deprecated(replacement="ApplyFormatToElementOperation", deprecatedSince="2.0")]
 	/**
 	 * The ApplyElementStyleNameOperation class encapsulates a style name change.
 	 *

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.as b/textLayout/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.as
index 02cf1d7..afc251f 100644
--- a/textLayout/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.as
+++ b/textLayout/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.as
@@ -30,7 +30,6 @@ package flashx.textLayout.operations
 
 	use namespace tlf_internal;
 	
-	[Deprecated(replacement="ApplyFormatToElementOperation", deprecatedSince="2.0")]
 	/**
 	 * The ApplyElementUserStyleOperation class encapsulates a change in a style value of an element.
 	 *


[02/25] git commit: [flex-tlf] [refs/heads/develop] - Commit of table work

Posted by pi...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
index f4579fc..1fec299 100644
--- a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
+++ b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
@@ -31,9 +31,9 @@ package flashx.textLayout.elements
 	import flash.text.engine.TextLine;
 	import flash.text.engine.TextLineValidity;
 	import flash.text.engine.TextRotation;
+	import flash.utils.Dictionary;
 	import flash.utils.getQualifiedClassName;
 	
-	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.compose.TextFlowLine;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.debug.Debugging;
@@ -50,6 +50,7 @@ package flashx.textLayout.elements
 	import flashx.textLayout.formats.TextJustify;
 	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.utils.CharacterUtil;
 	import flashx.textLayout.utils.LocaleUtil;
 	
@@ -79,7 +80,8 @@ package flashx.textLayout.elements
 	 
 	public final class ParagraphElement extends ParagraphFormattedElement
 	{
-		private var _textBlock:TextBlock;
+		//private var _textBlock:TextBlock;
+		private var _textBlockChildren:Dictionary;
 		private var _terminatorSpan:SpanElement;
 		
 		private var _interactiveChildrenCount:int;
@@ -95,6 +97,7 @@ package flashx.textLayout.elements
 			super();
 			_terminatorSpan = null;
 			_interactiveChildrenCount = 0 ;
+			_textBlockChildren = new Dictionary();
 		}
 		tlf_internal function get interactiveChildrenCount():int
 		{
@@ -106,26 +109,83 @@ package flashx.textLayout.elements
 		{
 			CONFIG::debug { assert(_textBlock == null,"createTextBlock called when there is already a textblock"); }
 			computedFormat;	// recreate the format BEFORE the _textBlock is created
-			_textBlock = new TextBlock();
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			//tbs.length = 0;
+			var tableCount:int = 0;
+			if(tbs.length == 0 && !(getChildAt(0) is TableElement) )
+				tbs.push(new TextBlock());
+			//getTextBlocks()[0] = new TextBlock();
 			CONFIG::debug { Debugging.traceFTECall(_textBlock,null,"new TextBlock()"); }
 			for (var i:int = 0; i < numChildren; i++)
 			{
 				var child:FlowElement = getChildAt(i);
+				if(child is TableElement)
+					tableCount++;
+//					tbs.push(new TextBlock());
+				else
+				{
+					//child.releaseContentElement();
+					//child.createContentElement();
+				}
+			}
+			while(tableCount >= tbs.length)
+				tbs.push(new TextBlock());
+			
+			for (i = 0; i < numChildren; i++)
+			{
+				child = getChildAt(i);
 				child.createContentElement();
 			}
-			updateTextBlock();
+			tbs.length = tableCount + 1;
+			var tb:TextBlock;
+			for each(tb in tbs){
+				updateTextBlock(tb);
+			}
 		}
-		
-		/** @private */
-		
-		tlf_internal function releaseTextBlock():void
+		private function updateTextBlockDict():void
+		{
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			if(tbs.length == 0)
+				return;//nothing to do
+			var tbIdx:int = 0;
+			var tb:TextBlock = tbs[tbIdx];
+			var items:Array = [];
+			var child:FlowElement;
+			for (var i:int = 0; i < numChildren; i++)
+			{
+				child = getChildAt(i);
+				if(child is TableElement)
+				{
+					_textBlockChildren[tb] = items;
+					tb = tbs[++tbIdx];
+					items = [];
+					continue;
+				}
+				items.push(child);
+			}
+			_textBlockChildren[tb] = items;
+		}
+		private function removeTextBlock(tb:TextBlock):void
+		{
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			if(tbs)
+			{
+				var idx:int = getTextBlocks().indexOf(tb);
+				if(idx > -1)
+				{
+					tbs.splice(idx,1);
+					delete _textBlockChildren[tb];
+				}
+			}
+		}
+		private function releaseTextBlockInternal(tb:TextBlock):void
 		{
-			if (!_textBlock)
+			if (!tb)
 				return;
-				
-			if (_textBlock.firstLine)	// A TextBlock may have no firstLine if it has previously been released.
+			
+			if (tb.firstLine)	// A TextBlock may have no firstLine if it has previously been released.
 			{
-				for (var textLineTest:TextLine = _textBlock.firstLine; textLineTest != null; textLineTest = textLineTest.nextLine)
+				for (var textLineTest:TextLine = tb.firstLine; textLineTest != null; textLineTest = textLineTest.nextLine)
 				{	
 					if(textLineTest.numChildren != 0)
 					{	
@@ -138,55 +198,169 @@ package flashx.textLayout.elements
 					}
 				}
 				
-				CONFIG::debug { Debugging.traceFTECall(null,_textBlock,"releaseLines",_textBlock.firstLine, _textBlock.lastLine); }				
-				_textBlock.releaseLines(_textBlock.firstLine, _textBlock.lastLine);	
+				CONFIG::debug { Debugging.traceFTECall(null,tb,"releaseLines",tb.firstLine, tb.lastLine); }				
+				tb.releaseLines(tb.firstLine, tb.lastLine);	
 			}	
-
-			_textBlock.content = null;
-			for (var i:int = 0; i < numChildren; i++)
+			var items:Array = _textBlockChildren[tb];
+			var len:int = items.length;
+			for (var i:int = 0; i < len; i++)
 			{
-				var child:FlowElement = getChildAt(i);
+				var child:FlowElement = items[i];
 				child.releaseContentElement();
 			}
-			_textBlock = null;
+			items.length = 0;
+			tb.content = null;
+			removeTextBlock(tb);
+		}
+		/** @private */
+		tlf_internal function releaseTextBlock(tb:TextBlock=null):void
+		{
+			updateTextBlockDict();
+			if(tb)
+			{
+				releaseTextBlockInternal(tb);
+				return;
+			}
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			for each(var tb:TextBlock in tbs)
+			{
+				releaseTextBlockInternal(tb);
+			}
+			//_textBlock = null;
 			if (_computedFormat)
 				_computedFormat = null;
 		}
-		
+		private var _textBlocks:Vector.<TextBlock>;
+		tlf_internal function getTextBlocks():Vector.<TextBlock>
+		{
+			if(_textBlocks == null)
+				_textBlocks = new Vector.<TextBlock>();
+			return _textBlocks;
+		}
 		/** TextBlock where the text of the paragraph is kept. @private */
 		tlf_internal function getTextBlock():TextBlock
-		{ 
-			if (!_textBlock)
+		{
+			if (!getTextBlocks().length)
+				createTextBlock();
+			
+			return getTextBlocks()[0]; 
+		}
+		/** Last TextBlock where the text of the paragraph is kept. @private */
+		tlf_internal function getLastTextBlock():TextBlock
+		{
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			if(!tbs.length)
 				createTextBlock();
-			return _textBlock; 
+			
+			return tbs[tbs.length-1];
+		}
+
+		/** Get TextBlock at specified position. @private */
+		tlf_internal function getTextBlockAtPosition(pos:int):TextBlock
+		{
+			var curPos:int = 0;
+			var posShift:int = 0;
+			var tables:Vector.<TableElement> = getTables();
+			if(!tables.length)
+				return getTextBlock();
+			
+			for each(var table:TableElement in tables)
+			{
+				if(table.getElementRelativeStart(this) < pos)
+					posShift++;
+			}
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			for each(var tb:TextBlock in tbs)
+			{
+				if(tb.content == null)
+					return tb;
+				curPos += tb.content.rawText.length;
+				if(curPos + posShift > pos)
+				{
+					if(getTextBlockStart(tb) > pos)
+						return null;
+					return tb;
+				}
+			}
+			return null;
+		}
+		
+		tlf_internal function getTextBlockAbsoluteStart(tb:TextBlock):int
+		{
+			var start:int = getTextBlockStart(tb);
+			if(start < 0)
+				start = 0;
+			return getAbsoluteStart() + start;
+		}
+		tlf_internal function getTextBlockStart(tb:TextBlock):int
+		{
+			var i:int;
+			var curPos:int = 0;
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			if(tbs.length == 0)
+				return -1;
+			var tables:Vector.<TableElement> = getTables();
+			for each(var curTB:TextBlock in tbs)
+			{
+				for each(var table:TableElement in tables)
+				{
+					if(table.getElementRelativeStart(this) <= curPos)
+					{
+						curPos++;
+						tables.splice(tables.indexOf(table),1);
+					}
+				}
+				if(tb == curTB)
+					return curPos;
+				if(tb.content)
+					curPos += curTB.content.rawText.length;
+			}
+			
+			return -1;
 		}
 		
+		private function getTables():Vector.<TableElement>
+		{
+			var tables:Vector.<TableElement> = new Vector.<TableElement>();
+			for (var i:int = 0; i < numChildren; i++)
+			{
+				var child:FlowElement = getChildAt(i);
+				if(child is TableElement)
+					tables.push(child as TableElement);
+			}
+			return tables;
+		}
+
 		/** TextBlock where the text of the paragraph is kept, or null if we currently don't have one. @private */
 		tlf_internal function peekTextBlock():TextBlock
 		{ 
-			return _textBlock; 
+			return getTextBlocks().length == 0 ? null : getTextBlocks()[0];
 		}
 		
 		/** @private */
 		tlf_internal function releaseLineCreationData():void
 		{
 			CONFIG::debug { assert(Configuration.playerEnablesArgoFeatures,"bad call to releaseLineCreationData"); }
-			if (_textBlock)
-				_textBlock["releaseLineCreationData"]();
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			for each(var tb:TextBlock in tbs)
+			{
+				tb["releaseLineCreationData"]();
+			}
 		}
 		
 		/** @private */
-		tlf_internal override function createContentAsGroup():GroupElement
-		{ 			
-			var group:GroupElement = _textBlock.content as GroupElement;
+		tlf_internal override function createContentAsGroup(pos:int=0):GroupElement
+		{
+			var tb:TextBlock = getTextBlockAtPosition(pos);
+			var group:GroupElement = tb.content as GroupElement;
 			if (!group)
 			{
-				var originalContent:ContentElement = _textBlock.content;
+				var originalContent:ContentElement = tb.content;
 				
 				group = new GroupElement();
 				CONFIG::debug { Debugging.traceFTECall(group,null,"new GroupElement()"); }
-				_textBlock.content = group;
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",group); }
+				tb.content = group;
+				CONFIG::debug { Debugging.traceFTEAssign(tb,"content",group); }
 
 				if (originalContent)
 				{
@@ -199,7 +373,7 @@ package flashx.textLayout.elements
 				}
 				
 				// Now we've got to force damage the entire paragraph, because we restructured it in FTE.
-				if (_textBlock.firstLine && textLength)
+				if (tb.firstLine && textLength)
 				{
 					var textFlow:TextFlow = getTextFlow();
 					if (textFlow)
@@ -212,7 +386,15 @@ package flashx.textLayout.elements
  		/** @private */
 		tlf_internal override function removeBlockElement(child:FlowElement, block:ContentElement):void
 		{
-			if (numChildren == 1)
+			var tb:TextBlock = getTextBlockAtPosition(child.getElementRelativeStart(this));
+			if(!tb)
+				tb = getTextBlock();
+			
+			if(tb.content == null)
+				return;
+			var relativeStart:int = child.getElementRelativeStart(this);
+
+			if (getChildrenInTextBlock(relativeStart).length < 2)
 			{
 				if (block is GroupElement)
 				{
@@ -221,18 +403,20 @@ package flashx.textLayout.elements
 					CONFIG::debug { assert(_textBlock.content is GroupElement,"removeBlockElement: bad content"); }
 					CONFIG::debug { assert(GroupElement(_textBlock.content).elementCount == 1,"removeBlockElement: bad element count"); }
 					CONFIG::debug { assert(GroupElement(_textBlock.content).getElementAt(0) == block,"removeBlockElement: bad group content"); }
-					GroupElement(_textBlock.content).replaceElements(0,1,null);
+					GroupElement(tb.content).replaceElements(0,1,null);
 					CONFIG::debug { Debugging.traceFTECall(null,_textBlock.content,"replaceElements",0,1,null); }
 				}
-				_textBlock.content = null;
+				tb.content = null;
 				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",null); }
 			}
-			else
+			else if(block.groupElement)
 			{
-				var idx:int = this.getChildIndex(child);
-				var group:GroupElement = GroupElement(_textBlock.content);
+				var idx:int = getChildIndexInBlock(child);
+				var group:GroupElement = GroupElement(tb.content);
 				CONFIG::debug { assert(group.elementCount == numChildren,"Mismatched group and elementCount"); }
 				group.replaceElements(idx,idx+1,null);
+				if(group.elementCount == 0)
+					return;
 				CONFIG::debug { Debugging.traceFTECall(null,group,"replaceElements",idx,idx+1,null); }
 				if (numChildren == 2)	// its going to be one so ungroup
 				{
@@ -243,18 +427,22 @@ package flashx.textLayout.elements
 					{
 						group.replaceElements(0,1,null);
 						CONFIG::debug { Debugging.traceFTECall(null,group,"replaceElements",0,1,null); }
-						_textBlock.content = elem;
-						CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",elem); }
+						tb.content = elem;
+						CONFIG::debug { Debugging.traceFTEAssign(tb,"content",elem); }
 					}
 				}
 			}
+			else {
+				//trace("1");
+				//tb.content = null;
+			}
 		}
 		
 		
 		/** @private */
 		tlf_internal override function hasBlockElement():Boolean
 		{
-			return _textBlock != null;
+			return getTextBlocks().length > 0;
 		}
 		
 		/** @private */
@@ -264,9 +452,42 @@ package flashx.textLayout.elements
 		}
 		
 		/** @private */
+		private function getChildrenInTextBlock(pos:int):Array
+		{
+			var retVal:Array = [];
+			if(numChildren == 0)
+				return retVal;
+			if(numChildren == 1)
+			{
+				retVal.push(getChildAt(0));
+				return retVal
+			}
+			var chldrn:Array = mxmlChildren.slice();
+			for(var i:int = 0; i<chldrn.length;i++)
+			{
+				if(chldrn[i] is TableElement)
+				{
+					if(chldrn[i].parentRelativeStart == pos)
+						return [chldrn[i]];
+					if(chldrn[i].parentRelativeStart < pos)
+					{
+						retVal.length = 0;
+						continue;
+					}
+					if(chldrn[i].parentRelativeStart > pos)
+						break;
+				}
+				retVal.push(chldrn[i]);		
+			}
+			return retVal;
+		}
+		
+		/** @private */
 		tlf_internal override function insertBlockElement(child:FlowElement, block:ContentElement):void
 		{
-			if (_textBlock == null)
+			var relativeStart:int = child.getElementRelativeStart(this);
+			var tb:TextBlock = getTextBlockAtPosition(relativeStart);
+			if (getTextBlocks().length == 0 || !tb)
 			{
 				child.releaseContentElement();
 				createTextBlock();	// does the whole tree
@@ -274,7 +495,7 @@ package flashx.textLayout.elements
 			}
 			var gc:Vector.<ContentElement>;	// scratch var
 			var group:GroupElement;			// scratch
-			if (numChildren == 1)
+			if (getChildrenInTextBlock(relativeStart).length < 2)
 			{
 				if (block is GroupElement)
 				{
@@ -285,19 +506,23 @@ package flashx.textLayout.elements
 					CONFIG::debug { Debugging.traceFTECall(null,gc,"push",block); }
 					group = new GroupElement(gc);
 					CONFIG::debug { Debugging.traceFTECall(group,null,"new GroupElement",gc); }
-					_textBlock.content = group;
+					tb.content = group;
 					CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",group); }
 				}
 				else
 				{
-					_textBlock.content = block;
+					if(block.groupElement)
+					{
+						block.groupElement.elementCount;
+					}
+					tb.content = block;
 					CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",block);  }
 				}
 			}
 			else
 			{
-				group = createContentAsGroup();
-				var idx:int = this.getChildIndex(child);
+				group = createContentAsGroup(relativeStart);
+				var idx:int = getChildIndexInBlock(child);
 				gc = new Vector.<ContentElement>();
 				CONFIG::debug { Debugging.traceFTECall(gc,null,"new Vector.<ContentElement>") }
 				gc.push(block);
@@ -307,6 +532,21 @@ package flashx.textLayout.elements
 			}
 		}
 		
+		private function getChildIndexInBlock(elem:FlowElement):int
+		{
+			var relIdx:int = 0;
+			for (var i:int = 0; i < numChildren; i++)
+			{
+				var child:FlowElement = getChildAt(i);
+				if(child == elem)
+					return relIdx;
+				relIdx++;
+				if(child is TableElement)
+					relIdx = 0;
+			}
+			return -1;
+		}
+		
 		/** @private */
 		override protected function get abstract():Boolean
 		{ return false;	}	
@@ -315,24 +555,63 @@ package flashx.textLayout.elements
 		tlf_internal override function get defaultTypeName():String
 		{ return "p"; }
 
+		tlf_internal function removeEmptyTerminator():void
+		{
+			if(numChildren == 1 && _terminatorSpan && _terminatorSpan.textLength == 1)
+			{
+				_terminatorSpan.removeParaTerminator();
+				super.replaceChildren(0, 1);
+				this._terminatorSpan = null;
+			}
+		}
 		/** @private */
 		public override function replaceChildren(beginChildIndex:int,endChildIndex:int,...rest):void
 		{
 			var applyParams:Array;
-			
-			// makes a measurable difference - rest.length zero and one are the common cases
-			if (rest.length == 1)
-				applyParams = [beginChildIndex, endChildIndex, rest[0]];
-			else
-			{
-				applyParams = [beginChildIndex, endChildIndex];
-				if (rest.length != 0)
-					applyParams = applyParams.concat.apply(applyParams, rest);
-			}
 
-			super.replaceChildren.apply(this, applyParams);
+			do{
+				if(_terminatorSpan)
+				{
+					var termIdx:int = getChildIndex(_terminatorSpan);
+					if(termIdx !=0 && _terminatorSpan.textLength == 1)
+					{
+						super.replaceChildren(termIdx, termIdx+1);
+						_terminatorSpan = null;
+						if(beginChildIndex >= termIdx)
+						{
+							beginChildIndex--;
+							if(rest.length == 0) // delete of terminator was already done.
+								break;
+						}
+						if(endChildIndex >= termIdx && beginChildIndex != endChildIndex)
+							endChildIndex--;
+					}
+				}
+				
+				// makes a measurable difference - rest.length zero and one are the common cases
+				if (rest.length == 1)
+					applyParams = [beginChildIndex, endChildIndex, rest[0]];
+				else
+				{
+					applyParams = [beginChildIndex, endChildIndex];
+					if (rest.length != 0)
+						applyParams = applyParams.concat.apply(applyParams, rest);
+				}
+				
+				super.replaceChildren.apply(this, applyParams);
+				
+			}while(false);
 			
 			ensureTerminatorAfterReplace();
+			// ensure correct text blocks
+			createTextBlock();
+		}
+		
+		public override function splitAtPosition(relativePosition:int):FlowElement
+		{
+			// need to handle multiple TextBlocks
+			// maybe not. It might be handled in replaceChildren().
+			return super.splitAtPosition(relativePosition);
 		}
 		/** @private */
 		tlf_internal function ensureTerminatorAfterReplace():void
@@ -340,27 +619,43 @@ package flashx.textLayout.elements
 			var newLastLeaf:FlowLeafElement = getLastLeaf();
 			if (_terminatorSpan != newLastLeaf)
 			{
-				if (_terminatorSpan)
+				if (newLastLeaf && _terminatorSpan)
 				{
 					_terminatorSpan.removeParaTerminator();
+					if(_terminatorSpan.textLength == 0)
+					{
+						var termIdx:int = getChildIndex(_terminatorSpan);
+						super.replaceChildren(termIdx, termIdx+1);
+					}
 					this._terminatorSpan = null;
 				}
 				
-				if (newLastLeaf)
+				if (newLastLeaf is SpanElement)
 				{
-					if (newLastLeaf is SpanElement)
-					{
-						(newLastLeaf as SpanElement).addParaTerminator();
-						this._terminatorSpan = newLastLeaf as SpanElement;
-					}
-					else
-					{
-						var s:SpanElement = new SpanElement();
-						super.replaceChildren(numChildren,numChildren,s);
-						s.format = newLastLeaf.format;
-						s.addParaTerminator();
-						this._terminatorSpan = s;
-					}
+					(newLastLeaf as SpanElement).addParaTerminator();
+					this._terminatorSpan = newLastLeaf as SpanElement;
+				}
+				else
+				{
+					var s:SpanElement = new SpanElement();
+					super.replaceChildren(numChildren,numChildren,s);
+					s.format = newLastLeaf ? newLastLeaf.format : _terminatorSpan.format;
+					s.addParaTerminator();
+					this._terminatorSpan = s;
+				}
+			}
+			//merge terminator span to previous if possible
+			if(_terminatorSpan.textLength == 1)
+			{
+				var prev:FlowLeafElement = _terminatorSpan.getPreviousLeaf(this);
+				if(prev && prev is SpanElement)
+				{
+					_terminatorSpan.removeParaTerminator();
+					termIdx = getChildIndex(_terminatorSpan);
+					super.replaceChildren(termIdx, termIdx+1);
+					s = prev as SpanElement;
+					s.addParaTerminator();
+					this._terminatorSpan = s;
 				}
 			}
 		}
@@ -387,7 +682,7 @@ package flashx.textLayout.elements
 						child.bindableElement = true;
 					
 					// Note: calling super.replaceChildren because we don't want to transfer para terminator each time
-					super.replaceChildren(numChildren, numChildren, child as FlowElement); 
+					super.replaceChildren(numChildren, numChildren, child as FlowElement);
 				}
 				else if (child is String)
 				{
@@ -404,6 +699,9 @@ package flashx.textLayout.elements
 			
 			// Now ensure para terminator
 			ensureTerminatorAfterReplace();
+			
+			// recreate text blocks to handle possible TableElement changes
+			createTextBlock();
 		}
 		
 		/** @private
@@ -411,17 +709,26 @@ package flashx.textLayout.elements
 		public override function getText(relativeStart:int=0, relativeEnd:int=-1, paragraphSeparator:String="\n"):String
 		{
 			// Optimization for getting text of the entire paragraph
-			if (relativeStart == 0 && (relativeEnd == -1 || relativeEnd >= textLength-1) && _textBlock)
+			if (relativeStart == 0 && (relativeEnd == -1 || relativeEnd >= textLength-1) && getTextBlocks().length)
 			{
-				if (_textBlock.content && _textBlock.content.rawText)
+				var tb:TextBlock;
+				var tbs:Vector.<TextBlock> = getTextBlocks();
+				var text:String = "";
+				for each(tb in tbs)
 				{
-					var text:String = _textBlock.content.rawText;
-					return text.substring(0, text.length - 1);
+					text = text + getTextInBlock(tb);
 				}
-				return "";		// content is null
+				if(tb.content && tb.content.rawText)
+					return text.substring(0, text.length - 1);
+				return text;
 			}
 			return super.getText(relativeStart, relativeEnd, paragraphSeparator);
 		}
+		private function getTextInBlock(tb:TextBlock):String{
+			if(!tb.content || !tb.content.rawText)
+				return "";
+			return tb.content.rawText;
+		}
 		
 		/** Returns the paragraph that follows this one, or null if there are no more paragraphs. 
 		 *
@@ -478,39 +785,46 @@ package flashx.textLayout.elements
 		 
 		public function findPreviousAtomBoundary(relativePosition:int):int
 		{
+			var tb:TextBlock = getTextBlockAtPosition(relativePosition);
+			var tbStart:int = getTextBlockStart(tb);
+			var textBlockPos:int = relativePosition - tbStart;
 			if (ContainerController.tlf_internal::usesDiscretionaryHyphens)
 			{
-				var textBlock:TextBlock = getTextBlock();
-				var tl:TextLine = textBlock.getTextLineAtCharIndex(relativePosition);
-				var currentAtomIndex:int = tl.getAtomIndexAtCharIndex(relativePosition);
+				var tl:TextLine = tb.getTextLineAtCharIndex(textBlockPos);
+				var currentAtomIndex:int = tl.getAtomIndexAtCharIndex(textBlockPos);
                 //trace("relpos", relativePosition, "atomIndex", currentAtomIndex);
                 var isRTL:Boolean = tl.getAtomBidiLevel(currentAtomIndex) == 1;
                 if (isRTL)
                 {
-                   var foo:int = getTextBlock().findPreviousAtomBoundary(relativePosition);
+                   var foo:int = tb.findPreviousAtomBoundary(textBlockPos);
                    if (currentAtomIndex == 0)
                    {
                        // when cursor is left of all characters (end of line)
                        // atomIndex is 0, so compensate
                        if (tl.atomCount > 0)
                        {
-                           while (--relativePosition)
+                           while (--textBlockPos)
                            {
-                               if (tl.getAtomIndexAtCharIndex(relativePosition) != currentAtomIndex)
+							   --relativePosition;
+                               if (tl.getAtomIndexAtCharIndex(textBlockPos) != currentAtomIndex)
                                    break;
                            }
                        }
                    }
                    else
                    {
-                       while (--relativePosition)
+                       while (--relativePosition && --textBlockPos)
                        {
-                           if (tl.getAtomIndexAtCharIndex(relativePosition) != currentAtomIndex)
+                           if (tl.getAtomIndexAtCharIndex(textBlockPos) != currentAtomIndex)
                                break;
                        }
                    }
                    if (CharacterUtil.isLowSurrogate(getText(relativePosition, relativePosition + 1).charCodeAt(0)))
-                       relativePosition--;
+				   {
+					   relativePosition--;
+					   textBlockPos--;
+				   }
+				   
                    //trace("previous", relativePosition, foo);
                 }
                 else
@@ -521,21 +835,26 @@ package flashx.textLayout.elements
     					if (!tl)
     						return -1;
     					// need this when 0x2028 line separator in use
-    					if (tl.textBlockBeginIndex + tl.rawTextLength == relativePosition)
-    						return tl.textBlockBeginIndex + tl.rawTextLength - 1;
-    					return tl.textBlockBeginIndex + tl.rawTextLength;
+    					if (tl.textBlockBeginIndex + tl.rawTextLength == textBlockPos)
+    						return tl.textBlockBeginIndex + tl.rawTextLength - 1 + tbStart;
+    					return tl.textBlockBeginIndex + tl.rawTextLength + tbStart;
     				}
-    				while (--relativePosition)
+    				while (--relativePosition && --textBlockPos)
     				{
-    					if (tl.getAtomIndexAtCharIndex(relativePosition) < currentAtomIndex)
+    					if (tl.getAtomIndexAtCharIndex(textBlockPos) < currentAtomIndex)
     						break;
     				}
                     if (CharacterUtil.isLowSurrogate(getText(relativePosition, relativePosition + 1).charCodeAt(0)))
-                        relativePosition--;
+					{
+						relativePosition--;
+						textBlockPos--;
+					}
                 }
 				return relativePosition;
 			}
-            var pos:int = getTextBlock().findPreviousAtomBoundary(relativePosition);
+            var pos:int = tb.findPreviousAtomBoundary(textBlockPos);
+			if(pos >= 0)
+				pos += tbStart;
             //trace("previous", relativePosition, pos);
 			return pos;
 		}
@@ -560,34 +879,41 @@ package flashx.textLayout.elements
 		 
 		public function findNextAtomBoundary(relativePosition:int):int
 		{
+			var tb:TextBlock = getTextBlockAtPosition(relativePosition);
+			var tbStart:int = getTextBlockStart(tb);
+			var textBlockPos:int = relativePosition - tbStart;
 			if (ContainerController.tlf_internal::usesDiscretionaryHyphens)
 			{
-				var textBlock:TextBlock = getTextBlock();
-				var tl:TextLine = textBlock.getTextLineAtCharIndex(relativePosition);
-				var currentAtomIndex:int = tl.getAtomIndexAtCharIndex(relativePosition);
+				var tl:TextLine = tb.getTextLineAtCharIndex(textBlockPos);
+				var currentAtomIndex:int = tl.getAtomIndexAtCharIndex(textBlockPos);
                 //trace("relpos", relativePosition, "atomIndex", currentAtomIndex);
                 var isRTL:Boolean = tl.getAtomBidiLevel(currentAtomIndex) == 1;
                 if (isRTL)
                 {
-                    var foo:int = getTextBlock().findNextAtomBoundary(relativePosition);
+                    var foo:int = tb.findNextAtomBoundary(textBlockPos);
                     if (currentAtomIndex == 0)
                     {
-                        while (++relativePosition)
+                        while (++textBlockPos)
                         {
-                            if (tl.getAtomIndexAtCharIndex(relativePosition) != currentAtomIndex)
+							++relativePosition;
+                            if (tl.getAtomIndexAtCharIndex(textBlockPos) != currentAtomIndex)
                                 break;
                         }
                     }
                     else
                     {
-                        while (++relativePosition)
+                        while (++textBlockPos)
                         {
-                            if (tl.getAtomIndexAtCharIndex(relativePosition) != currentAtomIndex)
+							++relativePosition;
+                            if (tl.getAtomIndexAtCharIndex(textBlockPos) != currentAtomIndex)
                                 break;
                         }
                     }
                     if (CharacterUtil.isHighSurrogate(getText(relativePosition, relativePosition + 1).charCodeAt(0)))
-                        relativePosition++;
+					{
+						relativePosition++;
+						textBlockPos++;
+					}
                     //trace("next", relativePosition, foo);
                 }
                 else
@@ -597,19 +923,25 @@ package flashx.textLayout.elements
     					tl = tl.nextLine;
     					if (!tl)
     						return -1;
-    					return tl.textBlockBeginIndex;
+    					return tl.textBlockBeginIndex + tbStart;
     				}
-    				while (++relativePosition)
+    				while (++textBlockPos)
     				{
-    					if (tl.getAtomIndexAtCharIndex(relativePosition) > currentAtomIndex)
+						++relativePosition;
+    					if (tl.getAtomIndexAtCharIndex(textBlockPos) > currentAtomIndex)
     						break;
     				}
                     if (CharacterUtil.isHighSurrogate(getText(relativePosition, relativePosition + 1).charCodeAt(0)))
-                        relativePosition++;
+					{
+						relativePosition++;
+						textBlockPos++;
+					}
                 }
 				return relativePosition;
 			}
-			var pos:int = getTextBlock().findNextAtomBoundary(relativePosition);
+			var pos:int = tb.findNextAtomBoundary(textBlockPos);
+			if(pos >= 0)
+				pos += tbStart;
             //trace("next", relativePosition, pos);
             return pos;
 		}
@@ -617,7 +949,27 @@ package flashx.textLayout.elements
 		/** @private */
 		public override function getCharAtPosition(relativePosition:int):String
 		{
-			return getTextBlock().content.rawText.charAt(relativePosition);
+			var foundTB:TextBlock = getTextBlockAtPosition(relativePosition);
+			if(!foundTB)
+				return "\u0016";
+			var tables:Vector.<TableElement> = getTables();
+			var pos:int = relativePosition;
+			for each(var table:TableElement in tables)
+			{
+				if(table.getElementRelativeStart(this) < pos)
+					relativePosition--;
+			}
+			var tbs:Vector.<TextBlock> = getTextBlocks();
+			for each(var tb:TextBlock in tbs)
+			{
+				if(foundTB == tb)
+					break;
+				if(tb)
+					relativePosition -= tb.content.rawText.length;
+				else
+					relativePosition -= 1;this.getText()
+			}
+			return foundTB.content.rawText.charAt(relativePosition);
 		} 
 
 		/** 
@@ -650,7 +1002,13 @@ package flashx.textLayout.elements
 				}
 				return relativePosition;
 			}
-			return getTextBlock().findPreviousWordBoundary(relativePosition);
+			var block:TextBlock = getTextBlockAtPosition(relativePosition);
+			if(block == null)
+				block = getTextBlockAtPosition(--relativePosition);
+			var pos:int = getTextBlockStart(block);
+			if(pos < 0)
+				pos = 0;
+			return relativePosition == pos ? pos : pos + block.findPreviousWordBoundary(relativePosition - pos);
 		}
 
 		/** 
@@ -683,7 +1041,13 @@ package flashx.textLayout.elements
 				}
 				return relativePosition;
 			}
-			return getTextBlock().findNextWordBoundary(relativePosition);
+			var block:TextBlock = getTextBlockAtPosition(relativePosition);
+			if(block == null)
+				block = getTextBlockAtPosition(--relativePosition);
+			var pos:int = getTextBlockStart(block);
+			if(pos < 0)
+				pos = 0;
+			return pos + block.findNextWordBoundary(relativePosition - pos);
 		}
 		
 		static private var _defaultTabStops:Vector.<TabStop>;
@@ -697,8 +1061,10 @@ package flashx.textLayout.elements
 				_defaultTabStops[i] = new TabStop(TextAlign.START, defaultTabWidth * i);
 		}
 		
-		private function updateTextBlock():void
+		private function updateTextBlock(textBlock:TextBlock=null):void
 		{
+			if(!textBlock)
+				textBlock = getTextBlock();
 			// find the ancestor with a container and use its format for various settings
 			var containerElement:ContainerFormattedElement = getAncestorWithContainer();
 			if (!containerElement)
@@ -746,10 +1112,10 @@ package flashx.textLayout.elements
 				}
 
 				CONFIG::debug { Debugging.traceFTECall(spaceJustifier,null,"new SpaceJustifier",_computedFormat.locale,lineJust,spaceJustifier.letterSpacing); }
-				_textBlock.textJustifier = spaceJustifier;
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"textJustifier",spaceJustifier); }
-				_textBlock.baselineZero = getLeadingBasis(this.getEffectiveLeadingModel());
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"baselineZero",_textBlock.baselineZero);  }
+				textBlock.textJustifier = spaceJustifier;
+				CONFIG::debug { Debugging.traceFTEAssign(textBlock,"textJustifier",spaceJustifier); }
+				textBlock.baselineZero = getLeadingBasis(this.getEffectiveLeadingModel());
+				CONFIG::debug { Debugging.traceFTEAssign(textBlock,"baselineZero",textBlock.baselineZero);  }
 			}
 			else
 			{
@@ -758,21 +1124,21 @@ package flashx.textLayout.elements
 					eastAsianJustifier.composeTrailingIdeographicSpaces = true;
 				}
 				CONFIG::debug { Debugging.traceFTECall(eastAsianJustifier,null,"new EastAsianJustifier",_computedFormat.locale,lineJust,makeJustRuleStyle); }
-				_textBlock.textJustifier = eastAsianJustifier as EastAsianJustifier;
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"textJustifier",eastAsianJustifier);  }
-				_textBlock.baselineZero = getLeadingBasis(this.getEffectiveLeadingModel());
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"baselineZero",_textBlock.baselineZero);  }
+				textBlock.textJustifier = eastAsianJustifier as EastAsianJustifier;
+				CONFIG::debug { Debugging.traceFTEAssign(textBlock,"textJustifier",eastAsianJustifier);  }
+				textBlock.baselineZero = getLeadingBasis(this.getEffectiveLeadingModel());
+				CONFIG::debug { Debugging.traceFTEAssign(textBlock,"baselineZero",textBlock.baselineZero);  }
 			}
 			
-			_textBlock.bidiLevel = _computedFormat.direction == Direction.LTR ? 0 : 1;
-			CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"bidiLevel",_textBlock.bidiLevel);  }
+			textBlock.bidiLevel = _computedFormat.direction == Direction.LTR ? 0 : 1;
+			CONFIG::debug { Debugging.traceFTEAssign(textBlock,"bidiLevel",textBlock.bidiLevel);  }
 
-			_textBlock.lineRotation = containerElementFormat.blockProgression == BlockProgression.RL ? TextRotation.ROTATE_90 : TextRotation.ROTATE_0;
-			CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"lineRotation",_textBlock.lineRotation);  }
+			textBlock.lineRotation = containerElementFormat.blockProgression == BlockProgression.RL ? TextRotation.ROTATE_90 : TextRotation.ROTATE_0;
+			CONFIG::debug { Debugging.traceFTEAssign(textBlock,"lineRotation",textBlock.lineRotation);  }
 			
 			if (_computedFormat.tabStops && _computedFormat.tabStops.length != 0)
 			{
-				//create a vector of TabStops and assign it to tabStops in _textBlock
+				//create a vector of TabStops and assign it to tabStops in textBlock
 				var tabStops:Vector.<TabStop> = new Vector.<TabStop>();
 				CONFIG::debug { Debugging.traceFTECall(tabStops,null,"new Vector.<TabStop>()"); }
 				for each(var tsa:TabStopFormat in _computedFormat.tabStops)
@@ -786,8 +1152,8 @@ package flashx.textLayout.elements
 					tabStops.push(tabStop);
 					CONFIG::debug { Debugging.traceFTECall(null,tabStops,"push",tabStop); }
 				}
-				_textBlock.tabStops = tabStops;
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"tabStops",tabStops);  }
+				textBlock.tabStops = tabStops;
+				CONFIG::debug { Debugging.traceFTEAssign(textBlock,"tabStops",tabStops);  }
 			} 
 			else if (GlobalSettings.enableDefaultTabStops && !Configuration.playerEnablesArgoFeatures)
 			{
@@ -795,13 +1161,13 @@ package flashx.textLayout.elements
 				//	is true, TLF will set up default tabStops in the case where there are no tabs defined. 
 				if (_defaultTabStops == null)
 					initializeDefaultTabStops();
-				_textBlock.tabStops = _defaultTabStops;
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"tabStops",_defaultTabStops);  }
+				textBlock.tabStops = _defaultTabStops;
+				CONFIG::debug { Debugging.traceFTEAssign(textBlock,"tabStops",_defaultTabStops);  }
 			}
 			else
 			{
-				_textBlock.tabStops = null;
-				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"tabStops",null);  }
+				textBlock.tabStops = null;
+				CONFIG::debug { Debugging.traceFTEAssign(textBlock,"tabStops",null);  }
 			}		 
 		}
 		
@@ -811,8 +1177,10 @@ package flashx.textLayout.elements
 			if (!_computedFormat)
 			{
 				super.computedFormat;
-				if (_textBlock)
-					updateTextBlock();
+				var tbs:Vector.<TextBlock> = getTextBlocks();
+				for each(var tb:TextBlock in tbs)
+					updateTextBlock(tb);
+					
 			}
 			return _computedFormat;
 		}
@@ -820,7 +1188,7 @@ package flashx.textLayout.elements
 		/** @private */
 		tlf_internal override function canOwnFlowElement(elem:FlowElement):Boolean
 		{
-			return elem is FlowLeafElement || elem is SubParagraphGroupElementBase;
+			return elem is FlowLeafElement || elem is SubParagraphGroupElementBase || elem is TableElement;
 		}
 		
 		/** @private */
@@ -884,32 +1252,6 @@ package flashx.textLayout.elements
 			}
 		}
 		
-		// mjzhang : new API for table feature, to discuss
-		public function isInTable():Boolean
-		{
-			var parent:FlowElement = this.parent;
-			while ( parent )
-			{
-				if ( (parent is TableDataCellElement) )
-					return true;
-				parent = parent.parent;
-			}
-				
-			return false;
-		}
-		
-		public function getTableDataCellElement():TableDataCellElement
-		{
-			var parent:FlowElement = this.parent;
-			while ( parent )
-			{
-				if ( (parent is TableDataCellElement) )
-					return parent as TableDataCellElement;
-				parent = parent.parent;
-			}
-			
-			return null;
-		}
 		/** @private */
 		tlf_internal function getEffectiveLeadingModel():String
 		{
@@ -938,19 +1280,20 @@ package flashx.textLayout.elements
 		/** @private */
 		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
 		{
-			var rslt:int = super.debugCheckFlowElement(depth," fte:"+getDebugIdentity(_textBlock)+" "+extraData);
+			var tb:TextBlock = getTextBlock();
+			var rslt:int = super.debugCheckFlowElement(depth," fte:"+getDebugIdentity(tb)+" "+extraData);
 			
 			// now check the character count and then the last character 
 			
-			if (_textBlock)
+			if (tb)
 			{
-				var contentLength:int = _textBlock.content && _textBlock.content.rawText ? _textBlock.content.rawText.length : 0;
+				var contentLength:int = tb.content && tb.content.rawText ? tb.content.rawText.length : 0;
 				rslt += assert(contentLength == textLength,"Bad paragraph length mode:"+textLength.toString()+" _textBlock:" + contentLength.toString());
 
-				var groupElement:GroupElement = _textBlock.content as GroupElement;
+				var groupElement:GroupElement = tb.content as GroupElement;
 				if (groupElement)
 					assert(groupElement.elementCount == numChildren,"Mismatched group and elementCount"); 
-				else if (_textBlock.content)
+				else if (tb.content)
 					assert(1 == numChildren,"Mismatched group and elementCount"); 
 				else 
 					assert(0 == numChildren,"Mismatched group and elementCount"); 
@@ -1013,5 +1356,11 @@ package flashx.textLayout.elements
 		{
 			return _interactiveChildrenCount != 0 ;
 		}
+
+		tlf_internal function get terminatorSpan():SpanElement
+		{
+			return _terminatorSpan;
+		}
+
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/SpanElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/SpanElement.as b/textLayout/src/flashx/textLayout/elements/SpanElement.as
index c16adff..9e37058 100644
--- a/textLayout/src/flashx/textLayout/elements/SpanElement.as
+++ b/textLayout/src/flashx/textLayout/elements/SpanElement.as
@@ -395,6 +395,8 @@ package flashx.textLayout.elements
 					assert(_blockElement.rawText.charAt(_blockElement.rawText.length-1) != SpanElement.kParagraphTerminator,"adding para terminator twice");
 			}
 
+			if(_text && _text.substr(-1) == SpanElement.kParagraphTerminator)// terminator exists. Bail out.
+				return;
 			replaceTextInternal(textLength,textLength,SpanElement.kParagraphTerminator);
 			
 			CONFIG::debug 
@@ -414,6 +416,9 @@ package flashx.textLayout.elements
 				assert(_text && _text.length && _text.charAt(_text.length-1) == SpanElement.kParagraphTerminator,
 					"attempting to remove para terminator when it doesn't exist");
 			}
+			if(!_text || _text.substr(-1) != SpanElement.kParagraphTerminator)// no terminator exists. Bail out.
+				return;
+
 			replaceTextInternal(textLength-1,textLength,"");
 			modelChanged(ModelChange.TEXT_DELETED,this,textLength > 0 ? textLength-1 : 0,1);
 		}
@@ -464,7 +469,7 @@ package flashx.textLayout.elements
 				{
 					// 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();
+					var group:GroupElement = parent.createContentAsGroup(getElementRelativeStart(parent));
 					
 					var elementIndex:int = group.getElementIndex(_blockElement);
 					

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as b/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
index c65e138..2affda3 100644
--- a/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
+++ b/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
@@ -190,7 +190,7 @@ package flashx.textLayout.elements
 		}
 		
 		/** @private */
-		tlf_internal override function createContentAsGroup():GroupElement
+		tlf_internal override function createContentAsGroup(pos:int=0):GroupElement
 		{ return groupElement; }
 
 		/** @private */

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TableColElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableColElement.as b/textLayout/src/flashx/textLayout/elements/TableColElement.as
index 85a1d9e..342b9ce 100644
--- a/textLayout/src/flashx/textLayout/elements/TableColElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableColElement.as
@@ -18,6 +18,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 package flashx.textLayout.elements
 {
+	import flashx.textLayout.formats.ITextLayoutFormat;
 	import flashx.textLayout.tlf_internal;
 	
 	use namespace tlf_internal;
@@ -36,6 +37,15 @@ package flashx.textLayout.elements
 	{		
 		//public var height:Number;
 		public var x:Number;
+		public var colIndex:int;
+		
+		public function TableColElement(format:ITextLayoutFormat=null)
+		{
+			super();
+			if(format)
+				this.format = format;
+		}
+
 		
 		/** @private */
 		override protected function get abstract():Boolean
@@ -56,6 +66,29 @@ package flashx.textLayout.elements
 		{
 			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.<TableCellElement> {
+			
+			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;
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TableElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableElement.as b/textLayout/src/flashx/textLayout/elements/TableElement.as
index 92cefcc..ed82a28 100644
--- a/textLayout/src/flashx/textLayout/elements/TableElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableElement.as
@@ -18,19 +18,17 @@
 ////////////////////////////////////////////////////////////////////////////////
 package flashx.textLayout.elements
 {
-	import flash.display.Graphics;
-	import flash.events.Event;
-	import flash.events.EventDispatcher;
-	import flash.events.IEventDispatcher;
-	import flash.events.MouseEvent;
-	import flash.geom.Point;
-	import flash.text.engine.TextBlock;
-	import flash.text.engine.TextLine;
+	import flash.display.Sprite;
+	import flash.text.engine.ContentElement;
+	import flash.text.engine.GraphicElement;
+	import flash.utils.Dictionary;
 	
-	import flashx.textLayout.events.FlowElementEventDispatcher;
-	import flashx.textLayout.events.FlowElementMouseEventManager;
+	import flashx.textLayout.compose.TextFlowTableBlock;
+	import flashx.textLayout.edit.SelectionFormat;
 	import flashx.textLayout.events.ModelChange;
-	import flashx.textLayout.formats.*;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.tlf_internal;
 	
 	use namespace tlf_internal;
@@ -41,7 +39,6 @@ package flashx.textLayout.elements
 	 * A TableElement's children must be of type TableRowElement, TableColElement, TableColGroupElement, TableBodyElement.
 	 * 
 	 * 
-	 * 
 	 * @playerversion Flash 10
 	 * @playerversion AIR 1.5
 	 * @langversion 3.0
@@ -49,41 +46,38 @@ package flashx.textLayout.elements
 	 */
 	public class TableElement extends TableFormattedElement 
 	{
-		private var _row:int;
-		private var _column:int;
 		
-		private var _height:Array = []; // parcel-indexed
-		public var computedWidth:Number;
+		private var _computedWidth:Number;
 		
 		public var x:Number;
 		public var y:Number;
 		
-		//These attributes is from the original loop prototype. Maybe changed later
-		public var totalRowDepth:Number = undefined;
-		public var originParcelIndex:Number;
-		public var numAcrossParcels:int;
-        public var curRowIdx:int = 0; // this value should be only used while composing
-        public var outOfLastParcel:Boolean = false; 
-			
-		private var arColumn:Array = [];
+		private var columns:Vector.<TableColElement> = new Vector.<TableColElement>();
+		private var rows:Vector.<TableRowElement> = new Vector.<TableRowElement>();
+		private var damagedColumns:Vector.<TableColElement> = new Vector.<TableColElement>();
+		private var damageRows:Vector.<TableRowElement> = new Vector.<TableRowElement>();
+		private var _hasCellDamage:Boolean = true;
+		
+		private var _headerRowCount:uint = 0;
+		private var _footerRowCount:uint = 0;
+		private var _tableRowsComputed:Boolean;
+		
+		private var _headerRows:Vector.< Vector.<TableCellElement> >;
+		private var _footerRows:Vector.< Vector.<TableCellElement> >;
+		private var _bodyRows:Vector.< Vector.<TableCellElement> >;
+		private var _composedRowIndex:uint = 0;
+		
+		private var _tableBlocks:Vector.<TextFlowTableBlock>;
+		private var _tableBlockIndex:uint = 0;
+		private var _tableBlockDict:Dictionary;
+		
+		private var _leaf:TableLeafElement;
 		
 		public function TableElement()
 		{
 			super();
 		}
 		
-		public function initTableElement(row:Number, column:Number):void
-		{
-			_row = row;
-			_column = column;
-			
-			for ( var i:int = 0; i < column; i ++ )
-			{
-				var col:TableColElement = new TableColElement();	
-				arColumn[i] = col;
-			}
-		}
-		
 		/** @private */
 		override protected function get abstract():Boolean
 		{ return false; }
@@ -95,35 +89,714 @@ package flashx.textLayout.elements
 		/** @private */
 		tlf_internal override function canOwnFlowElement(elem:FlowElement):Boolean
 		{
-			return  (elem is TableBodyElement) || (elem is TableRowElement) || (elem is TableColElement) || (elem is TableColGroupElement);
+			return (elem is TableCellElement) || (elem is TableRowElement) || (elem is TableColElement);// || (elem is TableBodyElement) || (elem is TableColGroupElement);
 		}
 		
 		/** @private if its in a numbered list expand the damage to all list items - causes the numbers to be regenerated */
 		tlf_internal override function modelChanged(changeType:String, elem:FlowElement, changeStart:int, changeLen:int, needNormalize:Boolean = true, bumpGeneration:Boolean = true):void
 		{
+			if (changeType==ModelChange.ELEMENT_ADDED) {
+				
+			}
+			else if (changeType==ModelChange.ELEMENT_REMOVAL) {
+				if (headerRowCount > 0 || footerRowCount > 0) {
+					
+				}
+			}
+			
 			super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
 		}
 		
-		public function get row():int
+		override public function set cellSpacing(cellSpacingValue:*):void
+		{
+			
+			markCellsDamaged();
+			hasCellDamage = true;
+			normalizeCells();
+			
+			super.cellSpacing = cellSpacingValue;
+		}
+		
+		public function get numRows():int
+		{
+			return rows.length;
+		}
+		
+		public function get numColumns():int
+		{
+			return columns.length;
+		}
+		
+		/**
+		 * Total number of cells
+		 **/
+		public function get numCells():int
 		{
-			return _row;
+			return getCells().length;
 		}
 		
-		public function get column():int
+		/**
+		 * Total number of rows in the table. If set to a value lower than
+		 * the current number of rows the rows at the end of the table are removed. 
+		 * If the set to a value greater than the current number of rows additional
+		 * rows are added to the table. 
+		 **/
+		public function set numRows(value:int):void
 		{
-			return _column;
+			while(value < numRows){
+				rows.pop();
+			}
+			var num:int = numRows;
+			for(var i:int = num;i<value;i++) {
+				var row:TableRowElement = createRowElement(i, defaultRowFormat);
+				rows.push(row);
+			}
 		}
 
+		/**
+		 * Total number of columns in the table. If set to a value lower than
+		 * the current number of columns the columns at the end of the table are removed. 
+		 * If the set to a value greater than the current number of columns additional
+		 * columns are added to the table. 
+		 **/
+		public function set numColumns(value:int):void
+		{
+			while(value < numColumns){
+				columns.pop();
+			}
+			var num:int = numColumns;
+			for(var i:int = num;i<value;i++) {
+				var column:TableColElement = createColumnElement(i, defaultColumnFormat);
+				columns.push(column);
+			}
+		}
+		private var _defaultRowFormat:ITextLayoutFormat;
+
+		/**
+		 * Gets the row format for new rows. 
+		 **/
+		public function get defaultRowFormat():ITextLayoutFormat
+		{
+			if(!_defaultRowFormat)
+				_defaultRowFormat = new TextLayoutFormat(computedFormat);
+			return _defaultRowFormat;
+		}
+
+		public function set defaultRowFormat(value:ITextLayoutFormat):void
+		{
+			_defaultRowFormat = value;
+		}
+		
+		private var _defaultColumnFormat:ITextLayoutFormat;
+
+		/**
+		 * Gets the column format for new columns. 
+		 **/
+		public function get defaultColumnFormat():ITextLayoutFormat
+		{
+			if(!_defaultColumnFormat)
+				_defaultColumnFormat = new TextLayoutFormat(computedFormat);
+			return _defaultColumnFormat;
+		}
+
+		public function set defaultColumnFormat(value:ITextLayoutFormat):void
+		{
+			_defaultColumnFormat = value;
+		}
+		
+		/**
+		 * Adds a table cell element to the table. 
+		 * @inheritDoc
+		 **/
+		override public function addChild(child:FlowElement):FlowElement
+		{
+			
+			if (child is TableFormattedElement) {
+				TableFormattedElement(child).table = this;
+			}
+			
+			super.addChild(child);
+			
+			return child;
+		}
+		
+		/**
+		 * Removes a table cell element from the table. 
+		 * @inheritDoc
+		 **/
+		override public function removeChild(child:FlowElement):FlowElement
+		{
+			super.removeChild(child);
+			
+			if (child is TableFormattedElement) {
+				TableFormattedElement(child).table = null;
+			}
+			
+			return child;
+		}
+		
+		/**
+		 * Add a row at the end of the table. You would use this if you want to add a row
+		 * without changing the table cells. 
+		 * @see addRowAt
+		 * @see insertRow
+		 * @see insertRowAt
+		 **/
+		public function addRow(format:ITextLayoutFormat=null):void{
+			addRowAt(rows.length,format);
+		}
+		
+		/**
+		 * Add a row at the index specified. 
+		 * @see addRow
+		 * @see insertRow
+		 * @see insertRowAt
+		 **/
+		public function addRowAt(idx:int, format:ITextLayoutFormat=null):void{
+			if(idx < 0 || idx > rows.length)
+				throw RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+			
+			var row:TableRowElement = createRowElement(idx, format);
+			rows.splice(idx, 0, row);
+			row.composedHeight = row.computedFormat.minCellHeight;
+			row.isMaxHeight = row.computedFormat.minCellHeight == row.computedFormat.maxCellHeight;
+			row.setParentAndRelativeStartOnly(this, 1);
+		}
+
+		/**
+		 * Adds a column. You would use this if you want to add a column without changing the table cells. 
+		 * The cells would reflow, so a cell in row 2 might move up to row 1.
+		 * @see addColumnAt
+		 * @see insertColumn
+		 * @see insertColumnAt
+		 **/
+		public function addColumn(format:ITextLayoutFormat=null):void{
+			addColumnAt(columns.length,format);
+		}
+		
+		/**
+		 * Adds a column at the index specified. 
+		 * @see addColumn
+		 * @see insertColumn
+		 * @see insertColumnAt
+		 **/
+		public function addColumnAt(idx:int, format:ITextLayoutFormat=null):void{
+			if(idx < 0 || idx > columns.length)
+				throw RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+			if(!format) {
+				format = defaultColumnFormat;
+			}
+			var column:TableColElement = createColumnElement(idx, format);
+			
+			columns.splice(idx, 0, column);
+		}
+
+		/**
+		 * Returns the column at the index specified or null if the index is out of range. 
+		 **/
 		public function getColumnAt(columnIndex:int):TableColElement
 		{
-			if ( columnIndex < 0 || columnIndex >= _column )
+			if ( columnIndex < 0 || columnIndex >= numColumns )
+				return null;
+			return columns[columnIndex];
+		}
+		
+		/**
+		 * Returns the row at the index specified or null if the index is out of range. 
+		 **/
+		public function getRowAt(rowIndex:int):TableRowElement
+		{
+			if ( rowIndex < 0 || rowIndex >= numRows )
+				return null;
+			return rows[rowIndex];
+		}
+		
+		/**
+		 * Return the index of the row provided or -1 if the row is not found. 
+		 **/
+		public function getRowIndex(row:TableRowElement):int
+		{
+			for(var i:int=0;i<rows.length;i++)
+			{
+				if(rows[i] == row)
+					return i;
+			}
+			return -1;
+		}
+		
+		/**
+		 * Returns a vector of the cells for the row specified. 
+		 **/
+		public function getCellsForRow(row:TableRowElement):Vector.<TableCellElement>{
+			
+			return getCellsForRowAt(row.rowIndex);
+		}
+		
+		/**
+		 * Returns a vector of the cells for the row specified. 
+		 **/
+		public function getCellsForRowArray(row:TableRowElement):Array {
+			
+			return getCellsForRowAtArray(row.rowIndex);
+		}
+		
+		/**
+		 * Returns a vector of the cells for the row at the specified index. 
+		 **/
+		public function getCellsForRowAt(index:int):Vector.<TableCellElement>{
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			
+			if (index < 0) {
+				return cells;
+			}
+			
+			for each(var cell:TableCellElement in mxmlChildren){
+				if (cell.rowIndex == index) {
+					cells.push(cell);
+				}
+			}
+			
+			return cells;
+		}
+		
+		/**
+		 * Returns an array of the cells for the row specified. 
+		 **/
+		public function getCellsForRowAtArray(index:int):Array {
+			var cells:Array = [];
+			
+			if (index < 0) {
+				return cells;
+			}
+			
+			for each(var cell:TableCellElement in mxmlChildren){
+				if (cell.rowIndex == index) {
+					cells.push(cell);
+				}
+			}
+			
+			return cells;
+		}
+		
+		/**
+		 * Returns a Vector of the TableCellElements for the column specified. 
+		 **/
+		public function getCellsForColumn(column:TableColElement):Vector.<TableCellElement> {
+			if(columns.indexOf(column) < 0)
+				return null;
+			
+			return getCellsForColumnAt(column.colIndex);
+		}
+		
+		/**
+		 * Returns a Vector of the TableCellElements for the column at the specified index. 
+		 **/
+		public function getCellsForColumnAt(index:int):Vector.<TableCellElement> {
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			
+			if (index < 0) {
+				return cells;
+			}
+			
+			for each(var cell:TableCellElement in mxmlChildren){
+				if (cell.colIndex == index) {
+					cells.push(cell);
+				}
+			}
+			
+			return cells;
+		}
+		
+		/**
+		 * Inserts a column at the end of the table. If a column is not provided one is created. 
+		 * 
+		 * @see addColumn
+		 * @see addColumnAt
+		 * @see insertColumnAt
+		 **/
+		public function insertColumn(column:TableColElement=null,cells:Array = null):Boolean{
+			return insertColumnAt(numColumns,column,cells);
+		}
+		
+		/**
+		 * Inserts a column at the column specified. If the column is not provided it
+		 * creates a new column containing the cells supplied or creates the cells
+		 * based on the number of rows in the table. 
+		 * @see addColumn
+		 * @see addColumnAt
+		 * @see insertColumn
+		 **/
+		public function insertColumnAt(idx:int,column:TableColElement=null,cells:Array = null):Boolean{
+			
+			if (idx < 0 || idx > columns.length) {
+				throw RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+			}
+			
+			if (!column) {
+				column = createColumnElement(idx, defaultColumnFormat);
+			}
+			
+			columns.splice(idx,0,column);
+			
+			var blockedCoords:Vector.<CellCoords> = getBlockedCoords(-1,idx);
+			var cellIdx:int = getCellIndex(0,idx);
+			if(cellIdx < 0)
+				cellIdx = numChildren;
+			var rowIdx:int = 0;
+			
+			if (cells==null) cells = []; 
+			
+			while(cells.length < numRows){
+				cells.push(new TableCellElement());
+			}
+			
+			for each(var cell:TableCellElement in cells){
+				while(blockedCoords.length && blockedCoords[0].row == rowIdx){
+					rowIdx++;
+					blockedCoords.shift();
+				}
+				cellIdx = getCellIndex(rowIdx,idx);
+				if(cellIdx < 0)
+					cellIdx = numChildren;
+				
+				if(rowIdx < numRows){
+					addChildAt(cellIdx,cell);
+				}
+			}
+
+
+			return true;
+		}
+		
+		/**
+		 * Inserts a row at the end of the table. If a row is not provided one is created. 
+		 * @see insertRowAt
+		 **/
+		public function insertRow(row:TableRowElement=null,cells:Array = null):Boolean{
+			return insertRowAt(numRows,row,cells);
+		}
+		
+		/**
+		 * Inserts a row at the index specified. If the row is not provided it
+		 * creates a new row containing the cells supplied or creates the cells
+		 * based on the number of columns in the table. 
+		 **/
+		public function insertRowAt(idx:int,row:TableRowElement=null,cells:Array = null):Boolean{
+			if (idx < 0 || idx > rows.length) {
+				throw RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+			}
+			
+			if (!row) {
+				row = createRowElement(idx, defaultRowFormat);
+			}
+			
+			rows.splice(idx,0,row);
+			row.composedHeight = row.computedFormat.minCellHeight;
+			row.isMaxHeight = row.computedFormat.minCellHeight == row.computedFormat.maxCellHeight;
+
+			var blockedCoords:Vector.<CellCoords> = getBlockedCoords(idx);
+			var cellIdx:int = getCellIndex(idx,0);
+			if(cellIdx < 0)
+				cellIdx = numChildren;
+
+			var colIdx:int = 0;
+			
+			if (cells==null) cells = [];
+			
+			// create more cells 
+			while(cells.length < numColumns){
+				cells.push(new TableCellElement());
+			}
+			
+			for each(var cell:TableCellElement in cells){
+				while(blockedCoords.length && blockedCoords[0].column == colIdx){
+					colIdx++;
+					blockedCoords.shift();
+				}
+				if(colIdx < numColumns){
+					addChildAt(cellIdx++,cell);
+				}
+			}
+			return true;
+		}
+		
+		/**
+		 * Removes the row
+		 **/
+		public function removeRow(row:TableRowElement):TableRowElement {
+			var i:int = rows.indexOf(row);
+			if(i < 0)
+				return null;
+			return removeRowAt(i);
+		}
+		
+		/**
+		 * Removes the row and the cells it contains.
+		 **/
+		public function removeRowWithContent(row:TableRowElement):Array
+		{
+			var i:int = rows.indexOf(row);
+			if(i < 0)
 				return null;
-			return arColumn[columnIndex];
+			return removeRowWithContentAt(i);
+		}
+		
+		/**
+		 * Removes the row at the index specified.
+		 * @see removeRowWithContentAt
+		 **/
+		public function removeRowAt(idx:int):TableRowElement {
+			if(idx < 0 || idx > rows.length - 1)
+				return null;
+			
+			var row:TableRowElement = TableRowElement(rows.splice(idx,1)[0]);
+			normalizeCells();
+			hasCellDamage = true;
+			return row;
+			
+		}
+		
+		/**
+		 * Removes the row at the index specified and the cells it contains.
+		 **/
+		public function removeRowWithContentAt(idx:int):Array
+		{
+
+			var removedCells:Array = [];
+			
+			if(mxmlChildren){
+				for (var i:int = mxmlChildren.length-1;i>=0;i--){
+					var child:* = mxmlChildren[i];
+					if(!(child is TableCellElement))
+						continue;
+					var cell:TableCellElement = child as TableCellElement;
+					if(cell.rowIndex == idx){
+						removedCells.unshift(removeChild(cell));
+					}
+				}
+			}
+			
+			removeRowAt(idx);
+			return removedCells;
+		}
+		
+		/**
+		 * Removes all the rows and the cells.
+		 **/
+		public function removeAllRowsWithContent():void
+		{
+			var rowCount:int;
+			var cellCount:int;
+			
+			if (numRows>-1) {
+				rowCount = numRows-1;
+				
+				for (;rowCount>-1;) {
+					removeRowWithContentAt(rowCount--);
+				}
+				
+			}
+		}
+		
+		/**
+		 * Removes all the rows. Does not remove the cells.
+		 * @see removeAllRowsWithContent
+		 **/
+		public function removeAllRows():void
+		{
+			var rowCount:int;
+			var cellCount:int;
+			
+			if (numRows>-1) {
+				rowCount = numRows;
+				
+				for (var i:int; i < rowCount; i++) {
+					removeRowAt(i);
+				}
+				
+			}
+		}
+		
+		/**
+		 * Removes the column
+		 **/
+		public function removeColumn(column:TableColElement):TableColElement {
+			var i:int = columns.indexOf(column);
+			if(i < 0)
+				return null;
+			return removeColumnAt(i);
+		}
+		
+		/**
+		 * Removes the column and the cells it contains.
+		 **/
+		public function removeColumnWithContent(column:TableColElement):Array
+		{
+			var i:int = columns.indexOf(column);
+			if(i < 0)
+				return null;
+			return removeColumnWithContentAt(i);
+		}
+
+		/**
+		 * Removes the column at the index specified
+		 **/
+		public function removeColumnAt(idx:int):TableColElement {
+			if(idx < 0 || idx > columns.length - 1)
+				return null;
+			
+			var col:TableColElement = columns.splice(idx,1)[0];
+			normalizeCells();
+			hasCellDamage = true;
+			return col;
+		}
+		
+		/**
+		 * Removes the column at the index specified and the cells it contains. 
+		 **/
+		public function removeColumnWithContentAt(idx:int):Array
+		{
+			
+			var removedCells:Array = [];
+			if(mxmlChildren){
+				for (var i:int = mxmlChildren.length-1;i>=0;i--){
+					var child:* = mxmlChildren[i];
+					if(!(child is TableCellElement))
+						continue;
+					var cell:TableCellElement = child as TableCellElement;
+					if(cell.colIndex == idx){
+						removedCells.unshift(removeChild(cell));
+					}
+				}
+			}
+			removeColumnAt(idx);
+
+			return removedCells;
+		}
+		
+		/**
+		 * Remove all cells
+		 * @inheritDoc
+		 **/
+		override tlf_internal function removed():void
+		{
+			hasCellDamage = true;
+			//removeAllRowsWithContent();
+		}
+		
+		/**
+		 * @private
+		 * Gets table coordinates which represents the space occupied by cells spanning rows or columns
+		 **/
+		private function getBlockedCoords(inRow:int = -1, inColumn:int = -1):Vector.<CellCoords>{
+			var coords:Vector.<CellCoords> = new Vector.<CellCoords>();
+			
+			if(mxmlChildren) {
+				for each(var child:* in mxmlChildren){
+					var cell:TableCellElement = child as TableCellElement;
+					if (cell==null) continue;
+					if(cell.columnSpan == 1 && cell.rowSpan == 1)
+						continue;
+					var curRow:int = cell.rowIndex;
+					if(inRow >= 0 && curRow != inRow)
+						continue;
+					if(inColumn >= 0 && inColumn != curColumn)
+						continue;
+					var curColumn:int = cell.colIndex;
+					var endRow:int = curRow + cell.rowSpan - 1;
+					var endColumn:int = curColumn + cell.columnSpan -1;
+					for(var rowIdx:int = curRow;rowIdx <= endRow;rowIdx++){
+						for(var colIdx:int = curColumn;colIdx <=endColumn;colIdx++){
+							if(rowIdx == curRow && colIdx == curColumn){
+								continue;
+							}
+							coords.push( new CellCoords(colIdx, rowIdx) );
+						}
+					}
+
+				}
+			}
+			return coords;
 		}
 		
+		/**
+		 * Sets the row and column indices of the cells in the table to match their logical position as described by the table columns and rows
+		 **/
+		public function normalizeCells():void
+		{
+			this.numColumns;this.numRows;
+			var i:int;
+			var blockedCoords:Vector.<CellCoords> = new Vector.<CellCoords>();
+			
+			if (!mxmlChildren) {
+				return;
+			}
+			
+			var curRow:int = 0;
+			var curColumn:int = 0;
+			
+			for each(var child:* in mxmlChildren) {
+				
+				if (!(child is TableCellElement)) {
+					continue;
+				}
+				
+				var cell:TableCellElement = child as TableCellElement;
+				
+				if (cell.rowIndex != curRow || cell.colIndex != curColumn) {
+					cell.rowIndex = curRow;
+					cell.colIndex = curColumn;
+					cell.damage();
+				}
+				
+				// add blocked coords if the cell spans rows or columns
+				var endRow:int = curRow + cell.rowSpan - 1;
+				var endColumn:int = curColumn + cell.columnSpan -1;
+				
+				for(var rowIdx:int = curRow;rowIdx <= endRow;rowIdx++){
+					for(var colIdx:int = curColumn;colIdx <=endColumn;colIdx++){
+						if(rowIdx == curRow && colIdx == curColumn){
+							continue;
+						}
+						blockedCoords.push(new CellCoords(colIdx,rowIdx) );
+					}
+				}
+				
+				// advance coordinates while checking blocked ones from spans
+				do {
+					curColumn++;
+					
+					if (curColumn >= numColumns){
+						curColumn = 0;
+						curRow++;
+					}
+					
+					var advanced:Boolean = true;
+					
+					for (i=0;i<blockedCoords.length;i++){
+						if(blockedCoords[i].column == curColumn && blockedCoords[i].row == curRow){
+							advanced = false;
+							blockedCoords.splice(i,1);
+						}
+					}
+					
+					if (advanced) {
+						break;
+					}
+					
+				} while(1);
+				
+			}
+			
+		}
+		
+		/**
+		 * Set the width of the specified column. The value can be a number or percent. 
+		 **/
 		public function setColumnWidth(columnIndex:int, value:*):Boolean
 		{
-			var tableColElement:TableColElement = getColumnAt(columnIndex) as TableColElement;
+			//TODO: changing the column width probably requires a recompose of all cells in that column. Mark the cells in that row damaged.
+			var tableColElement:TableColElement = getColumnAt(columnIndex);
 			if ( ! tableColElement )
 				return false;
 			
@@ -131,6 +804,22 @@ package flashx.textLayout.elements
 			return true;
 		}
 		
+		/**
+		 * Set the height of the specified row. The value can be a number or percent. 
+		 **/
+		public function setRowHeight(rowIdx:int, value:*):Boolean{
+			//TODO: setting the row height might change the composition height of the cells. We'll need to do some housekeeping here.
+			// I'm not sure this function makes sense. We need to handle both min and max values to allow for expanding cells.
+			var row:TableRowElement = getRowAt(rowIdx);
+			if(!row)
+				return false;
+			
+			return true;
+		}
+		
+		/**
+		 * Get the width of the column. 
+		 **/
 		public function getColumnWidth(columnIndex:int):*
 		{
 			var tableColElement:TableColElement = getColumnAt(columnIndex) as TableColElement;
@@ -138,26 +827,712 @@ package flashx.textLayout.elements
 				return tableColElement.tableColumnWidth;
 			return 0;
         }
-        
-        public function get height():Number
-        {
-            return _height[numAcrossParcels];
-        }
-        
-        public function set height(val:*):void
-        {
-            _height[numAcrossParcels] = val;
-        }
-        
-        public function get heightArray():Array
-        {
-            return _height;
-        }
-        
-        public function set heightArray(newArray:Array):void
-        {
-            _height = newArray;
-        }
 		
+		/**
+		 * Sizes and positions the cells in the table. 
+		 **/
+		public function composeCells():void{
+			normalizeCells();
+			_composedRowIndex = 0;
+			
+			// make sure the height that defines the row height did not change. If it did we might need to change the row height.
+			if(!hasCellDamage)
+				return;
+			var damagedCells:Vector.<TableCellElement> = getDamagedCells();
+			var cell:TableCellElement;
+			
+			for each(cell in damagedCells){
+				// recompose the cells while tracking row height if necessary
+				cell.compose();
+			}
+			
+			// set row heights to minimum
+			for each (var row:TableRowElement in rows){
+				var minH:Number = row.computedFormat.minCellHeight;
+				var maxH:Number = row.computedFormat.maxCellHeight;
+				row.totalHeight = row.composedHeight = minH;
+				if(maxH > minH)
+					row.isMaxHeight = false;
+				else
+					row.isMaxHeight = true;
+				
+			}
+			
+			// set column positions...
+			var xPos:Number = 0;
+			for each (var col:TableColElement in columns){
+				col.x = xPos;
+				xPos += col.columnWidth;
+			}
+			
+			if (mxmlChildren) {
+				for(var i:int=0;i<mxmlChildren.length;i++){
+					if( !(mxmlChildren[i] is TableCellElement) )
+						continue;
+					cell = mxmlChildren[i] as TableCellElement;
+					while(rows.length < cell.rowIndex+1){
+						addRow(defaultRowFormat);
+					}
+					row = getRowAt(cell.rowIndex);
+					if(!row)
+						throw new Error("this should not happen...");
+					if(row.isMaxHeight) {
+						continue;
+					}
+					
+					var cellHeight:Number = cell.getComposedHeight();
+					if(cell.rowSpan > 1)
+					{
+						// figure out the total height taking into account fixed height rows and the total span.
+						
+						// for now, we're taking the easy way out assuming the rows are not fixed...
+						row.totalHeight = Math.max(row.totalHeight, cellHeight);
+						
+					}
+					else
+					{
+						row.composedHeight = Math.max(row.composedHeight, cellHeight);
+						row.composedHeight = Math.min(row.composedHeight, row.computedFormat.maxCellHeight);
+						row.totalHeight = Math.max(row.composedHeight, row.totalHeight);
+					}
+					if(row.composedHeight == row.computedFormat.maxCellHeight)
+						row.isMaxHeight = true;
+				}
+			}
+			
+			
+			if(!_tableRowsComputed)
+			{
+				// create arrays or rows to make table composition simpler
+				// For now we're assuming all cells have the correct row and column indices.
+				// For this assumption to remain valid, the interaction manager will have to update all indices when inserting rows and columns.
+				// actually, it probably makes sense for TableElement to handle that when adding rows and columns.
+				// we need to think this through.
+				_bodyRows = new Vector.< Vector.<TableCellElement> >();
+				
+				if (mxmlChildren) {
+					for(i=0;i<mxmlChildren.length;i++){
+						
+						if ( !(mxmlChildren[i] is TableCellElement) ) {
+							continue;
+						}
+						
+						cell = mxmlChildren[i] as TableCellElement;
+						
+						while(cell.rowIndex >= _bodyRows.length)
+							_bodyRows.push(new Vector.<TableCellElement>());
+							
+						var rowVec:Vector.<TableCellElement> = _bodyRows[cell.rowIndex] as Vector.<TableCellElement>;
+						
+						if(!rowVec){
+							rowVec = new Vector.<TableCellElement>();
+							_bodyRows[cell.rowIndex] = rowVec;
+						}
+						
+						if(rowVec.length > cell.colIndex && rowVec[cell.colIndex]) {
+							throw new Error("Two cells cannot have the same coordinates");
+						}
+						
+						rowVec.push(cell);
+					}
+				}
+				
+				if(headerRowCount > 0){
+					_headerRows = _bodyRows.splice(0,headerRowCount);
+				} else {
+					_headerRows = null;
+				}
+				
+				if(footerRowCount > 0){
+					_footerRows = _bodyRows.splice(-footerRowCount,Number.MAX_VALUE);
+				} else {
+					_footerRows = null;
+				}
+			}
+		}
+		
+		/**
+		 * returns the header rows for composition
+		 **/
+		public function getHeaderRows():Vector.< Vector.<TableCellElement> >{
+			return _headerRows;
+		}
+		
+		/**
+		 * returns the footer rows for composition
+		 **/
+		public function getFooterRows():Vector.< Vector.<TableCellElement> >{
+			return _footerRows;
+		}
+		
+		/**
+		 * returns the body rows (sans header and footer cells) for composition
+		 **/
+		public function getBodyRows():Vector.< Vector.<TableCellElement> >{
+			return _bodyRows;
+		}
+		
+		/**
+		 * returns a vector of table cells in the next row during composition
+		 **/
+		public function getNextRow():Vector.<TableCellElement>{
+			if(_composedRowIndex >= _bodyRows.length)
+				return null;
+			return _bodyRows[_composedRowIndex++];
+		}
+		
+		/**
+		 * Returns the next table cell after the supplied table cell
+		 **/
+		public function getNextCell(tableCell:TableCellElement):TableCellElement {
+			var cell:TableCellElement;
+			
+			for each (var element:FlowElement in mxmlChildren) {
+				cell = element as TableCellElement;
+				
+				if (cell) {
+					
+					// get next cell in same row 
+					if (cell.rowIndex==tableCell.rowIndex && cell.colIndex-1==tableCell.colIndex) {
+						return cell;
+					}
+					
+					// get first cell in next row
+					if (cell.rowIndex-1==tableCell.rowIndex && cell.colIndex==0) {
+						return cell;
+					}
+					
+				}
+			}
+			
+			return null;
+		}
+		
+		/**
+		 * Returns the previous table cell after the supplied table cell
+		 **/
+		public function getPreviousCell(tableCell:TableCellElement):TableCellElement {
+			var cell:TableCellElement;
+			var highestCellIndex:int = -1;
+			var rowIndex:int = -1;
+			
+			for each (var element:FlowElement in mxmlChildren) {
+				cell = element as TableCellElement;
+				
+				if (cell) {
+					
+					// get previous cell in same row 
+					if (cell.rowIndex==tableCell.rowIndex && cell.colIndex+1==tableCell.colIndex) {
+						return cell;
+					}
+					
+					// get last cell in previous row
+					if (cell.rowIndex+1==tableCell.rowIndex) {
+						rowIndex = cell.rowIndex;
+						
+						if (highestCellIndex<cell.colIndex) {
+							highestCellIndex = cell.colIndex;
+						}
+					}
+					
+				}
+			}
+			
+			if (rowIndex>-1 && highestCellIndex>-1) {
+				return getCellAt(rowIndex, highestCellIndex);
+			}
+			
+			return null;
+		}
+		
+		/**
+		 * Returns the table cell at the row and column specified.
+		 **/
+		public function getCellAt(rowIndex:int, columnIndex:int):TableCellElement {
+			var cell:TableCellElement;
+			
+			for each (var element:FlowElement in mxmlChildren) {
+				cell = element as TableCellElement;
+				
+				if (cell && cell.rowIndex==rowIndex && cell.colIndex==columnIndex) {
+					return cell;
+				}
+			}
+			
+			return null;
+		}
+		
+		/**
+		 * Computed height of the header cells
+		 **/
+		public function getHeaderHeight():Number{
+			//TODO: compute the header height from the header cells
+			return 0;
+		}
+		
+		/**
+		 * Computed height of the footer cells
+		 **/
+		public function getFooterHeight():Number{
+			//TODO: compute the footer height from the footer cells
+			return 0;
+			
+		}
+		
+		/**
+		 * Accepts a suggested table width and calculates the column widths. 
+		 **/
+		public function normalizeColumnWidths(suggestedWidth:Number = 600):void{
+			//TODO: before composition make sure all column widths are rational numbers
+			// We feed in a width to use if there's no width otherwise specified.
+			
+			// quick and dirty...
+			var setCount:* = computedFormat.columnCount;
+			if(!setCount){
+				// we need to figure this out...
+			} else if(setCount == FormatValue.AUTO){
+				// figure out...
+			} else {
+				var cCount:Number = computedFormat.columnCount;
+			}
+			
+			while (cCount > columns.length){
+				addColumn();
+			}
+			
+			var w:Number;
+			switch(typeof(computedFormat.tableWidth)){
+				case "number":
+					w = suggestedWidth;
+					break;
+				case "string":
+					if(computedFormat.tableWidth.indexOf("%") > 0){
+						w = suggestedWidth / (parseFloat(computedFormat.tableWidth)/100);
+						break;
+					}
+				default:
+					w = suggestedWidth;
+					break;
+			}
+			if(isNaN(w))
+				w = 600;
+			if(w > 20000)
+				w = 600;
+			
+			_computedWidth = w;
+
+			var numNonsetColumns:int = numColumns;
+			var col:TableColElement;
+			for each(col in columns){
+				// simply stomp on the settings. (need to finesse this...)
+				if(typeof(col.columnWidth) == "number")
+				{
+					w-= col.columnWidth;
+					numNonsetColumns--;
+				}
+			}
+
+			for each(col in columns)
+			{
+				// simply stomp on the settings. (need to finesse this...)
+				if(typeof(col.columnWidth) == "number")
+					continue;
+				col.columnWidth = w / numNonsetColumns;
+			}
+		}
+		
+		/**
+		 * Returns a vector of all the damaged cells in the table.
+		 **/
+		private function getDamagedCells():Vector.<TableCellElement>{
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			for each (var cell:* in this.mxmlChildren){
+				if((cell is TableCellElement) && cell.isDamaged())
+					cells.push(cell as TableCellElement);
+			}
+			return cells;
+		}
+		
+		/**
+		 * Marks all of the cells in the table as damaged.
+		 **/
+		private function markCellsDamaged():void {
+			if (!mxmlChildren) return;
+			
+			for each (var cell:* in this.mxmlChildren){
+				if (cell is TableCellElement) {
+					cell.damage();
+				}
+			}
+		}
+		
+		/**
+		 * Returns a vector of all the table cell elements in the table.
+		 **/
+		public function getCells():Vector.<TableCellElement> {
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			
+			for each (var cell:* in mxmlChildren){
+				if (cell is TableCellElement) {
+					cells.push(cell as TableCellElement);
+				}
+			}
+			
+			return cells;
+		}
+		
+		/**
+		 * Returns an array of all the table cells.
+		 **/
+		public function getCellsArray():Array {
+			var cells:Array = [];
+			
+			for each (var cell:* in mxmlChildren){
+				if (cell is TableCellElement) {
+					cells.push(cell as TableCellElement);
+				}
+			}
+			
+			return cells;
+		}
+		
+		/**
+		 * Returns the table width
+		 **/
+		public function get width():Number
+		{
+			return _computedWidth;
+		}
+		
+		/**
+		 * Sets the table width
+		 **/
+		public function set width(value:*):void
+		{
+			normalizeColumnWidths(value);
+		}
+		
+		
+		/**
+		 * Indicates elements in the table have been modified and the table must be recomposed.
+		 **/
+		public function get hasCellDamage():Boolean
+		{
+			return _hasCellDamage;
+		}
+
+		public function set hasCellDamage(value:Boolean):void
+		{
+			_hasCellDamage = value;
+		}
+
+		/**
+		 * Returns the number of header rows in the table
+		 **/
+		public function get headerRowCount():uint
+		{
+			return _headerRowCount;
+		}
+
+		/**
+		 * Sets the number of header rows in the table
+		 **/
+		public function set headerRowCount(value:uint):void
+		{
+			if(value != _headerRowCount)
+				_tableRowsComputed = false;
+			_headerRowCount = value;
+		}
+
+		/**
+		 * Returns the number of footer rows in the table
+		 **/
+		public function get footerRowCount():uint
+		{
+			return _footerRowCount;
+		}
+
+		/**
+		 * Sets the number of footer rows in the table
+		 **/
+		public function set footerRowCount(value:uint):void
+		{
+			if(value != _footerRowCount)
+				_tableRowsComputed = false;
+			_footerRowCount = value;
+		}
+		
+		/**
+		 * Gets the first TextFlowTableBlock in the table. 
+		 **/
+		public function getFirstBlock():TextFlowTableBlock{
+			if(_tableBlocks == null)
+				_tableBlocks = new Vector.<TextFlowTableBlock>();
+			if(_tableBlocks.length == 0)
+				_tableBlocks.push(new TextFlowTableBlock(0));
+			_tableBlockIndex = 0;
+			_tableBlocks[0].parentTable = this;
+			
+			return _tableBlocks[0];
+		}
+		
+		/**
+		 * Gets the next TextFlowTableBlock. 
+		 **/
+		public function getNextBlock():TextFlowTableBlock{
+			if(_tableBlocks == null)
+				_tableBlocks = new Vector.<TextFlowTableBlock>();
+			_tableBlockIndex++;
+			while(_tableBlocks.length <= _tableBlockIndex){
+				_tableBlocks.push( new TextFlowTableBlock(_tableBlocks.length) );
+			}
+			_tableBlocks[_tableBlockIndex].parentTable = this;
+			
+			return _tableBlocks[_tableBlockIndex];
+		}
+		
+		/**
+		 * Gets the total atom length of this flow element in the text flow.  
+		 * 
+		 * @inheritDoc
+		 **/
+		override public function get textLength():int{
+			return 1;
+		}
+		
+		/**
+		 * Returns the cell at the specified row and column. 
+		 **/
+		private function getCellIndex(rowIdx:int,columnIdx:int):int{
+			if(rowIdx == 0 && columnIdx == 0)
+				return 0;
+			for (var i:int=0;i<mxmlChildren.length;i++){
+				var item:* = mxmlChildren[i];
+				if(!(item is TableCellElement))
+					continue;
+				var cell:TableCellElement = item as TableCellElement;
+				if(cell.rowIndex == rowIdx && cell.colIndex == columnIdx)
+					return i;
+			}
+			return -1;
+			
+		}
+		
+		/**
+		 * Returns a vector of table cell elements in the given cell range. 
+		 **/
+		public function getCellsInRange(anchorCoords:CellCoordinates, activeCoords:CellCoordinates, block:TextFlowTableBlock=null):Vector.<TableCellElement>
+		{
+			var firstCoords:CellCoordinates = anchorCoords.clone();
+			var lastCoords:CellCoordinates = activeCoords.clone();
+			if(
+				lastCoords.row < firstCoords.row ||
+				(lastCoords.row == firstCoords.row && lastCoords.column < firstCoords.column)
+			)
+			{
+				firstCoords = activeCoords.clone();
+				lastCoords = anchorCoords.clone();
+			}
+			
+			// make sure the rectangle is not inversed
+			if(lastCoords.column < firstCoords.column)
+			{
+				var col:int = firstCoords.column;
+				firstCoords.column = lastCoords.column;
+				lastCoords.column = col;
+			}
+			var firstCell:TableCellElement = findCell(firstCoords);
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			if(!block || getCellBlock(firstCell) == block)
+				cells.push(firstCell);
+			var idx:int = mxmlChildren.indexOf(firstCell);
+			while(++idx < mxmlChildren.length)
+			{
+				var nextCell:TableCellElement = mxmlChildren[idx];
+				if(nextCell.rowIndex > lastCoords.row || (nextCell.rowIndex == lastCoords.row && nextCell.colIndex > lastCoords.column))
+					break;
+				// skip cells outside rectangle
+				if(nextCell.colIndex > lastCoords.column || nextCell.colIndex < firstCoords.column)
+					continue;
+				if(!block || getCellBlock(nextCell) == block)
+					cells.push(nextCell);
+			}
+			return cells;
+		}
+		
+		/**
+		 * Finds the cell at the specified cell coordinates or null if no cell is found. 
+		 **/
+		public function findCell(coords:CellCoordinates):TableCellElement
+		{
+			// get a guess of the cell location. If there's no holes (such as spans), it should theoretically pinpoint the index.
+			var idx:int = (coords.row+1) * (coords.column+1) -1;
+			if(idx >= numChildren)
+				idx = numChildren-1;
+			
+			var cell:TableCellElement = mxmlChildren[idx];
+			// look ahead to see if we're short (not sure if this is needed).
+			do
+			{
+				if(idx == numChildren-1)
+					break;
+				var nextCell:TableCellElement = mxmlChildren[idx+1];
+				if(nextCell.rowIndex > coords.row || (nextCell.rowIndex == coords.row && nextCell.colIndex > coords.column))
+					break;
+				
+				cell = nextCell;
+				idx++;
+				
+			}while(true);
+			// look behind accounting for spans
+			do
+			{
+				//check if the coords fall within the row and column span
+				if(
+					cell.colIndex <= coords.column && cell.colIndex + cell.columnSpan - 1 >= coords.column &&
+					cell.rowIndex <= coords.row && cell.rowIndex + cell.rowSpan - 1 >= coords.row
+				)
+					break;
+				//oops we hit the first cell without finding anything. At least return that...
+				if(cell.colIndex == 0 && cell.rowIndex == 0)
+					break;
+				if(idx == 0)
+					break;
+				var prevCell:TableCellElement = mxmlChildren[idx-1];
+				cell = prevCell;
+				idx--;
+			}while(true);
+			
+			return cell;
+		}
+		
+		/**
+		 * Adds the table cell container to the table block specified. 
+		 **/
+		public function addCellToBlock(cell:TableCellElement, block:TextFlowTableBlock):void
+		{
+			block.addCell(cell.container);
+			tableBlockDict[cell] = block;
+		}
+		
+		/**
+		 * Returns the table block for the given table cell. 
+		 **/
+		public function getCellBlock(cell:TableCellElement):TextFlowTableBlock
+		{
+			return tableBlockDict[cell];
+		}
+
+		/**
+		 * Keeps a reference to all the table blocks belonging to this table. 
+		 **/
+		private function get tableBlockDict():Dictionary
+		{
+			if(_tableBlockDict == null)
+				_tableBlockDict = new Dictionary();
+			return _tableBlockDict;
+		}
+		
+		/**
+		 * Returns a vector of the table blocks.
+		 **/
+		public function get tableBlocks():Vector.<TextFlowTableBlock>
+		{
+			return _tableBlocks;
+		}
+		
+		public function getTableBlocksInRange(start:CellCoordinates,end:CellCoordinates):Vector.<TextFlowTableBlock>
+		{
+			var coords:CellCoordinates = start.clone();
+			if(end.column < start.column)
+			{
+				coords = end.clone();
+				end = start.clone();
+			}
+			var blocks:Vector.<TextFlowTableBlock> = new Vector.<TextFlowTableBlock>();
+			var block:TextFlowTableBlock = getCellBlock(findCell(coords));
+			if(block)
+				blocks.push(block);
+			while(block)
+			{
+				coords.row++;
+				if(coords.row > end.row)
+					break;
+				if(getCellBlock(findCell(coords)) == block)
+					continue;
+				block = getCellBlock(findCell(coords));
+				if(block)
+					blocks.push(block);
+			}
+			return blocks;
+		}
+
+		/** @private */
+		tlf_internal override function getNextLeafHelper(limitElement:FlowGroupElement,child:FlowElement):FlowLeafElement
+		{
+			return parent.getNextLeafHelper(limitElement,this);
+		}
+		
+		/** @private */
+		tlf_internal override function getPreviousLeafHelper(limitElement:FlowGroupElement,child:FlowElement):FlowLeafElement
+		{
+			return parent.getPreviousLeafHelper(limitElement,this);
+		}
+
+		private function getLeaf():TableLeafElement
+		{
+			if(_leaf == null)
+				_leaf = new TableLeafElement(this);
+			return _leaf;
+		}
+		
+		public override function findLeaf(relativePosition:int):FlowLeafElement
+		{
+			return getLeaf();
+		}
+		public override function getLastLeaf(): FlowLeafElement
+		{
+			return getLeaf();
+		}
+		public override function getFirstLeaf():FlowLeafElement
+		{
+			return getLeaf();
+		}
+
+		tlf_internal override function createContentElement():void{}
+		/** @private 
+		 * Release the FTE data structure that corresponds to the FlowElement, so it can be gc'ed
+		 */
+		tlf_internal override function releaseContentElement():void{}
+
+		/**
+		 * Creates and returns a default row 
+		 **/
+		tlf_internal function createRowElement(index:int, defaultRowFormat:ITextLayoutFormat):TableRowElement {
+			var row:TableRowElement = new TableRowElement(defaultRowFormat);
+			row.rowIndex = index;
+			row.table = this;
+			return row;
+		}
+
+		/**
+		 * Creates and returns a default column 
+		 **/
+		tlf_internal function createColumnElement(index:int, defaultColumnFormat:ITextLayoutFormat):TableColElement {
+			var column:TableColElement = new TableColElement(defaultColumnFormat);
+			column.colIndex = index;
+			column.table = this;
+			return column;
+		}
+	}
+}
+class CellCoords
+{
+	public var column:int;
+	public var row:int;
+	public function CellCoords(colIdx:int,rowIdx:int)
+	{
+		column = colIdx;
+		row = rowIdx;
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as b/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
index 4b5bd0f..edad5e3 100644
--- a/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
@@ -25,6 +25,9 @@ package flashx.textLayout.elements
 			super();
 		}
 		
+		/**
+		 * Get a reference to the table. We could refactor this since it's accessed multiple times.
+		 **/
 		public function getTable():TableElement
 		{
 			// find the root element entry and either return null or the containing textFlow
@@ -32,6 +35,37 @@ package flashx.textLayout.elements
 			while ((elem.parent) != null && !( elem.parent is TableElement))
 				elem = elem.parent;
 			return elem.parent as TableElement;		
-		}	
+		}
+		
+		
+		private var _table:TableElement;
+		
+		/**
+		 * Returns a reference to the table. For this to work we need to set the 
+		 * table to null when it's removed. 
+		 **/
+		public function get table():TableElement {
+			
+			if (_table) return _table;
+			
+			// find the root element entry and either return null or the containing textFlow
+			var elem:FlowGroupElement = this;
+			
+			while ((elem.parent) != null && !(elem.parent is TableElement)) {
+				elem = elem.parent;
+			}
+			
+			_table = elem.parent as TableElement;
+			
+			return _table;
+		}
+		
+		/**
+		 * @private
+		 **/
+		public function set table(element:TableElement):void {
+			_table = element;
+		}
 	}
-}
\ No newline at end of file
+}
+


[08/25] git commit: [flex-tlf] [refs/heads/develop] - Small change to getting selection rects

Posted by pi...@apache.org.
Small change to getting selection rects


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/537c3525
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/537c3525
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/537c3525

Branch: refs/heads/develop
Commit: 537c35259306c87abb74ad073cab270ecc5b2f12
Parents: 3d51c48
Author: Harbs <ha...@in-tools.com>
Authored: Wed Oct 8 11:50:19 2014 +0300
Committer: Harbs <ha...@in-tools.com>
Committed: Wed Oct 8 11:50:19 2014 +0300

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/compose/TextFlowLine.as     | 5 +++--
 .../src/flashx/textLayout/compose/TextFlowTableBlock.as      | 8 ++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/537c3525/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/TextFlowLine.as b/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
index 0ff278f..bd6e015 100644
--- a/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
+++ b/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
@@ -1386,7 +1386,9 @@ package flashx.textLayout.compose
 			
 			// 8-31-14 Do we need to adjust this for paras with multiple textBlocks? 
 			//get the absolute start of the paragraph.  Calculation is expensive, so just do this once.
-			var paraAbsStart:int = _para.getAbsoluteStart();
+			//var paraAbsStart:int = _para.getAbsoluteStart();
+			var textLine:TextLine = getTextLine();
+			var paraAbsStart:int = _para.getTextBlockAbsoluteStart(textLine.textBlock);
 			
 			//if the indexes are identical and are equal to the start of the line, then
 			//don't draw anything.  This prevents a bar being drawn on a following line when
@@ -1420,7 +1422,6 @@ package flashx.textLayout.compose
 			selectionCache.begIdx = begIdx;
 			selectionCache.endIdx = endIdx;
 			
-			var textLine:TextLine = getTextLine();
 			var heightAndAdj:Array = getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
 			calculateSelectionBounds(textLine, drawRects, begIdx, endIdx, blockProgression, heightAndAdj);
 			

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/537c3525/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as b/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as
index b5e3329..b37c804 100644
--- a/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as
+++ b/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as
@@ -1,9 +1,12 @@
 package flashx.textLayout.compose
 {
 	
+	import flash.display.DisplayObject;
+	import flash.display.Shape;
 	import flash.text.engine.TextLine;
 	
 	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.edit.SelectionFormat;
 	import flashx.textLayout.elements.CellContainer;
 	import flashx.textLayout.elements.CellCoordinates;
 	import flashx.textLayout.elements.ParagraphElement;
@@ -210,6 +213,11 @@ package flashx.textLayout.compose
 		{
 			return _textHeight;
 		}
+		
+		tlf_internal override function hiliteBlockSelection(selObj:Shape, selFormat:SelectionFormat, container:DisplayObject, begIdx:int, endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine):void
+		{
+			// do nothing for now...
+		}
 
 	}
 }
\ No newline at end of file


[07/25] git commit: [flex-tlf] [refs/heads/develop] - Fixed handling of span editing before TableElement

Posted by pi...@apache.org.
Fixed handling of span editing before TableElement


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/3d51c48f
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/3d51c48f
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/3d51c48f

Branch: refs/heads/develop
Commit: 3d51c48f3b3a4851dcb0019a5270eea8dddc75bc
Parents: a0a0749
Author: Harbs <ha...@in-tools.com>
Authored: Mon Oct 6 11:58:25 2014 +0300
Committer: Harbs <ha...@in-tools.com>
Committed: Mon Oct 6 11:58:25 2014 +0300

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/edit/ParaEdit.as   | 11 +++++++++--
 .../flashx/textLayout/elements/ParagraphElement.as  | 16 ++++++++++++----
 .../flashx/textLayout/elements/TableLeafElement.as  |  5 +++++
 3 files changed, 26 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/3d51c48f/textLayout/src/flashx/textLayout/edit/ParaEdit.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/ParaEdit.as b/textLayout/src/flashx/textLayout/edit/ParaEdit.as
index 09ee41b..4af7e23 100644
--- a/textLayout/src/flashx/textLayout/edit/ParaEdit.as
+++ b/textLayout/src/flashx/textLayout/edit/ParaEdit.as
@@ -30,11 +30,13 @@ package flashx.textLayout.edit
 	import flashx.textLayout.elements.ParagraphElement;
 	import flashx.textLayout.elements.SpanElement;
 	import flashx.textLayout.elements.SubParagraphGroupElementBase;
+	import flashx.textLayout.elements.TableLeafElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.formats.Float;
 	import flashx.textLayout.formats.ITextLayoutFormat;
 	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.elements.TableElement;
 	
 	use namespace tlf_internal;
 
@@ -69,10 +71,15 @@ package flashx.textLayout.edit
 			{
 				// If we're at the start a span, go to the previous span in the same paragraph, and insert at the end of it
 				if (paraSelBegIdx == sibling.getElementRelativeStart(paragraph))
-					sibling = FlowLeafElement(sibling).getPreviousLeaf(paragraph);	
-				siblingIndex = sibling.parent.getChildIndex(sibling) + 1;
+					sibling = FlowLeafElement(sibling).getPreviousLeaf(paragraph);
+				if(sibling is TableLeafElement)
+					siblingIndex = sibling.parent.parent.getChildIndex(sibling.parent) + 1;
+				else
+					siblingIndex = sibling.parent.getChildIndex(sibling) + 1;
 			}
 			var insertParent:FlowGroupElement = sibling.parent;
+			if(insertParent is TableElement)
+				insertParent = insertParent.parent;
 			
 			// If we are adding text to the start or end of a link, it doesn't allow the insertion to group with the link.
 			// So in that case, we will insert to the element beside the position that is *not* part of the link.

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/3d51c48f/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
index 1fec299..6527d7c 100644
--- a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
+++ b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
@@ -352,6 +352,8 @@ package flashx.textLayout.elements
 		tlf_internal override function createContentAsGroup(pos:int=0):GroupElement
 		{
 			var tb:TextBlock = getTextBlockAtPosition(pos);
+			if(!tb)
+				tb = getTextBlockAtPosition(pos-1);
 			var group:GroupElement = tb.content as GroupElement;
 			if (!group)
 			{
@@ -467,14 +469,12 @@ package flashx.textLayout.elements
 			{
 				if(chldrn[i] is TableElement)
 				{
-					if(chldrn[i].parentRelativeStart == pos)
-						return [chldrn[i]];
 					if(chldrn[i].parentRelativeStart < pos)
 					{
 						retVal.length = 0;
 						continue;
 					}
-					if(chldrn[i].parentRelativeStart > pos)
+					if(chldrn[i].parentRelativeStart >= pos)
 						break;
 				}
 				retVal.push(chldrn[i]);		
@@ -487,7 +487,15 @@ package flashx.textLayout.elements
 		{
 			var relativeStart:int = child.getElementRelativeStart(this);
 			var tb:TextBlock = getTextBlockAtPosition(relativeStart);
-			if (getTextBlocks().length == 0 || !tb)
+			if(!tb)
+				tb = getTextBlockAtPosition(relativeStart-1);
+			
+			if(!tb)
+			{
+				child.releaseContentElement();
+				return;
+			}
+			if (getTextBlocks().length == 0)
 			{
 				child.releaseContentElement();
 				createTextBlock();	// does the whole tree

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/3d51c48f/textLayout/src/flashx/textLayout/elements/TableLeafElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableLeafElement.as b/textLayout/src/flashx/textLayout/elements/TableLeafElement.as
index 44e62a4..0fdf629 100644
--- a/textLayout/src/flashx/textLayout/elements/TableLeafElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableLeafElement.as
@@ -115,6 +115,11 @@ package flashx.textLayout.elements
 		{
 			return _table.getParagraph();
 		}
+		
+		override public function getElementRelativeStart(ancestorElement:FlowElement):int
+		{
+			return _table.getElementRelativeStart(ancestorElement);
+		}
 
 	}
 }


[23/25] git commit: [flex-tlf] [refs/heads/develop] - Reverted a commit from Alex that was lost with the last merge. Fixed line start index for TextFlowLine initialization

Posted by pi...@apache.org.
Reverted a commit from Alex that was lost with the last merge.
Fixed line start index for TextFlowLine initialization


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/863d00f8
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/863d00f8
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/863d00f8

Branch: refs/heads/develop
Commit: 863d00f860cf36b9355f18f3d24186c0fb9cd2be
Parents: 741a40a
Author: Harbs <ha...@in-tools.com>
Authored: Mon Nov 24 00:18:51 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Mon Nov 24 00:18:51 2014 +0200

----------------------------------------------------------------------
 .../src/flashx/textLayout/compose/BaseCompose.as       |  3 +--
 .../src/flashx/textLayout/compose/ComposeState.as      | 13 ++++++++-----
 2 files changed, 9 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/863d00f8/textLayout/src/flashx/textLayout/compose/BaseCompose.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/BaseCompose.as b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
index d1b675f..3ed8352 100644
--- a/textLayout/src/flashx/textLayout/compose/BaseCompose.as
+++ b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
@@ -1390,8 +1390,6 @@ package flashx.textLayout.compose
 
 			_curLine.initialize(_curParaElement, targetWidth, lineOffset-_parcelList.insideListItemMargin, _curLineStart, textLine.rawTextLength, textLine);
 			CONFIG::debug { assert(_curLine.targetWidth == targetWidth,"Bad targetWidth"); }
-
-			_curLineStart += _curLine.textLength;
 			return textLine;
 		}
 		
@@ -1415,6 +1413,7 @@ package flashx.textLayout.compose
 		/** Called when we are finished composing a line, and it is committed. Handler for derived classes to override default behavior.  */
 		protected function endLine(textLine:TextLine):void	// No PMD
 		{
+			_curLineStart += _curLine.textLength;
 			_contentCommittedExtent = Math.max(_contentCommittedExtent, _workingContentExtent);
 			_contentCommittedHeight = Math.max(_contentCommittedHeight, _workingContentHeight);
 			_contentLogicalExtent = Math.max(_contentLogicalExtent, _workingContentLogicalExtent);

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/863d00f8/textLayout/src/flashx/textLayout/compose/ComposeState.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/ComposeState.as b/textLayout/src/flashx/textLayout/compose/ComposeState.as
index e170bae..171e1b6 100644
--- a/textLayout/src/flashx/textLayout/compose/ComposeState.as
+++ b/textLayout/src/flashx/textLayout/compose/ComposeState.as
@@ -347,11 +347,14 @@ package flashx.textLayout.compose
 			var startCompose:int = _curElementStart + _curElementOffset - _curParaStart;
 			var line:TextFlowLine = _curLineIndex < _flowComposer.numLines ? (_flowComposer as StandardFlowComposer).lines[_curLineIndex] : null;
 			var useExistingLine:Boolean = line && (!line.isDamaged() || line.validity == FlowDamageType.GEOMETRY);
-			// if the line ends with a hyphen, don't use existing line because the player seems to mis-handle
-			// starting the next line.
-			if (useExistingLine && line.textLength > 0 &&
-				line.paragraph.getCharCodeAtPosition(line.absoluteStart + line.textLength - 1) == 0xAD)
-				useExistingLine = false;
+			if (ContainerController.tlf_internal::usesDiscretionaryHyphens)
+			{
+				// if the line ends with a hyphen, don't use existing line because the player seems to mis-handle
+				// starting the next line.
+				if (useExistingLine && line.textLength > 0 &&
+					line.paragraph.getCharCodeAtPosition(line.absoluteStart + line.textLength - 1) == 0xAD)
+					useExistingLine = false;
+			}
 			var numberLine:TextLine;
 			
 			// create numberLine if in a listElement


[22/25] git commit: [flex-tlf] [refs/heads/develop] - Change var name again, to keep to existing namimg convention

Posted by pi...@apache.org.
Change var name again, to keep to existing namimg convention

Signed-off-by: Erik de Bruin <er...@ixsoftware.nl>


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/741a40a4
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/741a40a4
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/741a40a4

Branch: refs/heads/develop
Commit: 741a40a4970d1839b14a500fcad9fa6ba22b9000
Parents: a9a1f9e
Author: Erik de Bruin <er...@ixsoftware.nl>
Authored: Fri Nov 21 11:03:19 2014 +0100
Committer: Erik de Bruin <er...@ixsoftware.nl>
Committed: Fri Nov 21 11:03:19 2014 +0100

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/elements/ParagraphElement.as | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/741a40a4/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
index 5f7cd09..51b8283 100644
--- a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
+++ b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
@@ -222,9 +222,9 @@ package flashx.textLayout.elements
 				return;
 			}
 			var tbs:Vector.<TextBlock> = getTextBlocks();
-			for each(var tb_:TextBlock in tbs)
+			for each(var textBlock:TextBlock in tbs)
 			{
-				releaseTextBlockInternal(tb_);
+				releaseTextBlockInternal(textBlock);
 			}
 			//_textBlock = null;
 			if (_computedFormat)


[19/25] git commit: [flex-tlf] [refs/heads/develop] - Add flexdebug property to ant build.xml and build.properties file

Posted by pi...@apache.org.
Add flexdebug property to ant build.xml and build.properties file


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/9f0382b8
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/9f0382b8
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/9f0382b8

Branch: refs/heads/develop
Commit: 9f0382b87f33f37064cb6b6b90b345e40340492e
Parents: 723311b
Author: piotrz <pi...@gmail.com>
Authored: Tue Nov 18 23:16:09 2014 +0100
Committer: piotrz <pi...@gmail.com>
Committed: Tue Nov 18 23:16:09 2014 +0100

----------------------------------------------------------------------
 build.properties |  3 ++-
 build.xml        | 14 ++++++++++----
 2 files changed, 12 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/9f0382b8/build.properties
----------------------------------------------------------------------
diff --git a/build.properties b/build.properties
index 925d779..fb3b6f7 100644
--- a/build.properties
+++ b/build.properties
@@ -27,7 +27,8 @@ src.depend = true
 src.debug = on
 
 forkValue = true
-minimalTests = false
+minimalTests = true
+flexdebug = false
 
 # JVM options for <compc> and <mxmlc> tasks
 jvm.args = ${local.d32} -Xms64m -Xmx1024m -XX:MaxPermSize=1024m -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -ea -Dapple.awt.UIElement=true

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/9f0382b8/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index a7c5bb5..6a7b8f2 100644
--- a/build.xml
+++ b/build.xml
@@ -50,6 +50,7 @@
 
 	<property name="dbg" value="false"/>
 	<property name="rel" value="true"/>
+    <property name="flexdebug" value="${flexdebug}"/>
 
 	<condition property="digest" value="false" else="true">
 		<istrue value="${debug}"/>
@@ -97,6 +98,7 @@
 			<static-link-runtime-shared-libraries/>
 			<define name="CONFIG::debug" value="${dbg}"/>
 			<define name="CONFIG::release" value="${rel}"/>
+            <compiler.debug>${flexdebug}</compiler.debug>
 		</compc>
      </target>
 
@@ -110,6 +112,7 @@
             <arg value="+source.dir=textLayout" />
 			<define name="CONFIG::debug" value="${dbg}"/>
 			<define name="CONFIG::release" value="${rel}"/>
+            <compiler.debug>${flexdebug}</compiler.debug>
 		</compc>
      </target>
 
@@ -169,13 +172,14 @@
 
 			<define name="CONFIG::debug" 			value="${dbg}"/>
 			<define name="CONFIG::release" 			value="${rel}"/>
+            <compiler.debug>${flexdebug}</compiler.debug>
 		</compc>
      </target>
 
 	<target name="textLayout_ui" description="Builds textLayout_ui.swc">		
 		<compc fork="${forkValue}" output="${output.dir}/apps/testApps/bin/textLayout_ui.swc" 
 			include-classes="${textLayout.namespace}.UiClasses,bxf.BxfClasses" compute-digest="${digest}">
-			<source-path path-element="${textLayout_ui.dir}/src"/>	
+			<source-path path-element="${textLayout_ui.dir}/src"/>
 			<jvmarg line="${jvm.args}"/>
 			<library-path/>
 			
@@ -190,12 +194,13 @@
 
 			<define name="CONFIG::debug" 			value="${dbg}"/>
 			<define name="CONFIG::release" 			value="${rel}"/>
+            <compiler.debug>${flexdebug}</compiler.debug>
 		</compc>
      </target>
 
 	<target name="testApps" description="Builds TLF test application">
 		<mxmlc fork="${forkValue}" 	file="${testApps.dir}/src/Flow.mxml" 
-				keep-generated-actionscript="false"
+				keep-generated-actionscript="false" debug="${flexdebug}"
 				output="${output.dir}/apps/automation_apps/bin/Flow.swf">
 			
 			<default-size width="1100" height="550" />
@@ -225,7 +230,7 @@
 
 	<target name="asTestApp" description="build a single application in asTestApp" if="output">
 		<mxmlc fork="${forkValue}"
-			file="${asTestApps.dir}/src/${output}.as"
+			file="${asTestApps.dir}/src/${output}.as" debug="${flexdebug}"
 			output="${output.dir}/apps/asTestApps/bin/${output}.swf">
 			<source-path path-element="${asTestApps.dir}/src"/>
 			<jvmarg line="${jvm.args}"/>
@@ -319,7 +324,8 @@
 	</target>
 
 	<target name="automation_apps" description="Builds the automation test application">
-		<mxmlc fork="${forkValue}" 	file="${automation_apps.dir}/src/VellumUnit.mxml" 
+		<mxmlc fork="${forkValue}" 	file="${automation_apps.dir}/src/VellumUnit.mxml"
+               debug="${flexdebug}"
 				output="${output.dir}/apps/automation_apps/bin/VellumUnit.swf">
 			<jvmarg line="${jvm.args}"/>
 			<library-path/>


[21/25] git commit: [flex-tlf] [refs/heads/develop] - The local var had the same name as the function argument. The Falcon compiler objects to this ; -)

Posted by pi...@apache.org.
The local var had the same name as the function argument. The Falcon compiler objects to this ;-)

Signed-off-by: Erik de Bruin <er...@ixsoftware.nl>


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/a9a1f9e1
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/a9a1f9e1
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/a9a1f9e1

Branch: refs/heads/develop
Commit: a9a1f9e11518a489af95f0eb781979c279e8c437
Parents: 41abfa4
Author: Erik de Bruin <er...@ixsoftware.nl>
Authored: Thu Nov 20 18:42:09 2014 +0100
Committer: Erik de Bruin <er...@ixsoftware.nl>
Committed: Thu Nov 20 18:42:09 2014 +0100

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/elements/ParagraphElement.as | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a9a1f9e1/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
index 4ddd7c4..5f7cd09 100644
--- a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
+++ b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
@@ -222,9 +222,9 @@ package flashx.textLayout.elements
 				return;
 			}
 			var tbs:Vector.<TextBlock> = getTextBlocks();
-			for each(var tb:TextBlock in tbs)
+			for each(var tb_:TextBlock in tbs)
 			{
-				releaseTextBlockInternal(tb);
+				releaseTextBlockInternal(tb_);
 			}
 			//_textBlock = null;
 			if (_computedFormat)


[14/25] git commit: [flex-tlf] [refs/heads/develop] - Merge remote-tracking branch 'remotes/origin/develop' into tables

Posted by pi...@apache.org.
Merge remote-tracking branch 'remotes/origin/develop' into tables

* remotes/origin/develop: (31 commits)
  Add TabTest with ingnored noTabStop test
  Add WritingModeTest, UndoRedoTest, TextFlowEditTest Remove unused variable from TestDescriptorRunner
  Back to the original implementation Ignore arrowUp and arrowDown tests in GeneralFunctionsTest
  Add echo to build.xml for print minimalTests value
  Set minimalTests property to true just for check ContainerTypeTest
  Add property minimalTests to make MinimalTestsSuite runnable
  FLEX-34611: Application crash when textFlow property set to null with preserveSelection
  FLEX-26478 Responding to dev review by adding curly braces around if clauses. Also optimised imports and renamed comment parameters in StandardFlowComposer and ContainerController.
  Remove unused import in ContainerAttributeTest
  FLEX-26478 CAUSE: When replacing ContainerControllers (triggered when the text changes in a TextField / TextArea), StandardFlowComposer tried to dispose of the discarded ones first. It did this by calling clearSelectionShapes() and setRootElement(null) on the ContainerControllers. However, if that controller was already listening for mouse scroll events (when the user selects text and moves the mouse outside the text field in such a way that causes the text to scroll), this listener wasn't removed. Which meant that the next time scrollTimerHandler() was called (on the inactive ContainerController), textFlow was null due to the call to setRootElement(null).
  Revert "revert these to see if they made a difference"
  revert these to see if they made a difference
  Attempt to fix build - set forkValue to true
  another attempt to fix flex-tlf
  Try to fix build with really high values -Xmx1024m -XX:MaxPermSize=1024m
  Try to fix build increase -Xmx512m
  Try to fix build - higher values for MaxPermSize=768
  Back to the original values for jvm.args
  Remove additional mxmlc buld of Flow.swf from testApps target in build.xml
  try even more PermGen
  ...

Conflicts:
	textLayout/src/flashx/textLayout/compose/StandardFlowComposer.as
	textLayout/src/flashx/textLayout/container/ContainerController.as


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/f6348cdb
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/f6348cdb
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/f6348cdb

Branch: refs/heads/develop
Commit: f6348cdba36e64b3b4af39212915916a263d1009
Parents: 84e8b25 1d79e24
Author: piotrz <pi...@apache.org>
Authored: Mon Nov 3 21:49:55 2014 +0100
Committer: piotrz <pi...@apache.org>
Committed: Mon Nov 3 21:49:55 2014 +0100

----------------------------------------------------------------------
 .../src/UnitTest/TestDescriptorRunner.mxml      |   13 +-
 automation_apps/src/VellumUnit.mxml             |    7 +-
 automation_core/src/AutomationCoreClasses.as    |    2 +
 .../UnitTest/ExtendedClasses/VellumTestCase.as  |    1 -
 automation_tests/src/AllTestsSuite.as           |   23 +-
 automation_tests/src/MinimalTestsSuite.as       |    4 +-
 .../UnitTest/Tests/BoundsAndAlignmentTest.as    |  278 +-
 automation_tests/src/UnitTest/Tests/BoxTest.as  |   51 +-
 .../UnitTest/Tests/ContainerAttributeTest.as    |    1 -
 .../src/UnitTest/Tests/ContainerTypeTest.as     |    8 -
 .../src/UnitTest/Tests/CrossContainerTest.as    |  430 ++-
 .../src/UnitTest/Tests/ElementOperationTest.as  | 1192 ++++++++
 .../src/UnitTest/Tests/ElementOperationTests.as | 1228 --------
 .../src/UnitTest/Tests/EventOverrideTest.as     |  905 +++---
 .../src/UnitTest/Tests/FactoryImportTest.as     |  250 +-
 .../src/UnitTest/Tests/FloatTest.as             |   84 -
 .../src/UnitTest/Tests/FlowModelTest.as         | 1920 ++++++-------
 .../src/UnitTest/Tests/GeneralFunctionsTest.as  | 2675 +++++++++---------
 automation_tests/src/UnitTest/Tests/TabTest.as  | 1087 +++----
 .../src/UnitTest/Tests/TextFlowEditTest.as      |  305 +-
 .../src/UnitTest/Tests/UndoRedoTest.as          |  153 +-
 .../src/UnitTest/Tests/WritingModeTest.as       |  795 +++---
 build.properties                                |   40 +
 build.xml                                       |   30 +-
 .../textLayout/compose/StandardFlowComposer.as  |   47 +-
 .../textLayout/container/ContainerController.as |  262 +-
 .../container/TextContainerManager.as           |    2 +-
 .../src/flashx/textLayout/edit/TextClipboard.as |   15 +-
 .../flashx/textLayout/utils/NavigationUtil.as   |    3 +-
 29 files changed, 5660 insertions(+), 6151 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/f6348cdb/textLayout/src/flashx/textLayout/compose/StandardFlowComposer.as
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/f6348cdb/textLayout/src/flashx/textLayout/container/ContainerController.as
----------------------------------------------------------------------
diff --cc textLayout/src/flashx/textLayout/container/ContainerController.as
index 08f4a68,f992734..a000035
--- a/textLayout/src/flashx/textLayout/container/ContainerController.as
+++ b/textLayout/src/flashx/textLayout/container/ContainerController.as
@@@ -18,78 -18,68 +18,115 @@@
  ////////////////////////////////////////////////////////////////////////////////
  package flashx.textLayout.container 
  {
- 	import flash.display.BlendMode;
- 	import flash.display.DisplayObject;
- 	import flash.display.DisplayObjectContainer;
- 	import flash.display.InteractiveObject;
- 	import flash.display.Shape;
- 	import flash.display.Sprite;
- 	import flash.events.ContextMenuEvent;
- 	import flash.events.Event;
- 	import flash.events.FocusEvent;
- 	import flash.events.IMEEvent;
- 	import flash.events.KeyboardEvent;
- 	import flash.events.MouseEvent;
- 	import flash.events.TextEvent;
- 	import flash.events.TimerEvent;
- 	import flash.geom.Matrix;
- 	import flash.geom.Point;
- 	import flash.geom.Rectangle;
- 	import flash.text.engine.TextBlock;
- 	import flash.text.engine.TextLine;
- 	import flash.text.engine.TextLineValidity;
- 	import flash.ui.ContextMenu;
- 	import flash.ui.ContextMenuClipboardItems;
- 	import flash.utils.Dictionary;
- 	import flash.utils.Timer;
+     import flash.display.BlendMode;
+     import flash.display.DisplayObject;
+     import flash.display.DisplayObjectContainer;
+     import flash.display.Shape;
+     import flash.display.Sprite;
+     import flash.events.ContextMenuEvent;
+     import flash.events.Event;
+     import flash.events.FocusEvent;
+     import flash.events.IEventDispatcher;
+     import flash.events.IMEEvent;
+     import flash.events.KeyboardEvent;
+     import flash.events.MouseEvent;
+     import flash.events.TextEvent;
+     import flash.events.TimerEvent;
+     import flash.geom.Matrix;
+     import flash.geom.Point;
+     import flash.geom.Rectangle;
+     import flash.text.engine.TextBlock;
+     import flash.text.engine.TextLine;
+     import flash.text.engine.TextLineValidity;
+     import flash.ui.ContextMenu;
+     import flash.ui.ContextMenuClipboardItems;
+     import flash.utils.Dictionary;
+     import flash.utils.Timer;
+ 
+     import flashx.textLayout.compose.FloatCompositionData;
+     import flashx.textLayout.compose.FlowDamageType;
+     import flashx.textLayout.compose.IFlowComposer;
+     import flashx.textLayout.compose.TextFlowLine;
+     import flashx.textLayout.compose.TextLineRecycler;
+     import flashx.textLayout.debug.Debugging;
+     import flashx.textLayout.debug.assert;
+     import flashx.textLayout.edit.EditingMode;
+     import flashx.textLayout.edit.IInteractionEventHandler;
+     import flashx.textLayout.edit.ISelectionManager;
+     import flashx.textLayout.edit.SelectionFormat;
+     import flashx.textLayout.elements.BackgroundManager;
+     import flashx.textLayout.elements.Configuration;
+     import flashx.textLayout.elements.ContainerFormattedElement;
+     import flashx.textLayout.elements.FlowElement;
+     import flashx.textLayout.elements.FlowLeafElement;
+     import flashx.textLayout.elements.FlowValueHolder;
+     import flashx.textLayout.elements.InlineGraphicElement;
+     import flashx.textLayout.elements.ParagraphElement;
+     import flashx.textLayout.elements.TCYElement;
+     import flashx.textLayout.elements.TextFlow;
+     import flashx.textLayout.events.FlowElementMouseEventManager;
+     import flashx.textLayout.events.ModelChange;
+     import flashx.textLayout.events.ScrollEvent;
+     import flashx.textLayout.events.ScrollEventDirection;
+     import flashx.textLayout.events.TextLayoutEvent;
+     import flashx.textLayout.events.UpdateCompleteEvent;
+     import flashx.textLayout.formats.BlockProgression;
+     import flashx.textLayout.formats.Float;
+     import flashx.textLayout.formats.FormatValue;
+     import flashx.textLayout.formats.ITextLayoutFormat;
+     import flashx.textLayout.formats.TextLayoutFormat;
+     import flashx.textLayout.tlf_internal;
+     import flashx.textLayout.utils.Twips;
+ 
+     use namespace tlf_internal;
  	
 +	import flashx.textLayout.compose.FloatCompositionData;
 +	import flashx.textLayout.compose.FlowComposerBase;
 +	import flashx.textLayout.compose.FlowDamageType;
 +	import flashx.textLayout.compose.IFlowComposer;
 +	import flashx.textLayout.compose.TextFlowLine;
 +	import flashx.textLayout.compose.TextFlowTableBlock;
 +	import flashx.textLayout.compose.TextLineRecycler;
 +	import flashx.textLayout.debug.Debugging;
 +	import flashx.textLayout.debug.assert;
 +	import flashx.textLayout.edit.EditingMode;
 +	import flashx.textLayout.edit.IInteractionEventHandler;
 +	import flashx.textLayout.edit.ISelectionManager;
 +	import flashx.textLayout.edit.SelectionFormat;
 +	import flashx.textLayout.elements.BackgroundManager;
 +	import flashx.textLayout.elements.CellCoordinates;
 +	import flashx.textLayout.elements.CellRange;
 +	import flashx.textLayout.elements.Configuration;
 +	import flashx.textLayout.elements.ContainerFormattedElement;
 +	import flashx.textLayout.elements.FlowElement;
 +	import flashx.textLayout.elements.FlowLeafElement;
 +	import flashx.textLayout.elements.FlowValueHolder;
 +	import flashx.textLayout.elements.InlineGraphicElement;
 +	import flashx.textLayout.elements.LinkElement;
 +	import flashx.textLayout.elements.ParagraphElement;
 +	import flashx.textLayout.elements.TableBlockContainer;
 +	import flashx.textLayout.elements.TableCellElement;
 +	import flashx.textLayout.elements.TableElement;
 +	import flashx.textLayout.elements.TableRowElement;
 +	import flashx.textLayout.elements.TextFlow;
 +	import flashx.textLayout.events.FlowElementMouseEvent;
 +	import flashx.textLayout.events.FlowElementMouseEventManager;
 +	import flashx.textLayout.events.ModelChange;
 +	import flashx.textLayout.events.ScrollEvent;
 +	import flashx.textLayout.events.ScrollEventDirection;
 +	import flashx.textLayout.events.TextLayoutEvent;
 +	import flashx.textLayout.events.UpdateCompleteEvent;
 +	import flashx.textLayout.formats.BlockProgression;
 +	import flashx.textLayout.formats.Float;
 +	import flashx.textLayout.formats.FormatValue;
 +	import flashx.textLayout.formats.ITextLayoutFormat;
 +	import flashx.textLayout.formats.TextLayoutFormat;
 +	import flashx.textLayout.property.Property;
 +	import flashx.textLayout.tlf_internal;
 +	import flashx.textLayout.utils.Twips;
 +	
 +	use namespace tlf_internal;
 +	
  	/** 
  	 * The ContainerController class defines the relationship between a TextFlow object and a container.
  	 * A TextFlow may have one or more rectangular areas that can hold text; the text is said to be flowing


[25/25] git commit: [flex-tlf] [refs/heads/develop] - Changed build.properties

Posted by pi...@apache.org.
Changed build.properties


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/86fbe932
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/86fbe932
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/86fbe932

Branch: refs/heads/develop
Commit: 86fbe9325610a3ae8b756958d9177227681cfd5c
Parents: 5357c43
Author: Harbs <ha...@in-tools.com>
Authored: Thu Nov 27 13:38:48 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Thu Nov 27 13:38:48 2014 +0200

----------------------------------------------------------------------
 build.properties | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/86fbe932/build.properties
----------------------------------------------------------------------
diff --git a/build.properties b/build.properties
index fb3b6f7..be2b672 100644
--- a/build.properties
+++ b/build.properties
@@ -27,11 +27,11 @@ src.depend = true
 src.debug = on
 
 forkValue = true
-minimalTests = true
-flexdebug = false
+minimalTests = false
+flexdebug = true
 
 # JVM options for <compc> and <mxmlc> tasks
-jvm.args = ${local.d32} -Xms64m -Xmx1024m -XX:MaxPermSize=1024m -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -ea -Dapple.awt.UIElement=true
+jvm.args = ${local.d32} -Xms64m -Xmx1024m -XX:MaxPermSize=1024m -XX:+CMSClassUnloadingEnabled -ea -Dapple.awt.UIElement=true
     # -d32/-d64 for 32-bit/64-bit code model (or don't specify for the default)
 	# -Xms64m: start out with a 64 MB heap
 	# -Xmx512m: allow the heap to grow to 512 MB


[17/25] git commit: [flex-tlf] [refs/heads/develop] - Fixed vertical placement of table blocks to take into account the previous line descent and paragraph space before/space after.

Posted by pi...@apache.org.
Fixed vertical placement of table blocks to take into account the previous line descent and paragraph space before/space after.


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/135709a2
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/135709a2
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/135709a2

Branch: refs/heads/develop
Commit: 135709a2ce8b0ad03b40a07d1c71abe1260b60d0
Parents: 8db7a4a
Author: Harbs <ha...@in-tools.com>
Authored: Tue Nov 18 00:32:54 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Tue Nov 18 00:32:54 2014 +0200

----------------------------------------------------------------------
 .../flashx/textLayout/compose/BaseCompose.as    | 21 ++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/135709a2/textLayout/src/flashx/textLayout/compose/BaseCompose.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/BaseCompose.as b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
index b051036..6107c2f 100644
--- a/textLayout/src/flashx/textLayout/compose/BaseCompose.as
+++ b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
@@ -548,6 +548,8 @@ package flashx.textLayout.compose
 			var curTableBlock:TextFlowTableBlock = tableElement.getFirstBlock();
 			curTableBlock.clear();
 			curTableBlock.y = _parcelList.totalDepth;
+			var adjustTop:Number = isNaN(_lastLineDescent) ? 0 : _lastLineDescent;
+			curTableBlock.y += adjustTop;
 			curTableBlock.x = _lineSlug.leftMargin;
 			var lineOffset:Number = (_curParaFormat.direction == Direction.LTR) ? _lineSlug.leftMargin : _lineSlug.rightMargin;
 			curTableBlock.initialize(_curParaElement, _lineSlug.width, lineOffset-_parcelList.insideListItemMargin, tableElement.getAbsoluteStart(),1);
@@ -1073,6 +1075,9 @@ package flashx.textLayout.compose
 			var result:Boolean = true;
 			var textLine:TextLine;
 			
+			var spaceBefore:Number;
+			var spaceCarried:Number;
+			
 			var leftMargin:Number;
 			var rightMargin:Number;
 			
@@ -1124,6 +1129,18 @@ package flashx.textLayout.compose
 				var curChild:FlowElement = _curParaElement.getChildAt(_curParaElement.findChildIndexAtPosition(_curElementStart - _curParaStart));
 				if(curChild is TableElement)
 				{
+					// Space before does not apply to the first line, unless LeadingModel.BOX is used
+					// Space carried never applies to the first line
+					spaceBefore = isNaN(_curParaElement.computedFormat.paragraphSpaceBefore) ? 0 : _curParaElement.computedFormat.paragraphSpaceBefore;
+					spaceBefore  = _atColumnStart ? 0 : spaceBefore;
+					spaceCarried = _atColumnStart ? 0 : _paragraphSpaceCarried;
+					if (spaceBefore != 0 || spaceCarried != 0)
+						_parcelList.addTotalDepth(Math.max(spaceBefore, spaceCarried));
+					
+					_paragraphSpaceCarried = 0;
+					if (_verticalSpaceCarried != 0)
+						_verticalSpaceCarried = 0;
+					
 					if(!composeTableElement(curChild as TableElement, _curElementStart))
 						return false;
 					
@@ -1215,8 +1232,8 @@ package flashx.textLayout.compose
 				
 				// Space before does not apply to the first line, unless LeadingModel.BOX is used
 				// Space carried never applies to the first line
-				var spaceBefore:Number  = _atColumnStart && (_curParaFormat.leadingModel != LeadingModel.BOX) ? 0 : _curLine.spaceBefore;
-				var spaceCarried:Number = _atColumnStart ? 0 : _paragraphSpaceCarried;
+				spaceBefore  = _atColumnStart && (_curParaFormat.leadingModel != LeadingModel.BOX) ? 0 : _curLine.spaceBefore;
+				spaceCarried = _atColumnStart ? 0 : _paragraphSpaceCarried;
 				if (spaceBefore != 0 || spaceCarried != 0)
 					_parcelList.addTotalDepth(Math.max(spaceBefore, spaceCarried));
 				


[05/25] git commit: [flex-tlf] [refs/heads/develop] - Commit of table work

Posted by pi...@apache.org.
Commit of table work


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/33df98ab
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/33df98ab
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/33df98ab

Branch: refs/heads/develop
Commit: 33df98ab9d2c69c84d4de6ab2ae969f9c5f93e35
Parents: e57200c
Author: Harbs <ha...@in-tools.com>
Authored: Sun Oct 5 22:39:30 2014 +0300
Committer: Harbs <ha...@in-tools.com>
Committed: Sun Oct 5 22:39:30 2014 +0300

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/CoreClasses.as |    3 +-
 .../flashx/textLayout/compose/BaseCompose.as    |  735 ++++-----
 .../flashx/textLayout/compose/ComposeState.as   |   28 +-
 .../textLayout/compose/FlowComposerBase.as      |   19 +-
 .../src/flashx/textLayout/compose/Parcel.as     |    4 +-
 .../src/flashx/textLayout/compose/ParcelList.as |    5 +-
 .../textLayout/compose/StandardFlowComposer.as  |    2 +-
 .../flashx/textLayout/compose/TextFlowLine.as   |   83 +-
 .../flashx/textLayout/container/ColumnState.as  |    6 +-
 .../textLayout/container/ContainerController.as |  307 +++-
 .../conversion/BaseTextLayoutExporter.as        |  260 ++-
 .../conversion/BaseTextLayoutImporter.as        |  101 +-
 .../textLayout/conversion/ConverterBase.as      |   15 +
 .../textLayout/conversion/ITextExporter.as      |    8 +-
 .../conversion/ImportExportConfiguration.as     |   41 +-
 .../textLayout/conversion/TextLayoutExporter.as |   70 +-
 .../textLayout/conversion/TextLayoutImporter.as |  208 ++-
 .../src/flashx/textLayout/edit/EditManager.as   |   53 +-
 .../flashx/textLayout/edit/ISelectionManager.as |  154 +-
 .../src/flashx/textLayout/edit/ModelEdit.as     |    2 +-
 .../src/flashx/textLayout/edit/ParaEdit.as      |   16 +-
 .../flashx/textLayout/edit/SelectionManager.as  | 1353 +++++++++++++---
 .../flashx/textLayout/edit/SelectionState.as    |   22 +-
 .../src/flashx/textLayout/edit/TextFlowEdit.as  |    4 +
 .../textLayout/elements/BackgroundManager.as    |  159 +-
 .../flashx/textLayout/elements/CellContainer.as |   34 +-
 .../flashx/textLayout/elements/FlowElement.as   |   26 +
 .../textLayout/elements/FlowGroupElement.as     |   12 +-
 .../textLayout/elements/FlowLeafElement.as      |    2 +
 .../textLayout/elements/ParagraphElement.as     |  683 ++++++--
 .../flashx/textLayout/elements/SpanElement.as   |    7 +-
 .../elements/SubParagraphGroupElementBase.as    |    2 +-
 .../textLayout/elements/TableColElement.as      |   35 +-
 .../flashx/textLayout/elements/TableElement.as  | 1503 +++++++++++++++++-
 .../elements/TableFormattedElement.as           |   38 +-
 .../textLayout/elements/TableRowElement.as      |  122 +-
 .../src/flashx/textLayout/elements/TextFlow.as  |   26 +
 .../textLayout/factory/StringTextLineFactory.as |    2 +-
 .../textLayout/factory/TextLineFactoryBase.as   |    2 +-
 .../ApplyElementStyleNameOperation.as           |    1 -
 .../ApplyElementUserStyleOperation.as           |    1 -
 41 files changed, 4916 insertions(+), 1238 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/CoreClasses.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/CoreClasses.as b/textLayout/src/flashx/textLayout/CoreClasses.as
index 42eaa87..c102f00 100644
--- a/textLayout/src/flashx/textLayout/CoreClasses.as
+++ b/textLayout/src/flashx/textLayout/CoreClasses.as
@@ -57,6 +57,7 @@ package flashx.textLayout
 		import flashx.textLayout.edit.ISelectionManager; ISelectionManager;
 		import flashx.textLayout.edit.SelectionFormat; SelectionFormat;
 		import flashx.textLayout.edit.SelectionState; SelectionState;
+		import flashx.textLayout.edit.SelectionType; SelectionType;
 		
 		import flashx.textLayout.elements.SubParagraphGroupElementBase; SubParagraphGroupElementBase;
 		import flashx.textLayout.elements.BreakElement; BreakElement;
@@ -87,7 +88,7 @@ package flashx.textLayout
 		import flashx.textLayout.elements.TableBodyElement; TableBodyElement;
 		import flashx.textLayout.elements.TableColElement; TableColElement;
 		import flashx.textLayout.elements.TableColGroupElement; TableColGroupElement;
-		import flashx.textLayout.elements.TableDataCellElement; TableDataCellElement;
+		import flashx.textLayout.elements.TableCellElement; TableCellElement;
 		import flashx.textLayout.elements.TableRowElement; TableRowElement;
 		import flashx.textLayout.elements.TCYElement; TCYElement;
 		import flashx.textLayout.elements.TextFlow; TextFlow;

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/compose/BaseCompose.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/BaseCompose.as b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
index b7c4b02..7a0557d 100644
--- a/textLayout/src/flashx/textLayout/compose/BaseCompose.as
+++ b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
@@ -30,7 +30,6 @@ package flashx.textLayout.compose
 	import flash.text.engine.TextLineValidity;
 	import flash.utils.Dictionary;
 	
-	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.debug.Debugging;
 	import flashx.textLayout.debug.assert;
@@ -50,8 +49,8 @@ package flashx.textLayout.compose
 	import flashx.textLayout.elements.SpanElement;
 	import flashx.textLayout.elements.TCYElement;
 	import flashx.textLayout.elements.TableBodyElement;
+	import flashx.textLayout.elements.TableCellElement;
 	import flashx.textLayout.elements.TableColElement;
-	import flashx.textLayout.elements.TableDataCellElement;
 	import flashx.textLayout.elements.TableElement;
 	import flashx.textLayout.elements.TableFormattedElement;
 	import flashx.textLayout.elements.TableRowElement;
@@ -70,14 +69,16 @@ package flashx.textLayout.compose
 	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.formats.VerticalAlign;
 	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.utils.LocaleUtil;
 	import flashx.textLayout.utils.Twips;
 
 	use namespace tlf_internal;
 	
 	
-	[ExcludeClass]
-	/** @private Common composer base class */
+	/** 
+	 * Common composer base class 
+	 * */
 	public class BaseCompose
 	{
 		
@@ -125,6 +126,8 @@ package flashx.textLayout.compose
 		protected var _curParaFormat:ITextLayoutFormat;
 		/** Absolute start position of _curParaElement */
 		protected var _curParaStart:int;
+		/** Absolute start position of the current line */
+		protected var _curLineStart:int;
 		/** leading model for the current line's para (set when line is being composed and committed to _lastLineLeadingModel when line is finalized) */
 		private var _curLineLeadingModel:String = "";
 		/** leading factor calculated when composing the current line (committed to _lastLineLeading when line is finalized)
@@ -307,7 +310,7 @@ package flashx.textLayout.compose
 			if (controllerStartIndex < 0)
 				controllerStartIndex = 0;
 			
-			// this chains through the list - tell it if a "care about" comopseToPosition was specified
+			// this chains through the list - tell it if a "care about" composeToPosition was specified
 			_parcelList.beginCompose(composer, controllerStartIndex, controllerEndIndex, composeToPosition > 0);	
 			
 			_contentLogicalExtent = 0;
@@ -324,74 +327,53 @@ package flashx.textLayout.compose
 			_listItemElement = null;
 		}
 		
-		private function composeBlockElement(elem:FlowGroupElement,absStart:int,isInTable:Boolean=false, startChildIdx:int = -1):Boolean
+		private function composeBlockElement(elem:FlowGroupElement, absStart:int, isInTable:Boolean=false, startChildIdx:int = -1):Boolean
 		{	
 			var child:FlowElement;
 			var rslt:Boolean;	// scratch
+			var isInTableCell:Boolean = elem is TextFlow && TextFlow(elem).parentElement is TableCellElement ? true : false;
+			var cellSpacing:Number = 0;
+			
+			if (isInTableCell) {
+				var tableCell:TableCellElement = TextFlow(elem).parentElement as TableCellElement;
+				var table:TableElement = tableCell.table;
+				cellSpacing = table.cellSpacing!=undefined ? table.cellSpacing : 0;
+			}
 			
 			// Iterate through the children, composing them. If we're starting in the middle of the element,
 			// make sure we advance to the starting child.
 			var idx:int = 0;
 			if ( startChildIdx != -1 )
 				idx = startChildIdx;
-			if(!isInTable)
+			
+			if (absStart != _curElementStart + _curElementOffset) 	// starting partway in
 			{
-				if (absStart != _curElementStart + _curElementOffset) 	// starting partway in
+				idx = elem.findChildIndexAtPosition((_curElementStart + _curElementOffset) - absStart);
+				child = elem.getChildAt(idx);
+				absStart += child.parentRelativeStart;
+				
+				// Fix bug#2907691 When composition starts in middle of the container, paddingBottom for the previous paragraph is ignored
+				// add prevous paragraph's paddingBottom values to totalDepth
+				var previousElement:FlowLeafElement = _textFlow.findLeaf(_startComposePosition - 1);
+				if (previousElement)
 				{
-					idx = elem.findChildIndexAtPosition((_curElementStart + _curElementOffset) - absStart);
-					child = elem.getChildAt(idx);
-					absStart += child.parentRelativeStart;
-					
-					// Fix bug#2907691 When composition starts in middle of the container, paddingBottom for the previous paragraph is ignored
-					// add prevous paragraph's paddingBottom values to totalDepth
-					var previousElement:FlowLeafElement = _textFlow.findLeaf(_startComposePosition - 1);
-					if (previousElement)
-					{
-						var previousParagraph:ParagraphElement = previousElement.getParagraph();
-						if (previousParagraph && previousParagraph != _curElement.getParagraph())
-							if (previousParagraph.paddingBottom != undefined)
-								_parcelList.addTotalDepth(previousParagraph.paddingBottom);
-					}
-					
-					// child is table means recompose starts in the middle of a table. 
-					// In this case, we finished compose the table, then continue
-					if ( child is TableElement )
-					{
-						child = _curElement;
-						while ( child && ! (child is TableRowElement) )
-							child = child.parent;
-						
-						var tableElement:TableElement = child.parent as TableElement;
-						tableElement.totalRowDepth = 0;
-						tableElement.numAcrossParcels = 0;
-						tableElement.originParcelIndex = 0;
-						tableElement.heightArray = [];
-						if ( ! composeBlockElement(child.parent, _curElementStart, true, (child as TableRowElement).rowIndex) )
-						{
-							BackgroundManager.collectBlock(_textFlow, tableElement, _parcelList, true);
-							return false;
-						}
-						
-						// Add table border info
-						tableElement.totalRowDepth += tableElement.getEffectiveBorderBottomWidth() + tableElement.computedFormat.cellSpacing;
-						tableElement.height = tableElement.totalRowDepth;
-						
-						absStart = _curElementStart;
-						idx ++;
-						
-						if ( ! gotoParcel(tableElement.numAcrossParcels, tableElement.totalRowDepth) )	
-							return false;
-						
-						_atColumnStart = false;
-						_parcelList.addTotalDepth(tableElement.getEffectiveMarginBottom());
-						
-						BackgroundManager.collectBlock(_textFlow, tableElement, _parcelList, true);
-					}
+					var previousParagraph:ParagraphElement = previousElement.getParagraph();
+					if (previousParagraph && previousParagraph != _curElement.getParagraph())
+						if (previousParagraph.paddingBottom != undefined)
+							_parcelList.addTotalDepth(previousParagraph.paddingBottom);
 				}
-			}
+				
+				// child is table means recompose starts in the middle of a table. 
+				// In this case, we finished compose the table, then continue
+				// Harbs - need to analize whether this makes sense at all...
+				/*
+				if ( child is TableElement )
+				{
+				// if it makes sense, we need to redo this logic.
 
-			
-			
+				}
+				*/
+			}
 			
 			var composeEntireElement:Boolean = (absStart == _curElementStart + _curElementOffset);
 
@@ -400,41 +382,45 @@ package flashx.textLayout.compose
 			{
 				child = elem.getChildAt(idx);
 				
-				if(!isInTable)
+				// If the element has clear applied, handle that now
+				if (child.computedFormat.clearFloats != ClearFloats.NONE)
 				{
-					// If the element has clear applied, handle that now
-					if (child.computedFormat.clearFloats != ClearFloats.NONE)
-					{
-						var adjustedDepth:Number = _curParcel.applyClear(child.computedFormat.clearFloats, _parcelList.totalDepth, child.computedFormat.direction);
-						_parcelList.addTotalDepth(adjustedDepth);
-						_verticalSpaceCarried = 0;
-					}
-	
-					var boxLeftIndent:Number;		// logical with respect to horizontal/vertical text
-					var boxRightIndent:Number;		// logical with respect to horizontal/vertical text
-					var boxTopIndent:Number;		// logical with respect to horizontal/vertical text
-					var boxBottomIndent:Number;		// logical with respect to horizontal/vertical text
-					if (_blockProgression == BlockProgression.RL)
-					{
-						boxLeftIndent = child.getEffectivePaddingTop() + child.getEffectiveBorderTopWidth() + child.getEffectiveMarginTop();
-						boxRightIndent = child.getEffectivePaddingBottom() + child.getEffectiveBorderBottomWidth() + child.getEffectiveMarginBottom();
-						boxTopIndent = child.getEffectivePaddingRight() + child.getEffectiveBorderRightWidth() + child.getEffectiveMarginRight();
-						boxBottomIndent = child.getEffectivePaddingLeft() + child.getEffectiveBorderLeftWidth() + child.getEffectiveMarginLeft();
-					}
-					else
-					{
-						boxLeftIndent = child.getEffectivePaddingLeft() + child.getEffectiveBorderLeftWidth() + child.getEffectiveMarginLeft();
-						boxRightIndent = child.getEffectivePaddingRight() + child.getEffectiveBorderRightWidth() + child.getEffectiveMarginRight();
-						boxTopIndent = child.getEffectivePaddingTop() + child.getEffectiveBorderTopWidth() + child.getEffectiveMarginTop();
-						boxBottomIndent = child.getEffectivePaddingBottom() + child.getEffectiveBorderBottomWidth() + child.getEffectiveMarginBottom();
+					var adjustedDepth:Number = _curParcel.applyClear(child.computedFormat.clearFloats, _parcelList.totalDepth, child.computedFormat.direction);
+					_parcelList.addTotalDepth(adjustedDepth);
+					_verticalSpaceCarried = 0;
+				}
+				
+				var boxLeftIndent:Number;		// logical with respect to horizontal/vertical text
+				var boxRightIndent:Number;		// logical with respect to horizontal/vertical text
+				var boxTopIndent:Number;		// logical with respect to horizontal/vertical text
+				var boxBottomIndent:Number;		// logical with respect to horizontal/vertical text
+				if (_blockProgression == BlockProgression.RL)
+				{
+					boxLeftIndent = child.getEffectivePaddingTop() + child.getEffectiveBorderTopWidth() + child.getEffectiveMarginTop();
+					boxRightIndent = child.getEffectivePaddingBottom() + child.getEffectiveBorderBottomWidth() + child.getEffectiveMarginBottom();
+					boxTopIndent = child.getEffectivePaddingRight() + child.getEffectiveBorderRightWidth() + child.getEffectiveMarginRight();
+					boxBottomIndent = child.getEffectivePaddingLeft() + child.getEffectiveBorderLeftWidth() + child.getEffectiveMarginLeft();
+				}
+				else
+				{
+					boxLeftIndent = child.getEffectivePaddingLeft() + child.getEffectiveBorderLeftWidth() + child.getEffectiveMarginLeft();
+					boxRightIndent = child.getEffectivePaddingRight() + child.getEffectiveBorderRightWidth() + child.getEffectiveMarginRight();
+					boxTopIndent = child.getEffectivePaddingTop() + child.getEffectiveBorderTopWidth() + child.getEffectiveMarginTop();
+					boxBottomIndent = child.getEffectivePaddingBottom() + child.getEffectiveBorderBottomWidth() + child.getEffectiveMarginBottom();
+					
+					if (isInTableCell) {
+						boxLeftIndent += cellSpacing;
+						boxRightIndent += cellSpacing;
+						boxTopIndent += cellSpacing;
+						boxBottomIndent += cellSpacing;
 					}
-					CONFIG::debug { assert(!isNaN(boxLeftIndent) && ! isNaN(boxRightIndent),"BAD indents"); }
-					_parcelList.pushLeftMargin(boxLeftIndent);
-					_parcelList.pushRightMargin(boxRightIndent);
-					if (composeEntireElement && boxTopIndent > _verticalSpaceCarried)
-						_parcelList.addTotalDepth(boxTopIndent - _verticalSpaceCarried);
-					_verticalSpaceCarried = Math.max(boxTopIndent, 0);
 				}
+				CONFIG::debug { assert(!isNaN(boxLeftIndent) && ! isNaN(boxRightIndent),"BAD indents"); }
+				_parcelList.pushLeftMargin(boxLeftIndent);
+				_parcelList.pushRightMargin(boxRightIndent);
+				if (composeEntireElement && boxTopIndent > _verticalSpaceCarried)
+					_parcelList.addTotalDepth(boxTopIndent - _verticalSpaceCarried);
+				_verticalSpaceCarried = Math.max(boxTopIndent, 0);
 								
 				
 				var para:ParagraphElement = child as ParagraphElement;
@@ -468,7 +454,7 @@ package flashx.textLayout.compose
 				}
 				else if (child is ListElement)
 				{						
-					rslt = composeBlockElement(FlowGroupElement(child),absStart,isInTable);
+					rslt = composeBlockElement(FlowGroupElement(child),absStart);
 					
 					if (!rslt)
 					{
@@ -481,7 +467,7 @@ package flashx.textLayout.compose
 				{
 					var savedListItemElement:ListItemElement = _listItemElement;
 					_listItemElement = child as ListItemElement;
-					rslt = composeBlockElement(FlowGroupElement(child),absStart,isInTable);
+					rslt = composeBlockElement(FlowGroupElement(child),absStart);
 					_listItemElement = savedListItemElement;
 						
 					if (!rslt)
@@ -491,24 +477,6 @@ package flashx.textLayout.compose
 						return false;
 					}
 				}
-				else if (child is TableElement)         // Compose TableElement
-				{
-					if ( ! composeTableElement(child as TableElement, absStart, isInTable) )
-						return false;
-				}
-				else if (child is TableRowElement)     // Compose TableRowElement
-				{
-					var rowElement:TableRowElement = child as TableRowElement;
-					rowElement.rowIndex = idx;
-					
-					if ( ! composeTableRowElement(elem as TableElement, rowElement, absStart, isInTable) )
-						return false;
-				}
-				else if (child is TableDataCellElement) // Compose TableDataCellElement
-				{
-					if ( ! composeTableDataCellElement(elem as TableRowElement, child as TableDataCellElement, absStart, isInTable) )
-						return false;
-				}
 				else 
 				{
 					if ( ! composeBlockElement(FlowGroupElement(child),absStart))
@@ -519,22 +487,20 @@ package flashx.textLayout.compose
 					}
 				}
 				
-				if(! isInTable)
-				{
-					if (boxBottomIndent > _verticalSpaceCarried)
-						_parcelList.addTotalDepth(boxBottomIndent - _verticalSpaceCarried);
-					_verticalSpaceCarried = Math.max(boxBottomIndent, 0);
-	
-					// restore to original values
-					_parcelList.popLeftMargin(boxLeftIndent);
-					_parcelList.popRightMargin(boxRightIndent);
-					composeEntireElement = true;
-				}
+				if (boxBottomIndent > _verticalSpaceCarried)
+					_parcelList.addTotalDepth(boxBottomIndent - _verticalSpaceCarried);
+				_verticalSpaceCarried = Math.max(boxBottomIndent, 0);
+				
+				// restore to original values
+				_parcelList.popLeftMargin(boxLeftIndent);
+				_parcelList.popRightMargin(boxRightIndent);
+				composeEntireElement = true;
+				
 				absStart += child.textLength;
 			}
 			
-			//for elements, whose text are all visible, except for TableElement, TableRowElement and TableDataCellElement
-			if(!(elem is TableElement || elem is TableRowElement || elem is TableDataCellElement))
+			//for elements, whose text are all visible, except for TableElement, TableRowElement and TableCellElement
+			if(!(elem is TableElement || elem is TableRowElement || elem is TableCellElement))// (we don't process these...)
 				BackgroundManager.collectBlock(_textFlow, elem);
 			
 			return true;
@@ -545,322 +511,168 @@ package flashx.textLayout.compose
 		 * In  : TableElement, table's absStart position, isInTable
 		 * Out : Boolean value, composition result, true - successful, false - failed
 		 */
-		private function composeTableElement(tableElement:TableElement, absStart:int, isInTable:Boolean):Boolean
+		private function composeTableElement(tableElement:TableElement, absStart:int):Boolean
 		{
-			//1st step findout the TableGroup element and get the composing parameter for the columns
-			//my first idea is to read them to be a TableElement list or map. And remove all the column 
-			//element so that the column element will not fall into the recursive loop
-			tableElement.numAcrossParcels = 0;
-            tableElement.heightArray = [];
-            tableElement.curRowIdx = 0;
-            tableElement.outOfLastParcel = false;
-            
-			//2nd step setup the environment settings
-			var marginLeft:Number = tableElement.computedFormat.marginLeft;
-			var marginTop:Number  = tableElement.computedFormat.marginTop;
-            
-			tableElement.x = _parcelList.currentParcel.x + marginLeft;
-			tableElement.y = _parcelList.totalDepth + (_atColumnStart ? marginTop : _firstLineDescentAndLeading + marginTop);
-			
-			_parcelList.addTotalDepth(tableElement.y - _parcelList.totalDepth);
-			
-			// The following codes are setting the column width
-			serializeTableColumnWidth(tableElement);
-			
-			//TO-DO: Verify the borderTopWidth Value
-			tableElement.originParcelIndex = _parcelList.currentParcelIndex;
-			var originParcel:Parcel = _parcelList.currentParcel;
-			
-			// Add table border info
-			_parcelList.addTotalDepth(tableElement.getEffectiveBorderTopWidth());
-			tableElement.totalRowDepth = _parcelList.totalDepth;
-			
-			//2nd step recursively compose the table elements
-			if ( ! composeBlockElement(FlowGroupElement(tableElement), absStart, true) )
-            {
-                // If we're out of parcel, we don't need to calculate table height anymore,
-                // because we've done in composeTableRowElement before it return false.
-                if(tableElement.outOfLastParcel)
-                    BackgroundManager.collectBlock(_textFlow, tableElement, _parcelList, false, true);
-                
-                return false;
-            }
-			
-			// Add table border info
-			tableElement.totalRowDepth += tableElement.getEffectiveBorderBottomWidth() + tableElement.computedFormat.cellSpacing;
-			
-            if(tableElement.numAcrossParcels == 0 && _startComposePosition <= tableElement.getAbsoluteStart())
-                tableElement.height = tableElement.totalRowDepth - tableElement.y;
-            else
-				tableElement.height = tableElement.totalRowDepth;
-
-			// If current composition position plus one line height beyond the parcel bottom, then we jump to next parcel 
-			var depth:Number = tableElement.totalRowDepth;
-			
-			// If table already full the last column, we won't goto table cell parcel. Just goto last not table cell parcel
-			var parcelIdx:int = tableElement.originParcelIndex + tableElement.numAcrossParcels;
-			if ( _parcelList.getParcelAt(parcelIdx).isTableParcel )
-				depth = _parcelList.getParcelAt(--parcelIdx).bottom;
-			
-			if ( ! gotoParcel(parcelIdx, depth) )	
-				return false;
+			//TODO: remove any old existing cells in the _parcelList.currentParcel.controller from the position of the table and on.
+			// need to figure out the accounting needed for that.
 			
-            _atColumnStart = false;
-			_parcelList.addTotalDepth(tableElement.getEffectiveMarginBottom());
+			// get a slug...
+			_parcelList.getLineSlug(_lineSlug, 0, 1, _textIndent, _curParaFormat.direction == Direction.LTR);
 			
-			BackgroundManager.collectBlock(_textFlow, tableElement, _parcelList);
-			return true;
-		}
-		
-		/** @private
-		 * Compose a entire table row element
-		 * In  : TableElement, TableRowElement, table's absStart position, isInTable
-		 * Out : Boolean value, composition result, true - successful, false - failed
-		 */
-		private function composeTableRowElement(tableElement:TableElement, rowElement:TableRowElement, absStart:int, isInTable:Boolean):Boolean
-		{
-			rowElement.iMaxRowDepth = 0;
-            rowElement.columnIndex = 0;
-			
-			// Add table cell spacing value
-			tableElement.totalRowDepth += tableElement.computedFormat.cellSpacing;
-			
-			// Save environment parameters before compose a table row, because maybe this row out of "current" parcel, 
-			// in that case, we need to reload these parameters, then recompose this row.
-			var curParaStart:int = _curParaStart;
-			var curElementStart:int = _curElementStart;
-			var curParcelStart:int = _curParcelStart;
-			var curElement:FlowLeafElement = _curElement;
-			var curParaElement:ParagraphElement = _curParaElement;
-            
-            if ( ! composeBlockElement(FlowGroupElement(rowElement), absStart, isInTable) )
-			{
-				// Compose row failed, see if we it's because of out of parcel
-				if ( rowElement.beyondParcel )
-				{
-                    var nextParcel:Parcel = _parcelList.getParcelAt(tableElement.originParcelIndex + tableElement.numAcrossParcels + 1);
-
-                    if(tableElement.curRowIdx == 0)
-                    {
-                        if(!nextParcel || nextParcel.isTableParcel)
-                        {
-                            tableElement.x = tableElement.computedFormat.marginLeft;
-                            tableElement.y = tableElement.totalRowDepth;
-                        }
-                    }
-                    
-                    // Release textLines before re-compose
-                    for ( var i:int = 0; i < rowElement.numChildren; i ++ )
-                    {
-                        var cell:TableDataCellElement = rowElement.getChildAt(i) as TableDataCellElement;
-                        for ( var j:int = 0; j < cell.numChildren; j ++ )
-                        {
-                            var paragraph:ParagraphElement = cell.getChildAt(j) as ParagraphElement;
-                            var textBlock:TextBlock = paragraph.getTextBlock();
-                            _parcelList.currentParcel.controller.clearFloatsAt(paragraph.getAbsoluteStart());
-                            for (var textLine:TextLine = textBlock.lastLine; textLine; )
-                            {
-                                textBlock.releaseLines(textLine, textLine);
-                                textLine.userData = null;
-                                textLine.visible = false;
-                                //TextLineRecycler.addLineForReuse(textLine);
-                                if (_textFlow.backgroundManager)
-                                    _textFlow.backgroundManager.removeLineFromCache(textLine);
-                                textLine = textBlock.lastLine;
-                            }
-                            paragraph.releaseTextBlock();
-                        }
-                    }
-                    
-					// If table already full the last column, we won't goto table cell parcel. Just goto last not table cell parcel
-					if ( ! nextParcel || nextParcel.isTableParcel)
-                    {
-                        tableElement.outOfLastParcel = true;
-						return false;
-                    }
-                    
-                    if(tableElement.curRowIdx > 0)
-                    {
-                        tableElement.numAcrossParcels ++;
-                        tableElement.heightArray.push(0);
-                        tableElement.totalRowDepth = nextParcel.y + tableElement.computedFormat.cellSpacing;
-                    }
-                    else if(tableElement.curRowIdx == 0)
-                    {
-                        tableElement.originParcelIndex++;
-                        tableElement.x = nextParcel.x + tableElement.computedFormat.marginLeft;
-                        tableElement.y = nextParcel.y;
-                        tableElement.totalRowDepth = nextParcel.y + tableElement.computedFormat.cellSpacing + tableElement.getEffectiveBorderTopWidth();
-                    }
-
-					rowElement.beyondParcel = false;
-                    
-                    // Reload values for recompose
-                    _curParaStart = curParaStart;
-                    _curElementStart = curElementStart;
-                    _curParcelStart = curParcelStart;
-                    _curElement = curElement;
-                    _curParaElement = curParaElement;
-                    _curElementOffset = 0;
-                    _contentLogicalExtent = 0;
-                    rowElement.columnIndex = 0;
-                    
-					// Recompose current table row
-					if ( ! composeBlockElement(FlowGroupElement(rowElement), absStart, isInTable) )
-						return false;
-				}
-			}
+			// doesn't do anything yet.
+			tableElement.normalizeColumnWidths(_lineSlug.width);
 			
-            var curParcel:Parcel = _parcelList.getParcelAt(tableElement.originParcelIndex + tableElement.numAcrossParcels);
-			rowElement.parcelIndex = tableElement.originParcelIndex + tableElement.numAcrossParcels;
-			rowElement.height = rowElement.iMaxRowDepth;
-			rowElement.x = curParcel.x;
-			rowElement.y = tableElement.totalRowDepth;
-			tableElement.totalRowDepth += rowElement.height;
-			
-			if(tableElement.numAcrossParcels == 0 && _startComposePosition <= tableElement.getAbsoluteStart())
-				tableElement.height = tableElement.totalRowDepth - tableElement.y;
-			else
-				tableElement.height = tableElement.totalRowDepth;
+			// step 1 -- make sure all cells are composed
+			tableElement.composeCells();
 			
-			tableElement.height += tableElement.cellSpacing;
-			
-			// Add table cell to columnState for hitTest
-			var ccOfRow:ContainerController = _parcelList.getParcelAt(rowElement.parcelIndex).controller;
-			for ( i = 0; i < rowElement.numChildren; i ++ )
-			{
-				cell = rowElement.getChildAt(i) as TableDataCellElement;
-				cell.height = rowElement.height;
-				_parcelList.addTableCell2ColumnState(ccOfRow, cell);
-			}
-			
-			BackgroundManager.collectBlock(_textFlow, rowElement, _parcelList);
-            tableElement.curRowIdx++;
-			return true;
-		}
-		
-		/** @private
-		 * Compose a entire table row element
-		 * In  : TableRowElement, TableDataCellElement, table's absStart position, isInTable
-		 * Out : Boolean value, composition result, true - successful, false - failed
-		 */
-		private function composeTableDataCellElement(rowElement:TableRowElement, cellElement:TableDataCellElement, absStart:int, isInTable:Boolean):Boolean
-		{
-			//TableDataCellElement's parent must be TableRowElement
-			var tableElement:TableElement = rowElement.getTable();
-			
-			//TO-DO: This is temporary codes, needs to be updated when the real column attribute is implemented
-			var currParcel:Parcel = _parcelList.getParcelAt(tableElement.originParcelIndex + tableElement.numAcrossParcels);
-			cellElement.x = currParcel.x + tableElement.getColumnAt(rowElement.columnIndex).x;
-			cellElement.y = tableElement.totalRowDepth;
-			cellElement.width = tableElement.getColumnWidth(rowElement.columnIndex);
-			cellElement.height = undefined;
-			var rc:Rectangle = new Rectangle(cellElement.x, cellElement.y, cellElement.width, 8000); // 8000 is Max row height
-			cellElement.parcelIndex = _parcelList.numParcels();
-			var newParcel:Parcel = _parcelList.addParcel(rc, currParcel.controller,
-				tableElement.originParcelIndex + tableElement.numAcrossParcels);
-			newParcel.isTableParcel = true;
-			
-			if ( ! gotoParcel(cellElement.parcelIndex, 0) )
-				return false;
+			// step 2 get header and footer heights
+			// I'm not sure if we need to calculate table padding/margin
+			//var baseTableHeight:Number = tableElement.getHeaderHeight() + tableElement.getFooterHeight();
+			//_parcelList.getLineSlug(_lineSlug, 0, 1, _textIndent, _curParaFormat.direction == Direction.LTR);
 			
-			// Add border and cell padding
-			_parcelList.addTotalDepth(cellElement.getEffectiveBorderTopWidth() + cellElement.computedFormat.cellPadding);
-			_parcelList.pushLeftMargin(cellElement.getEffectiveBorderLeftWidth() + cellElement.computedFormat.cellPadding);
-			_parcelList.pushRightMargin(cellElement.getEffectiveBorderRightWidth() + cellElement.computedFormat.cellPadding);
+			var headerHeight:Number = tableElement.getHeaderHeight();
+			var footerHeight:Number = tableElement.getFooterHeight();
 			
-			// fall into the recursive loop directly
-			if ( ! composeBlockElement(FlowGroupElement(cellElement), absStart, isInTable) )
-				return false;
+			// need to calculate margins and padding as well. (top, bottom and sides) It should inherit from the containing paragraph if necessary.
+			// I'm assuming tables can inherit proeprties from paragraphs.
 			
-			// Add border and cell padding, pop out padding margin
-			_parcelList.addTotalDepth(cellElement.getEffectiveBorderBottomWidth() + cellElement.computedFormat.cellPadding);
-			_parcelList.popLeftMargin(cellElement.getEffectiveBorderLeftWidth() + cellElement.computedFormat.cellPadding);
-			_parcelList.popRightMargin(cellElement.getEffectiveBorderRightWidth() + cellElement.computedFormat.cellPadding);
+			// step 3 loop through the cells and assign them to containers and set the positions
+
+			var totalRowHeight:Number = 0;
+			var haveRealRows:Boolean = false;
+			//grab the headers and footers for use in each parcel
+			var headerRows:Vector.< Vector.<TableCellElement> > = tableElement.getHeaderRows();
+			var footerRows:Vector.< Vector.<TableCellElement> > = tableElement.getFooterRows();
 			
-			//TO-DO, The codes may be changed, mingjun's original codes are as following:
-			//cellElement.height = _parcelList.totalDepth + paragraph.paddingBottom + paragraph.borderBottomWidth + paragraph.marginBottom;
-			cellElement.height = _parcelList.totalDepth;
-			if ( cellElement.height > rowElement.iMaxRowDepth )
-				rowElement.iMaxRowDepth = cellElement.height;
-			rowElement.columnIndex ++;
+			var curRow:Vector.<TableCellElement> = tableElement.getNextRow();
+			var curTableBlock:TextFlowTableBlock = tableElement.getFirstBlock();
+			curTableBlock.clear();
+			curTableBlock.y = _parcelList.totalDepth;
+			curTableBlock.x = _lineSlug.leftMargin;
+			var lineOffset:Number = (_curParaFormat.direction == Direction.LTR) ? _lineSlug.leftMargin : _lineSlug.rightMargin;
+			curTableBlock.initialize(_curParaElement, _lineSlug.width, lineOffset-_parcelList.insideListItemMargin, tableElement.getAbsoluteStart(),1);
+			var blockToAdd:Boolean = true;
 			
-			// See if the composed line beyond "current" parcel's bottom
-			if ( tableElement.totalRowDepth + rowElement.iMaxRowDepth > currParcel.bottom)
-			{
-				rowElement.beyondParcel = true;
+			while(curRow){
 				
-				// Pop out useless parcels for this row
-				for ( var n:int = 0; n < rowElement.columnIndex; n ++ )
-					_parcelList.popParcel();
-				return false;
-			}
-			
-			return true;
-		}
-		
-		/** @private
-		 * Calculate table columm width based on column's width value, the rule is :
-		 * if there are zero column width or the sum(columnWidth) not equal to table.tableWidth,
-		 * we calculate average column width.
-		 * In  : Number or percentage
-		 * Out : Set pixcel based width of each table column
-		 */
-		private function serializeTableColumnWidth(table:TableElement):void
-		{
-            var curParcelWidth:Number = _parcelList.currentParcel.width;
-			if ( table.tableWidth != undefined && table.tableWidth < curParcelWidth )
-				table.computedWidth = table.tableWidth;
-			else
-                table.computedWidth = curParcelWidth;
-            
-            if(table.computedFormat.marginLeft > 0)
-                table.computedWidth -= table.computedFormat.marginLeft;
-            
-            table.computedWidth -= table.computedFormat.marginRight;
-            
-			var logicalWidth:Number = table.computedWidth - table.getEffectiveBorderLeftWidth() - table.getEffectiveBorderRightWidth() - (table.column + 1) * table.computedFormat.cellSpacing;
-			var columnTotalWidth:Number = table.getEffectiveBorderLeftWidth() + table.computedFormat.marginLeft;
-            
-			for ( var i:int = 0; i < table.column; i ++ )
-			{
-				var colWidth:* = table.getColumnWidth(i);
+				// I'm ignoring headers and footers for now. We need to add them in later.
+				var rIdx:int = curRow[0].rowIndex;
+				var curRowElem:TableRowElement = tableElement.getRowAt(rIdx);
+				var rowHeight:Number = curRowElem.composedHeight;
+				var minRowHeight:Number = curRowElem.totalHeight;
+				//_parcelList.addTotalDepth(tableElement.getEffectiveMarginBottom());
 				
-				// Column width is percentage like "20%"
-				var strWidth:String = colWidth as String;
-				if ( strWidth && strWidth.length != 0 && strWidth.charAt(strWidth.length - 1) == '%' )
-				{
-					colWidth = Property.toNumberIfPercent(colWidth) * logicalWidth / 100;
-					if ( colWidth >= 0 )
-						table.setColumnWidth(i, colWidth);
+				while(
+					false
+					//!(_parcelList.currentParcel.fitsInHeight(_parcelList.totalDepth, minRowHeight + footerHeight))
+				){
+					//TODO: add in footer rows...
+					
+					curTableBlock.height = totalRowHeight;
+					
+					if(!haveRealRows)
+						curTableBlock.clear();
+					
+					endTableBlock(curTableBlock);
+//					curTableBlock.setController(_parcelList.currentParcel.controller,_parcelList.currentParcel.columnIndex);
+
+//					_parcelList.currentParcel.controller.addComposedTableBlock(curTableBlock.container);
+//					BackgroundManager.collectTableBlock(_textFlow,curTableBlock, _parcelList.currentParcel.controller);
+					blockToAdd = false;
+					
+					if(!_parcelList.next())
+					{ // current parcel not valid
+						break;
+					}
+					_parcelList.getLineSlug(_lineSlug, 0, 1, _textIndent, _curParaFormat.direction == Direction.LTR);
+					curTableBlock = tableElement.getNextBlock();
+					blockToAdd = true;
+					curTableBlock.clear();
+					curTableBlock.y = _parcelList.totalDepth;
+					curTableBlock.x = _lineSlug.leftMargin;
+					curTableBlock.initialize(_curParaElement, _lineSlug.width, lineOffset-_parcelList.insideListItemMargin, tableElement.getAbsoluteStart(),1);
+					totalRowHeight = 0;
+					//TODO: remove any old existing cells in the _parcelList.currentParcel.controller
+					
+					//TODO: add in header rows. Collect them on the next iteration if no real rows fit.
+					
+					// not needed?
+					if(_parcelList.currentParcel == null){
+						blockToAdd = false;
+						break;
+					}
+				}
+				
+				if(_parcelList.currentParcel == null){
+					blockToAdd = false;
+					break;
 				}
 				
-				columnTotalWidth += table.computedFormat.cellSpacing;
-				table.getColumnAt(i).x = columnTotalWidth;
-				columnTotalWidth += colWidth;
+				// we have a parcel and a row. Let's add the cells.
+				for each(var cell:TableCellElement in curRow) {
+					cell.y = totalRowHeight;
+					var col:TableColElement = tableElement.getColumnAt(cell.colIndex);
+					
+					if (col) {
+						cell.x = col.x;
+					}
+					
+					tableElement.addCellToBlock(cell, curTableBlock);
+					//curTableBlock.addCell(cell.container);
+					// add the cells to _parcelList.currentParcel.controller
+					// need to figure out exactly how.
+					
+				}
+				
+				// add the row height
+				// we're assuming normal top to bottom tables -- not Japanese ones...
+				_parcelList.addTotalDepth(rowHeight);
+				
+				curRow = tableElement.getNextRow();
+				totalRowHeight += rowHeight;
 			}
-            
-			columnTotalWidth -= (table.computedFormat.marginLeft + table.getEffectiveBorderLeftWidth() + table.column * table.computedFormat.cellSpacing);
 			
-			// If the sum of column width wider than table width,
-			// we set every column width to average column width
-			if ( columnTotalWidth - logicalWidth > 1 )
-			{
-				var avgColumnWidth:Number = logicalWidth / table.column;
-				for ( var m:int = 0; m < table.column; m ++ )
-				{
-					table.setColumnWidth(m, avgColumnWidth);
-					table.getColumnAt(m).x = table.getEffectiveBorderLeftWidth() + table.computedFormat.marginLeft 
-						+ (m+1)*table.computedFormat.cellSpacing + m * avgColumnWidth;
-				}
-			} 
-			// if the sum of column width less than table width, we enlarge the last column's width to fit table width
-			else if ( columnTotalWidth < logicalWidth ) 
-			{
-				var orgWidth:Number = table.getColumnWidth(table.column - 1);
-				table.setColumnWidth(table.column - 1, orgWidth + logicalWidth - columnTotalWidth);
+			if(_parcelList.currentParcel && blockToAdd){
+				curTableBlock.height = totalRowHeight;
+				endTableBlock(curTableBlock);
+//				curTableBlock.setController(_curParcel.controller,_curParcel.columnIndex);
+//				_parcelList.currentParcel.controller.addComposedTableBlock(curTableBlock.container);
+//				BackgroundManager.collectTableBlock(_textFlow,curTableBlock, _parcelList.currentParcel.controller);
 			}
+			//reference ComposeState.composeNextLine() which creates the the TextLine.
+			// We don't need getLineSlug() because tables can extend beyond the container width
+			// We do need to get the available height and push any cells that don't fit to the next Parcel/container
+			// Repeat until there's no more Parcels.
+			
+			// step 4 draw the backgrounds and borders
+			// handled by the BackgroundManager			
+			
+			return true;
 		}
+		/** Called when we are finished composing a line, and it is committed. Handler for derived classes to override default behavior.  */
+		protected function endTableBlock(block:TextFlowTableBlock):void
+		{
+			_curLine = block;
+			block.setController(_curParcel.controller, _curParcel.columnIndex);
+			//				_parcelList.currentParcel.controller.addComposedTableBlock(curTableBlock.container);
+			BackgroundManager.collectTableBlock(_textFlow, block, _parcelList.currentParcel.controller);
+
+			_contentCommittedExtent = Math.max(_contentCommittedExtent, _workingContentExtent);
+			_contentCommittedHeight = Math.max(_contentCommittedHeight, _workingContentHeight);
+			_contentLogicalExtent = Math.max(_contentLogicalExtent, _workingContentLogicalExtent);
+			
+			// if not measuring than contentLogicalExtent needs to match contentCommitedExtent so restarting composition in the middle gets the right extent
+			// don't need contentLogicalExtent to exclude things pushing beyond the right margin as alignment is happening as we go
+			if (!_measuring)
+				_contentLogicalExtent = _contentCommittedExtent;
+			if (_pushInFloats)
+				_pushInFloats.length = 0;	// zero it out for the next line
+			_atColumnStart = false;
+			_linePass = 0;
+			if (!isNaN(_workingParcelLogicalTop))
+				_parcelLogicalTop = _workingParcelLogicalTop;
+		}		
+
 		
 		/**
 		 * Compose the flow into the text container. Starts at the root element,
@@ -892,9 +704,8 @@ package flashx.textLayout.compose
 			
 			resetControllerBounds();
 			
-			// Bug, needs to remove
-			if (ContainerController.tlf_internal::startComposeFromBeginning)
-				_startComposePosition = _startController.absoluteStart;
+			// Bug, needs to remove 
+			_startComposePosition = _startController.absoluteStart;
 			
 			// This is where we will start composing from
 			_curElement = _textFlow.findLeaf(_startComposePosition);
@@ -1186,6 +997,7 @@ package flashx.textLayout.compose
 		{
 			_curParaElement  = elem;
 			_curParaStart    = absStart;
+			_curLineStart    = absStart;
 			_curParaFormat = elem.computedFormat;
 			
 			CONFIG::debug { assert(_curParaStart == elem.getAbsoluteStart(),"composeParagraphElement: bad start"); }
@@ -1204,25 +1016,28 @@ package flashx.textLayout.compose
 			{
 				// Lines that are now composed that would not be visible on update, might still be in the display list from
 				// a previous update. Don't release in that case.
-				var textBlock:TextBlock = elem.getTextBlock();
+				var textBlocks:Vector.<TextBlock> = elem.getTextBlocks();
 				var textLine:TextLine;
-				for (textLine = textBlock.lastLine; textLine && okToRelease; textLine = textLine.previousLine) 
-				{
-					if (textLine.parent)
-						okToRelease = false;
-				}
-				if (okToRelease)	// no textlines were in view, go ahead and release them all, starting at the end and working to the start
+				for each(var textBlock:TextBlock in textBlocks)
 				{
-					for (textLine = textBlock.lastLine; textLine; )
+					for (textLine = textBlock.lastLine; textLine && okToRelease; textLine = textLine.previousLine) 
 					{
-						textBlock.releaseLines(textLine, textLine);
-						textLine.userData = null;
-						TextLineRecycler.addLineForReuse(textLine);
-						if (_textFlow.backgroundManager)
-							_textFlow.backgroundManager.removeLineFromCache(textLine);
-						textLine = textBlock.lastLine;
+						if (textLine.parent)
+							okToRelease = false;
+					}
+					if (okToRelease)	// no textlines were in view, go ahead and release them all, starting at the end and working to the start
+					{
+						for (textLine = textBlock.lastLine; textLine; )
+						{
+							textBlock.releaseLines(textLine, textLine);
+							textLine.userData = null;
+							TextLineRecycler.addLineForReuse(textLine);
+							if (_textFlow.backgroundManager)
+								_textFlow.backgroundManager.removeLineFromCache(textLine);
+							textLine = textBlock.lastLine;
+						}
+						elem.releaseTextBlock(textBlock);
 					}
-					elem.releaseTextBlock();
 				}
 			}
 
@@ -1256,6 +1071,8 @@ package flashx.textLayout.compose
 		 */
 		protected function composeParagraphElementIntoLines():Boolean
 		{
+			// make sure TextBlocks are normalized
+			_curParaElement.createContentElement();
 			var result:Boolean = true;
 			var textLine:TextLine;
 			
@@ -1304,6 +1121,35 @@ package flashx.textLayout.compose
 					break;
 				}
 
+				// do table here?
+				//_curElementStart == _curParaStart
+				//			var startCompose:int = _curElementStart + _curElementOffset - _curParaStart;
+				var c1:Object = _curParaElement.findChildIndexAtPosition(_curElementOffset);
+				var c2:Object = _curParaElement.findChildIndexAtPosition(_curElementStart);
+				var curChild:FlowElement = _curParaElement.getChildAt(_curParaElement.findChildIndexAtPosition(_curElementStart - _curParaStart));
+				if(curChild is TableElement)
+				{
+					if(!composeTableElement(curChild as TableElement, _curElementStart))
+						return false;
+					
+					_curElementOffset = 0;
+					_curElementStart  += _curElement.textLength;
+					_curElement = _curElement.getNextLeaf();
+					_curLineStart++;
+					_previousLine = null;
+
+					// if the next span is the terminator bail out...
+					if(_curElement is SpanElement && SpanElement(_curElement).hasParagraphTerminator && _curElement.textLength == 1)
+					{
+						_curElementOffset = 0;
+						_curElementStart  += _curElement.textLength;
+						_curElement = _curElement.getNextLeaf();
+						return true;
+					}
+					
+					//break;
+					//return true;
+				}
 				// Get the next line
 				textLine = composeNextLine();
 				if (textLine ==  null)
@@ -1507,7 +1353,7 @@ package flashx.textLayout.compose
 			
 			var textLine:TextLine = null;
 			textLine = TextLineRecycler.getLineForReuse();
-			var textBlock:TextBlock = _curParaElement.getTextBlock();
+			var textBlock:TextBlock = _curParaElement.getTextBlockAtPosition(_curElement.getElementRelativeStart(_curParaElement));
 			if (textLine)
 			{
 				CONFIG::debug { assert(_textFlow.backgroundManager == null || _textFlow.backgroundManager.getEntry(textLine) === undefined,"createTextLine - Bad TextLine in recycler cache"); }
@@ -1527,9 +1373,10 @@ package flashx.textLayout.compose
 
 			CONFIG::debug { assert(_curParaStart == _curParaElement.getAbsoluteStart(),"bad _curParaStart"); }
 
-			_curLine.initialize(_curParaElement, targetWidth, lineOffset-_parcelList.insideListItemMargin, textLine.textBlockBeginIndex + _curParaStart, textLine.rawTextLength, textLine);
+			_curLine.initialize(_curParaElement, targetWidth, lineOffset-_parcelList.insideListItemMargin, _curLineStart, textLine.rawTextLength, textLine);
 			CONFIG::debug { assert(_curLine.targetWidth == targetWidth,"Bad targetWidth"); }
 
+			_curLineStart += _curLine.textLength;
 			return textLine;
 		}
 		
@@ -1922,7 +1769,7 @@ package flashx.textLayout.compose
 				bounds = textLine.getAtomBounds(lastAtom != 0 && endOfParagraph ? 1 : 0);						
 				lineWidth -= (_blockProgression == BlockProgression.TB) ? bounds.left : bounds.top;
 			}
-			textLine.flushAtomData();
+			//textLine.flushAtomData(); // Warning: Now does nothing
 			return lineWidth;
 		}
 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/compose/ComposeState.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/ComposeState.as b/textLayout/src/flashx/textLayout/compose/ComposeState.as
index d40dc2b..98d16eb 100644
--- a/textLayout/src/flashx/textLayout/compose/ComposeState.as
+++ b/textLayout/src/flashx/textLayout/compose/ComposeState.as
@@ -27,7 +27,6 @@ package flashx.textLayout.compose
 	import flash.text.engine.TextLineCreationResult;
 	import flash.text.engine.TextLineValidity;
 	
-	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.debug.Debugging;
 	import flashx.textLayout.debug.assert;
@@ -47,11 +46,11 @@ package flashx.textLayout.compose
 	import flashx.textLayout.formats.ListStylePosition;
 	import flashx.textLayout.formats.TextAlign;
 	import flashx.textLayout.formats.VerticalAlign;
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.utils.Twips;
 	
 	use namespace tlf_internal;
 
-	[ExcludeClass]
 	/** Keeps track of internal state during composition. 
 	 * 
 	 * This is the simpler version, used when there are no floats, no wraps, no columns.
@@ -111,7 +110,7 @@ package flashx.textLayout.compose
 			vjBeginLineIndex = 0;
 			vjDisableThisParcel = false;
 			
-			return super.composeTextFlow(textFlow, composeToPosition, controllerEndIndex);
+ 			return super.composeTextFlow(textFlow, composeToPosition, controllerEndIndex);
 		}
 		
 		protected override function initializeForComposer(composer:IFlowComposer,composeToPosition:int,controllerStartIndex:int, controllerEndIndex:int):void
@@ -303,7 +302,15 @@ package flashx.textLayout.compose
          	if (minY != TextLine.MAX_LINE_WIDTH && Math.abs(minY-_parcelTop) >= 1)
            		_parcelTop = minY;
  		}
- 				
+ 			
+		protected override function endTableBlock(block:TextFlowTableBlock):void
+		{
+			super.endTableBlock(block);
+			(_flowComposer as StandardFlowComposer).addLine(block,_curLineIndex);
+			
+			commitLastLineState (_curLine);
+			_curLineIndex++;
+		}
 		/** Called when we are finished composing a line. Handler for derived classes to override default behavior.  */
 		override protected function endLine(textLine:TextLine):void
 		{
@@ -340,14 +347,11 @@ package flashx.textLayout.compose
 			var line:TextFlowLine = _curLineIndex < _flowComposer.numLines ? (_flowComposer as StandardFlowComposer).lines[_curLineIndex] : null;
 			
 			var useExistingLine:Boolean = line && (!line.isDamaged() || line.validity == FlowDamageType.GEOMETRY);
-			if (ContainerController.tlf_internal::usesDiscretionaryHyphens)
-			{
-				// if the line ends with a hyphen, don't use existing line because the player seems to mis-handle
-				// starting the next line.
-				if (useExistingLine && line.textLength > 0 &&
-					line.paragraph.getCharCodeAtPosition(line.absoluteStart + line.textLength - 1) == 0xAD)
-					useExistingLine = false;
-			}
+			// if the line ends with a hyphen, don't use existing line because the player seems to mis-handle
+			// starting the next line.
+			if (useExistingLine && line.textLength > 0 &&
+				line.paragraph.getCharCodeAtPosition(line.absoluteStart + line.textLength - 1) == 0xAD)
+				useExistingLine = false;
 			var numberLine:TextLine;
 			
 			// create numberLine if in a listElement

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/compose/FlowComposerBase.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/FlowComposerBase.as b/textLayout/src/flashx/textLayout/compose/FlowComposerBase.as
index b03592a..b050201 100644
--- a/textLayout/src/flashx/textLayout/compose/FlowComposerBase.as
+++ b/textLayout/src/flashx/textLayout/compose/FlowComposerBase.as
@@ -230,6 +230,10 @@ package flashx.textLayout.compose
 				while (true)
 				{
 					line = _lines[lineIdx];
+					// An empty span following a table can cause this.
+					//if(line == null)
+					//	break;
+					
 					line.setAbsoluteStart(line.absoluteStart + lenToDel + deltaLength);
 					curPos = (startPosition > line.absoluteStart ? startPosition : line.absoluteStart);
 					
@@ -454,7 +458,20 @@ package flashx.textLayout.compose
 				_damageAbsoluteStart = newLine.absoluteStart + newLine.textLength;
 				
 			if (workLine == null)
-				lines.push(newLine);				
+				lines.push(newLine);
+			else if((workLine is TextFlowTableBlock) && workLine != newLine)
+				_lines.splice(workIndex,1,newLine);
+			else if(newLine is TextFlowTableBlock)
+			{
+				if(workLine != newLine)
+				{
+					_lines.splice(workIndex,0,newLine);
+					// set the next line absolute start to be rational for the next line...
+					if(workLine.absoluteStart == newLine.absoluteStart)
+						workLine.setAbsoluteStart(workLine.absoluteStart+1);
+				}
+			}
+								
 			else if (workLine.absoluteStart != newLine.absoluteStart)
 			{
 				if (workLine.absoluteStart + workLine.textLength > newLine.absoluteStart + newLine.textLength)

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/compose/Parcel.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/Parcel.as b/textLayout/src/flashx/textLayout/compose/Parcel.as
index 68769b6..200dae6 100644
--- a/textLayout/src/flashx/textLayout/compose/Parcel.as
+++ b/textLayout/src/flashx/textLayout/compose/Parcel.as
@@ -31,8 +31,8 @@ package flashx.textLayout.compose
 
 	use namespace tlf_internal;
 		
-	[ExcludeClass]
-	/** Helper class for implementations of IParcelList
+	/** 
+	 * Helper class for implementations of IParcelList
 	 * 
 	 * @private
 	 */

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/compose/ParcelList.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/ParcelList.as b/textLayout/src/flashx/textLayout/compose/ParcelList.as
index fc3b516..b4e2a7b 100644
--- a/textLayout/src/flashx/textLayout/compose/ParcelList.as
+++ b/textLayout/src/flashx/textLayout/compose/ParcelList.as
@@ -25,7 +25,7 @@ package flashx.textLayout.compose
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.container.ScrollPolicy;
 	import flashx.textLayout.debug.assert;
-	import flashx.textLayout.elements.TableDataCellElement;
+	import flashx.textLayout.elements.TableCellElement;
 	import flashx.textLayout.formats.BlockProgression;
 	import flashx.textLayout.formats.ITextLayoutFormat;
 	import flashx.textLayout.formats.LineBreak;
@@ -35,7 +35,6 @@ package flashx.textLayout.compose
 	
 	use namespace tlf_internal;
 			
-	[ExcludeClass]
 	/** @private
 	 * Used for composing text containers, keeps track of the areas that text in the 
 	 * flow is composed into.
@@ -208,7 +207,7 @@ package flashx.textLayout.compose
 			return _parcelArray.pop();
 		}
 		
-		public function addTableCell2ColumnState(controller:ContainerController, cell:TableDataCellElement):void
+		public function addTableCell2ColumnState(controller:ContainerController, cell:TableCellElement):void
 		{
 			var columnState:ColumnState = controller.columnState;
 			if (columnState)

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/compose/StandardFlowComposer.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/StandardFlowComposer.as b/textLayout/src/flashx/textLayout/compose/StandardFlowComposer.as
index cb0b38e..25f06a4 100644
--- a/textLayout/src/flashx/textLayout/compose/StandardFlowComposer.as
+++ b/textLayout/src/flashx/textLayout/compose/StandardFlowComposer.as
@@ -67,7 +67,7 @@ package flashx.textLayout.compose
 	public class StandardFlowComposer extends FlowComposerBase implements IFlowComposer
 	{
 		/** @private */
-		tlf_internal var _rootElement:ContainerFormattedElement;
+		protected var _rootElement:ContainerFormattedElement;
 		private var _controllerList:Array;
 		private var _composing:Boolean;
 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/TextFlowLine.as b/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
index 11b8511..0ff278f 100644
--- a/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
+++ b/textLayout/src/flashx/textLayout/compose/TextFlowLine.as
@@ -52,6 +52,8 @@ package flashx.textLayout.compose
 	import flashx.textLayout.elements.SpanElement;
 	import flashx.textLayout.elements.SubParagraphGroupElementBase;
 	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.TableElement;
+	import flashx.textLayout.elements.TableLeafElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.factory.StringTextLineFactory;
 	import flashx.textLayout.formats.BackgroundColor;
@@ -92,7 +94,7 @@ package flashx.textLayout.compose
 	 * @langversion 3.0
 	 */
 	
-	public final class TextFlowLine implements IVerticalJustificationLine 
+	public class TextFlowLine implements IVerticalJustificationLine 
 	{
 		
 		/** @private - the selection block cache */
@@ -126,10 +128,10 @@ package flashx.textLayout.compose
 		
 		// added to support TextFlowLine when TextLine not available
 
-		private var _ascent:Number;
-		private var _descent:Number;
+		protected var _ascent:Number;
+		protected var _descent:Number;
 		private var _targetWidth:Number;
-		private var _lineOffset:Number;
+		protected var _lineOffset:Number;
 		private var _lineExtent:Number;	// content bounds logical width for the line
 		private var _accumulatedLineExtent:Number;
 		private var _accumulatedMinimumStart:Number;
@@ -356,8 +358,14 @@ package flashx.textLayout.compose
 		{
 			if (_para)
 			{
-				var lineStart:int = _absoluteStart - _para.getAbsoluteStart();
+				var lineStart:int;
 				
+				// Harbs 8-31-14 added handling of multiple textBlocks might need more work to handle end?
+				var textLine:TextLine = peekTextLine();
+				if(textLine)
+					lineStart = _absoluteStart - _para.getTextBlockAbsoluteStart(textLine.textBlock);
+				else
+					lineStart = _absoluteStart - _para.getAbsoluteStart();
 				// Initialize settings for location
 				if (lineStart == 0)		// we're at the start of the paragraph
 					return _textLength == _para.textLength ? TextFlowLineLocation.ONLY : TextFlowLineLocation.FIRST;
@@ -797,15 +805,16 @@ package flashx.textLayout.compose
 				return null;
 						
 			// Look it up in the textBlock
-			var textBlock:TextBlock = paragraph.peekTextBlock();
-			if (textBlock)
+			var textBlocks:Vector.<TextBlock> = paragraph.getTextBlocks();
+			for each(var textBlock:TextBlock in textBlocks)
 			{
 				for (textLine = textBlock.firstLine; textLine; textLine = textLine.nextLine)
 				{
 					if (textLine.userData == this) // found it
 						return textLine;
-					}
 				}
+				
+			}
 			return null;
 		}
 		
@@ -850,13 +859,14 @@ package flashx.textLayout.compose
 		}
 
 		private function getTextLineInternal():TextLine
-		{			
+		{		
+			// 8-31-14 Do we need to change this to handle multiple textBlocks?
 			// Look it up in the textBlock
 			var paraAbsStart:int = paragraph.getAbsoluteStart();
 			
 			// If we haven't found it yet, we need to regenerate it.
 			// Regenerate the whole paragraph at once, up to the current position. 
-			var textBlock:TextBlock = paragraph.getTextBlock();
+			var textBlock:TextBlock = paragraph.getTextBlockAtPosition(absoluteStart - paraAbsStart);
 			var currentLine:TextLine = textBlock.firstLine;
 			var flowComposer:IFlowComposer = paragraph.getTextFlow().flowComposer;
 			var lineIndex:int = flowComposer.findLineIndexAtPosition(paraAbsStart);
@@ -871,6 +881,11 @@ package flashx.textLayout.compose
 					textLine = currentLine;
 					currentLine = currentLine.nextLine;
 				}
+				else if(line is TextFlowTableBlock)
+				{
+					textLine = null;
+					currentLine = null;
+				}
 				else
 				{
 					textLine = line.recreateTextLine(textBlock, previousLine);
@@ -1205,6 +1220,8 @@ package flashx.textLayout.compose
 					break;
 				elem = elem.getNextLeaf(_para);
 				CONFIG::debug { assert(elem != null,"bad nextLeaf"); }
+				if(elem == null)
+					break;
 			}
 			return totalLeading;
 		}
@@ -1367,6 +1384,7 @@ package flashx.textLayout.compose
 			if (isDamaged())
 				return null;
 			
+			// 8-31-14 Do we need to adjust this for paras with multiple textBlocks? 
 			//get the absolute start of the paragraph.  Calculation is expensive, so just do this once.
 			var paraAbsStart:int = _para.getAbsoluteStart();
 			
@@ -1416,8 +1434,9 @@ package flashx.textLayout.compose
 			
 			
 			//allow the atoms to be garbage collected.
-			if (textLine)
-				textLine.flushAtomData();
+			//if (textLine) {
+				//textLine.flushAtomData(); // Warning: Now does nothing
+			//}
 			
 			return selectionCache;
 		}
@@ -1429,7 +1448,8 @@ package flashx.textLayout.compose
 			//the direction of the text
 			var direction:String = _para.computedFormat.direction;
 			//get the absolute start of the paragraph.  Calculation is expensive, so just do this once.
-			var paraAbsStart:int = _para.getAbsoluteStart();
+			//var paraAbsStart:int = _para.getAbsoluteStart();
+			var paraAbsStart:int = _para.getTextBlockAbsoluteStart(textLine.textBlock);
 			//the current index.  used to iterate to the next element
 			var curIdx:int = begIdx;
 			//the current FlowLeafElement as determined by curIdx
@@ -1472,6 +1492,18 @@ package flashx.textLayout.compose
 				}
 				//the number of potential glyphs to hilite.  Could larger than needs be if we are only selecting part of it.
 				var numCharsSelecting:int = curElem.textLength + curElem.getElementRelativeStart(_para) - curIdx;
+				// special handling for TableLeafElements (do nothing)
+				if(curElem is TableLeafElement)
+				{
+					//if(floatRectArray == null)
+					//	floatRectArray = new Array();
+
+					//var block:TextFlowTableBlock = TableElement(TableLeafElement(curElem).parent).getFirstBlock();
+					//var blockRect:Rectangle = new Rectangle(floatInfo.x - textLine.x, floatInfo.y - textLine.y, ilg.elementWidth, ilg.elementHeight);
+					//floatRectArray.push(new Rectangle(0,0,block.width,block.height));
+					++curIdx;
+					continue;
+				}
 				//the index of the last glyph to hilite.  If a partial selection, use endIdx
 				var endPos:int = (numCharsSelecting + curIdx) > endIdx ? endIdx : (numCharsSelecting + curIdx);
 				
@@ -1753,7 +1785,7 @@ package flashx.textLayout.compose
 		
 		/** @private 
 		 * 
-		 * 
+		 * ? Get a list of rects of the characters in the given textline? Used to show selection? JF 
 		 */
 		private function makeSelectionBlocks(textLine:TextLine, begIdx:int, endIdx:int, paraAbsStart:int, blockProgression:String, direction:String, heightAndAdj:Array):Array
 		{
@@ -1918,7 +1950,7 @@ package flashx.textLayout.compose
 		
 		/** @private 
 		 * 
-		 * 
+		 * ? Get the bounds of the supplied range of characters in the given textline? Used to show selection? JF 
 		 */
 		private function makeBlock(textLine:TextLine, begTextIndex:int, begAtomIndex:int, endAtomIndex:int, startMetrics:Rectangle, blockProgression:String, direction:String, heightAndAdj:Array):Rectangle
 		{
@@ -2157,7 +2189,7 @@ package flashx.textLayout.compose
 			if (!textLine || !textLine.parent)
 				return;
 			
-			var paraStart:int = _para.getAbsoluteStart();
+			var paraStart:int = _para.getTextBlockAbsoluteStart(textLine.textBlock);
 			begIdx -= paraStart;
 			endIdx -= paraStart;
 			
@@ -2198,7 +2230,9 @@ package flashx.textLayout.compose
 			if (!textLine || !textLine.parent)
 				return null;			
 			// adjust to this paragraph's TextBlock
-			idx -= _para.getAbsoluteStart();
+			// I'm assuming this needs to be relative to the TextBlock and not the paragraph -- Harbs
+				idx -= _para.getTextBlockAbsoluteStart(textLine.textBlock);
+			//idx -= _para.getAbsoluteStart();
 			
 			textLine = getTextLine(true);
 			
@@ -2247,7 +2281,7 @@ package flashx.textLayout.compose
 			}
 			
 			var heightAndAdj:Array = getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
-			var blockRectArray:Array = makeSelectionBlocks(textLine, idx, endIdx, _para.getAbsoluteStart(), blockProgression, direction, heightAndAdj);
+			var blockRectArray:Array = makeSelectionBlocks(textLine, idx, endIdx, _para.getTextBlockAbsoluteStart(textLine.textBlock), blockProgression, direction, heightAndAdj);
 			CONFIG::debug{ assert(blockRectArray.length == 1, "A point selection should return a single selection rectangle!"); }
 			var rect:Rectangle = blockRectArray[0];
 			
@@ -2291,7 +2325,7 @@ package flashx.textLayout.compose
 			}
 			
 			//allow the atoms to be garbage collected.
-			textLine.flushAtomData();
+			//textLine.flushAtomData(); // Warning: Now does nothing
 			
 			return rect;
 		}
@@ -2320,7 +2354,12 @@ package flashx.textLayout.compose
 			}
 			else
 			{
-				var paraStart:int = _para.getAbsoluteStart();
+				var paraStart:int;
+				//8-31-14 Assuming this should be from the textBlock. Keeping getAbsoluteStart() in case there's no textLine -- not sure if that's needed
+				if(textLine)
+					paraStart = _para.getTextBlockAbsoluteStart(textLine.textBlock);
+				else
+					paraStart = _para.getAbsoluteStart();
 				var selCache:SelectionCache = this.getSelectionShapesCacheEntry(begIdx-paraStart,endIdx-paraStart,prevLine,nextLine,blockProgression);
 				if (selCache)
 				{
@@ -2490,6 +2529,8 @@ package flashx.textLayout.compose
 		/** @private */
 		static tlf_internal function findNumberLine(textLine:TextLine):TextLine
 		{
+			if(textLine == null)
+				return null;
 			// not always going to be a numberLine - listStyleType may be "none"
 			// have to hunt for it because inlinegraphics get pushed at the beginning
 			// risk here is that clients decorate TextLines with other TextLines.
@@ -2715,7 +2756,7 @@ class NumberLineFactory extends StringTextLineFactory
 				}
 			}
 		}
-		numberLine.flushAtomData();
+		// numberLine.flushAtomData(); // Warning: Now does nothing
 		//trace("textWidth",numberLine.textWidth,maxVal-minVal);
 		return maxVal > minVal ? maxVal-minVal : 0;
 	}

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/container/ColumnState.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/container/ColumnState.as b/textLayout/src/flashx/textLayout/container/ColumnState.as
index 40a54e1..e84dd64 100644
--- a/textLayout/src/flashx/textLayout/container/ColumnState.as
+++ b/textLayout/src/flashx/textLayout/container/ColumnState.as
@@ -21,7 +21,7 @@ package flashx.textLayout.container
 	import flash.geom.Rectangle;
 	
 	import flashx.textLayout.debug.assert;
-	import flashx.textLayout.elements.TableDataCellElement;
+	import flashx.textLayout.elements.TableCellElement;
 	import flashx.textLayout.formats.BlockProgression;
 	import flashx.textLayout.formats.Direction;
 	import flashx.textLayout.formats.FormatValue;
@@ -181,12 +181,12 @@ package flashx.textLayout.container
 			return _columnCount == 1 ? _singleColumn : _columnArray[index];
 		}
 		
-		public function getCellAt(index:int):TableDataCellElement
+		public function getCellAt(index:int):TableCellElement
 		{
 			return _tableCellArray[index];
 		}
 		
-		public function pushTableCell(cell:TableDataCellElement):void
+		public function pushTableCell(cell:TableCellElement):void
 		{
 			if ( _tableCellArray == null )
 				_tableCellArray = new Array();


[15/25] git commit: [flex-tlf] [refs/heads/develop] - Fixed inserting columns so cells are inserted in the correct location

Posted by pi...@apache.org.
Fixed inserting columns so cells are inserted in the correct location


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/99d8b6c7
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/99d8b6c7
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/99d8b6c7

Branch: refs/heads/develop
Commit: 99d8b6c7a5ff8caa94e78119d490448fb06acac9
Parents: f6348cd
Author: Harbs <ha...@in-tools.com>
Authored: Thu Nov 6 01:09:35 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Thu Nov 6 01:09:35 2014 +0200

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/elements/TableElement.as | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/99d8b6c7/textLayout/src/flashx/textLayout/elements/TableElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableElement.as b/textLayout/src/flashx/textLayout/elements/TableElement.as
index 2718c13..c7f2fbc 100644
--- a/textLayout/src/flashx/textLayout/elements/TableElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableElement.as
@@ -481,6 +481,7 @@ package flashx.textLayout.elements
 				if(rowIdx < numRows){
 					addChildAt(cellIdx,cell);
 				}
+				rowIdx++;
 			}
 
 


[20/25] git commit: [flex-tlf] [refs/heads/develop] - Ignore table space-before mid-paragraph

Posted by pi...@apache.org.
Ignore table space-before mid-paragraph


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/41abfa4f
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/41abfa4f
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/41abfa4f

Branch: refs/heads/develop
Commit: 41abfa4f45b9581245f9002e5d832b1ef9ab5fe8
Parents: 9f0382b
Author: Harbs <ha...@in-tools.com>
Authored: Wed Nov 19 21:43:31 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Wed Nov 19 21:43:31 2014 +0200

----------------------------------------------------------------------
 .../flashx/textLayout/compose/BaseCompose.as    | 33 +++++++++++---------
 1 file changed, 18 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/41abfa4f/textLayout/src/flashx/textLayout/compose/BaseCompose.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/BaseCompose.as b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
index 6107c2f..d1b675f 100644
--- a/textLayout/src/flashx/textLayout/compose/BaseCompose.as
+++ b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
@@ -515,7 +515,23 @@ package flashx.textLayout.compose
 		{
 			//TODO: remove any old existing cells in the _parcelList.currentParcel.controller from the position of the table and on.
 			// need to figure out the accounting needed for that.
+
+			// Space before does not apply to the first line, unless LeadingModel.BOX is used
+			// Space carried never applies to the first line
+			if(_curLine && _curLine.paragraph == _curParaElement)
+				var spaceBefore:Number = 0;
+			else
+				spaceBefore = isNaN(_curParaElement.computedFormat.paragraphSpaceBefore) ? 0 : _curParaElement.computedFormat.paragraphSpaceBefore;
+			
+			spaceBefore  = _atColumnStart ? 0 : spaceBefore;
+			var spaceCarried:Number = _atColumnStart ? 0 : _paragraphSpaceCarried;
+			if (spaceBefore != 0 || spaceCarried != 0)
+				_parcelList.addTotalDepth(Math.max(spaceBefore, spaceCarried));
 			
+			_paragraphSpaceCarried = 0;
+			if (_verticalSpaceCarried != 0)
+				_verticalSpaceCarried = 0;
+
 			// get a slug...
 			_parcelList.getLineSlug(_lineSlug, 0, 1, _textIndent, _curParaFormat.direction == Direction.LTR);
 			
@@ -1075,8 +1091,6 @@ package flashx.textLayout.compose
 			var result:Boolean = true;
 			var textLine:TextLine;
 			
-			var spaceBefore:Number;
-			var spaceCarried:Number;
 			
 			var leftMargin:Number;
 			var rightMargin:Number;
@@ -1129,17 +1143,6 @@ package flashx.textLayout.compose
 				var curChild:FlowElement = _curParaElement.getChildAt(_curParaElement.findChildIndexAtPosition(_curElementStart - _curParaStart));
 				if(curChild is TableElement)
 				{
-					// Space before does not apply to the first line, unless LeadingModel.BOX is used
-					// Space carried never applies to the first line
-					spaceBefore = isNaN(_curParaElement.computedFormat.paragraphSpaceBefore) ? 0 : _curParaElement.computedFormat.paragraphSpaceBefore;
-					spaceBefore  = _atColumnStart ? 0 : spaceBefore;
-					spaceCarried = _atColumnStart ? 0 : _paragraphSpaceCarried;
-					if (spaceBefore != 0 || spaceCarried != 0)
-						_parcelList.addTotalDepth(Math.max(spaceBefore, spaceCarried));
-					
-					_paragraphSpaceCarried = 0;
-					if (_verticalSpaceCarried != 0)
-						_verticalSpaceCarried = 0;
 					
 					if(!composeTableElement(curChild as TableElement, _curElementStart))
 						return false;
@@ -1232,8 +1235,8 @@ package flashx.textLayout.compose
 				
 				// Space before does not apply to the first line, unless LeadingModel.BOX is used
 				// Space carried never applies to the first line
-				spaceBefore  = _atColumnStart && (_curParaFormat.leadingModel != LeadingModel.BOX) ? 0 : _curLine.spaceBefore;
-				spaceCarried = _atColumnStart ? 0 : _paragraphSpaceCarried;
+				var spaceBefore:Number  = _atColumnStart && (_curParaFormat.leadingModel != LeadingModel.BOX) ? 0 : _curLine.spaceBefore;
+				var spaceCarried:Number = _atColumnStart ? 0 : _paragraphSpaceCarried;
 				if (spaceBefore != 0 || spaceCarried != 0)
 					_parcelList.addTotalDepth(Math.max(spaceBefore, spaceCarried));
 				


[24/25] git commit: [flex-tlf] [refs/heads/develop] - Merge branch 'develop' into tables

Posted by pi...@apache.org.
Merge branch 'develop' into tables

* develop:
  the original change broke a few tests.  I think this one is better


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/5357c43c
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/5357c43c
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/5357c43c

Branch: refs/heads/develop
Commit: 5357c43c29f00b6e131dce7ec9ed9288643ecbf6
Parents: 863d00f 222d745
Author: Harbs <ha...@in-tools.com>
Authored: Thu Nov 27 10:28:06 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Thu Nov 27 10:28:06 2014 +0200

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/container/TextContainerManager.as | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------



[12/25] git commit: [flex-tlf] [refs/heads/develop] - Forced redrawing of cells when the parent ContainerController.updateCompositionShapes() is called. This fixes drawing of cells when the table structure of an existing table changes. It might be more e

Posted by pi...@apache.org.
Forced redrawing of cells when the parent ContainerController.updateCompositionShapes() is called.
This fixes drawing of cells when the table structure of an existing table changes.
It might be more efficient if there's a check to see if the table structure changes rather than blindly redrawing the table block every time.


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/b408e2fb
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/b408e2fb
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/b408e2fb

Branch: refs/heads/develop
Commit: b408e2fb585faf60e446f4b76563e7409a541712
Parents: d159e00
Author: Harbs <ha...@in-tools.com>
Authored: Tue Oct 28 10:56:31 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Tue Oct 28 10:56:31 2014 +0200

----------------------------------------------------------------------
 .../src/flashx/textLayout/container/ContainerController.as      | 5 +++++
 textLayout/src/flashx/textLayout/elements/TableElement.as       | 1 +
 2 files changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/b408e2fb/textLayout/src/flashx/textLayout/container/ContainerController.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/container/ContainerController.as b/textLayout/src/flashx/textLayout/container/ContainerController.as
index eef34fb..08f4a68 100644
--- a/textLayout/src/flashx/textLayout/container/ContainerController.as
+++ b/textLayout/src/flashx/textLayout/container/ContainerController.as
@@ -3203,6 +3203,11 @@ package flashx.textLayout.container
 					childIdx++;
 					newIdx++;
 					oldIdx++;
+					if(newChild is TableBlockContainer)
+					{
+						// update the contents in case cells were added or removed. (There might be a more efficient way to do this, but this works.)
+						(newChild as TableBlockContainer).userData.updateCompositionShapes();
+					}
 					continue;
 				}
 				var newChildIdx:int = _shapeChildren.indexOf(newChild);

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/b408e2fb/textLayout/src/flashx/textLayout/elements/TableElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableElement.as b/textLayout/src/flashx/textLayout/elements/TableElement.as
index a9472c1..2718c13 100644
--- a/textLayout/src/flashx/textLayout/elements/TableElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableElement.as
@@ -534,6 +534,7 @@ package flashx.textLayout.elements
 				}
 				if(colIdx < numColumns){
 					addChildAt(cellIdx++,cell);
+					cell.damage();
 				}
 			}
 			return true;


[18/25] git commit: [flex-tlf] [refs/heads/develop] - Add failing test to MinimalTestsSuite

Posted by pi...@apache.org.
Add failing test to MinimalTestsSuite


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/723311b5
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/723311b5
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/723311b5

Branch: refs/heads/develop
Commit: 723311b5812505de281124953c6b2aee7e1d0286
Parents: 135709a
Author: piotrz <pi...@gmail.com>
Authored: Tue Nov 18 23:06:46 2014 +0100
Committer: piotrz <pi...@gmail.com>
Committed: Tue Nov 18 23:06:46 2014 +0100

----------------------------------------------------------------------
 automation_tests/src/MinimalTestsSuite.as | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/723311b5/automation_tests/src/MinimalTestsSuite.as
----------------------------------------------------------------------
diff --git a/automation_tests/src/MinimalTestsSuite.as b/automation_tests/src/MinimalTestsSuite.as
index 7f4b558..5f413ce 100644
--- a/automation_tests/src/MinimalTestsSuite.as
+++ b/automation_tests/src/MinimalTestsSuite.as
@@ -19,13 +19,13 @@
 package
 {
 
-    import UnitTest.Tests.ContainerTypeTest;
+    import UnitTest.Tests.FloatTest;
 
     [Suite]
     [RunWith("org.flexunit.runners.Suite")]
     public dynamic class MinimalTestsSuite
     {
-        public var containerTypeTest:ContainerTypeTest;
+        public var floatTest:FloatTest;
     }
 
 }


[09/25] git commit: [flex-tlf] [refs/heads/develop] - Fixed issue where a null table reference could be present on mouse down.

Posted by pi...@apache.org.
Fixed issue where a null table reference could be present on mouse down.


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/e5a3382c
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/e5a3382c
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/e5a3382c

Branch: refs/heads/develop
Commit: e5a3382c4acbd04f1d03a1802089c2da96b7e43e
Parents: 537c352
Author: Harbs <ha...@in-tools.com>
Authored: Wed Oct 22 11:49:04 2014 +0300
Committer: Harbs <ha...@in-tools.com>
Committed: Wed Oct 22 11:49:04 2014 +0300

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/edit/SelectionManager.as | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/e5a3382c/textLayout/src/flashx/textLayout/edit/SelectionManager.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/SelectionManager.as b/textLayout/src/flashx/textLayout/edit/SelectionManager.as
index 6de1c2b..42e1579 100644
--- a/textLayout/src/flashx/textLayout/edit/SelectionManager.as
+++ b/textLayout/src/flashx/textLayout/edit/SelectionManager.as
@@ -1961,7 +1961,7 @@ package flashx.textLayout.edit
 			if(cell || coords)
 			{
 				if(coords)
-					cell = currentTable.findCell(coords);
+					cell = coords.table.findCell(coords);
 				
 				superManager = cell.getTextFlow().interactionManager;
 				if(event.shiftKey && cell.getTable() == superManager.currentTable)


[16/25] git commit: [flex-tlf] [refs/heads/develop] - Some code cleanup

Posted by pi...@apache.org.
Some code cleanup


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/8db7a4a2
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/8db7a4a2
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/8db7a4a2

Branch: refs/heads/develop
Commit: 8db7a4a2e707364c57c26bbb8d4c4286be634aa3
Parents: 99d8b6c
Author: Harbs <ha...@in-tools.com>
Authored: Mon Nov 17 14:00:13 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Mon Nov 17 14:00:13 2014 +0200

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/compose/BaseCompose.as | 12 +++---------
 .../src/flashx/textLayout/compose/ComposeState.as       |  8 ++++----
 textLayout/src/flashx/textLayout/compose/Parcel.as      |  2 --
 3 files changed, 7 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/8db7a4a2/textLayout/src/flashx/textLayout/compose/BaseCompose.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/BaseCompose.as b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
index 7a0557d..b051036 100644
--- a/textLayout/src/flashx/textLayout/compose/BaseCompose.as
+++ b/textLayout/src/flashx/textLayout/compose/BaseCompose.as
@@ -775,9 +775,6 @@ package flashx.textLayout.compose
 				}
 				
 				var nextParcel:Parcel = parcelList.getParcelAt(parcelList.currentParcelIndex + 1);
-				if ( parcelList.currentParcel.isTableParcel
-					&& ((nextParcel && nextParcel.isTableParcel) || parcelList.currentParcelIndex == parcelList.numParcels()-1))
-					_correctTextLength = true;
 		
 				advanceToNextParcel();
 				_correctTextLength = false;
@@ -1124,8 +1121,6 @@ package flashx.textLayout.compose
 				// do table here?
 				//_curElementStart == _curParaStart
 				//			var startCompose:int = _curElementStart + _curElementOffset - _curParaStart;
-				var c1:Object = _curParaElement.findChildIndexAtPosition(_curElementOffset);
-				var c2:Object = _curParaElement.findChildIndexAtPosition(_curElementStart);
 				var curChild:FlowElement = _curParaElement.getChildAt(_curParaElement.findChildIndexAtPosition(_curElementStart - _curParaStart));
 				if(curChild is TableElement)
 				{
@@ -2041,7 +2036,7 @@ package flashx.textLayout.compose
 				for (;;)
 				{
 					advanceToNextParcel();
-					if (!_curLine || _parcelList.atEnd() || _parcelList.currentParcel.isTableParcel)
+					if (!_curLine || _parcelList.atEnd())
 						return false;
 					if (_parcelList.getLineSlug(_lineSlug,0, 1, _textIndent, _curParaFormat.direction == Direction.LTR))
 					{
@@ -2704,15 +2699,14 @@ package flashx.textLayout.compose
 				{
 					if (oldController == null && _startController)
 						clearControllers(_startController, newController);
-					else if ( ! _curParcel.isTableParcel )
+					else
 						clearControllers(oldController, newController);
 				}
 				if (newController)
 				{
 					CONFIG::debug 
 					{ 
-						if ( ! newParcel.isTableParcel )
-							assert(!oldController || newController.absoluteStart == oldController.absoluteStart + oldController.textLength, "newController not yet set up");
+						assert(!oldController || newController.absoluteStart == oldController.absoluteStart + oldController.textLength, "newController not yet set up");
 					}
 					if (oldController)		// advance the start pos to the next controller if newController isn't the first controller
 						_startComposePosition = newController.absoluteStart;

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/8db7a4a2/textLayout/src/flashx/textLayout/compose/ComposeState.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/ComposeState.as b/textLayout/src/flashx/textLayout/compose/ComposeState.as
index 98d16eb..e170bae 100644
--- a/textLayout/src/flashx/textLayout/compose/ComposeState.as
+++ b/textLayout/src/flashx/textLayout/compose/ComposeState.as
@@ -335,7 +335,8 @@ package flashx.textLayout.compose
 		protected override function composeNextLine():TextLine
 		{			
 			// mjzhang: this code adds for recompose a table row, we need to recorrect _curLineIndex parameter based on _curElementStart and _curElementOffset.
-			_curLineIndex = _flowComposer.findLineIndexAtPosition(_curElementStart + _curElementOffset);
+			//Harbs: I don't see a need for this now that I changed the table logic.
+			//_curLineIndex = _flowComposer.findLineIndexAtPosition(_curElementStart + _curElementOffset);
 			
 			CONFIG::debug { assert(_curLineIndex == _flowComposer.findLineIndexAtPosition(_curElementStart + _curElementOffset),"bad _curLineIndex"); }
 
@@ -345,7 +346,6 @@ package flashx.textLayout.compose
 			// width in fitLineToParcel to make sure it fits at the (possibly changed) line height.
 			var startCompose:int = _curElementStart + _curElementOffset - _curParaStart;
 			var line:TextFlowLine = _curLineIndex < _flowComposer.numLines ? (_flowComposer as StandardFlowComposer).lines[_curLineIndex] : null;
-			
 			var useExistingLine:Boolean = line && (!line.isDamaged() || line.validity == FlowDamageType.GEOMETRY);
 			// if the line ends with a hyphen, don't use existing line because the player seems to mis-handle
 			// starting the next line.
@@ -422,7 +422,7 @@ package flashx.textLayout.compose
 				if (fitLineToParcel(textLine, !useExistingLine, numberLine))
 					break;	// we have a good line
 				_curLine = null;	// keep looking
-				if (_parcelList.atEnd() || _parcelList.currentParcel.isTableParcel)
+				if (_parcelList.atEnd())
 				{
 					popInsideListItemMargins(numberLine);
 					return null;
@@ -451,7 +451,7 @@ package flashx.textLayout.compose
 			var textLine:TextLine = super.createTextLine(targetWidth, allowEmergencyBreaks);
 			
 			if (textLine)
-	 			textLine.doubleClickEnabled = true;		// allow line to be the target oif a double click event
+	 			textLine.doubleClickEnabled = true;		// allow line to be the target of a double click event
 			else
 				_curLine = null;
  			

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/8db7a4a2/textLayout/src/flashx/textLayout/compose/Parcel.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/Parcel.as b/textLayout/src/flashx/textLayout/compose/Parcel.as
index 200dae6..9079d97 100644
--- a/textLayout/src/flashx/textLayout/compose/Parcel.as
+++ b/textLayout/src/flashx/textLayout/compose/Parcel.as
@@ -43,7 +43,6 @@ package flashx.textLayout.compose
 		public var width:Number;
 		public var height:Number;
 		public var logicalWidth:Number;
-		public var isTableParcel:Boolean;
 
 		private var _controller:ContainerController;
 		private var _columnIndex:int;
@@ -73,7 +72,6 @@ package flashx.textLayout.compose
 			this.height = height;
 			this.logicalWidth = verticalText ? height : width;
 			this._verticalText = verticalText; 
-			this.isTableParcel = false;
 			
 			_controller   = controller;
 			_columnIndex  =  columnIndex;


[11/25] git commit: [flex-tlf] [refs/heads/develop] - Cells were incorrectly setting padding every time they were composed which was causing cell lines to become incorrectly invalid and put cells into an unstable state. I think ContainerController should

Posted by pi...@apache.org.
Cells were incorrectly setting padding every time they were composed which was causing cell lines to become incorrectly invalid and put cells into an unstable state.
I think ContainerController should be adding the array including tables to _shapeChildren and not the old _linesInView which only contains pure lines.


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/d159e00c
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/d159e00c
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/d159e00c

Branch: refs/heads/develop
Commit: d159e00c74a698276221fe3c4e1d6e4a5fc14cb5
Parents: b901150
Author: Harbs <ha...@in-tools.com>
Authored: Sun Oct 26 23:08:40 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Sun Oct 26 23:08:40 2014 +0200

----------------------------------------------------------------------
 .../textLayout/container/ContainerController.as |  3 +-
 .../textLayout/elements/TableCellElement.as     | 47 +++++++++++++++-----
 2 files changed, 39 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/d159e00c/textLayout/src/flashx/textLayout/container/ContainerController.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/container/ContainerController.as b/textLayout/src/flashx/textLayout/container/ContainerController.as
index 2e375f4..eef34fb 100644
--- a/textLayout/src/flashx/textLayout/container/ContainerController.as
+++ b/textLayout/src/flashx/textLayout/container/ContainerController.as
@@ -3248,7 +3248,8 @@ package flashx.textLayout.container
 			{
 				// We only updated some of the lines. Remove the old versions off the end, and add in the new ones from _linesInView
 				_shapeChildren.length = shapeChildrenStartIdx;		// truncate
-				_shapeChildren = _shapeChildren.concat(_linesInView);	// append _linesInView to end of _shapeChildren
+				//_shapeChildren = _shapeChildren.concat(_linesInView);	// append _linesInView to end of _shapeChildren
+				_shapeChildren = _shapeChildren.concat(newShapeChildren);	// append _linesInView to end of _shapeChildren
 				_linesInView.length = 0;	// truncate
 			}
 			else

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/d159e00c/textLayout/src/flashx/textLayout/elements/TableCellElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableCellElement.as b/textLayout/src/flashx/textLayout/elements/TableCellElement.as
index 7f04939..197d4c9 100644
--- a/textLayout/src/flashx/textLayout/elements/TableCellElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableCellElement.as
@@ -27,6 +27,7 @@ package flashx.textLayout.elements
 	import flash.utils.getDefinitionByName;
 	import flash.utils.getQualifiedClassName;
 	
+	import flashx.textLayout.compose.FlowDamageType;
 	import flashx.textLayout.compose.TextFlowLine;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.edit.EditManager;
@@ -90,26 +91,52 @@ package flashx.textLayout.elements
 		}
 
 		public function isDamaged():Boolean {
-			return _damaged;
+			return _damaged || (_textFlow && _textFlow.flowComposer.isDamaged(_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:TableElement = getTable();
-			width = 0;
+			
+			_damaged = false;
+			
+			var compWidth:Number = 0;
 			for(var i:int=0;i<columnSpan;i++)
 			{
 				if (table && table.getColumnAt(colIndex+i)) {
-					width += table.getColumnAt(colIndex+i).columnWidth;
+					compWidth += table.getColumnAt(colIndex+i).columnWidth;
 				}
 				
 			}
-			
-			_damaged = false;
-			_controller.paddingTop = getEffectivePaddingTop();
-			_controller.paddingBottom = getEffectivePaddingBottom();
-			_controller.paddingLeft = getEffectivePaddingLeft();
-			_controller.paddingRight = getEffectivePaddingRight();
-			
+			width = compWidth;
+
 			if (_textFlow && _textFlow.flowComposer) {
 				return _textFlow.flowComposer.compose();
 			}


[06/25] git commit: [flex-tlf] [refs/heads/develop] - Added missing files

Posted by pi...@apache.org.
Added missing files


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/a0a0749e
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/a0a0749e
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/a0a0749e

Branch: refs/heads/develop
Commit: a0a0749eab37bd5284b1cf56fed780ecd5ed1bfb
Parents: 33df98a
Author: Harbs <ha...@in-tools.com>
Authored: Mon Oct 6 08:11:15 2014 +0300
Committer: Harbs <ha...@in-tools.com>
Committed: Mon Oct 6 08:11:15 2014 +0300

----------------------------------------------------------------------
 .../textLayout/compose/TextFlowTableBlock.as    | 215 +++++++++
 .../src/flashx/textLayout/edit/SelectionType.as |  30 ++
 .../textLayout/elements/CellCoordinates.as      |  89 ++++
 .../src/flashx/textLayout/elements/CellRange.as | 147 +++++++
 .../textLayout/elements/TableBlockContainer.as  |  31 ++
 .../textLayout/elements/TableCellElement.as     | 434 +++++++++++++++++++
 .../textLayout/elements/TableLeafElement.as     | 120 +++++
 .../textLayout/formats/ITextLayoutFormat.as     |  88 +++-
 .../textLayout/formats/TextLayoutFormat.as      | 174 +++++++-
 .../textLayout/formats/TextLayoutFormatInc.as   | 141 ++++++
 10 files changed, 1467 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as b/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as
new file mode 100644
index 0000000..b5e3329
--- /dev/null
+++ b/textLayout/src/flashx/textLayout/compose/TextFlowTableBlock.as
@@ -0,0 +1,215 @@
+package flashx.textLayout.compose
+{
+	
+	import flash.text.engine.TextLine;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.CellContainer;
+	import flashx.textLayout.elements.CellCoordinates;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TableBlockContainer;
+	import flashx.textLayout.elements.TableCellElement;
+	import flashx.textLayout.elements.TableElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	/**
+	 * 
+	 **/
+	public class TextFlowTableBlock extends TextFlowLine
+	{
+		
+		private var _textHeight:Number;
+		
+		/** Constructor - creates a new TextFlowTableBlock instance. 
+		 *  <p><strong>Note</strong>: No client should call this. It's exposed for writing your own composer.</p>
+		 *
+		 * @param index The index in the Table text flow.
+		 * */
+		public function TextFlowTableBlock(index:uint)
+		{
+			blockIndex = index;
+			_container = new TableBlockContainer();
+			super(null,null);
+		}
+		
+		/**
+		 * @inheritDoc
+		 **/
+		override tlf_internal function initialize(paragraph:ParagraphElement, outerTargetWidth:Number = 0, lineOffset:Number = 0, absoluteStart:int = 0, numChars:int = 0, textLine:TextLine = null):void
+		{
+			_container.userData = this;
+			_lineOffset = lineOffset;
+
+			super.initialize(paragraph, outerTargetWidth, lineOffset, absoluteStart, numChars, textLine);
+		}
+		override tlf_internal function setController(cont:ContainerController,colNumber:int):void
+		{
+			super.setController(cont, colNumber);
+			if(cont)
+				controller.addComposedTableBlock(container);
+		}
+
+		
+		/**
+		 * The table that owns this table block
+		 **/
+		public var parentTable:TableElement;
+		
+		/**
+		 * The index of this block in the table text flow layout
+		 **/
+		public var blockIndex:uint = 0;
+		
+		/**
+		 * @private
+		 **/
+		private var _container:TableBlockContainer;
+		
+		private var _cells:Array;
+		
+		/**
+		 * Returns an array of table cells. 
+		 * @private
+		 **/
+		private function getCells():Array{
+			if(_cells == null){
+				_cells = [];
+			}
+			return _cells;
+		}
+		
+		/**
+		 * Returns a vector of table cell elements in the given cell range. 
+		 **/
+		public function getCellsInRange(anchorCoords:CellCoordinates,activeCoords:CellCoordinates):Vector.<TableCellElement>
+		{
+			if(!parentTable)
+				return null;
+			return parentTable.getCellsInRange(anchorCoords,activeCoords,this);
+		}
+		
+		/**
+		 * Clears the cells in the table block. Wraps clearCells(). 
+		 **/
+		public function clear():void{
+			clearCells();
+		}
+		
+		/**
+		 * Clears the cells in the table block
+		 **/
+		public function clearCells():void{
+			_container.removeChildren();
+			getCells().length = 0;
+		}
+		
+		/**
+		 * Adds a cell container to table container. This adds it to the display list. 
+		 * If the cell is already added it does not add it twice. 
+		 **/
+		public function addCell(cell:CellContainer):void{
+			var cells:Array = getCells();
+			if(cells.indexOf(cell) < 0){
+				cells.push(cell);
+				_container.addChild(cell);
+			}
+		}
+		
+		
+		public function drawBackground(backgroundInfo:*):void{
+			//TODO: need to figure this out...
+			
+		}
+		
+		/**
+		 * Container that displays this collection of cells
+		 **/
+		public function get container():TableBlockContainer
+		{
+			return _container;
+		}
+		
+		/**
+		 * Triggers drawing of composed cell contents
+		 **/
+		public function updateCompositionShapes():void{
+			var cells:Array = getCells();
+			for each(var cell:CellContainer in cells){
+				cell.element.updateCompositionShapes();
+			}
+		}
+
+		/**
+		 * Sets the height of the container 
+		 **/
+		public function set height(value:Number):void{
+			//_container.height = value;
+			_textHeight = value;
+		}
+		
+		/**
+		 * @inheritDoc
+		 **/
+		override public function get height():Number{
+			return _textHeight;
+		}
+		/**
+		 * Sets the width of the container 
+		 **/
+		public function set width(value:Number):void{
+			_container.width = value;
+		}
+		
+		/**
+		 * Gets the width of the container 
+		 **/
+		public function get width():Number{
+			return _container.width;
+		}
+		
+		/**
+		 * Sets the x position of the container
+		 **/
+		override public function set x(value:Number):void{
+			super.x = _container.x = value;
+		}
+		
+		override public function get x():Number{
+			return _container.x;
+		}
+		
+		/**
+		 * Sets the y value of the container
+		 **/
+		override public function set y(value:Number):void{
+			super.y = _container.y = value;
+		}
+		override public function get y():Number{
+			return _container.y;
+		}
+		
+		/**
+		 * Returns a vector of table cell elements.
+		 **/
+		public function getTableCells():Vector.<TableCellElement>
+		{
+			var tCells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			var cells:Array = getCells();
+			
+			for each(var cellContainer:CellContainer in cells){
+				tCells.push(cellContainer.element);
+			}
+			
+			return tCells;
+		}
+
+		public override function get textHeight():Number
+		{
+			return _textHeight;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/edit/SelectionType.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/SelectionType.as b/textLayout/src/flashx/textLayout/edit/SelectionType.as
new file mode 100644
index 0000000..7188bb8
--- /dev/null
+++ b/textLayout/src/flashx/textLayout/edit/SelectionType.as
@@ -0,0 +1,30 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	public class SelectionType
+	{
+		public static const TEXT:String = "text";
+		public static const CELLS:String = "cells";
+		public static const NONE:String = "none";
+		public function SelectionType()
+		{
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/elements/CellCoordinates.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/CellCoordinates.as b/textLayout/src/flashx/textLayout/elements/CellCoordinates.as
new file mode 100644
index 0000000..d28a100
--- /dev/null
+++ b/textLayout/src/flashx/textLayout/elements/CellCoordinates.as
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	/**
+	 * Describes the location of table cell by row and column 
+	 **/
+	public class CellCoordinates
+	{
+		private var _column:int;
+		private var _row:int;
+		
+		/**
+		 * @constructor
+		 **/
+		public function CellCoordinates(row:int, column:int, table:TableElement = null)
+		{
+			_row = row;
+			_column = column;
+			this.table = table;
+		}
+
+		/**
+		 * The column the cell belongs to
+		 **/
+		public function get column():int
+			{return _column;}
+		
+		/**
+		 * @private
+		 **/
+		public function set column(value:int):void
+			{_column = value;}
+
+		/**
+		 * The row the cell belongs to
+		 **/
+		public function get row():int
+			{return _row;}
+		
+		/**
+		 * @private
+		 **/
+		public function set row(value:int):void
+			{_row = value;}
+		
+		/**
+		 * Checks if two coordiates are in the same location
+		 **/
+		public static function areEqual(coords1:CellCoordinates, coords2:CellCoordinates):Boolean
+		{
+			return coords1.row == coords2.row && coords1.column == coords2.column;
+		}
+		
+		/**
+		 * Returns true if the column and row are greater than -1
+		 **/
+		public function isValid():Boolean
+		{
+			return column > -1 && row > -1;
+		}
+		
+		/**
+		 * Creates a new CellCoordinates with the same row and column values
+		 **/
+		public function clone():CellCoordinates
+		{
+			return new CellCoordinates(row, column);
+		}
+
+		public var table:TableElement;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/elements/CellRange.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/CellRange.as b/textLayout/src/flashx/textLayout/elements/CellRange.as
new file mode 100644
index 0000000..27e8490
--- /dev/null
+++ b/textLayout/src/flashx/textLayout/elements/CellRange.as
@@ -0,0 +1,147 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/**
+	 * A read only class that describes a range of contiguous table cells. Such a range occurs when you select a
+	 * section of table cells. The range consists of the anchor point of the selection, <code>anchorPosition</code>,
+	 * and the point that is to be modified by actions, <code>activePosition</code>.  As block selections are 
+	 * modified and extended <code>anchorPosition</code> remains fixed and <code>activePosition</code> is modified.  
+	 * The anchor position may be placed in the text before or after the active position.
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see flashx.textLayout.elements.TextFlow TextFlow
+	 * @see flashx.textLayout.edit.SelectionState SelectionState
+	 */
+	public class CellRange
+	{
+		
+		private var _table:TableElement
+		
+		// current range of selection
+		private var _anchorCoords:CellCoordinates;
+		private var _activeCoords:CellCoordinates;
+		
+		/**
+		 * Limits the row and column values to 0 or the number of rows or column. 
+		 **/
+		private function clampToRange(coords:CellCoordinates):CellCoordinates
+		{
+			if(coords == null)
+				return null;
+			if (coords.row < 0)
+				coords.row = 0;
+			if (coords.row >= _table.numRows)
+				coords.row = _table.numRows-1;
+			if (coords.column < 0)
+				coords.column = 0;
+			if (coords.column >= _table.numColumns)
+				coords.column = _table.numColumns-1;
+			return coords;
+		}
+
+		public function CellRange(table:TableElement, anchorCoords:CellCoordinates, activeCoords:CellCoordinates)
+		{
+			_table = table;
+			_anchorCoords = clampToRange(anchorCoords);
+			_activeCoords = clampToRange(activeCoords);
+			
+		}
+		
+		/** 
+		 * Update the range with new anchor or active position values.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *  @param newAnchorPosition	the anchor index of the selection.
+		 *  @param newActivePosition	the active index of the selection.
+		 *  @return true if selection is changed.
+		 */
+		public function updateRange(newAnchorCoordinates:CellCoordinates, newActiveCoordinates:CellCoordinates):Boolean
+		{
+			clampToRange(newAnchorCoordinates);
+			clampToRange(newActiveCoordinates);
+			
+			if (!CellCoordinates.areEqual(_anchorCoords, newAnchorCoordinates) || !CellCoordinates.areEqual(_activeCoords, newActiveCoordinates))
+			{
+				_anchorCoords = newAnchorCoordinates;
+				_activeCoords = newActiveCoordinates;
+				return true;
+			}
+			return false;
+		}
+
+		/** The TableElement of the selection.
+		 */
+		public function get table():TableElement
+		{
+			return _table;
+		}
+
+		/**
+		 * @private
+		 */
+		public function set table(value:TableElement):void
+		{
+			_table = value;
+		}
+
+		/** 
+		 * Anchor point of the current selection, as a CellCoordinates in the TableElement. 
+		 */
+		public function get anchorCoordinates():CellCoordinates
+		{
+			return _anchorCoords;
+		}
+
+		/**
+		 * @private
+		 */
+		public function set anchorCoordinates(value:CellCoordinates):void
+		{
+			_anchorCoords = value;
+		}
+
+		/** 
+		 * Active end of the current selection, as a CellCoordinates in the TableElement. 
+		 */
+		public function get activeCoordinates():CellCoordinates
+		{
+			return _activeCoords;
+		}
+
+		/**
+		 * @private
+		 */
+		public function set activeCoordinates(value:CellCoordinates):void
+		{
+			_activeCoords = value;
+		}
+
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/elements/TableBlockContainer.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableBlockContainer.as b/textLayout/src/flashx/textLayout/elements/TableBlockContainer.as
new file mode 100644
index 0000000..d5aef05
--- /dev/null
+++ b/textLayout/src/flashx/textLayout/elements/TableBlockContainer.as
@@ -0,0 +1,31 @@
+package flashx.textLayout.elements
+{
+	import flash.display.Sprite;
+	
+	import flashx.textLayout.compose.TextFlowTableBlock;
+	
+	/**
+	 * The sprite that contains the table cells. 
+	 **/
+	public class TableBlockContainer extends Sprite
+	{
+		
+		public function TableBlockContainer()
+		{
+			super();
+		}
+		
+		/**
+		 * A reference to the TextFlowTableBlock
+		 **/
+		public var userData:TextFlowTableBlock;
+		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-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/elements/TableCellElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableCellElement.as b/textLayout/src/flashx/textLayout/elements/TableCellElement.as
new file mode 100644
index 0000000..7f04939
--- /dev/null
+++ b/textLayout/src/flashx/textLayout/elements/TableCellElement.as
@@ -0,0 +1,434 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.display.Graphics;
+	import flash.display.Shape;
+	import flash.display.Sprite;
+	import flash.events.MouseEvent;
+	import flash.geom.Point;
+	import flash.text.engine.GraphicElement;
+	import flash.utils.getDefinitionByName;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.edit.EditManager;
+	import flashx.textLayout.edit.IEditManager;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.events.DamageEvent;
+	import flashx.textLayout.events.ModelChange;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.tlf_internal;
+	import flashx.undo.UndoManager;
+	
+	use namespace tlf_internal;
+	
+	/** 
+	 * 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
+	{		
+		private var _x:Number;
+		private var _y:Number;
+		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:ContainerController;
+
+		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 = new ContainerController(container,NaN,NaN);
+		}
+
+		/** @private */
+		override protected function get abstract():Boolean
+		{ return false; }
+		
+		/** @private */
+		tlf_internal override function get defaultTypeName():String
+		{ return "td"; }
+		
+		/** @private */
+		tlf_internal override function canOwnFlowElement(elem:FlowElement):Boolean
+		{// Table cells have no TLF children. Instead it contains its own TextFlow.
+			return (elem is FlowElement);
+		}
+
+		public function isDamaged():Boolean {
+			return _damaged;
+		}
+		
+		public function compose():Boolean {
+			var table:TableElement = getTable();
+			width = 0;
+			for(var i:int=0;i<columnSpan;i++)
+			{
+				if (table && table.getColumnAt(colIndex+i)) {
+					width += table.getColumnAt(colIndex+i).columnWidth;
+				}
+				
+			}
+			
+			_damaged = false;
+			_controller.paddingTop = getEffectivePaddingTop();
+			_controller.paddingBottom = getEffectivePaddingBottom();
+			_controller.paddingLeft = getEffectivePaddingLeft();
+			_controller.paddingRight = getEffectivePaddingRight();
+			
+			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:TextFlow;
+		
+		public function get textFlow():TextFlow {
+			
+			if (_textFlow == null) {
+				var flow:TextFlow = new TextFlow();
+				
+				if (table && table.getTextFlow() && table.getTextFlow().interactionManager is IEditManager) {
+					flow.interactionManager = new EditManager(IEditManager(_textFlow.interactionManager).undoManager);
+				}
+				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:TextFlow):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():ContainerController {
+			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.element = 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:TextFlowLine = _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():TableRowElement
+		{
+			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():TableCellElement {
+			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():TableCellElement {
+			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-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/elements/TableLeafElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableLeafElement.as b/textLayout/src/flashx/textLayout/elements/TableLeafElement.as
new file mode 100644
index 0000000..44e62a4
--- /dev/null
+++ b/textLayout/src/flashx/textLayout/elements/TableLeafElement.as
@@ -0,0 +1,120 @@
+package flashx.textLayout.elements
+{
+	import flash.text.engine.ElementFormat;
+	import flash.text.engine.TextElement;
+	import flash.text.engine.TextLine;
+	
+	import flashx.textLayout.compose.BaseCompose;
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.ISWFContext;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	public class TableLeafElement extends FlowLeafElement
+	{
+		private var _table:TableElement;
+		public function TableLeafElement(table:TableElement)
+		{
+			super();
+			_table = table;
+		}
+
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			// not sure if this makes sense...
+			if (_blockElement)
+				return;
+			
+			computedFormat;	// BEFORE creating the element
+			var flowComposer:IFlowComposer = getTextFlow().flowComposer;
+			var swfContext:ISWFContext = flowComposer && flowComposer.swfContext ? flowComposer.swfContext : BaseCompose.globalSWFContext;
+
+			var format:ElementFormat = FlowLeafElement.computeElementFormatHelper (_table.computedFormat, _table.getParagraph(), swfContext) 
+			_blockElement = new TextElement(_text,format);
+			CONFIG::debug { Debugging.traceFTECall(_blockElement,null,"new TextElement()"); }
+			CONFIG::debug { Debugging.traceFTEAssign(_blockElement, "text", _text); }
+			super.createContentElement();
+
+		}
+
+		/** @private */
+		override protected function get abstract():Boolean
+		{ return false; }		
+		
+		/** @private */
+		tlf_internal override function get defaultTypeName():String
+		{ return "table"; }
+		
+		/** @private */
+		public override function get text():String
+		{
+			return "\u0016";
+		}
+		
+		/** @private */
+		public override function getText(relativeStart:int=0, relativeEnd:int=-1, paragraphSeparator:String="\n"):String
+		{
+			return _table.getText(relativeStart, relativeEnd, paragraphSeparator);
+		}
+		
+		/** @private */
+		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			// not sure what to do here (see SpanElement)...
+			super.normalizeRange(normalizeStart,normalizeEnd);
+		}
+		
+		/** @private */
+		tlf_internal override function mergeToPreviousIfPossible():Boolean
+		{
+			// not sure what to do here (see SpanElement)...
+			return false;
+		}
+		
+		public override function getNextLeaf(limitElement:FlowGroupElement=null):FlowLeafElement
+		{
+			return _table.getNextLeafHelper(limitElement,this);
+		}
+		
+		public override function getPreviousLeaf(limitElement:FlowGroupElement=null):FlowLeafElement
+		{
+			return _table.getPreviousLeafHelper(limitElement,this);
+		}
+		/** @private */
+		public override function getCharAtPosition(relativePosition:int):String
+		{
+			return getText(relativePosition,relativePosition);
+		}
+		public override function get computedFormat():ITextLayoutFormat
+		{
+			return _table.computedFormat;
+		}
+		public override function get textLength():int
+		{
+			return _table.textLength;
+		}
+		tlf_internal override function updateAdornments(tLine:TextLine, blockProgression:String):int
+		{
+			return 0;
+		}
+
+		override public function get parent():FlowGroupElement
+		{ 
+			return _table; 
+		}
+
+		override public function getTextFlow():TextFlow
+		{
+			return _table.getTextFlow();
+		}
+		
+		override public function getParagraph():ParagraphElement
+		{
+			return _table.getParagraph();
+		}
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/formats/ITextLayoutFormat.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/formats/ITextLayoutFormat.as b/textLayout/src/flashx/textLayout/formats/ITextLayoutFormat.as
index e25b683..8e3099d 100644
--- a/textLayout/src/flashx/textLayout/formats/ITextLayoutFormat.as
+++ b/textLayout/src/flashx/textLayout/formats/ITextLayoutFormat.as
@@ -1161,6 +1161,62 @@ package flashx.textLayout.formats
 		function get borderBottomColor():*;
 
 		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get borderLeftPriority():*;
+		
+		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get borderRightPriority():*;
+		
+		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get borderTopPriority():*;
+		
+		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get borderBottomPriority():*;
+
+		/**
 		 * left margin in pixels(adopts default value if undefined during cascade).
 		 * <p>Legal values are numbers from -8000 to 8000 and FormatValue.INHERIT.</p>
 		 * <p>Default value is undefined indicating not set.</p>
@@ -1245,7 +1301,7 @@ package flashx.textLayout.formats
 		 * @langversion 3.0
 		 */
 		function get cellPadding():*;
-
+		
 		/**
 		 * Width of table element specifies the desired width of the entire table and is intended for visual user agents. When the value is a percentage value, the value is relative to the user agent's available horizontal space.
 		 * <p>Legal values as a number are from 0 to 8000.</p>
@@ -1277,6 +1333,36 @@ package flashx.textLayout.formats
 		 * @langversion 3.0
 		 */
 		function get tableColumnWidth():*;
+		
+		/**
+		 * Minimum height of a table cell. If there is no maximum, the cell will grow in height to fit the content. Minimum and maximum of the same values will give the cell a fixed height.
+		 * <p>Legal values as a number are from 2 to 10000.</p>
+		 * <p>Legal values include FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 2.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get minCellHeight():*;
+		
+		/**
+		 * Maximum height of a table cell. If there is no maximum, the cell will grow in height to fit the content. Minimum and maximum of the same values will give the cell a fixed height.
+		 * <p>Legal values as a number are from 2 to 10000.</p>
+		 * <p>Legal values include FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 2.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get maxCellHeight():*;
 
 		/**
 		 * frame specifies which sides of the frame surrounding a table will be visible. Possible values:

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/formats/TextLayoutFormat.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/formats/TextLayoutFormat.as b/textLayout/src/flashx/textLayout/formats/TextLayoutFormat.as
index b532c40..aa8166a 100644
--- a/textLayout/src/flashx/textLayout/formats/TextLayoutFormat.as
+++ b/textLayout/src/flashx/textLayout/formats/TextLayoutFormat.as
@@ -74,7 +74,7 @@ package flashx.textLayout.formats
 
 	/**
 	 * The TextLayoutFormat class holds all of the text layout properties. These properties affect the format and style of a text flow at the container level, paragraph level, and text level.  Both the ContainerController class and the FlowElement base class have <code>format</code> properties that enable you to assign a TextLayoutFormat instance to them. Assign a TextLayoutFormat object to a container to affect the format of all of the container's content. Assign a TextLayoutFormat object to a FlowElement descendant to specify formatting for that particular element: TextFlow, ParagraphElement, DivElement, SpanElement, InlineGraphicElement, LinkElement, and TCYElement.
-	 * In addition to the <code>format</code> property, these classes also define each of the individual TextLayoutFormat properties so that you can override the setting of a particular style property for that element, if you wish. <p>Because you can set a given style at multiple levels, it is possible to have conflicts. For example, the color of the text at the TextFlow level could be set to black while a SpanElement object sets it to blue. The general rule is that the setting at the lowest level on the text flow tree takes precedence. So if the ligature level is set for a TextFlow instance and also set for a DivElement, the DivElement setting takes precedence. </p><p>Cascading styles refers to the process of adopting styles from a higher level in the text flow if a style value is undefined at a lower level. When a style is undefined on an element at the point it is about to be rendered, it either takes its default value or the value cascades or descends from the value on a parent ele
 ment. For example, if the transparency (<code>textAlpha</code> property) of the text is undefined on a SpanElement object, but is set on the TextFlow, the value of the <code>TextFlow.textAlpha</code> property cascades to the SpanElement object and is applied to the text for that span. The result of the cascade, or the sum of the styles that is applied to the element, is stored in the element's <code>computedFormat</code> property.</p><p>In the same way, you can apply user styles using the <code>userStyles</code> property of the ContainerController and FlowElement classes. This  property allows you to read or write a dictionary of user styles and apply its settings to a container or a text flow element. The user styles dictionary is an object that consists of <em>stylename-value</em> pairs. Styles specified by the <code>userStyles</code> property take precedence over all others.</p><p>Most styles that are undefined inherit the value of their immediate parent during a cascade. A small
  number of styles, however, do not inherit their parent�s value and take on their default values instead.</p><p><strong>Style properties that adopt their default values, if undefined, include:</strong> <code>backgroundAlpha</code>, <code>backgroundColor</code>, <code>columnCount</code>, <code>columnGap</code>, <code>columnWidth</code>, <code>lineBreak</code>, <code>paddingBottom</code>, <code>paddingLeft</code>, <code>paddingRight</code>, <code>paddingTop</code>, <code>verticalAlign</code></p>.
+	 * In addition to the <code>format</code> property, these classes also define each of the individual TextLayoutFormat properties so that you can override the setting of a particular style property for that element, if you wish. <p>Because you can set a given style at multiple levels, it is possible to have conflicts. For example, the color of the text at the TextFlow level could be set to black while a SpanElement object sets it to blue. The general rule is that the setting at the lowest level on the text flow tree takes precedence. So if the ligature level is set for a TextFlow instance and also set for a DivElement, the DivElement setting takes precedence. </p><p>Cascading styles refers to the process of adopting styles from a higher level in the text flow if a style value is undefined at a lower level. When a style is undefined on an element at the point it is about to be rendered, it either takes its default value or the value cascades or descends from the value on a parent ele
 ment. For example, if the transparency (<code>textAlpha</code> property) of the text is undefined on a SpanElement object, but is set on the TextFlow, the value of the <code>TextFlow.textAlpha</code> property cascades to the SpanElement object and is applied to the text for that span. The result of the cascade, or the sum of the styles that is applied to the element, is stored in the element's <code>computedFormat</code> property.</p><p>In the same way, you can apply user styles using the <code>userStyles</code> property of the ContainerController and FlowElement classes. This  property allows you to read or write a dictionary of user styles and apply its settings to a container or a text flow element. The user styles dictionary is an object that consists of <em>stylename-value</em> pairs. Styles specified by the <code>userStyles</code> property take precedence over all others.</p><p>Most styles that are undefined inherit the value of their immediate parent during a cascade. A small
  number of styles, however, do not inherit their parent�s value and take on their default values instead.</p><p><strong>Style properties that adopt their default values, if undefined, include:</strong> <code>backgroundAlpha</code>, <code>backgroundColor</code>, <code>columnCount</code>, <code>columnGap</code>, <code>columnWidth</code>, <code>lineBreak</code>, <code>paddingBottom</code>, <code>paddingLeft</code>, <code>paddingRight</code>, <code>paddingTop</code>, <code>verticalAlign</code></p>.
 	 * @includeExample examples\TextLayoutFormatExample.as -noswf
 	 * @includeExample examples\TextLayoutFormatExample2.as -noswf
 	 * @see flashx.textLayout.elements.FlowElement#format
@@ -953,6 +953,38 @@ package flashx.textLayout.formats
 			return _borderBottomColorProperty;
 		}
 		/** @private */
+		static private var _borderLeftPriorityProperty:Property;
+		static public function get borderLeftPriorityProperty():Property
+		{
+			if (!_borderLeftPriorityProperty)
+				_borderLeftPriorityProperty = Property.NewNumberProperty("borderLeftPriority",0,false,Vector.<String>([Category.TABLE,Category.TABLECELL,Category.TABLECOLUMN,Category.TABLEROW]),-8000,8000);
+			return _borderLeftPriorityProperty;
+		}
+		/** @private */
+		static private var _borderRightPriorityProperty:Property;
+		static public function get borderRightPriorityProperty():Property
+		{
+			if (!_borderRightPriorityProperty)
+				_borderRightPriorityProperty = Property.NewNumberProperty("borderRightPriority",0,false,Vector.<String>([Category.TABLE,Category.TABLECELL,Category.TABLECOLUMN,Category.TABLEROW]),-8000,8000);
+			return _borderRightPriorityProperty;
+		}
+		/** @private */
+		static private var _borderTopPriorityProperty:Property;
+		static public function get borderTopPriorityProperty():Property
+		{
+			if (!_borderTopPriorityProperty)
+				_borderTopPriorityProperty = Property.NewNumberProperty("borderTopPriority",0,false,Vector.<String>([Category.TABLE,Category.TABLECELL,Category.TABLECOLUMN,Category.TABLEROW]),-8000,8000);
+			return _borderTopPriorityProperty;
+		}
+		/** @private */
+		static private var _borderBottomPriorityProperty:Property;
+		static public function get borderBottomPriorityProperty():Property
+		{
+			if (!_borderBottomPriorityProperty)
+				_borderBottomPriorityProperty = Property.NewNumberProperty("borderBottomPriority",0,false,Vector.<String>([Category.TABLE,Category.TABLECELL,Category.TABLECOLUMN,Category.TABLEROW]),-8000,8000);
+			return _borderBottomPriorityProperty;
+		}
+		/** @private */
 		static private var _marginLeftProperty:Property;
 		static public function get marginLeftProperty():Property
 		{
@@ -1017,6 +1049,22 @@ package flashx.textLayout.formats
 			return _tableColumnWidthProperty;
 		}
 		/** @private */
+		static private var _minCellHeightProperty:Property;
+		static public function get minCellHeightProperty():Property
+		{
+			if (!_minCellHeightProperty)
+				_minCellHeightProperty = Property.NewNumberOrEnumProperty("minCellHeight",2,false,Vector.<String>([Category.TABLE,Category.TABLECELL]),2,8000);
+			return _minCellHeightProperty;
+		}
+		/** @private */
+		static private var _maxCellHeightProperty:Property;
+		static public function get maxCellHeightProperty():Property
+		{
+			if (!_maxCellHeightProperty)
+				_maxCellHeightProperty = Property.NewNumberOrEnumProperty("maxCellHeight",8000,false,Vector.<String>([Category.TABLE,Category.TABLECELL]),2,8000);
+			return _maxCellHeightProperty;
+		}
+		/** @private */
 		static private var _frameProperty:Property;
 		static public function get frameProperty():Property
 		{
@@ -1136,6 +1184,12 @@ package flashx.textLayout.formats
 			, tableColumnWidth:tableColumnWidthProperty
 			, frame:frameProperty
 			, rules:rulesProperty
+			, borderLeftPriority:borderLeftPriorityProperty
+			, borderRightPriority:borderRightPriorityProperty
+			, borderTopPriority:borderTopPriorityProperty
+			, borderBottomPriority:borderBottomPriorityProperty
+			, minCellHeight:minCellHeightProperty
+			, maxCellHeight:maxCellHeightProperty
 		}
 
 		/** Property descriptions accessible by name. @private */
@@ -2962,6 +3016,74 @@ package flashx.textLayout.formats
 		{ setStyleByProperty(TextLayoutFormat.borderBottomColorProperty,value); }
 
 		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get borderLeftPriority():*
+		{ return _styles.borderLeftPriority; }
+		public function set borderLeftPriority(value:*):void
+		{ setStyleByProperty(TextLayoutFormat.borderLeftPriorityProperty,value); }
+		
+		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get borderRightPriority():*
+		{ return _styles.borderRightPriority; }
+		public function set borderRightPriority(value:*):void
+		{ setStyleByProperty(TextLayoutFormat.borderRightPriorityProperty,value); }
+		
+		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get borderTopPriority():*
+		{ return _styles.borderTopPriority; }
+		public function set borderTopPriority(value:*):void
+		{ setStyleByProperty(TextLayoutFormat.borderTopPriorityProperty,value); }
+		
+		/**
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get borderBottomPriority():*
+		{ return _styles.borderBottomPriority; }
+		public function set borderBottomPriority(value:*):void
+		{ setStyleByProperty(TextLayoutFormat.borderBottomPriorityProperty,value); }
+
+		/**
 		 * left margin in pixels(adopts default value if undefined during cascade).
 		 * <p>Legal values are numbers from -8000 to 8000 and FormatValue.INHERIT.</p>
 		 * <p>Default value is undefined indicating not set.</p>
@@ -3102,6 +3224,44 @@ package flashx.textLayout.formats
 		{ return _styles.tableColumnWidth; }
 		public function set tableColumnWidth(value:*):void
 		{ setStyleByProperty(TextLayoutFormat.tableColumnWidthProperty,value); }
+		
+		/**
+		 * Minimum height of a table cell. If there is no maximum, the cell will grow in height to fit the content. Minimum and maximum of the same values will give the cell a fixed height.
+		 * <p>Legal values as a number are from 2 to 10000.</p>
+		 * <p>Legal values include FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 2.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get minCellHeight():*
+		{ return _styles.minCellHeight; }
+		public function set minCellHeight(value:*):void
+		{ setStyleByProperty(TextLayoutFormat.minCellHeightProperty,value); }
+		
+		/**
+		 * Maximum height of a table cell. If there is no maximum, the cell will grow in height to fit the content. Minimum and maximum of the same values will give the cell a fixed height.
+		 * <p>Legal values as a number are from 2 to 10000.</p>
+		 * <p>Legal values include FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 2.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get maxCellHeight():*
+		{ return _styles.maxCellHeight; }
+		public function set maxCellHeight(value:*):void
+		{ setStyleByProperty(TextLayoutFormat.maxCellHeightProperty,value); }
+
+
 
 		[Inspectable(enumeration="void,above,below,hsides,vsides,lhs,rhs,box,border,inherit")]
 		/**
@@ -3241,6 +3401,18 @@ package flashx.textLayout.formats
 				stylesObject.frame = TextLayoutFormat.frameProperty.defaultValue;
 			if (stylesObject.rules != undefined && stylesObject.rules != TextLayoutFormat.rulesProperty.defaultValue)
 				stylesObject.rules = TextLayoutFormat.rulesProperty.defaultValue;
+			if( stylesObject.borderBottomPriority != undefined &&  stylesObject.borderBottomPriority != TextLayoutFormat.borderBottomPriorityProperty.defaultValue)
+				stylesObject.borderBottomPriority = TextLayoutFormat.borderBottomPriorityProperty.defaultValue;
+			if( stylesObject.borderTopPriority != undefined &&  stylesObject.borderTopPriority != TextLayoutFormat.borderTopPriorityProperty.defaultValue)
+				stylesObject.borderTopPriority = TextLayoutFormat.borderTopPriorityProperty.defaultValue;
+			if( stylesObject.borderLeftPriority != undefined &&  stylesObject.borderLeftPriority != TextLayoutFormat.borderLeftPriorityProperty.defaultValue)
+				stylesObject.borderLeftPriority = TextLayoutFormat.borderLeftPriorityProperty.defaultValue;
+			if( stylesObject.borderRightPriority != undefined &&  stylesObject.borderRightPriority != TextLayoutFormat.borderRightPriorityProperty.defaultValue)
+				stylesObject.borderRightPriority = TextLayoutFormat.borderRightPriorityProperty.defaultValue;
+			if (stylesObject.minCellHeight != undefined && stylesObject.minCellHeight != TextLayoutFormat.minCellHeightProperty.defaultValue)
+				stylesObject.minCellHeight = TextLayoutFormat.minCellHeightProperty.defaultValue;
+			if (stylesObject.maxCellHeight != undefined && stylesObject.maxCellHeight != TextLayoutFormat.maxCellHeightProperty.defaultValue)
+				stylesObject.maxCellHeight = TextLayoutFormat.maxCellHeightProperty.defaultValue;
 		}
 
 		/**

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/a0a0749e/textLayout/src/flashx/textLayout/formats/TextLayoutFormatInc.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/formats/TextLayoutFormatInc.as b/textLayout/src/flashx/textLayout/formats/TextLayoutFormatInc.as
index c263433..2c1f6f6 100644
--- a/textLayout/src/flashx/textLayout/formats/TextLayoutFormatInc.as
+++ b/textLayout/src/flashx/textLayout/formats/TextLayoutFormatInc.as
@@ -1837,6 +1837,98 @@
 		}
 
 		/**
+ 		* TextLayoutFormat:
+ 		* Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+ 		* <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+ 		* <p>Default value is undefined indicating not set.</p>
+ 		* <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+ 		* 
+ 		* @throws RangeError when set value is not within range for this property
+ 		* 
+ 		* @playerversion Flash 10
+ 		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		*/
+		public function get borderLeftPriority():*
+		{
+			return _format ? _format.borderLeftPriority : undefined;
+		}
+		public function set borderLeftPriority(value:*):void
+		{ 
+			writableTextLayoutFormat().borderLeftPriority = value;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get borderRightPriority():*
+		{
+			return  _format ? _format.borderRightPriority : undefined;
+		}
+		public function set borderRightPriority(value:*):void
+		{
+			writableTextLayoutFormat().borderRightPriority = value;
+			formatChanged();
+		}
+		
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get borderTopPriority():*
+		{
+			return  _format ? _format.borderTopPriority : undefined;
+		}
+		public function set borderTopPriority(value:*):void
+		{
+			writableTextLayoutFormat().borderTopPriority = value;
+			formatChanged();
+		}
+		
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the priority when drawing cell boundaries. When settings between two adjacent cells conflict, the border with the higher priority wins. If the priorities are equal, the latter of the two cells takes priority.
+		 * <p>Legal values are any rational number. Conflicts are resolved with the properties of the higher number being drawn.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit, and default to 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get borderBottomPriority():*
+		{
+			return  _format ? _format.borderBottomPriority : undefined;
+		}
+		public function set borderBottomPriority(value:*):void
+		{
+			writableTextLayoutFormat().borderBottomPriority = value;
+			formatChanged();
+		}
+
+		/**
 		 * TextLayoutFormat:
 		 * left margin in pixels(adopts default value if undefined during cascade).
 		 * <p>Legal values are numbers from -8000 to 8000 and FormatValue.INHERIT.</p>
@@ -1849,6 +1941,7 @@
 		 * @playerversion AIR 1.5
 		 * @langversion 3.0
 		 */
+
 		public function get marginLeft():*
 		{
 			return _format ? _format.marginLeft : undefined;
@@ -2026,6 +2119,54 @@
 			formatChanged();
 		}
 
+		/**
+		 * TextLayoutFormat:
+		 * Minimum height of a table cell. If there is no maximum, the cell will grow in height to fit the content. Minimum and maximum of the same values will give the cell a fixed height.
+		 * <p>Legal values as a number are from 2 to 10000.</p>
+		 * <p>Legal values include FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 2.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get minCellHeight():*
+		{
+			return _format ? _format.minCellHeight : undefined;
+		}
+		public function set minCellHeight(value:*):void
+		{
+			writableTextLayoutFormat().minCellHeight = value;
+			formatChanged();
+		}
+		
+		/**
+		 * TextLayoutFormat:
+		 * Maximum height of a table cell. If there is no maximum, the cell will grow in height to fit the content. Minimum and maximum of the same values will give the cell a fixed height.
+		 * <p>Legal values as a number are from 2 to 10000.</p>
+		 * <p>Legal values include FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 2.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get maxCellHeight():*
+		{
+			return _format ? _format.maxCellHeight : undefined;
+		}
+		public function set maxCellHeight(value:*):void
+		{
+			writableTextLayoutFormat().maxCellHeight = value;
+			formatChanged();
+		}
+
 		[Inspectable(enumeration="void,above,below,hsides,vsides,lhs,rhs,box,border,inherit")]
 		/**
 		 * TextLayoutFormat:


[13/25] git commit: [flex-tlf] [refs/heads/develop] - Added check for valid terminator span after replacement

Posted by pi...@apache.org.
Added check for valid terminator span after replacement


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/84e8b25b
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/84e8b25b
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/84e8b25b

Branch: refs/heads/develop
Commit: 84e8b25b22a56e015c81f91e091e875c5f00bc71
Parents: b408e2f
Author: Harbs <ha...@in-tools.com>
Authored: Thu Oct 30 23:34:54 2014 +0200
Committer: Harbs <ha...@in-tools.com>
Committed: Thu Oct 30 23:34:54 2014 +0200

----------------------------------------------------------------------
 textLayout/src/flashx/textLayout/elements/ParagraphElement.as | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/84e8b25b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
index 6527d7c..4ddd7c4 100644
--- a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
+++ b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
@@ -653,7 +653,7 @@ package flashx.textLayout.elements
 				}
 			}
 			//merge terminator span to previous if possible
-			if(_terminatorSpan.textLength == 1)
+			if(_terminatorSpan && _terminatorSpan.textLength == 1)
 			{
 				var prev:FlowLeafElement = _terminatorSpan.getPreviousLeaf(this);
 				if(prev && prev is SpanElement)


[10/25] git commit: [flex-tlf] [refs/heads/develop] - Added convenience method for determining if a table has merged cells. Allow a CellRange to have a null table

Posted by pi...@apache.org.
Added convenience method for determining if a table has merged cells.
Allow a CellRange to have a null table


Project: http://git-wip-us.apache.org/repos/asf/flex-tlf/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-tlf/commit/b9011500
Tree: http://git-wip-us.apache.org/repos/asf/flex-tlf/tree/b9011500
Diff: http://git-wip-us.apache.org/repos/asf/flex-tlf/diff/b9011500

Branch: refs/heads/develop
Commit: b9011500beae1c9774d9621bdc706b5e85202cf9
Parents: e5a3382
Author: Harbs <ha...@in-tools.com>
Authored: Wed Oct 22 14:50:19 2014 +0300
Committer: Harbs <ha...@in-tools.com>
Committed: Wed Oct 22 14:50:19 2014 +0300

----------------------------------------------------------------------
 .../src/flashx/textLayout/elements/CellRange.as |  7 +++++--
 .../flashx/textLayout/elements/TableElement.as  | 22 ++++++++++++++++++++
 2 files changed, 27 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/b9011500/textLayout/src/flashx/textLayout/elements/CellRange.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/CellRange.as b/textLayout/src/flashx/textLayout/elements/CellRange.as
index 27e8490..8e83003 100644
--- a/textLayout/src/flashx/textLayout/elements/CellRange.as
+++ b/textLayout/src/flashx/textLayout/elements/CellRange.as
@@ -54,10 +54,13 @@ package flashx.textLayout.elements
 				return null;
 			if (coords.row < 0)
 				coords.row = 0;
-			if (coords.row >= _table.numRows)
-				coords.row = _table.numRows-1;
 			if (coords.column < 0)
 				coords.column = 0;
+			if(_table == null)
+				return coords;
+			
+			if (coords.row >= _table.numRows)
+				coords.row = _table.numRows-1;
 			if (coords.column >= _table.numColumns)
 				coords.column = _table.numColumns-1;
 			return coords;

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/b9011500/textLayout/src/flashx/textLayout/elements/TableElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableElement.as b/textLayout/src/flashx/textLayout/elements/TableElement.as
index ed82a28..a9472c1 100644
--- a/textLayout/src/flashx/textLayout/elements/TableElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableElement.as
@@ -408,6 +408,25 @@ package flashx.textLayout.elements
 		}
 		
 		/**
+		 * Convenience method for checking if table has merged cells
+		 * 
+		 */
+		public function hasMergedCells():Boolean
+		{
+			var cell:TableCellElement;
+			var child:*;
+			if(mxmlChildren == null)
+				return false;
+			for each(child in mxmlChildren)
+			{
+				cell = child as TableCellElement;
+				if( cell && (cell.columnSpan > 1 || cell.rowSpan > 1) )
+					return true;
+			}
+			return false;
+		}
+		
+		/**
 		 * Inserts a column at the end of the table. If a column is not provided one is created. 
 		 * 
 		 * @see addColumn
@@ -1441,6 +1460,9 @@ package flashx.textLayout.elements
 			return _tableBlocks;
 		}
 		
+		/**
+		 * Returns a vector of the table blocks in the specified cell range.
+		 **/
 		public function getTableBlocksInRange(start:CellCoordinates,end:CellCoordinates):Vector.<TextFlowTableBlock>
 		{
 			var coords:CellCoordinates = start.clone();


[04/25] git commit: [flex-tlf] [refs/heads/develop] - Commit of table work

Posted by pi...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/container/ContainerController.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/container/ContainerController.as b/textLayout/src/flashx/textLayout/container/ContainerController.as
index a4e63f1..2e375f4 100644
--- a/textLayout/src/flashx/textLayout/container/ContainerController.as
+++ b/textLayout/src/flashx/textLayout/container/ContainerController.as
@@ -48,6 +48,7 @@ package flashx.textLayout.container
 	import flashx.textLayout.compose.FlowDamageType;
 	import flashx.textLayout.compose.IFlowComposer;
 	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.compose.TextFlowTableBlock;
 	import flashx.textLayout.compose.TextLineRecycler;
 	import flashx.textLayout.debug.Debugging;
 	import flashx.textLayout.debug.assert;
@@ -56,6 +57,8 @@ package flashx.textLayout.container
 	import flashx.textLayout.edit.ISelectionManager;
 	import flashx.textLayout.edit.SelectionFormat;
 	import flashx.textLayout.elements.BackgroundManager;
+	import flashx.textLayout.elements.CellCoordinates;
+	import flashx.textLayout.elements.CellRange;
 	import flashx.textLayout.elements.Configuration;
 	import flashx.textLayout.elements.ContainerFormattedElement;
 	import flashx.textLayout.elements.FlowElement;
@@ -64,6 +67,10 @@ package flashx.textLayout.container
 	import flashx.textLayout.elements.InlineGraphicElement;
 	import flashx.textLayout.elements.LinkElement;
 	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TableBlockContainer;
+	import flashx.textLayout.elements.TableCellElement;
+	import flashx.textLayout.elements.TableElement;
+	import flashx.textLayout.elements.TableRowElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.events.FlowElementMouseEvent;
 	import flashx.textLayout.events.FlowElementMouseEventManager;
@@ -112,7 +119,6 @@ package flashx.textLayout.container
 	public class ContainerController implements IInteractionEventHandler, ITextLayoutFormat, ISandboxSupport
 	{		
 		static tlf_internal var usesDiscretionaryHyphens:Boolean = true;
-		static tlf_internal var startComposeFromBeginning:Boolean = false;
 		
 		private var _textFlowCache:TextFlow;
 		private var _rootElement:ContainerFormattedElement;
@@ -178,6 +184,7 @@ package flashx.textLayout.container
 		
 		private var _linesInView:Array;	// lines that were in view according to the previous compose(). Empty if the lines have already been posted to the display list.
 		private var _updateStart:int;
+		private var _tableBlocksInView:Array; // // table blocks that were in view according to the previous compose(). Empty if the lines have already been posted to the display list.
 		
 		private var _composedFloats:Array;  // floats that were composed into the controller -- array of FloatCompositionData
 		private var _floatsInContainer:Array;  // floats are currently in view -- array of DisplayObject
@@ -267,6 +274,7 @@ package flashx.textLayout.container
 			
 			_shapeChildren = [ ];
 			_linesInView = [ ];
+			_tableBlocksInView = [];
 			
 			setCompositionSize(compositionWidth, compositionHeight);
 			format = _containerControllerInitialFormat;
@@ -397,7 +405,7 @@ package flashx.textLayout.container
 		/** 
 		 * Sets the width and height allowed for text in the container. Width and height can be specified in pixels or <code>NaN</code> can be used for either value.  <code>NaN</code> indicates measure that value. 
 		 * This can be used to find the widest line and/or the total height of all the content.  When NaN is specified as the width lines are broken with a maximum width of <code>TextLine.MAX_LINE_WIDTH</code>. 
-		 * When <code>NaN</code> is specified as the height the container is assumed to have unlimited height.  The actual measured values can be ready back in <code>getContentBounds</code>.  
+		 * When <code>NaN</code> is specified as the height the container is assumed to have unlimited height.  The actual measured values can be read back in <code>getContentBounds</code>.  
 		 * When the computed <code>blockProgression</code> property of <code>TextFlow</code>
 		 * is <code>BlockProgression.RL</code> the meanings of width and height are exchanged.
 		 *
@@ -415,7 +423,7 @@ package flashx.textLayout.container
 		 * @langversion 3.0
 		 */
 		
-		public function setCompositionSize(w:Number,h:Number):void
+		public function setCompositionSize(w:Number, h:Number):void
 		{
 		//	trace("setCompositionSize(" + w + ", " + h + ")");
 			
@@ -737,13 +745,19 @@ package flashx.textLayout.container
 				var curLine:TextFlowLine;
 				var textLine:TextLine;
 				var lineIndex:int;
+				var testRslt:*;
 				
 				//Use binary search when there is one single column
 				if(columnCount == 1)
 				{
 					// First just test the firstLine - normal unscrolled case
-					curLine = flowComposer.getLineAt(firstLine);	
-					textLine = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null) as TextLine;
+					var testPos:int = firstLine;
+					curLine = flowComposer.getLineAt(testPos++);
+					while(curLine && curLine is TextFlowTableBlock)
+						curLine = flowComposer.getLineAt(testPos++);
+					
+					testRslt = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null)
+					textLine = testRslt as TextLine;
 					firstLine++;	// its been tested
 					if (textLine)
 					{
@@ -759,10 +773,11 @@ package flashx.textLayout.container
 							var mid:int = (firstLine+hi)/2;
 							CONFIG::debug { assert(mid != 0,"ContainerController:gatherVisibleLines: bad mid"); }
 							curLine = flowComposer.getLineAt(mid);
-							var testRslt:* = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null);
-							textLine = testRslt as TextLine;
-							if (textLine)
+							testRslt = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null);
+							
+							if (testRslt && testRslt is TextLine)
 							{
+								textLine = testRslt as TextLine;
 								// note that we tested firstLine above so going to mid-1 is always valid
 								var tempLine:TextFlowLine = flowComposer.getLineAt(mid-1);
 								if (!(testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, tempLine, null) is TextLine))
@@ -776,6 +791,8 @@ package flashx.textLayout.container
 								}
 								testRslt = -1;	// past the start
 							}
+							// need to deal with TextFlowTableBlocks
+							
 							if (testRslt < 0 || testRslt == 2)
 								hi = mid-1;
 							else
@@ -785,8 +802,12 @@ package flashx.textLayout.container
 					
 					for (lineIndex = firstLine; lineIndex <= lastLine; lineIndex++)
 					{
-						curLine = flowComposer.getLineAt(lineIndex);	
-						textLine = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null) as TextLine;
+						curLine = flowComposer.getLineAt(lineIndex);
+						testRslt = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null);
+						
+						if(testRslt is TableBlockContainer)
+							continue;
+						textLine = testRslt as TextLine;
 						if (!textLine)
 							break;
 		
@@ -2811,6 +2832,42 @@ package flashx.textLayout.container
 			addSelectionChild(selObj);
 		}
 		
+		/** Add cell selection shapes to the displaylist. @private */
+		tlf_internal function addCellSelectionShapes(color:uint, tableBlock:TextFlowTableBlock, startCoords:CellCoordinates, endCoords:CellCoordinates): void
+		{
+			if(!tableBlock)
+				return;
+			if(!startCoords.isValid() || !endCoords.isValid())
+				return;
+			var cells:Vector.<TableCellElement> = tableBlock.getCellsInRange(startCoords,endCoords);
+			var selObj:Shape = new Shape();
+			selObj.graphics.beginFill(color);
+			for each( var cell:TableCellElement in cells)
+			{
+				var row:TableRowElement = cell.getRow();
+				var r:Rectangle = new Rectangle(cell.x, cell.y + tableBlock.y, cell.width, row.composedHeight);
+				selObj.graphics.drawRect(r.x,r.y,r.width,r.height);
+			}
+			addSelectionChild(selObj);
+		}
+		
+		/** 
+		 * Add cell selection shapes to the displaylist.
+		 * */
+		tlf_internal function addCellSelections(cells:Array, color:uint, tableBlock:TextFlowTableBlock): void
+		{
+			var shape:Shape = new Shape();
+			shape.graphics.beginFill(color);
+			
+			for each(var cell:TableCellElement in cells) {
+				var row:TableRowElement = cell.getRow();
+				var rectangle:Rectangle = new Rectangle(cell.x, cell.y + tableBlock.y, cell.width, row.composedHeight);
+				shape.graphics.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+			}
+			
+			addSelectionChild(shape);
+		}
+		
 		/** Add selection shapes to the displaylist. @private */
 		tlf_internal function addSelectionShapes(selFormat:SelectionFormat, selectionAbsoluteStart:int, selectionAbsoluteEnd:int): void
 		{
@@ -2855,6 +2912,7 @@ package flashx.textLayout.container
 				{
 					nextLine = idx != flowComposer.numLines - 1 ? flowComposer.getLineAt(idx+1) : null;
 					
+					// 9-1-14 Harbs Do we draw a selection rect for tables? If yes, this needs special handling in TextFlowTableBlock
 					line.hiliteBlockSelection(selObj, selFormat, this._container,
 						selectionAbsoluteStart < line.absoluteStart ? line.absoluteStart : selectionAbsoluteStart,
 						selectionAbsoluteEnd > line.absoluteStart+line.textLength ? line.absoluteStart+line.textLength : selectionAbsoluteEnd, prevLine, nextLine);
@@ -2903,7 +2961,7 @@ package flashx.textLayout.container
 		{
 			// If there's no selectionSprite on this controller, we use the parent's.
 			// That means we have to translate the coordinates.
-			// TODO: this only supports one level of ntesting
+			// TODO: this only supports one level of nesting
 			var selectionSprite:DisplayObjectContainer = getSelectionSprite(true);
 			
 			if (selectionSprite == null)
@@ -2918,7 +2976,7 @@ package flashx.textLayout.container
 				selectionSprite.blendMode = curBlendMode;
 			
 			if (selectionSprite.alpha != curAlpha)
-				selectionSprite.alpha = curAlpha;
+				selectionSprite.alpha = 1;//curAlpha; testing remove this 
 			
 			if (selectionSprite.numChildren == 0)
 				addSelectionContainer(selectionSprite);
@@ -3042,10 +3100,13 @@ package flashx.textLayout.container
 		{
 			setTextLength(0); 
 			
-			for each (var textLine:TextLine in _shapeChildren)
+			for each (var line:* in _shapeChildren)
 			{
-				removeTextLine(textLine);
-				CONFIG::debug { Debugging.traceFTECall(null,_container,"removeTextLine",textLine); }
+				if(line is TextLine)
+					removeTextLine(line as TextLine);
+				else
+					removeTableBlock(line as TableBlockContainer);
+				CONFIG::debug { Debugging.traceFTECall(null,_container,"removeTextLine",line); }
 			}
 			_shapeChildren.length = 0;
 			_linesInView.length = 0;
@@ -3058,6 +3119,21 @@ package flashx.textLayout.container
 		
 		private static var scratchRectangle:Rectangle = new Rectangle();
 		
+		private function intersperseTableBlocks(targetArray:Array):void{
+			if(_tableBlocksInView.length == 0)
+				return;
+			var blockIdx:int = 0;
+			var startLoc:int = (_tableBlocksInView[0] as TableBlockContainer).userData.parentTable.getAbsoluteStart();
+			for(var i:int=0;i<targetArray.length;i++){
+				if( targetArray[i].userData.absoluteStart < startLoc )
+					continue;
+				targetArray.splice(i,0,_tableBlocksInView[blockIdx++]);
+				if(blockIdx == _tableBlocksInView.length)
+					break;
+			}
+			while(blockIdx < _tableBlocksInView.length)
+				targetArray.push(_tableBlocksInView[blockIdx++]);
+		}
 		/** Add DisplayObjects that were created by composition to the container. @private */
 		tlf_internal function updateCompositionShapes():void
 		{
@@ -3085,6 +3161,9 @@ package flashx.textLayout.container
 			fillShapeChildren();
 			var newShapeChildren:Array = _linesInView;
 			
+			// Add in table blocks
+			intersperseTableBlocks(newShapeChildren);
+			
 			var childIdx:int = getFirstTextLineChildIndex(); // index where the first text line must appear at in its container  
 			var newIdx:int = 0;		// offset into newShapeChildren
 			var shapeChildrenStartIdx:int = 0;	// starting offset into shapeChildren
@@ -3096,11 +3175,14 @@ package flashx.textLayout.container
 			// beginning as usual. This can happen if we're scrolled forward, and then edit the first visible line.
 			if (_updateStart > absoluteStart && newShapeChildren.length > 0)
 			{
-				var firstTextLine:TextLine = newShapeChildren[0];
-				var firstLine:TextFlowLine = TextFlowLine(firstTextLine.userData);
+				var firstLine:TextFlowLine = TextFlowLine(newShapeChildren[0].userData);
 				var prevLine:TextFlowLine = flowComposer.findLineAtPosition(firstLine.absoluteStart - 1);
-				var prevTextLine:TextLine = prevLine.peekTextLine(); 
-				shapeChildrenStartIdx = _shapeChildren.indexOf(prevTextLine);
+				if(prevLine is TextFlowTableBlock){
+					shapeChildrenStartIdx = _shapeChildren.indexOf((prevLine as TextFlowTableBlock).container);
+				} else {
+					var prevTextLine:TextLine = prevLine.peekTextLine(); 
+					shapeChildrenStartIdx = _shapeChildren.indexOf(prevTextLine);
+				}
 				if (shapeChildrenStartIdx >= 0)
 				{
 					shapeChildrenStartIdx++;
@@ -3113,7 +3195,7 @@ package flashx.textLayout.container
 			
 			while (newIdx != newShapeChildren.length)
 			{
-				var newChild:TextLine = newShapeChildren[newIdx];
+				var newChild:* = newShapeChildren[newIdx];
 				if (newChild == _shapeChildren[oldIdx])
 				{
 					// Same shape is in both lists, no change necessary, advance to next item in each list
@@ -3123,21 +3205,38 @@ package flashx.textLayout.container
 					oldIdx++;
 					continue;
 				}
-				
 				var newChildIdx:int = _shapeChildren.indexOf(newChild);
-				if (newChildIdx == -1)
-				{
-					// Shape is in the new list, but not in the old list, add it to the display list at the current location, and advance to next item
-					addTextLine(newChild, childIdx++);
-					CONFIG::debug { Debugging.traceFTECall(null,_container,"addTextLine",newChild); }
-					newIdx++;
-				}
-				else
-				{
+				if(newChild is TextLine){
+					if (newChildIdx == -1)
+					{
+						// Shape is in the new list, but not in the old list, add it to the display list at the current location, and advance to next item
+						addTextLine((newChild as TextLine), childIdx++);
+						CONFIG::debug { Debugging.traceFTECall(null,_container,"addTextLine",newChild); }
+						newIdx++;
+					}
+					else
+					{
 						// The shape is on both lists, but there are several intervening "old" shapes in between. We'll remove the old shapes that
-					// come before the new one we want to insert.
-					removeAndRecycleTextLines (oldIdx, newChildIdx);
-					oldIdx = newChildIdx;
+						// come before the new one we want to insert.
+						removeAndRecycleTextLines (oldIdx, newChildIdx);
+						oldIdx = newChildIdx;
+					}
+				} else {// it's a table block
+					if (newChildIdx == -1)
+					{
+						// Shape is in the new list, but not in the old list, add it to the display list at the current location, and advance to next item
+						addTableBlock((newChild as TableBlockContainer), childIdx++);
+						CONFIG::debug { Debugging.traceFTECall(null,_container,"addTableBlock",newChild); }
+						newIdx++;
+					}
+					else
+					{
+						// The shape is on both lists, but there are several intervening "old" shapes in between. We'll remove the old shapes that
+						// come before the new one we want to insert.
+						(newChild as TableBlockContainer).userData.updateCompositionShapes();
+						removeAndRecycleTextLines (oldIdx, newChildIdx);
+						oldIdx = newChildIdx;
+					}					
 				}
 			}
 			
@@ -3989,6 +4088,12 @@ package flashx.textLayout.container
 			var textBlock:TextBlock;
 			for (var index:int = beginIndex; index < endIndex; index++)
 			{
+				// we don't recycle table blocks
+				if( !(_shapeChildren[index] is TextLine) ){
+					removeTableBlock(_shapeChildren[index]);
+					child = null;
+					continue;
+				}
 				child = _shapeChildren[index];					
 				removeTextLine(child);
 				CONFIG::debug { Debugging.traceFTECall(null,_container,"removeTextLine",child); }
@@ -4013,6 +4118,10 @@ package flashx.textLayout.container
 			{
 				while (beginIndex < endIndex)
 				{
+					if( !(_shapeChildren[beginIndex] is TextLine) ){
+						beginIndex++;
+						continue;
+					}
 					child = _shapeChildren[beginIndex++];
 										
 					// Recycle if its not displayed and not connected to the textblock
@@ -4069,6 +4178,10 @@ package flashx.textLayout.container
 				{
 					break;
 				}
+				
+				if(_container.getChildAt(firstTextLine) is TableBlockContainer)
+					break;
+				
 			}
 			return firstTextLine;
 		}
@@ -4121,6 +4234,54 @@ package flashx.textLayout.container
 		}
 		
 		/**
+		 * Adds a <code>TableBlockContainer</code> object as a descendant of <code>container</code>.
+		 * The default implementation of this method, which may be overriden, adds the object
+		 * as a direct child of <code>container</code> at the specified index.
+		 * 
+		 * @param textLine the <code>TableBlockContainer</code> object to add
+		 * @param index insertion index of the text line in its parent 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see #container
+		 * 
+		 */	
+		protected function addTableBlock(block:TableBlockContainer, index:int):void
+		{ 
+			if ( index > _container.numChildren )
+				index = _container.numChildren;
+			_container.addChildAt(block, index);
+			block.userData.updateCompositionShapes();
+		}
+		
+		/**
+		 * Removes a <code>TableBlockContainer</code> object from its parent. 
+		 * The default implementation of this method, which may be overriden, removes the object
+		 * from <code>container</code> if it is a direct child of the latter.
+		 * 
+		 * This method may be called even if the object is not a descendant of <code>container</code>.
+		 * Any implementation of this method must ensure that no action is taken in this case.
+		 * 
+		 * @param textLine the <code>TableBlockContainer</code> object to remove 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see #container
+		 * 
+		 */	
+
+		protected function removeTableBlock(block:TableBlockContainer):void
+		{
+			if (_container.contains(block))
+				_container.removeChild(block);
+		}
+
+		
+		/**
 		 * Adds a <code>flash.display.Shape</code> object on which background shapes (such as background color) are drawn.
 		 * The default implementation of this method, which may be overriden, adds the object to <code>container</code>
 		 * just before the first <code>flash.text.engine.TextLine</code> child, if one exists, and after the last exisiting
@@ -4586,6 +4747,13 @@ package flashx.textLayout.container
 			// bounds than the getBounds. I've left the old code here for verification.
 			CONFIG::debug { assert(textFlowLine != null,"testLineVisible"); }
 			
+			if(textFlowLine is TextFlowTableBlock)
+			{
+				if(textFlowLine.controller == this)
+					return TextFlowTableBlock(textFlowLine).container;
+				return null;
+			}
+			
 			//Bug #2988852, scrolling in the application causes all text to disappear. When auto-size images make the line "after visible"
 			//It's "after visible", but it cannot return 1. Because if it were 1, the binary-search in gatherVisibleLines() would make all the lines invisible.
 			if(textFlowLine.controller == null)
@@ -4653,6 +4821,10 @@ package flashx.textLayout.container
 			// about the children, and also the bounds of visible glyphs. We decided that the logical bounds is close enough,
 			// and is much faster to obtain. However, there may be some lines, that get a different result using the logical 
 			// bounds than the getBounds. I've left the old code here for verification.
+			
+			if(textFlowLine is TextFlowTableBlock)
+				return null;
+
 			if (!textFlowLine.hasLineBounds())
 			{
 				if (!textLine)
@@ -4727,7 +4899,47 @@ package flashx.textLayout.container
 			}
 			return boundsRect;
 		}
-		
+		/** @private */
+		tlf_internal function findCellAtPosition(point:Point):CellCoordinates
+		{
+			point = point.clone();
+			for each(var chld:Object in _shapeChildren)
+			{
+				if( !(chld is TableBlockContainer) )
+					continue;
+				
+				var block:TableBlockContainer = chld as TableBlockContainer;
+				if(block.y > point.y)
+					continue;
+				if(block.x > point.x)
+					continue;
+				if(block.y + block.height < point.y)
+					continue;
+				if(block.x + block.getTableWidth() < point.x)
+					continue;
+				
+				point.x -= block.x;
+				point.y -= block.y;
+				
+				// the point falls out inside the block. Find the cell...
+				var cells:Vector.<TableCellElement> = block.userData.getTableCells();
+				for each (var cell:TableCellElement in  cells)
+				{
+					if(cell.x + cell.width < point.x)
+						continue;
+					if(cell.y + cell.getRow().composedHeight < point.y)
+						continue;
+					if(cell.x > point.x)
+						continue;
+					if(cell.y > point.y)
+						continue;
+					return new CellCoordinates(cell.rowIndex,cell.colIndex,cell.getTable());
+					
+				}
+			}
+			
+			return null;
+		}
 		/** @private */
 		tlf_internal function getPlacedTextLineBounds(textLine:TextLine):Rectangle
 		{
@@ -4781,13 +4993,25 @@ package flashx.textLayout.container
 		{
 			_linesInView.push(textLine);			
 		}
-		
+
+		/** @private */
+		tlf_internal function addComposedTableBlock(block:TableBlockContainer):void
+		{
+			var idx:int = _tableBlocksInView.indexOf(block);
+			if(idx >= 0)
+				_tableBlocksInView.splice(idx,1);
+			else
+				_tableBlocksInView.push(block);
+		}
+
 		/** @private Return the array. Client code may add lines to the array. */
 		tlf_internal function get composedLines():Array
 		{
 			if (!_linesInView)
 				_linesInView = [];
-			return _linesInView;
+			var arr:Array = _linesInView.slice();
+			intersperseTableBlocks(arr);
+			return arr;
 		}
 		
 		/** @private Empty out the linesInView, starting from the supplied text index. */
@@ -4802,6 +5026,17 @@ package flashx.textLayout.container
 				index++;
 			}
 			_linesInView.length = index;
+			
+			index = 0;
+			for each (var tbc:TableBlockContainer in _tableBlocksInView)
+			{
+				var tftb:TextFlowTableBlock = tbc.userData;
+				if(tbc.userData.absoluteStart >= pos)
+					break;
+				index++;
+			}
+			_tableBlocksInView.length = index;
+			
 			_updateStart = Math.min(_updateStart, pos);
 		}
 		

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as b/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as
index 6b88cc2..9e0e105 100644
--- a/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as
+++ b/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as
@@ -22,6 +22,7 @@ package flashx.textLayout.conversion
 	import flash.utils.getQualifiedClassName;
 	
 	import flashx.textLayout.TextLayoutVersion;
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.debug.assert;
 	import flashx.textLayout.elements.Configuration;
 	import flashx.textLayout.elements.ContainerFormattedElement;
@@ -31,34 +32,35 @@ package flashx.textLayout.conversion
 	import flashx.textLayout.elements.LinkElement;
 	import flashx.textLayout.elements.ParagraphFormattedElement;
 	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TableCellElement;
+	import flashx.textLayout.elements.TableElement;
+	import flashx.textLayout.elements.TableRowElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.elements.TextRange;
 	import flashx.textLayout.formats.ITextLayoutFormat;
 	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.formats.WhiteSpaceCollapse;
 	import flashx.textLayout.property.Property;
-	import flashx.textLayout.tlf_internal;
+
 	use namespace tlf_internal;
 	
-	[ExcludeClass]
 	/** 
-	 * @private 
-	 * Export converter for TextLayout format. 
+	 * Base export converter for TextLayout format. 
 	 */
-	internal class BaseTextLayoutExporter extends ConverterBase implements ITextExporter
-	{	
-		private var _config:ImportExportConfiguration;
+	public class BaseTextLayoutExporter extends ConverterBase implements ITextExporter
+	{
 		private var _rootTag:XML;
 		private var _ns:Namespace;
-				
-		public function BaseTextLayoutExporter(ns:Namespace, rootTag:XML, config:ImportExportConfiguration)
+		
+		public function BaseTextLayoutExporter(ns:Namespace, rootTag:XML, configuration:ImportExportConfiguration)
 		{
-			_config = config;
+			config = configuration;
 			_ns = ns;
 			_rootTag = rootTag;
 		}
 		
-		/** @copy ITextExporter#export()
+		/** 
+		 * @copy ITextExporter#export()
 		 */
 		public function export(source:TextFlow, conversionType:String):Object
 		{
@@ -68,7 +70,9 @@ package flashx.textLayout.conversion
 			return conversionType == ConversionType.STRING_TYPE ? convertXMLToString(result) : result;
 		}
 		
-		/** Export text content of a TextFlow into XFL format.
+		/** 
+		 * Export text content of a TextFlow into XFL format.
+		 * 
 		 * @param source	the text to export
 		 * @return XML	the exported content
 		 */
@@ -89,7 +93,9 @@ package flashx.textLayout.conversion
 			return result;
 		}
 		
-		/** Export text content as a string
+		/** 
+		 * Export text content as a string
+		 * 
 		 * @param xml	the XML to convert
 		 * @return String	the exported content
 		 * @private
@@ -118,7 +124,9 @@ package flashx.textLayout.conversion
 		}
 
 	
-		/** Base functionality for exporting a FlowElement. 
+		/** 
+		 * Base functionality for exporting a FlowElement.
+		 *  
 		 * @param exporter	Root object for the export
 		 * @param flowElement	Element to export
 		 * @return XMLList	XML for the element
@@ -128,14 +136,16 @@ package flashx.textLayout.conversion
 			return exporter.exportFlowElement(flowElement);
 		}
 		
-		/** Overridable worker method for exporting a FlowElement. Creates the XMLList.
+		/** 
+		 * Overridable worker method for exporting a FlowElement. Creates the XMLList.
+		 * 
 		 * @param flowElement	Element to export
 		 * @return XMLList	XML for the element
 		 */
 		protected function exportFlowElement (flowElement:FlowElement):XMLList
 		{
 			var className:String = flash.utils.getQualifiedClassName(flowElement);
-			var elementName:String = _config.lookupName(className);	// NO PMD
+			var elementName:String = config.lookupName(className);	// NO PMD
 			var output:XML = <{elementName}/>;
 			output.setNamespace(_ns);
 			return XMLList(output);
@@ -199,8 +209,10 @@ package flashx.textLayout.conversion
 			}		
 		}  
 		
-		/** Base functionality for exporting a Span. Exports as a FlowElement,
+		/** 
+		 * Base functionality for exporting a Span. Exports as a FlowElement,
 		 * and exports the text of the span.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param span	Element to export
 		 * @return XMLList	XML for the element
@@ -214,7 +226,8 @@ package flashx.textLayout.conversion
 		
 		static private const brRegEx:RegExp = /\u2028/;
 		
-		/** Gets the regex that specifies characters in span text to be replaced with XML elements
+		/** 
+		 * Gets the regex that specifies characters in span text to be replaced with XML elements.
 		 *  Note: Each match is a single character 
 		 */
 		protected function get spanTextReplacementRegex():RegExp
@@ -222,7 +235,8 @@ package flashx.textLayout.conversion
 			return brRegEx;
 		}
 
-		/** Gets the xml element used to represent a character in the export format
+		/** 
+		 * Gets the xml element used to represent a character in the export format
 		 */
 		protected function getSpanTextReplacementXML(ch:String):XML
 		{
@@ -232,8 +246,10 @@ package flashx.textLayout.conversion
 			return breakXML;
 		}
 		
-		/** Base functionality for exporting a FlowGroupElement. Exports as a FlowElement,
+		/** 
+		 * Base functionality for exporting a FlowGroupElement. Exports as a FlowElement,
 		 * and exports the children of a element.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param flowBlockElement	Element to export
 		 * @return XMLList	XML for the element
@@ -241,20 +257,26 @@ package flashx.textLayout.conversion
 		static public function exportFlowGroupElement(exporter:BaseTextLayoutExporter, flowBlockElement:FlowGroupElement):XMLList
 		{
 			var output:XMLList = exportFlowElement(exporter, flowBlockElement);
+			var count:int = flowBlockElement.numChildren;
 			
 			// output each child
-			for(var childIter:int = 0; childIter < flowBlockElement.numChildren; ++childIter)
+			for(var index:int; index < count; ++index)
 			{
-				var flowChild:FlowElement = flowBlockElement.getChildAt(childIter);
+				var flowChild:FlowElement = flowBlockElement.getChildAt(index);
 				var childXML:XMLList = exporter.exportChild(flowChild);
-				if (childXML)
+				
+				if (childXML) {
 					output.appendChild(childXML);
+				}
 			}
+			
 			return output;
 		}
 
-		/** Base functionality for exporting a ParagraphFormattedElement. Exports as a FlowGroupElement,
+		/** 
+		 * Base functionality for exporting a ParagraphFormattedElement. Exports as a FlowGroupElement,
 		 * and exports paragraph attributes.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param flowParagraph	Element to export
 		 * @return XMLList	XML for the element
@@ -264,22 +286,6 @@ package flashx.textLayout.conversion
 			return exporter.exportParagraphFormattedElement(flowParagraph);
 		}
 		
-		/** Overridable worker method for exporting a ParagraphFormattedElement. Creates the XMLList.
-		 * @param flowElement	Element to export
-		 * @return XMLList	XML for the element
-		 */
-		protected function exportParagraphFormattedElement(flowElement:FlowElement):XMLList
-		{
-			var rslt:XMLList = exportFlowElement(flowElement);
-			// output each child
-			for(var childIter:int = 0; childIter < ParagraphFormattedElement(flowElement).numChildren; ++childIter)
-			{
-				var flowChild:FlowElement = ParagraphFormattedElement(flowElement).getChildAt(childIter);
-				rslt.appendChild(exportChild(flowChild));
-			}
-			return rslt;
-		}
-		
 		static public function exportList(exporter:BaseTextLayoutExporter, flowParagraph:ParagraphFormattedElement):XMLList
 		{
 			return exporter.exportList(flowParagraph);
@@ -287,14 +293,17 @@ package flashx.textLayout.conversion
 		
 		protected function exportList(flowElement:FlowElement):XMLList
 		{
-			var rslt:XMLList = exportFlowElement(flowElement);
+			var result:XMLList = exportFlowElement(flowElement);
+			var count:int = FlowGroupElement(flowElement).numChildren;
+			
 			// output each child
-			for(var childIter:int = 0; childIter < FlowGroupElement(flowElement).numChildren; ++childIter)
+			for(var index:int; index < count; ++index)
 			{
-				var flowChild:FlowElement = FlowGroupElement(flowElement).getChildAt(childIter);
-				rslt.appendChild(exportChild(flowChild));
+				var flowChild:FlowElement = FlowGroupElement(flowElement).getChildAt(index);
+				result.appendChild(exportChild(flowChild));
 			}
-			return rslt;
+			
+			return result;
 		}
 		
 		static public function exportListItem(exporter:BaseTextLayoutExporter, flowParagraph:ParagraphFormattedElement):XMLList
@@ -304,18 +313,23 @@ package flashx.textLayout.conversion
 		
 		protected function exportListItem(flowElement:FlowElement):XMLList
 		{
-			var rslt:XMLList = exportFlowElement(flowElement);
+			var result:XMLList = exportFlowElement(flowElement);
+			var count:int = FlowGroupElement(flowElement).numChildren;
+			
 			// output each child
-			for(var childIter:int = 0; childIter < FlowGroupElement(flowElement).numChildren; ++childIter)
+			for(var index:int; index < count; ++index)
 			{
-				var flowChild:FlowElement = FlowGroupElement(flowElement).getChildAt(childIter);
-				rslt.appendChild(exportChild(flowChild));
+				var flowChild:FlowElement = FlowGroupElement(flowElement).getChildAt(index);
+				result.appendChild(exportChild(flowChild));
 			}
-			return rslt;
+			
+			return result;
 		}
 		
-		/** Base functionality for exporting a ContainerFormattedElement. Exports as a ParagraphFormattedElement,
+		/** 
+		 * Base functionality for exporting a ContainerFormattedElement. Exports as a ParagraphFormattedElement,
 		 * and exports container attributes.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param container	Element to export
 		 * @return XMLList	XML for the element
@@ -325,7 +339,9 @@ package flashx.textLayout.conversion
 			return exporter.exportContainerFormattedElement(container);
 		}
 		
-		/** Overridable worker method for exporting a ParagraphFormattedElement. Creates the XMLList.
+		/** 
+		 * Overridable worker method for exporting a ParagraphFormattedElement. Creates the XMLList.
+		 * 
 		 * @param flowElement	Element to export
 		 * @return XMLList	XML for the element
 		 */
@@ -333,9 +349,126 @@ package flashx.textLayout.conversion
 		{
 			return exportParagraphFormattedElement(flowElement);
 		}
-
-		/** Base functionality for exporting a TextFlow. Exports as a ContainerElement,
+		
+		/** 
+		 * Base functionality for exporting a TableElement. Exports as a TableElement,
+		 * and exports table attributes.
+		 * 
+		 * @param exporter	Root object for the export
+		 * @param container	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTableElement(exporter:BaseTextLayoutExporter, table:TableElement):XMLList
+		{
+			return exporter.exportTableElement(table);
+		}
+		
+		/** 
+		 * Overridable worker method for exporting a TableElement. Creates the XMLList.
+		 * 
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		protected function exportTableElement(tableElement:TableElement):XMLList
+		{
+			var result:XMLList = exportFlowElement(tableElement);
+			var count:int = tableElement.numRows;
+			
+			// output each child
+			for(var index:int = 0; index < count; ++index)
+			{
+				var flowChild:FlowElement = tableElement.getRowAt(index);
+				result.appendChild(exportChild(flowChild));
+			}
+			
+			return result;
+		}
+		
+		/** 
+		 * Base functionality for exporting a TableRowElement. Exports as a TableRowElement,
+		 * and exports table row attributes.
+		 * 
+		 * @param exporter	Root object for the export
+		 * @param container	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTableRowElement(exporter:BaseTextLayoutExporter, tableRow:TableRowElement):XMLList
+		{
+			return exporter.exportTableRowElement(tableRow);
+		}
+		
+		/** 
+		 * Overridable worker method for exporting a TableRowElement. Creates the XMLList.
+		 * 
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		protected function exportTableRowElement(tableRowElement:TableRowElement):XMLList
+		{
+			var result:XMLList = exportFlowElement(tableRowElement);
+			var count:int = tableRowElement.numCells;
+			
+			// output each child
+			for(var index:int; index < count; ++index)
+			{
+				var flowChild:FlowElement = tableRowElement.getCellAt(index);
+				result.appendChild(exportChild(flowChild));
+			}
+			
+			return result;
+		}
+		
+		/** 
+		 * Base functionality for exporting a TableCellElement. Exports as a TableCellElement,
+		 * and exports table cell attributes.
+		 * 
+		 * @param exporter	Root object for the export
+		 * @param container	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTableCellElement(exporter:BaseTextLayoutExporter, tableCell:TableCellElement):XMLList
+		{
+			return exporter.exportTableCellElement(tableCell);
+		}
+		
+		/** 
+		 * Overridable worker method for exporting a TableCellElement. Creates the XMLList.
+		 * 
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		protected function exportTableCellElement(tableCellElement:TableCellElement):XMLList
+		{
+			var result:XMLList = exportFlowElement(tableCellElement);
+			
+			return result;
+		}
+		
+		/** 
+		 * Overridable worker method for exporting a ParagraphFormattedElement. Creates the XMLList.
+		 * 
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		protected function exportParagraphFormattedElement(flowElement:FlowElement):XMLList
+		{
+			var result:XMLList = exportFlowElement(flowElement);
+			var count:int = ParagraphFormattedElement(flowElement).numChildren;
+			
+			// output each child
+			for(var index:int; index < count; ++index)
+			{
+				var flowChild:FlowElement = ParagraphFormattedElement(flowElement).getChildAt(index);
+				result.appendChild(exportChild(flowChild));
+			}
+			
+			return result;
+		}
+		
+		/** 
+		 * Base functionality for exporting a TextFlow. Exports as a ContainerElement,
 		 * and exports container attributes.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param textFlow	Element to export
 		 * @return XMLList	XML for the element
@@ -344,8 +477,10 @@ package flashx.textLayout.conversion
 		{
 			var output:XMLList = exportContainerFormattedElement(exporter, textFlow);
 			
-			// TextLayout will use PRESERVE on output
-			output.@[TextLayoutFormat.whiteSpaceCollapseProperty.name] = WhiteSpaceCollapse.PRESERVE;
+			if (exporter.config.whiteSpaceCollapse) {
+				// TextLayout will use PRESERVE on output
+				output.@[TextLayoutFormat.whiteSpaceCollapseProperty.name] = exporter.config.whiteSpaceCollapse;
+			}
 			
 			// TextLayout adds version information
 			output.@["version"] = TextLayoutVersion.getVersionString(TextLayoutVersion.CURRENT_VERSION);
@@ -354,8 +489,10 @@ package flashx.textLayout.conversion
 		}
 
 
-		/** Exports the object. It will find the appropriate exporter and use it to 
+		/** 
+		 * Exports the object. It will find the appropriate exporter and use it to 
 		 * export the object.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param flowElement	Element to export
 		 * @return XMLList	XML for the flowElement
@@ -363,13 +500,15 @@ package flashx.textLayout.conversion
 		public function exportChild(flowElement:FlowElement):XMLList
 		{
 			var className:String = flash.utils.getQualifiedClassName(flowElement);
-			var info:FlowElementInfo = _config.lookupByClass(className);
+			var info:FlowElementInfo = config.lookupByClass(className);
 			if (info != null)
 				return info.exporter(this, flowElement);
 			return null;
 		}
 					
-		/** Helper function to export styles (core or user) in the form of xml attributes or xml children
+		/** 
+		 * Helper function to export styles (core or user) in the form of xml attributes or xml children.
+		 * 
 		 * @param xml object to which attributes/children are added 
 		 * @param sortableStyles an array of objects (xmlName,xmlVal) members that is sorted and exported.
 		 */
@@ -400,7 +539,6 @@ package flashx.textLayout.conversion
 		protected function get formatDescription():Object
 		{
 			return null;
-		}		
-
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as b/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as
index 21317b3..3eb6ac3 100644
--- a/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as
+++ b/textLayout/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as
@@ -21,6 +21,7 @@ package flashx.textLayout.conversion
 	import flash.system.System;
 	
 	import flashx.textLayout.TextLayoutVersion;
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.debug.assert;
 	import flashx.textLayout.elements.BreakElement;
 	import flashx.textLayout.elements.Configuration;
@@ -36,15 +37,15 @@ package flashx.textLayout.conversion
 	import flashx.textLayout.elements.ParagraphFormattedElement;
 	import flashx.textLayout.elements.SpanElement;
 	import flashx.textLayout.elements.TabElement;
+	import flashx.textLayout.elements.TableCellElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.property.Property;
-	import flashx.textLayout.tlf_internal;
+
 	use namespace tlf_internal;
 
-	[ExcludeClass]
 	/**
-	 * @private  
-	 * BaseTextLayoutImporter is a base class for handling the import/export of TextLayout text in the native format.
+	 * BaseTextLayoutImporter is a base class for handling the import/export of TextLayout text 
+	 * in the native format.
 	 */ 
 	internal class BaseTextLayoutImporter extends ConverterBase implements ITextImporter
 	{	
@@ -205,7 +206,9 @@ package flashx.textLayout.conversion
 			return importer.createTextFlowFromXML(xmlToParse, null);
 		}		
 		
-		/** Static method to parse the supplied XML into a paragrph. Parse the <p ...> tag and it's children.
+		/** 
+		 * Static method to parse the supplied XML into a paragrph. 
+		 * Parse the <p ...> tag and it's children.
 		 * 
 		 * @param importer	parser object
 		 * @param xmlToParse	content to parse
@@ -230,7 +233,8 @@ package flashx.textLayout.conversion
 			dst.id          = src.id;
 		}
 		
-		/** Static method for constructing a span from XML. Parse the <span> ... </span> tag. 
+		/** 
+		 * Static method for constructing a span from XML. Parse the <span> ... </span> tag. 
 		 * Insert the span into its parent
 		 * 
 		 * @param importer	parser object
@@ -296,7 +300,8 @@ package flashx.textLayout.conversion
 			}
 		}
 		
-		/** Static method for constructing a break element from XML. Validate the <br> ... </br> tag. 
+		/** 
+		 * Static method for constructing a break element from XML. Validate the <br> ... </br> tag. 
 		 * Use "\u2028" as the text; Insert the new element into its parent 
 		 * 
 		 * @param importer	parser object
@@ -308,9 +313,9 @@ package flashx.textLayout.conversion
 			var breakElem:BreakElement = importer.createBreakFromXML(xmlToParse);
 			importer.addChild(parent, breakElem);
 		}
-
 		
-		/** Static method for constructing a tab element from XML. Validate the <tab> ... </tab> tag. 
+		/** 
+		 * Static method for constructing a tab element from XML. Validate the <tab> ... </tab> tag. 
 		 * Use "\t" as the text; Insert the new element into its parent 
 		 * 
 		 * @param importer	parser object
@@ -323,7 +328,14 @@ package flashx.textLayout.conversion
 			if (tabElem)
 				importer.addChild(parent, tabElem);
 		}
-
+		
+		/** 
+		 * Static method for constructing a list element from XML. 
+		 * 
+		 * @param importer	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
 		static public function parseList(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
 		{
 			var listElem:ListElement = importer.createListFromXML(xmlToParse);
@@ -332,7 +344,14 @@ package flashx.textLayout.conversion
 				importer.parseFlowGroupElementChildren(xmlToParse, listElem);
 			}
 		}
-
+		
+		/** 
+		 * Static method for constructing a list item from XML. 
+		 * 
+		 * @param importer	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
 		static public function parseListItem(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
 		{
 			var listItem:ListItemElement = importer.createListItemFromXML(xmlToParse);
@@ -420,7 +439,9 @@ package flashx.textLayout.conversion
 			return workAttrs;
 		}	
 		
-		/** Parse XML and convert to  TextFlow.
+		/** 
+		 * Parse XML and convert to  TextFlow.
+		 * 
 		 * @param xmlToParse	content to parse
 		 * @param textFlow 		TextFlow we're parsing. If null, create or find a new TextFlow based on XML content
 		 * @return TextFlow	the new TextFlow created as a result of the parse
@@ -467,7 +488,9 @@ package flashx.textLayout.conversion
 			return new TabElement();
 		}
 		
-		/** Parse XML, convert to FlowElements and add to the parent.
+		/** 
+		 * Parse XML, convert to FlowElements and add to the parent.
+		 * 
 		 * @param xmlToParse	content to parse
 		 * @param parent 		the parent for the new content
 		 */
@@ -476,7 +499,9 @@ package flashx.textLayout.conversion
 			parseFlowGroupElementChildren(xmlToParse, parent);
 		}
 		
-		/** Parse XML, convert to FlowElements and add to the parent.
+		/** 
+		 * Parse XML, convert to FlowElements and add to the parent.
+		 * 
 		 * @param xmlToParse	content to parse
 		 * @param parent 		the parent for the new content
 		 * @param chainedParent whether parent actually corresponds to xmlToParse or has been chained (such as when xmlToParse is a formatting element) 
@@ -510,6 +535,54 @@ package flashx.textLayout.conversion
 				resetImpliedPara();
 		}
 		
+		/** 
+		 * Parse XML, convert XML to FlowElements and TextFlow and add to the parent table cell
+		 * 
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 * @param chainedParent whether parent actually corresponds to xmlToParse or has been chained (such as when xmlToParse is a formatting element) 
+		 */
+		public function parseTableCellElementChildren(xmlToParse:XML, parent:FlowGroupElement, exceptionElements:Object = null, chainedParent:Boolean=false):void
+		{
+			var textFlow:TextFlow;
+			
+			for each (var child:XML in xmlToParse.children())
+			{
+				if (child.nodeKind() == "element")
+				{
+					if (child.name().localName=="p") {
+						textFlow = new TextFlow();
+						parseObject(child.name().localName, child, textFlow, exceptionElements);
+					}
+					else if (child.name().localName=="TextFlow") {
+						TableCellElement(parent).textFlow = createTextFlowFromXML(child);
+					}
+				}
+					// look for mixed content here
+				else if (child.nodeKind() == "text") 
+				{
+					var txt:String = child.toString();
+					// Strip whitespace-only text appearing as a child of a container-formatted element
+					var strip:Boolean = false;
+					if (parent is ContainerFormattedElement)
+					{
+						strip = txt.search(anyPrintChar) == -1;
+					}
+					
+					if (!strip) {
+						textFlow = new TextFlow();
+						parseObject(child.name().localName, child, textFlow, exceptionElements);
+						//addChild(textFlow, createImpliedSpan(txt));
+					}
+				}
+				
+				if (textFlow) {
+					TableCellElement(parent).textFlow = textFlow;
+					textFlow = null;
+				}
+			}
+		}
+		
 		/** create an implied span with specified text */
 		public function createImpliedSpan(text:String):SpanElement
 		{

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/conversion/ConverterBase.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/conversion/ConverterBase.as b/textLayout/src/flashx/textLayout/conversion/ConverterBase.as
index de22970..6924d21 100644
--- a/textLayout/src/flashx/textLayout/conversion/ConverterBase.as
+++ b/textLayout/src/flashx/textLayout/conversion/ConverterBase.as
@@ -34,6 +34,7 @@ package flashx.textLayout.conversion
 		private var _errors:Vector.<String> = null;
 		private var _throwOnError:Boolean = false;
 		private var _useClipboardAnnotations:Boolean = false;
+		private var _config:ImportExportConfiguration;
 
 		/** A converter that converts clipboard data into a TextFlow should use the MERGE_TO_NEXT_ON_PASTE property
 		 * to control how the elements are treated when they are merged into an existing TextFlow on paste. This is useful
@@ -111,5 +112,19 @@ package flashx.textLayout.conversion
 			_useClipboardAnnotations = value;
 		}
 		
+		/**
+		 * Returns the import and export configuration. 
+		 **/
+		public function get config():ImportExportConfiguration {
+			return _config;
+		}
+		
+		/**
+		 * @private
+		 **/
+		public function set config(value:ImportExportConfiguration):void {
+			_config = value;
+		}
+		
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/conversion/ITextExporter.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/conversion/ITextExporter.as b/textLayout/src/flashx/textLayout/conversion/ITextExporter.as
index 8b3a955..fc10128 100644
--- a/textLayout/src/flashx/textLayout/conversion/ITextExporter.as
+++ b/textLayout/src/flashx/textLayout/conversion/ITextExporter.as
@@ -94,6 +94,12 @@ package flashx.textLayout.conversion
 		 * @langversion 3.0
 		 */
 		function get useClipboardAnnotations():Boolean;
-		function set useClipboardAnnotations(value:Boolean):void;		
+		function set useClipboardAnnotations(value:Boolean):void;
+		
+		/**
+		 * Accesses the config options for the exporter. 
+		 **/
+		function get config():ImportExportConfiguration;
+		function set config(value:ImportExportConfiguration):void;		
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/conversion/ImportExportConfiguration.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/conversion/ImportExportConfiguration.as b/textLayout/src/flashx/textLayout/conversion/ImportExportConfiguration.as
index 3406284..b9c996c 100644
--- a/textLayout/src/flashx/textLayout/conversion/ImportExportConfiguration.as
+++ b/textLayout/src/flashx/textLayout/conversion/ImportExportConfiguration.as
@@ -18,13 +18,16 @@
 ////////////////////////////////////////////////////////////////////////////////
 package flashx.textLayout.conversion
 {
-	import flashx.textLayout.debug.assert;
 	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.WhiteSpaceCollapse;
+
 	use namespace tlf_internal;
 
-	[ExcludeClass]
-	/** Configure for import/export of standard components.
-	 * Configures the import/export package so it can export all the standard FlowElements. 
+	/** 
+	 * Configure for import/export of standard components.
+	 * Configures the import/export package so it can export all the standard FlowElements.
+	 *  
 	 * @see flashx.textLayout.elements.Configuration
 	 * @playerversion Flash 10
 	 * @playerversion AIR 1.5
@@ -32,12 +35,22 @@ package flashx.textLayout.conversion
 	 */
 	public class ImportExportConfiguration 
 	{
-		/** array of FlowElementInfo objects (key = name, value = FlowElementInfo) */	
+		/** 
+		 * array of FlowElementInfo objects (key = name, value = FlowElementInfo) 
+		 * */	
 		tlf_internal var flowElementInfoList:Object = {};	
 		tlf_internal var flowElementClassList:Object= {};	
 		tlf_internal var classToNameMap:Object = {};
+		
+		/**
+		 * Whitespace collapse export setting
+		 * @default WhiteSpaceCollapse.PRESERVE
+		 **/
+		public var whiteSpaceCollapse:String = WhiteSpaceCollapse.PRESERVE;
 
-		/** Constructor.
+		/** 
+		 * Constructor.
+		 * 
 		* @playerversion Flash 10
 		* @playerversion AIR 1.5
 	 	* @langversion 3.0
@@ -46,8 +59,10 @@ package flashx.textLayout.conversion
 		{
 		}
 		
-		/** Add a parser for a new FlowElement type. This allows FlowElements to be added from outside the main system,
+		/** 
+		 * Add a parser for a new FlowElement type. This allows FlowElements to be added from outside the main system,
 		 * and still have the main system be able to import them from XML.
+		 * 
 		 * @param name		the name of the FlowElement class, as it appear in the XML
 		 * @param flowClass	the class of the FlowElement
 		 * @param parser	function fpr importing the XML into a FlowElement
@@ -71,7 +86,9 @@ package flashx.textLayout.conversion
 				classToNameMap[info.flowClassName] = name;
 		}
 		
-		/** Return the information being held about the FlowElement, as a FlowElementInfo.
+		/** 
+		 * Return the information being held about the FlowElement, as a FlowElementInfo.
+		 * 
 		 * @param name				the name of the FlowElement class, as it appears in the XML
 		 * @return FlowElementInfo	the information being held, as it was supplied to addParseInfo
 		 * @private
@@ -81,7 +98,9 @@ package flashx.textLayout.conversion
 			return flowElementInfoList[name];
 		}
 
-		/** Return the element name for the class
+		/** 
+		 * Return the element name for the class
+		 * 
 		 * @param classToMatch		fully qualified class name of the FlowElement
 		 * @return name				export name to use for class
 		 * @private
@@ -91,7 +110,9 @@ package flashx.textLayout.conversion
 			return classToNameMap[classToMatch];
 		}
 
-		/** Return the information being held about the FlowElement, as a FlowElementInfo.
+		/** 
+		 * Return the information being held about the FlowElement, as a FlowElementInfo.
+		 * 
 		 * @param classToMatch		fully qualified class name of the FlowElement
 		 * @return FlowElementInfo	the information being held, as it was supplied to addParseInfo
 		 * @private

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/conversion/TextLayoutExporter.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/conversion/TextLayoutExporter.as b/textLayout/src/flashx/textLayout/conversion/TextLayoutExporter.as
index 4965993..d4649ba 100644
--- a/textLayout/src/flashx/textLayout/conversion/TextLayoutExporter.as
+++ b/textLayout/src/flashx/textLayout/conversion/TextLayoutExporter.as
@@ -20,6 +20,7 @@ package flashx.textLayout.conversion
 {
 	import flash.utils.Dictionary;
 	
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.debug.assert;
 	import flashx.textLayout.elements.ContainerFormattedElement;
 	import flashx.textLayout.elements.DivElement;
@@ -33,6 +34,9 @@ package flashx.textLayout.conversion
 	import flashx.textLayout.elements.SpanElement;
 	import flashx.textLayout.elements.SubParagraphGroupElement;
 	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.TableElement;
+	import flashx.textLayout.elements.TableCellElement;
+	import flashx.textLayout.elements.TableRowElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.formats.FormatValue;
 	import flashx.textLayout.formats.ITextLayoutFormat;
@@ -40,13 +44,10 @@ package flashx.textLayout.conversion
 	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.formats.WhiteSpaceCollapse;
 	import flashx.textLayout.property.Property;
-	import flashx.textLayout.tlf_internal;
 	
 	use namespace tlf_internal;
 	
-	[ExcludeClass]
 	/** 
-	 * @private
 	 * Export filter for TextLayout format. 
 	 */
 	internal class TextLayoutExporter extends BaseTextLayoutExporter
@@ -87,8 +88,9 @@ package flashx.textLayout.conversion
 			return replacementXML;	
 		}
 		
-		/** Helper function to export styles (core or user) in the form of xml attributes or xml children
-		 * @private
+		/** 
+		 * Helper function to export styles (core or user) in the form of xml attributes or xml children
+		 * 
 		 */
 		tlf_internal function createStylesFromDescription(styles:Object, description:Object, includeUserStyles:Boolean, exclusions:Array):Array
 		{
@@ -170,7 +172,7 @@ package flashx.textLayout.conversion
 				exportStyles(rslt, sortableStyles );
 			}
 			
-			// export id and styleName
+			// export id and typeName
 			if (flowElement.id != null)
 				rslt.@["id"] = flowElement.id;
 			if (flowElement.typeName != flowElement.defaultTypeName)
@@ -179,8 +181,10 @@ package flashx.textLayout.conversion
 			return rslt;
 		}
 
-		/** Base functionality for exporting an Image. Exports as a FlowElement,
+		/** 
+		 * Base functionality for exporting an Image. Exports as a FlowElement,
 		 * and exports image properties.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param image	Element to export
 		 * @return XMLList	XML for the element
@@ -203,8 +207,10 @@ package flashx.textLayout.conversion
 			return output;
 		}
 
-		/** Base functionality for exporting a LinkElement. Exports as a FlowGroupElement,
+		/** 
+		 * Base functionality for exporting a LinkElement. Exports as a FlowGroupElement,
 		 * and exports link properties.
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param link	Element to export
 		 * @return XMLList	XML for the element
@@ -222,7 +228,9 @@ package flashx.textLayout.conversion
 			return output;
 		}
 		
-		/** Base functionality for exporting a DivElement. Exports as a FlowContainerFormattedElement
+		/** 
+		 * Base functionality for exporting a DivElement. Exports as a FlowContainerFormattedElement
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param div	Element to export
 		 * @return XMLList	XML for the element
@@ -232,7 +240,9 @@ package flashx.textLayout.conversion
 			return exportContainerFormattedElement(exporter, div);
 		}
 		
-		/** Base functionality for exporting a SubParagraphGroupElement. Exports as a FlowGroupElement
+		/** 
+		 * Base functionality for exporting a SubParagraphGroupElement. Exports as a FlowGroupElement
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param elem	Element to export
 		 * @return XMLList	XML for the element
@@ -241,7 +251,9 @@ package flashx.textLayout.conversion
 		{
 			return exportFlowGroupElement(exporter, elem);
 		}
-		/** Base functionality for exporting a TCYElement. Exports as a FlowGroupElement
+		/** 
+		 * Base functionality for exporting a TCYElement. Exports as a FlowGroupElement
+		 * 
 		 * @param exporter	Root object for the export
 		 * @param tcy	Element to export
 		 * @return XMLList	XML for the element
@@ -251,6 +263,42 @@ package flashx.textLayout.conversion
 			return exportFlowGroupElement(exporter, tcy);
 		}
 		
+		/** 
+		 * Base functionality for exporting a TableElement. 
+		 * 
+		 * @param exporter	Root object for the export
+		 * @param table	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTable(exporter:BaseTextLayoutExporter, table:TableElement):XMLList
+		{
+			return exportTableElement(exporter, table);
+		}
+		
+		/** 
+		 * Base functionality for exporting a TableRowElement. 
+		 * 
+		 * @param exporter	Root object for the export
+		 * @param table	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTableRow(exporter:BaseTextLayoutExporter, tableRow:TableRowElement):XMLList
+		{
+			return exportTableRowElement(exporter, tableRow);
+		}
+		
+		/** 
+		 * Base functionality for exporting a TableCellElement. 
+		 * 
+		 * @param exporter	Root object for the export
+		 * @param table	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTableCell(exporter:BaseTextLayoutExporter, tableCell:TableCellElement):XMLList
+		{
+			return exportTableCellElement(exporter, tableCell);
+		}
+		
 		override protected function get formatDescription():Object
 		{
 			return _formatDescription;

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/conversion/TextLayoutImporter.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/conversion/TextLayoutImporter.as b/textLayout/src/flashx/textLayout/conversion/TextLayoutImporter.as
index 9ebc61c..2cc9793 100644
--- a/textLayout/src/flashx/textLayout/conversion/TextLayoutImporter.as
+++ b/textLayout/src/flashx/textLayout/conversion/TextLayoutImporter.as
@@ -17,15 +17,19 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 package flashx.textLayout.conversion 
-{	
+{
 	import flash.display.Shape;
 	import flash.text.engine.TextRotation;
 	import flash.utils.Dictionary;
 	
 	import flashx.textLayout.TextLayoutVersion;
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.EditManager;
+	import flashx.textLayout.edit.SelectionManager;
 	import flashx.textLayout.elements.BreakElement;
+	import flashx.textLayout.elements.ContainerFormattedElement;
 	import flashx.textLayout.elements.DivElement;
 	import flashx.textLayout.elements.FlowElement;
 	import flashx.textLayout.elements.FlowGroupElement;
@@ -40,16 +44,18 @@ package flashx.textLayout.conversion
 	import flashx.textLayout.elements.SubParagraphGroupElement;
 	import flashx.textLayout.elements.TCYElement;
 	import flashx.textLayout.elements.TabElement;
+	import flashx.textLayout.elements.TableCellElement;
+	import flashx.textLayout.elements.TableColElement;
+	import flashx.textLayout.elements.TableElement;
+	import flashx.textLayout.elements.TableRowElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.formats.ITextLayoutFormat;
 	import flashx.textLayout.formats.ListMarkerFormat;
 	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.property.Property;
-	import flashx.textLayout.tlf_internal;
 	
 	use namespace tlf_internal;
 
-	[ExcludeClass]
 	/** 
 	 * @private
 	 * TextLayoutImporter converts from XML to TextLayout data structures and back.
@@ -82,6 +88,10 @@ package flashx.textLayout.conversion
 				_defaultConfiguration.addIEInfo("a", LinkElement,            TextLayoutImporter.parseLink, 			TextLayoutExporter.exportLink);
 	 			_defaultConfiguration.addIEInfo("div", DivElement,           TextLayoutImporter.parseDivElement, 	TextLayoutExporter.exportDiv);
 				_defaultConfiguration.addIEInfo("img", InlineGraphicElement, TextLayoutImporter.parseInlineGraphic, TextLayoutExporter.exportImage);	
+				_defaultConfiguration.addIEInfo("table", TableElement, 		 TextLayoutImporter.parseTable,     	TextLayoutExporter.exportTable);	
+				_defaultConfiguration.addIEInfo("tr", TableRowElement, 	     TextLayoutImporter.parseTableRow,	    TextLayoutExporter.exportTableRow);	
+				_defaultConfiguration.addIEInfo("th", TableCellElement, 	 TextLayoutImporter.parseTableCell,  	TextLayoutExporter.exportTableCell);	
+				_defaultConfiguration.addIEInfo("td", TableCellElement, 	 TextLayoutImporter.parseTableCell,  	TextLayoutExporter.exportTableCell);	
 				
 				// validate the defaultTypeName values.  They are to match the TLF format export xml names
 				CONFIG::debug 
@@ -251,6 +261,48 @@ package flashx.textLayout.conversion
 			return divElem;
 		}
 		
+		/**
+		 * Create a table element from XML
+		 **/
+		public function createTableFromXML(xmlToParse:XML):TableElement
+		{
+			// add the table element to the parent
+			var tableElement:TableElement = new TableElement();
+			
+			parseStandardFlowElementAttributes(tableElement, xmlToParse);
+
+			return tableElement;
+		}
+		
+		/**
+		 * Create a table row element from XML
+		 **/
+		public function createTableRowFromXML(xmlToParse:XML):TableRowElement
+		{
+			// add the table row element to the parent
+			var tableRowElement:TableRowElement = new TableRowElement();
+			
+			parseStandardFlowElementAttributes(tableRowElement, xmlToParse);
+			
+			return tableRowElement;
+		}
+		
+		/**
+		 * Create a table cell element from XML
+		 **/
+		public function createTableCellFromXML(xmlToParse:XML):TableCellElement
+		{
+			// add the table cell element to the parent
+			var tableCellElement:TableCellElement = new TableCellElement();
+			
+			parseStandardFlowElementAttributes(tableCellElement, xmlToParse);
+			
+			return tableCellElement;
+		}
+		
+		/**
+		 * Create a paragraph element from XML
+		 **/
 		public override function createParagraphFromXML(xmlToParse:XML):ParagraphElement
 		{
 			var paraElem:ParagraphElement = new ParagraphElement();
@@ -258,6 +310,9 @@ package flashx.textLayout.conversion
 			return paraElem;
 		}
 		
+		/**
+		 * Create a sub paragraph group element from XML
+		 **/
 		public function createSubParagraphGroupFromXML(xmlToParse:XML):SubParagraphGroupElement
 		{
 			var elem:SubParagraphGroupElement = new SubParagraphGroupElement();
@@ -265,6 +320,9 @@ package flashx.textLayout.conversion
 			return elem;
 		}
 		
+		/**
+		 * Create a tate chu yoko element from XML
+		 **/
 		public function createTCYFromXML(xmlToParse:XML):TCYElement
 		{
 			var tcyElem:TCYElement = new TCYElement();
@@ -272,7 +330,7 @@ package flashx.textLayout.conversion
 			return tcyElem;
 		}
 		
-			
+		
 		static internal const _linkDescription:Object = {
 			href : Property.NewStringProperty("href",null, false, null),
 			target : Property.NewStringProperty("target",null, false, null)
@@ -280,7 +338,8 @@ package flashx.textLayout.conversion
 		static private const _linkFormatImporter:TLFormatImporter = new TLFormatImporter(Dictionary,_linkDescription);
 		static private const _linkElementFormatImporters:Array = [ _linkFormatImporter, _formatImporter,_idImporter,_typeNameImporter,_customFormatImporter ];
 
-		/** Parse a LinkElement Block.
+		/** 
+		 * Parse a LinkElement Block.
 		 * 
 		 * @param - importFilter:BaseTextLayoutImporter - parser object
 		 * @param - xmlToParse:XML - the xml describing the Link
@@ -300,6 +359,9 @@ package flashx.textLayout.conversion
 			return linkElem;
 		}
 		
+		/**
+		 * Create a span element from XML
+		 **/
 		public override function createSpanFromXML(xmlToParse:XML):SpanElement
 		{
 			var spanElem:SpanElement = new SpanElement();
@@ -319,6 +381,9 @@ package flashx.textLayout.conversion
 		static private const _ilgFormatImporter:TLFormatImporter = new TLFormatImporter(Dictionary,_imageDescription);
 		static private const _ilgElementFormatImporters:Array = [ _ilgFormatImporter, _formatImporter, _idImporter, _typeNameImporter, _customFormatImporter ];
 
+		/**
+		 * Create an inline graphic from XML
+		 **/
 		public function createInlineGraphicFromXML(xmlToParse:XML):InlineGraphicElement
 		{				
 			var imgElem:InlineGraphicElement = new InlineGraphicElement();
@@ -341,6 +406,9 @@ package flashx.textLayout.conversion
 			return imgElem;
 		}
 	
+		/**
+		 * Create a list element from XML
+		 **/
 		public override function createListFromXML(xmlToParse:XML):ListElement
 		{
 			var rslt:ListElement = new ListElement;
@@ -348,6 +416,9 @@ package flashx.textLayout.conversion
 			return rslt;
 		}
 
+		/**
+		 * Create a list item element from XML
+		 **/
 		public override function createListItemFromXML(xmlToParse:XML):ListItemElement
 		{
 			var rslt:ListItemElement = new ListItemElement;
@@ -355,12 +426,16 @@ package flashx.textLayout.conversion
 			return rslt;
 		}
 		
+		/**
+		 * Extract text format attributes
+		 **/
 		public function extractTextFormatAttributesHelper(curAttrs:Object, importer:TLFormatImporter):Object
 		{
 			return extractAttributesHelper(curAttrs,importer);
 		}
 		
-		/** Parse an SPGE element
+		/** 
+		 * Parse an SPGE element
 		 * 
 		 * @param - importFilter:BaseTextLayoutImporter - parser object
 		 * @param - xmlToParse:XML - the xml describing the TCY Block
@@ -379,7 +454,8 @@ package flashx.textLayout.conversion
 			}
 		}
 
-		/** Parse a TCY Block.
+		/** 
+		 * Parse a TCY Block.
 		 * 
 		 * @param - importFilter:BaseTextLayoutImporter - parser object
 		 * @param - xmlToParse:XML - the xml describing the TCY Block
@@ -399,7 +475,8 @@ package flashx.textLayout.conversion
 		}
 		
 				
-		/** Parse a LinkElement Block.
+		/** 
+		 * Parse a LinkElement Block.
 		 * 
 		 * @param - importFilter:BaseTextLayoutImporter - parser object
 		 * @param - xmlToParse:XML - the xml describing the Link
@@ -456,7 +533,8 @@ package flashx.textLayout.conversion
 		static public function parseListMarkerFormat(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
 		{ parent.listMarkerFormat = TextLayoutImporter(importFilter).createListMarkerFormatDictionaryFromXML(xmlToParse); }
 
-		/** Parse the <div ...> tag and all its children
+		/** 
+		 * Parse the <div ...> tag and all its children
 		 * 
 		 * @param - importFilter:BaseTextLayoutImportFilter - parser object
 		 * @param - xmlToParse:XML - the xml describing the Div
@@ -474,7 +552,8 @@ package flashx.textLayout.conversion
 			}
 		}
 
-		/** Parse a leaf element, the <img ...>  tag.
+		/** 
+		 * Parse a leaf element, the <img ...>  tag.
 		 * 
 		 * @param - importFilter:BaseTextLayoutImporter - parser object
 		 * @param - xmlToParse:XML - the xml describing the InlineGraphic FlowElement
@@ -485,6 +564,115 @@ package flashx.textLayout.conversion
 			var ilg:InlineGraphicElement = TextLayoutImporter(importFilter).createInlineGraphicFromXML(xmlToParse);
 			importFilter.addChild(parent, ilg);
 		}
+		
+		/** 
+		 * Parse the <table ...> tag and all its children
+		 * 
+		 * @param - importFilter:BaseTextLayoutImportFilter - parser object
+		 * @param - xmlToParse:XML - the xml describing the Table
+		 * @param - parent:FlowBlockElement - the parent of the new Table
+		 */
+		static public function parseTable(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var tableElement:TableElement = TextLayoutImporter(importFilter).createTableFromXML(xmlToParse);
+			
+			if (importFilter.addChild(parent, tableElement)) 
+			{
+				importFilter.parseFlowGroupElementChildren(xmlToParse, tableElement);
+				
+			}
+		}
+		
+		/** 
+		 * Parse the <tr ...> tag (TableRowElement) and all its children
+		 * 
+		 * @param - importFilter:BaseTextLayoutImportFilter - parser object
+		 * @param - xmlToParse:XML - the xml describing the Table
+		 * @param - parent:FlowBlockElement - the parent of the new Table
+		 */
+		static public function parseTableRow(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var tableRowElement:TableRowElement = TextLayoutImporter(importFilter).createTableRowFromXML(xmlToParse);
+			var table:TableElement;
+			
+			if (importFilter.addChild(parent, tableRowElement))
+			{
+				
+				importFilter.parseFlowGroupElementChildren(xmlToParse, tableRowElement);
+				
+				table = tableRowElement.getTable();
+				
+				var columnCount:int = tableRowElement.getColumnCount();
+				
+				if (table.numColumns<columnCount) {
+					table.numColumns = columnCount;
+				}
+				
+				table.insertRow(tableRowElement, tableRowElement.mxmlChildren);
+				
+			}
+		}
+		
+		/** 
+		 * Parse the <td ...> or <th ...> tag (TableCellElement) and all its children
+		 * 
+		 * @param - importFilter:BaseTextLayoutImportFilter - parser object
+		 * @param - xmlToParse:XML - the xml describing the Table
+		 * @param - parent:FlowBlockElement - the parent of the new Table
+		 */
+		static public function parseTableCell(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var tableCellElement:TableCellElement = TextLayoutImporter(importFilter).createTableCellFromXML(xmlToParse);
+			
+			if (importFilter.addChild(parent, tableCellElement))
+			{
+				importFilter.parseTableCellElementChildren(xmlToParse, tableCellElement);
+			}
+			
+			//tableCellElement.textFlow = getTextFlowContent("test cell");
+			
+			TableRowElement(parent).addCell(tableCellElement);
+			//TableRowElement(parent).getTable().addChild(tableCellElement);
+			//importFilter.parseFlowGroupElementChildren(xmlToParse, tableCellElement);
+			
+			// we can't have a <td> tag w/no children... so, add an empty text flow
+			//if (tableCellElement.numChildren == 0) {
+			//	tableCellElement.addChild(new TextFlow());
+			//}
+				
+		}
+		
+		/**
+		 * Creates default text flow from the text value passed in. Used for table cell text flows. 
+		 * Used for testing. May be removed in the future. 
+		 **/
+		static public function getTextFlowContent(text:String = null, selectable:Boolean = false, editable:Boolean = false):TextFlow {
+			var textFlowContent:TextFlow = new TextFlow();
+			var paragraph:ParagraphElement = new ParagraphElement();
+			var span:SpanElement = new SpanElement();
+			
+			if (text) {
+				span.text = text;
+			}
+			else {
+				span.text = "";
+			}
+			
+			paragraph.backgroundAlpha = 0.2;
+			paragraph.backgroundColor = 0xFF0000;
+			paragraph.addChild(span);
+			
+			if (editable) {
+				//textFlowContent.interactionManager = new EditManager(new UndoManager);
+			}
+			else if (selectable) {
+				//textFlowContent.interactionManager = new SelectionManager();
+			}
+			
+			textFlowContent.addChild(paragraph);
+			
+			return textFlowContent;
+		}
 	}
 }
 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/EditManager.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/EditManager.as b/textLayout/src/flashx/textLayout/edit/EditManager.as
index 2b46e72..28a45c6 100644
--- a/textLayout/src/flashx/textLayout/edit/EditManager.as
+++ b/textLayout/src/flashx/textLayout/edit/EditManager.as
@@ -35,6 +35,7 @@ package flashx.textLayout.edit
 	import flash.ui.Keyboard;
 	import flash.utils.getQualifiedClassName;
 	
+	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.compose.IFlowComposer;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.debug.Debugging;
@@ -52,11 +53,12 @@ package flashx.textLayout.edit
 	import flashx.textLayout.elements.ParagraphElement;
 	import flashx.textLayout.elements.SubParagraphGroupElement;
 	import flashx.textLayout.elements.TCYElement;
-	import flashx.textLayout.elements.TableDataCellElement;
+	import flashx.textLayout.elements.TableCellElement;
 	import flashx.textLayout.elements.TableElement;
 	import flashx.textLayout.elements.TextFlow;
 	import flashx.textLayout.elements.TextRange;
 	import flashx.textLayout.events.FlowOperationEvent;
+	import flashx.textLayout.events.ModelChange;
 	import flashx.textLayout.formats.IListMarkerFormat;
 	import flashx.textLayout.formats.ITextLayoutFormat;
 	import flashx.textLayout.formats.TextLayoutFormat;
@@ -85,7 +87,6 @@ package flashx.textLayout.edit
 	import flashx.textLayout.operations.SplitElementOperation;
 	import flashx.textLayout.operations.SplitParagraphOperation;
 	import flashx.textLayout.operations.UndoOperation;
-	import flashx.textLayout.tlf_internal;
 	import flashx.textLayout.utils.CharacterUtil;
 	import flashx.textLayout.utils.GeometryUtil;
 	import flashx.textLayout.utils.NavigationUtil;
@@ -466,6 +467,23 @@ package flashx.textLayout.edit
 								doOperation(new CreateListOperation(new SelectionState(textFlow, element.getAbsoluteStart(), element.getAbsoluteStart() + element.textLength), listItem.parent));
 							}
 						}
+						else if (textFlow.nestedInTable()) {
+							var cell:TableCellElement;
+							
+							if (event.shiftKey) {
+								cell = (textFlow.parentElement as TableCellElement).getPreviousCell();
+							}
+							else {
+								cell = (textFlow.parentElement as TableCellElement).getNextCell();
+							}
+							
+							// select next cell in table
+							if (cell && cell.textFlow && cell.textFlow.interactionManager is EditManager) {
+								//cell.textFlow.interactionManager.selectLastPosition();
+								cell.textFlow.interactionManager.selectAll();
+								cell.textFlow.interactionManager.setFocus();
+							}
+						}
 						else
 						{
 							overwriteMode ? overwriteText(String.fromCharCode(event.charCode)) : insertText(String.fromCharCode(event.charCode));
@@ -829,8 +847,19 @@ package flashx.textLayout.edit
 				redrawListener = null;
 			}
 
+			var cellHeight:Number = 0;
 			if (textFlow.flowComposer)
 			{
+				if(superManager && superManager is IEditManager)
+				{
+					var controller:ContainerController = textFlow.flowComposer.getControllerAt(0);
+					if (controller)
+					{
+						cellHeight = controller.container.height;
+					}
+				}
+
+
 				 textFlow.flowComposer.updateAllControllers(); 
 
 				// Scroll to selection
@@ -840,6 +869,18 @@ package flashx.textLayout.edit
 					if (controllerIndex >= 0)
 						textFlow.flowComposer.getControllerAt(controllerIndex).scrollToRange(activePosition,anchorPosition);	
 				}
+				if(superManager && superManager is IEditManager)
+				{
+					if(controller.container.height != cellHeight)
+					{
+						var setFormat:String = selectionFormatState;
+						var table:TableElement = (textFlow.parentElement as TableCellElement).getTable();
+						table.modelChanged(ModelChange.ELEMENT_MODIFIED, table, 0, table.textLength);
+						(superManager as IEditManager).updateAllControllers();
+						if(setFormat == SelectionFormatState.FOCUSED)
+							setFocus();
+					}
+				}
 			}
 
 			selectionChanged(true, false);
@@ -1259,12 +1300,14 @@ package flashx.textLayout.edit
 			if (!operationState)
 				return;
 
+			/*
+			This should not be necessary...
 			// mjzhang : fix for table
 			var leaf:FlowLeafElement = textFlow.findLeaf(operationState.absoluteStart);
 			var para:ParagraphElement = leaf.getParagraph();
 			if ( para.isInTable() )
 				return;
-			
+			*/
 			// Delete the next character if it's a caret selection, and allow adejacent delete next's to merge
 			// If it's a range selection, delete the range and disallow merge
 			var deleteOp:DeleteTextOperation;
@@ -1369,10 +1412,12 @@ package flashx.textLayout.edit
 				}
 				if(movePara)
 				{
+					/*
+					should not be necessary...
 					// mjzhang: fix for table feature
 					if ( para.isInTable() )
 						return;
-					
+					*/
 					var source:FlowGroupElement;
 					var target:FlowGroupElement;
 					var numElementsToMove:int;

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/ISelectionManager.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/ISelectionManager.as b/textLayout/src/flashx/textLayout/edit/ISelectionManager.as
index abe6f29..30eb446 100644
--- a/textLayout/src/flashx/textLayout/edit/ISelectionManager.as
+++ b/textLayout/src/flashx/textLayout/edit/ISelectionManager.as
@@ -25,9 +25,12 @@ package flashx.textLayout.edit
 	import flash.events.MouseEvent;
 	import flash.events.TextEvent;
 	
+	import flashx.textLayout.elements.CellCoordinates;
+	import flashx.textLayout.elements.CellRange;
+	import flashx.textLayout.elements.TableElement;
 	import flashx.textLayout.elements.TextFlow;
-	import flashx.textLayout.formats.TextLayoutFormat;
 	import flashx.textLayout.elements.TextRange;
+	import flashx.textLayout.formats.TextLayoutFormat;
 
 	/** 
 	 * The ISelectionManager interface defines the interface for handling text selection.
@@ -64,6 +67,23 @@ package flashx.textLayout.edit
 		function get textFlow():TextFlow;
 		function set textFlow(flow:TextFlow):void;
 		
+		function get currentTable():TableElement;
+		function set currentTable(table:TableElement):void;
+		function hasCellRangeSelection():Boolean;
+		
+		function selectCellRange(anchorCoords:CellCoordinates,activeCoords:CellCoordinates):void;
+		
+		function getCellRange():CellRange;
+		function setCellRange(range:CellRange):void;
+
+		/** Anchor point of the current cell selection, as coordinates within the table. */
+		function get anchorCellPosition():CellCoordinates;
+		function set anchorCellPosition(value:CellCoordinates):void;
+		
+		/** Active end of the current cell selection, as coordinates within the table. */
+		function get activeCellPosition():CellCoordinates;
+		function set activeCellPosition(value:CellCoordinates):void;
+
 		/** 
 		 * The text position of the start of the selection, as an offset from the start of the text flow.
 		 *  
@@ -113,6 +133,33 @@ package flashx.textLayout.edit
 		 */
 		function selectAll() : void
 		
+		/**
+		 * Selects the last position in the entire flow.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function selectLastPosition() : void
+		
+		/**
+		 * Selects the first position in the entire flow.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function selectFirstPosition() : void
+
+		/**
+		 * Removes any selection from the text flow
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function deselect() : void
+
 		/** 
 		 * The anchor point of the selection. 
 		 * 
@@ -140,7 +187,7 @@ package flashx.textLayout.edit
 		function get activePosition() : int;
 		
 		/**
-		 * Indicates whether there is a selection. 
+		 * Indicates whether there is a text selection. 
 		 * 
 		 * <p>Returns <code>true</code> if there is either a range selection or a point selection. 
 		 * By default, when a selection manager is first set up, there is no selection (the start and end are -1).</p>
@@ -152,6 +199,34 @@ package flashx.textLayout.edit
  		 * @langversion 3.0
 		 */
 		function hasSelection():Boolean;
+
+		/**
+		 * Indicates whether there is a text or cell selection. 
+		 * 
+		 * <p>Returns <code>true</code> if there is either a range selection or a point selection. 
+		 * By default, when a selection manager is first set up, there is no selection (the start and end are -1).</p>
+		 * 
+		 * @includeExample examples\SelectionManager_hasSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function hasAnySelection():Boolean;
+
+		/**
+		 * Indicates the type of selection. 
+		 * 
+		 * <p>The <code>selectionType</code> describes the kind of selection. 
+		 * It can either be <code>SelectionType.TEXT</code> or <code>SelectionType.CELLS</code>
+		 * 
+		 * @see flashx.textLayout.edit.SelectionType
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get selectionType() : String;
 		
 		/**
 		 * Indicates whether the selection covers a range of text.
@@ -201,6 +276,14 @@ package flashx.textLayout.edit
 		 */	
 		function refreshSelection():void;
 
+		/** 
+		 * Clears the selection shapes. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		function clearSelection():void;
 
 		/** 
 		 * Gives the focus to the first container in the selection.
@@ -250,6 +333,19 @@ package flashx.textLayout.edit
 		 */
 		function get currentSelectionFormat():SelectionFormat;
 
+		/** 
+		 * The current Cell SelectionFormat object.
+		 * 
+		 * <p>The current cell SelectionFormat object is chosen from the SelectionFormat objects assigned to the 
+		 * <code>unfocusedCellSelectionFormat</code>, <code>inactiveCellSelectionFormat</code> and <code>focusedCellSelectionFormat</code> 
+		 * properties based on the current state of the <code>windowActive</code> and <code>focused</code> properties.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get currentCellSelectionFormat():SelectionFormat;
+
 		/**
 		 * Gets the character format attributes that are common to all characters in the specified text range or current selection.
 		 * 
@@ -346,7 +442,38 @@ package flashx.textLayout.edit
 		 */		 		 
 		 function get inactiveSelectionFormat():SelectionFormat;
 		 function set inactiveSelectionFormat(val:SelectionFormat):void;		 		 
-		
+
+		 /**
+		  * The SelectionFormat object used to draw cell selections in a focused container. 
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  */		 
+		 function get focusedCellSelectionFormat():SelectionFormat;
+		 function set focusedCellSelectionFormat(val:SelectionFormat):void;
+		 
+		 /**
+		  * The SelectionFormat object used to draw cell selections when they are not in a focused container, but are in
+		  * the active window.
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  */		 		 
+		 function get unfocusedCellSelectionFormat():SelectionFormat;
+		 function set unfocusedCellSelectionFormat(val:SelectionFormat):void;
+		 
+		 /**
+		  * The SelectionFormat object used to draw cell selections when they are not in the active window.
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  */		 		 
+		 function get inactiveCellSelectionFormat():SelectionFormat;
+		 function set inactiveCellSelectionFormat(val:SelectionFormat):void;		 		 
+
 		/**
 		 * Executes any pending FlowOperations. 
 		 * 
@@ -379,6 +506,25 @@ package flashx.textLayout.edit
  	 	 * @langversion 3.0
 		 */
 		function notifyInsertOrDelete(absolutePosition:int, length:int):void		 
-		 	
+		 
+		/**
+		 * The ISelectionManager object used to for cell selections nested within the TextFlow managed by this ISelectionManager.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 
+		function get subManager():ISelectionManager;
+		function set subManager(value:ISelectionManager):void;
+		
+		/**
+		 * The ISelectionManager object used to manage the parent TextFlow of this ISelectionManager (i.e. for cell ISelectionManagers).
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 
+		function get superManager():ISelectionManager;
+		function set superManager(value:ISelectionManager):void;
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/ModelEdit.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/ModelEdit.as b/textLayout/src/flashx/textLayout/edit/ModelEdit.as
index cdddb3b..b18f55f 100644
--- a/textLayout/src/flashx/textLayout/edit/ModelEdit.as
+++ b/textLayout/src/flashx/textLayout/edit/ModelEdit.as
@@ -516,7 +516,7 @@ class JoinMemento extends BaseMemento implements IMemento
 		
 		var element1Mark:ElementMark = new ElementMark(element1,0);
 		var element2Mark:ElementMark = new ElementMark(element2,0);
-		performInternal(textFlow, element1Mark, element2Mark);		
+		performInternal(textFlow, element1Mark, element2Mark);
 		var removeParentChain:IMemento = TextFlowEdit.removeEmptyParentChain(element2);
 
 		if (createMemento)

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/ParaEdit.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/ParaEdit.as b/textLayout/src/flashx/textLayout/edit/ParaEdit.as
index 974eba2..09ee41b 100644
--- a/textLayout/src/flashx/textLayout/edit/ParaEdit.as
+++ b/textLayout/src/flashx/textLayout/edit/ParaEdit.as
@@ -93,9 +93,13 @@ package flashx.textLayout.edit
 					break;
 				}
 			}
-				
 			// adjust the flow so that we are in a span for the insertion
 			var insertSpan:SpanElement = sibling as SpanElement;
+			
+			// use the terminator span if it's empty
+			if(paragraph.terminatorSpan.textLength == 1 && paragraph.terminatorSpan == insertSpan)
+				createNewSpan = false;
+			
 			if (!insertSpan || createNewSpan)
 			{
 				var newSpan:SpanElement = new SpanElement();
@@ -111,7 +115,15 @@ package flashx.textLayout.edit
 							sibling.splitAtPosition(relativeStart);		// we'll insert between the two elements
 					}
 				}
-				insertParent.replaceChildren(siblingIndex, siblingIndex, newSpan);
+				var nextLeaf:FlowLeafElement = paragraph.findLeaf(paraSelBegIdx);
+				if(nextLeaf && nextLeaf.textLength == 1 && nextLeaf == paragraph.terminatorSpan)
+				{
+					// use the terminator span instead of inserting a new one.
+					newSpan = SpanElement(nextLeaf);
+				}
+				else {
+					insertParent.replaceChildren(siblingIndex, siblingIndex, newSpan);
+				}
 				var formatElem:FlowLeafElement = newSpan.getPreviousLeaf(paragraph);
 				if (formatElem == null)
 					newSpan.format = newSpan.getNextLeaf(paragraph).format;


[03/25] git commit: [flex-tlf] [refs/heads/develop] - Commit of table work

Posted by pi...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/SelectionManager.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/SelectionManager.as b/textLayout/src/flashx/textLayout/edit/SelectionManager.as
index dd6f117..6de1c2b 100644
--- a/textLayout/src/flashx/textLayout/edit/SelectionManager.as
+++ b/textLayout/src/flashx/textLayout/edit/SelectionManager.as
@@ -20,8 +20,10 @@ package flashx.textLayout.edit
 {
     import flash.desktop.Clipboard;
     import flash.desktop.ClipboardFormats;
+    import flash.display.BitmapData;
     import flash.display.DisplayObject;
     import flash.display.InteractiveObject;
+    import flash.display.Shape;
     import flash.display.Stage;
     import flash.errors.IllegalOperationError;
     import flash.events.ContextMenuEvent;
@@ -31,8 +33,10 @@ package flashx.textLayout.edit
     import flash.events.KeyboardEvent;
     import flash.events.MouseEvent;
     import flash.events.TextEvent;
+    import flash.geom.Matrix;
     import flash.geom.Point;
     import flash.geom.Rectangle;
+    import flash.text.engine.TextBlock;
     import flash.text.engine.TextLine;
     import flash.text.engine.TextLineValidity;
     import flash.text.engine.TextRotation;
@@ -40,14 +44,20 @@ package flashx.textLayout.edit
     import flash.ui.Keyboard;
     import flash.ui.Mouse;
     import flash.ui.MouseCursor;
+    import flash.ui.MouseCursorData;
+    import flash.utils.Dictionary;
     import flash.utils.getQualifiedClassName;
     
     import flashx.textLayout.compose.IFlowComposer;
     import flashx.textLayout.compose.TextFlowLine;
+    import flashx.textLayout.compose.TextFlowTableBlock;
     import flashx.textLayout.container.ColumnState;
     import flashx.textLayout.container.ContainerController;
     import flashx.textLayout.debug.Debugging;
     import flashx.textLayout.debug.assert;
+    import flashx.textLayout.elements.CellContainer;
+    import flashx.textLayout.elements.CellCoordinates;
+    import flashx.textLayout.elements.CellRange;
     import flashx.textLayout.elements.Configuration;
     import flashx.textLayout.elements.FlowElement;
     import flashx.textLayout.elements.FlowLeafElement;
@@ -55,7 +65,9 @@ package flashx.textLayout.edit
     import flashx.textLayout.elements.IConfiguration;
     import flashx.textLayout.elements.InlineGraphicElement;
     import flashx.textLayout.elements.ParagraphElement;
-    import flashx.textLayout.elements.TableDataCellElement;
+    import flashx.textLayout.elements.TableBlockContainer;
+    import flashx.textLayout.elements.TableCellElement;
+    import flashx.textLayout.elements.TableColElement;
     import flashx.textLayout.elements.TableElement;
     import flashx.textLayout.elements.TableRowElement;
     import flashx.textLayout.elements.TextFlow;
@@ -122,23 +134,325 @@ package flashx.textLayout.edit
      * @langversion 3.0
      */
     public class SelectionManager implements ISelectionManager
-    {       
+    {
+		static tlf_internal var useTableSelectionCursors:Boolean = false;
+		/**
+		 * Cursor for selection of table
+		 **/
+		public static var SelectTable:String = "selectTable";
+		
+		/**
+		 * Cursor for selection of table row
+		 **/
+		public static var SelectTableRow:String = "selectTableRow";
+		
+		/**
+		 * Cursor for selection of table column
+		 **/
+		public static var SelectTableColumn:String = "selectTableColumn";
+		
         private var _focusedSelectionFormat:SelectionFormat;
         private var _unfocusedSelectionFormat:SelectionFormat;
         private var _inactiveSelectionFormat:SelectionFormat;
+		private var _focusedCellSelectionFormat:SelectionFormat;
+		private var _unfocusedCellSelectionFormat:SelectionFormat;
+		private var _inactiveCellSelectionFormat:SelectionFormat;
         private var _selFormatState:String = SelectionFormatState.UNFOCUSED;
         private var _isActive:Boolean;
         
         /** The TextFlow of the selection. */
         private var _textFlow:TextFlow;
+		
+		protected var _subManager:ISelectionManager;
+		protected var _superManager:ISelectionManager;
+		
+		private var _currentTable:TableElement;
+		
+		// this should probably be produced dynamically rather than keep a reference.
+		private var _cellRange:CellRange;
+		
+		//TODO the following functions need proper comments and should be moved to a logical location within the class.
+		
+		public function get currentTable():TableElement
+		{
+			return _currentTable;
+		}
+		public function set currentTable(table:TableElement):void
+		{
+			_currentTable = table;
+		}
+		
+		public function hasCellRangeSelection():Boolean
+		{
+			if (!_currentTable) {
+				return false;
+			}
+			
+			//we should really check the anchorCellPosition and activeCellPosition instead
+			if (!_cellRange) {
+				return false;
+			}
+			
+			return true;
+		}
+		
+		/**
+		 * Select a table cell text flow
+		 **/
+		public function selectCellTextFlow(cell:TableCellElement):void {
+			
+			if (cell && cell.table) {
+				var selectionManager:SelectionManager = cell.textFlow.interactionManager as SelectionManager;
+				
+				clear();
+				
+				if (selectionManager) {
+					selectionManager.currentTable = cell.table;
+					selectionManager.selectAll();
+					
+					// this seems to be required to work but it should not be
+					selectionManager.setFocus(); 
+				}
+			}
+		}
+		
+		/**
+		 * Select a table cell. 
+		 **/
+		public function selectCell(cell:TableCellElement):void {
+			var beginCoordinates:CellCoordinates;
+			var endCoordinates:CellCoordinates;
+			
+			if (cell) {
+				beginCoordinates = new CellCoordinates(cell.rowIndex, cell.colIndex);
+				endCoordinates = new CellCoordinates(cell.rowIndex, cell.colIndex);
+				
+				if (beginCoordinates.isValid()) {
+					selectCellRange(beginCoordinates, endCoordinates);
+				}
+			}
+		}
+		
+		/**
+		 * Select table cells at the specified index.
+		 **/
+		public function selectCellAt(table:TableElement, rowIndex:int, colIndex:int):void {
+			var cell:TableCellElement = table.getCellAt(rowIndex, colIndex);
+			
+			if (cell) {
+				selectCell(cell);
+			}
+		}
+		
+		/**
+		 * Select table cells at the specified index
+		 **/
+		public function selectCells(cells:Vector.<TableCellElement>):void {
+			var startX:int = int.MAX_VALUE;
+			var startY:int = int.MAX_VALUE;
+			var endX:int = int.MIN_VALUE;
+			var endY:int = int.MIN_VALUE;
+			var cell:TableCellElement;
+			var table:TableElement;
+			for each(cell in cells)
+			{
+				if(cell)
+				{
+					if(table == null)
+						table = cell.getTable();
+					
+					var col:int = cell.colIndex;
+					var row:int = cell.rowIndex;
+					if(col < startX)
+						startX = col;
+					if(col > endX)
+						endX = col;
+					if(row < startY)
+						startY = row;
+					if(row > endY)
+						endY = row;
+				}
+			}
+			if(startX <= endX && startY <= endY)
+				selectCellRange(
+					new CellCoordinates(startY,startX,table),
+					new CellCoordinates(endY,endX,table)
+				);
+		}
+		
+		/**
+		 * Select the specified table row. 
+		 **/
+		public function selectRow(row:TableRowElement):void {
+			var beginCoordinates:CellCoordinates;
+			var endCoordinates:CellCoordinates;
+			
+			if (row) {
+				beginCoordinates = new CellCoordinates(row.rowIndex, 0);
+				endCoordinates = new CellCoordinates(row.rowIndex, row.numCells);
+				
+				if (beginCoordinates.isValid() && endCoordinates.isValid()) {
+					selectCellRange(beginCoordinates, endCoordinates);
+				}
+			}
+		}
+		
+		/**
+		 * Select a table row at the specified index
+		 **/
+		public function selectRowAt(table:TableElement, index:int):void {
+			var row:TableRowElement = table ? table.getRowAt(index) : null;
+			
+			if (row) {
+				selectRow(row);
+			}
+		}
+		
+		/**
+		 * Selects the table rows provided
+		 **/
+		public function selectRows(rows:Array):void {
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			var table:TableElement;
+			var cell:TableCellElement;
+			
+			if (rows && rows.length) {
+				
+				for (var i:int;i<rows.length;i++) 
+				{
+					var row:TableRowElement = rows[i] as TableRowElement;
+					
+					if (row)
+					{
+						for each(cell in row.cells)
+						cells.push(cell);
+					}
+				}
+				
+				selectCells(cells);
+			}
+		}
+		
+		/**
+		 * Select a table column. 
+		 **/
+		public function selectColumn(column:TableColElement):void {
+			var table:TableElement = column.table;
+			
+			if (column && table) {
+				selectCells(table.getCellsForColumn(column));
+			}
+		}
+		
+		/**
+		 * Select a table column at the specified index 
+		 **/
+		public function selectColumnAt(table:TableElement, index:int):void {
+			var column:TableColElement = table.getColumnAt(index);
+			
+			if (column && table) {
+				return selectColumn(column);
+			}
+		}
+		
+		/**
+		 * Selects the table columns provided
+		 **/
+		public function selectColumns(columns:Array):void {
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			var cell:TableCellElement;
+			
+			if (columns && columns.length) {
+				
+				for (var i:int;i<columns.length;i++) 
+				{
+					var column:TableColElement = columns[i] as TableColElement;
+					
+					if (column)
+					{
+						for each(cell in column.cells)
+							cells.push(cell);
+					}
+					
+				}
+				
+				selectCells(cells);
+			}
+		}
+		
+		/**
+		 * Select all cells in a table. 
+		 **/
+		public function selectTable(table:TableElement):void {
+			
+			if (table)
+			{
+				var startCoords:CellCoordinates = new CellCoordinates(0,0,table);
+				var endCoords:CellCoordinates = new CellCoordinates(table.numRows-1,table.numColumns-1,table);
+				selectCellRange(startCoords,endCoords);
+			}
+			
+		}
+		
+		/**
+		 * Select a range of table cells. 
+		 **/
+		public function selectCellRange(anchorCoords:CellCoordinates, activeCoords:CellCoordinates):void
+		{
+			var blocks:Vector.<TextFlowTableBlock>;
+			var block:TextFlowTableBlock;
+			var controller:ContainerController;
+			
+			if (selectionType == SelectionType.TEXT) {
+				clear();
+			}
+			clearCellSelections();
+			
+			if (anchorCoords && activeCoords) {
+				_cellRange = new CellRange(_currentTable, anchorCoords, activeCoords);
+				activeCellPosition = activeCoords;
+				blocks = _currentTable.getTableBlocksInRange(anchorCoords, activeCoords);
+				
+				for each(block in blocks) {
+					block.controller.clearSelectionShapes();
+					block.controller.addCellSelectionShapes(currentCellSelectionFormat.rangeColor, block, anchorCoords, activeCoords);
+				}
+				if(subManager)
+				{
+					subManager.selectRange(-1,-1);
+					subManager = null;
+				}
+			}
+			else
+			{
+				_cellRange = null;
+				activeCellPosition.column = -1;
+				activeCellPosition.row = -1;
+			}
+			selectionChanged();
+		}
+		
+		public function getCellRange():CellRange
+		{
+			// not really a good implementation. We'll fix this later
+			return _cellRange;
+		}
+		public function setCellRange(range:CellRange):void
+		{
+			selectCellRange(range.anchorCoordinates,range.activeCoordinates);
+			//_cellRange = range;
+			// do something about actually drawing the selection.
+		}
         
         // current range of selection
         /** Anchor point of the current selection, as an index into the TextFlow. */
         private var anchorMark:Mark;
         /** Active end of the current selection, as an index into the TextFlow. */
         private var activeMark:Mark;
-        
-        // used to save pending attributes at a point selection
+        private var _anchorCellPosition:CellCoordinates;
+		private var _activeCellPosition:CellCoordinates;
+
+		// used to save pending attributes at a point selection
         private var _pointFormat:ITextLayoutFormat;
         /** 
          * The format that will be applied to inserted text. 
@@ -190,6 +504,8 @@ package flashx.textLayout.edit
             _textFlow = null;
             anchorMark = createMark();
             activeMark = createMark();
+			anchorCellPosition = createCellMark();
+			activeCellPosition = createCellMark();
             _pointFormat = null;
             _isActive = false;
             CONFIG::debug 
@@ -197,7 +513,12 @@ package flashx.textLayout.edit
                 this.id = smCount.toString();
                 smCount++;
             }
+			
+			Mouse.registerCursor(SelectTable, createSelectTableCursor());
+			Mouse.registerCursor(SelectTableRow, createSelectTableRowCursor());
+			Mouse.registerCursor(SelectTableColumn, createSelectTableColumnCursor());
         }
+		
         /**
          * @copy ISelectionManager#getSelectionState()
          * 
@@ -211,7 +532,10 @@ package flashx.textLayout.edit
          */
         public function getSelectionState():SelectionState
         {
-            return new SelectionState(_textFlow, anchorMark.position, activeMark.position, pointFormat);
+			if(subManager)
+				return subManager.getSelectionState();
+			
+            return new SelectionState(_textFlow, anchorMark.position, activeMark.position, pointFormat, _cellRange);
         }
                 
         /**
@@ -238,8 +562,45 @@ package flashx.textLayout.edit
          * @langversion 3.0
          */
         public function hasSelection():Boolean
-        { return anchorMark.position != -1; }
+        {
+			return selectionType == SelectionType.TEXT;
+		}
+
+		/**
+		 *  @copy ISelectionManager#hasAnySelection()
+		 * 
+		 * @includeExample examples\SelectionManager_hasSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function hasAnySelection():Boolean
+		{
+			return selectionType != SelectionType.NONE;
+		}
 
+		/**
+		 * Indicates the type of selection. 
+		 * 
+		 * <p>The <code>selectionType</code> describes the kind of selection. 
+		 * It can either be <code>SelectionType.TEXT</code> or <code>SelectionType.CELLS</code>
+		 * 
+		 * @see flashx.textLayout.edit.SelectionType
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get selectionType() : String
+		{
+			if(anchorMark.position != -1)
+				return SelectionType.TEXT;
+			else if(anchorCellPosition.isValid())
+				return SelectionType.CELLS;
+			
+			return SelectionType.NONE;
+		}
         /** 
          *  @copy ISelectionManager#isRangeSelection()
          * 
@@ -277,6 +638,8 @@ package flashx.textLayout.edit
                     flushPendingOperations();
                 
                 clear();
+				clearCellSelections();
+				_cellRange = null;
                 
                 // If we switch into read-only mode, make sure the cursor isn't showing a text selection IBeam
                 if (!value) // see Watson 2637162
@@ -348,7 +711,29 @@ package flashx.textLayout.edit
             }
             return focusedSelectionFormat;
          }
-         
+
+		 /**
+		  *  @copy ISelectionManager#currentCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function get currentCellSelectionFormat():SelectionFormat
+		 { 
+			 if (_selFormatState == SelectionFormatState.UNFOCUSED)
+			 {
+				 return unfocusedCellSelectionFormat;
+			 }
+			 else if (_selFormatState == SelectionFormatState.INACTIVE)
+			 {
+				 return inactiveCellSelectionFormat;
+			 }
+			 return focusedCellSelectionFormat;
+		 }
+
         /**
          *  @copy ISelectionManager#focusedSelectionFormat
          * 
@@ -420,7 +805,79 @@ package flashx.textLayout.edit
          { 
             return _inactiveSelectionFormat ? _inactiveSelectionFormat : (_textFlow ? _textFlow.configuration.inactiveSelectionFormat : null);
          }       
-         
+
+		 /**
+		  *  @copy ISelectionManager#focusedCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function set focusedCellSelectionFormat(val:SelectionFormat):void
+		 { 
+			 _focusedCellSelectionFormat = val;
+			 if (this._selFormatState == SelectionFormatState.FOCUSED)
+				 refreshSelection();
+		 }
+		 
+		 /**
+		  * @private - docs on setter
+		  */
+		 public function get focusedCellSelectionFormat():SelectionFormat
+		 { 
+			 return _focusedCellSelectionFormat ? _focusedCellSelectionFormat : (_textFlow ? _textFlow.configuration.focusedSelectionFormat : null);
+		 }       
+		 
+		 /**
+		  *  @copy ISelectionManager#unfocusedCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function set unfocusedCellSelectionFormat(val:SelectionFormat):void
+		 { 
+			 _unfocusedCellSelectionFormat = val;
+			 if (this._selFormatState == SelectionFormatState.UNFOCUSED)
+				 refreshSelection();
+		 }          
+		 
+		 /**
+		  *  @private - docs on setter
+		  */
+		 public function get unfocusedCellSelectionFormat():SelectionFormat
+		 { 
+			 return _unfocusedCellSelectionFormat ? _unfocusedCellSelectionFormat : (_textFlow ? _textFlow.configuration.unfocusedSelectionFormat : null);
+		 }
+		 
+		 /**
+		  *  @copy ISelectionManager#inactiveCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function set inactiveCellSelectionFormat(val:SelectionFormat):void
+		 { 
+			 _inactiveCellSelectionFormat = val;
+			 if (this._selFormatState == SelectionFormatState.INACTIVE)
+				 refreshSelection();
+		 }          
+		 
+		 /**
+		  * @private - docs on setter
+		  */
+		 public function get inactiveCellSelectionFormat():SelectionFormat
+		 { 
+			 return _inactiveCellSelectionFormat ? _inactiveCellSelectionFormat : (_textFlow ? _textFlow.configuration.inactiveSelectionFormat : null);
+		 }       
+		 
          /** @private - returns the selectionFormatState.  @see flashx.textLayout.edit.SelectionFormatState */
          tlf_internal function get selectionFormatState():String
          { return _selFormatState; }
@@ -584,11 +1041,17 @@ package flashx.textLayout.edit
          */
         public function selectAll() : void
         {
-            selectRange(0, int.MAX_VALUE);
+			if(subManager)
+				subManager.selectAll();
+			else
+			{
+				var lastSelectablePos:int = (_textFlow.textLength > 0) ? _textFlow.textLength - 1 : 0;
+				selectRange(0, lastSelectablePos);
+			}
         }
         
         /** 
-         *  @copy ISelectionManager#selectRange
+         * @copy ISelectionManager#selectRange
          * 
          * @includeExample examples\SelectionManager_selectRange.as -noswf
          * 
@@ -601,22 +1064,76 @@ package flashx.textLayout.edit
         public function selectRange(anchorPosition:int, activePosition:int) : void
         {
             flushPendingOperations();
+			
+			if(subManager)
+				subManager.selectRange(-1,-1);
             
             // anchor and active can be in any order
             // TODO: range check and clamp anchor,active
             if (anchorPosition != anchorMark.position || activePosition != activeMark.position)
             {   
                 clearSelectionShapes();
+				clearCellSelections();
+				_cellRange = null;
                     
-                internalSetSelection(_textFlow, anchorPosition, activePosition);
+                internalSetSelection(_textFlow, anchorPosition, activePosition, _pointFormat);
                 
                 // selection changed
-                selectionChanged();     
+                selectionChanged();
                 
                 allowOperationMerge = false;
             }
         }
-        
+		
+		/** 
+		 * @copy ISelectionManager#selectFirstPosition
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function selectFirstPosition():void
+		{
+			selectRange(0, 0);
+		}
+		
+		/** 
+		 * @copy ISelectionManager#selectLastPosition
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function selectLastPosition():void
+		{
+			selectRange(int.MAX_VALUE, int.MAX_VALUE);
+		}
+
+		/** 
+		 * @copy ISelectionManager#deselect
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function deselect():void
+		{
+			if (hasAnySelection())
+			{
+				clearSelectionShapes();
+				clearCellSelections();
+				addSelectionShapes();
+			}
+			selectRange(-1,-1);
+			_cellRange = null;
+		}
+
         private function internalSetSelection(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null) : void
         {
             _textFlow = root;
@@ -627,6 +1144,8 @@ package flashx.textLayout.edit
                 anchorPosition = -1;
                 activePosition = -1;
             }
+			else if(subManager)
+				subManager = null;
             
             var lastSelectablePos:int = (_textFlow.textLength > 0) ? _textFlow.textLength - 1 : 0;
             
@@ -645,7 +1164,8 @@ package flashx.textLayout.edit
         //  trace("Selection ", anchorMark, "to", activeMark.position);
         }       
         
-        /** Clear any active selections.
+        /** 
+		 * Clear any active selections.
          */
         private function clear(): void
         {
@@ -659,7 +1179,32 @@ package flashx.textLayout.edit
                 allowOperationMerge = false;
             }
         }
-        
+        /**
+		 * Clear any cell selections
+		 * */
+		private function clearCellSelections():void
+		{
+			var blocks:Vector.<TextFlowTableBlock>;
+			var block:TextFlowTableBlock;
+			var controller:ContainerController;
+			
+			if (_cellRange) {
+				blocks = _cellRange.table.getTableBlocksInRange(_cellRange.anchorCoordinates, _cellRange.activeCoordinates);
+				
+				for each (block in blocks) {
+					if (controller != block.controller) {
+						block.controller.clearSelectionShapes();
+					}
+					
+					controller = block.controller;
+				}
+				
+			}
+			if(block)
+				block.controller.clearSelectionShapes();
+			
+			//_cellRange = null;
+		}
         private function addSelectionShapes():void
         {
             if (_textFlow.flowComposer)
@@ -677,7 +1222,7 @@ package flashx.textLayout.edit
                     {
                         _textFlow.flowComposer.getControllerAt(containerIter++).addSelectionShapes(currentSelectionFormat, absoluteStart, absoluteEnd);
                     }
-                } 
+                }
             }
         }
         
@@ -693,22 +1238,39 @@ package flashx.textLayout.edit
                 }
             }
         }
-        
-        /** 
-         *  @copy ISelectionManager#refreshSelection()
-         * 
-         * @playerversion Flash 10
-         * @playerversion AIR 1.5
-         * @langversion 3.0
-        */
-        public function refreshSelection(): void
-        {
-            if (hasSelection())
-            {
-                clearSelectionShapes();
-                addSelectionShapes();
-            }
-        }
+		
+		/** 
+		 *  @copy ISelectionManager#refreshSelection()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function refreshSelection(): void
+		{
+			if (hasAnySelection())
+			{
+				clearSelectionShapes();
+				clearCellSelections();
+				addSelectionShapes();
+			}
+		}
+		
+		/** 
+		 *  @copy ISelectionManager#clearSelection()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function clearSelection(): void
+		{
+			if (hasAnySelection())
+			{
+				clearSelectionShapes();
+				clearCellSelections();
+			}
+		}
         
         /** Verifies that the selection is in a legal state. @private */
         CONFIG::debug public function debugCheckSelectionManager():int
@@ -745,7 +1307,12 @@ package flashx.textLayout.edit
                 _pointFormat = null;
             
             if (doDispatchEvent && _textFlow)
-                textFlow.dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
+			{
+				if(textFlow.parentElement && textFlow.parentElement.getTextFlow())
+					textFlow.parentElement.getTextFlow().dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
+				else
+					textFlow.dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
+			}
         }
 
         // TODO: this routine could be much more efficient - instead of iterating over all lines in the TextFlow it should iterate over 
@@ -771,11 +1338,14 @@ package flashx.textLayout.edit
             //get the nearest column so we can ignore lines which aren't in the column we're looking for.
             //if we don't do this, we won't be able to select across column boundaries.
             var nearestColIdx:int = locateNearestColumn(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
+
+			var prevLineBounds:Rectangle = null;
+			var previousLineIndex:int = -1;
+
+			/*
 			//For the table feature, we are trying to make sure if the current point is in the table and which cell it is in
-			var nearestCell:TableDataCellElement = locateNearestCell(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
+			var nearestCell:TableCellElement = locateNearestCell(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
             
-            var prevLineBounds:Rectangle = null;
-            var previousLineIndex:int = -1;
 			
 			if(nearestCell)
 			{
@@ -790,7 +1360,7 @@ package flashx.textLayout.edit
 					return cellPara.getAbsoluteStart() + cellPara.textLength - 1;
 				}
 			}
-            
+            */
             var lastLineIndexInColumn:int = -1;
             
             // Matching TextFlowLine and TextLine - they are not necessarily valid
@@ -845,6 +1415,7 @@ package flashx.textLayout.edit
                     //current line,. Otherwise, if the click's perpendicular coordinate is below the mid point between the current
                     //line or below it, then we want to use the line below (ie the previous line, but logically the one after the current)
                     var inPrevLine:Boolean = midPerpCoor != -1 && (isTTB ? perpCoor < midPerpCoor : perpCoor > midPerpCoor);
+					/*
 					if(rtline.paragraph.isInTable())
 					{
 						//if rtline is the last line of the cell and the isPrevLine is true, find the cell of the column in next row
@@ -852,10 +1423,10 @@ package flashx.textLayout.edit
 						if ( inPrevLine && testIndex != lastLineIndexInColumn )
 						{
 							var rtPara:ParagraphElement = rtline.paragraph;
-							var rtCell:TableDataCellElement = rtPara.getTableDataCellElement();
+							var rtCell:TableCellElement = rtPara.getParentCellElement();
 							//get the last element of the cell
 							var lastElement:FlowElement = rtCell.getLastLeaf();
-							var rtLastTbLine:TextFlowLine = lastElement.getParagraph().getTextBlock().lastLine.userData;
+							var rtLastTbLine:TextFlowLine = lastElement ? lastElement.getParagraph().getTextBlock().lastLine.userData : null;
 							if( rtline == rtLastTbLine )
 							{
 								//temproray codes, need to be updated when the column apis are ready
@@ -864,7 +1435,7 @@ package flashx.textLayout.edit
 								var nextRow:TableRowElement = rtRow.getNextSibling() as TableRowElement;
 								if ( nextRow && rtCell )
 								{
-									var nextCell:TableDataCellElement = nextRow.getChildAt(rtCell.colIndex) as TableDataCellElement;
+									var nextCell:TableCellElement = nextRow.getChildAt(rtCell.colIndex) as TableCellElement;
 									lineIndex = textFlow.flowComposer.findLineIndexAtPosition(nextCell.getFirstLeaf().getParagraph().getAbsoluteStart());
 								}
 							}
@@ -875,6 +1446,7 @@ package flashx.textLayout.edit
 							lineIndex = testIndex;
 					}
 					else
+					*/
                     	lineIndex = inPrevLine && testIndex != lastLineIndexInColumn ? testIndex+1 : testIndex;
 					break;
                 }
@@ -895,79 +1467,87 @@ package flashx.textLayout.edit
                 
             //Get a valid textLine -- check to make sure line is valid, regenerate if necessary, make sure it has correct container relative coordinates
             var textFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(lineIndex);
-            var textLine:TextLine = textFlowLine.getTextLine(true);
-            
-            // adjust localX,localY to be relative to the textLine.  
-            // Can't use localToGlobal/globalToLocal because textLine may not be on the display list due to virtualization
-            // we may need to bring this back if textline's can be rotated or placed by any mechanism other than a translation
-            // but then we'll need to provisionally place a virtualized TextLine in its parent container
-            localX -= textLine.x;
-            localY -= textLine.y;
-            /* var localPoint:Point = DisplayObject(controller.container).localToGlobal(new Point(localX,localY));
-            localPoint = textLine.globalToLocal(localPoint);
-            localX = localPoint.x;
-            localY = localPoint.y; */
-            
-            
-            var startOnNextLineIfNecessary:Boolean = false;
-            
-            var lastAtom:int = -1;
-            if (isDirectionRTL) {
-                lastAtom = textLine.atomCount - 1;
-            } else {
-                if ((textFlowLine.absoluteStart + textFlowLine.textLength) >= textFlowLine.paragraph.getAbsoluteStart() + textFlowLine.paragraph.textLength) {
-                    if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
-                } else {
-                    var lastLinePosInPar:int = textFlowLine.absoluteStart + textFlowLine.textLength - 1;
-                    var lastChar:String = textLine.textBlock.content.rawText.charAt(lastLinePosInPar);
-                    if (lastChar == " ") {
-                        if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
-                    } else {
-                        startOnNextLineIfNecessary = true;
-                        if (textLine.atomCount > 0) lastAtom = textLine.atomCount - 1;
-                    }
-                }
-            }
-            var lastAtomRect:Rectangle = (lastAtom > 0) ? textLine.getAtomBounds(lastAtom) : new Rectangle(0, 0, 0, 0);
-                        
-            if (!isTTB)
-            {
-                if (localX < 0)
-                    localX = 0;
-                else if (localX > (lastAtomRect.x + lastAtomRect.width))
-                {
-                    if (startOnNextLineIfNecessary) 
-                        return textFlowLine.absoluteStart + textFlowLine.textLength - 1;
-                    if (lastAtomRect.x + lastAtomRect.width > 0)
-                        localX = lastAtomRect.x + lastAtomRect.width;
-                }
-            }
-            else
-            {   
-                if (localY < 0) 
-                    localY = 0;
-                else if (localY > (lastAtomRect.y + lastAtomRect.height))
-                {
-                    if (startOnNextLineIfNecessary) 
-                        return textFlowLine.absoluteStart + textFlowLine.textLength - 1;    
-                    if (lastAtomRect.y + lastAtomRect.height > 0)
-                        localY = lastAtomRect.y + lastAtomRect.height;
-                }
-            }
-            
-			result = computeSelectionIndexInLine(textFlow, textLine, localX, localY);
+			if(textFlowLine is TextFlowTableBlock)
+			{
+				result = TextFlowTableBlock(textFlowLine).absoluteStart;
+			}
+			else
+			{
+				var textLine:TextLine = textFlowLine.getTextLine(true);
+				
+				// adjust localX,localY to be relative to the textLine.  
+				// Can't use localToGlobal/globalToLocal because textLine may not be on the display list due to virtualization
+				// we may need to bring this back if textline's can be rotated or placed by any mechanism other than a translation
+				// but then we'll need to provisionally place a virtualized TextLine in its parent container
+				localX -= textLine.x;
+				localY -= textLine.y;
+				/* var localPoint:Point = DisplayObject(controller.container).localToGlobal(new Point(localX,localY));
+				localPoint = textLine.globalToLocal(localPoint);
+				localX = localPoint.x;
+				localY = localPoint.y; */
+				
+				
+				var startOnNextLineIfNecessary:Boolean = false;
+				
+				var lastAtom:int = -1;
+				if (isDirectionRTL) {
+					lastAtom = textLine.atomCount - 1;
+				} else {
+					if ((textFlowLine.absoluteStart + textFlowLine.textLength) >= textFlowLine.paragraph.getAbsoluteStart() + textFlowLine.paragraph.textLength) {
+						if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
+					} else {
+						var lastLinePosInPar:int = textFlowLine.absoluteStart + textFlowLine.textLength - 1;
+						var lastChar:String = textLine.textBlock.content.rawText.charAt(lastLinePosInPar);
+						if (lastChar == " ") {
+							if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
+						} else {
+							startOnNextLineIfNecessary = true;
+							if (textLine.atomCount > 0) lastAtom = textLine.atomCount - 1;
+						}
+					}
+				}
+				var lastAtomRect:Rectangle = (lastAtom > 0) ? textLine.getAtomBounds(lastAtom) : new Rectangle(0, 0, 0, 0);
+				
+				if (!isTTB)
+				{
+					if (localX < 0)
+						localX = 0;
+					else if (localX > (lastAtomRect.x + lastAtomRect.width))
+					{
+						if (startOnNextLineIfNecessary) 
+							return textFlowLine.absoluteStart + textFlowLine.textLength - 1;
+						if (lastAtomRect.x + lastAtomRect.width > 0)
+							localX = lastAtomRect.x + lastAtomRect.width;
+					}
+				}
+				else
+				{   
+					if (localY < 0) 
+						localY = 0;
+					else if (localY > (lastAtomRect.y + lastAtomRect.height))
+					{
+						if (startOnNextLineIfNecessary) 
+							return textFlowLine.absoluteStart + textFlowLine.textLength - 1;    
+						if (lastAtomRect.y + lastAtomRect.height > 0)
+							localY = lastAtomRect.y + lastAtomRect.height;
+					}
+				}
+				
+				result = computeSelectionIndexInLine(textFlow, textLine, localX, localY);
+			}
+
             // trace("computeSelectionIndexInContainer:(",origX,origY,")",textFlow.flowComposer.getControllerIndex(controller).toString(),lineIndex.toString(),result.toString());
             return result != -1 ? result : firstCharVisible + length;   
         }
-		
-		static private function locateNearestCell(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):TableDataCellElement
+		/*
+		static private function locateNearestCell(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):TableCellElement
 		{
 			var cellIdx:int = 0;
 			//if we only have 1 column, no need to perform calculation...
 			var columnState:ColumnState = container.columnState;
 			
 			var isFound:Boolean = false;
-			var curCell:TableDataCellElement = null;
+			var curCell:TableCellElement = null;
 			
 			//we need to compare the current column to the nextColmn
 			while(cellIdx < columnState.cellCount - 1)
@@ -984,7 +1564,7 @@ package flashx.textLayout.edit
 			}
 			return isFound? curCell : null;
 		}
-        
+        */
         static private function locateNearestColumn(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):int
         {
             var colIdx:int = 0;
@@ -1141,9 +1721,8 @@ package flashx.textLayout.edit
             else  // Left to right case, right is "end" unicode
                 paraSelectionIdx = leanRight ? textLine.getAtomTextBlockEndIndex(elemIdx) : textLine.getAtomTextBlockBeginIndex(elemIdx);
 
-            //we again need to do some fixup here.  Unfortunately, we don't have the index into the paragraph until
-            
-            return rtline.paragraph.getAbsoluteStart() + paraSelectionIdx;
+			//we again need to do some fixup here.  Unfortunately, we don't have the index into the paragraph until
+            return rtline.paragraph.getTextBlockAbsoluteStart(textLine.textBlock) + paraSelectionIdx;
         }
         
         static private function checkForDisplayed(container:DisplayObject):Boolean
@@ -1164,6 +1743,142 @@ package flashx.textLayout.edit
             return false;   // not on the stage
 
         }
+		/** @private - find a controller and adjusts the x and y values of localPoint if necessary */
+		private static function findController(textFlow:TextFlow, target:Object, currentTarget:Object, localPoint:Point):ContainerController
+		{
+			var localX:Number = localPoint.x;
+			var localY:Number = localPoint.y;
+			var controller:ContainerController;
+			var containerPoint:Point; // scratch
+			
+			var globalPoint:Point = DisplayObject(target).localToGlobal(new Point(localX, localY));
+
+			for (var idx:int = 0; idx < textFlow.flowComposer.numControllers; idx++)
+			{
+				var testController:ContainerController = textFlow.flowComposer.getControllerAt(idx); 
+				if (testController.container == target || testController.container == currentTarget)
+				{
+					controller = testController;
+					break;
+				}
+			}
+			if (controller)
+			{   
+				if (target != controller.container)
+				{
+					containerPoint = DisplayObject(controller.container).globalToLocal(globalPoint);
+					localPoint.x = containerPoint.x;
+					localPoint.y = containerPoint.y;
+				}
+				return controller;         
+			} 
+			
+			//the point is someplace else on stage.  Map the target 
+			//to the textFlow.container.
+			CONFIG::debug { assert(textFlow.flowComposer && textFlow.flowComposer.numControllers,"findController: invalid textFlow"); }
+			
+			
+			
+			// result of the search
+			var controllerCandidate:ContainerController = null;
+			var candidateLocalX:Number;
+			var candidateLocalY:Number;
+			var relDistance:Number = Number.MAX_VALUE;
+			
+			for (var containerIndex:int = 0; containerIndex < textFlow.flowComposer.numControllers; containerIndex++)
+			{
+				var curContainerController:ContainerController = textFlow.flowComposer.getControllerAt(containerIndex);
+				
+				// displayed??
+				if (!checkForDisplayed(curContainerController.container as DisplayObject))
+					continue;
+				
+				// handle measured containers??
+				var bounds:Rectangle = curContainerController.getContentBounds();
+				var containerWidth:Number = isNaN(curContainerController.compositionWidth) ? curContainerController.getTotalPaddingLeft()+bounds.width : curContainerController.compositionWidth;
+				var containerHeight:Number = isNaN(curContainerController.compositionHeight) ? curContainerController.getTotalPaddingTop()+bounds.height : curContainerController.compositionHeight;
+				
+				containerPoint = DisplayObject(curContainerController.container).globalToLocal(globalPoint);
+				
+				// remove scrollRect effects for the distance test but add it back in for the result
+				var adjustX:Number = 0;
+				var adjustY:Number = 0;
+				
+				if (curContainerController.hasScrollRect)
+				{
+					containerPoint.x -= (adjustX = curContainerController.container.scrollRect.x);
+					containerPoint.y -= (adjustY = curContainerController.container.scrollRect.y);
+				}
+				
+				if ((containerPoint.x >= 0) && (containerPoint.x <= containerWidth) &&
+					(containerPoint.y >= 0) && (containerPoint.y <= containerHeight))
+				{
+					controllerCandidate = curContainerController;
+					candidateLocalX = containerPoint.x+adjustX;
+					candidateLocalY = containerPoint.y+adjustY;
+					break;
+				}
+				
+				// figure minimum distance of containerPoint to curContainerController - 8 cases
+				var relDistanceX:Number = 0;
+				var relDistanceY:Number = 0;
+				
+				if (containerPoint.x < 0)
+				{
+					relDistanceX = containerPoint.x;
+					if (containerPoint.y < 0)
+						relDistanceY = containerPoint.y;
+					else if (containerPoint.y > containerHeight)
+						relDistanceY = containerPoint.y-containerHeight;
+				}
+				else if (containerPoint.x > containerWidth)
+				{
+					relDistanceX = containerPoint.x-containerWidth;
+					if (containerPoint.y < 0)
+						relDistanceY = containerPoint.y;
+					else if (containerPoint.y > containerHeight)
+						relDistanceY = containerPoint.y-containerHeight;
+				}
+				else if (containerPoint.y < 0)
+					relDistanceY = -containerPoint.y;
+				else
+					relDistanceY = containerPoint.y-containerHeight;
+				var tempDist:Number = relDistanceX*relDistanceX + relDistanceY*relDistanceY;    // could do sqrt but why bother - there is no Math.hypot function
+				if (tempDist <= relDistance)
+				{
+					relDistance = tempDist;
+					controllerCandidate = curContainerController;
+					candidateLocalX = containerPoint.x+adjustX;
+					candidateLocalY = containerPoint.y+adjustY;
+				}
+			}
+			localPoint.x = candidateLocalX;
+			localPoint.y = candidateLocalY;
+			return controllerCandidate;
+
+		}
+		/** @private - given a target and location compute the CellCoordinates */
+		static tlf_internal function computeCellCoordinates(textFlow:TextFlow, target:Object, currentTarget:Object, localX:Number, localY:Number):CellCoordinates
+		{
+			var rslt:CellCoordinates;
+			var containerPoint:Point; // scratch
+			
+
+			if (target is TextLine)
+				return null;
+			if(target is CellContainer)
+			{
+				var cell:TableCellElement = (target as CellContainer).element;
+				return new CellCoordinates(cell.rowIndex, cell.colIndex, cell.getTable());
+			}
+			var localPoint:Point = new Point(localX, localY);
+			var controller:ContainerController = findController(textFlow, target, currentTarget, localPoint);
+			if(!controller)
+				return null;
+			
+			return controller.findCellAtPosition(localPoint);
+		}
+
         /** @private - given a target and location compute the selectionIndex */
         static tlf_internal function computeSelectionIndex(textFlow:TextFlow, target:Object, currentTarget:Object, localX:Number,localY:Number):int
         {           
@@ -1196,112 +1911,9 @@ package flashx.textLayout.edit
                 rslt = computeSelectionIndexInLine(textFlow, TextLine(target), localX, localY);
             else
             {
-                var controller:ContainerController;
-                for (var idx:int = 0; idx < textFlow.flowComposer.numControllers; idx++)
-                {
-                    var testController:ContainerController = textFlow.flowComposer.getControllerAt(idx); 
-                    if (testController.container == target || testController.container == currentTarget)
-                    {
-                        controller = testController;
-                        break;
-                    }
-                }
-                if (controller)
-                {   
-                    if (target != controller.container)
-                    {
-                        containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
-                        containerPoint = DisplayObject(controller.container).globalToLocal(containerPoint);
-                        localX = containerPoint.x;
-                        localY = containerPoint.y;
-                    }
-                    rslt = computeSelectionIndexInContainer(textFlow, controller, localX, localY);          
-                } 
-                else 
-                {
-                    //the point is someplace else on stage.  Map the target 
-                    //to the textFlow.container.
-                    CONFIG::debug { assert(textFlow.flowComposer && textFlow.flowComposer.numControllers,"computeSelectionIndex: invalid textFlow"); }
-                    
-                    
-                    // result of the search
-                    var controllerCandidate:ContainerController = null;
-                    var candidateLocalX:Number;
-                    var candidateLocalY:Number;
-                    var relDistance:Number = Number.MAX_VALUE;
-                    
-                    for (var containerIndex:int = 0; containerIndex < textFlow.flowComposer.numControllers; containerIndex++)
-                    {
-                        var curContainerController:ContainerController = textFlow.flowComposer.getControllerAt(containerIndex);
-                        
-                        // displayed??
-                        if (!checkForDisplayed(curContainerController.container as DisplayObject))
-                            continue;
-
-                        // handle measured containers??
-                        var bounds:Rectangle = curContainerController.getContentBounds();
-                        var containerWidth:Number = isNaN(curContainerController.compositionWidth) ? curContainerController.getTotalPaddingLeft()+bounds.width : curContainerController.compositionWidth;
-                        var containerHeight:Number = isNaN(curContainerController.compositionHeight) ? curContainerController.getTotalPaddingTop()+bounds.height : curContainerController.compositionHeight;
-                        
-                        containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
-                        containerPoint = DisplayObject(curContainerController.container).globalToLocal(containerPoint);
-                        
-                        // remove scrollRect effects for the distance test but add it back in for the result
-                        var adjustX:Number = 0;
-                        var adjustY:Number = 0;
-                        
-                        if (curContainerController.hasScrollRect)
-                        {
-                            containerPoint.x -= (adjustX = curContainerController.container.scrollRect.x);
-                            containerPoint.y -= (adjustY = curContainerController.container.scrollRect.y);
-                        }
-                        
-                        if ((containerPoint.x >= 0) && (containerPoint.x <= containerWidth) &&
-                            (containerPoint.y >= 0) && (containerPoint.y <= containerHeight))
-                        {
-                            controllerCandidate = curContainerController;
-                            candidateLocalX = containerPoint.x+adjustX;
-                            candidateLocalY = containerPoint.y+adjustY;
-                            break;
-                        }
-                        
-                        // figure minimum distance of containerPoint to curContainerController - 8 cases
-                        var relDistanceX:Number = 0;
-                        var relDistanceY:Number = 0;
-
-                        if (containerPoint.x < 0)
-                        {
-                            relDistanceX = containerPoint.x;
-                            if (containerPoint.y < 0)
-                                relDistanceY = containerPoint.y;
-                            else if (containerPoint.y > containerHeight)
-                                relDistanceY = containerPoint.y-containerHeight;
-                        }
-                        else if (containerPoint.x > containerWidth)
-                        {
-                            relDistanceX = containerPoint.x-containerWidth;
-                            if (containerPoint.y < 0)
-                                relDistanceY = containerPoint.y;
-                            else if (containerPoint.y > containerHeight)
-                                relDistanceY = containerPoint.y-containerHeight;
-                        }
-                        else if (containerPoint.y < 0)
-                            relDistanceY = -containerPoint.y;
-                        else
-                            relDistanceY = containerPoint.y-containerHeight;
-                        var tempDist:Number = relDistanceX*relDistanceX + relDistanceY*relDistanceY;    // could do sqrt but why bother - there is no Math.hypot function
-                        if (tempDist <= relDistance)
-                        {
-                            relDistance = tempDist;
-                            controllerCandidate = curContainerController;
-                            candidateLocalX = containerPoint.x+adjustX;
-                            candidateLocalY = containerPoint.y+adjustY;
-                        }
-                    }
-
-
-                    rslt = controllerCandidate ? computeSelectionIndexInContainer(textFlow, controllerCandidate, candidateLocalX, candidateLocalY) : -1;
-                }
+				var localPoint:Point = new Point(localX,localY);
+                var controller:ContainerController = findController(textFlow, target, currentTarget, localPoint);
+				rslt = controller ? computeSelectionIndexInContainer(textFlow, controller, localPoint.x, localPoint.y) : -1;
             }
             
             if (rslt >= textFlow.textLength)
@@ -1339,7 +1951,50 @@ package flashx.textLayout.edit
          */ 
         public function mouseDownHandler(event:MouseEvent):void
         {
-            handleMouseEventForSelection(event, event.shiftKey);
+			if(subManager)
+				subManager.selectRange(-1,-1);
+			
+			var cell:TableCellElement = _textFlow.parentElement as TableCellElement;
+			var coords:CellCoordinates;
+			if(!cell)
+				coords = computeCellCoordinates(textFlow,event.target,event.currentTarget,event.localX, event.localY);
+			if(cell || coords)
+			{
+				if(coords)
+					cell = currentTable.findCell(coords);
+				
+				superManager = cell.getTextFlow().interactionManager;
+				if(event.shiftKey && cell.getTable() == superManager.currentTable)
+				{
+					// expand cell selection if applicable
+					coords = new CellCoordinates(cell.rowIndex,cell.colIndex);
+					if(
+						!CellCoordinates.areEqual(coords,superManager.anchorCellPosition) ||
+						superManager.activeCellPosition.isValid()
+					){
+						superManager.selectCellRange(superManager.anchorCellPosition,coords);
+						superManager.subManager = null;
+						allowOperationMerge = false;
+						event.stopPropagation();
+						return;
+					}
+				}
+				if(superManager == this)
+				{
+					if(cell.textFlow.interactionManager)
+					{
+						cell.textFlow.interactionManager.mouseDownHandler(event);
+					}
+					return;
+				}
+				superManager.currentTable = cell.getTable();
+				superManager.deselect();
+				//superManager.setSelectionState(new SelectionState(superManager.textFlow,-1,-1) );
+				superManager.anchorCellPosition.column = cell.colIndex;
+				superManager.anchorCellPosition.row = cell.rowIndex;
+				superManager.subManager = this;
+			}
+            handleMouseEventForSelection(event, event.shiftKey, cell != null);
         }
         
         /**
@@ -1348,17 +2003,56 @@ package flashx.textLayout.edit
          * @playerversion AIR 1.5
          * @langversion 3.0
          */ 
-        public function mouseMoveHandler(event:MouseEvent):void
-        {
+        public function mouseMoveHandler(event:MouseEvent):void {
             var wmode:String = textFlow.computedFormat.blockProgression;            
-            if (wmode != BlockProgression.RL) 
-                setMouseCursor(MouseCursor.IBEAM);          
+			
+			if (wmode != BlockProgression.RL) {
+                setMouseCursor(MouseCursor.IBEAM);
+			}
+			
+			
             if (event.buttonDown)
-                handleMouseEventForSelection(event, true);
+			{
+				var cell:TableCellElement = _textFlow.parentElement as TableCellElement;
+				
+				// if the event is owned by a cell, we need to check if the mouse is now above another cell to select a cell range.
+				if (cell) {
+					
+					do {
+						var cellCoords:CellCoordinates = new CellCoordinates(cell.rowIndex, cell.colIndex, cell.getTable());
+						var coords:CellCoordinates = computeCellCoordinates(cell.getTextFlow(), event.target, event.currentTarget, event.localX, event.localY);
+						if(!coords)
+							break;
+						if(CellCoordinates.areEqual(cellCoords, coords) &&
+							(!superManager.activeCellPosition.isValid() || CellCoordinates.areEqual(coords, superManager.activeCellPosition))
+						)
+							break;
+						if(coords.table != cellCoords.table)
+							break;
+						
+						superManager = cell.getTextFlow().interactionManager;
+						if(
+							!CellCoordinates.areEqual(coords, superManager.activeCellPosition)
+						){
+							allowOperationMerge = false;
+							superManager.selectCellRange(superManager.anchorCellPosition, coords);
+							event.stopPropagation();
+							return;
+						}
+
+						
+					}while(0);
+				}
+				if(superManager && superManager.getCellRange())
+					return;
+				
+				handleMouseEventForSelection(event, true, _textFlow.parentElement != null);
+
+			}
         }
         
         /** @private */
-        tlf_internal function handleMouseEventForSelection(event:MouseEvent, allowExtend:Boolean):void
+        tlf_internal function handleMouseEventForSelection(event:MouseEvent, allowExtend:Boolean,stopPropogate:Boolean=false):void
         {
             var startSelectionActive:Boolean = hasSelection();
             
@@ -1371,6 +2065,8 @@ package flashx.textLayout.edit
                     addSelectionShapes();
             }       
             allowOperationMerge = false;
+			if(stopPropogate)
+				event.stopPropagation();
         }
         
         /** 
@@ -1479,10 +2175,60 @@ package flashx.textLayout.edit
         {
             _mouseOverSelectionArea = true;
             var wmode:String = textFlow.computedFormat.blockProgression;
-            if (wmode != BlockProgression.RL) 
-                setMouseCursor(MouseCursor.IBEAM);  
-            else 
-                setMouseCursor(MouseCursor.AUTO);                               
+			
+            if (wmode != BlockProgression.RL) {
+				var cell:TableCellElement = _textFlow.parentElement as TableCellElement;
+				
+				// set the cursor if around the edge of the table
+				if (cell) {
+					var leftEdge:int = 5;
+					var topEdge:int = 5;
+					var globalPoint:Point = new Point(event.stageX, event.stageY);
+					var cellContainer:CellContainer = event.currentTarget as CellContainer;
+					var point:Point;
+					
+					if (cellContainer) {
+						var cellContainerPoint:Point = cellContainer.localToGlobal(new Point);
+						point = globalPoint.subtract(cellContainerPoint);
+					}
+					if(useTableSelectionCursors)
+					{
+						// set cursor for row, table or column
+						if (cell.colIndex==0 && point.x<leftEdge && point.y>topEdge)
+						{
+							event.stopPropagation();
+							event.stopImmediatePropagation();
+							setMouseCursor(SelectTableRow);
+						}
+						else if (cell.rowIndex==0 && cell.colIndex==0 &&
+							point.x<leftEdge && point.y<topEdge)
+						{
+							event.stopPropagation();
+							event.stopImmediatePropagation();
+							setMouseCursor(SelectTable);
+						}
+						else if (cell.rowIndex==0 && point.x>leftEdge && point.y<topEdge)
+						{
+							event.stopPropagation();
+							event.stopImmediatePropagation();
+							setMouseCursor(SelectTableColumn);
+						}
+						else {
+							setMouseCursor(MouseCursor.IBEAM);
+						}
+						
+					}
+					else {
+						setMouseCursor(MouseCursor.IBEAM);
+					}
+				}
+				else {
+                	setMouseCursor(MouseCursor.IBEAM);
+				}
+			}
+            else {
+                setMouseCursor(MouseCursor.AUTO);
+			}
         }
 
         /** 
@@ -1873,6 +2619,9 @@ package flashx.textLayout.edit
             }
             else if (event.keyCode == Keyboard.ESCAPE)
                 handleKeyEvent(event);
+			if(_textFlow.parentElement)
+				event.stopPropagation();
+			
         }
 
         /** 
@@ -2098,9 +2847,26 @@ package flashx.textLayout.edit
         {
             var idx:int = marks.indexOf(mark);
             if (idx != -1)
-                marks.splice(idx,idx+1);
+                marks.splice(idx,1);
         }
-        
+
+		private var cellMarks:Array = [];
+		
+		/** @private */
+		tlf_internal function createCellMark():CellCoordinates
+		{
+			var mark:CellCoordinates = new CellCoordinates(-1,-1);
+			cellMarks.push(mark);
+			return mark;
+		}
+		/** @private */
+		tlf_internal function removeCellMark(mark:CellCoordinates):void
+		{
+			var idx:int = cellMarks.indexOf(mark);
+			if (idx != -1)
+				marks.splice(idx,1);
+		}
+
         /** 
          * @copy ISelectionManager#notifyInsertOrDelete()
          * 
@@ -2126,5 +2892,138 @@ package flashx.textLayout.edit
                 }
             }
         }
+
+		/**
+		 * The ISelectionManager object used to for cell selections nested within the TextFlow managed by this ISelectionManager.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 
+		public function get subManager():ISelectionManager
+		{
+			return _subManager;
+		}
+		public function set subManager(value:ISelectionManager):void
+		{
+			if(_subManager)
+				_subManager.selectRange(-1,-1);
+			_subManager = value;
+		}
+		/**
+		 * The ISelectionManager object used to manage the parent TextFlow of this ISelectionManager (i.e. for cell ISelectionManagers).
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 
+
+		public function get superManager():ISelectionManager
+		{
+			return _superManager;
+		}
+
+		public function set superManager(value:ISelectionManager):void
+		{
+			_superManager = value;
+		}
+
+		/** Anchor point of the current cell selection, as coordinates within the table. */
+		public function get anchorCellPosition():CellCoordinates
+		{
+			return _anchorCellPosition;
+		}
+		public function set anchorCellPosition(value:CellCoordinates):void
+		{
+			_anchorCellPosition = value;
+		}
+
+		/** Active end of the current cell selection, as coordinates within the table. */
+		public function get activeCellPosition():CellCoordinates
+		{
+			return _activeCellPosition;
+		}
+		public function set activeCellPosition(value:CellCoordinates):void
+		{
+			_activeCellPosition = value;
+		}
+		
+		public var selectTableCursorPoints:Vector.<Number> = new <Number>[1,3, 11,3, 11,0, 12,0, 16,4, 12,8, 11,8, 11,5, 1,5, 1,3];
+		public var selectTableCursorDrawCommands:Vector.<int> = new <int>[1,2,2,2,2,2,2,2,2,2];
+		
+		
+		/**
+		 * Create a select table cursor
+		 */
+		public function createSelectTableCursor():MouseCursorData {
+			var cursorData:Vector.<BitmapData> = new Vector.<BitmapData>();
+			var cursorShape:Shape = new Shape();
+			cursorShape.graphics.beginFill(0x0, 1);
+			cursorShape.graphics.lineStyle(0, 0xFFFFFF, 1, true);
+			cursorShape.graphics.drawPath( selectTableCursorDrawCommands, selectTableCursorPoints);
+			cursorShape.graphics.endFill();
+			var transformer:Matrix = new Matrix();
+			var cursorFrame:BitmapData = new BitmapData(32, 32, true, 0);
+			var angle:int = 8;
+			var rotation:Number = 0.785398163;
+			transformer.translate(-angle,-angle);
+			transformer.rotate(rotation);
+			transformer.translate(angle, angle);
+			cursorFrame.draw(cursorShape, transformer);
+			cursorData.push(cursorFrame);
+			var mouseCursorData:MouseCursorData = new MouseCursorData();
+			mouseCursorData.data = cursorData;
+			mouseCursorData.hotSpot = new Point(16, 10);
+			mouseCursorData.frameRate = 1;
+			return mouseCursorData;
+		}
+		
+		/**
+		 * Create a select row cursor
+		 */
+		public function createSelectTableRowCursor():MouseCursorData {
+			var cursorData:Vector.<BitmapData> = new Vector.<BitmapData>();
+			var cursorShape:Shape = new Shape();
+			cursorShape.graphics.beginFill(0x0, 1);
+			cursorShape.graphics.lineStyle(0, 0xFFFFFF, 1, true);
+			cursorShape.graphics.drawPath(selectTableCursorDrawCommands, selectTableCursorPoints);
+			cursorShape.graphics.endFill();
+			var transformer:Matrix = new Matrix();
+			var cursorFrame:BitmapData = new BitmapData(32, 32, true, 0);
+			cursorFrame.draw(cursorShape, transformer);
+			cursorData.push(cursorFrame);
+			var mouseCursorData:MouseCursorData = new MouseCursorData();
+			mouseCursorData.data = cursorData;
+			mouseCursorData.hotSpot = new Point(16, 4);
+			mouseCursorData.frameRate = 1;
+			return mouseCursorData;
+		}
+		
+		/**
+		 * Create a select table column cursor
+		 */
+		public function createSelectTableColumnCursor():MouseCursorData {
+			var cursorData:Vector.<BitmapData> = new Vector.<BitmapData>();
+			var cursorShape:Shape = new Shape();
+			cursorShape.graphics.beginFill(0x0, 1 );
+			cursorShape.graphics.lineStyle(0, 0xFFFFFF, 1, true );
+			cursorShape.graphics.drawPath(selectTableCursorDrawCommands, selectTableCursorPoints);
+			cursorShape.graphics.endFill();
+			var transformer:Matrix = new Matrix();
+			var cursorFrame:BitmapData = new BitmapData(32, 32, true, 0);
+			var angle:int = 16;
+			var rotation:Number = 0.785398163;
+			transformer.translate(-angle,-angle);
+			transformer.rotate(rotation * 2);
+			transformer.translate(angle, angle);
+			cursorFrame.draw(cursorShape, transformer);
+			cursorData.push(cursorFrame);
+			var mouseCursorData:MouseCursorData = new MouseCursorData();
+			mouseCursorData.data = cursorData;
+			mouseCursorData.hotSpot = new Point(28, 16);
+			mouseCursorData.frameRate = 1;
+			return mouseCursorData;
+		}
+
     }
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/SelectionState.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/SelectionState.as b/textLayout/src/flashx/textLayout/edit/SelectionState.as
index 4d500e4..379f023 100644
--- a/textLayout/src/flashx/textLayout/edit/SelectionState.as
+++ b/textLayout/src/flashx/textLayout/edit/SelectionState.as
@@ -27,6 +27,8 @@ package flashx.textLayout.edit
 	use namespace tlf_internal;
 	
 	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.elements.CellRange;
+
 	use namespace tlf_internal;
 	/**
 	 * The SelectionState class represents a selection in a text flow.  
@@ -49,6 +51,8 @@ package flashx.textLayout.edit
 		/** Format that are associated with the caret position & will be applied to inserted text */
 		private var _pointFormat:ITextLayoutFormat;
 		
+		private var _cellRange:CellRange;
+		
 		private var _selectionManagerOperationState:Boolean;
 
 		/** 
@@ -72,11 +76,12 @@ package flashx.textLayout.edit
 		 * @playerversion AIR 1.5
  	 	 * @langversion 3.0
 		 */		
-		public function SelectionState(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null)
+		public function SelectionState(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null,cellRange:CellRange = null)
 		{
 			super(root, anchorPosition, activePosition);
 			if (format)
 				_pointFormat = format;
+			_cellRange = cellRange;
 		}
 		
 		/** 
@@ -126,5 +131,20 @@ package flashx.textLayout.edit
 		/** @private */
 		tlf_internal function clone():SelectionState
 		{ return new SelectionState(textFlow,anchorPosition,activePosition,pointFormat); }
+
+		/** Range of table cells in selection (null if no cells selected)*/
+		public function get cellRange():CellRange
+		{
+			return _cellRange;
+		}
+
+		/**
+		 * @private
+		 */
+		public function set cellRange(value:CellRange):void
+		{
+			_cellRange = value;
+		}
+
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as b/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
index 347aa53..235cd08 100644
--- a/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
+++ b/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
@@ -1114,10 +1114,14 @@ package flashx.textLayout.edit
 		/** if parent is a singleton element, deletes it, then repeats deletion of singletons up the parent chain.  Used after paragraph merge. */
 		tlf_internal static function removeEmptyParentChain(parent:FlowGroupElement):IMemento
 		{
+			if(parent is ParagraphElement)
+				ParagraphElement(parent).removeEmptyTerminator();
 			var mementoList:MementoList = new MementoList(parent.getTextFlow());
 			while(parent && (parent.numChildren == 0))
 			{
 				var grandParent:FlowGroupElement = parent.parent;
+				if(grandParent is ParagraphElement)
+					ParagraphElement(grandParent).removeEmptyTerminator();
 				if(grandParent)
 				{
 					var parentIdx:int = grandParent.getChildIndex(parent);

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/BackgroundManager.as b/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
index adee363..b29accf 100644
--- a/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
+++ b/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
@@ -32,6 +32,7 @@ package flashx.textLayout.elements
 	import flashx.textLayout.compose.ParcelList;
 	import flashx.textLayout.compose.StandardFlowComposer;
 	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.compose.TextFlowTableBlock;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.container.TextContainerManager;
 	import flashx.textLayout.debug.assert;
@@ -45,7 +46,6 @@ package flashx.textLayout.elements
 	
 	use namespace tlf_internal;
 	
-	[ExcludeClass]
 	/** @private Manages bounds calculation and rendering of backgroundColor character format. */
 	public class BackgroundManager
 	{
@@ -109,6 +109,34 @@ package flashx.textLayout.elements
 			}
 		}
 		
+		public static function collectTableBlock(_textFlow:TextFlow,block:TextFlowTableBlock,controller:ContainerController):void
+		{
+			// add block rect for each cell in table block
+			
+			var bb:BackgroundManager;
+			var r:Rectangle;
+			var composer:IFlowComposer;
+
+			var cells:Vector.<TableCellElement> = block.getTableCells();
+			for each(var cell:TableCellElement in cells){
+				if(BackgroundManager.hasBorderOrBackground(cell))
+				{
+					if(!_textFlow.backgroundManager)
+						_textFlow.getBackgroundManager();
+					bb = _textFlow.backgroundManager;
+
+					bb.addBlockElement(cell);
+
+					var row:TableRowElement = cell.getRow();
+					r = new Rectangle(cell.x, cell.y + block.y, cell.width, row.composedHeight);
+					bb.addBlockRect(cell, r, controller);
+
+				}
+			}
+			block.y;
+			
+		}
+		
 		public static function collectBlock(_textFlow:TextFlow, elem:FlowGroupElement, _parcelList:ParcelList = null, tableComposeNotFromBeginning:Boolean = false, tableOutOfView:Boolean = false):void
 		{
 			var bb:BackgroundManager;
@@ -118,61 +146,8 @@ package flashx.textLayout.elements
 
 			if(elem)
 			{
-				//The height of TableDataCellElement can only be identified after all the cells in the row are composed.
-				//So, pick it out of the common process 
-				if(elem is TableRowElement)
-				{
-					var tabRow:TableRowElement = elem as TableRowElement;
-					//for table cells
-					var cell:TableDataCellElement;
-					var cellParcel:Parcel;
-					for(var cIdx:Number = 0; cIdx < elem.numChildren; cIdx++)
-					{
-						cell = elem.getChildAt(cIdx) as TableDataCellElement;
-						if(BackgroundManager.hasBorderOrBackground(cell) || BackgroundManager.hasBorderOrBackground(elem))
-						{
-							//mark the paragraph that has border or background
-							if(!_textFlow.backgroundManager)
-								_textFlow.getBackgroundManager();
-							bb = _textFlow.backgroundManager;
-							
-							//BackgroundManager should not be null here
-							CONFIG::debug { assert(_textFlow.backgroundManager != null ,"BackgroundManager should not be null"); }
-							
-							bb.addBlockElement(cell);
-							
-							cellParcel = _parcelList.getParcelAt(cell.parcelIndex);
-							if(cellParcel)
-							{
-								r = new Rectangle(cell.x, cell.y, cell.width, tabRow.height);
-								bb.addBlockRect(cell, r, cellParcel.controller);
-							}
-						}
-					}
-					
-					//for table rows
-					/*if(BackgroundManager.hasBorderOrBackground(elem))
-					{
-						//mark the paragraph that has border or background
-						if(!_textFlow.backgroundManager)
-							_textFlow.getBackgroundManager();
-						bb = _textFlow.backgroundManager;
-						
-						//BackgroundManager should not be null here
-						CONFIG::debug { assert(_textFlow.backgroundManager != null ,"BackgroundManager should not be null"); }
-						
-						bb.addBlockElement(elem);
-						
-						var parentTable:TableElement = elem.parent as TableElement;
-						var rowParcel:Parcel = _parcelList.getParcelAt(tabRow.parcelIndex);
-						if(parentTable && rowParcel){
-							r = new Rectangle(parentTable.x + rowParcel.x, tabRow.y + rowParcel.y, parentTable.computedWidth, tabRow.height);
-							bb.addBlockRect(elem, r, rowParcel.controller);
-						}
-					}*/
-				}
-				//for the other elements
-				else if(BackgroundManager.hasBorderOrBackground(elem))
+
+				if(BackgroundManager.hasBorderOrBackground(elem))
 				{
 					//mark the paragraph that has border or background
 					if(!_textFlow.backgroundManager)
@@ -189,61 +164,9 @@ package flashx.textLayout.elements
 					{
 						if(elem is TableElement)
 						{
+							// Do we need to do anything for table elements? Not sure...
 							var tab:TableElement = elem as TableElement;
-							var parcel:Parcel;
-							if(tab.numAcrossParcels == 0)
-							{
-								r = new Rectangle();
-								parcel = _parcelList.getParcelAt(tab.originParcelIndex);
-								if(parcel)
-								{
-									if(tableComposeNotFromBeginning)
-									{
-										r.x = parcel.x;
-										r.y = parcel.y;
-									}
-									else
-									{
-										r.x = tab.x;
-										r.y = tab.y;
-									}
-									r.width = tab.computedWidth;
-									r.height = tab.height;
-									bb.addBlockRect(elem, r, parcel.controller);
-								}
-							}else
-							{
-								for(var tIdx:Number = 0; tIdx <= tab.numAcrossParcels; tIdx++)
-								{
-									r = new Rectangle();
-									parcel = _parcelList.getParcelAt(tab.originParcelIndex + tIdx);
-									if(parcel)
-									{
-										if(tIdx == 0 && !tableComposeNotFromBeginning)
-										{
-											r.x = tab.x;
-											r.y = tab.y;
-											r.width = tab.computedWidth;
-											r.height = tab.heightArray[tIdx];
-											bb.addBlockRect(elem, r, parcel.controller, BackgroundManager.BOTTOM_EXCLUDED);
-										}else if (tIdx == tab.numAcrossParcels && !tableOutOfView)
-										{
-											r.x = parcel.x + tab.computedFormat.marginLeft;
-											r.y = parcel.y;
-											r.width = tab.computedWidth;
-											r.height = tab.totalRowDepth;
-											bb.addBlockRect(elem, r, parcel.controller, BackgroundManager.TOP_EXCLUDED);
-										}else
-										{
-											r.x = parcel.x + tab.computedFormat.marginLeft;
-											r.y = parcel.y;
-											r.width = tab.computedWidth;
-											r.height = tab.heightArray[tIdx];
-											bb.addBlockRect(elem, r, parcel.controller, BackgroundManager.TOP_AND_BOTTOM_EXCLUDED);
-										}
-									}
-								}
-							}
+
 						}
 						else //for elements like ParagraphElement, DivElement, ListItemElement, ListElement, TextFlow
 						{	
@@ -461,8 +384,9 @@ package flashx.textLayout.elements
 					//draw background
 					if(style.backgroundColor != BackgroundColor.TRANSPARENT)
 					{
-						g.lineStyle(0, style.backgroundColor, style.backgroundAlpha, true);
-						g.beginFill(style.backgroundColor);
+						// The value 0 indicates hairline thickness; 
+						g.lineStyle(NaN, style.backgroundColor, style.backgroundAlpha, true);
+						g.beginFill(style.backgroundColor, style.backgroundAlpha);
 						g.drawRect(rec.x, rec.y, rec.width, rec.height);
 						g.endFill();
 					}
@@ -577,8 +501,9 @@ package flashx.textLayout.elements
 							//draw background
 							if(style.backgroundColor != BackgroundColor.TRANSPARENT)
 							{
-								g.lineStyle(0, style.backgroundColor, style.backgroundAlpha, true);
-								g.beginFill(style.backgroundColor);
+								// The value 0 indicates hairline thickness; NaN removes line
+								g.lineStyle(NaN, style.backgroundColor, style.backgroundAlpha, true);
+								g.beginFill(style.backgroundColor, style.backgroundAlpha);
 								g.drawRect(rec.x, rec.y, rec.width, rec.height);
 								g.endFill();
 							}
@@ -618,7 +543,11 @@ package flashx.textLayout.elements
 				//draw background for span	
 				for(var childIdx:int = 0; childIdx<controller.textLines.length; ++childIdx)
 				{
-					var tl:TextLine = controller.textLines[childIdx];
+					var line:* = controller.textLines[childIdx];
+					// skip TextFlowTableBlocks
+					if(!(line is TextLine))
+						continue;
+					var tl:TextLine = line;
 					var entry:Array = _lineDict[tl];
 		
 					if (entry)

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/CellContainer.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/CellContainer.as b/textLayout/src/flashx/textLayout/elements/CellContainer.as
index 336da5a..256c495 100644
--- a/textLayout/src/flashx/textLayout/elements/CellContainer.as
+++ b/textLayout/src/flashx/textLayout/elements/CellContainer.as
@@ -20,13 +20,37 @@ package flashx.textLayout.elements
 {
 	import flash.display.Sprite;
 	
-	public class CellContainer extends Sprite
+	//import mx.core.IIMESupport;
+	
+	public class CellContainer extends Sprite// implements IIMESupport
 	{
-		public var userData:Object=null;
+		private var _imeMode:String;
+		private var _enableIME:Boolean;
+		public var element:TableCellElement;
+
+		public function CellContainer(imeEnabled:Boolean = true)
+		{
+			_enableIME = imeEnabled;
+		}
+		
+		public function get enableIME():Boolean
+		{
+			return false;
+		}
+		
+		public function set enableIME(value:Boolean):void
+		{
+			_enableIME = value;
+		}
+		
+		public function get imeMode():String
+		{
+			return _imeMode;
+		}
 		
-		public function CellContainer()
+		public function set imeMode(value:String):void
 		{
-			super();
+			_imeMode = value;
 		}
 	}
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/FlowElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/FlowElement.as b/textLayout/src/flashx/textLayout/elements/FlowElement.as
index 6ef5053..12ba288 100644
--- a/textLayout/src/flashx/textLayout/elements/FlowElement.as
+++ b/textLayout/src/flashx/textLayout/elements/FlowElement.as
@@ -805,6 +805,14 @@ package flashx.textLayout.elements
 		{ setStyle(styleProp,undefined); }
 		
 		/**
+		 * Called when an element is removed. Used for container elements to run any clean up code. 
+		 **/
+		tlf_internal function removed():void
+		{
+			// override in sub classes
+		}
+		
+		/**
 		 * Called whenever the model is modified.  Updates the TextFlow and notifies the selection manager - if it is set.
 		 * This method has to be called while the element is still in the flow
 		 * @param changeType - type of change
@@ -1024,6 +1032,24 @@ package flashx.textLayout.elements
 		}
 		
 		
+		public function isInTable():Boolean
+		{
+			var tf:TextFlow = getTextFlow();
+			return tf && tf.parentElement && tf.parentElement is TableCellElement;
+		}
+		
+		public function getParentCellElement():TableCellElement
+		{
+			var tf:TextFlow = getTextFlow();
+			
+			if(!tf)
+				return null;
+			if(tf.parentElement && tf.parentElement is TableCellElement)
+				return tf.parentElement as TableCellElement;
+			return null;
+		}
+
+		
 		/** 
 		 * Returns the FlowElement object that contains this FlowElement object, if this element is contained within 
 		 * an element of a particular type. 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as b/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
index b02a22d..62567dd 100644
--- a/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
+++ b/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
@@ -582,7 +582,7 @@ package flashx.textLayout.elements
 		}
 		
 		/** @private */
-		tlf_internal function createContentAsGroup():GroupElement
+		tlf_internal function createContentAsGroup(pos:int=0):GroupElement
 		{
 			CONFIG::debug { assert(false,"invalid call to createContentAsGroup"); }
 			return null;
@@ -626,7 +626,7 @@ package flashx.textLayout.elements
 		 */
 		tlf_internal function canOwnFlowElement(elem:FlowElement):Boolean
 		{
-			return !(elem is TextFlow) && !(elem is FlowLeafElement) && !(elem is SubParagraphGroupElementBase) && !(elem is ListItemElement);
+			return !(elem is TextFlow) && !(elem is FlowLeafElement) && !(elem is SubParagraphGroupElementBase) && !(elem is ListItemElement) && !(elem is TableElement);
 		}
 		
 		/** @private */	
@@ -687,6 +687,7 @@ package flashx.textLayout.elements
 				{
 					child = this.getChildAt(beginChildIndex);
 					this.modelChanged(ModelChange.ELEMENT_REMOVAL, child, child.parentRelativeStart, child.textLength);
+					child.removed();
 					len += child.textLength;
 					
 					child.setParentAndRelativeStart(null,0);
@@ -770,8 +771,10 @@ package flashx.textLayout.elements
 								relStartIdx = beginChildIndex == _numChildren ? textLength : getChildAt(beginChildIndex).parentRelativeStart;
 							}
 						}
-						if (!canOwnFlowElement(newChild))
-							throw ArgumentError(GlobalSettings.resourceStringFunction("invalidChildType"));
+						
+						if (!canOwnFlowElement(newChild)) {
+							throw ArgumentError(GlobalSettings.resourceStringFunction("invalidChildType") + ". " + defaultTypeName + " cannot own " + newChild.defaultTypeName);
+						}
 						
 						// manage as an array or a single child
 						if (childrenToAdd == 0)
@@ -988,6 +991,7 @@ package flashx.textLayout.elements
 				parent.replaceChildren(myidx+1,myidx+1,newSibling);
 			}
 
+			newSibling.normalizeRange(0,newSibling.textLength);
 			return newSibling;
 		}
 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as b/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
index 22bfe40..894a362 100644
--- a/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
+++ b/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
@@ -337,6 +337,8 @@ package flashx.textLayout.elements
 		{
 			if (!_blockElement)
 				createContentElement();
+			if(!_blockElement)
+				return null;
 			var ef:ElementFormat = _blockElement.elementFormat;
 			if (!ef)
 				return null;