5

How to implement Undo Redo operation in flex 4 for maintain history? I'm working with flex UIComponent and DisplayObjects for creating and editing diagrams,but in flex there is no way to handle user operation history directly. there is any idea to achieve this?

Devendra
  • 1,816
  • 6
  • 29
  • 45

3 Answers3

5

You could implement the Command Pattern for all actions with execute and undo methods, and queue them up.

so when the user wants to do some thing - lets say create an AddFiveToTotal class and executes:

public method execute():void{
     totalModel.add( 5 );
}

This class would then be stored on a FIFO queue.

if the user needs to undo the command would be popped and the undo function called:

public method undo():void{
     totalModel.subtract( 5 );
}

for redoability, don't pop, just iterate the queue

also take a look at the Memento Pattern

If you are using any of the currently popular MVC(S) frameworks you will undoubtably find a util that some one has already created

neil manuell
  • 225
  • 2
  • 10
  • sure, thats fine, it just means you'll have to roll your own. you could do a search for undo utils, and check out their implementation. – neil manuell Jan 31 '13 at 11:24
0

You can acheive with help of memento pattern. It hard to track all properties better you can what are property need to use for undo/redo operation.

Memento Design pattern

Memento pattern

Demo sample with source code http://www.flairpy.com/mementoPattern/MementoSample.html

Raja Jaganathan
  • 22,671
  • 4
  • 22
  • 30
  • my tool is like [cacoo](www.cacoo.com). so i need to all operation that user perform. – Devendra Jan 31 '13 at 10:23
  • A pattern is the way you write code. It's not even about languages. It will work on every language and every framework. (provided that language has OOP support) – Gio Jan 31 '13 at 10:41
  • i want to say that memento pattern..., Is memento pattern only a way? – Devendra Jan 31 '13 at 10:47
0

There are several ways you can address to this problem. First is to keep the states of your whole canvas in a Vector (I mean have a listener for all the things user can do on the stage and saving the state after a change) and then have an index of current state saved, so that you could move through your Vector and put the needed state on the stage. This is the easiest way to approach undo/redo functionality, but beware that you'll have to make clones of objects a lot and this will become a memory hog if you're going to deal with a lot of objects or a lot of undo/redos.

The second approach is to only keep what changed in that vector, so that you won't have to create and clone a lot of objects, but only save one object in your Vector which will contain all the properties that have changed and their last values. This will get you something like this:

private var mHistory:Vector.<Object> = new Vector.<Object>();
private var mCurrentIndex:int = -1;

public function storeState(state:Object)
{
   mHistory.push(state);
   mCurrentIndex++;
}     

public function undo():void
{
   if(mCurrentIndex < 1)
       return;

   mCurrentIndex--;

   //here you could test for values that could have changed
   var item:DisplayObject = this.getChildByName(mHistory[mCurrentIndex].name);
   if(mHistory[mCurrentIndex].x != undefined)
       item.x = mHistory[mCurrentIndex].x;
   // etc. you get the point. Note that this is only comfortable if only several things can change
}

And the call for storeState function would be like this:

var state:Object = { name:DisplayObjectName, x:120, y:20 };
storeState(state);

Again, you will have to listen to all movement and changes if you want to record them.

Gio
  • 1,899
  • 3
  • 22
  • 41