Return-Path:
X-Original-To: apmail-flex-commits-archive@www.apache.org
Delivered-To: apmail-flex-commits-archive@www.apache.org
Received: from mail.apache.org (hermes.apache.org [140.211.11.3])
by minotaur.apache.org (Postfix) with SMTP id BBF3F11A04
for ;
Wed, 3 Sep 2014 22:49:48 +0000 (UTC)
Received: (qmail 63812 invoked by uid 500); 3 Sep 2014 22:49:44 -0000
Delivered-To: apmail-flex-commits-archive@flex.apache.org
Received: (qmail 63741 invoked by uid 500); 3 Sep 2014 22:49:44 -0000
Mailing-List: contact commits-help@flex.apache.org; run by ezmlm
Precedence: bulk
List-Help:
List-Unsubscribe:
List-Post:
List-Id:
Reply-To: dev@flex.apache.org
Delivered-To: mailing list commits@flex.apache.org
Received: (qmail 63653 invoked by uid 99); 3 Sep 2014 22:49:44 -0000
Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org)
(140.211.11.114)
by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 03 Sep 2014 22:49:44 +0000
Received: by tyr.zones.apache.org (Postfix, from userid 65534)
id D03149B29C6; Wed, 3 Sep 2014 22:49:43 +0000 (UTC)
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
From: jmclean@apache.org
To: commits@flex.apache.org
Date: Wed, 03 Sep 2014 22:50:01 -0000
Message-Id: <01dd01ed69994888bc00341caad5f5c5@git.apache.org>
In-Reply-To: <1186597fb7b744c6bad6a284a9ea070e@git.apache.org>
References: <1186597fb7b744c6bad6a284a9ea070e@git.apache.org>
X-Mailer: ASF-Git Admin Mailer
Subject: [20/50] [abbrv] remove Adobe from directory names (package name still
contains Adobe)
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
new file mode 100644
index 0000000..426ca4c
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
@@ -0,0 +1,562 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling
+{
+ import com.adobe.linguistics.spelling.UserDictionary;
+ import com.adobe.linguistics.spelling.framework.ResourceTable;
+ import com.adobe.linguistics.spelling.framework.SpellingConfiguration;
+ import com.adobe.linguistics.spelling.framework.SpellingService;
+ import com.adobe.linguistics.spelling.ui.HaloHighlighter;
+ import com.adobe.linguistics.spelling.ui.HaloWordProcessor;
+ import com.adobe.linguistics.spelling.ui.IHighlighter;
+ import com.adobe.linguistics.spelling.ui.IWordProcessor;
+ import com.adobe.linguistics.utils.TextTokenizer;
+ import com.adobe.linguistics.utils.Token;
+
+ import flash.events.Event;
+ import flash.events.FocusEvent;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.net.SharedObject;
+ import flash.net.URLLoader;
+ import flash.net.URLRequest;
+ import flash.text.TextField;
+ import flash.utils.Dictionary;
+
+ import mx.controls.RichTextEditor;
+ import mx.controls.TextArea;
+ import mx.controls.TextInput;
+ import mx.core.UIComponent;
+ import mx.core.mx_internal;
+ import mx.events.ScrollEvent;
+
+ use namespace mx_internal;
+
+ /**
+ * A comprehensive convenience class that bundles a context menu UI,
+ * the spelling engine, the dictionary loader, and user dictionary support
+ * to enable a single-line integration of spell checking functionality into
+ * any text related Flex UI component. While this class drastically simplifies
+ * the effort to enable spell checking functionality in a Flex UI component,
+ * it does shield the developer form controlling detailed behaviors of the spell
+ * checker and the user dictionary storage options.
+ *
+ * This class provides a simple UI for some standard Flex UI components.
+ * It is not intended to address a complete user interface.
+ * Instead, it presents a basic user interface for some commonly used Flex UI components.
+ *
+ * For advanced text editing applications, more complex features are likely required.
+ * For those applications, we recommend bypassing this class and utilizing the SpellChecker
class directly.
+ *
+ * SpellUI
uses the AdobeSpellingConfig.xml file to lookup corresponding resource files for a given locale.
+ * The default location of AdobeSpellingConfig.xml is [yourapplicationDirectory]/AdobeSpellingConfig.xml. This could be customized using
+ * spellingConfigUrl
property of SpellUI
. You don't have to change the content of this file. However,
+ * if you want to add a new language, to use an alternative dictionary or to customize the location for your dictionaries, you can modify it.
+ * There's an known issue with IIS web server when loading dictionary files with unknown extensions, in which case you can modify the XML to work around it.
+ * A sample AdobeSpellingConfig.xml will look as follows:
+ *
+ *
+ * <?xml version="1.0" encoding='UTF-8'?>
+ * <SpellingConfig>
+ * <LanguageResource language="English" languageCode="en_US" ruleFile="dictionaries/en_US/en_US.aff" dictionaryFile="dictionaries/en_US/en_US.dic"/>
+ * <LanguageResource language="Spanish" languageCode="es_ES" ruleFile="dictionaries/es_ES/es_ES.aff" dictionaryFile="dictionaries/es_ES/es_ES.dic"/>
+ * <LanguageResource language="Portuguese" languageCode="pt_PT" ruleFile="dictionaries/pt_PT/pt_PT.aff" dictionaryFile="dictionaries/pt_PT/pt_PT.dic"/>
+ * <LanguageResource language="Italian" languageCode="it_IT" ruleFile="dictionaries/it_IT/it_IT.aff" dictionaryFile="dictionaries/it_IT/it_IT.dic"/>
+ * </SpellingConfig>
+ *
+ *
+ * Note: The languageCode can be an arbitrary value, as long as you are consistent when passing them to the Squiggly classes.
+ * However, we highly encourage you to follow the two part Unicode language identifier format.
+ * For more information, please consult the latest Unicode Technical Standard that can be found at: http://unicode.org/reports/tr35/.
+ *
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public class SpellUI
+ {
+ private var hh:IHighlighter;
+ private var hw:IWordProcessor;
+
+
+ private var _checkLastWord:Boolean = true;
+
+ private var _spellingEnabled:Boolean;
+
+ private var _actualParent:*;
+ private var isHaloComponent:Boolean;
+
+ //New Added below
+ private var mTextField:TextField;
+
+ private var _dictname:String = new String();
+
+ private var _userdict:UserDictionary = null;
+ private var _sharedobj:SharedObject = null;
+ private var scm:SpellingContextMenu;
+ private var _newchecker:SpellChecker = null;
+ private var _resource_locale:Object = null;
+ private var _spellingservice:SpellingService = null;
+
+ private static var _contextMenuEntries:Object = {enable:"Enable Spelling", disable:"Disable Spelling", add:"Add to dictionary"};
+ private static var _spellingConfigUrl:String = "AdobeSpellingConfig.xml";
+
+ private static var _UITable:Dictionary= new Dictionary();
+ private static var _parentTable:Dictionary= new Dictionary();
+ private static var _cacheDictTable:Dictionary= new Dictionary();
+
+ private static var _configXML:XML = null;
+ private static var _configXMLLoading:Boolean = false;
+ private static var _configXMLLoader:URLLoader = new URLLoader();
+
+
+
+ // Work around for the memory usage problem, ideally a better fix is to provide a dicitonary unload function
+ private static var _cache:Object = new Object();
+
+ /**
+ * Enable the spell checking feature in the specified language for a UI component. Once a component is spell checking enabled, misspelled words will be highlighted with a squiggly line. Users can
+ * right click on a misspelled word to see the suggestions in the context menu.
+ *
+ *
+ *
+ * @param comp A text editing Flex UI component. It can be a mx TextArea
, TextInput
or RichTextEditor
.
+ * If you are using AdobeSpellingUIEx.swc, it can also be a spark TextArea
or TextInput
.
+ * @param lang The language code used for spell checking, for example en_US
. it will lookup the AdobeSpellingConfig.xml file to access corresponding resource files.
+ * AdobeSpellingConfig.xml should be located at the same folder as your main mxml source file. You don't have to change the content of this file. However,
+ * if you want to add a new language, to use an alternative dictionary or to customize the location for your dictionaries, you can modify it. There's an known issue with
+ * IIS web server when loading dictionary files with unknown extensions, in which case you can modify the XML to work around it.
+ *
+ *
+ *
+ * @includeExample Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public static function enableSpelling(comp:UIComponent, lang:String):void
+ {
+ if ( lang == null ) return;
+ // TODO: Change dict parameter type to a SpellCheck class or a URL string.
+ var txt:* = getComponentTextModel(comp);
+
+ if ( txt==null || _UITable[comp]!=undefined )
+ return;
+
+ // TODO: dangerous, is garbage collection going to clear this?
+ _UITable[comp]=new SpellUI(txt, lang);
+ _parentTable[txt] = comp;
+ _cacheDictTable[comp]=lang;
+ }
+
+ /**
+ * Set the spelling context menu entries. This uses the flex object as an associative array for extensibility.
+ * entries
should have all the customized contextMenu entries including enable (spelling),
+ * disable (spelling) and add (to dictionary)
. To ensure a consistent contextMenu within your application,
+ * the spelling context menu entries you provide here are applied to all UI components. We recommend you use this API
+ * with Flex resource for localization. Make sure to also have a look at the Flex localization documentation.
+ *
+ * @see http://livedocs.adobe.com/flex/3/html/help.html?content=l10n_1.html
+ *
+ * @param entries A flex Ojbect that looks like entries:Object = {enable:"Enable Spelling", disable:"Disable Spelling",
+ * add:"Add to dictionary"}
. If you don't customize the contextMenu, the default contextMenu in English will be used.
+ * We recommend that you use the Flex localization resource to obtain these strings.
+ * @return True
if the spelling menu is successfully customized, false
if it fails. Possible failure
+ * reasons include passing the wrong object or missing some required entries. If the function fails, the contextMenu is left unchanged.
+ *
+ *
+ * @includeExample Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
+ * @includeExample Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public static function setSpellingMenuEntries(entries:Object):Boolean
+ {
+ if (entries.enable && entries.disable && entries.add && (entries.enable != "") && (entries.disable != "") && (entries.add != ""))
+ {
+ _contextMenuEntries = entries;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Get the spelling context menu entries.
+ *
+ * @return A flex Object
containing the spelling context menu entries. If you haven't customized the entries, you get the default associative array {enable:"Enable Spelling", disable:"Disable Spelling", add:"Add to dictionary"}
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public static function getSpellingMenuEntries():Object
+ {
+ return _contextMenuEntries;
+ }
+
+ /**
+ * The URL for the spelling config xml file. If you haven't specified it, the default URL is [applicationDirectory]/AdobeSpellingConfig.xml. Note that we don't validate the URL, if the file doesn't exist, you will get an error when calling enableSpelling() function.
+ *
+ * @example The following code customize the spellingConfigUrl before enabling spell checking.
+ *
+ * SpellUI.spellingConfigUrl = "./config/MySpellingConfig.xml";
+ * SpellUI.enableSpelling(textArea, "es_ES");
+ *
+ */
+ public static function get spellingConfigURL():String
+ {
+ return _spellingConfigUrl;
+ }
+
+ public static function set spellingConfigURL(url:String):void
+ {
+ if (url == null) throw new Error("URL can't be null");
+ _spellingConfigUrl = url;
+ }
+
+
+
+ /**
+ * Disable the spell checking feature for a UI component.
+ *
+ * @param comp A text editing Flex UI component.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public static function disableSpelling(comp:UIComponent):void{
+ if ( _UITable[comp] == undefined )
+ return;
+ var _ui:SpellUI = _UITable[comp];
+ if ( _ui != null) _ui.cleanUp();
+ var dictName:String = _cacheDictTable[comp];
+ var cleanUPDictionaryCount:int = 0;
+ for each ( var _dictName:String in _cacheDictTable ) {
+ if ( _dictName == dictName )
+ cleanUPDictionaryCount++;
+ }
+ if ( cleanUPDictionaryCount == 1 ) {
+ _cache[dictName] = undefined;
+ }
+ delete _UITable[comp];
+ delete _cacheDictTable[comp];
+
+ }
+
+ /**
+ @private
+ (This property is for Squiggly Developer use only.)
+ */
+ public static function get UITable():Dictionary {
+ return _UITable;
+ }
+
+ /**
+ @private
+ (This property is for Squiggly Developer use only.)
+ */
+ public function set spellingEnabled(value:Boolean):void {
+ _spellingEnabled = value;
+ }
+
+ /**
+ @private
+ (This property is for Squiggly Developer use only.)
+ */
+ public static function get parentComp():Dictionary {
+ return _parentTable;
+ }
+
+ private static function getComponentTextModel(comp:UIComponent):* {
+ var txt:TextField = null;
+ if ( (comp == null) || !( (comp is TextArea) || (comp is TextInput) || (comp is RichTextEditor) ) )
+ return null;
+ if ((comp as RichTextEditor) != null) {
+ txt = (comp as RichTextEditor).textArea.getTextField() as TextField;
+ }
+ else if ((comp as TextArea) != null){
+ txt = (comp as TextArea).getTextField() as TextField;
+ }
+ else if ((comp as TextInput) != null) {
+ txt = (comp as TextInput).getTextField() as TextField;
+ }
+ else {
+ // do nothing if it's not a valid text component
+ return null;
+ }
+ return txt;
+ }
+
+ /**
+ * Constructs a SpellUI object.
+ * @private
+ *
+ * @param textFiled A Flex UI component to include spell-check capability
+ * @param lang The language code used for spell checking
+ *
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function SpellUI(textModel:*, lang:String)
+ {
+ // TODO: Consider making this method invisible to user, only expose the static function.
+ if ( textModel is TextField ) {
+ isHaloComponent=true;
+ }else {
+ // do nothing, we only accept textField and TextFlow here....
+ return;
+ }
+ _actualParent = textModel;
+
+ //New Added below -- check if text field needs to be extracted from textModel
+ mTextField = textModel;
+
+ mTextField.addEventListener(FocusEvent.FOCUS_OUT, handleFocusOut);
+ mTextField.addEventListener(ScrollEvent.SCROLL, spellCheckScreen);
+ mTextField.parent.addEventListener(Event.RENDER, spellCheckScreen);
+ mTextField.parent.addEventListener(Event.CHANGE, handleChangeEvent);
+ _dictname = lang;
+ loadConfig();
+
+ }
+
+ private function spellCheckScreen(event:Event):void
+ {
+ doSpellingJob();
+ }
+
+ private function handleFocusOut(event:FocusEvent):void
+ {
+ _checkLastWord = true;
+ doSpellingJob();
+ }
+
+ private function handleChangeEvent( event:Event ) :void {
+ _checkLastWord = false;
+ doSpellingJob();
+ }
+
+ /*private function doSpelling():void
+ {
+ _checkLastWord = true;
+ doSpellingJob();
+ }*/
+
+ /**
+ @private
+ (This property is for Squiggly Developer use only.)
+ */
+ public function doSpellingJob():void
+ {
+ if (_spellingEnabled == false) return;
+ spellCheckRange(getValidFirstWordIndex(), getValidLastWordIndex());
+ }
+
+ private function spellCheckRange(start:uint, end:uint):void {
+ //hh.preSpellCheckRange(start, end);
+ hh.clearSquiggles();
+
+ //if (end <= start) return;
+ var firstLine:int = mTextField.getLineIndexOfChar(start);
+ var rect:Rectangle = mTextField.getCharBoundaries(start);
+ var counter:uint = start;
+ var numLines:Number = 0;
+
+ /* mTextField.getCharBoundaries returns null for blank lines and for end of line characters. Placing this workaround
+ to count line heights until a non-null bounding rectangle is found */
+
+ while (rect == null) {
+ if (counter+1 > end) {
+ rect = new Rectangle(0,0,0,0);
+ break;
+ }
+ if(mTextField.text.charCodeAt(counter)<0x0300 || mTextField.text.charCodeAt(counter)>0x036F)//not in diacritic combining range
+ {
+ numLines += mTextField.getLineMetrics(firstLine).height;
+ firstLine++;
+ }
+ counter++;
+ rect = mTextField.getCharBoundaries(counter);
+ }
+
+ var yoffset:Number = rect.y - numLines;
+ var pleft:uint = (mTextField.parent as UIComponent).getStyle("paddingLeft");
+ var ptop:uint = (mTextField.parent as UIComponent).getStyle("paddingTop");
+
+ var offsetPoint:Point = new Point(pleft, ptop-yoffset);
+
+ var tokenizer:TextTokenizer = new TextTokenizer(mTextField.text.substring(start,end));
+ //var seps:Vector. = new Vector.();
+ //seps.push(new int(34));
+ //tokenizer.ignoredSeperators = seps;
+ var tokens:Vector. = new Vector.();
+
+ hh.offsetPoint = offsetPoint;
+
+ for ( var token:Token = tokenizer.getFirstToken(); token != tokenizer.getLastToken(); token= tokenizer.getNextToken(token) ) {
+ var result:Boolean=_spellingservice.checkWord(mTextField.text.substring(token.first+start, token.last+start));
+ if (!result){
+ if (_checkLastWord || (token.last+start != mTextField.text.length))
+ //hh.highlightWord(token.first+start, token.last+start-1);
+ //tokens.push(new Token(token.first+start, token.last+start-1));
+ hh.drawSquiggleAt(new Token(token.first+start, token.last+start-1));
+ }
+
+ }
+ //hh.postSpellCheckRange(start, end);
+ //hh.offsetPoint = offsetPoint;
+ //hh.drawSquiggles(tokens);
+ }
+
+
+ private function getValidFirstWordIndex():int{
+ return mTextField.getLineOffset(mTextField.scrollV-1);
+ }
+
+ private function getValidLastWordIndex():int{
+ return mTextField.getLineOffset(mTextField.bottomScrollV-1)+mTextField.getLineLength(mTextField.bottomScrollV-1);
+ }
+
+ private function loadConfig():void{
+ _resource_locale = SpellingConfiguration.resourceTable.getResource(_dictname);
+
+ if ((_resource_locale != null) || (SpellUI._configXML != null))
+ loadConfigComplete(null);
+ else {
+ SpellUI._configXMLLoader.addEventListener(Event.COMPLETE, loadConfigComplete);
+
+ if (SpellUI._configXMLLoading == false)
+ {
+ SpellUI._configXMLLoader.load(new URLRequest(_spellingConfigUrl));
+ SpellUI._configXMLLoading = true;
+ }
+ }
+ }
+
+ private function loadConfigComplete(evt:Event):void{
+ if (_resource_locale == null) {
+ if (SpellUI._configXML == null)
+ SpellUI._configXML= new XML(evt.target.data);
+
+ SpellingConfiguration.resourceTable.setResource(_dictname,{rule:SpellUI._configXML.LanguageResource.(@languageCode==_dictname).@ruleFile,
+ dict:SpellUI._configXML.LanguageResource.(@languageCode==_dictname).@dictionaryFile});
+ }
+ //New Added
+ _spellingservice = new SpellingService(_dictname);
+ _spellingservice.addEventListener(Event.COMPLETE, loadDictComplete);
+ _spellingservice.init();
+ }
+
+
+
+
+ private function loadDictComplete(evt:Event):void
+ {
+
+
+ // Lazy loading the UD only when the main dict is loaded successfully
+ if ((SpellUI._cache["Squiggly_UD"] as UserDictionary) == null)
+ {
+ _sharedobj = SharedObject.getLocal("Squiggly_v03");
+ var vec:Vector. = new Vector.();
+ if (_sharedobj.data.ud) {
+ for each (var w:String in _sharedobj.data.ud)
+ vec.push(w);
+ }
+ _userdict = new UserDictionary(vec);
+
+ SpellUI._cache["Squiggly_SO"] = _sharedobj;
+ SpellUI._cache["Squiggly_UD"] = _userdict;
+ }
+ else
+ {
+ _sharedobj = SpellUI._cache["Squiggly_SO"];
+ _userdict = SpellUI._cache["Squiggly_UD"];
+ }
+ _spellingservice.addUserDictionary(_userdict);
+ //Adding default behaviour to accomodate ignoring of abbreviations bug#2756840
+ _spellingservice.ignoreWordWithAllUpperCase=true;
+
+
+ // Add the context menu, this might be not successful
+ scm = null;
+ try {
+ addContextMenu(null);
+ }
+ catch (err:Error)
+ {
+ // TODO: error handling here
+ }
+ _actualParent.addEventListener(Event.ADDED_TO_STAGE, addContextMenu);
+ }
+
+
+ private function addContextMenu(event:Event):void
+ {
+ if ( scm != null ) return;
+ if ( isHaloComponent ) {
+ hh= new HaloHighlighter( _actualParent);
+ hw= new HaloWordProcessor( _actualParent);
+ }else {
+ trace("error now, later will be true");
+ }
+
+ scm = new SpellingContextMenu(hh, hw, _spellingservice, _actualParent, _actualParent.contextMenu);
+ scm.setIgnoreWordCallback( addWordToUserDictionary );
+
+ // Halo need this
+ if (_actualParent.contextMenu == null)
+ {
+ _actualParent.contextMenu = scm.contextMenu;
+ }
+
+ //hh.spellingEnabled=true;
+ _spellingEnabled = true;
+ try {
+ doSpellingJob();
+ }
+ catch (err:Error)
+ {
+ // If it fails here, it should later triggered by the render event, so no need to do anything
+ }
+
+
+ }
+
+ private function addWordToUserDictionary(word:String):void
+ {
+ _userdict.addWord(word);
+
+ // TODO: serialization here might affect ther performance
+ _sharedobj.data.ud = _userdict.wordList;
+
+ }
+ /**
+ * @private
+ */
+ private function cleanUp():void {
+ hh.clearSquiggles();
+ scm.cleanUp();
+ _actualParent.removeEventListener(Event.ADDED_TO_STAGE, addContextMenu);
+
+ mTextField.removeEventListener(ScrollEvent.SCROLL, spellCheckScreen);
+ mTextField.parent.removeEventListener(Event.RENDER, spellCheckScreen);
+ mTextField.parent.removeEventListener(Event.CHANGE, handleChangeEvent);
+ mTextField.removeEventListener(FocusEvent.FOCUS_OUT, handleFocusOut);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
new file mode 100644
index 0000000..d84f325
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
@@ -0,0 +1,243 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling
+{
+ import com.adobe.linguistics.spelling.framework.SpellingService;
+ import com.adobe.linguistics.utils.Token;
+ import com.adobe.linguistics.utils.TextTokenizer;
+
+ import flash.events.ContextMenuEvent;
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+
+ import flash.ui.ContextMenu;
+ import flash.ui.ContextMenuItem;
+
+ import flash.text.TextField;
+ import mx.core.UIComponent;
+
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import com.adobe.linguistics.spelling.ui.IHighlighter;
+ import com.adobe.linguistics.spelling.ui.IWordProcessor;
+
+ public class SpellingContextMenu
+ {
+ private var disableMenuItem:ContextMenuItem = new ContextMenuItem("Disable spell checking",true);
+ private var enableMenuItem:ContextMenuItem = new ContextMenuItem("Enable spell checking");
+ private var controlMenuItemList:Array = new Array();
+ private var suggestionMenuItemList:Array = new Array();
+ private var _spellingEnabled:Boolean;
+ private var _contextMenu:ContextMenu;
+ private var mTextHighlighter:IHighlighter;
+ private var mWordProcessor:IWordProcessor;
+ private var mSpellEngine:SpellingService;
+ private var mParentTextField:TextField;
+ private var _ignoreWordFunctionProcessor:Function;
+ private var _misspelledToken:Token;
+ private var _misspelled:String;
+ public function SpellingContextMenu(textHighlighter:IHighlighter, wordProcessor:IWordProcessor, engine:SpellingService, actualParent:*, contextMenu:ContextMenu=null)
+ {
+
+ if ( textHighlighter == null || wordProcessor == null || engine == null) throw new Error("illegal argument.");
+ mTextHighlighter = textHighlighter;
+ mWordProcessor = wordProcessor;
+ mSpellEngine = engine;
+ mParentTextField = actualParent;
+ if (contextMenu != null) {
+ _contextMenu =contextMenu;
+ }else {
+ _contextMenu = new ContextMenu();
+ }
+ enableMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleEnableSpellCheck);
+ disableMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleDisableSpellCheck);
+ controlMenuItemList.push(enableMenuItem);
+ controlMenuItemList.push(disableMenuItem);
+
+ _contextMenu.customItems.push(disableMenuItem);
+ _contextMenu.customItems.push(enableMenuItem);
+ spellingEnabled = true; //default value
+ //spellingEnabled= mTextHighlighter.spellingEnabled;
+ _contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, handleContextMenuSelect);
+ _ignoreWordFunctionProcessor=null;
+ }
+
+ public function cleanUp():void
+ {
+ mTextHighlighter=null;
+ mWordProcessor=null;
+ spellingEnabled = false;
+ _ignoreWordFunctionProcessor=null;
+
+ _contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, handleContextMenuSelect);
+
+ var removedNum:int = 0;
+ var count:uint = _contextMenu.customItems.length;
+ for (var j:uint=count; j>0; j--) {
+ if ( isWordItem(_contextMenu.customItems[j-1]) || isControlItem(_contextMenu.customItems[j-1]) ) {
+ _contextMenu.customItems.splice(j-1,1);
+ removedNum++
+ }
+ }
+ if ( removedNum != suggestionMenuItemList.length + controlMenuItemList.length ) {
+ trace("internal error");
+ }
+
+ suggestionMenuItemList = null;
+ controlMenuItemList = null;
+ }
+
+ public function get contextMenu():ContextMenu {
+ return this._contextMenu;
+ }
+
+ private function handleContextMenuSelect(event:ContextMenuEvent):void
+ {
+ /* Clear the context menu */
+ //spellingEnabled= mTextHighlighter.spellingEnabled;
+ //SpellUI.doSpelling1();
+ var removedNum:int = 0;
+ var count:uint = _contextMenu.customItems.length;
+ for (var j:uint=count; j>0; j--) {
+ if ( isWordItem(_contextMenu.customItems[j-1]) ) {
+ _contextMenu.customItems.splice(j-1,1);
+ removedNum++
+ }
+ }
+ if ( removedNum != suggestionMenuItemList.length ) {
+ trace("internal error");
+ }
+
+
+ suggestionMenuItemList = new Array();
+
+ // localized entries
+ var entries:Object = SpellUI.getSpellingMenuEntries();
+ disableMenuItem.caption = entries.disable;
+ enableMenuItem.caption = entries.enable;
+
+ if (spellingEnabled == true) {
+ _misspelledToken = mWordProcessor.getWordAtPoint(mParentTextField.mouseX, mParentTextField.mouseY);
+ if (_misspelledToken==null) return;
+ _misspelled = mParentTextField.text.substring(_misspelledToken.first, _misspelledToken.last);
+ if ((_misspelled==null) || (_misspelled == "")) return;
+
+ if (mSpellEngine.checkWord(_misspelled)==true) return;
+
+ var suseAddToItem:ContextMenuItem = new ContextMenuItem(entries.add);
+ suseAddToItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleAddToItemSelect);
+ suggestionMenuItemList.push(suseAddToItem);
+ _contextMenu.customItems.splice(0,0,suseAddToItem);
+ //var result:Array = mWordProcessor.getSuggestionsAtPoint();
+ var resultVector:Vector. = mSpellEngine.getSuggestions(_misspelled);
+ var result:Array = new Array();
+ if (resultVector) {
+ for each (var w:String in resultVector)
+ result.push(w);
+ }
+ if (result!=null) {
+ for (var i:int=result.length-1;i>=0;i-- ) {
+ var suseMenuItem:ContextMenuItem = new ContextMenuItem(result[i]);
+ suseMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleSuseItemSelect);
+ suggestionMenuItemList.push(suseMenuItem);
+ //_contextMenu.customItems.push(suseMenuItem);
+ _contextMenu.customItems.splice(0,0,suseMenuItem);
+ }
+ }
+ }
+
+
+
+ }
+
+ public function setIgnoreWordCallback(func:Function ) :void {
+ if ( func != null )
+ _ignoreWordFunctionProcessor = func;
+ }
+
+ private function handleAddToItemSelect(event:ContextMenuEvent):void
+ {
+ if ( _ignoreWordFunctionProcessor == null ) return;
+
+ /*
+ var menuEntry:String = (event.currentTarget as ContextMenuItem).caption;
+ var start:uint = 5;
+ var end:uint = menuEntry.length - 15;
+ var word:String = menuEntry.substring(start, end);
+ */
+ _ignoreWordFunctionProcessor(_misspelled);
+ //SpellUI.UITable[SpellUI.parentComp[mParentTextField]].doSpellingJob();//Reason bug#2713972 Fix Added Under
+ //now implicitly calling dospelling on all text areas
+ for each (var tempUIComponent:SpellUI in SpellUI.UITable)
+ {
+ tempUIComponent.doSpellingJob();
+ }
+ }
+
+ private function isWordItem(item:ContextMenuItem):Boolean {
+
+ for ( var i:int=0; iThis class facilitates drawing of squiggly lines below words for TextField class. TextField class is used to create display objects for text display
+ * and input for Halo TextArea and TextInput components. HaloHighlighter could therefore be used for drawing squiggly lines in these Halo components.
+ *
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+
+ public class HaloHighlighter implements IHighlighter
+ {
+ private var mTextField:TextField;
+ private var mHighlighter:SpellingHighlighter;
+ /*
+ * offset point:
+ */
+ private var _offsetPoint:Point;
+
+ /**
+ * The constructor for HaloHighlighter.
+ * @param textField TextField
in which to enable highlighting.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function HaloHighlighter( textField:TextField )
+ {
+ if (textField == null ) throw new Error("illegal argument.");
+ mTextField = textField;
+ mHighlighter = null;
+ this._offsetPoint = new Point(0,0);
+ }
+ /**
+ * Draw squiggly lines below a given token.
+ * @param token Token
information of the word to be highlighted.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function drawSquiggleAt(token:Token):void
+ {
+ squiggleWord(token);
+ }
+
+ /**
+ * Clear all squiggly lines in the TextField.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function clearSquiggles():void
+ {
+ if (mHighlighter) {
+ mTextField.parent.removeChild(mHighlighter);
+ mHighlighter=null;
+ }
+
+ }
+
+ /**
+ * Set offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function set offsetPoint(op:Point):void{
+ _offsetPoint = op;
+ }
+
+ /**
+ * Get offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function get offsetPoint():Point{
+ return _offsetPoint;
+ }
+
+
+ private function squiggleWord(token:Token):void {
+
+ if (!mHighlighter) {
+ mHighlighter= new SpellingHighlighter( mTextField as IUITextField);
+ mTextField.parent.addChild(mHighlighter);
+ }
+
+ mHighlighter.drawSquigglyLine(token.first, token.last);
+
+
+ //mTextField.parent.addChild(mHighlighter);
+ mHighlighter.move(_offsetPoint.x, _offsetPoint.y);
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
new file mode 100644
index 0000000..9c05b3b
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
@@ -0,0 +1,112 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import com.adobe.linguistics.utils.ITokenizer;
+ import com.adobe.linguistics.utils.TextTokenizer;
+ import com.adobe.linguistics.utils.Token;
+
+ import flash.text.TextField;
+ import flash.text.TextFormat;
+
+ import mx.controls.TextArea;
+ import mx.controls.TextInput;
+ import com.adobe.linguistics.spelling.ui.IWordProcessor;
+
+
+ public class HaloWordProcessor implements IWordProcessor
+ {
+ private var mTextField:TextField;
+
+ public function HaloWordProcessor(textField:TextField)
+ {
+ if (textField == null ) throw new Error("illegal argument.");
+ mTextField = textField;
+ }
+
+
+ public function replaceText(token:Token, replacement:String):void {
+ var startIndex:int = token.first;
+ var endIndex:int = token.last;
+
+ if ( replacement == null ) return;
+
+ if (mTextField.text.length= mTextField.text.length) return null;
+
+ var tmpToken:Token = new Token(index,index);
+ var tokenizer:ITokenizer;
+ if ( externalTokenizer == null ) {
+ tokenizer = new TextTokenizer(mTextField.text);
+ }else {
+ tokenizer = externalTokenizer;
+ }
+
+ var result:Token = new Token(0,0);
+
+ var preToken:Token = tokenizer.getPreviousToken(tmpToken);
+ var nextToken:Token = tokenizer.getNextToken(tmpToken);
+ if ( preToken.last == nextToken.first ) {
+ result.first = preToken.first;
+ result.last = nextToken.last;
+ return result;
+ }else {
+ return null;
+ }
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
new file mode 100644
index 0000000..3b5a309
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
@@ -0,0 +1,67 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import com.adobe.linguistics.utils.Token;
+ import __AS3__.vec.Vector;
+ import flash.geom.Point;
+
+ /**
+ * The IHighlighter
Interface.
+ * This interface defines default methods which will be used for highlighting text in UI components.
+ *
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+
+ public interface IHighlighter
+ {
+ /**
+ * Draw squiggly lines below a given token.
+ * @param token Token
information of the word to be highlighted.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ function drawSquiggleAt(token:Token):void;
+ /**
+ * Clear all squiggly lines in the UI.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ function clearSquiggles():void;
+ /**
+ * Set offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ function set offsetPoint(op:Point):void;
+ /**
+ * Get offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ function get offsetPoint():Point;
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
new file mode 100644
index 0000000..8196691
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
@@ -0,0 +1,30 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import com.adobe.linguistics.utils.ITokenizer;
+ import com.adobe.linguistics.utils.Token;
+
+ public interface IWordProcessor
+ {
+ function getWordAtPoint(x:uint, y:uint, externalTokenizer:ITokenizer=null):Token;
+ function replaceText(token:Token, replacement:String):void;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
new file mode 100644
index 0000000..ffe9653
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
@@ -0,0 +1,229 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import com.adobe.linguistics.utils.Token;
+ import com.adobe.linguistics.utils.TextTokenizer;
+ import flash.geom.Point;
+
+ import flash.display.Shape;
+ import flash.geom.Rectangle;
+ import flash.text.engine.TextLine;
+
+ import flashx.textLayout.compose.TextFlowLine;
+ import flashx.textLayout.edit.SelectionManager;
+ import flashx.textLayout.elements.TextFlow;
+ import flashx.textLayout.tlf_internal;
+
+ import spark.components.RichEditableText;
+ import com.adobe.linguistics.spelling.ui.IHighlighter;
+
+ use namespace tlf_internal;
+
+ /**
+ * This class facilitates drawing of squiggly lines below words for RichEditableText class. RichEditableText is a low-level UIComponent for displaying,
+ * scrolling, selecting, and editing richly-formatted text. This class is used in the skins of the Spark versions of TextInput and TextArea.
+ * SparkHighlighter could therefore be used for drawing squiggly lines in these Spark components.
+ *
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public class SparkHighlighter implements IHighlighter
+ {
+
+ private var mTextField:RichEditableText;
+ private var mHighlighter:Shape;
+ /*
+ * offset point:
+ */
+ private var _offsetPoint:Point;
+
+ /**
+ * The constructor for SparkHighlighter.
+ * @param richEditableText RichEditableText
in which to enable highlighting.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function SparkHighlighter( richEditableText:RichEditableText )
+ {
+ if (richEditableText == null ) throw new Error("illegal argument.");
+ mTextField = richEditableText;
+ mHighlighter = null;
+ this._offsetPoint = new Point(0,0);
+ }
+
+ /**
+ * Draw squiggly lines below a given token.
+ * @param token Token
information of the word to be highlighted.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function drawSquiggleAt(token:Token):void
+ {
+ squiggleWord(token);
+ }
+
+ /**
+ * Clear all squiggly lines in the component.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function clearSquiggles():void
+ {
+ if (mHighlighter) {
+ mTextField.removeChild(mHighlighter);
+ mHighlighter=null;
+ }
+ }
+
+ /**
+ * Set offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function set offsetPoint(op:Point):void{
+ _offsetPoint = op;
+ }
+
+ /**
+ * Get offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function get offsetPoint():Point{
+ return _offsetPoint;
+ }
+
+
+
+ // TODO: refactor this code to share with halo components, and support words that cross lines
+ private function squiggleWord(token:Token):void {
+
+ var ta:RichEditableText = mTextField;
+ if (!ta) return;
+
+ if (!mHighlighter) {
+ mHighlighter= new Shape();
+ mHighlighter.graphics.clear();
+ mTextField.addChild(mHighlighter);
+ }
+
+ drawSquigglyLineForRange(token.first, token.last);
+
+ // Just adjust the left padding, top padding is not an issue
+ //var pleft:uint = mTextField.getStyle("paddingLeft");
+ //mHighlighter.x += pleft;
+ }
+
+ // Draw squiggly line
+ private function drawSquigglyLineForRange(start:Number, end:Number):void
+ {
+ // draw squiggly line
+ var tf:TextFlow = mTextField.textFlow;
+ var tflFirst:TextFlowLine = tf.flowComposer.findLineAtPosition(start);
+ var tflLast:TextFlowLine = tf.flowComposer.findLineAtPosition(end);
+ var tflIndexFirst:int = tf.flowComposer.findLineIndexAtPosition(start);
+ var tflIndexLast:int = tf.flowComposer.findLineIndexAtPosition(end);
+
+ // Pointer
+ var tflIndex:int = tflIndexFirst;
+ var tfl:TextFlowLine = tflFirst;
+
+ if (tflIndexFirst == tflIndexLast) {
+ // Draw one line
+ drawSquigglyLineAtIndex(tflIndexFirst, start - tflFirst.absoluteStart, end - tflFirst.absoluteStart);
+ } else {
+ // Multiple lines (very long word)
+ drawSquigglyLineAtIndex(tflIndexFirst, start - tflFirst.absoluteStart);
+
+ tflIndex++;
+ while (tflIndex != tflIndexLast) {
+ drawSquigglyLineAtIndex(tflIndex);
+ tflIndex++;
+ }
+
+ drawSquigglyLineAtIndex(tflIndexLast, 0, end - tflLast.absoluteStart);
+ }
+ }
+
+ // Draw a squiggly line at specific line for specific index range
+ private function drawSquigglyLineAtIndex(lineIndex:Number, startIndex:Number=0, endIndex:Number=0x7FFFFFFF):void
+ {
+ var tf:TextFlow = mTextField.textFlow;
+ var tfl:TextFlowLine = tf.flowComposer.getLineAt(lineIndex);
+ var rectLine:Rectangle = tfl.getBounds();
+ if (endIndex == 0x7FFFFFFF) {
+ drawSquigglyLineAtPoint(rectLine.left, rectLine.bottom, rectLine.right - rectLine.left);
+ }
+ else {
+ // Force to have a valid TextLine
+ var tl:TextLine = tfl.getTextLine(true);
+ if(tl==null) return;
+ var atomStartIndex:int= tl.getAtomIndexAtCharIndex(startIndex+ tl.textBlockBeginIndex);//fix for diacritic characters bug#2854971(adding textBlockBeginIndex since getAtomIndexAtCharIndex is relative to beginning of block)
+ var atomEndIndex:int= tl.getAtomIndexAtCharIndex(endIndex+tl.textBlockBeginIndex);//fix for diacritic characters bug#2854971
+ // TODO: atom index and char index is not matching for some chars, use try/catch to avoid crash
+ try {
+ var rectFirst:Rectangle = tl.getAtomBounds(atomStartIndex);
+ var rectLast:Rectangle = tl.getAtomBounds(atomEndIndex);
+ drawSquigglyLineAtPoint(rectFirst.left + tfl.x, rectLine.bottom, rectLast.right - rectFirst.left);
+ } catch (err:Error)
+ {
+ trace(err);
+ }
+ }
+
+ }
+ // Draw a squiggly from point x,y with given width, the line is drew in mHighlighter
+ private function drawSquigglyLineAtPoint(x:Number, y:Number, width:Number):void
+ {
+ mHighlighter.graphics.lineStyle(1, 0xfa0707, .65);
+ mHighlighter.graphics.moveTo(x, y);
+ var upDirection:Boolean = false;
+ var offset:uint = 0;
+ var stepLength:uint = 2;
+ for ( var i:uint = 1; offset <= width; i++) {
+ offset = offset + stepLength;
+ if ( upDirection )
+ mHighlighter.graphics.lineTo(x+offset,y);
+ else
+ mHighlighter.graphics.lineTo(x+offset,y+stepLength);
+ upDirection = !upDirection;
+ }
+ }
+
+ private function getValidFirstWordIndex():int{
+ var index:int = SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, mTextField, 0 + mTextField.horizontalScrollPosition, 0 + mTextField.verticalScrollPosition);
+ return index;
+
+
+ }
+
+ private function getValidLastWordIndex():int{
+ var index:int = SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, mTextField, mTextField.width+mTextField.horizontalScrollPosition, mTextField.height+mTextField.verticalScrollPosition);
+ return index;
+
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
new file mode 100644
index 0000000..3ae7a88
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
@@ -0,0 +1,133 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import com.adobe.linguistics.utils.ITokenizer;
+ import com.adobe.linguistics.utils.TextTokenizer;
+ import com.adobe.linguistics.utils.Token;
+
+ import flashx.textLayout.edit.SelectionManager;
+ import flashx.textLayout.tlf_internal;
+
+ import spark.components.RichEditableText;
+ import com.adobe.linguistics.spelling.ui.IWordProcessor;
+
+ use namespace tlf_internal;
+
+ public class SparkWordProcessor implements IWordProcessor
+ {
+ private var mTextField:RichEditableText;
+
+ public function SparkWordProcessor(textField:RichEditableText)
+ {
+ if (textField == null ) throw new Error("illegal argument.");
+ mTextField = textField;
+ }
+
+
+ public function replaceText(token:Token, replacement:String):void {
+ var startIndex:int = token.first;
+ var endIndex:int = token.last;
+
+ var ta:RichEditableText = mTextField;
+ var end:int = getValidLastWordIndex();
+
+ if ( replacement == null ) return;
+
+ if (mTextField.text.length= ta.text.length) return null;
+
+ var tmpToken:Token = new Token(index,index);
+ var tokenizer:ITokenizer;
+ if ( externalTokenizer == null ) {
+ tokenizer = new TextTokenizer(mTextField.text);
+ }else {
+ tokenizer = externalTokenizer;
+ }
+
+ var result:Token = new Token(0,0);
+ var preToken:Token = tokenizer.getPreviousToken(tmpToken);
+ var nextToken:Token = tokenizer.getNextToken(tmpToken);
+ if ( preToken.last == nextToken.first ) {
+ result.first = preToken.first;
+ result.last = nextToken.last;
+ return result;
+ }else {
+ return null;
+ }
+
+ }
+
+ // TODO: workaround for unexpected jump when word replaced, to be refactored for code sharing
+ private function getValidLastWordIndex():int{
+ var index:int = SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, mTextField, mTextField.width+mTextField.horizontalScrollPosition, mTextField.height+mTextField.verticalScrollPosition);
+ return index;
+ }
+
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
new file mode 100644
index 0000000..27cd2fb
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
@@ -0,0 +1,196 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import flash.display.Shape;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.text.TextLineMetrics;
+
+ import mx.core.IUITextField;
+ import mx.flash.UIMovieClip;
+
+
+ public class SpellingHighlighter extends UIMovieClip
+ {
+ /*
+ * offset point:
+ */
+ private var _offsetPoint:Point;
+
+ /*
+ * Target TextField.
+ */
+ private var _textField:IUITextField;
+ private static var InvalidIndexValue:int = -2;
+ public function SpellingHighlighter(textField:IUITextField) {
+ super();
+ this._textField = textField;
+ this._offsetPoint = new Point(0,0);
+ }
+
+ public function drawSquigglyLine(firstCharIndex:int, lastCharIndex:int ):void {
+ var validFirstCharIndex:int = getValidFirstCharIndex(firstCharIndex);
+ var validLastCharIndex:int = getValidLastCharIndex(lastCharIndex);
+ if ( validFirstCharIndex == InvalidIndexValue || validLastCharIndex == InvalidIndexValue ){
+ return;
+ }
+ /* draw squiggly line here. */
+ if ( validFirstCharIndex <= validLastCharIndex ) {
+ var firstLine:int = _textField.getLineIndexOfChar(validFirstCharIndex);
+ var lastLine:int = _textField.getLineIndexOfChar(validLastCharIndex);
+ //only one line case.
+ if(lastLine==firstLine)
+ {
+ drawSingleSquigglyLine(validFirstCharIndex, validLastCharIndex);
+ return;
+ }
+ //more than one line.
+ //first line
+ drawSingleSquigglyLine(validFirstCharIndex, _textField.getLineOffset(firstLine)+_textField.getLineLength(firstLine)-1);
+ //middle....
+ for(var i:int=firstLine+1;i(_textField.getLineOffset(line)+_textField.getLineLength(line)-1)||(firstCharIndex+1)>lastCharIndex) return;// go till the last character
+ firstCharIndex++;
+ rect1= _textField.getCharBoundaries(firstCharIndex);
+ }
+
+ while(rect2==null){//this case appears for diacritic characters made using Decomposed chars
+ line=_textField.getLineIndexOfChar(lastCharIndex);
+ if( lastCharIndex-1 < (_textField.getLineOffset(line))||firstCharIndex>(lastCharIndex-1) ) return; //go till the first character
+ lastCharIndex--;// check for the previos character
+ rect2= _textField.getCharBoundaries(lastCharIndex);
+ }
+
+
+ var x:Number = rect1.x+_offsetPoint.x - _textField.scrollH;
+ var y:Number = rect1.y + rect1.height + 2;
+ var width:Number = rect2.x+rect2.width-rect1.x;
+
+ // Avoid drawing outside the textField
+ if (x<0)
+ {
+ if (x+width > 0) {
+ width += x;
+ x = 0;
+ }
+ else
+ return;
+ }
+ if (x+width > _textField.width)
+ {
+ if (x < _textField.width) {
+ width = textField.width - x;
+ }
+ else
+ return;
+ }
+
+ // The rectangle that bound the string you want
+ // actual work here.
+ var myShape:Shape = new Shape();
+ myShape.graphics.clear();
+ //myShape.graphics.beginFill(0x0099CC, .35);
+ myShape.graphics.lineStyle(1, 0xfa0707, .65);
+ //myShape.graphics.moveTo(0,0);
+ myShape.graphics.moveTo(x, y);
+ var upDirection:Boolean = false;
+ var offset:uint = 0;
+ var stepLength:uint = 2;
+ for ( var i:uint = 1; offset <= width; i++) {
+ offset = offset + stepLength;
+ if ( upDirection )
+ myShape.graphics.lineTo(x+offset,y);
+ else
+ myShape.graphics.lineTo(x+offset,y+stepLength);
+ upDirection = !upDirection;
+ }
+ //myShape.graphics.endFill();
+ this.addChild(myShape);
+ }
+ }
+
+ private function getValidFirstCharIndex(firstCharIndex:int):int{
+ if(firstCharIndex<0 || firstCharIndex>_textField.text.length-1)
+ {
+ return InvalidIndexValue;
+ }
+ var firstLine:Number = _textField.getLineIndexOfChar(firstCharIndex);
+
+ if(firstLine<_textField.scrollV-1)
+ {
+ firstLine = _textField.scrollV-1;
+ return _textField.getLineOffset(firstLine);
+ }
+ return firstCharIndex;
+ }
+
+ private function getValidLastCharIndex(lastCharIndex:int):int{
+ if(lastCharIndex<0 || lastCharIndex>_textField.text.length-1)
+ {
+ return InvalidIndexValue;
+ }
+ var lastLine:Number = _textField.getLineIndexOfChar(lastCharIndex);
+ if(lastLine>_textField.bottomScrollV-1)
+ {
+ lastLine = _textField.bottomScrollV-1;
+ return _textField.getLineOffset(lastLine)+_textField.getLineLength(lastLine)-1;
+ }
+ return lastCharIndex;
+ }
+
+ public function set textField(tf:IUITextField):void{
+ _textField = tf;
+ }
+
+ public function get textField():IUITextField{
+ return _textField;
+ }
+
+ public function set offsetPoint(op:Point):void{
+ _offsetPoint = op;
+ }
+
+ public function get offsetPoint():Point{
+ return _offsetPoint;
+ }
+
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
new file mode 100644
index 0000000..92b7c71
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
@@ -0,0 +1,252 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import com.adobe.linguistics.utils.TextTokenizer;
+ import com.adobe.linguistics.utils.Token;
+
+ import flash.display.Graphics;
+ import flash.display.Shape;
+ import flash.display.Sprite;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.text.engine.TextLine;
+ import flash.utils.Dictionary;
+
+ import flashx.textLayout.compose.TextFlowLine;
+ import flashx.textLayout.container.ContainerController;
+ import flashx.textLayout.edit.SelectionManager;
+ import flashx.textLayout.elements.TextFlow;
+ import flashx.textLayout.tlf_internal;
+ import com.adobe.linguistics.spelling.ui.IHighlighter;
+
+
+ use namespace tlf_internal;
+
+ /**
+ * This class facilitates drawing of squiggly lines below words for TLF TextFlow class.
+ * The TextFlow class is responsible for managing all
+ * the text content of a story. In TextLayout, text is stored in a hierarchical tree of elements. TextFlow is the root object of the element tree.
+ * All elements on the tree derive from the base class, FlowElement.
+ * TLFHighlighter could be used for drawing squiggly lines in any of the custom visual components(probably based on Sprite
) which make use
+ * of TextFlow to display text.
+ *
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public class TLFHighlighter implements IHighlighter
+ {
+
+ private var mTextFlow:TextFlow;
+ private var mHighlighter:Dictionary;
+
+ //private var mHighlighter:Shape;
+ private var ccindex:int;
+ private var cc:ContainerController;
+ /*
+ * offset point:
+ */
+ private var _offsetPoint:Point;
+
+ /**
+ * The constructor for TLFHighlighter.
+ * @param textFlow TextFlow
in which to enable highlighting.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function TLFHighlighter( textFlow:TextFlow )
+ {
+ if (textFlow == null ) throw new Error("illegal argument.");
+ mTextFlow = textFlow;
+ //mHighlighter = null;
+ mHighlighter = new Dictionary(true);
+ this._offsetPoint = new Point(0,0);
+ }
+ /**
+ * Draw squiggly lines below a given token.
+ * @param token Token
information of the word to be highlighted.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function drawSquiggleAt(token:Token):void
+ {
+ squiggleWord(token);
+ }
+ /**
+ * Clear all squiggly lines in the component.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function clearSquiggles():void
+ {
+
+ for (var idx:int = 0; idx < mTextFlow.flowComposer.numControllers; idx++)
+ {
+ var cctmp:ContainerController = mTextFlow.flowComposer.getControllerAt(idx);
+ if (!cctmp) return;
+ if (mHighlighter[cctmp.container] != null) {
+
+ //ToDO: This assumes single container for whole of mTextFlow. Need to implement for multiple container case.
+ cctmp.container.removeChild((mHighlighter[cctmp.container] as Shape));
+
+ mHighlighter[cctmp.container] = null;
+ }
+ }
+ }
+
+ /**
+ * Set offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function set offsetPoint(op:Point):void{
+ _offsetPoint = op;
+ }
+ /**
+ * Get offset point information for scrollable controls. This is used by the highlighter to move
+ * the squiggly lines as the text scrolls inside the control.
+ * @param op offset information as a Point
instance.
+ * @playerversion Flash 10
+ * @langversion 3.0
+ */
+ public function get offsetPoint():Point{
+ return _offsetPoint;
+ }
+
+
+
+ // TODO: refactor this code to share with halo components, and support words that cross lines
+ private function squiggleWord(token:Token):void {
+ var ta:TextFlow = mTextFlow;
+
+ if (!ta) return;
+ ccindex = ta.flowComposer.findControllerIndexAtPosition(token.first);
+
+ cc = ta.flowComposer.getControllerAt(ccindex);
+ if (!cc) return;
+ if (mHighlighter[cc.container] == null ) {
+ mHighlighter[cc.container]= new Shape();
+ (mHighlighter[cc.container] as Shape).graphics.clear();
+ //ccindex = ta.flowComposer.findControllerIndexAtPosition(token.first);
+
+ //var cc:ContainerController = ta.flowComposer.getControllerAt(ccindex);
+ //ToDO: This assumes single container for whole of mTextFlow. Need to implement for multiple container case.
+ cc.container.addChild((mHighlighter[cc.container] as Shape));
+ }
+
+ drawSquigglyLineForRange(token.first, token.last);
+
+ // Just adjust the left padding, top padding is not an issue
+ //var pleft:uint = mTextFlow.getStyle("paddingLeft");
+ //mHighlighter.x += pleft;
+ }
+
+ // Draw squiggly line
+ private function drawSquigglyLineForRange(start:Number, end:Number):void
+ {
+ // draw squiggly line
+ var tf:TextFlow = mTextFlow;
+ var tflFirst:TextFlowLine = tf.flowComposer.findLineAtPosition(start);
+ var tflLast:TextFlowLine = tf.flowComposer.findLineAtPosition(end);
+ var tflIndexFirst:int = tf.flowComposer.findLineIndexAtPosition(start);
+ var tflIndexLast:int = tf.flowComposer.findLineIndexAtPosition(end);
+
+ // Pointer
+ var tflIndex:int = tflIndexFirst;
+ var tfl:TextFlowLine = tflFirst;
+
+ if (tflIndexFirst == tflIndexLast) {
+ // Draw one line
+ drawSquigglyLineAtIndex(tflIndexFirst, start - tflFirst.absoluteStart, end - tflFirst.absoluteStart);
+ } else {
+ // Multiple lines (very long word)
+ drawSquigglyLineAtIndex(tflIndexFirst, start - tflFirst.absoluteStart);
+
+ tflIndex++;
+ while (tflIndex != tflIndexLast) {
+ drawSquigglyLineAtIndex(tflIndex);
+ tflIndex++;
+ }
+
+ drawSquigglyLineAtIndex(tflIndexLast, 0, end - tflLast.absoluteStart);
+ }
+ }
+
+ // Draw a squiggly line at specific line for specific index range
+ private function drawSquigglyLineAtIndex(lineIndex:Number, startIndex:Number=0, endIndex:Number=0x7FFFFFFF):void
+ {
+ var tf:TextFlow = mTextFlow;
+ var tfl:TextFlowLine = tf.flowComposer.getLineAt(lineIndex);
+ var rectLine:Rectangle = tfl.getBounds();
+ if (endIndex == 0x7FFFFFFF) {
+ drawSquigglyLineAtPoint(rectLine.left, rectLine.bottom, rectLine.right - rectLine.left, lineIndex);
+ }
+ else {
+ // Force to have a valid TextLine
+ var tl:TextLine = tfl.getTextLine(true);
+ if(tl==null)return;
+ var atomStartIndex:int= tl.getAtomIndexAtCharIndex(startIndex+ tl.textBlockBeginIndex);//fix for diacritic characters bug#2854971
+ var atomEndIndex:int= tl.getAtomIndexAtCharIndex(endIndex+ tl.textBlockBeginIndex);//fix for diacritic characters bug#2854971
+ // TODO: atom index and char index is not matching for some chars, use try/catch to avoid crash
+ try {
+ var rectFirst:Rectangle = tl.getAtomBounds(atomStartIndex);
+ var rectLast:Rectangle = tl.getAtomBounds(atomEndIndex);
+ drawSquigglyLineAtPoint(rectFirst.left + tfl.x, rectLine.bottom, rectLast.right - rectFirst.left, lineIndex);
+ } catch (err:Error)
+ {
+ trace(err);
+ }
+ }
+
+ }
+ // Draw a squiggly from point x,y with given width, the line is drawn in mHighlighter
+ private function drawSquigglyLineAtPoint(x:Number, y:Number, width:Number, lineIndex:Number):void
+ {
+ var tf:TextFlow = mTextFlow;
+ var tfl:TextFlowLine = tf.flowComposer.getLineAt(lineIndex);
+ var tl:TextLine = tfl.getTextLine(true);
+
+ (mHighlighter[cc.container] as Shape).graphics.lineStyle(1, 0xfa0707, .65);
+ (mHighlighter[cc.container] as Shape).graphics.moveTo(x, y);
+ var upDirection:Boolean = false;
+ var offset:uint = 0;
+ var stepLength:uint = 2;
+ for ( var i:uint = 1; offset <= width; i++) {
+ offset = offset + stepLength;
+ if ( upDirection )
+ (mHighlighter[cc.container] as Shape).graphics.lineTo(x+offset,y);
+ else
+ (mHighlighter[cc.container] as Shape).graphics.lineTo(x+offset,y+stepLength);
+ upDirection = !upDirection;
+ }
+
+ //tl.addChild(mHighlighter);
+
+ //tf.flowComposer.updateToController(ccindex);
+
+ }
+
+
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
new file mode 100644
index 0000000..749e218
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
@@ -0,0 +1,159 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import com.adobe.linguistics.utils.ITokenizer;
+ import com.adobe.linguistics.utils.TextTokenizer;
+ import com.adobe.linguistics.utils.Token;
+
+ import flashx.textLayout.edit.SelectionManager;
+ import flashx.textLayout.edit.EditManager;
+ import flashx.textLayout.tlf_internal;
+ import flashx.textLayout.elements.TextFlow;
+
+ import flashx.textLayout.container.ContainerController;
+ import flashx.textLayout.elements.FlowLeafElement;
+ import flashx.textLayout.elements.ParagraphElement;
+ import com.adobe.linguistics.spelling.ui.IWordProcessor;
+
+ use namespace tlf_internal;
+
+ public class TLFWordProcessor implements IWordProcessor
+ {
+ private var mTextFlow:TextFlow;
+ private var _containerController:ContainerController;
+
+ public function TLFWordProcessor(textFlow:TextFlow)
+ {
+ if (textFlow == null ) throw new Error("illegal argument.");
+ mTextFlow = textFlow;
+ }
+
+
+ public function replaceText(token:Token, replacement:String):void {
+ var startIndex:int = token.first;
+ var endIndex:int = token.last;
+
+ var ta:TextFlow = mTextFlow;
+ //var end:int = getValidLastWordIndex();
+
+ if ( replacement == null ) return;
+
+ /*if (mTextFlow.text.length= ta.textLength) return null;
+
+ var currentLeaf:FlowLeafElement = ta.findLeaf(index);
+ var currentParagraph:ParagraphElement = currentLeaf ? currentLeaf.getParagraph() : null;
+
+ if (currentParagraph == null) return null;
+ var paraStart:uint = currentParagraph.getAbsoluteStart();
+
+ //tokenizer = new TextTokenizer(currentParagraph.getText().substring());
+
+ var tmpToken:Token = new Token(index - paraStart,index - paraStart);
+ var tokenizer:ITokenizer;
+ if ( externalTokenizer == null ) {
+ tokenizer = new TextTokenizer(currentParagraph.getText().substring());
+ }else {
+ tokenizer = externalTokenizer;
+ }
+
+ var result:Token = new Token(0,0);
+ var preToken:Token = tokenizer.getPreviousToken(tmpToken);
+ var nextToken:Token = tokenizer.getNextToken(tmpToken);
+ if ( preToken.last == nextToken.first ) {
+ result.first = preToken.first + paraStart;
+ result.last = nextToken.last + paraStart;
+ return result;
+ }else {
+ return null;
+ }
+
+ }
+
+ // TODO: workaround for unexpected jump when word replaced, to be refactored for code sharing
+ private function getValidLastWordIndex():int{
+ var index:int = 0;
+ //var index:int = SelectionManager.computeSelectionIndex(mTextFlow.textFlow, mTextFlow, mTextFlow, mTextFlow.width+mTextFlow.horizontalScrollPosition, mTextFlow.height+mTextFlow.verticalScrollPosition);
+ return index;
+ }
+
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as b/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
new file mode 100644
index 0000000..28f16e6
--- /dev/null
+++ b/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
@@ -0,0 +1,87 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+ import __AS3__.vec.Vector;
+
+ import com.adobe.linguistics.utils.Token;
+
+ import flash.geom.Point;
+ import flash.text.TextField;
+
+ import mx.core.IUITextField;
+
+
+ public class HaloHighlighter implements IHighlighter
+ {
+ private var mTextField:TextField;
+ private var mHighlighter:SpellingHighlighter;
+ /*
+ * offset point:
+ */
+ private var _offsetPoint:Point;
+
+ public function HaloHighlighter( textField:TextField )
+ {
+ if (textField == null ) throw new Error("illegal argument.");
+ mTextField = textField;
+ mHighlighter = null;
+ this._offsetPoint = new Point(0,0);
+ }
+ /*************************Public function************************************/
+ public function drawSquiggles(tokens:Vector.):void
+ {
+ spellCheckRange(tokens);
+ }
+
+ public function clearSquiggles():void
+ {
+ if (mHighlighter) {
+ mTextField.parent.removeChild(mHighlighter);
+ mHighlighter=null;
+ }
+
+ }
+
+ public function set offsetPoint(op:Point):void{
+ _offsetPoint = op;
+ }
+
+ public function get offsetPoint():Point{
+ return _offsetPoint;
+ }
+
+
+ private function spellCheckRange(tokens:Vector.):void {
+
+ mHighlighter= new SpellingHighlighter( mTextField as IUITextField);
+
+
+ for ( var i:int = 0; i< tokens.length; ++i ) {
+ var _token:Token = tokens[i];
+ mHighlighter.drawSquigglyLine(_token.first, _token.last);
+ }
+
+ mTextField.parent.addChild(mHighlighter);
+ mHighlighter.move(_offsetPoint.x, _offsetPoint.y);
+ }
+
+ }
+}
\ No newline at end of file