How would you recommend building undo/redo functionality?

700 views
Skip to first unread message

Evgeny

unread,
Feb 27, 2010, 3:38:39 PM2/27/10
to Closure Library Discuss
Hello, in my problem there is a data structure that is reflected on
the drawing canvas, where elements are added by dragging new ones
onto the canvas, and modified by mouse actions.

I would like to add an undo/redo functionality - how can I use closure
library for that?

Thanks!

Evgeny.

Mohamed Mansour

unread,
Feb 27, 2010, 11:39:43 PM2/27/10
to closure-lib...@googlegroups.com
Hi,

Maybe you can create some sort of JavaScript stack implementation with arrays. If I was going to implement one, I would create an Action object that has some sort of execute functionality and perhaps an undo function. And the undo stack class will keep track of those actions in an array.

Once you undo, you just go back an item on the stack (if you can) from head (which you can control from a simple pointer within the undo stack class) and call the undo function from the action object (in the array). If you want to redo, same thing, you go forward (if you can), and you execute that action.

Maybe it would be best to add limits for how many times you can go back and forth.

-Mohamed Mansour

Julie Parent

unread,
Feb 28, 2010, 4:58:43 PM2/28/10
to closure-lib...@googlegroups.com
The rich text editor in Closure library includes a custom undo-redo implementation.  There are parts you could probably re-use, specifically goog.editor.plugins.UndoRedoState and goog.editor.plugins.UndoRedoManager.  goog.editor.plugins.UndoRedo is editor specific, but will give you a sense of how the other classes are used.

Julie

Mohamed Mansour

unread,
Feb 28, 2010, 9:54:20 PM2/28/10
to closure-lib...@googlegroups.com
After the hockey game finished (yay we won) I wanted to work on something fun (improve my skills in JS), so I thought the undo/redo thing would be nice. If you want a undo/redo functionality as I stated before, take a look at this example to see how it works:


I tried documenting as much as I could, the source for the history stack is here:

Note: I am no expert in JavaScript/Closure, I just like experimenting new technologies, I  am still a newbie in the JS world, just learning from contributing in open source projects  and personal interest. So there might be bad practice or something would have been done better, if you find anything, please let me know.

Basically, the way I implemented is how I explained it before, you have an Action object which its main purpose is to provide some sort of functionality:
  • execute() - Execute the action.
  • undo() - Undo the action
You can create multiple actions, in my example above, I thought the perfect demo would be drawing random circles on the screen once you click. Every time you add something to the History stack, it will execute it. From thinking more about it now, I think it should have been renamed to ActionStack (instead of HistoryStack) and instead of "add" it should have been "execute", but you get the point.

I pushed the source to github for you to take a more detailed look.

-Mohamed Mansour

Evgeny

unread,
Mar 1, 2010, 4:04:35 PM3/1/10
to Closure Library Discuss
Mohamed, congratulations on the win.

I guess the biggest question about undo/redo business is how to handle
internal structures.

in my case it will be a big object (sort of like a drawing scene)
with quite a few items - both abstract and their drawing
representations and meta-data.

so one option is to deepcopy or serialize everything and stash that on
the stack, or like
you do - translate batch actions into incrementally applicable
commands

I guess the second approach is more demanding as you have to do
special things
to make your object "undoable".

Cheers,
Evgeny.

On Feb 28, 6:54 pm, Mohamed Mansour <m0.interact...@gmail.com> wrote:
> After the hockey game finished (yay we won) I wanted to work on something
> fun (improve my skills in JS), so I thought the undo/redo thing would be
> nice. If you want a undo/redo functionality as I stated before, take a look
> at this example to see how it works:
>
> http://mohamedmansour.com/sandbox/closure/undo-redo-draw.html
>
> I tried documenting as much as I could, the source for the history stack is

> here:http://github.com/mohamedmansour/closure-simple-draw/blob/master/js/s...


>
> Note: I am no expert in JavaScript/Closure, I just like experimenting new
> technologies, I  am still a newbie in the JS world, just learning from
> contributing in open source projects  and personal interest. So there might
> be bad practice or something would have been done better, if you find
> anything, please let me know.
>
> Basically, the way I implemented is how I explained it before, you have an
> Action object which its main purpose is to provide some sort of
> functionality:
>

>    - execute() - Execute the action.
>    - undo() - Undo the action


>
> You can create multiple actions, in my example

> above<http://github.com/mohamedmansour/closure-simple-draw/blob/master/js/s...>,


> I thought the perfect demo would be drawing random circles on the screen
> once you click. Every time you add something to the History stack, it will
> execute it. From thinking more about it now, I think it should have been
> renamed to ActionStack (instead of HistoryStack) and instead of "add" it
> should have been "execute", but you get the point.
>
> I pushed the source to github for you to take a more detailed look.http://github.com/mohamedmansour/closure-simple-draw

>  <http://mohamedmansour.com/sandbox/closure/undo-redo-draw.html>


> -Mohamed Mansour
>
>
>
> On Sun, Feb 28, 2010 at 4:58 PM, Julie Parent <jpar...@google.com> wrote:
> > The rich text editor in Closure library includes a custom undo-redo
> > implementation.  There are parts you could probably
> > re-use, specifically goog.editor.plugins.UndoRedoState and
> > goog.editor.plugins.UndoRedoManager.  goog.editor.plugins.UndoRedo is editor
> > specific, but will give you a sense of how the other classes are used.
>
> > Julie
>

> > On Sat, Feb 27, 2010 at 8:39 PM, Mohamed Mansour <m0.interact...@gmail.com


> > > wrote:
>
> >> Hi,
>
> >> Maybe you can create some sort of JavaScript stack implementation with
> >> arrays. If I was going to implement one, I would create an Action object
> >> that has some sort of execute functionality and perhaps an undo function.
> >> And the undo stack class will keep track of those actions in an array.
>
> >> Once you undo, you just go back an item on the stack (if you can) from
> >> head (which you can control from a simple pointer within the undo stack
> >> class) and call the undo function from the action object (in the array). If
> >> you want to redo, same thing, you go forward (if you can), and you execute
> >> that action.
>
> >> Maybe it would be best to add limits for how many times you can go back
> >> and forth.
>
> >> -Mohamed Mansour
>

Reply all
Reply to author
Forward
0 new messages