アンドゥー可能なTextArea
UndoableTextArea(アンドゥー可能なTextArea)を先日作りました。
特徴としてはカーソル位置も対象としているところでしょうか。
2008.6.11追記
入力完了時のカーソル位置を覚えているので、カーソル移動→入力→Undoで位置がずれます。バグです・・orz
2008.6.12さらに追記
修正版(http://d.hatena.ne.jp/masatoshisw20/20080612/1213254313)
editableの切り替えを編集開始・確定のトリガーにしてるところは一般的じゃないかも。
focusInとfocusOutをトリガーにするように変更すれば、フォーカスの切り替えが編集開始・確定になります。
<?xml version="1.0" encoding="utf-8"?> <mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml" keyDown="keyDown(event)" change="change(event)" creationComplete="init()"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; private var edits:ArrayCollection; private var index:int = -1; private function init():void { enableUndo(editable); this.addEventListener("editableChanged", editableChanged); } private function editableChanged(ev:Event):void { enableUndo(editable); } private function enableUndo(value:Boolean):void { if (value) { edits = new ArrayCollection(); index = -1; addEdit(); } else { if (edits != null) { edits.removeAll(); edits = null; } } } private function addEdit():void { cleanUselessEdits(edits.length); edits.addItem({str:text, cursorIndex:selectionEndIndex}); index = edits.length - 1; } private function cleanUselessEdits(length:int):void { for (var i:int = length - 1; i > index; i--) { edits.removeItemAt(edits.length - 1); } } public function undo():void { if (!canUndo()) { return; } restoreState(edits.getItemAt(--index)); } public function redo():void { if (!canRedo()) { return; } restoreState(edits.getItemAt(++index)); } private function restoreState(edit:Object):void { text = edit.str; setSelection(edit.cursorIndex, edit.cursorIndex); } public function canUndo():Boolean { if (index < 1) { return false; } else { return true; } } public function canRedo():Boolean { if (index == edits.length - 1) { return false; } else { return true; } } public function clearUndoHistory():void { edits.removeAll(); index = -1; } private function keyDown(ev:KeyboardEvent):void { if (ev.controlKey) { if (ev.keyCode == Keyboard.Z) { undo(); ev.preventDefault(); } else if (ev.keyCode == Keyboard.Y) { redo(); ev.preventDefault(); } } } private function change(ev:Event):void { addEdit(); } ]]> </mx:Script> </mx:TextArea>