ListViewPort Update content issue


#1

Hi Julian,

 I happen to come across a problem with update method of ListViewPort. I have a listBox, and if 2 rows are displayed completely and the third row isn't displayed completely the current code would delete the components of the third row and re-create them since they are partially visible.

In void updateContents();

  const int numNeeded = 2 + getMaximumVisibleHeight() / rowHeight;           

Both getMaximumVisibleHeight() and rowHeight are integers and their division will return integer. So if two and half rows are visible, this code would assume calculate it to 2 rows and the third row will be deleted and again created.

If you change the code to this

  const int numNeeded = std::ceil( ( 2 + getMaximumVisibleHeight() ) /(float) rowHeight);

it would not delete a row if it’s partially visible.

Secondly shouldn’t there be a bracket since division has higher priority hence “getMaximumVisibleHeight()/rowHeight” would be done first and then 2 will be added.( I am assuming that 2 there is 2 pixel and not row rows)


#2

Well, no… the lack of brackets is deliberate, so for 2.5 rows, numNeeded would be 4… (?)


#3

I have realized one thing now, I need to debug my code again :shock:

If only two rows are visible, you would be making provisions for 2 extra rows, when they are not required. You could use this instead.

const int numNeeded = std::ceil( getMaximumVisibleHeight()  /(float) rowHeight); 

#4

I don’t think that works - a list with visible height of 2.5 rows can actually contain 4 items if the top one is mostly scrolled offscreen.


#5

You have a valid point there, but just for educational purpose, I was changing your code a little. and ended up adding a conditional where i check if the component is visible or not. If it’s not visible i delete the component. But I ended up have issues where two rows went missing.

int counter = 0;
  while (numNeeded < (getViewedComponent()->getNumChildComponents() - counter))
{
      Component* const rowToRemove
                    = getViewedComponent()->getChildComponent (getViewedComponent()->getNumChildComponents() - 1);

if (rowToRemove != 0L && rowToRemove->isValidComponent() &&  !rowToRemove->isVisible())
				delete rowToRemove;
else
counter++;
}
 

I don’t understand why thing went. Can you please explain to me what I have done wrong.


#6

Your logic looks bit weird there, where you use that counter variable but then always look at the last component in the list… Can’t really see what you’re trying to do.

What was the actual problem that you were first trying to solve?


#7

I have sorted out the problem. It was a issue with our code.

We have created a general UI library using juce similar to the juce demo you have created. When i was debugging my code I realized that the viewport was deleting and recreating the components in the row which were visible.

So I thought it could be some issue with juce since we use 1.39 with the UI dylib.

I tried different things and thought instead of deleting components based on calculation of visible range, why not use component visibility to decide whether to remove it or not.

And that logic didn’t work right, so thought of asking you what I have done wrong?

Back to the original problem, somebody had written the code calling
ListBox::setRowHeight and passing height as 10 and in the very next line ListBox::setRowHeight is called again with the correct height of the row.

First time too many rows were created and the second time they are deleted. Slowing down my application whenever I tried to resize it.

I didn’t realize that and thought it could be some problem with ListBox.

Sorry for raising another false alarm. :oops:


#8

I hadn’t read the entire message, now I know the reason why my code didn’t work

int counter = 0;
  while (numNeeded < (getViewedComponent()->getNumChildComponents() - counter))
{
      Component* const rowToRemove
                    = getViewedComponent()->getChildComponent (getViewedComponent()->getNumChildComponents() - 1 - counter); // this may work

if (rowToRemove != 0L && rowToRemove->isValidComponent() &&  !rowToRemove->isVisible())
            delete rowToRemove;
else
counter++;
} 

it may work now. But it’s not needed!!! :smiley: Thanks Jules you have put in a very good logic there. HATS OFF TO YOU :smiley: