METHOD(ListBox, getItemAtPos, float(entity, float))
METHOD(ListBox, getItemStart, float(entity, float))
METHOD(ListBox, getItemHeight, float(entity, float))
+ // NOTE: if getItemAt* are overridden, it may make sense to cache the
+ // start and height of the last item returned by getItemAtPos and fast
+ // track returning their properties for getItemStart and getItemHeight.
+ // The "hot" code path calls getItemAtPos first, then will query
+ // getItemStart and getItemHeight on it soon.
+ // When overriding, the following consistency rules must hold:
+ // getTotalHeight() == SUM(getItemHeight(i), i, 0, me.nItems-1)
+ // getItemStart(i+1) == getItemStart(i) + getItemHeight(i)
+ // for 0 <= i < me.nItems-1
+ // getItemStart(0) == 0
+ // getItemStart(getItemAtPos(p)) <= p
+ // if p >= 0
+ // getItemAtPos(p) == 0
+ // if p < 0
+ // getItemStart(getItemAtPos(p)) + getItemHeight(getItemAtPos(p)) > p
+ // if p < getTotalHeigt()
+ // getItemAtPos(p) == me.nItems - 1
+ // if p >= getTotalHeight()
ENDCLASS(ListBox)
#endif
#ifdef IMPLEMENTATION
void ListBox_setSelected(entity me, float i)
{
- me.selectedItem = floor(0.5 + bound(0, i, me.nItems - 1));
+ me.selectedItem = bound(0, i, me.nItems - 1);
}
void ListBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
{
}
else if(key == K_PGUP || key == K_KP_PGUP)
{
- me.scrollPos = max(me.scrollPos - 1, 0);
- me.setSelected(me, min(me.selectedItem, me.getLastFullyVisibleItemAtScrollPos(me, me.scrollPos)));
+ float i = me.selectedItem;
+ float a = me.getItemHeight(me, i);
+ for(;;)
+ {
+ --i;
+ if (i < 0)
+ break;
+ a += me.getItemHeight(me, i);
+ if (a >= 1)
+ break;
+ }
+ me.setSelected(me, i + 1);
}
else if(key == K_PGDN || key == K_KP_PGDN)
{
- me.scrollPos = min(me.scrollPos + 1, me.getTotalHeight(me) - 1);
- me.setSelected(me, max(me.selectedItem, me.getFirstFullyVisibleItemAtScrollPos(me, me.scrollPos)));
+ float i = me.selectedItem;
+ float a = me.getItemHeight(me, i);
+ for(;;)
+ {
+ ++i;
+ if (i >= me.nItems)
+ break;
+ a += me.getItemHeight(me, i);
+ if (a >= 1)
+ break;
+ }
+ me.setSelected(me, i - 1);
}
else if(key == K_UPARROW || key == K_KP_UPARROW)
me.setSelected(me, me.selectedItem - 1);
absSize = boxToGlobalSize(relSize, me.size);
draw_scale = boxToGlobalSize(relSize, oldscale);
me.drawListBoxItem(me, i, absSize, (me.selectedItem == i));
- y += absSize_y;
+ y += relSize_y;
}
draw_ClearClip();