ListBoxModel::refreshComponentForRow


#1

If I'm understanding [url=http://learn.juce.com/doc/classListBoxModel.php#af049aa731e43557c107b1285ca7e3d88]the documentation[/url] right, particularly this line: "If you do want a custom component, and the existingComponentToUpdate is null, then this method must create a suitable new component and return it." My only option for using a component in a ListBoxModel is to call

myListBoxModel->refreshComponentForRow(someRowNumber, false, nullptr);

and let the Model generate a component for me. I can't pass it a component that I created because "If the existingComponentToUpdate is non-null, it will be a pointer to a component previously created by this method. In this case, the method must either update it to make sure it's correctly representing the given row (which may be different from the one that the component was created for), or it can delete this component and return a new one."

My subclass of ListBoxModel also can't use alternative methods of tracking the lifetime of the component either, because "The component that your method returns will be deleted by the ListBox when it is no longer needed."

--

This is what I *want* to have: I want to make a component that can display a scrollable list of juce::BooleanPropertyComponents. Technically, the list will be comprised of some objects of class A and some of class B, where A and B both inherit from juce::BooleanPropertyComponents. At first I tried drawing them directly to a component, but that's not scrollable. Then I tried putting them in a viewport, but that seems to only support one component at a time. Then I tried putting them all on one component and putting that inside a viewport, but nothing showed up at all.

So now I'm looking at inheriting from ListBoxModel again, but I'm not sure how to go about the implementation details.

If there's a simpler way to get what I want, please do share. I'm very new to the JUCE library and there's still a lot I haven't used or read about (I just started this project about a week ago).


#2

I just learned that last week, so it's not necessarily the best method, but that approach worked for me:

My component has a pointer (WeakReference) to "the thing" in my model. This reference can be set in a setter method (I called it "setComponentReference" or is set in the constructor. To access "the thing" by rownumber I called the method "referenceBy(rownumber)".

When the ListBox wants to display the component, it calls your refreshComponentForRow. Either it has a nullptr, so you create you create your custom component and return it. If there is already a component I try to cast it into my custom component. If it works, I update the data in the component according to the given rownumber. If the cast doesn't work (i.e. returns nullptr), I delete the component and create a new one of my custom component type and return it.

Component* MyListBoxModelModel::refreshComponentForRow(int  rowNumber,
                                                       bool isRowSelected,
                                                       Component * existingComponentToUpdate )
{
    if (existingComponentToUpdate!=nullptr) {
        if (MyComponent* component = dynamic_cast<MyComponent*>(existingComponentToUpdate)) {
            component->setComponentReference (referenceBy (rowNumber));
            return component;
        }
        delete existingComponentToUpdate;
    }
    existingComponentToUpdate = new MyComponent (referenceBy (rowNumber));
    return existingComponentToUpdate;
}

Hope that helps, daniel


#3

So, if I am following this correctly, you're storing the components (we'll call them ImplComponent) in your model. Then the Component * (we'll call it DisplayComponent) that is used to do the displaying stores a weak pointer to the ImplComponent it gets from the model? But you still have to dynamically create the DisplayComponents? That seems a little unsatisfactory to me, and not very exception-safe. But If it's what I have to do, I'll do it.

 

JUCE team, if you had a better usage methodology in mind for this type of situation, please let us know.