Accessing ValueTree from child component - strange behaviour

I am trying to access a ValueTree strored in an object belonging to my MainContentComponent, from a component (InterfaceComponent) nested inside it.  

Within the MainContentComponent I have an instance of a class (say MyClass) which contains a ValueTree,

 

I've declared a pointer in the InterfaceComponent as: 

MainContentComponent* main;

In the InterfaceComponent constructor I've defined:

main = static_cast<MainContentComponent*>(getTopLevelComponent());

However, if I try and access the ValueTree using the pointer

ValueTree valueTree = main->myClass.valueTree;
log->writeToLog("numChildren:"+String(valueTree.getNumChildren()));

It seems to not be initialised,  even though it passes the isValid() function - getNumChildren() returns a large random value (e.g. 27888).

I've just rearranged some code and it looks like the InterfaceComponent constructor is called before the MainContentComponent one, so that the object I am trying to share has not been initialised when the nested Component is trying to access it. I would expect the ValueTree to not be valid in this case.

Perhaps I am going about this a strange way, basically just want a way of sharing data across components. 

That wont fly, at least not elegantly

Use composition

childComponent.setValueTree(ValueTree* treeToSet);

and then just use that pointer

Dont forget to initialize properly either to the right value tree in the constructor, or to a nullptr if you are putting it later

Thanks, I have changed it around so that I am setting it via

getChildComponent(0)->setValueTree(&myClass.valueTree)

This is working. I can test that the ValueTree is as it should be from the setValueTree function of the childComponent (InterfaceComponent).

The InterfaceComponent has a pointer, ValueTree* valueTree, which is set to nullptr at the constructor:

InterfaceComponent::InterfaceComponent () : valueTree(nullptr)  

InterfaceComponent also inherits Value::Listener, to update a GUI element with incoming values.

For a reason I cannot work out, the InterfaceComponent::valueChanged override function says the valueTree is nullptr, even though the log output says it has been previously initialised by the setValueTree function (which shows correct output).     

 

 

Don't use pointers to ValueTrees!

They have value semantics, and although you might sometimes want to pass them by reference, there's almost never a good reason to take a pointer to one.

Ok, thanks, I did try without and was getting similar behaviour, i.e. the ValueTree having random values when called from the valueChanged function... I'll take out the pointer and report back.

OK - I have now taken out the pointer to the ValueTree, but the problem remains - the valueChanged function gets an invalid (empty) ValueTree where it has been set and tested to be valid in the setValueTree function, which is called before the valueChanged function as I can see in the log output.. 

Code for clarity: 

InterfaceComponent constructor

InterfaceComponent::InterfaceComponent () : valueTree(ValueTree()) {...}

ValueTree declaration, InterfaceComponent.h 

ValueTree valueTree;


InterfaceComponent.cpp

void InterfaceComponent::setValueTree (ValueTree& treeToSet)
{

    valueTree = treeToSet;

    log->writeToLog("Interface.valueTree.numChildren:"+String(valueTree.getNumChildren()));

}

void InterfaceComponent::valueChanged(juce::Value &value)

{

    if (value.refersToSameSourceAs(currentValue))

    {

        ...
            log->writeToLog("Interface.valueTree.valueChanged.numChildren:"+String(valueTree.getNumChildren()));

            if (valueTree.isValid())
            {
                ...
            }
            else
            {
                log->writeToLog ("noteTree invalid");
            }

    }

}


From MainComponent.cpp constructor:

    static_cast<InterfaceComponent*>(getChildComponent(0)->setValueTree(myClass.noteTree);

Output from console log:

Interface.noteTree.numChildren:55

noteTree(MainComponent).numChildren:55

Interface.noteTree.valueChanged.numChildren:0

noteTree invalid

Interface.noteTree.valueChanged.numChildren:0

noteTree invalid  ...

 

Sorry guys, I oversimplified the code I posted, and actually the problem was a nullptr to the InterfaceComponent, as it is nested inside a TabbedComponent, and I wasn't checking for nullptr before calling the method  - I changed static_cast to dynamic and followed how its done in Introjucer, using jassert to make sure, and then discovered the getTabContentComponent function which was what I needed to get at the necessary component. 

Hope I have not cluttered the forum with my debugging,  Jules feel free to delete thread in case it confuses people searching in future...