Re: Undo/Text Field/Checkbox Issue
Re: Undo/Text Field/Checkbox Issue
- Subject: Re: Undo/Text Field/Checkbox Issue
- From: Pete Yandell <email@hidden>
- Date: Mon, 26 May 2003 14:09:54 +1000
This is effectively the same question I asked a couple of weeks ago
about using field editors in outline or table views and supporting
undo. I've spent a lot of time on this one.
The simplest solution I've come up with involves the following:
1) Call setGroupsByEvent:NO on your undo manager and call
beginUndoGrouping and endUndoGrouping yourself in action methods. This
seems like a pain, but it's actually not that bad when you sit down to
do it.
2) Whenever an action method for a button is going to end editing in
your text field, make sure you call endEditingFor:nil on your window
before doing anything else in your action method and before you call
beginUndoGrouping.
3) Make sure you have beginUndoGrouping and endUndoGrouping in your set
action for the text field.
That way, clicking a button should end the text editing and save that
change in one undo group and then perform the action for the button in
a second.
For buttons that don't need to end the text editing, you simply don't
call endEditingFor. The text editor should remain active and an undo
event should be registered for the button.
There's an optional step 4 that makes things a lot neater too: subclass
NSUndoManager as follows.
- (NSTextView*)keyTextView
{
// If the first responder is a text view or field editor return it,
// otherwise return nil.
NSWindow* window = [[NSApplication sharedApplication] keyWindow];
NSResponder* responder = [window firstResponder];
if ([responder isMemberOfClass:[NSTextView class]])
return (NSTextView*)responder;
else
return nil;
}
- (BOOL)canUndo
{
if ([self keyTextView] != nil)
return YES;
else
return [super canUndo];
}
- (BOOL)canRedo
{
if ([self keyTextView] != nil)
return NO;
else
return [super canRedo];
}
- (NSString *)undoActionName
{
if ([self keyTextView] != nil)
return @"Editing";
else
return [super undoActionName];
}
- (void)undo
{
NSTextView* keyTextView = [self keyTextView];
if (keyTextView != nil) {
[keyTextView setString:@""];
[[[NSApplication sharedApplication] keyWindow]
endEditingFor:nil];
}
else
[super undo];
}
This basically says that whenever a text view is the first responder,
undo should simply undo the changes to the text view and end its
editing rather than calling the usual undo manager stuff. (My hack for
doing this is to set the contents of the text field to the empty string
and then, in my set action method for the text field, ignore empty
strings. This doesn't work real well if the empty string is a
legitimate value for you.) This simplifies things because you know that
no undo or redo actions that you've registered are ever going to get
called while a field editor is open.
I still don't think all of this is a terribly nice solution from a user
perspective, but it avoids the big problems of grouping of unrelated
undo events and undo events being out of order.
I've got a big slab of example code relating to this stuff and outline
views and at some point I'll clean it up and write an article to go
with it.
P.S. I'm not feeling very lucid today, so I hope my explanations of all
this aren't too confusing.
P.P.S. Bill Cheeseman suggests a more powerful but much more complex
solution in his book Cocoa Recipes for Mac OS X. I think there might be
a couple of problems with his approach in situations like yours - his
test application never puts buttons and text fields on the screen at
the same time - but I need to dig deeper before I can confirm that.
Pete Yandell
http://pete.yandell.com/
On Monday, May 26, 2003, at 01:43 AM, Erik J. Barzeski wrote:
>
I've researched this issue, tried about twenty different things, and
>
asked a
>
number of pals. I've yet to find a "best" solution.
>
>
I'm working on a simple document-based app (well, it's simple right
>
now). I
>
have both checkboxes and text fields. I have undo/redo working
>
everywhere.
>
Each text field and checkbox is wired to to an action in the controller
>
("MyDocument").
>
>
...
>
>
This works beautifully except in a case like this:
>
>
1) user types some text
>
2) without tabbing or pressing enter, user clicks a checkbox. (I
>
imagine
>
other actions would cause these issues as well - switching tab views,
>
an
>
external AppleScript changing a value somewhere, etc.)
_______________________________________________
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.