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