About ValueTree::valueTreeChildOrderChanged

Let’s say I have ValueTree called “node”.
I listen to it’s changes with: node.addListener(this);
Then I do the following:

        node.addChild(juc::ValueTree(blah), 0, nullptr);
        node.addChild(juc::ValueTree(blah), 1, nullptr);
        node.addChild(juc::ValueTree(blah), 0, nullptr);

As expected, ValueTree::Listener::valueTreeChildAdded() gets called for each of those three rows.

However, I would assume that ValueTree::Listener::valueTreeChildOrderChanged() would get called after the last row, which adds a new child node infront of all the previous nodes. So I would assume ValueTree::Listener::valueTreeChildOrderChanged() would get called twice. But it doesn’t get called at all.

What do I don’t understand of the ValueTree’s basic behavior?

Another oddity I just noticed is the following:

    juce::ValueTree nodeA(typeAID);
    juce::ValueTree nodeB(typeBID);
    juce::ValueTree nodeC(typeCID);

    nodeA.addListener(this);

    nodeB.appendChild(nodeC, pUndoManager);
    nodeA.appendChild(nodeB, pUndoManager);

What happens is that at the last code line above ValueTree::Listener::valueTreeChildAdded() gets called as it should be. But what is weird is that it gets called twice instead of once. Both times the parameters seem to be the same:

parentTree = nodeA
childWhichHasBeenAdded = nodeB

I would expect one of the following to happen:

  1. The listener method gets called only once with the above parameters.
  2. The #1 happens and in addition also the same method gets called with nodeB and nodeC as its parameters. So the method would be called twice in total.

Is this the intended behavior or is there a bug or am I doing something wrong?

About your first question:
Adding a child at the beginning doesn’t change the order. Therefore, ValueTree::Listener::valueTreeChildOrderChanged is not called. It will be called when you explicitly change the order with ValueTree::moveChild.

About your second question:
If I run your code, it only calls ValueTree::Listener::valueTreeChildAdded once. I tested this with the code below (which is the same as your code but slightly modified).

struct Listener : juce::ValueTree::Listener
{
    void valueTreeChildAdded (juce::ValueTree &parentTree, juce::ValueTree &childWhichHasBeenAdded)
    {
        DBG("valueTreeChildAdded");
    }
};
Listener listener;

juce::ValueTree nodeA("typeAID");
juce::ValueTree nodeB("typeBID");
juce::ValueTree nodeC("typeCID");

nodeA.addListener(&listener);

nodeB.appendChild(nodeC, nullptr);
nodeA.appendChild(nodeB, nullptr);

// Output:
// valueTreeChildAdded
1 Like

OK, these helped me figure out what was wrong with my code. Thanks!

Regarding the first question:
I thought “order changed” was the same as “child index changed”, but those are actually conceptually two different things. Makes sense now.

Regarding the second question:
I found an extra addListener(this) to a parent ValueTree from my code. So the same class was registered as a listener to two different hierarchy levels for the ValueTrees. That’s what caused the weirdness.