diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-22 11:57:08 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-22 11:57:08 +0300 |
commit | 6c9914b729a8e020b44018bcc3aa950c8322b313 (patch) | |
tree | 8e87e140f0882d4aac7efd9ea37141730e5d3837 /src/ui | |
parent | c56870ab69b71887d703f51881c26ac79f4b7969 (diff) |
ListWidget: Use SmoothScroll
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/documentwidget.c | 14 | ||||
-rw-r--r-- | src/ui/listwidget.c | 72 | ||||
-rw-r--r-- | src/ui/listwidget.h | 2 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 5 |
4 files changed, 63 insertions, 30 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 1298dda9..853c25a9 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -3687,19 +3687,15 @@ static void drawMedia_DocumentWidget_(const iDocumentWidget *d, iPaint *p) { | |||
3687 | 3687 | ||
3688 | static void drawPin_(iPaint *p, iRect rangeRect, int dir) { | 3688 | static void drawPin_(iPaint *p, iRect rangeRect, int dir) { |
3689 | const int pinColor = tmQuote_ColorId; | 3689 | const int pinColor = tmQuote_ColorId; |
3690 | const int height = height_Rect(rangeRect); | 3690 | const int height = height_Rect(rangeRect); |
3691 | iRect pin; | 3691 | iRect pin; |
3692 | if (dir == 0) { | 3692 | if (dir == 0) { |
3693 | pin = (iRect){ | 3693 | pin = (iRect){ add_I2(topLeft_Rect(rangeRect), init_I2(-gap_UI / 4, -gap_UI)), |
3694 | add_I2(topLeft_Rect(rangeRect), init_I2(-gap_UI / 4, -gap_UI)), | 3694 | init_I2(gap_UI / 2, height + gap_UI) }; |
3695 | init_I2(gap_UI / 2, height_Rect(rangeRect) + gap_UI) | ||
3696 | }; | ||
3697 | } | 3695 | } |
3698 | else { | 3696 | else { |
3699 | pin = (iRect){ | 3697 | pin = (iRect){ addX_I2(topRight_Rect(rangeRect), -gap_UI / 4), |
3700 | addX_I2(topRight_Rect(rangeRect), -gap_UI / 4), | 3698 | init_I2(gap_UI / 2, height + gap_UI) }; |
3701 | init_I2(gap_UI / 2, height_Rect(rangeRect) + gap_UI) | ||
3702 | }; | ||
3703 | } | 3699 | } |
3704 | fillRect_Paint(p, pin, pinColor); | 3700 | fillRect_Paint(p, pin, pinColor); |
3705 | fillRect_Paint(p, initCentered_Rect(dir == 0 ? topMid_Rect(pin) : bottomMid_Rect(pin), | 3701 | fillRect_Paint(p, initCentered_Rect(dir == 0 ? topMid_Rect(pin) : bottomMid_Rect(pin), |
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c index 8690f8e5..0e2f9d7e 100644 --- a/src/ui/listwidget.c +++ b/src/ui/listwidget.c | |||
@@ -50,7 +50,8 @@ iDefineObjectConstruction(ListWidget) | |||
50 | struct Impl_ListWidget { | 50 | struct Impl_ListWidget { |
51 | iWidget widget; | 51 | iWidget widget; |
52 | iScrollWidget *scroll; | 52 | iScrollWidget *scroll; |
53 | int scrollY; | 53 | // int scrollY; |
54 | iSmoothScroll scrollY; | ||
54 | int itemHeight; | 55 | int itemHeight; |
55 | iPtrArray items; | 56 | iPtrArray items; |
56 | size_t hoverItem; | 57 | size_t hoverItem; |
@@ -60,6 +61,28 @@ struct Impl_ListWidget { | |||
60 | iBool noHoverWhileScrolling; | 61 | iBool noHoverWhileScrolling; |
61 | }; | 62 | }; |
62 | 63 | ||
64 | static void refreshWhileScrolling_ListWidget_(iAnyObject *any) { | ||
65 | iListWidget *d = any; | ||
66 | updateVisible_ListWidget(d); | ||
67 | refresh_Widget(d); | ||
68 | if (!isFinished_SmoothScroll(&d->scrollY)) { | ||
69 | addTicker_App(refreshWhileScrolling_ListWidget_, any); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static void scrollBegan_ListWidget_(iAnyObject *any, int offset, uint32_t span) { | ||
74 | iListWidget *d = any; | ||
75 | iUnused(span); | ||
76 | if (offset) { | ||
77 | if (d->hoverItem != iInvalidPos) { | ||
78 | invalidateItem_ListWidget(d, d->hoverItem); | ||
79 | d->hoverItem = iInvalidPos; | ||
80 | } | ||
81 | d->noHoverWhileScrolling = iTrue; | ||
82 | } | ||
83 | refreshWhileScrolling_ListWidget_(d); | ||
84 | } | ||
85 | |||
63 | void init_ListWidget(iListWidget *d) { | 86 | void init_ListWidget(iListWidget *d) { |
64 | iWidget *w = as_Widget(d); | 87 | iWidget *w = as_Widget(d); |
65 | init_Widget(w); | 88 | init_Widget(w); |
@@ -68,7 +91,7 @@ void init_ListWidget(iListWidget *d) { | |||
68 | setFlags_Widget(w, hover_WidgetFlag, iTrue); | 91 | setFlags_Widget(w, hover_WidgetFlag, iTrue); |
69 | addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); | 92 | addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); |
70 | setThumb_ScrollWidget(d->scroll, 0, 0); | 93 | setThumb_ScrollWidget(d->scroll, 0, 0); |
71 | d->scrollY = 0; | 94 | init_SmoothScroll(&d->scrollY, w, scrollBegan_ListWidget_); |
72 | d->itemHeight = 0; | 95 | d->itemHeight = 0; |
73 | d->noHoverWhileScrolling = iFalse; | 96 | d->noHoverWhileScrolling = iFalse; |
74 | init_PtrArray(&d->items); | 97 | init_PtrArray(&d->items); |
@@ -79,6 +102,7 @@ void init_ListWidget(iListWidget *d) { | |||
79 | } | 102 | } |
80 | 103 | ||
81 | void deinit_ListWidget(iListWidget *d) { | 104 | void deinit_ListWidget(iListWidget *d) { |
105 | removeTicker_App(refreshWhileScrolling_ListWidget_, d); | ||
82 | clear_ListWidget(d); | 106 | clear_ListWidget(d); |
83 | deinit_PtrArray(&d->items); | 107 | deinit_PtrArray(&d->items); |
84 | delete_VisBuf(d->visBuf); | 108 | delete_VisBuf(d->visBuf); |
@@ -128,9 +152,10 @@ void updateVisible_ListWidget(iListWidget *d) { | |||
128 | if (area_Rect(bounds) == 0) { | 152 | if (area_Rect(bounds) == 0) { |
129 | return; | 153 | return; |
130 | } | 154 | } |
131 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_ListWidget_(d) }); | 155 | setMax_SmoothScroll(&d->scrollY, scrollMax_ListWidget_(d)); |
156 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, d->scrollY.max }); | ||
132 | setThumb_ScrollWidget(d->scroll, | 157 | setThumb_ScrollWidget(d->scroll, |
133 | d->scrollY, | 158 | pos_SmoothScroll(&d->scrollY), |
134 | contentSize > 0 ? height_Rect(bounds_Widget(as_Widget(d->scroll))) * | 159 | contentSize > 0 ? height_Rect(bounds_Widget(as_Widget(d->scroll))) * |
135 | height_Rect(bounds) / contentSize | 160 | height_Rect(bounds) / contentSize |
136 | : 0); | 161 | : 0); |
@@ -158,17 +183,19 @@ int itemHeight_ListWidget(const iListWidget *d) { | |||
158 | } | 183 | } |
159 | 184 | ||
160 | int scrollPos_ListWidget(const iListWidget *d) { | 185 | int scrollPos_ListWidget(const iListWidget *d) { |
161 | return d->scrollY; | 186 | return targetValue_Anim(&d->scrollY.pos); |
162 | } | 187 | } |
163 | 188 | ||
164 | void setScrollPos_ListWidget(iListWidget *d, int pos) { | 189 | void setScrollPos_ListWidget(iListWidget *d, int pos) { |
165 | d->scrollY = pos; | 190 | // d->scrollY = pos; |
191 | setValue_Anim(&d->scrollY.pos, pos, 0); | ||
166 | d->hoverItem = iInvalidPos; | 192 | d->hoverItem = iInvalidPos; |
167 | refresh_Widget(as_Widget(d)); | 193 | refresh_Widget(as_Widget(d)); |
168 | } | 194 | } |
169 | 195 | ||
170 | iBool scrollOffset_ListWidget(iListWidget *d, int offset) { | 196 | void scrollOffset_ListWidget(iListWidget *d, int offset) { |
171 | const int oldScroll = d->scrollY; | 197 | moveSpan_SmoothScroll(&d->scrollY, offset, 0); |
198 | /* | ||
172 | d->scrollY += offset; | 199 | d->scrollY += offset; |
173 | if (d->scrollY < 0) { | 200 | if (d->scrollY < 0) { |
174 | d->scrollY = 0; | 201 | d->scrollY = 0; |
@@ -188,13 +215,14 @@ iBool scrollOffset_ListWidget(iListWidget *d, int offset) { | |||
188 | updateVisible_ListWidget(d); | 215 | updateVisible_ListWidget(d); |
189 | refresh_Widget(as_Widget(d)); | 216 | refresh_Widget(as_Widget(d)); |
190 | return iTrue; | 217 | return iTrue; |
191 | } | 218 | }*/ |
192 | return iFalse; | 219 | // return iFalse; |
193 | } | 220 | } |
194 | 221 | ||
195 | void scrollToItem_ListWidget(iListWidget *d, size_t index) { | 222 | void scrollToItem_ListWidget(iListWidget *d, size_t index) { |
223 | stop_Anim(&d->scrollY.pos); | ||
196 | const iRect rect = innerBounds_Widget(as_Widget(d)); | 224 | const iRect rect = innerBounds_Widget(as_Widget(d)); |
197 | int yTop = d->itemHeight * index - d->scrollY; | 225 | int yTop = d->itemHeight * index - pos_SmoothScroll(&d->scrollY); |
198 | int yBottom = yTop + d->itemHeight; | 226 | int yBottom = yTop + d->itemHeight; |
199 | if (yBottom > height_Rect(rect)) { | 227 | if (yBottom > height_Rect(rect)) { |
200 | scrollOffset_ListWidget(d, yBottom - height_Rect(rect)); | 228 | scrollOffset_ListWidget(d, yBottom - height_Rect(rect)); |
@@ -222,7 +250,7 @@ static iRanges visRange_ListWidget_(const iListWidget *d) { | |||
222 | 250 | ||
223 | size_t itemIndex_ListWidget(const iListWidget *d, iInt2 pos) { | 251 | size_t itemIndex_ListWidget(const iListWidget *d, iInt2 pos) { |
224 | const iRect bounds = innerBounds_Widget(constAs_Widget(d)); | 252 | const iRect bounds = innerBounds_Widget(constAs_Widget(d)); |
225 | pos.y -= top_Rect(bounds) - d->scrollY; | 253 | pos.y -= top_Rect(bounds) - pos_SmoothScroll(&d->scrollY); |
226 | if (pos.y < 0 || !d->itemHeight) return iInvalidPos; | 254 | if (pos.y < 0 || !d->itemHeight) return iInvalidPos; |
227 | size_t index = pos.y / d->itemHeight; | 255 | size_t index = pos.y / d->itemHeight; |
228 | if (index >= size_Array(&d->items)) return iInvalidPos; | 256 | if (index >= size_Array(&d->items)) return iInvalidPos; |
@@ -304,6 +332,9 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | |||
304 | if (isMetricsChange_UserEvent(ev)) { | 332 | if (isMetricsChange_UserEvent(ev)) { |
305 | invalidate_ListWidget(d); | 333 | invalidate_ListWidget(d); |
306 | } | 334 | } |
335 | else if (processEvent_SmoothScroll(&d->scrollY, ev)) { | ||
336 | return iTrue; | ||
337 | } | ||
307 | else if (isCommand_SDLEvent(ev)) { | 338 | else if (isCommand_SDLEvent(ev)) { |
308 | const char *cmd = command_UserEvent(ev); | 339 | const char *cmd = command_UserEvent(ev); |
309 | if (equal_Command(cmd, "theme.changed")) { | 340 | if (equal_Command(cmd, "theme.changed")) { |
@@ -325,10 +356,16 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | |||
325 | } | 356 | } |
326 | if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { | 357 | if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { |
327 | int amount = -ev->wheel.y; | 358 | int amount = -ev->wheel.y; |
328 | if (!isPerPixel_MouseWheelEvent(&ev->wheel)) { | 359 | if (isPerPixel_MouseWheelEvent(&ev->wheel)) { |
360 | stop_Anim(&d->scrollY.pos); | ||
361 | moveSpan_SmoothScroll(&d->scrollY, amount, 0); | ||
362 | } | ||
363 | else { | ||
364 | /* Traditional mouse wheel. */ | ||
329 | amount *= 3 * d->itemHeight; | 365 | amount *= 3 * d->itemHeight; |
366 | //if (!isFinished_SmoothScroll(&d->scrollY) && pos_Anim(&d->scrollY.pos) < 0.25f ? 0.5f : 1.0f) | ||
367 | moveSpan_SmoothScroll(&d->scrollY, amount, 200); | ||
330 | } | 368 | } |
331 | scrollOffset_ListWidget(d, amount); | ||
332 | return iTrue; | 369 | return iTrue; |
333 | } | 370 | } |
334 | switch (processEvent_Click(&d->click, ev)) { | 371 | switch (processEvent_Click(&d->click, ev)) { |
@@ -360,6 +397,7 @@ static void draw_ListWidget_(const iListWidget *d) { | |||
360 | if (!bounds.size.y || !bounds.size.x || !d->itemHeight) { | 397 | if (!bounds.size.y || !bounds.size.x || !d->itemHeight) { |
361 | return; | 398 | return; |
362 | } | 399 | } |
400 | const int scrollY = pos_SmoothScroll(&d->scrollY); | ||
363 | iPaint p; | 401 | iPaint p; |
364 | init_Paint(&p); | 402 | init_Paint(&p); |
365 | drawBackground_Widget(w); | 403 | drawBackground_Widget(w); |
@@ -375,8 +413,8 @@ static void draw_ListWidget_(const iListWidget *d) { | |||
375 | w->bgColor, w->bgColor, w->bgColor, w->bgColor | 413 | w->bgColor, w->bgColor, w->bgColor, w->bgColor |
376 | }; | 414 | }; |
377 | const int bottom = numItems_ListWidget(d) * d->itemHeight; | 415 | const int bottom = numItems_ListWidget(d) * d->itemHeight; |
378 | const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight, | 416 | const iRangei vis = { scrollY / d->itemHeight * d->itemHeight, |
379 | ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight }; | 417 | ((scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight }; |
380 | reposition_VisBuf(d->visBuf, vis); | 418 | reposition_VisBuf(d->visBuf, vis); |
381 | /* Check which parts are invalid. */ | 419 | /* Check which parts are invalid. */ |
382 | iRangei invalidRange[iElemCount(d->visBuf->buffers)]; | 420 | iRangei invalidRange[iElemCount(d->visBuf->buffers)]; |
@@ -428,7 +466,7 @@ static void draw_ListWidget_(const iListWidget *d) { | |||
428 | clear_IntSet(&iConstCast(iListWidget *, d)->invalidItems); | 466 | clear_IntSet(&iConstCast(iListWidget *, d)->invalidItems); |
429 | } | 467 | } |
430 | setClip_Paint(&p, bounds_Widget(w)); | 468 | setClip_Paint(&p, bounds_Widget(w)); |
431 | draw_VisBuf(d->visBuf, addY_I2(topLeft_Rect(bounds), -d->scrollY), ySpan_Rect(bounds)); | 469 | draw_VisBuf(d->visBuf, addY_I2(topLeft_Rect(bounds), -scrollY), ySpan_Rect(bounds)); |
432 | unsetClip_Paint(&p); | 470 | unsetClip_Paint(&p); |
433 | drawChildren_Widget(w); | 471 | drawChildren_Widget(w); |
434 | } | 472 | } |
diff --git a/src/ui/listwidget.h b/src/ui/listwidget.h index d7e2c55e..16adf664 100644 --- a/src/ui/listwidget.h +++ b/src/ui/listwidget.h | |||
@@ -61,7 +61,7 @@ int scrollPos_ListWidget (const iListWidget *); | |||
61 | 61 | ||
62 | void setScrollPos_ListWidget (iListWidget *, int pos); | 62 | void setScrollPos_ListWidget (iListWidget *, int pos); |
63 | void scrollToItem_ListWidget (iListWidget *, size_t index); | 63 | void scrollToItem_ListWidget (iListWidget *, size_t index); |
64 | iBool scrollOffset_ListWidget (iListWidget *, int offset); /* returns true if position changed */ | 64 | void scrollOffset_ListWidget (iListWidget *, int offset); |
65 | void updateVisible_ListWidget (iListWidget *); | 65 | void updateVisible_ListWidget (iListWidget *); |
66 | void updateMouseHover_ListWidget (iListWidget *); | 66 | void updateMouseHover_ListWidget (iListWidget *); |
67 | 67 | ||
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index cb084ccc..e7dcadde 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -426,9 +426,8 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
426 | default: | 426 | default: |
427 | break; | 427 | break; |
428 | } | 428 | } |
429 | if (!scrollOffset_ListWidget(d->list, 0)) { | 429 | scrollOffset_ListWidget(d->list, 0); |
430 | updateVisible_ListWidget(d->list); | 430 | updateVisible_ListWidget(d->list); |
431 | } | ||
432 | invalidate_ListWidget(d->list); | 431 | invalidate_ListWidget(d->list); |
433 | /* Content for a blank tab. */ | 432 | /* Content for a blank tab. */ |
434 | if (isEmpty) { | 433 | if (isEmpty) { |