]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/menu/item/listbox.c
Merge remote-tracking branch 'origin/mirceakitsune/func_train_beizer_curve'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / listbox.c
index dc2663149e4a73a2770bebad3bd980c8065185f2..0f9502d97f022bb7c434da93aa4c6cf219e25df3 100644 (file)
@@ -47,13 +47,31 @@ CLASS(ListBox) EXTENDS(Item)
        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)
 {
@@ -106,13 +124,33 @@ float ListBox_keyDown(entity me, float key, float ascii, float shift)
        }
        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);
@@ -325,7 +363,7 @@ void ListBox_draw(entity me)
                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();