<?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.
-->


<!-- Demonstrate some example controls.  This example does not attempt to create a control for every property in the TextLayoutFramework -->

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" label="Text Editor Example" initialize="init()" backgroundColor="#FFFFFF" horizontalScrollPolicy="off" verticalScrollPolicy="off">
	<mx:Script>
		<![CDATA[

			import flashx.textLayout.container.ContainerController;
			import flashx.textLayout.conversion.TextConverter;
			import flashx.textLayout.edit.EditManager;
			import flashx.textLayout.edit.IEditManager;
			import flashx.textLayout.edit.ElementRange;
			import flashx.textLayout.edit.SelectionState;
			import flashx.textLayout.elements.Configuration;
			import flashx.textLayout.elements.TextFlow;
			import flashx.textLayout.events.StatusChangeEvent;
			import flashx.textLayout.events.SelectionEvent;
			import flashx.textLayout.formats.ITextLayoutFormat;
			import flashx.textLayout.formats.TextLayoutFormat;
			import flashx.textLayout.formats.TextAlign;
			import flashx.textLayout.formats.VerticalAlign;
			import flashx.textLayout.formats.BlockProgression;
			import flashx.textLayout.formats.Direction;
			import flashx.textLayout.tlf_internal;
			
			use namespace tlf_internal;
			
			import flashx.undo.UndoManager;

			import flash.display.Sprite;
			import flash.system.Capabilities;	
			
			// the textFlow being worked on
			private var _textFlow:TextFlow = null;
			// container to hold the text
			private var _container:Sprite = null;
			
			// ///////////////////////////////////////
			// data providers for enumerated list boxes
			// ///////////////////////////////////////
			static private const textAlignData:Array = [
				{ label:"Justify",	data:TextAlign.JUSTIFY},
				{ label:"Left",		data:TextAlign.LEFT},
				{ label:"Right",	data:TextAlign.RIGHT},
				{ label:"Center",	data:TextAlign.CENTER},
				{ label:"End",		data:TextAlign.END},
				{ label:"Start",	data:TextAlign.START}
			];
			static private const verticalAlignData:Array = [
				{ label:"Bottom",	data:VerticalAlign.BOTTOM },
				{ label:"Justify",	data:VerticalAlign.JUSTIFY },
				{ label:"Middle",	data:VerticalAlign.MIDDLE },
				{ label:"Top",		data:VerticalAlign.TOP }
			];
			
			static private const blockProgressionData:Array = [
				{ label:"TopToBottom",	data:BlockProgression.TB },
				{ label:"RightToleft",	data:BlockProgression.RL }
			];
			
			static private const directionData:Array = [
				{ label:"LeftToRight",	data:Direction.LTR },
				{ label:"RightToleft",	data:Direction.RTL }
			];
			
			/** 
			 * initialization
			 */
			private function init():void
			{
				// create a sprite to hold the TextLines
				_container = new Sprite();
				textArea.rawChildren.addChild(_container);
				
				fontFamily.dataProvider = populateFontFamily();
				
				versionInfo.text = "Vellum: " + flashx.textLayout.TextLayoutVersion.BUILD_NUMBER + (Configuration.tlf_internal::debugCodeEnabled ? " Debug" : " Release") 
					+ ", Flex: " + mx_internal::VERSION
					+ ", Player: " + Capabilities.version;
			}
			
			/**
			* Create an array of available font families
			*/ 
			static private function populateFontFamily():Array
			{
				// really this returns an array of fonts - would be nice to strip it down to just the families
				var fonts:Array = Font.enumerateFonts(true);
				var fontfamily:Array = new Array();
				fonts.sortOn("fontName", Array.CASEINSENSITIVE);
				for(var i:int = 0; i< fonts.length; i++)
				{
					// trace(fonts[i].fontName);
					fontfamily.push({label: fonts[i].fontName, data: fonts[i].fontName});
				}
				return fontfamily;
			}
			
			/** called to set the size of this panel */
			public function setSize(w:int,h:int):void
			{
				this.width = w;
				this.height = h;
				textArea.width = width;
				textArea.height = height > bottomTabs.height ? this.height-bottomTabs.height : 0;
				if (_textFlow)
				{
					_textFlow.flowComposer.getControllerAt(0).setCompositionSize(textArea.width,textArea.height);
					_textFlow.flowComposer.updateAllControllers();
				}
			}
			
			/** called when the bottom tabs finally gets sized. */
			private function bottomTabsResize():void
			{
				setSize(width,height);
			}
			
			/** The TextFlow to edit. */
			public function get textFlow():TextFlow
			{ return _textFlow; }
			
			public function set textFlow(newFlow:TextFlow):void
			{
				// clear any old flow if present
				if (_textFlow)
				{
					_textFlow.flowComposer = null;
					_textFlow = null;
				}
				_textFlow = newFlow;
				if (_textFlow)
				{
					_textFlow.flowComposer.addController(new ContainerController(_container,textArea.width,textArea.height));
					
					// setup event listeners for selection changed and ILG loaded
					_textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE,selectionChangeListener,false,0,true);
					_textFlow.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,graphicStatusChangeEvent,false,0,true);
					
					// make _textFlow editable with undo 
					_textFlow.interactionManager = new EditManager(new UndoManager());
					// initialize with a selection before the first character
					_textFlow.interactionManager.selectRange(0,0);
					
					// compose the new textFlow and give it focus
					_textFlow.flowComposer.updateAllControllers();
					_textFlow.interactionManager.setFocus();
				}
			}
			
			/** Receives an event any time an ILG with a computed size finishes loading. */
 			private function graphicStatusChangeEvent(evt:StatusChangeEvent):void
			{
				// recompose if the evt is from an element in this textFlow
				if (_textFlow && evt.element.getTextFlow() == _textFlow)
					_textFlow.flowComposer.updateAllControllers();
			}	
			
			/** Receives an event any time the selection is changed.  Update the UI */
			private function selectionChangeListener(e:SelectionEvent):void
 			{
 				var selectionState:SelectionState = e.selectionState;
 				var selectedElementRange:ElementRange = ElementRange.createElementRange(selectionState.textFlow, selectionState.absoluteStart, selectionState.absoluteEnd);
 				// set display according to the values at the beginning of the selection range.  For point selection/characterFormat use getCommonCharacterFormat as that tracks pending attributes waiting for the next character
 				var characterFormat:ITextLayoutFormat = _textFlow.interactionManager.activePosition == _textFlow.interactionManager.anchorPosition ? _textFlow.interactionManager.getCommonCharacterFormat() : selectedElementRange.characterFormat;
 				var paragraphFormat:ITextLayoutFormat = selectedElementRange.paragraphFormat;
 				var containerFormat:ITextLayoutFormat = selectedElementRange.containerFormat;
 				
 				updateComboBox(fontFamily,characterFormat.fontFamily);
 				fontSize.text = characterFormat.fontSize.toString();
 				lineHeight.text = characterFormat.lineHeight.toString();
 				
 				updateComboBox(textAlign,paragraphFormat.textAlign);
 				textIndent.text = paragraphFormat.textIndent.toString();
 				
 				columnCount.text = containerFormat.columnCount.toString();
 				columnGap.text = containerFormat.columnGap.toString();
 				updateComboBox(verticalAlign,containerFormat.verticalAlign);
 				
 				updateComboBox(blockProgression,_textFlow.computedFormat.blockProgression);
 				updateComboBox(directionBox,_textFlow.computedFormat.direction);
 			}
 			
 			/** Helper function to update a comboBox in the UI */
 			private function updateComboBox(box:ComboBox,val:String):void
 			{
 				for (var i:int = 0; i < box.dataProvider.length; i++)
 				{
 					if (box.dataProvider[i].data == val)
 					{
 						box.selectedIndex = i;
 						return;
 					}
 				}
 				box.text = val;
 			}
 			
 			/**
 			 * These functions are helpers for the various widgets to actually perform the operations on the TextFlow
 			 */
			private function changeFontFamily(newFontFamily:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var cf:TextLayoutFormat = new TextLayoutFormat();
					cf.fontFamily = newFontFamily;
					IEditManager(_textFlow.interactionManager).applyLeafFormat(cf);
					_textFlow.interactionManager.setFocus();
				}
			}
			private function changeFontSize(newFontSize:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var cf:TextLayoutFormat = new TextLayoutFormat();
					cf.fontSize = newFontSize;
					IEditManager(_textFlow.interactionManager).applyLeafFormat(cf);
					_textFlow.interactionManager.setFocus();
				}
			}
			private function changeLeading(newLeading:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var cf:TextLayoutFormat = new TextLayoutFormat();
					cf.lineHeight = newLeading;
					IEditManager(_textFlow.interactionManager).applyLeafFormat(cf);
					_textFlow.interactionManager.setFocus();
				}
			}
			
			private function changeTextAlign(newAlign:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var pf:TextLayoutFormat = new TextLayoutFormat();
					pf.textAlign = newAlign;
					IEditManager(_textFlow.interactionManager).applyParagraphFormat(pf);
					_textFlow.interactionManager.setFocus();
				}
			}
			
			private function changeTextIndent(newIndent:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var pf:TextLayoutFormat = new TextLayoutFormat();
					pf.textIndent = newIndent;
					IEditManager(_textFlow.interactionManager).applyParagraphFormat(pf);
					_textFlow.interactionManager.setFocus();
				}
			}
			
			private function changeColumnCount(newCount:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var cf:TextLayoutFormat = new TextLayoutFormat();
					cf.columnCount = newCount;
					IEditManager(_textFlow.interactionManager).applyContainerFormat(cf);
					_textFlow.interactionManager.setFocus();
				}
			}
			
			private function changeColumnGap(newGap:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var cf:TextLayoutFormat = new TextLayoutFormat();
					cf.columnGap = newGap;
					IEditManager(_textFlow.interactionManager).applyContainerFormat(cf);
					_textFlow.interactionManager.setFocus();
				}
			}
			
			private function changeVerticalAlign(newAlign:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var cf:TextLayoutFormat = new TextLayoutFormat();
					cf.verticalAlign = newAlign;
					IEditManager(_textFlow.interactionManager).applyContainerFormat(cf);
					_textFlow.interactionManager.setFocus();
				}
			}
			
			private function changeBlockProgression(newProgression:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var cf:TextLayoutFormat = new TextLayoutFormat();
					cf.blockProgression = newProgression;
					IEditManager(_textFlow.interactionManager).applyFormatToElement(_textFlow,cf);
					_textFlow.interactionManager.setFocus();
				}
			}
			
			/** Set direction on the rootElement.  This effects both columnDirection and default reading order. */
			private function changeDirection(newDirection:String):void
			{
				if (_textFlow && _textFlow.interactionManager is IEditManager)
				{
					var pf:TextLayoutFormat = new TextLayoutFormat();
					pf.direction = newDirection;
					IEditManager(_textFlow.interactionManager).applyFormatToElement(_textFlow,pf);
					_textFlow.interactionManager.setFocus();
				}
			}
		]]>
	</mx:Script>
	<!-- <mx:VBox horizontalScrollPolicy="off" verticalScrollPolicy="off" width="100%" height="100%"> -->
		<mx:Canvas id="textArea" width="520" height="400"/>
		<mx:TabNavigator id="bottomTabs" width="100%" creationPolicy="all" paddingLeft="4" paddingBottom="8" backgroundColor="#D9D9D9" color="#202020" horizontalScrollPolicy="off" verticalScrollPolicy="off" resize="bottomTabsResize()">
			<mx:HBox label="Text" backgroundColor="#D9D9D9" width="496" horizontalScrollPolicy="off" verticalScrollPolicy="off" >
				<mx:Label text="Font:"/>
				<mx:ComboBox id="fontFamily" editable="true" enter="changeFontFamily(fontFamily.text)"  close="changeFontFamily(fontFamily.text)" width="200"/>
				<mx:Label text="Size:"/>
				<mx:TextInput id="fontSize" enter="changeFontSize(fontSize.text)" width="40"/>
				<mx:Label text="LineHeight:"/>
				<mx:TextInput id="lineHeight" enter="changeLeading(lineHeight.text)" width="40"/>
			</mx:HBox>
			<mx:HBox label="Para" backgroundColor="#D9D9D9" width="496">
				<mx:Label text="Alignment:"/>
				<mx:ComboBox id="textAlign" close="changeTextAlign(textAlign.selectedItem.data)" dataProvider="{textAlignData}"/>
				<mx:Label text="FirstLineIdent:"/>
				<mx:TextInput id="textIndent" enter="changeTextIndent(textIndent.text)" width="40"/>
			</mx:HBox>
			<mx:HBox label="Container" backgroundColor="#D9D9D9" width="496">
				<mx:Label text="Columns:"/>
				<mx:TextInput id="columnCount" toolTip="auto or a number" enter="changeColumnCount(columnCount.text)" width="40"/>
				<mx:Label text="Gap:"/>
				<mx:TextInput id="columnGap" toolTip="a number" enter="changeColumnGap(columnGap.text)" width="40"/>
				<mx:Label text="VerticalAlignment:"/>
				<mx:ComboBox id="verticalAlign" close="changeVerticalAlign(verticalAlign.selectedItem.data)" dataProvider="{verticalAlignData}"/>
			</mx:HBox>
			<mx:HBox label="Flow" backgroundColor="#D9D9D9" width="496">
				<mx:Label text="Progression:"/>
				<mx:ComboBox id="blockProgression" close="changeBlockProgression(blockProgression.selectedItem.data)" dataProvider="{blockProgressionData}"/>
				<mx:Label text="Direction:"/>
				<mx:ComboBox id="directionBox" close="changeDirection(directionBox.selectedItem.data)" dataProvider="{directionData}"/>
			</mx:HBox>
			<mx:HBox label="Version" backgroundColor="#D9D9D9" width="496">
				<mx:TextInput id="versionInfo" editable="false" width="100%"/>
			</mx:HBox>
		</mx:TabNavigator>
	<!-- </mx:VBox> -->
</mx:VBox>
