Re: Delete action from variety of key presses
Re: Delete action from variety of key presses
- Subject: Re: Delete action from variety of key presses
- From: Caleb Strockbine <email@hidden>
- Date: Wed, 9 Jul 2008 00:56:29 -0400
On Jul 8, 2008, at 3:02 PM, email@hidden wrote:
Okay, got this message late though it looks like another had responded
to it already. Given that I need to override -keyDown: (or -
performKeyEquivalent:) in applicable first responders anyway, and it
doesn't really read well to have -forwardDelete:, backwardDelete:,
etc. actions, I just did the following:
Unless I'm really misunderstanding what you're trying to do, I think
you're making things much more complicated than they need to be. The
graph of responders looks like a tree, and in the case of events, the
root of the tree is generally a window or a window controller. The
responder chain is the path from the current first responder to the
root of the tree. So why override -keyDown:, etc., in every leaf of
the tree, which is to say every first responder, when you can instead
insert a single responder that implements the desired behavior closer
to the root of the tree?
I'm tempted to improve upon this by using the
NSUserInterfaceValidations informal protocol (which my app delegate
already conforms to for the sake of the Edit>Delete menu item) to
check if the delete action is even performed. The way this code
works, the delete key gets swallowed even when nothing is deleted.
This silent dropping of the delete key is how many apps behave, but
wouldn't it be better to pass the event up to super when the delete:
action isn't really valid, so it can eventually result in a beep/bonk/
blip?
If you put a responder that implements your desired "default"
deleting behavior near the root of the tree, then any responders that
happen to be earlier in the chain (i.e. nearer the first responder)
are free to intercept the keyDown event and do what they like with
it, but if nobody else catches it, your responder ensures that the
expected thing happens. For example, the delete key will behave as
expected in an active text field, but when nothing else grabs the
keyDown, your responder will delete selected objects from your custom
view (or whatever).
Here's a more concrete example. Create an instance of the following
DeleteBeeper class in the nib file of a vanilla Cocoa app (i.e. one
that's not document-based) and connect it's window outlet to the
nib's window. Add a text field or two to the window, and build and
run the app. When a text field is active, the delete button behaves
as expected and deletes the previous character. When no text field is
active, DeleteBeeper's -deleteBackward: method is called.
// DeleteBeeper.h
#import <Cocoa/Cocoa.h>
@interface DeleteBeeper : NSResponder
{
IBOutlet NSWindow *window;
}
@end
// DeleteBeeper.m
#import "DeleteBeeper.h"
@implementation DeleteBeeper
- (void)awakeFromNib
{
[window setNextResponder:self];
}
- (void)keyDown:(NSEvent *)theEvent
{
[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
}
- (void)deleteBackward:(id)sender
{
NSLog(@"DeleteBeeper caught the -deleteBackward: message!");
NSBeep();
}
@end
I like letting -interpretKeyEvents: worry about deciding what action
to take based on the key event and then just implementing the
appropriate methods, but you can certainly use your own -keyDown:
implementation instead. The important thing here is that -
awakeFromNib inserts the DeleteBeeper instance as the window's next
responder, which means that the DeleteBeeper gets a look at any
keyDown's that haven't already been handled by somebody else.
You can do the same thing in a document-based app, but in that case
you might be better off subclassing NSWindowController and putting
the -keyDown:, -deleteBackward:, etc. there.
Note: the NSBeep() isn't really all that helpful in this case, since
NSResponder's default behavior when nobody else handles a key down
event is to beep. To make sure that DeleteBeeper's -deleteBackward:
method really is being called, look for the log message or put a
breakpoint in the method.
Hope that helps,
-Caleb.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden