Undo manager and field editors: a tale of woe
Undo manager and field editors: a tale of woe
- Subject: Undo manager and field editors: a tale of woe
- From: Pete Yandell <email@hidden>
- Date: Fri, 16 May 2003 10:39:55 +1000
I have my app set up such that a keypress in an open field editor for
an outline view causes an immediate call to the data source's
outlineView:setObjectValue:forTableColumn:byItem: method (as opposed to
the default behaviour in which this method is only called when the
field editor is closed.)
The problem is that I end up registering an undo event for each
keypress, which is not what I want. What I'd like to do is inspect the
undo stack, see if the last posted event was also a change in this
field editor and, if so, pull it off and replace it with a new event
combining the changes. (I believe this is exactly what an NSTextView
does.) Unfortunately NSUndoManager doesn't have any methods that let me
inspect and modify the undo stack in this way. How do I go about it? Is
there an alternative approach that will produce the same effect?
The rest of this e-mail is a description of how I got to this point. If
you're working with field editors and you need to implement undo in
your app then read on. If you work for Apple then please tell me why
all of this is so hard! :)
Here is the fundamental problem with field editors and undo handling:
I start with a simple application: each document has a one column
outline view with editable items, and a button to add a new row to the
outline view. Undo events are registered when adding a row and when
outlineView:setObjectValue:forTableColumn:byItem: is called on the
outline view's data source.
Example 1: I click the button to add a row. I start editing the row and
type a few characters into the field editor. I choose Undo. No undo
event has been registered for the text I've typed so, rather than
undoing that change, the row is deleted again.
Example 2: I click the button to add a row and then save the document.
I double click a row, type a few characters and close the document. No
undo event has been registered for the text I've typed, so the document
closes without asking me to save my changes.
Example 3: I click the button to add a row, edit the row and type in
some text. Without closing the field editor, I add another row. Now the
field editor closes, the new text is saved and an undo event is added
for the change. However the addition of the second row occurs in the
same runloop, so the undo events for the change to the first row and
the creation of the second row are grouped together. Choosing undo now
undoes both changes in one hit.
Example 1 was the first one that bit me, and I tried working around it
by catching NSUndoManagerCheckpointNotifications (which occur on
opening and closing undo groups and calls to canRedo) and forcing the
field editor to save its changes at that point. That means that
whenever you pull down the Edit menu, changes get saved. That works
well, but doesn't solve either example 2 or example 3.
The only way I can see to solve problems 2 and 3 is to register changes
immediately whenever a key is pressed in a field editor, which is
simple enough to implement. The catch is that you end up with undo
events for each character typed, hence the initial question.
As a wise man once said, there has to be a better way! Comments?
Pete Yandell
http://pete.yandell.com/
_______________________________________________
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.