<commit_before><?xml version="1.0" encoding="utf-8"?>
<!--
/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/
-->
<ui:DraggablePanel xmlns="weave.ui.annotation.*"
				   xmlns:mx="http://www.adobe.com/2006/mxml"
				   xmlns:ui="weave.ui.*"
				   width="25%" height="25%" backgroundAlpha="0" borderThickness="0"
				   horizontalScrollPolicy="off" layout="absolute" verticalScrollPolicy="off">
	<mx:TextArea id="textArea" width="100%" height="100%" minWidth="5" minHeight="5"
				 borderStyle="solid" editable="false" wordWrap="true"/>
	<ui:ControlPanel added="if (event.target == controlPanel) updateTextArea()"
					 percentHeight="NaN" percentWidth="NaN"
					 removed="if (event.target == controlPanel) callLater(updateTextArea)"
					 sessionPanelCoordsAsPercentages="false" title="Annotation Editor">
		<mx:VBox id="toolbar" width="100%" height="100%" horizontalGap="7"
				 horizontalScrollPolicy="off" paddingBottom="2" paddingLeft="2" paddingRight="2"
				 paddingTop="2" verticalScrollPolicy="off">

			<mx:CheckBox id="lockCheckBox" label="Enable window borders and resizing"/>
			
			<mx:HBox width="100%" horizontalScrollPolicy="off" paddingBottom="2" paddingLeft="2"
					 paddingRight="2" paddingTop="2" verticalScrollPolicy="off">
				
				<mx:ColorPicker id="colorPicker" width="22" height="22"
								change="applyTextFormat(event)"/>
				
				<ui:CustomComboBox id="fontFamilyCombo" change="applyTextFormat(event)"
								   dataProvider="{fontFamilyArray}" editable="false"/>
				
				<ui:CustomComboBox id="fontSizeCombo" change="applyTextFormat(event)"
								   dataProvider="{fontSizeArray}" editable="false" paddingLeft="2"
								   paddingRight="2"/>
				
				<mx:HBox id="toolBar2" horizontalGap="0">
					<mx:Button id="boldButton" width="30" label="B" change="applyTextFormat(event)"
							   fontFamily="_serif" fontWeight="bold" toggle="true" toolTip="Bold"/>
					<mx:Button id="italicButton" width="30" label="I" change="applyTextFormat(event)"
							   fontFamily="_serif" fontStyle="italic" toggle="true" toolTip="Italic"/>
					<mx:Button id="underlineButton" width="30" label="U"
							   change="applyTextFormat(event)" fontFamily="_serif"
							   textDecoration="underline" toggle="true" toolTip="Underline"/>
				</mx:HBox>
			</mx:HBox>
			
			<mx:Grid>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label text="Paragraph style:"/>
					</mx:GridItem>
					<mx:GridItem>
						<ui:CustomComboBox id="paragraphCombo" change="applyParagraphFormat(event);"
										   dataProvider="{['Left align','Right align','Center','Justify','Bullet']}"
										   selectedIndex="0"/>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="roundingLabel" text="Corner rounding:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HSlider id="cornerRadiusSlider" width="100%" liveDragging="true"
									maximum="30" minimum="0" snapInterval="1"
									toolTip="Change the editing text area's corner rounding."
									value="0"/>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="paddingLabel" text="Padding around text:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HSlider id="paddingSlider" width="100%" liveDragging="true" maximum="25"
									minimum="0" snapInterval="1"
									toolTip="Set the space between the text and the text box."
									value="0"/>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="backgroundLabel" text="Background properties:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HBox width="100%">
							<mx:ColorPicker id="backgroundColorPicker" selectedColor="white"
											toolTip="Change the editing text area's background color."/>
							<mx:HSlider id="backgroundAlphaSlider" width="100%" liveDragging="true"
										maximum="1" minimum="0"
										toolTip="Change the editing text area's background transparency.  A value of 1 (slider to the right) is fully opaque, 0 (slider to the left) is fully transparent."
										value="1.0"/>
						</mx:HBox>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="borderLabel" text="Border properties:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HBox width="100%">
							<mx:ColorPicker id="borderColorPicker"
											enabled="{borderThicknessSlider.value &gt; 0}"
											toolTip="Change the editing text area's border color."/>
							
							<mx:HSlider id="borderThicknessSlider"
										value="1" minimum="0" maximum="25" snapInterval="1" 
										toolTip = "Change the editing text area's border thickness."
										width="100%" liveDragging="true"/>
						</mx:HBox>
					</mx:GridItem>
				</mx:GridRow>
			</mx:Grid>
		</mx:VBox>
	</ui:ControlPanel>
	<mx:Script>
		<![CDATA[
			import mx.binding.utils.BindingUtils;
			import mx.core.IUITextField;
			import mx.core.mx_internal;
			
			import weave.Weave;
			import weave.api.core.ILinkableContainer;
			import weave.api.getCallbackCollection;
			import weave.api.linkBindableProperty;
			import weave.api.linkSessionState;
			import weave.api.newDisposableChild;
			import weave.api.registerLinkableChild;
			import weave.api.reportError;
			import weave.core.LinkableFunction;
			import weave.core.LinkableNumber;
			import weave.core.LinkableString;
			import weave.ui.CustomContextMenuManager;
			
			public const htmlText:LinkableString        = registerLinkableChild(this, new LinkableString(''), handleLinkableHtmlText, true);
			public const backgroundAlpha:LinkableNumber = registerLinkableChild(this, new LinkableNumber(1, isFinite), applyStyle, true);
			public const backgroundColor:LinkableNumber = registerLinkableChild(this, new LinkableNumber(0xFFFFFF, isFinite), applyStyle, true);
			public const cornerRadius:LinkableNumber    = registerLinkableChild(this, new LinkableNumber(0, isFinite), applyStyle, true);
			public const borderColor:LinkableNumber     = registerLinkableChild(this, new LinkableNumber(0x000000, isFinite), applyStyle, true);
			public const borderThickness:LinkableNumber = registerLinkableChild(this, new LinkableNumber(1.0, isFinite), applyStyle, true);
			public const padding:LinkableNumber         = registerLinkableChild(this, new LinkableNumber(10, isFinite), applyStyle, true);
			
			private const htmlTextFunction:LinkableFunction = newDisposableChild(this, LinkableFunction);
			
			override protected function constructor():void
			{
				super.constructor();
				
				minimizable.value = false;
				maximizable.value = false;
				enableBorders.addImmediateCallback(this, updateBorders);
			}
			
			override protected function updateForceEnableBorders():void
			{
				if (controlPanel && controlPanel.parent)
					super.updateForceEnableBorders();
				else
					forceEnableBorders.value = false;
			}
			
			override protected function childrenCreated():void
			{
				super.childrenCreated();
				
				linkSessionState(enableBorders, resizeable);
				linkBindableProperty(enableBorders, lockCheckBox, 'selected');
				linkBindableProperty(backgroundAlpha, backgroundAlphaSlider, "value");
				linkBindableProperty(backgroundColor, backgroundColorPicker, "selectedColor");
				linkBindableProperty(cornerRadius,    cornerRadiusSlider, "value" );
				linkBindableProperty(borderColor,     borderColorPicker, "selectedColor");
				linkBindableProperty(borderThickness, borderThicknessSlider, "value");
				linkBindableProperty(padding,         paddingSlider, "value");
				BindingUtils.bindSetter(handleTextAreaChange, textArea, 'htmlText');
				getCallbackCollection(Weave.root).addGroupedCallback(this, handleWeaveRootChange);

				getTextField().alwaysShowSelection = true;
				textArea.setStyle("focusAlpha", 0);
				
				applyStyle();
			}

			private function handleTextAreaChange(value:String):void
			{
				// we only want to save the session state if the control panel is open (the user is editing the text).
				if (controlPanel.parent)
					htmlText.value = value;
			}
			
			private function handleLinkableHtmlText():void
			{
				if (!parent)
				{
					callLater(handleLinkableHtmlText);
					return;
				}
				
				// use internal text field because the real _tempTextField loses formatting.
				var _tempTextField:IUITextField = textArea.mx_internal::getTextField();
				
				if (!_tempTextField)
				{
					reportError("Unexpected: textArea.mx_internal::getTextField() is null");
					return;
				}
				
				_tempTextField.htmlText = htmlText.value; // use the textField temporarily for getTextFormat,setTextFormat
				// make sure the text between each pair of { and } brackets only has a single format.
				var begin:int;
				var end:int = 0;
				while (true)
				{
					// find a pair of { and } brackets
					begin = _tempTextField.text.indexOf("{", end);
					if (begin < 0)
						break;
					end = _tempTextField.text.indexOf("}", begin);
					if (end < 0)
						break;
					
					// make sure the text between begin & end only has a single format
					var f:TextFormat = _tempTextField.getTextFormat(begin, end + 1);
					_tempTextField.setTextFormat(f, begin, end + 1);
					
//					// replace the text from { to }
//					var script:String = _tempTextField.text.substring(begin + 1, end);
//					htmlTextFunction.value = script;
//					_tempTextField.replaceText(begin, end + 1, String(htmlTextFunction.apply()));
				}
				
				htmlTextFunction.value = '`' + _tempTextField.htmlText.split('`').join('\\`') + '`';
				
				updateTextArea();
			}
			
			/**
			 * This function gets called when anything in Weave changes so that inline code within brackets can be re-evaluated.
			 */
			private function handleWeaveRootChange():void
			{
				// while the control panel is closed, update the text area in case inline code needs to be re-evaluated
				if (!controlPanel.parent)
					updateTextArea();
			}
			
			private function updateTextArea():void
			{
				if (!parent)
				{
					callLater(updateTextArea);
					return;
				}
				
				// if control panel is closed, evaluate inline code
				if (!controlPanel.parent)
				{
					textArea.editable = false;
					try
					{
						textArea.htmlText = htmlTextFunction.apply();
					}
					catch (e:Error)
					{
						reportError(e);
						textArea.htmlText = htmlText.value; // show literally what the user has typed
					}
				}
				else
				{
					textArea.editable = true;
					textArea.htmlText = htmlText.value; // show literally what the user has typed
				}
			}
			
			private function applyStyle():void
			{
				if (!parent)
					return;
				textArea.setStyle("backgroundAlpha", backgroundAlpha.value);
				textArea.setStyle("backgroundColor", backgroundColor.value);
				textArea.setStyle("cornerRadius", cornerRadius.value);
				textArea.setStyle("paddingLeft", padding.value);
				textArea.setStyle("paddingRight", padding.value);
				textArea.setStyle("borderColor", borderColor.value);
				textArea.setStyle("borderThickness", borderThickness.value);
			}

			/**
			 * This function is called when the user presses the tool button.
			 */
			override public function toggleControlPanel():void
			{
				super.toggleControlPanel();
			}
			
 			private function getTextField():TextField
			{
				return textArea.mx_internal::getTextField();
			}
 			
			private function applyParagraphFormat(e:Event):void
			{
				if (false)
				{
					//TODO: fix this buggy code
					
					// Apply the paragraph styles to the whole paragraph instead of just the selected text
					var beginIndex:int = getTextField().selectionBeginIndex;
					var endIndex:int = getTextField().selectionEndIndex;
					
					beginIndex = getTextField().getFirstCharInParagraph(beginIndex) - 1;
					beginIndex = Math.max(0, beginIndex);
					endIndex = getTextField().getFirstCharInParagraph(endIndex);
					if (endIndex >= 0)
						endIndex += getTextField().getParagraphLength(endIndex) - 1;
					else
						endIndex = beginIndex + getTextField().getParagraphLength(beginIndex);
					applyTextFormat(e, beginIndex, endIndex);
				}
				else
				{
					applyTextFormat(e, 0, getTextField().length);
				}
			}
			
			private function applyTextFormat(e:Event, beginIndex:int = -1, endIndex:int = -1):void
			{
				// save selection & scroll position
				var selectionBeginIndex:int = getTextField().selectionBeginIndex;
				var selectionEndIndex:int = getTextField().selectionEndIndex;
				var vsp:int = textArea.verticalScrollPosition;
				if (beginIndex < 0)
					beginIndex = selectionBeginIndex;
				if (endIndex < 0)
					endIndex = selectionEndIndex;
				
				// get text format from gui
				var f:TextFormat = new TextFormat();
				if (e.target == fontFamilyCombo)
					f.font = fontFamilyCombo.selectedItem as String;
				if (e.target == fontSizeCombo)
					f.size = fontSizeCombo.selectedItem;
				if (e.target == boldButton)
					f.bold = boldButton.selected;
				if (e.target == italicButton)
					f.italic = italicButton.selected;
				if (e.target == underlineButton)
					f.underline = underlineButton.selected;
				if (e.target == colorPicker)
					f.color = colorPicker.selectedColor;
				if (e.target == paragraphCombo)
				{
					if (paragraphCombo.selectedIndex == 4)
					{
						f.bullet = true;
					}
					else
					{
						f.bullet = false;
						f.align = ['left','right','center','justify'][paragraphCombo.selectedIndex];
					}
				}
				
				// set text format using temporary text field
				getTextField().defaultTextFormat = f;
				if (beginIndex >= 0 && beginIndex < getTextField().length)
				{
					// compute new htmlText using temporary text field
					_tempTextField.htmlText = textArea.htmlText;
					// extra newline may get removed from htmlText, so make sure endIndex <= length
					endIndex = Math.min(endIndex, _tempTextField.length);
					if (beginIndex < endIndex)
						_tempTextField.setTextFormat(f, beginIndex, endIndex);
					htmlText.value = _tempTextField.htmlText;
				}
				
				textArea.setFocus();
				textArea.validateNow();
				
				// restore selection & scroll position
				selectionEndIndex = Math.min(selectionEndIndex, getTextField().length);
				getTextField().setSelection(selectionBeginIndex, selectionEndIndex);
				textArea.verticalScrollPosition = vsp;
			}
			<commit_msg>Made changes so that the font list now matches the one in the preferences menu and editing the text format can be done on the fly now. There is a bug with going back and modifying the text style.<commit_after><?xml version="1.0" encoding="utf-8"?>
<!--
/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/
-->
<ui:DraggablePanel xmlns="weave.ui.annotation.*"
				   xmlns:mx="http://www.adobe.com/2006/mxml"
				   xmlns:ui="weave.ui.*"
				   width="25%" height="25%" backgroundAlpha="0" borderThickness="0"
				   horizontalScrollPolicy="off" layout="absolute" verticalScrollPolicy="off">
	<mx:TextArea id="textArea" width="100%" height="100%" minWidth="5" minHeight="5"
				 borderStyle="solid" editable="false" wordWrap="true"/>
	<ui:ControlPanel added="if (event.target == controlPanel) updateTextArea()"
					 percentHeight="NaN" percentWidth="NaN"
					 removed="if (event.target == controlPanel) callLater(updateTextArea)"
					 sessionPanelCoordsAsPercentages="false" title="Annotation Editor">
		<mx:VBox id="toolbar" width="100%" height="100%" horizontalGap="7"
				 horizontalScrollPolicy="off" paddingBottom="2" paddingLeft="2" paddingRight="2"
				 paddingTop="2" verticalScrollPolicy="off">

			<mx:CheckBox id="lockCheckBox" label="Enable window borders and resizing"/>
			
			<mx:HBox width="100%" horizontalScrollPolicy="off" paddingBottom="2" paddingLeft="2"
					 paddingRight="2" paddingTop="2" verticalScrollPolicy="off">
				<ui:FontControl id="fontControls" />
			</mx:HBox>
			
			<mx:Grid>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label text="Paragraph style:"/>
					</mx:GridItem>
					<mx:GridItem>
						<ui:CustomComboBox id="paragraphCombo" change="applyParagraphFormat(event);"
										   dataProvider="{['Left align','Right align','Center','Justify','Bullet']}"
										   selectedIndex="0"/>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="roundingLabel" text="Corner rounding:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HSlider id="cornerRadiusSlider" width="100%" liveDragging="true"
									maximum="30" minimum="0" snapInterval="1"
									toolTip="Change the editing text area's corner rounding."
									value="0"/>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="paddingLabel" text="Padding around text:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HSlider id="paddingSlider" width="100%" liveDragging="true" maximum="25"
									minimum="0" snapInterval="1"
									toolTip="Set the space between the text and the text box."
									value="0"/>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="backgroundLabel" text="Background properties:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HBox width="100%">
							<mx:ColorPicker id="backgroundColorPicker" selectedColor="white"
											toolTip="Change the editing text area's background color."/>
							<mx:HSlider id="backgroundAlphaSlider" width="100%" liveDragging="true"
										maximum="1" minimum="0"
										toolTip="Change the editing text area's background transparency.  A value of 1 (slider to the right) is fully opaque, 0 (slider to the left) is fully transparent."
										value="1.0"/>
						</mx:HBox>
					</mx:GridItem>
				</mx:GridRow>
				<mx:GridRow>
					<mx:GridItem>
						<mx:Label id="borderLabel" text="Border properties:"/>
					</mx:GridItem>
					<mx:GridItem>
						<mx:HBox width="100%">
							<mx:ColorPicker id="borderColorPicker"
											enabled="{borderThicknessSlider.value &gt; 0}"
											toolTip="Change the editing text area's border color."/>
							
							<mx:HSlider id="borderThicknessSlider"
										value="1" minimum="0" maximum="25" snapInterval="1" 
										toolTip = "Change the editing text area's border thickness."
										width="100%" liveDragging="true"/>
						</mx:HBox>
					</mx:GridItem>
				</mx:GridRow>
			</mx:Grid>
		</mx:VBox>
	</ui:ControlPanel>
	<mx:Script>
		<![CDATA[
			import mx.binding.utils.BindingUtils;
			import mx.core.IUITextField;
			import mx.core.mx_internal;
			import mx.events.ColorPickerEvent;
			import mx.events.ListEvent;
			import mx.events.StateChangeEvent;
			
			import weave.Weave;
			import weave.api.core.ILinkableContainer;
			import weave.api.getCallbackCollection;
			import weave.api.linkBindableProperty;
			import weave.api.linkSessionState;
			import weave.api.newDisposableChild;
			import weave.api.registerLinkableChild;
			import weave.api.reportError;
			import weave.core.LinkableFunction;
			import weave.core.LinkableNumber;
			import weave.core.LinkableString;
			import weave.ui.CustomContextMenuManager;
			
			public const htmlText:LinkableString        = registerLinkableChild(this, new LinkableString(''), handleLinkableHtmlText, true);
			public const backgroundAlpha:LinkableNumber = registerLinkableChild(this, new LinkableNumber(1, isFinite), applyStyle, true);
			public const backgroundColor:LinkableNumber = registerLinkableChild(this, new LinkableNumber(0xFFFFFF, isFinite), applyStyle, true);
			public const cornerRadius:LinkableNumber    = registerLinkableChild(this, new LinkableNumber(0, isFinite), applyStyle, true);
			public const borderColor:LinkableNumber     = registerLinkableChild(this, new LinkableNumber(0x000000, isFinite), applyStyle, true);
			public const borderThickness:LinkableNumber = registerLinkableChild(this, new LinkableNumber(1.0, isFinite), applyStyle, true);
			public const padding:LinkableNumber         = registerLinkableChild(this, new LinkableNumber(10, isFinite), applyStyle, true);
			
			private const htmlTextFunction:LinkableFunction = newDisposableChild(this, LinkableFunction);
			
			override protected function constructor():void
			{
				super.constructor();
				
				minimizable.value = false;
				maximizable.value = false;
				enableBorders.addImmediateCallback(this, updateBorders);
			}
			
			override protected function updateForceEnableBorders():void
			{
				if (controlPanel && controlPanel.parent)
					super.updateForceEnableBorders();
				else
					forceEnableBorders.value = false;
			}
			
			override protected function childrenCreated():void
			{
				fontControls.initialize();
				super.childrenCreated();
				
				linkSessionState(enableBorders, resizeable);
				linkBindableProperty(enableBorders, lockCheckBox, 'selected');
				linkBindableProperty(backgroundAlpha, backgroundAlphaSlider, "value");
				linkBindableProperty(backgroundColor, backgroundColorPicker, "selectedColor");
				linkBindableProperty(cornerRadius,    cornerRadiusSlider, "value" );
				linkBindableProperty(borderColor,     borderColorPicker, "selectedColor");
				linkBindableProperty(borderThickness, borderThicknessSlider, "value");
				linkBindableProperty(padding,         paddingSlider, "value");
				BindingUtils.bindSetter(handleTextAreaChange, textArea, 'htmlText');
				getCallbackCollection(Weave.root).addGroupedCallback(this, handleWeaveRootChange);

				getTextField().alwaysShowSelection = true;
				textArea.setStyle("focusAlpha", 0);
				getTextField().embedFonts = true;
				textArea.setStyle("embedFonts", true);
				
				fontControls.fontFamilyCombo.selectedLabel = getTextField().defaultTextFormat.font;
				fontControls.fontSizeCombo.selectedItem = getTextField().defaultTextFormat.size;
				fontControls.colorPicker.addEventListener(ColorPickerEvent.CHANGE, applyTextFormat);
				fontControls.fontFamilyCombo.addEventListener(ListEvent.CHANGE, applyTextFormat);
				fontControls.fontSizeCombo.addEventListener(ListEvent.CHANGE, applyTextFormat);
				fontControls.boldButton.addEventListener(Event.CHANGE, applyTextFormat);
				fontControls.italicButton.addEventListener(Event.CHANGE, applyTextFormat);
				fontControls.underlineButton.addEventListener(Event.CHANGE, applyTextFormat);
				
				applyStyle();
			}

			private function handleTextAreaChange(value:String):void
			{
				// we only want to save the session state if the control panel is open (the user is editing the text).
				if (controlPanel.parent)
					htmlText.value = value;
			}
			
			private function handleLinkableHtmlText():void
			{
				if (!parent)
				{
					callLater(handleLinkableHtmlText);
					return;
				}
				
				// use internal text field because the real _tempTextField loses formatting.
				var _tempTextField:IUITextField = textArea.mx_internal::getTextField();
				
				if (!_tempTextField)
				{
					reportError("Unexpected: textArea.mx_internal::getTextField() is null");
					return;
				}
				
				_tempTextField.htmlText = htmlText.value; // use the textField temporarily for getTextFormat,setTextFormat
				// make sure the text between each pair of { and } brackets only has a single format.
				var begin:int;
				var end:int = 0;
				while (true)
				{
					// find a pair of { and } brackets
					begin = _tempTextField.text.indexOf("{", end);
					if (begin < 0)
						break;
					end = _tempTextField.text.indexOf("}", begin);
					if (end < 0)
						break;
					
					// make sure the text between begin & end only has a single format
				 	var f:TextFormat = _tempTextField.getTextFormat(begin, end + 1);
					_tempTextField.setTextFormat(f, begin, end + 1);
					
//					// replace the text from { to }
//					var script:String = _tempTextField.text.substring(begin + 1, end);
//					htmlTextFunction.value = script;
//					_tempTextField.replaceText(begin, end + 1, String(htmlTextFunction.apply()));
				}
				
				htmlTextFunction.value = '`' + _tempTextField.htmlText.split('`').join('\\`') + '`';
				
				//This is a hack to keep re-applying the currently selected text format.
				applyTextFormat(new Event("LIST"));
				
				updateTextArea();
			}
			
			/**
			 * This function gets called when anything in Weave changes so that inline code within brackets can be re-evaluated.
			 */
			private function handleWeaveRootChange():void
			{
				// while the control panel is closed, update the text area in case inline code needs to be re-evaluated
				if (!controlPanel.parent)
					updateTextArea();
			}
			
			private function updateTextArea():void
			{
				if (!parent)
				{
					callLater(updateTextArea);
					return;
				}
				
				// if control panel is closed, evaluate inline code
				if (!controlPanel.parent)
				{
					textArea.editable = false;
					try
					{
						textArea.htmlText = htmlTextFunction.apply();
					}
					catch (e:Error)
					{
						reportError(e);
						textArea.htmlText = htmlText.value; // show literally what the user has typed
					}
				}
				else
				{
					textArea.editable = true;
					textArea.htmlText = htmlText.value; // show literally what the user has typed
				}
			}
			
			private function applyStyle():void
			{
				if (!parent)
					return;
				textArea.setStyle("backgroundAlpha", backgroundAlpha.value);
				textArea.setStyle("backgroundColor", backgroundColor.value);
				textArea.setStyle("cornerRadius", cornerRadius.value);
				textArea.setStyle("paddingLeft", padding.value);
				textArea.setStyle("paddingRight", padding.value);
				textArea.setStyle("borderColor", borderColor.value);
				textArea.setStyle("borderThickness", borderThickness.value);
			}

			/**
			 * This function is called when the user presses the tool button.
			 */
			override public function toggleControlPanel():void
			{
				super.toggleControlPanel();
			}
			
 			private function getTextField():TextField
			{
				return textArea.mx_internal::getTextField();
			}
 			
			private function applyParagraphFormat(e:Event):void
			{
				if (false)
				{
					//TODO: fix this buggy code
					
					// Apply the paragraph styles to the whole paragraph instead of just the selected text
					var beginIndex:int = getTextField().selectionBeginIndex;
					var endIndex:int = getTextField().selectionEndIndex;
					
					beginIndex = getTextField().getFirstCharInParagraph(beginIndex) - 1;
					beginIndex = Math.max(0, beginIndex);
					endIndex = getTextField().getFirstCharInParagraph(endIndex);
					if (endIndex >= 0)
						endIndex += getTextField().getParagraphLength(endIndex) - 1;
					else
						endIndex = beginIndex + getTextField().getParagraphLength(beginIndex);
					applyTextFormat(e, beginIndex, endIndex);
				}
				else
				{
					applyTextFormat(e, 0, getTextField().length);
				}
			}
			
			private function applyTextFormat(e:Event, beginIndex:int = -1, endIndex:int = -1):void
			{
				// save selection & scroll position
				var selectionBeginIndex:int = getTextField().selectionBeginIndex;
				var selectionEndIndex:int = getTextField().selectionEndIndex;
				var vsp:int = textArea.verticalScrollPosition;
				if (beginIndex < 0)
					beginIndex = selectionBeginIndex;
				if (endIndex < 0)
					endIndex = selectionEndIndex;
				
				// get text format from gui
				var f:TextFormat = new TextFormat();
				f.font = fontControls.fontFamilyCombo.selectedItem as String;
				f.size = fontControls.fontSizeCombo.selectedItem;
				f.color = fontControls.colorPicker.selectedColor;
				f.bold = fontControls.boldButton.selected;
				f.italic = fontControls.italicButton.selected;
				f.underline = fontControls.underlineButton.selected;
				if (e.target == paragraphCombo)
				{
					if (paragraphCombo.selectedIndex == 4)
					{
						f.bullet = true;
					}
					else
					{
						f.bullet = false;
						f.align = ['left','right','center','justify'][paragraphCombo.selectedIndex];
					}
				}
				
				// set text format using temporary text field
				if( beginIndex == getTextField().caretIndex && endIndex == getTextField().caretIndex )
				{
					getTextField().defaultTextFormat = f;
					textArea.setStyle("fontFamily", fontControls.fontFamilyCombo.selectedLabel);
				}
				else
				{
					getTextField().setTextFormat(f, beginIndex, endIndex);
				}
/* 				if (beginIndex >= 0 && beginIndex < getTextField().length)
				{
					// compute new htmlText using temporary text field
					_tempTextField.htmlText = textArea.htmlText;
					// extra newline may get removed from htmlText, so make sure endIndex <= length
					endIndex = Math.min(endIndex, _tempTextField.length);
					if (beginIndex < endIndex)
						_tempTextField.setTextFormat(f, beginIndex, endIndex);
					htmlText.value = _tempTextField.htmlText;
				} */
				
				textArea.setFocus();
				textArea.validateNow();
				
				// restore selection & scroll position
				selectionEndIndex = Math.min(selectionEndIndex, getTextField().length);
				getTextField().setSelection(selectionBeginIndex, selectionEndIndex);
				textArea.verticalScrollPosition = vsp;
			}
			
{'fraction_non_alphanumeric': 0.1143604689673445, 'fraction_numerical': 0.00854474398887196, 'mean_word_length': 3.4912985274431056, 'pattern_counts': {'":': 0, '<': 150, '<?xml version=': 2, '>': 138, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5826531', 'n_tokens_mistral': 11476, 'n_tokens_neox': 8617, 'n_words': 2062}