Observer pattern for ListBox and ListBoxModel

I am missing an option to send a changed from a ListBoxModel to (all) connected ListBoxes.
Whenever my model changes, I find myself hacking around adding ChangeListeners or redundant references, just to call ListBox::updateContent() or ListBox::resized() to force updates.

Is there something, that I overlooked? Otherwise it would be great, if an internal ListenerList could be added to the ListBoxModel. It could act completely under the hood, no need to add a public ListBoxModel::Listener or something.

(I saw this old thread, but I think there are better solutions)

I have always wondered as well why there is no default fireHasChanged in ListBoxModel that ListBox would listen to by default using some kind of ListBoxModelListener

Slight bump.

Usually I add ChangeBroadcaster to my ListBoxModel, but I still need to inherit ListBox to be a ChangeListener which calls updateContent(). Would be nice, if a ListBox could do that out of the box, since it already has a connection via setModel().

2 Likes

wondering where you send out the changeBroadcaster message from ListBoxModel in this? I am having trouble register listBoxItemClicked while using custom list items. i.e. If I define a custom listComponent through refreshComponentForRow the listBoxItemClicked function never executes.

When I create the custom component in refreshComponentForRow(), I supply a backlink as reference.

Untested example:

class MyCustomComponent : public juce::Component
{
  public:
    MyCustomComponent (MyModel& model) : owner (model) {}
    void setData (MyRow& rowToUse)
    {
        data = rowToUse;
    }

    void mouseDown (const juce::MouseEvent& e) override
    {
        // do what is necessary

        owner.sendChangeMessage();
    }

  private:
    MyModel& owner;
    MyRow&   data;
};

// === in model ===
juce::Component* MyModel::refreshComponentForRow (int rowNumber, bool isSelected, juce::Component* c)
{
    auto* myComponent = dynamic_cast<MyCustomComponent*>(c);
    if (!myComponent)
    {
        delete (c);
        myComponent = new MyCustomComponent (*this);
    }
    myComponent->setData (rows[rowNumber]); // or anything to update the component data
}

thanks this code snippet was very helpful!