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




<mx:Canvas
    xmlns="http://ns.adobe.com/mxml/2009"
 	xmlns:mx="library://ns.adobe.com/flex/mx"
	xmlns:flow="library://ns.adobe.com/flashx/textLayout"
	xmlns:textEditBar="textEditBar.*"
	xmlns:txui="flashx.textLayout.ui.*"
	xmlns:txrulers="flashx.textLayout.ui.rulers.*"
	xmlns:txinsp="flashx.textLayout.ui.inspectors.*"
	explicitMinWidth="300" 
	explicitMinHeight="200"
	creationComplete="handleCreationComplete()"
	resize="handleResize()">
	
		
    <Script><![CDATA[
		import flashx.textLayout.container.ContainerController;
		import flashx.textLayout.debug.assert;
		import flashx.textLayout.edit.EditManager;
		import flashx.textLayout.edit.EditingMode;
		import flashx.textLayout.edit.ElementRange;
		import flashx.textLayout.edit.ISelectionManager;
		import flashx.textLayout.edit.SelectionFormat;
		import flashx.textLayout.edit.SelectionManager;
		import flashx.textLayout.edit.SelectionState;
		import flashx.textLayout.elements.Configuration;
		import flashx.textLayout.elements.InlineGraphicElementStatus;
		import flashx.textLayout.elements.ParagraphElement;
		import flashx.textLayout.elements.SpanElement;
		import flashx.textLayout.elements.TextFlow;
		import flashx.textLayout.events.SelectionEvent;
		import flashx.textLayout.events.StatusChangeEvent;
		import flashx.textLayout.formats.TextLayoutFormat;
		import flashx.undo.IUndoManager;
		import flashx.undo.UndoManager;
		
		import textEditBar.FileIOHelper;
		import flashx.textLayout.ui.inspectors.TextInspectorController;
		
		import mx.events.IndexChangedEvent;
				
		private var resizeOK:Boolean;
		public var activeFlow:TextFlow;

		// undo/redo manager
		private var undoManager:IUndoManager;
		
		private var bottomPanels:Array = [];
		
		
		public function handleCreationComplete(): void
		{
			initializeConfiguration();
			FileIOHelper.parentWindow = this;
			FileIOHelper.changeContent = changeContent;
					
			resizeOK = true;
			handleResize();
 			 			
 			undoManager = new UndoManager();
  			 			
			hruler.creationComplete();
 			vruler.creationComplete();
 			
 			var numPanels:int = bottomTabs.numChildren;
 			for (var i:int = 0; i < numPanels; ++i)
 			{
 				var panel:Canvas = bottomTabs.getChildAt(i) as Canvas;
 				bottomPanels.push(panel.getChildAt(0));
 				if (i > 0)
 					panel.removeAllChildren();
 			}
  			bottomTabs.addEventListener(IndexChangedEvent.CHANGE, onBottomTabChanged);
  			
  			this.addEventListener(Event.ACTIVATE, onFocus); 
  			
			changeContent(createEmptyFlow());
			callLater(doFocus);
		}
		
		private function doFocus():void
		{
			if (activeFlow)
			{
				var selMgr:ISelectionManager = activeFlow.interactionManager;
				if (selMgr && textPanel.visible)
					selMgr.setFocus();
			}
		}
		private function createEmptyFlow():TextFlow
		{
			var newFlow:TextFlow = new TextFlow();
			var para:ParagraphElement = new ParagraphElement();
			para.addChild(new SpanElement());
			newFlow.addChild(para);
			return newFlow;
		}
 		
 		private function initializeConfiguration():void
 		{
 			var config:Configuration = TextFlow.defaultConfiguration;
			config.unfocusedSelectionFormat = new SelectionFormat(0xffffff, 1.0, BlendMode.DIFFERENCE, 0xffffff, 1.0, BlendMode.DIFFERENCE, 0);
			config.inactiveSelectionFormat = new SelectionFormat(0xffffff, 1.0, BlendMode.DIFFERENCE, 0xffffff, 1.0, BlendMode.DIFFERENCE, 0);
			config.manageTabKey = true;
			var initialFormat:TextLayoutFormat = new TextLayoutFormat();
			initialFormat.fontFamily = "Arial";
			initialFormat.fontSize = 16;
			initialFormat.paddingLeft = 2;
			initialFormat.paddingTop = 2;
			initialFormat.paddingRight = 2;
			initialFormat.paddingBottom = 2;
			config.textFlowInitialFormat = initialFormat;
		}
 		
 		private function onFocus(event:Event):void
 		{
 			if (activeFlow)
 			{
	 			var selMgr:ISelectionManager = activeFlow.interactionManager;
	 			if(selMgr)
	 				selMgr.setFocus();
	 		}
 			
 		}
 		private function onBottomTabChanged(evt:IndexChangedEvent):void
 		{
 			var panel:Canvas = bottomTabs.getChildAt(evt.oldIndex) as Canvas;
 			panel.removeAllChildren();
 			panel = bottomTabs.getChildAt(evt.newIndex) as Canvas;
 			panel.addChild(bottomPanels[evt.newIndex]);
 		}
 		
  		private var editingMode:String = EditingMode.READ_WRITE;
 		
		private function keyListener(event:KeyboardEvent):void
 		{
			if (event.keyCode == Keyboard.ESCAPE)
				activeFlow.interactionManager.selectRange(-1,-1);
 		}
 		
 		private function updateEscapeKeyListener():void
 		{
 			for (var i:int = 0; i < activeFlow.flowComposer.numControllers; i++)
 			{
 				var controller:ContainerController = activeFlow.flowComposer.getControllerAt(i);
 				var container:DisplayObject = controller.container as DisplayObject;
 				if (activeFlow.interactionManager)
 					container.addEventListener(KeyboardEvent.KEY_DOWN, keyListener,false,0,true);
 				else 
 					container.removeEventListener(KeyboardEvent.KEY_DOWN, keyListener);
 			}
 		}		

		public function setActiveFlow(newActiveFlow:TextFlow):void
		{
			TextInspectorController.Instance().activeFlow = newActiveFlow;
			for (var i:int = bottomPanels.length - 1; i >= 0; --i)
				bottomPanels[i].activeFlow = newActiveFlow;
		}
		
 		public function setInteractionManager(selectType:String):void
 		{
			editingMode = selectType;
			var uiActiveFlow:TextFlow = null;

 			if (activeFlow)	
 			{
	 			switch (selectType)
	 			{
	 				case EditingMode.READ_ONLY:
						if (activeFlow.interactionManager)
							activeFlow.interactionManager = null;
						break;
					case EditingMode.READ_WRITE:
						// either direction should work.
						new EditManager(undoManager).textFlow = activeFlow;
						activeFlow.interactionManager = new EditManager(undoManager);
						
						activeFlow.addEventListener(SelectionEvent.SELECTION_CHANGE,mySelectionChangeListener,false,0,true);
						uiActiveFlow = activeFlow;
						activeFlow.interactionManager.selectRange(0, 0);
						break;
					case EditingMode.READ_SELECT:
						activeFlow.interactionManager = new SelectionManager();
						activeFlow.addEventListener(SelectionEvent.SELECTION_CHANGE,mySelectionChangeListener,false,0,true);
						break;
				}
				setActiveFlow(uiActiveFlow);
				updateEscapeKeyListener();
				updateForSelectedElementRange(new SelectionState( activeFlow, 0, 0));
 			}
		}
	
	
 		private function mySelectionChangeListener(e:SelectionEvent):void
 		{
  			updateForSelectedElementRange(e ? e.selectionState : null);
 		}
 		
 		/**
 		* Update the GUI for a particular selection range.
 		* @private
 		* @param range may be null
 		*/
 		private function updateForSelectedElementRange(selectionState:SelectionState):void
 		{
 			var range:ElementRange = selectionState ? ElementRange.createElementRange(selectionState.textFlow, selectionState.absoluteStart, selectionState.absoluteEnd) : null;
 			var selMgr:ISelectionManager = activeFlow.interactionManager;
 			
			for (var i:int = bottomPanels.length - 1; i >= 0; --i)
				bottomPanels[i].update(range);

			if (selMgr && textPanel.visible)
				selMgr.setFocus();
 		}
 		
 		/** handleResize - resize the child containers
 		  * @param alwaysResize - do the recalucation no matter if the size didn't change 
 		  */
 		public function handleResize():void
		{
			if (resizeOK && activeFlow)
			{
			 	vruler.RedrawRuler();
		 		hruler.RedrawRuler();		
			}
		}
		
		public function detachActiveFlow(deleteTheComposer:Boolean):void
		{
			if (activeFlow && activeFlow.flowComposer != null)
			{
				// Detach the containers from the display list
				for (var idx:int = 0; idx < activeFlow.flowComposer.numControllers; idx++)
				{
					var controller:ContainerController = activeFlow.flowComposer.getControllerAt(idx);
					var oldContainer:DisplayObject = controller.container;
					if (oldContainer && oldContainer.parent)
					{
						Canvas(oldContainer.parent).rawChildren.removeChild(oldContainer);
					}
				}
				activeFlow.flowComposer.removeAllControllers();
				
				// also shuts down inline graphics - need another API if we want to do this another way
				if (deleteTheComposer)
					activeFlow.flowComposer = null;
			}		
		}
		
		private function recomposeOnLoadComplete(e:StatusChangeEvent):void
		{
			if (e.status == InlineGraphicElementStatus.ERROR)
				trace("IOERROR loading inlinegraphicelement",e.errorEvent.toString());
			if (e.element.getTextFlow() == activeFlow && e.status == InlineGraphicElementStatus.SIZE_PENDING)
				activeFlow.flowComposer.updateAllControllers();
		}
		
		public function changeContent(newFlow:TextFlow):void
		{
			// Remove old containers from the display list
			if (undoManager != null) 
				undoManager.clearAll();
			if (activeFlow)
			{
				detachActiveFlow(true);
				activeFlow.removeEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,recomposeOnLoadComplete);
			}
			
			// set activeFlow (note: this variable is used in the mxml code below.)
			activeFlow = newFlow;
			if (!activeFlow)
				return;
				
			activeFlow.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,recomposeOnLoadComplete,false,0,true);
			
			textPanel.changeContainerSetup(activeFlow);

			activeFlow.interactionManager = new EditManager(undoManager);
			activeFlow.addEventListener(SelectionEvent.SELECTION_CHANGE,mySelectionChangeListener,false,0,true);
			setActiveFlow(activeFlow);
			activeFlow.interactionManager.selectRange(0, 0);
			updateEscapeKeyListener();
			activeFlow.flowComposer.updateAllControllers();

 			vruler.RedrawRuler();
 			hruler.RedrawRuler();
 		}
 		
		/** visiblePanels is an array of the labels of the right-side property panels that are opened.
		 * if you set it, the panels specified will be opened and all others will be closed.
		 */
		public function set visiblePanels(inPanelNames:Array):void
		{
			var panels:Array = inspectorBox.getChildren();
			for each(var panel:DisplayObject in panels)
			{
				if (panel is MultiPanel)
				{
					var mp:MultiPanel = panel as MultiPanel;
					mp.opened = (inPanelNames.indexOf(mp.label) != -1);
				}
			}
		}
		
		public function get visiblePanels():Array
		{
			var result:Array = [];
			var panels:Array = inspectorBox.getChildren();
			for each(var panel:DisplayObject in panels)
			{
				if (panel is MultiPanel)
				{
					var mp:MultiPanel = panel as MultiPanel;
					if (mp.opened)
						result.push(mp.label);
				}
			}
			return result;
		}
		
       ]]>
    </Script>
	
	<mx:VBox
		width="100%"
		height="100%" 
		verticalGap="2"
		backgroundColor="0x607D8A"
		fontFamily="Myriad Pro"
		fontWeight="bold">
		<mx:HBox
			width="100%"
			height="100%"
			horizontalGap="4">
			<txui:PanelWithEdgeBars
				id="panelWithScrollBars"
				width="100%"
				height="100%"
				edgeInset="18"
				gap="1"
				mainPanel="{textPanel}"
				topBar="{horizontalRulerBar}"
				rightBar="{verticalRulerBar}">
				
				<textEditBar:SingleContainerView id="textPanel"/>

				<mx:Canvas
					id="verticalRulerBar"
					verticalScrollPolicy="off"
					horizontalScrollPolicy="off">
					<txrulers:RulerBar
						id="vruler"
						orientation="vertical"
						syncToPanel="{textPanel}"
						tabPropertyEditor="{tabPropEditor}"
						tabPanelActive="{tabPanel.opened}">
					</txrulers:RulerBar>
				</mx:Canvas>
				<mx:Canvas
					id="horizontalRulerBar"
					verticalScrollPolicy="off"
					horizontalScrollPolicy="off">
					<txrulers:RulerBar
						id="hruler"
						syncToPanel="{textPanel}"
						tabPropertyEditor="{tabPropEditor}"
						tabPanelActive="{tabPanel.opened}">
					</txrulers:RulerBar>
				</mx:Canvas>
			</txui:PanelWithEdgeBars>
			<mx:Canvas
				width="270"
				height="100%"
				horizontalScrollPolicy="off"
				backgroundColor="#D9D9D9"
				verticalScrollBarStyleName="scrollbarStyle">
				<mx:VBox id="inspectorBox" verticalGap="1" width="100%" backgroundColor="#D9D9D9">
				    <txui:MultiPanel id="charPanel" styleName="multiPanel" label="CHARACTER" width="100%">
				    	<txinsp:CharacterPropertyEditor active="{charPanel.opened}"/>
				    </txui:MultiPanel>	
				    <txui:MultiPanel id="parPanel" styleName="multiPanel" label="PARAGRAPH" width="100%">
				    	<txinsp:ParagraphPropertyEditor active="{parPanel.opened}"/>
				    </txui:MultiPanel>
				    <txui:MultiPanel id="tabPanel" styleName="multiPanel" label="TAB" width="100%" opened="false">
				    	<txinsp:TabPropertyEditor id="tabPropEditor"/>
				    </txui:MultiPanel>
					<txui:MultiPanel id="listPanel" styleName="multiPanel" label="LISTS" width="100%" opened="false">
						<txinsp:ListPropertyEditor active="{listPanel.opened}"/>
					</txui:MultiPanel>
				    <txui:MultiPanel id="advancedPanel" styleName="multiPanel" label="ADVANCED CHARACTER" width="100%" opened="false">
				    	<txinsp:AdvancedTextPropertyEditor active="{advancedPanel.opened}"/>
				    </txui:MultiPanel>
				    <txui:MultiPanel id="antialiasPanel" styleName="multiPanel" label="ANTIALIAS" width="100%" opened="false">
				    	<txinsp:AntiAliasPropertyEditor active="{antialiasPanel.opened}"/>
				    </txui:MultiPanel>
				    <txui:MultiPanel id="containerPanel" styleName="multiPanel" label="CONTAINER" width="100%" opened="false">
				    	<txinsp:TextContainerPropertyEditor active="{containerPanel.opened}"/>
				    </txui:MultiPanel>
				    <txui:MultiPanel id="flowPanel" styleName="multiPanel" label="FLOW" width="100%" opened="false">
				    	<txinsp:TextFlowPropertyEditor active="{flowPanel.opened}"/>
				    </txui:MultiPanel>
				</mx:VBox>
			</mx:Canvas>
		</mx:HBox>
		<mx:TabNavigator id="bottomTabs" width="100%" creationPolicy="all" paddingLeft="8" backgroundColor="#D9D9D9" color="#202020">
			<mx:Canvas label="SOURCE" width="100%" height="28">
	 			<textEditBar:FileServices id="fileWidget" fileChoose="FileIOHelper.fileChoose(event.fileName)" textLayoutExport="FileIOHelper.textLayoutExport(activeFlow)" htmlExport="FileIOHelper.htmlExport(activeFlow)" includeInLayout="false" width="100%"/> 
			</mx:Canvas>
			<mx:Canvas label="LINKS" width="100%" height="100%">
   				<textEditBar:LinkBar id="linkElementProps" creationPolicy="all" includeInLayout="false"/>  	
			</mx:Canvas>
			<mx:Canvas label="GRAPHICS" width="100%" height="100%">
				<textEditBar:GraphicBar id="foreignElementProps" creationPolicy="all" includeInLayout="false"/>
			</mx:Canvas>
			
		</mx:TabNavigator>
	</mx:VBox>

</mx:Canvas>