4
votes

I need a NSButton that gives me 2 events, one when the button is pressed down (NSOnState) and one when the button is released (NSOffState) and so far i've got it working with the mouse (intercepting the mouseDown: event). But using a keyboard shortcut doesn't work, it fires a NSOnState once and then after a delay really often. Is there any way to get a button that fires NSOnState when pressed and NSOffState when released?

My current subclass of NSButton looks like this and unfortunately works using a delegate:

-(void)awakeFromNib {
    [self setTarget:self];
    [self setAction:@selector(buttonAction:)];
}

-(void)mouseDown:(NSEvent *)theEvent {
    [_delegate button:self isPressed:YES];
    [super mouseDown:theEvent];
}

-(void)buttonAction:(id)sender {
    [_delegate button:self isPressed:NO];
}
1

1 Answers

6
votes

The button can be set to send mouse events at both times by using -sendActionOn::

[self.button sendActionOn: NSLeftMouseDownMask | NSLeftMouseUpMask];

Handling keyboard events similarly seems more difficult. If you don't need the event exactly at the same time the highlight is removed from the button, you could override NSButton's -performKeyEquivalent: so that it will e.g. send the action twice.

- (BOOL) performKeyEquivalent: (NSEvent *) anEvent
{
    if ([super performKeyEquivalent: anEvent])
    {
        [self sendAction: self.action to: self.target];
        return YES;
    }
    return NO;
}

If you do need the event at the same time, I think you need to use a custom button cell (by creating a subclass of NSButtonCell and setting the button's cell in the initializer) and override its -highlight:withFrame:inView::

- (void)highlight:(BOOL)flag
        withFrame:(NSRect)cellFrame
           inView:(NSView *)controlView
{
    [super highlight: flag withFrame:cellFrame inView:controlView];

    if (flag)
    {
        // Action hasn't been sent yet.
    }
    else
    {
        // Action has been sent.
    }
}