• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Changing up/down arrow behavior for NSTextField
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Changing up/down arrow behavior for NSTextField


  • Subject: Re: Changing up/down arrow behavior for NSTextField
  • From: Duncan Champney <email@hidden>
  • Date: Thu, 14 Feb 2008 09:44:48 -0500


As mentioned in a previous post, using a key binding and the control:textView:doCommandBySelector method seems the way to do this, but I can't find an explanation of how to do this, and am not clear on how bindings work.

I'm not sure what you mean by a "key binding". You shouldn't have to do anything other than implement -textView:doCommandBySelector: in the NSTextField subclass you want to treat specially. For example:


@implementation MyTextField
-(BOOL)textView:(NSTextView *)aTextView doCommandBySelector: (SEL)aSelector{
NSLog(@"selector: %s", (char *)aSelector);
return NO;
}


this will log the selector that gets sent every non-character key press. Looking at the log, you can see, for example, that the up arrow sends the "moveUp:" selector and shift+up sends "moveUpAndModifySelection:". To make use of this, you can either examine/compare aSelector and do everything in - textView:doCommandBySelector: or do something like this (which I think is more readable and has the added benefit of passing unhanded events up the responder chain):

@implementation MyTextField
-(BOOL)textView:(NSTextView *)aTextView doCommandBySelector: (SEL)aSelector{
return [self tryToPerform:aSelector with:aTextView]; }


-(void)moveUpAndModifySelection:(id)sender{
   NSLog(@"Increment by 10");
}

-(void)moveUp:(id)sender{
   NSLog(@"Increment by 1");
}

The details as to why this work go something like this:

When a text field is edited, a NSTextView called the field editor is attached to it. The field editor's delegate is automagically set to the text field it's editing. When a key is pressed, NSTextView's keyDown: is called which passes the event to interpretKeyEvents: which, in turn, sends the event to the input manager for processing. If it's a character (a, b, c, etc.) it will come out as an - insertText: call. If it's a non-character event (tab, enter, etc) it will come out as a call to -doCommandBySelector:.

You don't want to override these methods directly in your field editor because you might require different behavior for each field in your app and the same field editor is used for all of them. But remember that the text field that is being edited is the field editor's delegate. So you can implement the delegate method - textView:doCommandBySelector: in your text field and do the work there instead.

There's a great explanation of all this by Douglas Davidson (I think?) in the list archives. I can't find it at the moment, but it's worth looking up.

Cheers,
-Joshua Emmons

------
Joshua,

Now I understand. There are predefined command selectors that the text system generates for certain keystrokes, and I just need to intercept those command selectors in my code.

Happily, the keystrokes I want to special-case, up/down arrow and shift up/down arrow, have existing command selectors ("moveUp", "moveDown", "moveUpAndModifySelection", and "moveDownAndModifySelection"). I wrote my code to handle those 4 messages, and ignore others. Rather than using "- tryToPerform:aSelector", I just do a string match on the different command selectors, like this:

   NSLog(@"Command = %s", command);
   if (!strcmp((char *)command, "moveUp:"))
       //handle up arrow
   else if (!strcmp((char *)command, "moveUpAndModifySelection:"))
       //handle shift up arrow
   else if (!strcmp((char *)command, "moveDown:"))
       //handle down arrow
   else if (!strcmp((char *)command, "moveDownAndModifySelection:"))
       //handle shift down arrow
   [control setDoubleValue: [control doubleValue] + value];
   [self performSelector: [control action] withObject: (id) control];

I adjust the value of my field, then invoke the IBAction for the field directly, so it gets handled as normal.

Thanks for your help.

What if I needed to handle a keystroke for which there is not a defined method selector? (Various keystrokes return no-op, and I might wand shift-command-option up arrow, or somesuch.)

How would I handle those cases? Is there a way to intercept key down events for the NSTextView when it is the first responder?



Duncan C
_______________________________________________

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


  • Follow-Ups:
    • Re: Changing up/down arrow behavior for NSTextField
      • From: glenn andreas <email@hidden>
  • Prev by Date: Re: how to simulate passing parameter with selector
  • Next by Date: Re: Changing up/down arrow behavior for NSTextField
  • Previous by thread: Re: Changing up/down arrow behavior for NSTextField
  • Next by thread: Re: Changing up/down arrow behavior for NSTextField
  • Index(es):
    • Date
    • Thread