summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ui/documentwidget.c14
-rw-r--r--src/ui/listwidget.c72
-rw-r--r--src/ui/listwidget.h2
-rw-r--r--src/ui/sidebarwidget.c5
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
3688static void drawPin_(iPaint *p, iRect rangeRect, int dir) { 3688static 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)
50struct Impl_ListWidget { 50struct 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
64static 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
73static 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
63void init_ListWidget(iListWidget *d) { 86void 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
81void deinit_ListWidget(iListWidget *d) { 104void 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
160int scrollPos_ListWidget(const iListWidget *d) { 185int scrollPos_ListWidget(const iListWidget *d) {
161 return d->scrollY; 186 return targetValue_Anim(&d->scrollY.pos);
162} 187}
163 188
164void setScrollPos_ListWidget(iListWidget *d, int pos) { 189void 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
170iBool scrollOffset_ListWidget(iListWidget *d, int offset) { 196void 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
195void scrollToItem_ListWidget(iListWidget *d, size_t index) { 222void 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
223size_t itemIndex_ListWidget(const iListWidget *d, iInt2 pos) { 251size_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
62void setScrollPos_ListWidget (iListWidget *, int pos); 62void setScrollPos_ListWidget (iListWidget *, int pos);
63void scrollToItem_ListWidget (iListWidget *, size_t index); 63void scrollToItem_ListWidget (iListWidget *, size_t index);
64iBool scrollOffset_ListWidget (iListWidget *, int offset); /* returns true if position changed */ 64void scrollOffset_ListWidget (iListWidget *, int offset);
65void updateVisible_ListWidget (iListWidget *); 65void updateVisible_ListWidget (iListWidget *);
66void updateMouseHover_ListWidget (iListWidget *); 66void 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) {