[Mono-winforms-list] New to the list
Ernesto
equistango at gmail.com
Fri Sep 7 09:17:22 EDT 2007
Jonathan Pobst wrote:
> Hey Ernesto!
>
> The changes look harmless, but I have a feeling they are simply hiding
> a bigger problem, ie: what is trying to set a scroll position bigger
> than the maximum and why. The ListView maintainer (calberto) thinks
> the same about the ListView one. Do you have a test case or code
> snippet for each of them that reproduces the crash so we can dig a bit
> a deeper?
>
Heh... yes, I have that feeling too. I just didn't want to made
design-level changes (and even if I did want, I didn't dare since this
is my first day with the winforms source code).
However, I can explain how I see the problem so you guys decide if
deeper changes are necesary.
The ListView problem:
1) When a new SubItem is added, the ListViewSubItem constructor sets the
SubItem text.
2) Text.set in the SubItem Text property calls Invalidate(Bounds).
3) Bounds.get calls GetBounds() and this calls GetItemLocation().
4) GetItemLocation() uses the items_location[] array.
Now, items_location[] is set to an initial lenght of [16] by the
ListView constructor, and extended by AdjustItemsPositionArray if needed.
AdjustItemsPositionArray is only called by CalculateListView, which is
called only before a redraw.
So, if you add a 17th item before a redraw, you get an index out of
bounds at ListView.GetItemLocation().
I think the problem here is that Invalidate() ends up usign
items_location[], which is only calculated when redrawing. That doesn't
seem to make sense sometimes, since Invalidate() happens _before_ the
redraw.
Anyway, my patch only ensures the items_location[] array grows when the
collection grows. It doesn't seem to care if items_location[] has valid
information because we are not redrawing, just invalidating.
The ScrollBar problem is much simpler.
vscrollbar.LargeChange = 0;
vscrollbar.Maximum = 100;
vscrollbar.Value = 20;
vscrollbar.Maximum = 0; // BONGGGGG!!!
It only happens if LargeChange == 0, because of this code in UpdatePos()
in ScrollBar.cs:
if (newPos > maximum + 1 - large_change)
pos = maximum + 1 - large_change;
else
pos = newPos;
For a large_change value of 5
if (20 > 0 + 1 - 5)
pos = -4;
else
pos = newPos;
and then
if (pos < minimum)
pos = minimum;
will reset pos to 0 (or wharever minimum is).
But for large_change value of 0,
if (20 > 0 + 1 - 0)
pos = maximum + 1 - large_change;
else
pos = newPos;
pos == 1, which is more than Maximum, so a SetValue (pos) a few lines
below will fail.
LargeChange values of 0 should be accepted. On the other hand "if
(newPos > maximum + 1 - large_change) pos = maximum + 1 - large_change;"
sounds correct to me, but may result in negative values that must be
corrected.
In short, I tought it was a good idea to give pos a last check before
calling SetValue(pos).
However, if you think that's not correct, and that I should find another
solution to fix UpdatePos(), I will. I just want the problem solved, you
can tell me how.
Regards,
Ernesto
More information about the Mono-winforms-list
mailing list