Pergunta

I wanted to be able to set the keyEquivalent of an NSMenuItem based on an NSString, e.g. : CMD+R, ALT+SHIFT+D, etc

For this, I created a method in an NSString category as following (debugging NSLogs included) :

- (NSDictionary*)toKeyEquivalent
{
    NSMutableDictionary* result = [NSMutableDictionary dictionary];

    NSArray* parts = [self componentsSeparatedByString:@"+"];

    NSLog(@"parts :%@",parts);

    if ([[parts objectAtIndex:0] isEqualToString:@""])
    {
        return [NSDictionary dictionaryWithObjectsAndKeys:@"",@"key",[NSNumber numberWithInt:0],@"mask", nil];
    }
    else
    {
        [result setValue:[parts lastObject] forKey:@"key"];

        int mask = 0;

        for (NSString* p in parts)
        {
            if ([p isEqualToString:@"CMD"])
            {
                NSLog(@"cmd");
                mask |= NSCommandKeyMask;
            }
            else if ([p isEqualToString:@"SHIFT"])
            {
                NSLog(@"shift");
                mask |= NSShiftKeyMask;
            }
            else if ([p isEqualToString:@"CTRL"])
            {
                NSLog(@"ctrl");
                mask |= NSControlKeyMask;
            }
            else if ([p isEqualToString:@"ALT"])
            {
                NSLog(@"alt");
                mask = NSAlternateKeyMask;
            }
        }

        [result setValue:[NSNumber numberWithInt:mask] forKey:@"mask"];

        return result;
    }
}

Now, I'm testing that using CMD+R.

The NSLog output is :

2012-04-03 10:36:19.051 App[4654:903] parts :( CMD, R )

2012-04-03 10:36:19.052 App[4654:903] cmd

2012-04-03 10:36:19.052 App[4654:903] keyEq : { key = R; mask = 1048576; } - for Run

Which looks good; mask=1048576 means 1<<20 which is equal to NSCommandKeyMask.

In other words, it SEEMS as if the Key Equivalent (Command-R) has been correctly interpreted.

The weird thing, though, is that when the menu item finally appears, the Key Equivalent appearing next to is "Command-SHIFT-R".... :-S

Why is that? Any ideas?

Foi útil?

Solução

Did you pass in r or R? I think if you pass it an upper case string, it automatically adds the shift requirement.

Outras dicas

Sounds like you're passing an uppercase letter to setKeyEquivalent:. The docs have this to say:

Discussion
This method considers the case of the letter passed to determine if it has a Shift modifier added. That is, [item setKeyEquivalent:@"w"] sets the key equivalent to Command-w, while [item setKeyEquivalent:@"W"] is Command-Shift-w.

You'll need to do a bit more processing on the entered string, and make sure that the letter is lowercase if "SHIFT" isn't present.

You should also (eventually) consider being more liberal in your accepted input -- this code won't work if the input is "Shift" or "shift", both of which are reasonable variations.

I also think that you have a bug/typo: your assignment to mask in the "Alt" key branch seems to be missing the OR:

mask = NSAlternateKeyMask;
// should be mask |= NSAlternateKeyMask;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top