Undo/Redo Action Framework
DescriptionIn order to facilitate the undo and redo functionality of an editor we need to be able to track and reverse changes we make to the project data.
in order to do this we need a Framework that can wrap the functionality.
the framework should consist of two parts
1) A manager:
- The manager should contains two stacks of action objects. actions that have been done and can be undone, and actions that have been undone and can be redone.
- The manager should properly track history changes and keep data safe. ie if a action is undo and then a new action is done. the redo stack should be cleared as the first action can't safely be redone.
- In the facilitation of a future "history" feature like you would find in Photoshop methods should be made that can do batch calls to undo or redo several actions at once going forward or backward in the history.
- The ability to configurable limit the number of actions in the stacks should also be available as this system has the potential to eat up a lot of memory.
2) An Action template:
- The idea is that when we want to modify project data we create an action object of the type we need, fill in the necessary data, and then call some sort of commit method on the action object. the Action should add itself to the top of the undo stack and record any data it needs to undo it's changes and then make it's changes.
- When an undo call is made the the manager it pulls the action on the top of the stack calls a reverse method on it. the reverse method should record any data it needs to redo itself, and then undo it's past changes. the action then be moved to the top of the redo stack.
- When a redo call to the manger pulls the action on the top of the redo stack and should call the commit method again and move it to the top of the undo stack.
- This class should be a template that real action objects subclass.
PriorityHigh
PrerequisitesNone
AssignedNone
Everything elseThis system should be included in the Core library in it's own module name "Actions". Don't worry about doing the house keeping code to register the system to the Kernel, I'll take care of that.
Consider using a doubly-linked list as the structure for recording actions in a sequential manner. You can then go forward and backwards in time (undo/redo) by moving a pointer around the list. It's easier than the hassle of moving data between two data structures.
*hugs*
Since we're using Python, a normal Python array will be used for this.
I think a simple data structure with an action ID, the previous state and the new state should be enough for an undo/redo functionality.
I'm not sure what your saying.I thought that two lists was pretty simple
* I think * what he means is each action has an ID, and is stored in array. Then when the Undo is executed, it simply goes back through the array, reads the ID and then knows what protocol to use to make the action.
Alright, G_G I was hoping that you would be the one to do this but we can't wait any longer. I'm going to do it tonight. I'll probably finish it too. if you've done ANY work on it commit the work as it will likely save me time.
ok
Action framework done
to create an action you subclass the ActionTemplate class from the Action.py in the Core
the init method should take any data that the action need to know in order to change data in the project. it should also call the __init__ method of the super class
super(<classname>, self).__init__()
the subclass should then define a "do_apply" method (no arguments) that will a)record data in the project necessary for the action to be undone and b) set the new data in the project
then the action needs to have a "do_undo" method (no arguments) that will a)record data so the action can be redone and b) use recorded data from the do_apply method to undo the action
the recorded data can be recorded to the action object itself
You so sexy.
The pieces of the editor are coming along nicely. Now comes the horrible task of linking them all together. :P
I suggest you alias do_apply with do_redo as well. This will make the code easier to read because when you call the event for the redo button, the code will read "action.do_redo".
actualy it will read
the apply method of the action class will add the action to the action stack if it not in the stack already and call the do_apply method in the middle in the template class the do_apply method does nothing it just has a simple pass statement. then all we to do to create create an actual action is subclass and make the do_apply and do_undo methods actually do something along with make the init method collect data to carry out the action.
I suppose I'll make one action as an example for how it will work.
also, there is no alias in python. a similar effect can be achieved but we don't need to do that here.
I meant alias in general, not literally Ruby's function. xD
class Woman(object):
def do(self):
# hurr hurr hurr code comes here
def do_again(self):
self.do()