Re: NSUndoManager & NSTableView editing
Re: NSUndoManager & NSTableView editing
- Subject: Re: NSUndoManager & NSTableView editing
- From: James DiPalma <email@hidden>
- Date: Thu, 26 Sep 2002 17:35:08 -0400
From: Pete Yandell <email@hidden>
A problem occurs when you do this: double click a row to edit it,
change the text, then click the button to add a row. The edited row
is changed and a new row is added, but the undo events for both these
things are grouped together because they both occur within the one
runloop. Choosing Undo in the Edit menu will then undo both in one
hit, whereas they should be separate undo events.
Tricky problem. You clearly don't have a problem getting your textfield
to end editing since your problem is isolating these two undoable
events. Without having tried Hannes's suggestion, I think it will work
for your specific case.
However, a more general problem exists where a single event (like
clicking a button) can cause a field editor in your application (may
not even be in button's window) to end editing. I tried to solve this
problem well over a year ago and never found a good general solution
and don't remember much about how everything works.
Some observations:
1. If an undo event is registered, NSUndoManager's endUndoGrouping will
always get called when returning to your runloop (even if groupingLevel
== 0). If no undo grouping exists at this point (because you ended it
somewhere like tableView:setObjectValue:forTableColumn:row:), you will
raise an exception (*1).
2. NSUndoManager will only open 1 undo group for each loop of a run
loop. This undo group actually opens when someone registers this loops
first undo event (*2). Once this undo group is begun, registering new
undo events will not open a new undo group even after an
endUndoGrouping. An exception raises when registering undo operations
with no open undo grouping (*3).
3. If you call endUndoGrouping for an undo group that has no registered
undo events, you will end up with an undo on your stack that does
nothing (verified on 10.2). NSUndoManager appears to have no public way
of getting a notification when undo operations are registered, nor does
it have any public way to detect if a current undo grouping has undo
operations.
a) use setGroupsByEvent:NO on my NSUndoManager and do any event
grouping manually? Seems like that could get painful pretty quickly,
but I haven't written much code for the undo manager yet, so I'm not
sure how painful.
This might be your solution. I have avoided this solution because I'm
working on a framework and don't want to require all applications that
use this framework to be burdened with grouping their own events
because text editing can sometimes wrongly group action into one undo.
I would like to find some way to get NSUndoManager to begin a new undo
grouping after an endUndoGrouping. Then to fix your problem a call to
endUndoGrouping during any action message that handles endEditing of
text will isolote related undo operations.
But, I can't figure out how to use a poseAs: to change this behavior
given where/how NSUndoManager calls beginUndoGrouping (*2); there must
be some state variable used to detect when registering an undo
operation triggers a beginUndoGrouping. I've tried [undoManager
setGroupsByEvent:NO];[undoManager setGroupsByEvent:YES]; which doesn't
do anything.
I gave up trying to solve this problem; hope you have better luck...
-jim
(*1) Here is that exception: 2002-09-26 16:34:56.339 Number[3755] ***
Uncaught exception: <NSInternalInconsistencyException> endUndoGrouping:
NSUndoManager 0x1ca1b0 is in invalid state, endUndoGrouping called with
no matching begin
(*2) I set a breakpoint at beginUndoGrouping. My test application
stopped at this line:
[[self undoManager] registerUndoWithTarget:self
selector:@selector(setNumber:) object:number];
and had this stack trace (I can't explain how registerUndoWithTarget
turns into _registerUndoObject:):
#0 0x908368d4 in -[NSUndoManager beginUndoGrouping] ()
#1 0x908366cc in -[NSUndoManager(NSUndoManagerPrivate)
_registerUndoObject:] ()
#2 0x000044d0 in -[NumberModel setNumber:] () at NumberModel.m:61
(*3) Here is that exception: 2002-09-26 16:34:56.337 Number[3755]
_registerUndoObject:: NSUndoManager 0x1ca1b0 is in invalid state, must
begin a group before registering undo
_______________________________________________
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.