In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

editor inline ime test

an experimental code to implement
inline ime at the flash player level
(inline ime is not supported for tlf)
http://forums.adobe.com/message/2057505#2057505

this sample only works for FP 10.0

@author kobayashi-taro
Get Adobe Flash player
by 9re 20 May 2010
    Embed
/**
 * Copyright 9re ( http://wonderfl.net/user/9re )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eVPk
 */

package  
{
	/**
	 * an experimental code to implement
	 * inline ime at the flash player level
	 * (inline ime is not supported for tlf)
	 * http://forums.adobe.com/message/2057505#2057505
	 * 
	 * this sample only works for FP 10.0
	 *
	 * @author kobayashi-taro
	 * 
	 */
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.IMEEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	import flash.external.ExternalInterface;
	import flash.geom.Rectangle;
	import flash.system.IME;
	import flash.system.System;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.ui.Keyboard;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import flash.utils.setTimeout;
	
	public class FlashTest extends Sprite 
	{
		private var _imeInlineInput:TextField;
		private var _tf:TextField;
		private var _sp:Sprite;
		private var _imeMode:Boolean;
		private var _defaultInputTarget:InteractiveObject;
		private var _caret:int;
		private var _text:String = '';
		private var _selEnd:int;
		private var _selStart:int;
		private var NL:String = '\n';
		private var lastCol:int;
		private var _lineHeight:int;
		
		public function FlashTest() 
		{
			_tf = new TextField;
			_tf.mouseEnabled = false;
			//_tf.type = TextFieldType.INPUT;
			_tf.multiline = true;
			_tf.textColor = 0xffffff;
			_sp = new Sprite;
			
			_tf.text = ' ';
			var rect:Rectangle = _tf.getCharBoundaries(0);
			_tf.text = '';
			_lineHeight = rect.height;
			
			
			_imeInlineInput = new TextField;
			_imeInlineInput.type = TextFieldType.INPUT;
			_imeInlineInput.background = true;
			_imeInlineInput.textColor = 0xffffff;
			_imeInlineInput.backgroundColor = 0x333333;
			//_imeInlineInput.alpha = 0.3;
			_imeInlineInput.height = _lineHeight;
			_imeInlineInput.addEventListener(FocusEvent.FOCUS_OUT, imeFocusOut);
			_imeInlineInput.addEventListener(TextEvent.TEXT_INPUT, onIMETextInput);
			
			_imeMode = (IME.conversionMode != "ALPHANUMERIC_HALF");
			
			addChild(_tf);
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function imeFocusOut(e:FocusEvent):void 
		{
			if (stage.focus != _defaultInputTarget)
				stage.focus = _defaultInputTarget;
		}
		
		private function init(e:Event):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			_defaultInputTarget = this;
			
			_defaultInputTarget.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
			_defaultInputTarget.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
			_defaultInputTarget.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
//			_sp.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			_defaultInputTarget.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			//_defaultInputTarget.addEventListener(IMEEvent.IME_COMPOSITION, imeComposition);
			_defaultInputTarget.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, onKeyFocusChange);
			_defaultInputTarget.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
			// 10.1
			addEventListener("imeStartComposition", imeStartCompositionHandler);
			_defaultInputTarget.addEventListener(TextEvent.TEXT_INPUT, onTextInput);
			focusRect = false;
			
			System.ime.addEventListener(IMEEvent.IME_COMPOSITION, imeComposition);
			
			addChild(_sp);
			addChild(_tf);
			addChild(_imeInlineInput);
			_imeInlineInput.visible = _imeMode;
				
			stage.addEventListener(KeyboardEvent.KEY_DOWN, function ():void {
				if (stage.focus != _defaultInputTarget && !_imeMode) {
					stage.focus = _defaultInputTarget;
				} else if (stage.focus != _imeInlineInput && _imeMode) {
					stage.focus = _imeInlineInput;
				}
				//if (stage.focus != _defaultInputTarget)
					//stage.focus = _defaultInputTarget;
			});
			stage.focus = this;
			//setTimeout(function ():void {
				//stage.focus = _sp;
			//}, 200);
			
			stage.addEventListener(Event.RESIZE, onResize);
			stage.dispatchEvent(new Event(Event.RESIZE));
		}
		
		private function onTextInput(e:TextEvent):void 
		{
			replaceSelection(e.text);
			//_setSelection(_caret, _caret);
			//resetInlineInputFook();
			setTimeout(resetInlineInputFook, 50);
		}
		
		private function resetInlineInputFook():void {
			var i:int = Math.max(_selStart - 1, 0);
			var rect:Rectangle = _tf.getCharBoundaries(i);
			
			if (rect == null) { // this occurs when the previous char is '\n'
				var l:int = _tf.getLineIndexOfChar(i);
				trace(l);
				rect = new Rectangle(2, _lineHeight * (1 + l));
				
			}
			
			_imeInlineInput.x = rect.x + rect.width;
			_imeInlineInput.y = rect.y;
		}
		
		private function onMouseDown(e:MouseEvent):void 
		{
			stage.focus = this;
		}
		
		private function onMouseOver(e:MouseEvent):void 
		{
			Mouse.cursor = MouseCursor.IBEAM;
		}
		
		private function onMouseOut(e:MouseEvent):void 
		{
			Mouse.cursor = MouseCursor.ARROW;
		}
		
		private function onFocusIn(e:FocusEvent):void 
		{
			//log(e.type, e.keyCode);
			//e.preventDefault();
		}
		
		private function onKeyFocusChange(e:FocusEvent):void 
		{
			log(e.type, e.keyCode);
		}
		
		private function onKeyUp(e:KeyboardEvent):void 
		{
			//log(e.type, e.keyCode);
		}
		
		private function imeStartCompositionHandler(e:IMEEvent):void 
		{
			
		}
		
		private function imeComposition(e:IMEEvent):void 
		{
			log(e.type, e.text);
			if (stage.focus == _imeInlineInput) {
				_imeMode = false;
				_imeInlineInput.text = '';
				_imeInlineInput.visible = false;
				stage.focus = _defaultInputTarget;
				resetInlineInputFook();
				trace(e);
			}
		}
		
		private function onKeyDown(e:KeyboardEvent):void 
		{
			var k:int = e.keyCode;
			resetInlineInputFook();
			
			if (k == Keyboard.BACKSPACE) { // deletes a char before selection
				var i:int = _selStart - 1;
				i = (i < 0) ? 0 : i;
				replaceText(i, _selEnd, '');
				return;
			} else if (k == Keyboard.ENTER) { // add enter
				replaceSelection('');
				return;
			}
			
			if (IME.enabled && IME.conversionMode != "ALPHANUMERIC_HALF") {
				if (!_imeMode) {
					_imeMode = true;
					_imeInlineInput.text = '';
					_imeInlineInput.visible = true;
					if (stage.focus != _imeInlineInput)
						stage.focus = _imeInlineInput;
				}
				log(e.type, e.keyCode);
			} else if (_imeMode) {
				_imeMode = false;
				_imeInlineInput.visible = false;
				stage.focus = _defaultInputTarget;
				if (k == Keyboard.CONTROL || k == Keyboard.SHIFT || e.keyCode == 3/*ALT*/ || e.keyCode == Keyboard.ESCAPE)
					return;
				//handleKeyEvent(e);
			}
		}
		
		public function replaceText(startIndex:int, endIndex:int, text:String):void
		{
			text = text.replace(/\r\n/g, NL);
			text = text.replace(/\r/g, NL);
			
			//undoBuff.push({s:startIndex, e:startIndex+text.length, t:_text.substring(startIndex, endIndex)});
			//redoBuff.length = 0;
			//_replaceText(startIndex, endIndex, text);
			_tf.replaceText(startIndex, endIndex, text);
			_selEnd = _selStart = startIndex + text.length;
		}
		
		private function saveLastCol():void
		{
			lastCol = _caret - _text.lastIndexOf(NL, _caret-1) - 1;
		}
		public function replaceSelection(text:String):void
		{
			replaceText(_selStart, _selEnd, text);
			
			//FIXME filter text
			//_setSelection(_selStart+text.length, _selStart+text.length, true);
		}
		
		private function dipatchChange():void
		{
			
		}
		
		private function updateCaret():void
		{
			_tf.setSelection(_caret, _caret);
		}
		
		private function checkScrollToCursor():void
		{
			
		}
		
		private function _setSelection(beginIndex:int, endIndex:int, caret:Boolean = false):void
		{
			_selStart = beginIndex;
			_selEnd = endIndex;
			//_tf.setSelection(beginIndex, endIndex);
			if (caret) {
				_caret = _selEnd
			}
			setTimeout(_tf.setSelection, 0, beginIndex, endIndex);
		}
		
		public function get length():int { return _text.length; }
		
		private function findWordBound(start:int, left:Boolean):int
		{
			if (left)
			{
				while (/\w/.test(_text.charAt(start))) start--;
				return start + 1;
			}
			else
			{ 
				while (/\w/.test(_text.charAt(start))) start++;
				return start;
			}
		}
		
		private function onIMETextInput(e:TextEvent):void 
		{
			log('imeMode', e.text);
			_imeMode = false;
			_imeInlineInput.visible = false;
			//_imeInlineInput.removeEventListener(TextEvent.TEXT_INPUT, onIMETextInput);
			//stage.focus = this;
		}
		//
		private function log(...args):void {
			//_tf.appendText(args + '\n');
			//_tf.scrollV = _tf.maxScrollV;
			trace(args);
			//ExternalInterface.call('console.log', args);
		}
		
		private function onResize(e:Event):void 
		{
			log(e.type);
			_imeInlineInput.width = stage.stageWidth;
			_tf.width = stage.stageWidth;
			_tf.height = stage.stageHeight;
			_sp.graphics.clear();
			_sp.graphics.beginFill(0);
			_sp.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			_sp.graphics.endFill();
		}
		
	}

}