class EightAudioProcessorEditor : public AudioProcessorEditor, public MenuBarModel, public KeyListener, public KeyPress
{
...
private:
...
AulusKnob mKnobA;
AulusDisplay mDisplay;
...
}
class AulusDisplay : public Component, public Value::Listener
{
public:
...
void valueChanged(Value& value) override;
...
AulusDisplay.cpp
...
void AulusDisplay::valueChanged(Value& value)
{
//String t = ((Component)(value.getValueSource())).getName();
DBG(value.toString().getIntValue());
// How to access the Sender here ?
// DBG(dynamic_cast<Component*>(value.operator juce::var().getObject()).getName());
// DBG((Component)(value.operator juce::var().getObject()).getName());
drawValue("Test", value.toString().getIntValue());
}
...
In the Method AulusDisplay::valueChanged() I would like to access the Sender Object which triggered the Listeners valueChanged() Method to access it’s Name or other Properties.
Here’s how you’d add that lambda member variable to your listener class.
class AulusDisplay : public Component, public Value::Listener
{
public:
...
void valueChanged(Value& value) override;
...
std::function<void(juce::Value)> lambda;
...
};
capture your Sender when you create your lambda. Here is an example capturing your Editor.
EightAudioProcessorEditor::EightAudioProcessorEditor(EightAudioProcessor& p)
: AudioProcessorEditor(&p),
processor(p),
keyboardComponent(p.keyboardState, MidiKeyboardComponent::horizontalKeyboard),
menuBar(this)
{
...
mKnobA.setName("Knob A");
mKnobA.value.addListener(&mDisplay);
addAndMakeVisible(mKnobA);
...
mDisplay.setName("Display");
mDisplay.lambda = [safePtr = Component::SafePointer<EightAudioProcessorEditor>(this)](juce::Value value) mutable
{
//do something with value and whatever else you captured in the lambda.
//your editor was captured inside a safePtr.
//you can call editor member functions from here, if you check that the editor is stil valid.
};
addAndMakeVisible(mDisplay);
...
}
@daniel do you have an alternate solution to what they’re asking to be able to do? This is the only way that I can think of. Well, you could use Listener list, but that still requires a lambda…
Thank you a lot, also Daniel! I implemented the Lambda as you wrote but I don’t see any value in that. I passed in a new Variable name to get a String Value from the Editor but it seems not to work as you wrote.
The name Variable is empty after calling the Lambda.
Thats how I implemented it:
PluginEditor.cpp
...
mDisplay.lambda = [safePtr = Component::SafePointer<EightAudioProcessorEditor>(this)](juce::Value value, juce::String name) mutable
{
if (!safePtr) return;
//do something with value and whatever else you captured in the lambda.
//your editor was captured inside a safePtr.
//you can call editor member functions from here, if you check that the editor is stil valid.
name = "1234";
};
...
If I set value inside the Lambda Function then it works for the value Variable. Wonder why it doesn’t work for the name Variable.
PluginEditor.cpp
mDisplay.lambda = [safePtr = Component::SafePointer<EightAudioProcessorEditor>(this)](juce::Value value, juce::String name) mutable
{
if (!safePtr) return;
//do something with value and whatever else you captured in the lambda.
//your editor was captured inside a safePtr.
//you can call editor member functions from here, if you check that the editor is stil valid.
name = "1234";
value = 10;
};
AulusDisplay.cpp
void AulusDisplay::valueChanged(Value& value)
{
DBG(value.toString().getIntValue()); // << Here the Value is between 1 and 127
String name = "";
if (lambda)
lambda(value, name);
DBG("Name: " + name);
drawValue("Test", value.toString().getIntValue()); // Here the Value is 10 from the lambda Function
}
I understand that the reference to the Value object doesn’t help, and also there is no access path from the Value further, because it has neither a parent link (because it is not a Component), now a user value field where information could be transported.
Generally I would avoid this kind of loose coupling, as it is often hard to maintain. When the hierarchy is recreated, you need to make sure all connections are also recreated.
Instead of listening to the Value object in the editor I would add a Value in the AulusDisplay and listen to that one. And then I would call this in the constructor of the Editor, where aulus and knobA are both known:
mDisplay.value.referTo (mKnobA.getValueObject());
and implement the Value::Listener in AulusDisplay:
That makes all listener adding simple straight forward.
@dschiller that’s nasty about VS. Xcode takes often long for that task, you wait 2-5 seconds for the auto complete sometimes, but at least they appear eventually.