guitarflow
guitarflow

Reputation: 2970

Invoke NSControl's "valueChanged" when changing values programmatically

I am about to implement a simple audio fader. I subclassed NSSlider and NSSliderCell to be able to draw the graphics accordingly.

I want the slider to jump to a defined position whenever the handle is clicked with the Cmd key pressed. This is pretty common in most audio applications.

Setting the value to the slider is working flawlessly, but it does not invoke the action method to inform my target that the value changed. This must be happening somewhere in the mouseDown event handling of "super", probably in NSControl. This is what I got so far :

- (void) mouseDown:(NSEvent *)theEvent
{
    if ( ([theEvent modifierFlags] & NSCommandKeyMask) > 0)
        [self setFloatValue:100.0f];
    else
        [super mouseDown:theEvent];
}

I found a method in the NSControl doc that looks promising:

-(BOOL)sendAction:(SEL)theAction to:(id)theTarget Parameters : 

theAction : The selector to invoke on the target. If the selector is NULL, no message is sent.

theTarget : The target object to receive the message. If the object is nil, the application searches the responder chain for an object capable of handling the message. For more information on dispatching actions, see the class description for NSActionCell.

But I don't have a clue what the selector would be named like. The target would probably be super?

Any help is much appreciated!!

Best,

Flo

Upvotes: 3

Views: 1129

Answers (2)

guitarflow
guitarflow

Reputation: 2970

I found an answer myself. Although the answer of @rdelmar might also work, it won't anymore if you change the name of the action method.

I found a universal way of triggering the action method manually:

- (void) mouseDown:(NSEvent *)theEvent
{
    if ( ([theEvent modifierFlags] & NSCommandKeyMask) != 0)
    {
        [self setFloatValue:100.0f];
        [self.target performSelector:self.action withObject:self];
    }
    else
        [super mouseDown:theEvent];
}

Upvotes: 2

rdelmar
rdelmar

Reputation: 104082

The action could be the name of the action method that you already are using for your slider, and the target should be the class instance where that method is implemented. So, for example, if you had an IBAction in your app delegate that was connected to your slider called sliderReport: then do this:

[self sendAction:@selector(sliderReport:) to:[NSApp delegate]];

Additional Note: I assumed from your question that you wanted to invoke the same IBAction that you have connected to your slider, but you could send a different selector if you want -- if you need to distinguish between how the slider value was changed, having a different method would be the way to go. You can name it anything you want (with a colon on the end, so it can send itself as the sender argument if you need that).

Upvotes: 2

Related Questions