On 6 Dec 2009, at 10:53, Graham Cox wrote: > > On 06/12/2009, at 8:12 PM, Uli Kusterer wrote: > >> I thought that was what undo groups were for? Open a group at the start of >> the drag manually, close it at the end, and everything in between gets >> lumped into one big action at the end. It may get "replayed" internally, but >> will all be triggered by one Cmd-Z. > > > Indeed, undo groups are great. Unfortunately, NSUndoManager has a bug where > if you open a group (on mouse down, say), do nothing (no drag), and close it > again (on mouse up), an empty Undo task appears in the Undo menu. It's > harmless, in that it does nothing, but it's also a nuisance, since the user > doesn't expect this and reports it as a bug with your app.
But why are you opening a group without registering an undo action? Why not just wait until the first action actually needs to be registered? > It's working around this bug that is horrible and surprisingly complicated > (for two reasons - one, you can't peek at the top of the undo stack to see > what's there and two, even if you could there's no way to tell whether the > task there is empty, because the 'tasks' are all private classes. Therefore > you have to come up with another way either to detect this case, or to > prevent it from happening. Either way, it's a complicated and nasty hack). > Incidentally I have reported this bug but it came back as a dupe. It's been > there since I started with Cocoa, on 10.2. I'm not even sure it is a bug, since the undo manager is designed to work in terms of groups, not individual actions. > > In addition, you don't really want a group to record every intermediate step > of a drag - theoretically that could run to any number of tasks, which on > Undo would be 'replayed', so the drag would eventually get undone but who > cares about all the in-between steps? You just want the object to return to > the position at the start of the drag. This is what 'task coalescing' > achieves, along with the potentially huge memory saving of not recording the > irrelevant in-between steps. Unfortunately NSUndoManager doesn't support task > coalescing, so you have to subclass it to add this. It's not a huge deal but > the bogus task problem is. So again, why not just wait till the end of the drag and record a single action? > > I've now written my own undo manager from scratch. It's much more > straightforward than NSUndoManager in that it uses Cocoa collection classes > internally - I'm guessing that one reason for NSUndoManager's arcane > implementation with all its weird group end and start markers and so on is so > that it also works with Core Foundation alone. It turns out my approach is > coincidentally very near identical to GNUStep's implementation. I was > concerned that because it subclasses NSObject, not NSUndoManager, it would > cause trouble when passed to NSDocument's -setUndoManager: method, but so far > I can report that it works perfectly with no issues, supports coalescing and > doesn't exhibit the empty group bug. It has an identical public API to > NSUndoManager so my main concern was whether internal parts of Cocoa were > using private API but that does not appear to be the case. I followed the > documentation with respect to when the various notifications are sent, and > that didn't quite keep NSDocument's dirty state properly in synch, so I did > what was necessary to keep it happy and so now it's slightly not as > documented - but I suspect the issue there is that the docs are subtly > incorrect. There's also a suspicion among users who contacted me off-list > that Core Data is doing something with private Undo API, so mine may not > support a Core Data app, but for now that doesn't concern me. > > I've still got some testing to do to really prove it's safe to use, but so > far I'm much happier with it than NSUndoManager (and if things do go wrong I > can at least debug it directly instead of having to guess what's going on > inside the black box and relying on the inaccurate documentation). I'll put > it out on my website when I'm done - not seeing those useless 'undo manager > is in an invalid state' logs is liberating, I can tell you. > > --Graham > > > _______________________________________________ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > http://lists.apple.com/mailman/options/cocoa-dev/cocoadev%40mikeabdullah.net > > This email sent to cocoa...@mikeabdullah.net _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com