How to programmatically toggle ToggleButtons?


#1

What is the right way to toggle a ToggleButton in software?
Here is what I tried unsuccessfully:

std::unique_ptr muteToggleButton;

muteToggleButton.reset (new ToggleButton (“MuteToggleButton”));
addAndMakeVisible (muteToggleButton.get());


bool getMute() {
return muteToggleButton.get()->getToggleState();
}

void setMute(bool b) {
if (b != getMute()) {
muteToggleButton.get()->triggerClick();
}
}

Basically I want to automatically mute in situations likely to have acoustic feedback.

Thanks for any tips!

  • Julius

#2

It occurs to me that perhaps the problem is that the click is triggered asynchronously. Maybe this is the Right Thing?:

void setMute(bool b) {
if (b != getMute()) {
muteToggleButton.get()->setToggleState(b,sendNotificationSync);
}
}

It seems to be working…


#3

Hi Julius!

Yes, that’s right, just call setToggleState().

triggerClick() is handy when you want the GUI to flash a button to show it being clicked, but it will be async. So it’s not really very useful for toggle buttons, more for single-push ones.

You probably don’t actually need to add the boilerplate -

void setMute(bool b) {
    muteToggleButton->setToggleState(b,sendNotificationSync);
}

would do the same thing.

…however, it does worry me that it looks like you’re approaching things the wrong way round. You really want your GUI to follow any changes to your underlying data model, not to be relying on a callback from a GUI class to make something happen. Hopefully that’s what you’re really doing, but from your example it looks suspicious!

The robust way to implement a setMute() function would be for it to modify whatever your actual data model’s mute flag is, but it shouldn’t have any knowledge of GUI components (which may or may not even exist). Instead, any GUI objects would listen for changes to the model and do something in response like e.g. muteButton->setToggleState (isCurrentlyMuted(), dontSendNotification); to keep themselves up to date when the model changes.

Loads of people get this wrong, which is one reason we recommend the AudioProcessorValueTreeState - it forces you to keep the data model in a ValueTree, so you can just connect a value to e.g. a toggle button and the two will magically keep themselves in sync.


#4

Hi Jules!

Thanks for your orientation.

I thought I should follow the principle of having each state variable in only one place, and since the ToggleButton holds its own bit of state, I thought that the “model” had to be in there. The Faust world uses stateless GUI objects, so that all GUI and DSP state is held in the dsp class, and any number of UI classes can be “built” to obtain pointers directly to the state variables in the dsp class (corresponding to slider values and such). I will now read up on AudioProcessorValueTreeState . . .


#5

Sounds like you know what you’re doing then! If you already have a lot of code then converting to AudioProcessorValueTreeState is probably more hassle than it’s worth, but we like to recommend it for new projects.


#6

Usually I know what I’m trying to do. :slight_smile:
Thanks again!


#7

AudioProcessorValueTreeState looks very nice!
Can it be used with AudioAppComponent as well as with an AudioProcessor? While I’ve already implemented my GUI wiring, this could be a shortcut to saving/restoring XML preset files. It looks like ValueTree alone might be enough for this purpose.


#8

Well, yes, I guess you could use it like that. Certainly that’s the kind of task that ValueTree is really good for, whether or not you use the AudioProcessorValueTreeState around it.