• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Action based undo or snapshot based undo?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Action based undo or snapshot based undo?


  • Subject: Re: Action based undo or snapshot based undo?
  • From: Greg Titus <email@hidden>
  • Date: Wed, 29 Jan 2003 09:37:20 -0800

On Tuesday, January 28, 2003, at 11:32 PM, Alexander Lamb wrote:

Hello,

As I understood, the NSUndoManager is based on the idea of recording a series of actions needed if the user wants to undo what he just did.
In Bill Cheeseman's book, he recommands recording those actions in the action methods rather than at the object level, because it reflects more closely what the user is doing and allows to customize the undo for an action that may involve several changes on objects attributes.

I totally disagree with Bill here (sorry Bill), and I think that that is why you are running into problems.

You should register the changes at the object level, but you should set the action name in the action methods.

Now, I am having trouble with this whole concept for a few reasons:

Firstly, registering undo everywhere a user may hit an action can become rather complex because of the number of places where this might happen. For example: the data source of a NSTableView. How can you implement the undo in the data source method setting the new cell value? Not very elegant!

Nope, sure isn't. But it's an easy place to know what the action name should be, so that's all you should do in the data source method.

Another issue is calculations. Not everything can be undone by actions! Imagine I have an object graph on which I need to perform a calculation. Lots of attributes get changed and then I need to undo. I can't register the contrary of an optimisation calculation (imagine I am optimising a schedule for example). The only way here would be to duplicate the whole object graph and upon an undo discard the new object graph.

What you should be doing here is registering an undo invocation for every individual attribute change. All of those attribute changes end up in the same undo group (which is the whole reason why undo groups exist). At the action level you just set the name to "Optimisation Calculation" or whatever.

Voila, when you look at the Edit menu it shows "Undo Optimisation Calculation", and when you hit cmd-z, all of those attribute changes are set back to their original values. (And of course you _are_ using notifications or some other method to redraw your view when the attributes change rather than making your control or view layer redraw itself, right? Otherwise, not only is undo/redo going to be more difficult to get right, but you won't be able to implement AppleScript support easily either.)

Now there may well be rare times when you are changing so much of your model that storing a whole snapshot of the object graph is smaller and faster than generating the big series of attribute changes. But this is an optimization that you shouldn't worry about unless you profile your app and find that it is an issue.

So, (and you will see my roots in EOF here:-), why not implement a snapshot based undo. Like the EOControl layer of EOF? No need for the same complexity since you really need only one editing context and no SQL generation. Just the registration of attributes changes. Now, the nice thing about that is that you could register in one snapshot all the attributes that have changed in one event loop. Therefore an undo is just a question of going back one set of attributes. And... it works also when objects are changed "in the background" from a calculation or a network access, and... last but not least: it could allow notification of change in a standard way and allow automatic update of UI elements (like the EOInterface layer in EOF).

You should be doing all this anyway with the existing implementation of NSUndoManager. :-)

The only difference is that instead of storing a snapshot like EOControl, NSUndoManager is more flexible because it can invoke arbitrary method invocations instead of just calling set methods. But usually you should end up using them exactly the same way if you register your undo invocations in your object graph set attribute methods.

Hope this helps,
- Greg
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: Action based undo or snapshot based undo?
      • From: Bill Cheeseman <email@hidden>
    • Re: Action based undo or snapshot based undo?
      • From: Jim Correia <email@hidden>
References: 
 >Action based undo or snapshot based undo? (From: Alexander Lamb <email@hidden>)

  • Prev by Date: drawing text on a path?
  • Next by Date: Re: newbie q's - Storing arrays of non-objects
  • Previous by thread: Action based undo or snapshot based undo?
  • Next by thread: Re: Action based undo or snapshot based undo?
  • Index(es):
    • Date
    • Thread