Hello!
I suspect the answer might be no, but I’ll try anyway. Is there a way to enforce the order of listener callbacks if a class inherits from multiple listeners?
I have a preset manager UI component that inherits from ComboBox::Listener to display items based on changes to the ComboBox used for selecting presets by overriding comboBoxChanged(). I am now adding inheritance from Slider::Listener to display a * next to the preset name when any slider is moved after loading the preset by overriding sliderValueChanged().
Due to the order in which comboBoxChanged() and sliderValueChanged() are called, things aren’t working properly. If I load a new preset, comboBoxChanged() is called, followed by a call to sliderValueChanged() for each slider, causing the * to be added even when loading a new preset.
I tried adding logic to handle this, but nothing seems to work well. Changing the callback order would simplify things.
I also tried going through the ValueTree + ChangeBroadcaster + ChangeListener route, but encountered similar issues and experienced too much delay between a slider change and the * appearing.
Thanks!
I stay out of the “enforce order”, I also suspect no. You should never rely on a specific order.
But when you set the comboBox.setCurrentId or slider.setValue() from restoring the preset, how about setting it with this flag
slider.setValue (restoredValue, juce::dontSendNotification);
This should stop the circle…
I don’t explicitly call each slider’s setValue() when loading a preset, but simply load a new ValueTree from the preset file (via juce::ValueTree::fromXml()) and then replace my AudioProcessorValueTreeState’s state via replaceState().
A bit off topic: if you rely on sliderValueChanged(), how can you tell whether * should be added when you re-open the editor?
Perhaps you can compare whether the whole APVTS state is equal to the one from the preset.
ah ok, makes sense.
I can see two pragmatic solutions:
- add a flag which is set while restoring a preset, which avoids setting the dirty flag (use ScopedValueSetter)
- reset the dirty flag once you are done restoring
Blowing a bit in @zsliu98 's horn: maybe you should rather listen to parameter changes than from the GUI, when automation, a control surface or anything else changes the values, I think the user would expect the dirty flag as well…?
Yeah that won’t work. I compared the behaviour to some competitors and noticed they also don’t recall the * if the preset was saved while changed. I can live with that.
Maybe. I tried involving the ValueTree and the behaviour was too slow.
I tried using a very simple flag, but the logic was not very trivial because of the callbacks order: the last sliderValueChanged() call would need to know to reset the flag. I can probably come up with some solution around this, just wanted to investigate if there was an easier way with the callbacks order.
If not for the slow response I get when involving the ValueTree I’d also prefer that solution. Automation/control surface wise everything seems to work as I want even by just involving the sliders though.