Callback from Array<PropertyComponent*>

Hello,
I liked the PropertiesDemo example in the Juce Demo, but stuck with the choice made of adding pointers of class DemoSliderPropertyComponent to an array of PropertyComponent*.
Could someone be kind enough to illustrate the way we can get callback from the sliders in this specific example ?

The DemoSliderPropertyComponent class in the JUCE Demo inherits from SliderPropertyComponent so you can access its protected Slider member and attach a listener to it. You’ll need to inherit from Slider::Listener and then call slider.addListener (this) in the constructor. Then implement the listener’s sliderValueChanged() method, which will be called whenever the Slider value changes.

This is clear for me. What is less clear is how to get it working in the context of the PropertiesDemo example. I would really need that for a better understanding.
In the example, demoSliderComponents are added to an array of PropertyComponent. When I create a demoSliderComponent, I can’t do slider.addListener with this newly added component.
Let’s say I do the following:
Considering displayLimits is defined like this, in order for being able to be added to the main propertyPanel with the function addSection() :

	Array<PropertyComponent*> displayLimits;

Then when I write the following code:

		DemoSliderPropertyComponent* s = new DemoSliderPropertyComponent ("Something rich and strange");
	displayLimits.add (s);
	s->addListener(this);

(‘this’ implementing Slider::Listener),
I get: “No member named addListener in DemoSliderPropertyComponent”

Well no that won’t work as DemoSliderPropertyComponent isn’t a Slider, it just contains one as a child component. If you wanted to do something like your example, you’d need to expose its Slider as a public member or have getter method then you could do:

s->slider.addListener (this);

What are you trying to achieve though? You’ll probably be better off just using a SliderPropertyComponent to control a Value object that you can listen to. So you’d have some member variables like this:

OwnedArray<PropertyComponent> propertyComponents;
Value valueToControl;

and then in your constructor:

valueToControl.addListener (this);
...
propertyComponents.add  (new SliderPropertyComponent (valueToControl, "SliderProperty", 0.0, 1.0, 0.1));

Now if your parent class inherits from Value::Listener and implements its valueChanged() method you will get a callback whenever the user moves the Slider and changes its underlying Value.

Thanks, that looks nice. However I tried the following and could not monitor any change from the Slider, could you tell where I got wrong ?:

class SettingsGUI : public Component, public Value::Listener, public Slider::Listener
{

public:
SettingsGUI()
{
	PropertyPanel*  panel = new PropertyPanel ("Project Settings");
	valueToControl.addListener(this);
	someSliders.add (new SliderPropertyComponent (valueToControl, "valueOfSomeKind", 0.0, 1.0, 0.1));
	panel->addSection("Special", someSliders, true);
}
void valueChanged (Value &value) override
{
	DBG(" valchgd: " << value.toString());
}
private:
Array<PropertyComponent*> someSliders;

};

Here is a really minimal working example:

//==============================================================================
class MainContentComponent   : public Component,
                                  private Value::Listener
{
public:
    //==============================================================================
    MainContentComponent()
    {
        valueToControl.addListener (this);
        
        sliderProps.add (new SliderPropertyComponent (valueToControl, "Slider", 0.0, 1.0, 0.01));
        propPanel.addSection ("Sliders", sliderProps);
        
        addAndMakeVisible (propPanel);
        
        setSize (600, 400);
    }
    
    ~MainContentComponent() {}

    void paint (Graphics& g) override
    {
        g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
    }
    
    void resized() override
    {
        propPanel.setBounds (getLocalBounds().reduced (5));
    }

private:
    void valueChanged (Value& v) override
    {
        DBG ("Value changed");
    }
    
    Value valueToControl;
    Array<PropertyComponent*> sliderProps;
    PropertyPanel propPanel;
    
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};

Well, thanks and sorry for my last complaint: I don’t why, but my own code was working, in fact.
While we are getting to the core of the question: how do I distinguish in this example, which slider has issued the value (if I add more sliders) ?

The valueChanged() callback is called with a reference to the Value that has been modified as its argument, so you can compare this to your Value members to determine which has changed.

Great, that worked!
I am not used to Values, so did’nt know the easiest way.
Thanks