summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-09-07 06:50:34 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-09-07 06:50:34 +0300
commitc58c46c96cf490a1d585a28560dda138479f00be (patch)
treee8bda26590b69c5f2fd631ae9bde36c8621b8f79 /src/ui
parenta364d9456dfdfd8181904fca6308e9c36eefd10a (diff)
LookupWidget: Improved keyboard navigation
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/listwidget.c18
-rw-r--r--src/ui/listwidget.h2
-rw-r--r--src/ui/lookupwidget.c38
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
182static int visCount_ListWidget_(const iListWidget *d) { 182void 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
194int 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 *);
59int scrollPos_ListWidget (const iListWidget *); 59int scrollPos_ListWidget (const iListWidget *);
60 60
61void setScrollPos_ListWidget (iListWidget *, int pos); 61void setScrollPos_ListWidget (iListWidget *, int pos);
62void scrollToItem_ListWidget (iListWidget *, size_t index);
62void scrollOffset_ListWidget (iListWidget *, int offset); 63void scrollOffset_ListWidget (iListWidget *, int offset);
63void updateVisible_ListWidget (iListWidget *); 64void updateVisible_ListWidget (iListWidget *);
64void updateMouseHover_ListWidget (iListWidget *); 65void updateMouseHover_ListWidget (iListWidget *);
@@ -67,6 +68,7 @@ iAnyObject *item_ListWidget (iListWidget *, size_t index);
67iAnyObject *hoverItem_ListWidget (iListWidget *); 68iAnyObject *hoverItem_ListWidget (iListWidget *);
68 69
69size_t numItems_ListWidget (const iListWidget *); 70size_t numItems_ListWidget (const iListWidget *);
71int visCount_ListWidget(const iListWidget *);
70size_t itemIndex_ListWidget(const iListWidget *, iInt2 pos); 72size_t itemIndex_ListWidget(const iListWidget *, iInt2 pos);
71const iAnyObject *constItem_ListWidget (const iListWidget *, size_t index); 73const iAnyObject *constItem_ListWidget (const iListWidget *, size_t index);
72const iAnyObject *constHoverItem_ListWidget (const iListWidget *); 74const 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
379static 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
378static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { 394static 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);