Help wanted: How to deal with ListBox row components?


#1

The task is to fill a ListBox component with some numbered custom row components that can be changed, added and removed dynamically.
The JUCE demo code is not suitable for my purposes as the specimen.
The following code samples explain the steps I create and manage my ListBox component:

[list]1) I derive MyListBox class from ListBox and ListBoxModel classes;
2) I declare a class member «Array<MyComponent*> m_Carts» to refer to each row component directly later on (e.g. to change a button text or set some value for its sub components).
3) I use the «void addToContent(String sFilePath, bool bUpdateContent = true)» class member function to add and update the MyListBox component with the following code:[/list]

[code]void MyListBox::addToContent(String sFilePath, bool bUpdate)
{
m_Carts.add(new MyComponent(sFilePath, m_Carts.size()));

if(bUpdate)
	updateContent();

}

int MyListBox::getNumRows()
{
return m_Carts.size();
}[/code]

[list]4) I override the «refreshComponentForRow» virtual function in the following maner:[/list]

[code]Component *MyListBox::refreshComponentForRow(int rowNumber, bool isRowSelected, Component *existingComponentToUpdate)
{
if(!existingComponentToUpdate)
{
if(rowNumber < m_Carts.size())
return m_Carts[rowNumber];
}

return existingComponentToUpdate;

}[/code]

[list]5) Each row component is numbered and must follow in ascending order but… after running my application and filling the MyListBox component with 25 test rows, I’ve seen the following surprising results:[/list]

[list][/list]

What must I do to get the result I want?
Am I doing something in a wrong way?


#2

Yes - it does explain all this in the comments for refreshComponentForRow. As the title suggests, you need to actually refresh the component for that row - i.e. by telling it that it’s now been assigned to a different row.

And you can’t keep a list of components yourself, as each one needs to be able to represent any row of the table. Plus, as it explains in the comments, the ListBox will delete those components whenever it feels like it, so you’ll be left with a list of dangling pointers…


#3

Julian. Ok, I’ve expected the answer like that. Implementing this way is not suitable for my purposes. To refresh every row component to make it reflect a new row number is not that simple in my situation. Beside changing the number of a row, I have to reopen a different file instead of that a row currently holds open, reanalyze it, then to produce many time consuming tasks to reflect the state of the new numbered row component and many other inconveniences (e.g. I cannot stop playing unexpectedly if the current row plays a sound at the time it must be refreshed to reflect a new state or even worse it’s going to be deleted at the moment). This is why it is important for me to create a row component at once and to keep it alive till it’s needed. Every row is a self-sufficient and independent component in my instance. I just want to scroll them vertically. That’s all.

Is it possible to implement exactly this behaviour in JUCE easily by using a different component class or any other means? ScrollView or something?


#4

you could do this even simply by using the ViewPort component… just create one, and setViewedComponent… and you’ll be able to scroll in both directions !


#5

If I was writing it, I’d use a special object for each item, containing all the info it needs, and managing the item’s state. Then the row components could just connect to the item object they need. That’s a much neater model/view architecture. Also, storing component objects for items that are off-screen is a waste of memory.

Or as a quick fix, you could also just stick your components inside a simple row component, of course.


#6

You’re absolutely right, Julian. I must review my code to make changes.

Thanks, kraken. I’ll try it too.


#7

Thanks. I had a similar misunderstanding, and in one place, had cached ‘where’ the component was to avoid updating it. But more to the point, I uncovered a bug I had where I was letting the passed in component get passed out, when I meant the cell to be blank.

Bruce


#8