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

git commit: [flex-sdk] [refs/heads/develop] - Moved button logic in to main RTE class. Moved all the diplay parts in to the skin.

Repository: flex-sdk
Updated Branches:
  refs/heads/develop 4f6fe2edb -> fb48bb700


Moved button logic in to main RTE class. Moved all the diplay parts in to the skin.


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

Branch: refs/heads/develop
Commit: fb48bb7008d0a431c4fade370e58488e6bf62633
Parents: 4f6fe2e
Author: cjaube <cu...@piematrix.com>
Authored: Mon Nov 24 23:24:14 2014 -0500
Committer: cjaube <cu...@piematrix.com>
Committed: Mon Nov 24 23:24:14 2014 -0500

----------------------------------------------------------------------
 frameworks/projects/experimental/defaults.css   |   4 +
 frameworks/projects/experimental/manifest.xml   |   2 +
 .../experimental/src/ExperimentalClasses.as     |   1 +
 .../src/spark/components/RichTextEditor.as      | 643 +++++++++++++++++--
 .../richTextEditorClasses/AlignTool.mxml        | 105 +--
 .../richTextEditorClasses/BoldTool.mxml         |  55 +-
 .../richTextEditorClasses/BulletTool.mxml       | 165 +----
 .../richTextEditorClasses/ColorTool.mxml        |  55 +-
 .../richTextEditorClasses/FontTool.mxml         |  55 +-
 .../richTextEditorClasses/ItalicTool.mxml       |  57 +-
 .../richTextEditorClasses/LinkTool.mxml         | 226 +------
 .../RichTextEditorToolBar.mxml                  | 105 ---
 .../richTextEditorClasses/SizeTool.mxml         |  49 +-
 .../richTextEditorClasses/UnderlineTool.mxml    |  58 +-
 .../src/spark/skins/AlignToolSkin.mxml          |  86 ---
 .../src/spark/skins/RichTextEditorSkin.mxml     |  78 +++
 .../richTextEditorClasses/AlignToolSkin.mxml    |  86 +++
 17 files changed, 884 insertions(+), 946 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/defaults.css
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/defaults.css b/frameworks/projects/experimental/defaults.css
index 033d0b0..7d2a3ba 100644
--- a/frameworks/projects/experimental/defaults.css
+++ b/frameworks/projects/experimental/defaults.css
@@ -100,4 +100,8 @@ MaskedTextInput #promptDisplay {
 
 MaskedTextInput:disabledWithPrompt {
     color: #cccccc;
+}
+
+RichTextEditor {
+	skinClass: ClassReference("spark.skins.RichTextEditorSkin");
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/manifest.xml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/manifest.xml b/frameworks/projects/experimental/manifest.xml
index 440eae5..6ae1e5d 100644
--- a/frameworks/projects/experimental/manifest.xml
+++ b/frameworks/projects/experimental/manifest.xml
@@ -49,6 +49,8 @@
     <component id="MenuBarItemRenderer" class="spark.components.itemRenderers.MenuBarItemRenderer"/>
     <!-- ProgressBar -->
     <component id="ProgressBar" class="spark.components.ProgressBar"/>
+    <!-- RichTextEditor -->
+    <component id="RichTextEditor" class="spark.components.RichTextEditor"/>
     
 	<!-- containers -->
     <component id="Accordion" class="spark.containers.Accordion"/>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/ExperimentalClasses.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/ExperimentalClasses.as b/frameworks/projects/experimental/src/ExperimentalClasses.as
index 33024da..f392be0 100644
--- a/frameworks/projects/experimental/src/ExperimentalClasses.as
+++ b/frameworks/projects/experimental/src/ExperimentalClasses.as
@@ -64,6 +64,7 @@ package
 		import spark.skins.MenuSkin; MenuSkin;
 		import spark.skins.NavigatorSkin; NavigatorSkin;
 		import spark.skins.ProgressBarSkin; ProgressBarSkin;
+		import spark.skins.RichTextEditorSkin; RichTextEditorSkin;
 		import spark.skins.TabNavigatorSkin; TabNavigatorSkin;
 		import spark.skins.VNoTrackNoThumbScrollBarSkin; VNoTrackNoThumbScrollBarSkin;
 		import spark.supportClasses.INavigator; INavigator;

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/RichTextEditor.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/RichTextEditor.as b/frameworks/projects/experimental/src/spark/components/RichTextEditor.as
index 1507d9e..32945f2 100644
--- a/frameworks/projects/experimental/src/spark/components/RichTextEditor.as
+++ b/frameworks/projects/experimental/src/spark/components/RichTextEditor.as
@@ -20,27 +20,85 @@
 package spark.components
 {
 	import flash.events.Event;
+	import flash.events.FocusEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.MouseEvent;
+	import flash.text.engine.FontPosture;
+	import flash.text.engine.FontWeight;
+	import flash.ui.Keyboard;
 	import flash.utils.Dictionary;
+	
+	import mx.events.FlexEvent;
+	
+	import spark.components.richTextEditorClasses.AlignTool;
+	import spark.components.richTextEditorClasses.BoldTool;
+	import spark.components.richTextEditorClasses.BulletTool;
+	import spark.components.richTextEditorClasses.ColorTool;
+	import spark.components.richTextEditorClasses.FontTool;
+	import spark.components.richTextEditorClasses.ItalicTool;
+	import spark.components.richTextEditorClasses.LinkTool;
+	import spark.components.richTextEditorClasses.SizeTool;
+	import spark.components.richTextEditorClasses.UnderlineTool;
+	import spark.components.supportClasses.SkinnableComponent;
+	import spark.events.ColorChangeEvent;
+	import spark.events.IndexChangeEvent;
+	import spark.events.TextOperationEvent;
+	
 	import flashx.textLayout.conversion.ConversionType;
 	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.ElementRange;
+	import flashx.textLayout.edit.IEditManager;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.ListElement;
+	import flashx.textLayout.elements.ParagraphElement;
 	import flashx.textLayout.elements.TextFlow;
-	import spark.components.richTextEditorClasses.RichTextEditorToolBar;
-	import spark.events.TextOperationEvent;
+	import flashx.textLayout.formats.TextAlign;
+	import flashx.textLayout.formats.TextDecoration;
+	import flashx.textLayout.formats.TextLayoutFormat;
 
 	// for asdoc
 	[Experimental]
 	[Event(name = "change", type = "flash.events.Event")]
 	[Style(name = "borderColor", inherit = "no", type = "unit")]
 	[Style(name = "focusColor", inherit = "yes", type = "unit")]
-	public class RichTextEditor extends Group
+	public class RichTextEditor extends SkinnableComponent
 	{
 		private var _htmlText:String;
 		private var _htmlTextChanged:Boolean = false;
 		private var _prompt:String = "";
 		private var _stylesChanged:Dictionary = new Dictionary;
 		private var _text:String;
-		private var _textArea:TextArea;
 		private var _textFlow:TextFlow;
+		private var _linkSelected:Boolean = false;
+		private var _urlRegExpression:RegExp = new RegExp("^(https?://(www\\.)?|www\\.)[-._~:/?#\\[\\]@!$&'()*+,;=a-z0-9]+$", 'i');
+		private const _defaultLinkText:String = "http://";
+		private var _linkEl:LinkElement
+		private var _lastRange:ElementRange;
+		
+		[SkinPart(required="true")]
+		public var textArea:TextArea;
+		[SkinPart(required="false")]
+		public var fontTool:FontTool;
+		[SkinPart(required="false")]
+		public var sizeTool:SizeTool;
+		[SkinPart(required="false")]
+		public var boldTool:BoldTool;
+		[SkinPart(required="false")]
+		public var italicTool:ItalicTool;
+		[SkinPart(required="false")]
+		public var underlineTool:UnderlineTool;
+		[SkinPart(required="false")]
+		public var colorTool:ColorTool;
+		[SkinPart(required="false")]
+		public var alignTool:AlignTool;
+		[SkinPart(required="false")]
+		public var bulletTool:BulletTool;
+		[SkinPart(required="false")]
+		public var linkTool:LinkTool;
 
 		public function RichTextEditor()
 		{
@@ -98,9 +156,9 @@ package spark.components
 		public function set prompt(value:String):void
 		{
 			_prompt = value;
-			if (_textArea)
+			if (textArea)
 			{
-				_textArea.prompt = _prompt;
+				textArea.prompt = _prompt;
 			}
 		}
 
@@ -120,9 +178,9 @@ package spark.components
 		 */
 		public function get text():String
 		{
-			if (_textArea)
+			if (textArea)
 			{
-				return _textArea.text;
+				return textArea.text;
 			}
 			else
 			{
@@ -136,9 +194,9 @@ package spark.components
 		public function set text(value:String):void
 		{
 			_text = value;
-			if (_textArea)
+			if (textArea)
 			{
-				_textArea.text = value;
+				textArea.text = value;
 			}
 		}
 
@@ -157,45 +215,123 @@ package spark.components
 		public function set textFlow(value:TextFlow):void
 		{
 			_textFlow = value;
-			if (_textArea)
+			if (textArea)
 			{
-				_textArea.textFlow = value;
+				textArea.textFlow = value;
 			}
 		}
 
 		/**
 		 *  @private
 		 */
-		protected override function createChildren():void
-		{
-			super.createChildren();
-			var container:VGroup = new VGroup;
-			container.percentHeight = 100;
-			container.percentWidth = 100;
-			this.addElement(container);
-
-			var toolbar:RichTextEditorToolBar = new RichTextEditorToolBar();
-			toolbar.percentWidth = 100;
-			toolbar.bottom = 6;
-			container.addElement(toolbar);
-
-			_textArea = new TextArea();
-			_textArea.percentHeight = 100;
-			_textArea.percentWidth = 100;
-			_textArea.addEventListener(TextOperationEvent.CHANGE, handleChange);
-			_textArea.prompt = prompt;
-			_textArea.textFlow = textFlow;
-			if (_htmlText)
+		protected override function partAdded(partName:String, instance:Object):void
+		{ 
+			super.partAdded(partName, instance); 
+			if (instance == textArea)
 			{
-				textFlow = TextConverter.importToFlow(_htmlText, TextConverter.TEXT_FIELD_HTML_FORMAT);
+				textArea.addEventListener(TextOperationEvent.CHANGE, handleChange);
+				textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
+				textArea.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
+				textArea.prompt = prompt;
+				textArea.textFlow = textFlow;
+				if (_htmlText)
+				{
+					textFlow = TextConverter.importToFlow(_htmlText, TextConverter.TEXT_FIELD_HTML_FORMAT);
+				}
+				else if (_text)
+				{
+					textArea.text = _text;
+				}
 			}
-			else if (_text)
+			if (instance == fontTool)
+			{ 
+				fontTool.addEventListener(IndexChangeEvent.CHANGE, handleFontChange);
+			}
+			if (instance == sizeTool)
+			{ 
+				sizeTool.addEventListener(IndexChangeEvent.CHANGE, handleSizeChange);
+			} 
+			if (instance == boldTool)
+			{  
+				boldTool.addEventListener(MouseEvent.CLICK, handleBoldClick);
+			} 
+			if (instance == italicTool)
+			{ 
+				italicTool.addEventListener(MouseEvent.CLICK, handleItalicClick);
+			} 
+			if (instance == underlineTool)
+			{ 
+				underlineTool.addEventListener(MouseEvent.CLICK, handleUnderlineClick);
+			} 
+			if (instance == colorTool)
+			{ 
+				colorTool.addEventListener(ColorChangeEvent.CHOOSE, handleColorChoose);
+			} 
+			if (instance == alignTool)
+			{ 
+				alignTool.addEventListener(IndexChangeEvent.CHANGE, handleAlignChange);
+			} 
+			if (instance == bulletTool)
+			{ 
+				bulletTool.addEventListener(MouseEvent.CLICK, handleBulletClick);
+			} 
+			if (instance == linkTool)
+			{ 
+				linkTool.addEventListener(KeyboardEvent.KEY_DOWN, handleLinkKeydown);
+				linkTool.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, handleLinkUpdate);
+			}
+			handleSelectionChange();
+		}
+		
+		/**
+		 *  @private
+		 */
+		protected override function partRemoved(partName:String, instance:Object):void
+		{
+			super.partRemoved(partName, instance);
+			if (instance == textArea)
 			{
-				_textArea.text = _text;
+				textArea.removeEventListener(TextOperationEvent.CHANGE, handleChange);
+				textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
+				textArea.removeEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
 			}
-			container.addElement(_textArea);
-
-			toolbar.textArea = _textArea;
+			if (instance == fontTool)
+			{ 
+				fontTool.removeEventListener(IndexChangeEvent.CHANGE, handleFontChange);
+			}
+			if (instance == sizeTool)
+			{ 
+				sizeTool.removeEventListener(IndexChangeEvent.CHANGE, handleSizeChange);
+			} 
+			if (instance == boldTool)
+			{  
+				boldTool.removeEventListener(MouseEvent.CLICK, handleBoldClick);
+			} 
+			if (instance == italicTool)
+			{ 
+				italicTool.removeEventListener(MouseEvent.CLICK, handleItalicClick);
+			} 
+			if (instance == underlineTool)
+			{ 
+				underlineTool.removeEventListener(MouseEvent.CLICK, handleUnderlineClick);
+			} 
+			if (instance == colorTool)
+			{ 
+				colorTool.removeEventListener(ColorChangeEvent.CHOOSE, handleColorChoose);
+			} 
+			if (instance == alignTool)
+			{ 
+				alignTool.removeEventListener(IndexChangeEvent.CHANGE, handleAlignChange);
+			} 
+			if (instance == bulletTool)
+			{ 
+				bulletTool.removeEventListener(MouseEvent.CLICK, handleBulletClick);
+			} 
+			if (instance == linkTool)
+			{ 
+				linkTool.removeEventListener(KeyboardEvent.KEY_DOWN, handleLinkKeydown);
+				linkTool.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, handleLinkUpdate);
+			} 
 		}
 
 		/**
@@ -204,15 +340,421 @@ package spark.components
 		protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
 		{
 			super.updateDisplayList(unscaledWidth, unscaledHeight);
-			if (_textArea)
+			if (textArea)
 			{
 				for (var key:String in _stylesChanged)
 				{
-					_textArea.setStyle(key, _stylesChanged[key]);
+					textArea.setStyle(key, _stylesChanged[key]);
 				}
 				_stylesChanged = new Dictionary; //Clear it out
 			}
 		}
+		
+		/**
+		 *  @private
+		 *  Actually apply the link to the selection. Repair the formating in the process.
+		 */
+		private function applyLink(href:String, target:String = null, extendToLinkBoundary:Boolean = false, operationState:SelectionState = null):void
+		{
+			if (textArea && textArea.textFlow && textArea.textFlow.interactionManager is IEditManager)
+			{
+				//Get the current format
+				var txtLayFmt:TextLayoutFormat = textArea.textFlow.interactionManager.getCommonCharacterFormat();
+				//Set the link
+				if (operationState == null && _linkEl != null)
+				{
+					operationState = new SelectionState(textArea.textFlow, _linkEl.getAbsoluteStart(), _linkEl.getAbsoluteStart() + _linkEl.textLength);
+				}
+				var linkElement:LinkElement = IEditManager(textArea.textFlow.interactionManager).applyLink(href, target, extendToLinkBoundary, operationState);
+				//Fix the formatting
+				if(linkElement)
+				{
+					IEditManager(textArea.textFlow.interactionManager).clearFormatOnElement(linkElement.getChildAt(0), txtLayFmt);
+				}
+				var selectionEnd:int = Math.max(textArea.selectionActivePosition, textArea.selectionAnchorPosition);
+				textArea.selectRange(selectionEnd, selectionEnd);
+				IEditManager(textArea.textFlow.interactionManager).applyLeafFormat(txtLayFmt);
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  Automatically add a link if the previous text looks like a link
+		 */
+		private function checkLinks():void
+		{
+			var position:int = textArea.selectionActivePosition;
+			//Find the firt non-whitespace character
+			while (position > 0)
+			{
+				if (!isWhitespace(textArea.textFlow.getCharCodeAtPosition(position)))
+				{
+					break;
+				}
+				position--;
+			}
+			//Find the next whitespace character
+			while (position > 0)
+			{
+				if (isWhitespace(textArea.textFlow.getCharCodeAtPosition(position)))
+				{
+					position++; //Back up one character
+					break;
+				}
+				position--;
+			}
+			var testText:String = textArea.textFlow.getText(position, textArea.selectionActivePosition);
+			var result:Array = testText.match(_urlRegExpression);
+			if (result != null && result.length > 0)
+			{
+				if (textArea.textFlow.interactionManager is IEditManager)
+				{
+					var selectionState:SelectionState = new SelectionState(textArea.textFlow, position, textArea.selectionActivePosition);
+					if (testText.substr(0, 3) == "www")
+					{
+						testText = "http://" + testText; //Add a missing 'http://' if needed
+					}
+					applyLink(testText, "_blank", true, selectionState);
+					textArea.setFocus();
+				}
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function getBulletSelectionState():SelectionState
+		{
+			if (textArea.textFlow)
+			{
+				var selectionManager:ISelectionManager = textArea.textFlow.interactionManager;
+				var selectionState:SelectionState = selectionManager.getSelectionState();
+				var startleaf:FlowLeafElement = textArea.textFlow.findLeaf(selectionState.absoluteStart);
+				var endleaf:FlowLeafElement = textArea.textFlow.findLeaf(selectionState.absoluteEnd);
+				if (startleaf != null)
+				{
+					selectionState.absoluteStart = startleaf.getAbsoluteStart();
+				}
+				if (endleaf != null)
+				{
+					selectionState.absoluteEnd = endleaf.getAbsoluteStart() + endleaf.parentRelativeEnd - endleaf.parentRelativeStart;
+				}
+				return selectionState;
+			}
+			return null;
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleAlignChange(e:Event):void
+		{
+			if (alignTool.selectedItem)
+			{
+				var txtLayFmt:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+				txtLayFmt.textAlign = alignTool.selectedItem.value;
+				textArea.setFormatOfRange(txtLayFmt, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+				textArea.setFocus();
+				textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleBoldClick(e:MouseEvent):void
+		{
+			var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			format.fontWeight = (format.fontWeight == FontWeight.BOLD) ? FontWeight.NORMAL : FontWeight.BOLD;
+			textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			textArea.setFocus();
+			textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleBulletClick(e:MouseEvent):void
+		{
+			if (textArea.textFlow && textArea.textFlow.interactionManager is IEditManager)
+			{
+				var editManager:IEditManager = IEditManager(textArea.textFlow.interactionManager);
+				var doCreate:Boolean = true;
+				var selectionState:SelectionState = getBulletSelectionState();
+				var listElements:Array = textArea.textFlow.getElementsByTypeName("list");
+				for each (var listElement:ListElement in listElements)
+				{
+					var start:int = listElement.getAbsoluteStart();
+					var end:int = listElement.getAbsoluteStart() + listElement.parentRelativeEnd - listElement.parentRelativeStart;
+					if (selectionState.absoluteStart == start && selectionState.absoluteEnd == end)
+					{ //Same
+						removeList(listElement);
+						doCreate = false;
+						break;
+					}
+					else if (selectionState.absoluteStart == start && selectionState.absoluteEnd <= end)
+					{ //Inside touching start
+						selectionState = new SelectionState(textArea.textFlow, end, selectionState.absoluteEnd);
+						removeList(listElement);
+						editManager.createList(null, null, selectionState);
+						doCreate = false;
+						break;
+					}
+					else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd == end)
+					{ //Inside touching end
+						selectionState = new SelectionState(textArea.textFlow, selectionState.absoluteStart, start);
+						removeList(listElement);
+						editManager.createList(null, null, selectionState);
+						doCreate = false;
+						break;
+					}
+					else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd <= end)
+					{ //Inside
+						var firstRange:SelectionState = new SelectionState(textArea.textFlow, selectionState.absoluteStart, start);
+						var secondRange:SelectionState = new SelectionState(textArea.textFlow, end, selectionState.absoluteEnd);
+						removeList(listElement);
+						editManager.createList(null, null, firstRange);
+						editManager.createList(null, null, secondRange);
+						doCreate = false;
+						break;
+					}
+					else if ((selectionState.absoluteStart >= start && selectionState.absoluteStart <= end) || (selectionState.absoluteEnd >= start && selectionState.absoluteEnd <= end))
+					{ //Overlap. Include this list in the selection
+						selectionState = new SelectionState(textArea.textFlow, Math.min(start, selectionState.absoluteStart), Math.max(end, selectionState.absoluteEnd));
+						removeList(listElement);
+					}
+					else if (selectionState.absoluteStart <= start && selectionState.absoluteEnd >= end)
+					{ //surround. Remove this list since it will get added back in, only expanded.
+						removeList(listElement);
+					}
+				}
+				if (doCreate)
+				{
+					IEditManager(textArea.textFlow.interactionManager).createList(null, null, selectionState);
+				}
+				textArea.textFlow.interactionManager.setFocus();
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleColorChoose(e:ColorChangeEvent):void
+		{
+			var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			format.color = e.color
+			textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			textArea.setFocus();
+			textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleFontChange(e:Event):void
+		{
+			if (fontTool.selectedItem)
+			{
+				var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+				format.fontFamily = fontTool.selectedItem;
+				textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+				textArea.setFocus();
+				textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleItalicClick(e:MouseEvent):void
+		{
+			var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			format.fontStyle = (format.fontStyle == FontPosture.ITALIC) ? FontPosture.NORMAL : FontPosture.ITALIC;
+			textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			textArea.setFocus();
+			textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleKeyDown(e:KeyboardEvent):void
+		{
+			if (e.keyCode == Keyboard.ENTER || e.keyCode == Keyboard.SPACE || e.keyCode == Keyboard.TAB)
+			{
+				checkLinks();
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleLinkKeydown(e:KeyboardEvent):void
+		{
+			e.stopImmediatePropagation();
+			if (e.keyCode == Keyboard.ENTER)
+			{
+				handleLinkUpdate();
+				textArea.setFocus();
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  Handle link set by applying the link to the selected text
+		 */
+		private function handleLinkUpdate(e:Event = null):void
+		{
+			var urlText:String = linkTool.selectedLink == _defaultLinkText ? '' : linkTool.selectedLink;
+			applyLink(urlText, "_blank", true);
+			//Set focus to textFlow
+			textArea.textFlow.interactionManager.setFocus();
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleSelectionChange(e:FlexEvent = null):void
+		{
+			if (textArea != null)
+			{
+				var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+				if (fontTool != null)
+				{ 
+					fontTool.selectedFontFamily = format.fontFamily;
+				}
+				if (sizeTool != null)
+				{ 
+					sizeTool.selectedFontSize = format.fontSize;
+				} 
+				if (boldTool != null)
+				{  
+					boldTool.selectedFontWeight = format.fontWeight;
+				} 
+				if (italicTool != null)
+				{ 
+					italicTool.selectedFontStyle = format.fontStyle;
+				} 
+				if (underlineTool != null)
+				{ 
+					underlineTool.selectedTextDecoration = format.textDecoration;
+				} 
+				if (colorTool != null)
+				{ 
+					colorTool.selectedTextColor = format.color;
+				} 
+				if (alignTool != null)
+				{ 
+					alignTool.selectedTextAlign = format.textAlign;
+				} 
+				if (bulletTool != null)
+				{ 
+					if (textArea.textFlow)
+					{
+						var willRemoveBulletsIfClicked:Boolean = false;
+						var selectionState:SelectionState = getBulletSelectionState();
+						var listElements:Array = textArea.textFlow.getElementsByTypeName("list");
+						for each (var listElement:ListElement in listElements)
+						{
+							var start:int = listElement.getAbsoluteStart();
+							var end:int = listElement.getAbsoluteStart() + listElement.parentRelativeEnd - listElement.parentRelativeStart;
+							if (selectionState.absoluteStart == start && selectionState.absoluteEnd == end)
+							{ //Same
+								willRemoveBulletsIfClicked = true;
+								break;
+							}
+							else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd <= end)
+							{ //Inside
+								willRemoveBulletsIfClicked = true;
+								break;
+							}
+						}
+						bulletTool.selected = willRemoveBulletsIfClicked;
+						
+					}
+				} 
+				if (linkTool != null)
+				{ 
+					var bulletSelectionState:SelectionState = textArea.textFlow.interactionManager.getSelectionState();
+					if (bulletSelectionState.absoluteStart != -1 && bulletSelectionState.absoluteEnd != -1)
+					{
+						var range:ElementRange = ElementRange.createElementRange(bulletSelectionState.textFlow, bulletSelectionState.absoluteStart, bulletSelectionState.absoluteEnd);
+						if (range)
+						{
+							var linkString:String = _defaultLinkText;
+							_linkEl = range.firstLeaf.getParentByType(LinkElement) as LinkElement;
+							if (_linkEl != null)
+							{
+								var linkElStart:int = _linkEl.getAbsoluteStart();
+								var linkElEnd:int = linkElStart + _linkEl.textLength;
+								if (linkElEnd < linkElStart)
+								{
+									var temp:int = linkElStart;
+									linkElStart = linkElEnd;
+									linkElEnd = temp;
+								}
+								
+								var beginRange:int = range.absoluteStart;
+								var endRange:int = range.absoluteEnd;
+								
+								var beginPara:ParagraphElement = range.firstParagraph;
+								if (endRange == (beginPara.getAbsoluteStart() + beginPara.textLength))
+								{
+									endRange--;
+								}
+								
+								if ((beginRange == endRange) || (endRange <= linkElEnd))
+								{
+									linkString = LinkElement(_linkEl).href;
+								}
+							}
+							var newLinkSelected:Boolean = _linkEl != null;
+							if (_linkSelected != newLinkSelected)
+							{
+								_linkSelected = newLinkSelected;
+								this.dispatchEvent(new Event("linkSelectedChange"));
+							}
+							
+							linkTool.selectedLink = linkString;
+							
+							_lastRange = range;
+						}
+						else
+						{
+							_lastRange = null;
+						}
+					}
+					linkTool.enabled = textArea.selectionAnchorPosition != textArea.selectionActivePosition || _linkSelected;
+				}
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleSizeChange(e:Event):void
+		{
+			if (sizeTool.selectedItem)
+			{
+				var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+				format.fontSize = sizeTool.selectedItem;
+				textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+				textArea.setFocus();
+				textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function handleUnderlineClick(e:MouseEvent):void
+		{
+			var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			format.textDecoration = (format.textDecoration == TextDecoration.UNDERLINE) ? TextDecoration.NONE : TextDecoration.UNDERLINE;
+			textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+			textArea.setFocus();
+			textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+		}
 
 		/**
 		 *  @private
@@ -222,5 +764,26 @@ package spark.components
 			_htmlTextChanged = true;
 			this.dispatchEvent(e);
 		}
+		
+		/**
+		 *  @private
+		 */
+		private function removeList(listElement:ListElement):void
+		{
+			var editManager:IEditManager = IEditManager(textArea.textFlow.interactionManager);
+			
+			var target:FlowGroupElement = listElement.parent;
+			var targetIndex:int = target.getChildIndex(listElement);
+			editManager.moveChildren(listElement, 0, listElement.numChildren, target, targetIndex);
+		}
+		
+		/**
+		 *  @private
+		 *  Return true if the character is a whitespace character
+		 */
+		private function isWhitespace(charCode:uint):Boolean
+		{
+			return charCode === 0x0009 || charCode === 0x000A || charCode === 0x000B || charCode === 0x000C || charCode === 0x000D || charCode === 0x0020 || charCode === 0x0085 || charCode === 0x00A0 || charCode === 0x1680 || charCode === 0x180E || charCode === 0x2000 || charCode === 0x2001 || charCode === 0x2002 || charCode === 0x2003 || charCode === 0x2004 || charCode === 0x2005 || charCode === 0x2006 || charCode === 0x2007 || charCode === 0x2008 || charCode === 0x2009 || charCode === 0x200A || charCode === 0x2028 || charCode === 0x2029 || charCode === 0x202F || charCode === 0x205F || charCode === 0x3000;
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml
index 20f9c5f..e9ba133 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml
@@ -17,91 +17,30 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:ButtonBar width="80" arrowKeysWrapFocus="true" change="handleChange(event);" mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
+<s:ButtonBar arrowKeysWrapFocus="true" mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
 			 xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
-			import flashx.textLayout.formats.TextAlign;
-			import flashx.textLayout.formats.TextLayoutFormat;
 			import mx.collections.ArrayList;
-			import mx.events.FlexEvent;
-			import spark.components.TextArea;
-			import spark.events.TextOperationEvent;
-
-			[Embed(source = "../../../../assets/tools/center.png")]
-			private const CENTER:Class;
-			[Embed(source = "../../../../assets/tools/justify.png")]
-			private const JUSTIFY:Class;
-			[Embed(source = "../../../../assets/tools/left.png")]
-			private const LEFT:Class;
-			[Embed(source = "../../../../assets/tools/right.png")]
-			private const RIGHT:Class;
-
-			private var _textArea:TextArea;
-
-			/**
-			 *  The textArea that this component interacts with
-			 */
-			public function get textArea():TextArea
-			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
-				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
-				}
-				_textArea = value;
-				if (_textArea)
-				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
-				}
-			}
-
-			/**
-			 *  @private
-			 */
-			protected override function createChildren():void
-			{
-				super.createChildren();
-
-				var dp:ArrayList = new ArrayList();
-				dp.addItem({icon: LEFT, toolTip: "Left align text", value: TextAlign.LEFT});
-				dp.addItem({icon: CENTER, toolTip: "Left align text", value: TextAlign.CENTER});
-				dp.addItem({icon: RIGHT, toolTip: "Left align text", value: TextAlign.RIGHT});
-				dp.addItem({icon: JUSTIFY, toolTip: "Left align text", value: TextAlign.JUSTIFY});
-				this.dataProvider = dp;
-			}
+			import mx.core.UIComponent;
+			
+			import flashx.textLayout.formats.TextAlign;
 
-			/**
-			 *  @private
-			 */
-			private function handleChange(e:Event):void
+			public override function addChildAt(child:DisplayObject, index:int):DisplayObject
 			{
-				if (this.selectedItem)
+				if(child is UIComponent)
 				{
-					var txtLayFmt:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-					txtLayFmt.textAlign = this.selectedItem.value;
-					_textArea.setFormatOfRange(txtLayFmt, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-					_textArea.setFocus();
-					_textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+					(child as UIComponent).toolTip = null;
 				}
+				return super.addChildAt(child, index);
 			}
-
+			
 			/**
-			 *  @private
+			 *  The selected text align
 			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
+			public function set selectedTextAlign(value:String):void
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-
-				switch (format.textAlign)
+				switch (value)
 				{
 					case TextAlign.LEFT:
 						this.selectedIndex = 0;
@@ -120,6 +59,26 @@ limitations under the License.
 						break;
 				}
 			}
+			
+			/**
+			 *  The text align
+			 */
+			public function get selectedTextAlign():String
+			{
+				switch (selectedIndex)
+				{
+					case 0:
+						return TextAlign.LEFT;
+					case 1:
+						return TextAlign.CENTER;
+					case 2:
+						return TextAlign.RIGHT;
+					case 3:
+						return TextAlign.JUSTIFY;
+					default:
+						return "";
+				}
+			}
 		]]>
 	</fx:Script>
 	<fx:Declarations>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml
index 8e1e89d..2c154f9 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml
@@ -17,68 +17,39 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:ToggleButton width="20" click="handleClick(event);" icon="@Embed('../../../../assets/tools/bold.png')" mouseFocusEnabled="false" toolTip="Bold text" xmlns:fx="http://ns.adobe.com/mxml/2009"
+<s:ToggleButton mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009"
 				xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
 			import flash.text.engine.FontWeight;
-			import flashx.textLayout.formats.TextLayoutFormat;
-			import mx.events.FlexEvent;
-			import spark.components.TextArea;
-			import spark.events.TextOperationEvent;
-
-			private var _textArea:TextArea;
 
 			/**
-			 *  The textArea that this component interacts with
+			 *  The selected font weight
 			 */
-			public function get textArea():TextArea
+			public function set selectedFontWeight(value:String):void
 			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
+				if (value == FontWeight.BOLD)
 				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
+					this.selected = true;
 				}
-				_textArea = value;
-				if (_textArea)
+				else
 				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
+					this.selected = false;
 				}
 			}
-
-			/**
-			 *  @private
-			 */
-			private function handleClick(e:MouseEvent):void
-			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				format.fontWeight = (format.fontWeight == FontWeight.BOLD) ? FontWeight.NORMAL : FontWeight.BOLD;
-				_textArea.setFormatOfRange(format, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				_textArea.setFocus();
-				_textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
-			}
-
+			
 			/**
-			 *  @private
+			 *  The selected font weight
 			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
+			public function get selectedFontWeight():String
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				if (format.fontWeight == FontWeight.BOLD)
+				if (this.selected)
 				{
-					this.selected = true;
+					return FontWeight.BOLD;
 				}
 				else
 				{
-					this.selected = false;
+					return FontWeight.NORMAL;
 				}
 			}
 		]]>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml
index ca93cd8..e8555f2 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml
@@ -17,174 +17,11 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:ToggleButton width="20" click="handleClick(event);" icon="@Embed('../../../../assets/tools/bullet.png')" mouseFocusEnabled="false" toolTip="Bullet points" xmlns:fx="http://ns.adobe.com/mxml/2009"
+<s:ToggleButton mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009"
 				xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
-			import flash.text.engine.FontWeight;
-			import flashx.textLayout.edit.IEditManager;
-			import flashx.textLayout.edit.ISelectionManager;
-			import flashx.textLayout.edit.SelectionState;
-			import flashx.textLayout.elements.FlowGroupElement;
-			import flashx.textLayout.elements.FlowLeafElement;
-			import flashx.textLayout.elements.ListElement;
-			import flashx.textLayout.formats.TextLayoutFormat;
-			import mx.events.FlexEvent;
-			import spark.components.TextArea;
-			import spark.events.TextOperationEvent;
 
-			private var _textArea:TextArea;
-
-			/**
-			 *  The textArea that this component interacts with
-			 */
-			public function get textArea():TextArea
-			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
-				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
-				}
-				_textArea = value;
-				if (_textArea)
-				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
-				}
-			}
-
-			/**
-			 *  @private
-			 */
-			private function getSelectionState():SelectionState
-			{
-				if (_textArea.textFlow)
-				{
-					var selectionManager:ISelectionManager = _textArea.textFlow.interactionManager;
-					var selectionState:SelectionState = selectionManager.getSelectionState();
-					var startleaf:FlowLeafElement = _textArea.textFlow.findLeaf(selectionState.absoluteStart);
-					var endleaf:FlowLeafElement = _textArea.textFlow.findLeaf(selectionState.absoluteEnd);
-					selectionState.absoluteStart = startleaf.getAbsoluteStart();
-					selectionState.absoluteEnd = endleaf.getAbsoluteStart() + endleaf.parentRelativeEnd - endleaf.parentRelativeStart;
-					return selectionState;
-				}
-				return null;
-			}
-
-			/**
-			 *  @private
-			 */
-			private function handleClick(e:MouseEvent):void
-			{
-				if (_textArea.textFlow && _textArea.textFlow.interactionManager is IEditManager)
-				{
-					var editManager:IEditManager = IEditManager(_textArea.textFlow.interactionManager);
-					var doCreate:Boolean = true;
-					var selectionState:SelectionState = getSelectionState();
-					var listElements:Array = _textArea.textFlow.getElementsByTypeName("list");
-					for each (var listElement:ListElement in listElements)
-					{
-						var start:int = listElement.getAbsoluteStart();
-						var end:int = listElement.getAbsoluteStart() + listElement.parentRelativeEnd - listElement.parentRelativeStart;
-						if (selectionState.absoluteStart == start && selectionState.absoluteEnd == end)
-						{ //Same
-							removeList(listElement);
-							doCreate = false;
-							break;
-						}
-						else if (selectionState.absoluteStart == start && selectionState.absoluteEnd <= end)
-						{ //Inside touching start
-							selectionState = new SelectionState(_textArea.textFlow, end, selectionState.absoluteEnd);
-							removeList(listElement);
-							editManager.createList(null, null, selectionState);
-							doCreate = false;
-							break;
-						}
-						else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd == end)
-						{ //Inside touching end
-							selectionState = new SelectionState(_textArea.textFlow, selectionState.absoluteStart, start);
-							removeList(listElement);
-							editManager.createList(null, null, selectionState);
-							doCreate = false;
-							break;
-						}
-						else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd <= end)
-						{ //Inside
-							var firstRange:SelectionState = new SelectionState(_textArea.textFlow, selectionState.absoluteStart, start);
-							var secondRange:SelectionState = new SelectionState(_textArea.textFlow, end, selectionState.absoluteEnd);
-							removeList(listElement);
-							editManager.createList(null, null, firstRange);
-							editManager.createList(null, null, secondRange);
-							doCreate = false;
-							break;
-						}
-						else if ((selectionState.absoluteStart >= start && selectionState.absoluteStart <= end) || (selectionState.absoluteEnd >= start && selectionState.absoluteEnd <= end))
-						{ //Overlap. Include this list in the selection
-							selectionState = new SelectionState(_textArea.textFlow, Math.min(start, selectionState.absoluteStart), Math.max(end, selectionState.absoluteEnd));
-							removeList(listElement);
-						}
-						else if (selectionState.absoluteStart <= start && selectionState.absoluteEnd >= end)
-						{ //surround. Remove this list since it will get added back in, only expanded.
-							removeList(listElement);
-						}
-					}
-					if (doCreate)
-					{
-						IEditManager(_textArea.textFlow.interactionManager).createList(null, null, selectionState);
-					}
-					_textArea.textFlow.interactionManager.setFocus();
-				}
-			}
-
-			/**
-			 *  @private
-			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
-			{
-				if (_textArea.textFlow)
-				{
-					var willRemoveBulletsIfClicked:Boolean = false;
-					var selectionState:SelectionState = getSelectionState();
-					var listElements:Array = _textArea.textFlow.getElementsByTypeName("list");
-					for each (var listElement:ListElement in listElements)
-					{
-						var start:int = listElement.getAbsoluteStart();
-						var end:int = listElement.getAbsoluteStart() + listElement.parentRelativeEnd - listElement.parentRelativeStart;
-						if (selectionState.absoluteStart == start && selectionState.absoluteEnd == end)
-						{ //Same
-							willRemoveBulletsIfClicked = true;
-							break;
-						}
-						else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd <= end)
-						{ //Inside
-							willRemoveBulletsIfClicked = true;
-							break;
-						}
-					}
-					this.selected = willRemoveBulletsIfClicked;
-
-				}
-
-			}
-
-			/**
-			 *  @private
-			 */
-			private function removeList(listElement:ListElement):void
-			{
-				var editManager:IEditManager = IEditManager(_textArea.textFlow.interactionManager);
-
-				var target:FlowGroupElement = listElement.parent;
-				var targetIndex:int = target.getChildIndex(listElement);
-				editManager.moveChildren(listElement, 0, listElement.numChildren, target, targetIndex);
-			}
 		]]>
 	</fx:Script>
 	<fx:Declarations>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml
index 86d3006..02d9547 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml
@@ -17,64 +17,25 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<ns:ColorPicker height="21" width="20" choose="{handleChoose(event)}" mouseFocusEnabled="false" toolTip="Color text" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
+<ns:ColorPicker mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
 				xmlns:ns="http://flex.apache.org/experimental/ns" xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
-			import mx.events.FlexEvent;
 			
-			import spark.components.TextArea;
-			import spark.events.ColorChangeEvent;
-			import spark.events.TextOperationEvent;
-			
-			import flashx.textLayout.formats.TextLayoutFormat;
-
-			private var _textArea:TextArea;
-
-			/**
-			 *  The textArea that this component interacts with
-			 */
-			public function get textArea():TextArea
-			{
-				return _textArea;
-			}
-
 			/**
-			 *  @private
+			 *  The selected text color
 			 */
-			public function set textArea(value:TextArea):void
+			public function set selectedTextColor(value:uint):void
 			{
-				if (_textArea)
-				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
-				}
-				_textArea = value;
-				if (_textArea)
-				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
-				}
+				this.selectedColor = value;
 			}
-
-			/**
-			 *  @private
-			 */
-			private function handleChoose(e:ColorChangeEvent):void
-			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				format.color = e.color
-				_textArea.setFormatOfRange(format, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				_textArea.setFocus();
-				_textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
-			}
-
+			
 			/**
-			 *  @private
+			 *  The selected text color
 			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
+			public function get selectedTextColor():uint
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				this.selectedColor = format.color;
+				return this.selectedColor;
 			}
 		]]>
 	</fx:Script>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml
index f0eba89..292a2e3 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml
@@ -17,19 +17,16 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:DropDownList width="100%" change="callLater(handleChange, [event]);" dataProvider="{null}" maxWidth="120" minWidth="80" mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009"
+<s:DropDownList dataProvider="{null}" mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009"
 				xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
-			import flashx.textLayout.formats.TextLayoutFormat;
+			import flash.text.engine.FontWeight;
+			
 			import mx.collections.ArrayList;
 			import mx.collections.IList;
-			import mx.events.FlexEvent;
-			import spark.components.TextArea;
-			import spark.events.TextOperationEvent;
 
 			private const _defaultDataProvider:ArrayList = new ArrayList(["_sans", "_serif", "_typewriter", "Arial", "Calibri", "Courier", "Courier New", "Geneva,Georgia", "Helvetica", "Times New Roman", "Times", "Trebuchet MS", "Verdana"]);
-			private var _textArea:TextArea;
 
 			public override function set dataProvider(value:IList):void
 			{
@@ -42,51 +39,21 @@ limitations under the License.
 					super.dataProvider = value;
 				}
 			}
-
-			/**
-			 *  The textArea that this component interacts with
-			 */
-			public function get textArea():TextArea
-			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
-				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
-				}
-				_textArea = value;
-				if (_textArea)
-				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
-				}
-			}
-
+			
 			/**
-			 *  @private
+			 *  The selected font family
 			 */
-			private function handleChange(e:Event):void
+			public function set selectedFontFamily(value:String):void
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				format.fontFamily = this.selectedItem;
-				_textArea.setFormatOfRange(format, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				_textArea.setFocus();
-				_textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+				this.selectedItem = value;
 			}
-
+			
 			/**
-			 *  @private
+			 *  The selected font family
 			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
+			public function get selectedFontFamily():String
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				this.selectedItem = format.fontFamily;
+				return this.selectedItem;
 			}
 		]]>
 	</fx:Script>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml
index 9c54159..c6ee382 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml
@@ -17,68 +17,39 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:ToggleButton width="20" click="handleClick(event);" icon="@Embed('../../../../assets/tools/italic.png')" mouseFocusEnabled="false" toolTip="Italic text" xmlns:fx="http://ns.adobe.com/mxml/2009"
+<s:ToggleButton mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009"
 				xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
 			import flash.text.engine.FontPosture;
-			import flashx.textLayout.formats.TextLayoutFormat;
-			import mx.events.FlexEvent;
-			import spark.components.TextArea;
-			import spark.events.TextOperationEvent;
-
-			private var _textArea:TextArea;
-
+			
 			/**
-			 *  The textArea that this component interacts with
+			 *  The selected font style
 			 */
-			public function get textArea():TextArea
+			public function set selectedFontStyle(value:String):void
 			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
+				if (value == FontPosture.ITALIC)
 				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
+					this.selected = true;
 				}
-				_textArea = value;
-				if (_textArea)
+				else
 				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
+					this.selected = false;
 				}
 			}
-
+			
 			/**
-			 *  @private
+			 *  The selected font style
 			 */
-			private function handleClick(e:MouseEvent):void
+			public function get selectedFontStyle():String
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				format.fontStyle = (format.fontStyle == FontPosture.ITALIC) ? FontPosture.NORMAL : FontPosture.ITALIC;
-				_textArea.setFormatOfRange(format, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				_textArea.setFocus();
-				_textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
-			}
-
-			/**
-			 *  @private
-			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
-			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				if (format.fontStyle == FontPosture.ITALIC)
+				if (this.selected)
 				{
-					this.selected = true;
+					return FontPosture.ITALIC;
 				}
 				else
 				{
-					this.selected = false;
+					return FontPosture.NORMAL;
 				}
 			}
 		]]>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml
index 82fb837..e780acb 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml
@@ -17,234 +17,24 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:TextInput width="100%" text="" enabled="false" enter="apply(event)" keyDown="handleLinkKeydown(event)" minWidth="100" mouseFocusChange="apply(event)" mouseFocusEnabled="false"
+<s:TextInput text="" enabled="false" minWidth="100" mouseFocusEnabled="false"
 			 toolTip="Hyperlink text" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
-	<fx:Metadata>
-		[Event(name="linkSelectedChange", type="flash.events.Event")]
-	</fx:Metadata>
 	<fx:Script>
 		<![CDATA[
-			import flashx.textLayout.edit.ElementRange;
-			import flashx.textLayout.edit.IEditManager;
-			import flashx.textLayout.edit.SelectionState;
-			import flashx.textLayout.elements.LinkElement;
-			import flashx.textLayout.elements.ParagraphElement;
-			import flashx.textLayout.formats.TextLayoutFormat;
-			import mx.events.FlexEvent;
-			import spark.components.TextArea;
-
-			private var _linkSelected:Boolean = false;
-
-			private var _textArea:TextArea;
-			private var _urlRegExpression:RegExp = new RegExp("^(https?://(www\\.)?|www\\.)[-._~:/?#\\[\\]@!$&'()*+,;=a-z0-9]+$", 'i');
-			private const defaultLinkText:String = "http://";
-			private var lastRange:ElementRange;
-			private var _linkEl:LinkElement
-
-			[Bindable("linkSelectedChange")]
-			public function get linkSelected():Boolean
-			{
-				return _linkSelected;
-			}
-
-			/**
-			 *  The textArea that this component interacts with
-			 */
-			public function get textArea():TextArea
-			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
-				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
-					_textArea.removeEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
-				}
-				_textArea = value;
-				if (_textArea)
-				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					_textArea.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown, false, 0, true);
-					handleSelectionChange();
-				}
-			}
-
-			/**
-			 *  @private
-			 *  Apply the link to the selected text
-			 */
-			private function apply(e:Event = null):void
-			{
-				var urlText:String = this.text == defaultLinkText ? '' : this.text;
-				applyLink(urlText, "_blank", true);
-				//Set focus to textFlow
-				textArea.textFlow.interactionManager.setFocus();
-			}
-
 			/**
-			 *  @private
-			 *  Actually apply the link to the selection. Repair the formating in the process.
+			 *  The selected font size
 			 */
-			private function applyLink(href:String, target:String = null, extendToLinkBoundary:Boolean = false, operationState:SelectionState = null):void
+			public function set selectedLink(value:String):void
 			{
-				if (textArea && textArea.textFlow && textArea.textFlow.interactionManager is IEditManager)
-				{
-					//Get the current format
-					var txtLayFmt:TextLayoutFormat = textArea.textFlow.interactionManager.getCommonCharacterFormat();
-					//Set the link
-					if (_linkEl != null)
-					{
-						operationState = new SelectionState(textArea.textFlow, _linkEl.getAbsoluteStart(), _linkEl.getAbsoluteStart() + _linkEl.textLength);
-					}
-					var linkElement:LinkElement = IEditManager(textArea.textFlow.interactionManager).applyLink(href, target, extendToLinkBoundary, operationState);
-					//Fix the formatting
-					if(linkElement)
-					{
-						IEditManager(textArea.textFlow.interactionManager).clearFormatOnElement(linkElement.getChildAt(0), txtLayFmt);
-					}
-					var selectionEnd:int = Math.max(textArea.selectionActivePosition, textArea.selectionAnchorPosition);
-					textArea.selectRange(selectionEnd, selectionEnd);
-					IEditManager(textArea.textFlow.interactionManager).applyLeafFormat(txtLayFmt);
-				}
+				this.text = value;
 			}
-
-			/**
-			 *  @private
-			 *  Automatically add a link if the previous text looks like a link
-			 */
-			private function checkLinks():void
-			{
-				var position:int = _textArea.selectionActivePosition;
-				//Find the firt non-whitespace character
-				while (position > 0)
-				{
-					if (!isWhitespace(_textArea.textFlow.getCharCodeAtPosition(position)))
-					{
-						break;
-					}
-					position--;
-				}
-				//Find the next whitespace character
-				while (position > 0)
-				{
-					if (isWhitespace(_textArea.textFlow.getCharCodeAtPosition(position)))
-					{
-						position++; //Back up one character
-						break;
-					}
-					position--;
-				}
-				var testText:String = _textArea.textFlow.getText(position, _textArea.selectionActivePosition);
-				var result:Array = testText.match(_urlRegExpression);
-				if (result != null && result.length > 0)
-				{
-					if (_textArea.textFlow.interactionManager is IEditManager)
-					{
-						var selectionState:SelectionState = new SelectionState(_textArea.textFlow, position, _textArea.selectionActivePosition);
-						if (testText.substr(0, 3) == "www")
-						{
-							testText = "http://" + testText; //Add a missing 'http://' if needed
-						}
-						applyLink(testText, "_blank", true, selectionState);
-						_textArea.setFocus();
-					}
-				}
-			}
-
-			/**
-			 *  @private
-			 */
-			private function handleKeyDown(e:KeyboardEvent):void
-			{
-				if (e.keyCode == Keyboard.ENTER || e.keyCode == Keyboard.SPACE || e.keyCode == Keyboard.TAB)
-				{
-					checkLinks();
-				}
-			}
-
-			/**
-			 *  @private
-			 */
-			private function handleLinkKeydown(e:KeyboardEvent):void
-			{
-				e.stopImmediatePropagation();
-				if (e.keyCode == Keyboard.ENTER)
-				{
-					_textArea.setFocus();
-				}
-			}
-
-			/**
-			 *  @private
-			 *  Update the text display based on the selected range
-			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
-			{
-				var selectionState:SelectionState = _textArea.textFlow.interactionManager.getSelectionState();
-				if (selectionState.absoluteStart != -1 && selectionState.absoluteEnd != -1)
-				{
-					var range:ElementRange = ElementRange.createElementRange(selectionState.textFlow, selectionState.absoluteStart, selectionState.absoluteEnd);
-					if (range)
-					{
-						var linkString:String = defaultLinkText;
-						_linkEl = range.firstLeaf.getParentByType(LinkElement) as LinkElement;
-						if (_linkEl != null)
-						{
-							var linkElStart:int = _linkEl.getAbsoluteStart();
-							var linkElEnd:int = linkElStart + _linkEl.textLength;
-							if (linkElEnd < linkElStart)
-							{
-								var temp:int = linkElStart;
-								linkElStart = linkElEnd;
-								linkElEnd = temp;
-							}
-
-							var beginRange:int = range.absoluteStart;
-							var endRange:int = range.absoluteEnd;
-
-							var beginPara:ParagraphElement = range.firstParagraph;
-							if (endRange == (beginPara.getAbsoluteStart() + beginPara.textLength))
-							{
-								endRange--;
-							}
-
-							if ((beginRange == endRange) || (endRange <= linkElEnd))
-							{
-								linkString = LinkElement(_linkEl).href;
-							}
-						}
-						var newLinkSelected:Boolean = _linkEl != null;
-						if (_linkSelected != newLinkSelected)
-						{
-							_linkSelected = newLinkSelected;
-							this.dispatchEvent(new Event("linkSelectedChange"));
-						}
-
-						this.text = linkString;
-
-						lastRange = range;
-					}
-					else
-					{
-						lastRange = null;
-					}
-				}
-				
-				enabled = _textArea.selectionAnchorPosition != _textArea.selectionActivePosition || _linkSelected;
-			}
-
+			
 			/**
-			 *  @private
-			 *  Return true if the character is a whitespace character
+			 *  The selected font family
 			 */
-			private function isWhitespace(charCode:uint):Boolean
+			public function get selectedLink():String
 			{
-				return charCode === 0x0009 || charCode === 0x000A || charCode === 0x000B || charCode === 0x000C || charCode === 0x000D || charCode === 0x0020 || charCode === 0x0085 || charCode === 0x00A0 || charCode === 0x1680 || charCode === 0x180E || charCode === 0x2000 || charCode === 0x2001 || charCode === 0x2002 || charCode === 0x2003 || charCode === 0x2004 || charCode === 0x2005 || charCode === 0x2006 || charCode === 0x2007 || charCode === 0x2008 || charCode === 0x2009 || charCode === 0x200A || charCode === 0x2028 || charCode === 0x2029 || charCode === 0x202F || charCode === 0x205F || charCode === 0x3000;
+				return this.text;
 			}
 		]]>
 	</fx:Script>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/RichTextEditorToolBar.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/RichTextEditorToolBar.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/RichTextEditorToolBar.mxml
deleted file mode 100755
index d7ef167..0000000
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/RichTextEditorToolBar.mxml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
-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.
-
--->
-<s:HGroup gap="6" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:richTextEditorClasses="spark.components.richTextEditorClasses.*"
-		  xmlns:s="library://ns.adobe.com/flex/spark">
-	<fx:Metadata>
-		[Event(name="linkSelectedChange", type="flash.events.Event")]
-	</fx:Metadata>
-	<fx:Script>
-		<![CDATA[
-			import mx.collections.IList;
-			import spark.components.TextArea;
-
-			[Bindable]
-			/**
-			 * A list of fonts for the font dropdown
-			 */
-			public var fonts:IList = null;
-
-			[Bindable]
-			/**
-			 * A list of sizes for the size dropdown
-			 */
-			public var sizes:IList = null;
-
-			private var _linkSelected:Boolean = false;
-			private var _textArea:TextArea;
-
-			[Bindable("linkSelectedChange")]
-			/**
-			 *  True if a link is currently selected
-			 */
-			public function get linkSelected():Boolean
-			{
-				return _linkSelected;
-			}
-
-			/**
-			 * The textArea that this toolbar is controlling
-			 */
-			[Bindable]
-			public function get textArea():TextArea
-			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				_textArea = value;
-			}
-
-			/**
-			 *  @private
-			 */
-			private function handleLinkSelectedChange(e:Event):void
-			{
-				_linkSelected = (e.currentTarget as LinkTool).linkSelected;
-				this.dispatchEvent(new Event("linkSelectedChange"));
-			}
-		]]>
-	</fx:Script>
-	<fx:Declarations>
-		<!-- Place non-visual elements (e.g., services, value objects) here -->
-	</fx:Declarations>
-	<richTextEditorClasses:FontTool dataProvider="{fonts}" textArea="{textArea}"/>
-	<richTextEditorClasses:SizeTool dataProvider="{sizes}" textArea="{textArea}"/>
-	<s:HGroup gap="0">
-		<richTextEditorClasses:BoldTool textArea="{textArea}"/>
-		<richTextEditorClasses:ItalicTool textArea="{textArea}"/>
-		<richTextEditorClasses:UnderlineTool textArea="{textArea}"/>
-	</s:HGroup>
-	<richTextEditorClasses:ColorTool textArea="{textArea}"/>
-	<s:Line height="100%">
-		<s:stroke>
-			<s:SolidColorStroke color="#B3C2B8"/>
-		</s:stroke>
-	</s:Line>
-	<richTextEditorClasses:AlignTool textArea="{textArea}"/>
-	<richTextEditorClasses:BulletTool textArea="{textArea}"/>
-	<s:Line height="100%">
-		<s:stroke>
-			<s:SolidColorStroke color="#B3C2B8"/>
-		</s:stroke>
-	</s:Line>
-	<richTextEditorClasses:LinkTool linkSelectedChange="handleLinkSelectedChange(event)" textArea="{textArea}"/>
-</s:HGroup>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml
index 0f9b6e6..f56be1a 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml
@@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:DropDownList width="60" change="callLater(handleChange, [event]);" dataProvider="{null}" mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
+<s:DropDownList dataProvider="{null}" mouseFocusEnabled="false" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
 				xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
@@ -30,7 +30,6 @@ limitations under the License.
 			import spark.events.TextOperationEvent;
 
 			private const _defaultDataProvider:ArrayList = new ArrayList([8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]);
-			private var _textArea:TextArea;
 
 			public override function set dataProvider(value:IList):void
 			{
@@ -43,51 +42,21 @@ limitations under the License.
 					super.dataProvider = value;
 				}
 			}
-
-			/**
-			 *  The textArea that this component interacts with
-			 */
-			public function get textArea():TextArea
-			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
-				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
-				}
-				_textArea = value;
-				if (_textArea)
-				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
-				}
-			}
-
+			
 			/**
-			 *  @private
+			 *  The selected font size
 			 */
-			private function handleChange(e:Event):void
+			public function set selectedFontSize(value:String):void
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				format.fontSize = this.selectedItem;
-				_textArea.setFormatOfRange(format, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				_textArea.setFocus();
-				_textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+				this.selectedItem = value;
 			}
-
+			
 			/**
-			 *  @private
+			 *  The selected font family
 			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
+			public function get selectedFontSize():String
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				this.selectedItem = format.fontSize;
+				return this.selectedItem;
 			}
 		]]>
 	</fx:Script>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml
index 1ae0663..f623dd4 100644
--- a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml
@@ -17,69 +17,39 @@ See the License for the specific language governing permissions and
 limitations under the License.
 
 -->
-<s:ToggleButton width="20" click="handleClick(event);" icon="@Embed('../../../../assets/tools/underline.png')" mouseFocusEnabled="false" toolTip="Underline text"
+<s:ToggleButton mouseFocusEnabled="false"
 				xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
 	<fx:Script>
 		<![CDATA[
-			import flash.text.engine.FontPosture;
 			import flashx.textLayout.formats.TextDecoration;
-			import flashx.textLayout.formats.TextLayoutFormat;
-			import mx.events.FlexEvent;
-			import spark.components.TextArea;
-			import spark.events.TextOperationEvent;
-
-			private var _textArea:TextArea;
-
+			
 			/**
-			 *  The textArea that this component interacts with
+			 *  The selected text decoration
 			 */
-			public function get textArea():TextArea
+			public function set selectedTextDecoration(value:String):void
 			{
-				return _textArea;
-			}
-
-			/**
-			 *  @private
-			 */
-			public function set textArea(value:TextArea):void
-			{
-				if (_textArea)
+				if (value == TextDecoration.UNDERLINE)
 				{
-					_textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
+					this.selected = true;
 				}
-				_textArea = value;
-				if (_textArea)
+				else
 				{
-					_textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange, false, 0, true);
-					handleSelectionChange();
+					this.selected = false;
 				}
 			}
-
+			
 			/**
-			 *  @private
+			 *  The selected text decoration
 			 */
-			private function handleClick(e:MouseEvent):void
+			public function get selectedTextDecoration():String
 			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				format.textDecoration = (format.textDecoration == TextDecoration.UNDERLINE) ? TextDecoration.NONE : TextDecoration.UNDERLINE;
-				_textArea.setFormatOfRange(format, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				_textArea.setFocus();
-				_textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
-			}
-
-			/**
-			 *  @private
-			 */
-			private function handleSelectionChange(e:FlexEvent = null):void
-			{
-				var format:TextLayoutFormat = _textArea.getFormatOfRange(null, _textArea.selectionAnchorPosition, _textArea.selectionActivePosition);
-				if (format.textDecoration == TextDecoration.UNDERLINE)
+				if (this.selected)
 				{
-					this.selected = true;
+					return TextDecoration.UNDERLINE;
 				}
 				else
 				{
-					this.selected = false;
+					return TextDecoration.NONE;
 				}
 			}
 		]]>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/skins/AlignToolSkin.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/skins/AlignToolSkin.mxml b/frameworks/projects/experimental/src/spark/skins/AlignToolSkin.mxml
deleted file mode 100644
index 36e58b3..0000000
--- a/frameworks/projects/experimental/src/spark/skins/AlignToolSkin.mxml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
-  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.
-
--->
-
-
-<!--- The default skin class for the Spark ButtonBar component. The buttons on the ButtonBar component
-	use the ButtonBarLastButtonSkin, ButtonBarFirstButtonSkin and ButtonBarMiddleButtonSkin classes.
-
-	  @see spark.components.ButtonBar
-	  @see spark.components.ButtonBarButton
-
-	  @langversion 3.0
-	  @playerversion Flash 10
-	  @playerversion AIR 1.5
-	  @productversion Flex 4
--->
-<s:Skin alpha.disabled="0.5" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">
-
-	<fx:Metadata>
-		<![CDATA[ 
-       /** 
-         * @copy spark.skins.spark.ApplicationSkin#hostComponent
-         */
-        [HostComponent("spark.components.ButtonBar")]
-    ]]>
-	</fx:Metadata>
-
-	<s:states>
-		<s:State name="normal"/>
-		<s:State name="disabled"/>
-	</s:states>
-
-	<fx:Declarations>
-		<!---
-			@copy spark.components.ButtonBar#firstButton
-			@default spark.skins.spark.ButtonBarFirstButtonSkin
-			@see spark.skins.spark.ButtonBarFirstButtonSkin
-		-->
-		<fx:Component id="firstButton">
-			<s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarFirstButtonSkin" toolTip="{data.toolTip}"/>
-		</fx:Component>
-
-		<!---
-			@copy spark.components.ButtonBar#middleButton
-			@default spark.skins.spark.ButtonBarMiddleButtonSkin
-			@see spark.skins.spark.ButtonBarMiddleButtonSkin
-		-->
-		<fx:Component id="middleButton">
-			<s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarMiddleButtonSkin" toolTip="{data.toolTip}"/>
-		</fx:Component>
-
-		<!---
-			@copy spark.components.ButtonBar#lastButton
-			@default spark.skins.spark.ButtonBarLastButtonSkin
-			@see spark.skins.spark.ButtonBarLastButtonSkin
-		-->
-		<fx:Component id="lastButton">
-			<s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarLastButtonSkin" toolTip="{data.toolTip}"/>
-		</fx:Component>
-
-	</fx:Declarations>
-
-	<!--- @copy spark.components.SkinnableDataContainer#dataGroup -->
-	<s:DataGroup id="dataGroup" height="100%" width="100%">
-		<s:layout>
-			<s:ButtonBarHorizontalLayout gap="-1"/>
-		</s:layout>
-	</s:DataGroup>
-
-</s:Skin>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/skins/RichTextEditorSkin.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/skins/RichTextEditorSkin.mxml b/frameworks/projects/experimental/src/spark/skins/RichTextEditorSkin.mxml
new file mode 100644
index 0000000..f9cf148
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/skins/RichTextEditorSkin.mxml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
+		xmlns:s="library://ns.adobe.com/flex/spark" 
+		xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:richTextEditorClasses="spark.components.richTextEditorClasses.*">
+	<!-- host component -->
+	<fx:Metadata>
+		[HostComponent("spark.components.RichTextEditor")]
+	</fx:Metadata>	
+	
+	<fx:Script>
+		<![CDATA[
+			import mx.collections.ArrayList;
+			
+			import flashx.textLayout.formats.TextAlign;
+			
+			[Embed(source = "../../../assets/tools/center.png")]
+			private const CENTER:Class;
+			[Embed(source = "../../../assets/tools/justify.png")]
+			private const JUSTIFY:Class;
+			[Embed(source = "../../../assets/tools/left.png")]
+			private const LEFT:Class;
+			[Embed(source = "../../../assets/tools/right.png")]
+			private const RIGHT:Class;
+			
+			override protected function createChildren():void
+			{
+				super.createChildren();
+				var dp:ArrayList = new ArrayList();
+				dp.addItem({icon: LEFT, toolTip: "", value: TextAlign.LEFT});
+				dp.addItem({icon: CENTER, toolTip: "", value: TextAlign.CENTER});
+				dp.addItem({icon: RIGHT, toolTip: "", value: TextAlign.RIGHT});
+				dp.addItem({icon: JUSTIFY, toolTip: "", value: TextAlign.JUSTIFY});
+				alignTool.dataProvider = dp;
+			}
+			
+		]]>
+	</fx:Script>
+	
+	<!-- SkinParts
+	name=textArea, type=spark.components.TextArea, required=true
+	name=fontTool, type=spark.components.richTextEditorClasses.FontTool, required=false
+	name=sizeTool, type=spark.components.richTextEditorClasses.SizeTool, required=false
+	name=boldTool, type=spark.components.richTextEditorClasses.BoldTool, required=false
+	name=italicTool, type=spark.components.richTextEditorClasses.ItalicTool, required=true
+	name=underlineTool, type=spark.components.richTextEditorClasses.UnderlineTool, required=true
+	name=colorTool, type=spark.components.richTextEditorClasses.ColorTool, required=false
+	name=alignTool, type=spark.components.richTextEditorClasses.AlignTool, required=false
+	name=bulletTool, type=spark.components.richTextEditorClasses.BulletTool, required=false
+	name=linkTool, type=spark.components.richTextEditorClasses.LinkTool, required=false
+	-->
+	
+	<s:VGroup width="100%" height="100%">	
+		<s:HGroup width="100%" bottom="6">	
+			<richTextEditorClasses:FontTool id="fontTool" width="100%" maxWidth="120" minWidth="80"/>
+			<richTextEditorClasses:SizeTool id="sizeTool" width="60"/>
+			<s:HGroup gap="0">
+				<richTextEditorClasses:BoldTool id="boldTool" width="20" icon="@Embed('../../../assets/tools/bold.png')"/>
+				<richTextEditorClasses:ItalicTool id="italicTool" width="20" icon="@Embed('../../../assets/tools/italic.png')"/>
+				<richTextEditorClasses:UnderlineTool id="underlineTool" width="20" icon="@Embed('../../../assets/tools/underline.png')"/>
+			</s:HGroup>
+			<richTextEditorClasses:ColorTool id="colorTool" height="21" width="20"/>
+			<s:Line height="100%">
+				<s:stroke>
+					<s:SolidColorStroke color="#B3C2B8"/>
+				</s:stroke>
+			</s:Line>
+			<richTextEditorClasses:AlignTool id="alignTool" width="80" skinClass="spark.skins.richTextEditorClasses.AlignToolSkin"/>
+			<richTextEditorClasses:BulletTool id="bulletTool" width="20" icon="@Embed('../../../assets/tools/bullet.png')"/>
+			<s:Line height="100%">
+				<s:stroke>
+					<s:SolidColorStroke color="#B3C2B8"/>
+				</s:stroke>
+			</s:Line>
+			<richTextEditorClasses:LinkTool id="linkTool" width="100%"/>
+		</s:HGroup>
+		<s:TextArea id="textArea" height="100%" width="100%"/>
+	</s:VGroup>
+</s:Skin>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/fb48bb70/frameworks/projects/experimental/src/spark/skins/richTextEditorClasses/AlignToolSkin.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/skins/richTextEditorClasses/AlignToolSkin.mxml b/frameworks/projects/experimental/src/spark/skins/richTextEditorClasses/AlignToolSkin.mxml
new file mode 100644
index 0000000..36e58b3
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/skins/richTextEditorClasses/AlignToolSkin.mxml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+
+
+<!--- The default skin class for the Spark ButtonBar component. The buttons on the ButtonBar component
+	use the ButtonBarLastButtonSkin, ButtonBarFirstButtonSkin and ButtonBarMiddleButtonSkin classes.
+
+	  @see spark.components.ButtonBar
+	  @see spark.components.ButtonBarButton
+
+	  @langversion 3.0
+	  @playerversion Flash 10
+	  @playerversion AIR 1.5
+	  @productversion Flex 4
+-->
+<s:Skin alpha.disabled="0.5" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">
+
+	<fx:Metadata>
+		<![CDATA[ 
+       /** 
+         * @copy spark.skins.spark.ApplicationSkin#hostComponent
+         */
+        [HostComponent("spark.components.ButtonBar")]
+    ]]>
+	</fx:Metadata>
+
+	<s:states>
+		<s:State name="normal"/>
+		<s:State name="disabled"/>
+	</s:states>
+
+	<fx:Declarations>
+		<!---
+			@copy spark.components.ButtonBar#firstButton
+			@default spark.skins.spark.ButtonBarFirstButtonSkin
+			@see spark.skins.spark.ButtonBarFirstButtonSkin
+		-->
+		<fx:Component id="firstButton">
+			<s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarFirstButtonSkin" toolTip="{data.toolTip}"/>
+		</fx:Component>
+
+		<!---
+			@copy spark.components.ButtonBar#middleButton
+			@default spark.skins.spark.ButtonBarMiddleButtonSkin
+			@see spark.skins.spark.ButtonBarMiddleButtonSkin
+		-->
+		<fx:Component id="middleButton">
+			<s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarMiddleButtonSkin" toolTip="{data.toolTip}"/>
+		</fx:Component>
+
+		<!---
+			@copy spark.components.ButtonBar#lastButton
+			@default spark.skins.spark.ButtonBarLastButtonSkin
+			@see spark.skins.spark.ButtonBarLastButtonSkin
+		-->
+		<fx:Component id="lastButton">
+			<s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarLastButtonSkin" toolTip="{data.toolTip}"/>
+		</fx:Component>
+
+	</fx:Declarations>
+
+	<!--- @copy spark.components.SkinnableDataContainer#dataGroup -->
+	<s:DataGroup id="dataGroup" height="100%" width="100%">
+		<s:layout>
+			<s:ButtonBarHorizontalLayout gap="-1"/>
+		</s:layout>
+	</s:DataGroup>
+
+</s:Skin>