False ValueTree Listener Calls

Hello

I have recently been using ValueTrees for managing various data throughout a project of mine. I have come across a situation that is slowly driving me crazy though. Through a dialog with various control components, I am setting their values based on the ValueTree properties, and when the user “saves” this information, it writes the values into the same ValueTree properties again.

This all works fine. But I’ve noticed that three of my ValueTree properties will send a change notification through the valueTreePropertyChanged method, even though they haven’t actually changed at all! And to make things even more fun, when performing the same actions again (open dialog, set controls based on ValueTree properties, close and “save” values to same ValueTree), I only have the method called on those properties that actually did change. Basically, the only time I have this false call is on the first change.

I thought maybe I was setting the values into the ValueTree wrong, but all the controls are properly set, and debugging shows that the same values are loaded/set into the ValueTree each time. I can’t figure out what in the world might be causing this. If it matters, the properties are all bools.

Any insight into this would be extremely helpful!

1 Like

Put together an incredibly minimal example of what my code looks like, hopefully it helps me explain the problem.

// File 1
class Class1 : public Component(), public ValueTree::Listener
{
    void valueTreePropertyChanged(ValueTree &treeWhosePropertyHasChanged, const Identifier &property) override
    {
        logger->addMessage("Change to ValueTree, Identifier: " + String(property.toString()) + ", Value: " + treeWhosePropertyHasChanged.getProperty(property).toString());
    }
}
// File 2.h
class Class2 : public Component, public Button::Listener
{
public:
    void loadStateFromVT();
    void buttonClicked(Button *b) override;
private:
    OwnedArray<ToggleButton> buttons;
    ScopedPointer<TextButton> tb;
    ValueTree valueTree;
}
// File 2.cpp
void Class2::loadStateFromVT()
{
    if(valueTree.getPropertyAsValue(IdentifierForProperty, nullptr) == true) { buttons[2]->setToggleState(true, NotificationType::dontSendNotifications); }
    else { buttons[2]->setToggleState(false, NotificationType::dontSendNotifications);
}

void Class2::buttonClicked(Button *b)
{
    if(b == tb)
    {
        valueTree.setProperty(IdentifierForProperty, buttons[2]->getToggleState(), nullptr);
        getParentComponent()->exitModalState(0);
    }
}

Class2 is opened/closed through a dialog. My problem is that the property in the ValueTree that tracks the ToggleButton state, tracks it accurately, but if that property is set to FALSE, and then set to FALSE again through the ToggleButton, it still calls valueTreePropertyChanged, even though the property didn’t actually change. And again, the most odd part is that only 3 of my controls (out of around 15) are doing this, and only the first time. If I call the dialog again and change the value, it doesn’t erroneously call the change method.

Properties are stored as vars, and their initial value is obviously an empty var(), which has no type.

var v;
bool b = v; // b is false, because casting an empty var to boolean obviously returns false
v = false; // this is a change, because you're changing its type to 'bool'!
v = false; // no change this time
v = 0; // this counts as a change because again, its type changes, despite the fact that casting to bool will still still give false
v = false; // counts as a change again, because its type is changing
1 Like

Yep, that’s one thing that I made sure to check. What I didn’t check was the type that was originally being stored into the properties, it was typed as an integer rather than a bool. What’s most odd was that upon checking the var with isBool and isInt, it was still registering it as a bool. Hence my confusion.

Thanks for the fresh perspective, it’s exactly what I needed to look at this from a different angle.

1 Like