NSTokenField catch some NSEvents

2019-03-04 06:31发布

问题:

I need implement Command + Enter, Command + O and Esc shotcuts for NSTokenField and solutonns like https://stackoverflow.com/a/18486965/1067147 not worked because -(void)noop:(SEL)sel isn't useful.

回答1:

My way is to create category for upper-in-hierarchy class NSView (also I try it for NSTextView but no luck):

//  NSView+WideInterpreter.h

#import <Cocoa/Cocoa.h>

#define kNotificationTokenModifier          @"kNotificationTokenModifier"
#define kNotificationTokenModifier_modifier @"kNotificationTokenModifier_modifier"

typedef enum{

    BMTokenModifier_CommandEnter = 10,
    BMTokenModifier_CommandO,
    BMTokenModifier_Esc,
    BMTokenModifier_nextKeyViewActivate

} BMTokenModifier;

@interface NSView (WideInterpreter)

@end

and

NSView+WideInterpreter.m
#import "NSView+WideInterpreter.h"

@implementation NSView (WideInterpreter)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

- (void)interpretKeyEvents:(id)keyEvents{

    NSMutableArray *result = [[NSMutableArray alloc] init];

    for (NSEvent *theEvent in keyEvents) {

        NSUInteger clearFlags = ([theEvent modifierFlags] &     NSDeviceIndependentModifierFlagsMask);
        BOOL commandPressed = (clearFlags == NSCommandKeyMask);

        switch ([theEvent keyCode]) {
            case 31:{//Ctrl+O
                if (commandPressed)
                    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationTokenModifier
                                                                        object:self
                                                                          userInfo:@{kNotificationTokenModifier_modifier: @(BMTokenModifier_CommandO)}];
            }break;

            case 36:{//Enter
                if (commandPressed)
                    [[NSNotificationCenter defaultCenter]     postNotificationName:kNotificationTokenModifier
                                                                        object:self
                                                                          userInfo:@{kNotificationTokenModifier_modifier: @(BMTokenModifier_CommandEnter)}];
                else
                    [super insertNewlineIgnoringFieldEditor:self];
            }break;

            case 53://Esc
                [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationTokenModifier
                                                                    object:self
                                                                  userInfo:@{kNotificationTokenModifier_modifier: @(BMTokenModifier_Esc)}];
                break;

            default:// allow super to handle everything else
                [result addObject:theEvent];
                break;
        }
    }

    [super interpretKeyEvents:result];

}

#pragma clang diagnostic pop

@end

For works with use:

[[NSNotificationCenter defaultCenter] addObserverForName:kNotificationTokenModifier
                                                  object:nil
                                                   queue:[NSOperationQueue currentQueue]
                                              usingBlock:^(NSNotification *note) {

                                                  BMTokenModifier modifier = (BMTokenModifier)[[[note userInfo] objectForKey:kNotificationTokenModifier_modifier] integerValue];

                                                  switch (modifier) {
                                                      case BMTokenModifier_CommandEnter:
                                                          [self sendMessage];
                                                          break;

                                                      case BMTokenModifier_CommandO:
                                                          [self attachFiles];
                                                          break;

                                                      default:
                                                          break;
                                                  }
                                              }];