AS3: Undo-Funktion mit dem Command Pattern
Wenn man eine Flash Anwendung entwickelt, in welcher der Benutzer vieles falsch machen kann, ist es oft ratsam eine Funktion bereitzustellen die es ihm ermöglichst verschiedene Arbeitsschritte rückgängig zu machen. Doch wie implementiert man so eine Undo-Funktion genau? In diesem Artikel möchte ich mit einem kleinen Beispiel zeigen wie sich ein solches Problem unter Einsatz des Command Patterns sauber lösen lässt.
Nachfolgend habe ich rudimentär zwei Buttons und zwei Eingabefelder zusammen mit einem Kreis auf einer Bühne platziert. Man kann mit Hilfe der Eingabefelder offensichtlich die x- und y-Positionen des Kreises verändern. Der Clou daran ist, dass man auch einen Undo-Befehl ausführen kann, welcher jeweils die letzte Aktion rückgängig macht.
Als erstes bin ich hergegangen und habe ein Command-Interface mit dem Namen ICommand definiert. Dieses Interface beschreibt die beiden Methoden die ich benötige. Zum einen natürlich die execute()-Methode, welche die eigentliche Funktionalität beinhaltet und zum anderen die undo()-Methode:
package com.boxedfolder.examples.undo
{
public interface ICommand
{
function execute():void;
function undo():void;
}
}
Die Klasse MoveCommand, welche konkret für die Bewegung meines Objekts zuständig ist sieht nun folgendermaßen aus:
package com.boxedfolder.examples.undo
{
import flash.display.Sprite;
public class MoveCommand implements ICommand
{
private var _addedY:int;
private var _addedX:int;
private var _sprite:Sprite
public function MoveCommand(sprite:Sprite, addedX:int, addedY:int)
{
_addedX = addedX;
_addedY = addedY;
_sprite = sprite;
}
public function execute():void
{
_sprite.x += _addedX;
_sprite.y += _addedY;
}
public function undo():void
{
_sprite.x -= _addedX;
_sprite.y -= _addedY;
}
}
}
Mit unserer konkreten MoveCommand-Klasse, haben wir nun das Werkzeug, mit Hilfe der Methode execute() eine Bewegung in x- und y-Richtung an einem Sprite durchzuführen. Des weiteren speichert eine Move-Command Instanz, die hinzugefügten Werte und merkt sich also indirekt die alte Position des Sprites. Die Methode undo() nimmt die gespeicherten Werte und zieht sie vom referenzierten Sprite wieder ab. Sie macht also den gesamten Vorgang rückgängig.
Die Dokumenten-Klasse UndoExample sieht wie folgt aus:
package
{
import com.boxedfolder.examples.undo.ICommand;
import com.boxedfolder.examples.undo.MoveCommand;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
[SWF(height="550", width="550", backgroundColor="#ffffff", frameRate="50")]
public class UndoExample extends Sprite
{
//... verkürzt
private var commandStack:Array = [];
public function UndoExample()
{
setupVisuals();
}
private function setupVisuals():void
{
//....verkürzt
}
private function buttonHandler(e:MouseEvent):void
{
if(e.target == goButton)
changeObject();
if(e.target == undoButton)
undo();
}
private function changeObject():void
{
var command:ICommand;
var yv:Number = Number(yTextField.text);
var xv:Number = Number(xTextField.text);
if(!isNaN(yv) && !isNaN(xv))
{
command = new MoveCommand(circle, xv, yv);
commandStack.push(command);
command.execute();
}
}
private function undo():void
{
var command:ICommand;
if(commandStack.length > 0)
{
command = commandStack.pop() as ICommand;
command.undo();
}
}
}
}
Wir legen jeden Command, welchen wir instantiieren und ausführen, am Ende eines Arrays ab. Dies bietet uns sozusagen ein Command-Stapel. Wenn der Benutzer den Undo-Button betätigt, wird die Methode undo() des Commands aufgerufen, welcher sich am ende des Arrays befindet. Gleichzeitig wird besagter Command aus dem Array entfernt.
In diesem simplen Beispiel sieht man wie man mit einfachen Mitteln eine Struktur aufbaut, in der ein Benutzer beliebig viele Schritte einzeln zurückgehen kann. In einem weiteren Artikel möchte ich das Beispiel noch etwas komplexer machen und die Struktur unter Anderem mit Hilfe des Composite Patterns verfeinern. Der komplette Source Code des oberen Beispiels lässt sich mit Rechtsklick und der Option “View Source” einsehen.























[...] dem vorherigen Artikel über das Command-Pattern, hab ich eine kleine Beispielanwendung vorgestellt. Diese [...]
Pingback von boxedfolder.com – Flex, Flash & Web » archive » Composite & Command: Undo-Funktion noch flexibler _ 30 November 2009 um 12:08 Uhr