diff options
-rw-r--r-- | src/ui/listwidget.c | 18 | ||||
-rw-r--r-- | src/ui/listwidget.h | 2 | ||||
-rw-r--r-- | src/ui/lookupwidget.c | 38 |
3 files changed, 39 insertions, 19 deletions
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c index 06689023..3e7203b8 100644 --- a/src/ui/listwidget.c +++ b/src/ui/listwidget.c | |||
@@ -179,8 +179,20 @@ void scrollOffset_ListWidget(iListWidget *d, int offset) { | |||
179 | } | 179 | } |
180 | } | 180 | } |
181 | 181 | ||
182 | static int visCount_ListWidget_(const iListWidget *d) { | 182 | void scrollToItem_ListWidget(iListWidget *d, size_t index) { |
183 | return iMin(height_Rect(innerBounds_Widget(constAs_Widget(d))) / d->itemHeight + 2, | 183 | const iRect rect = innerBounds_Widget(as_Widget(d)); |
184 | int yTop = d->itemHeight * index - d->scrollY; | ||
185 | int yBottom = yTop + d->itemHeight; | ||
186 | if (yBottom > height_Rect(rect)) { | ||
187 | scrollOffset_ListWidget(d, yBottom - height_Rect(rect)); | ||
188 | } | ||
189 | else if (yTop < 0) { | ||
190 | scrollOffset_ListWidget(d, yTop); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | int visCount_ListWidget(const iListWidget *d) { | ||
195 | return iMin(height_Rect(innerBounds_Widget(constAs_Widget(d))) / d->itemHeight, | ||
184 | (int) size_PtrArray(&d->items)); | 196 | (int) size_PtrArray(&d->items)); |
185 | } | 197 | } |
186 | 198 | ||
@@ -189,7 +201,7 @@ static iRanges visRange_ListWidget_(const iListWidget *d) { | |||
189 | return (iRanges){ 0, 0 }; | 201 | return (iRanges){ 0, 0 }; |
190 | } | 202 | } |
191 | iRanges vis = { d->scrollY / d->itemHeight, 0 }; | 203 | iRanges vis = { d->scrollY / d->itemHeight, 0 }; |
192 | vis.end = iMin(size_PtrArray(&d->items), vis.start + visCount_ListWidget_(d)); | 204 | vis.end = iMin(size_PtrArray(&d->items), vis.start + visCount_ListWidget(d) + 1); |
193 | return vis; | 205 | return vis; |
194 | } | 206 | } |
195 | 207 | ||
diff --git a/src/ui/listwidget.h b/src/ui/listwidget.h index 72b7dba4..29140c59 100644 --- a/src/ui/listwidget.h +++ b/src/ui/listwidget.h | |||
@@ -59,6 +59,7 @@ int itemHeight_ListWidget (const iListWidget *); | |||
59 | int scrollPos_ListWidget (const iListWidget *); | 59 | int scrollPos_ListWidget (const iListWidget *); |
60 | 60 | ||
61 | void setScrollPos_ListWidget (iListWidget *, int pos); | 61 | void setScrollPos_ListWidget (iListWidget *, int pos); |
62 | void scrollToItem_ListWidget (iListWidget *, size_t index); | ||
62 | void scrollOffset_ListWidget (iListWidget *, int offset); | 63 | void scrollOffset_ListWidget (iListWidget *, int offset); |
63 | void updateVisible_ListWidget (iListWidget *); | 64 | void updateVisible_ListWidget (iListWidget *); |
64 | void updateMouseHover_ListWidget (iListWidget *); | 65 | void updateMouseHover_ListWidget (iListWidget *); |
@@ -67,6 +68,7 @@ iAnyObject *item_ListWidget (iListWidget *, size_t index); | |||
67 | iAnyObject *hoverItem_ListWidget (iListWidget *); | 68 | iAnyObject *hoverItem_ListWidget (iListWidget *); |
68 | 69 | ||
69 | size_t numItems_ListWidget (const iListWidget *); | 70 | size_t numItems_ListWidget (const iListWidget *); |
71 | int visCount_ListWidget(const iListWidget *); | ||
70 | size_t itemIndex_ListWidget(const iListWidget *, iInt2 pos); | 72 | size_t itemIndex_ListWidget(const iListWidget *, iInt2 pos); |
71 | const iAnyObject *constItem_ListWidget (const iListWidget *, size_t index); | 73 | const iAnyObject *constItem_ListWidget (const iListWidget *, size_t index); |
72 | const iAnyObject *constHoverItem_ListWidget (const iListWidget *); | 74 | const iAnyObject *constHoverItem_ListWidget (const iListWidget *); |
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c index fbb5d365..c1c52708 100644 --- a/src/ui/lookupwidget.c +++ b/src/ui/lookupwidget.c | |||
@@ -372,9 +372,25 @@ static void setCursor_LookupWidget_(iLookupWidget *d, size_t index) { | |||
372 | item->listItem.isSelected = iTrue; | 372 | item->listItem.isSelected = iTrue; |
373 | invalidateItem_ListWidget(d->list, d->cursor); | 373 | invalidateItem_ListWidget(d->list, d->cursor); |
374 | } | 374 | } |
375 | scrollToItem_ListWidget(d->list, d->cursor); | ||
375 | } | 376 | } |
376 | } | 377 | } |
377 | 378 | ||
379 | static iBool moveCursor_LookupWidget_(iLookupWidget *d, int delta) { | ||
380 | const int dir = iSign(delta); | ||
381 | size_t cur = d->cursor; | ||
382 | size_t good = cur; | ||
383 | while (delta && ((dir < 0 && cur > 0) || (dir > 0 && cur < numItems_ListWidget(d->list) - 1))) { | ||
384 | cur += dir; | ||
385 | if (!item_LookupWidget_(d, cur)->listItem.isSeparator) { | ||
386 | delta -= dir; | ||
387 | good = cur; | ||
388 | } | ||
389 | } | ||
390 | setCursor_LookupWidget_(d, good); | ||
391 | return delta == 0; | ||
392 | } | ||
393 | |||
378 | static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { | 394 | static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { |
379 | iWidget *w = as_Widget(d); | 395 | iWidget *w = as_Widget(d); |
380 | const char *cmd = command_UserEvent(ev); | 396 | const char *cmd = command_UserEvent(ev); |
@@ -431,29 +447,19 @@ static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { | |||
431 | setFocus_Widget(url); | 447 | setFocus_Widget(url); |
432 | return iTrue; | 448 | return iTrue; |
433 | case SDLK_UP: | 449 | case SDLK_UP: |
434 | for (;;) { | 450 | if (!moveCursor_LookupWidget_(d, -1)) { |
435 | if (d->cursor == 0) { | 451 | setCursor_LookupWidget_(d, iInvalidPos); |
436 | setCursor_LookupWidget_(d, iInvalidPos); | 452 | setFocus_Widget(url); |
437 | setFocus_Widget(url); | ||
438 | break; | ||
439 | } | ||
440 | setCursor_LookupWidget_(d, d->cursor - 1); | ||
441 | if (!item_LookupWidget_(d, d->cursor)->listItem.isSeparator) { | ||
442 | break; | ||
443 | } | ||
444 | } | 453 | } |
445 | return iTrue; | 454 | return iTrue; |
446 | case SDLK_DOWN: | 455 | case SDLK_DOWN: |
447 | while (d->cursor < numItems_ListWidget(d->list) - 1) { | 456 | moveCursor_LookupWidget_(d, +1); |
448 | setCursor_LookupWidget_(d, d->cursor + 1); | ||
449 | if (!item_LookupWidget_(d, d->cursor)->listItem.isSeparator) { | ||
450 | break; | ||
451 | } | ||
452 | } | ||
453 | return iTrue; | 457 | return iTrue; |
454 | case SDLK_PAGEUP: | 458 | case SDLK_PAGEUP: |
459 | moveCursor_LookupWidget_(d, -visCount_ListWidget(d->list) + 1); | ||
455 | return iTrue; | 460 | return iTrue; |
456 | case SDLK_PAGEDOWN: | 461 | case SDLK_PAGEDOWN: |
462 | moveCursor_LookupWidget_(d, visCount_ListWidget(d->list) - 1); | ||
457 | return iTrue; | 463 | return iTrue; |
458 | case SDLK_HOME: | 464 | case SDLK_HOME: |
459 | setCursor_LookupWidget_(d, 1); | 465 | setCursor_LookupWidget_(d, 1); |