diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-24 07:36:08 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-24 07:36:08 +0300 |
commit | 446df26adb969dcb4dd9cf5e171fbb9453a8e27c (patch) | |
tree | 562c647f7c9dc907d34e263d44c9a414a80a8017 /src | |
parent | 27ebfc904b9b3eac3ef5479ed0d0ba166fac1543 (diff) |
SidebarWidget: Reordering bookmarks manually
One can now drag and drop bookmarks to change their order in the list.
Diffstat (limited to 'src')
-rw-r--r-- | src/bookmarks.c | 14 | ||||
-rw-r--r-- | src/bookmarks.h | 10 | ||||
-rw-r--r-- | src/ui/listwidget.c | 53 | ||||
-rw-r--r-- | src/ui/listwidget.h | 1 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 31 | ||||
-rw-r--r-- | src/ui/util.c | 2 |
6 files changed, 91 insertions, 20 deletions
diff --git a/src/bookmarks.c b/src/bookmarks.c index 94f4be4e..616e4632 100644 --- a/src/bookmarks.c +++ b/src/bookmarks.c | |||
@@ -402,6 +402,20 @@ iBookmark *get_Bookmarks(iBookmarks *d, uint32_t id) { | |||
402 | return (iBookmark *) value_Hash(&d->bookmarks, id); | 402 | return (iBookmark *) value_Hash(&d->bookmarks, id); |
403 | } | 403 | } |
404 | 404 | ||
405 | void reorder_Bookmarks(iBookmarks *d, uint32_t id, int newOrder) { | ||
406 | lock_Mutex(d->mtx); | ||
407 | iForEach(Hash, i, &d->bookmarks) { | ||
408 | iBookmark *bm = (iBookmark *) i.value; | ||
409 | if (id_Bookmark(bm) == id) { | ||
410 | bm->order = newOrder; | ||
411 | } | ||
412 | else if (bm->order >= newOrder) { | ||
413 | bm->order++; | ||
414 | } | ||
415 | } | ||
416 | unlock_Mutex(d->mtx); | ||
417 | } | ||
418 | |||
405 | iBool filterTagsRegExp_Bookmarks(void *regExp, const iBookmark *bm) { | 419 | iBool filterTagsRegExp_Bookmarks(void *regExp, const iBookmark *bm) { |
406 | iRegExpMatch m; | 420 | iRegExpMatch m; |
407 | init_RegExpMatch(&m); | 421 | init_RegExpMatch(&m); |
diff --git a/src/bookmarks.h b/src/bookmarks.h index dc7eca9a..0de930d7 100644 --- a/src/bookmarks.h +++ b/src/bookmarks.h | |||
@@ -32,6 +32,8 @@ iDeclareType(GmRequest) | |||
32 | iDeclareType(Bookmark) | 32 | iDeclareType(Bookmark) |
33 | iDeclareTypeConstruction(Bookmark) | 33 | iDeclareTypeConstruction(Bookmark) |
34 | 34 | ||
35 | /* TODO: Make the special internal tags a bitfield, separate from user's tags. */ | ||
36 | |||
35 | #define headings_BookmarkTag "headings" | 37 | #define headings_BookmarkTag "headings" |
36 | #define homepage_BookmarkTag "homepage" | 38 | #define homepage_BookmarkTag "homepage" |
37 | #define linkSplit_BookmarkTag "linksplit" | 39 | #define linkSplit_BookmarkTag "linksplit" |
@@ -78,16 +80,18 @@ iDeclareTypeConstruction(Bookmarks) | |||
78 | 80 | ||
79 | void clear_Bookmarks (iBookmarks *); | 81 | void clear_Bookmarks (iBookmarks *); |
80 | void load_Bookmarks (iBookmarks *, const char *dirPath); | 82 | void load_Bookmarks (iBookmarks *, const char *dirPath); |
83 | void save_Bookmarks (const iBookmarks *, const char *dirPath); | ||
84 | |||
81 | uint32_t add_Bookmarks (iBookmarks *, const iString *url, const iString *title, | 85 | uint32_t add_Bookmarks (iBookmarks *, const iString *url, const iString *title, |
82 | const iString *tags, iChar icon); | 86 | const iString *tags, iChar icon); |
83 | iBool remove_Bookmarks (iBookmarks *, uint32_t id); | 87 | iBool remove_Bookmarks (iBookmarks *, uint32_t id); |
84 | iBookmark * get_Bookmarks (iBookmarks *, uint32_t id); | 88 | iBookmark * get_Bookmarks (iBookmarks *, uint32_t id); |
89 | void reorder_Bookmarks (iBookmarks *, uint32_t id, int newOrder); | ||
90 | iBool updateBookmarkIcon_Bookmarks(iBookmarks *, const iString *url, iChar icon); | ||
85 | void fetchRemote_Bookmarks (iBookmarks *); | 91 | void fetchRemote_Bookmarks (iBookmarks *); |
86 | void requestFinished_Bookmarks (iBookmarks *, iGmRequest *req); | 92 | void requestFinished_Bookmarks (iBookmarks *, iGmRequest *req); |
87 | iBool updateBookmarkIcon_Bookmarks(iBookmarks *, const iString *url, iChar icon); | ||
88 | iChar siteIcon_Bookmarks (const iBookmarks *, const iString *url); | ||
89 | 93 | ||
90 | void save_Bookmarks (const iBookmarks *, const char *dirPath); | 94 | iChar siteIcon_Bookmarks (const iBookmarks *, const iString *url); |
91 | uint32_t findUrl_Bookmarks (const iBookmarks *, const iString *url); /* O(n) */ | 95 | uint32_t findUrl_Bookmarks (const iBookmarks *, const iString *url); /* O(n) */ |
92 | 96 | ||
93 | typedef iBool (*iBookmarksFilterFunc) (void *context, const iBookmark *); | 97 | typedef iBool (*iBookmarksFilterFunc) (void *context, const iBookmark *); |
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c index 6a1372ab..a34f3d03 100644 --- a/src/ui/listwidget.c +++ b/src/ui/listwidget.c | |||
@@ -277,7 +277,7 @@ size_t hoverItemIndex_ListWidget(const iListWidget *d) { | |||
277 | return d->hoverItem; | 277 | return d->hoverItem; |
278 | } | 278 | } |
279 | 279 | ||
280 | static void setHoverItem_ListWidget_(iListWidget *d, size_t index) { | 280 | void setHoverItem_ListWidget(iListWidget *d, size_t index) { |
281 | if (index < size_PtrArray(&d->items)) { | 281 | if (index < size_PtrArray(&d->items)) { |
282 | const iListItem *item = at_PtrArray(&d->items, index); | 282 | const iListItem *item = at_PtrArray(&d->items, index); |
283 | if (item->isSeparator) { | 283 | if (item->isSeparator) { |
@@ -294,7 +294,7 @@ static void setHoverItem_ListWidget_(iListWidget *d, size_t index) { | |||
294 | 294 | ||
295 | void updateMouseHover_ListWidget(iListWidget *d) { | 295 | void updateMouseHover_ListWidget(iListWidget *d) { |
296 | const iInt2 mouse = mouseCoord_Window(get_Window(), 0); | 296 | const iInt2 mouse = mouseCoord_Window(get_Window(), 0); |
297 | setHoverItem_ListWidget_(d, itemIndex_ListWidget(d, mouse)); | 297 | setHoverItem_ListWidget(d, itemIndex_ListWidget(d, mouse)); |
298 | } | 298 | } |
299 | 299 | ||
300 | void sort_ListWidget(iListWidget *d, int (*cmp)(const iListItem **item1, const iListItem **item2)) { | 300 | void sort_ListWidget(iListWidget *d, int (*cmp)(const iListItem **item1, const iListItem **item2)) { |
@@ -318,19 +318,18 @@ static void updateHover_ListWidget_(iListWidget *d, const iInt2 mouse) { | |||
318 | contains_Widget(constAs_Widget(d), mouse)) { | 318 | contains_Widget(constAs_Widget(d), mouse)) { |
319 | hover = itemIndex_ListWidget(d, mouse); | 319 | hover = itemIndex_ListWidget(d, mouse); |
320 | } | 320 | } |
321 | setHoverItem_ListWidget_(d, hover); | 321 | setHoverItem_ListWidget(d, hover); |
322 | } | 322 | } |
323 | 323 | ||
324 | static size_t resolveDragDestination_ListWidget_(const iListWidget *d, iInt2 dstPos, iBool *isOnto) { | 324 | static size_t resolveDragDestination_ListWidget_(const iListWidget *d, iInt2 dstPos, iBool *isOnto) { |
325 | size_t index = itemIndex_ListWidget(d, dstPos); | 325 | size_t index = itemIndex_ListWidget(d, dstPos); |
326 | const iRect rect = itemRect_ListWidget(d, index); | ||
327 | const iListItem *item = constItem_ListWidget(d, index); | 326 | const iListItem *item = constItem_ListWidget(d, index); |
328 | const iRangei span = ySpan_Rect(rect); | ||
329 | if (!item) { | 327 | if (!item) { |
330 | item = constItem_ListWidget( | 328 | index = (dstPos.y < mid_Rect(bounds_Widget(constAs_Widget(d))).y ? 0 : (numItems_ListWidget(d) - 1)); |
331 | d, | 329 | item = constItem_ListWidget(d, index); |
332 | dstPos.y < mid_Rect(bounds_Widget(constAs_Widget(d))).y ? 0 : (numItems_ListWidget(d) - 1)); | ||
333 | } | 330 | } |
331 | const iRect rect = itemRect_ListWidget(d, index); | ||
332 | const iRangei span = ySpan_Rect(rect); | ||
334 | if (item->isDropTarget) { | 333 | if (item->isDropTarget) { |
335 | const int pad = size_Range(&span) / 4; | 334 | const int pad = size_Range(&span) / 4; |
336 | if (dstPos.y >= span.start + pad && dstPos.y < span.end) { | 335 | if (dstPos.y >= span.start + pad && dstPos.y < span.end) { |
@@ -350,6 +349,7 @@ static iBool endDrag_ListWidget_(iListWidget *d, iInt2 endPos) { | |||
350 | if (d->dragItem == iInvalidPos) { | 349 | if (d->dragItem == iInvalidPos) { |
351 | return iFalse; | 350 | return iFalse; |
352 | } | 351 | } |
352 | stop_Anim(&d->scrollY.pos); | ||
353 | iBool isOnto; | 353 | iBool isOnto; |
354 | const size_t index = resolveDragDestination_ListWidget_(d, endPos, &isOnto); | 354 | const size_t index = resolveDragDestination_ListWidget_(d, endPos, &isOnto); |
355 | if (isOnto) { | 355 | if (isOnto) { |
@@ -385,14 +385,34 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | |||
385 | d->noHoverWhileScrolling = iFalse; | 385 | d->noHoverWhileScrolling = iFalse; |
386 | } | 386 | } |
387 | if (ev->type == SDL_MOUSEMOTION) { | 387 | if (ev->type == SDL_MOUSEMOTION) { |
388 | const iInt2 mousePos = init_I2(ev->motion.x, ev->motion.y); | ||
388 | if (ev->motion.state == 0 /* not dragging */) { | 389 | if (ev->motion.state == 0 /* not dragging */) { |
389 | if (ev->motion.which != SDL_TOUCH_MOUSEID) { | 390 | if (ev->motion.which != SDL_TOUCH_MOUSEID) { |
390 | d->noHoverWhileScrolling = iFalse; | 391 | d->noHoverWhileScrolling = iFalse; |
391 | } | 392 | } |
392 | updateHover_ListWidget_(d, init_I2(ev->motion.x, ev->motion.y)); | 393 | updateHover_ListWidget_(d, mousePos); |
393 | } | 394 | } |
394 | else if (d->dragItem != iInvalidPos) { | 395 | else if (d->dragItem != iInvalidPos) { |
395 | refresh_Widget(d); | 396 | /* Start scrolling if near the ends. */ |
397 | const int zone = d->itemHeight; | ||
398 | const iRect bounds = bounds_Widget(w); | ||
399 | float scrollSpeed = 0.0f; | ||
400 | if (mousePos.y > bottom_Rect(bounds) - zone) { | ||
401 | scrollSpeed = (mousePos.y - bottom_Rect(bounds) + zone) / (float) zone; | ||
402 | } | ||
403 | else if (mousePos.y < top_Rect(bounds) + zone) { | ||
404 | scrollSpeed = -(top_Rect(bounds) + zone - mousePos.y) / (float) zone; | ||
405 | } | ||
406 | scrollSpeed = iClamp(scrollSpeed, -1.0f, 1.0f); | ||
407 | if (iAbs(scrollSpeed) < 0.001f) { | ||
408 | stop_Anim(&d->scrollY.pos); | ||
409 | refresh_Widget(d); | ||
410 | } | ||
411 | else { | ||
412 | setValueSpeed_Anim(&d->scrollY.pos, scrollSpeed < 0 ? 0 : scrollMax_ListWidget_(d), | ||
413 | iAbs(scrollSpeed * gap_UI * 100)); | ||
414 | refreshWhileScrolling_ListWidget_(d); | ||
415 | } | ||
396 | } | 416 | } |
397 | } | 417 | } |
398 | if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { | 418 | if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { |
@@ -416,7 +436,12 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | |||
416 | redrawHoverItem_ListWidget_(d); | 436 | redrawHoverItem_ListWidget_(d); |
417 | return iTrue; | 437 | return iTrue; |
418 | case aborted_ClickResult: | 438 | case aborted_ClickResult: |
419 | endDrag_ListWidget_(d, pos_Click(&d->click)); | 439 | // endDrag_ListWidget_(d, pos_Click(&d->click)); |
440 | if (d->dragItem != iInvalidPos) { | ||
441 | stop_Anim(&d->scrollY.pos); | ||
442 | invalidateItem_ListWidget(d, d->dragItem); | ||
443 | d->dragItem = iInvalidPos; | ||
444 | } | ||
420 | redrawHoverItem_ListWidget_(d); | 445 | redrawHoverItem_ListWidget_(d); |
421 | break; | 446 | break; |
422 | case drag_ClickResult: | 447 | case drag_ClickResult: |
@@ -436,7 +461,7 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { | |||
436 | return iTrue; | 461 | return iTrue; |
437 | } | 462 | } |
438 | redrawHoverItem_ListWidget_(d); | 463 | redrawHoverItem_ListWidget_(d); |
439 | if (contains_Rect(innerBounds_Widget(w), pos_Click(&d->click)) && | 464 | if (contains_Rect(itemRect_ListWidget(d, d->hoverItem), pos_Click(&d->click)) && |
440 | d->hoverItem != iInvalidPos) { | 465 | d->hoverItem != iInvalidPos) { |
441 | postCommand_Widget(w, "list.clicked arg:%zu item:%p", | 466 | postCommand_Widget(w, "list.clicked arg:%zu item:%p", |
442 | d->hoverItem, constHoverItem_ListWidget(d)); | 467 | d->hoverItem, constHoverItem_ListWidget(d)); |
@@ -542,14 +567,10 @@ static void draw_ListWidget_(const iListWidget *d) { | |||
542 | const iListItem *item = constAt_PtrArray(&d->items, d->dragItem); | 567 | const iListItem *item = constAt_PtrArray(&d->items, d->dragItem); |
543 | const iRect itemRect = { init_I2(left_Rect(bounds), pos.y), init_I2(d->visBuf->texSize.x, d->itemHeight) }; | 568 | const iRect itemRect = { init_I2(left_Rect(bounds), pos.y), init_I2(d->visBuf->texSize.x, d->itemHeight) }; |
544 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); | 569 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); |
545 | // setOpacity_Text(0.25f); | ||
546 | // SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); | ||
547 | // setOpacity_Text(1.0f); | ||
548 | iBool dstOnto; | 570 | iBool dstOnto; |
549 | const size_t dstIndex = resolveDragDestination_ListWidget_(d, mousePos, &dstOnto); | 571 | const size_t dstIndex = resolveDragDestination_ListWidget_(d, mousePos, &dstOnto); |
550 | if (dstIndex != d->dragItem && dstIndex != d->dragItem + 1) { | 572 | if (dstIndex != d->dragItem && dstIndex != d->dragItem + 1) { |
551 | const iRect dstRect = itemRect_ListWidget(d, dstIndex); | 573 | const iRect dstRect = itemRect_ListWidget(d, dstIndex); |
552 | // SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); | ||
553 | p.alpha = 0xff; | 574 | p.alpha = 0xff; |
554 | if (dstOnto) { | 575 | if (dstOnto) { |
555 | fillRect_Paint(&p, dstRect, uiTextAction_ColorId); | 576 | fillRect_Paint(&p, dstRect, uiTextAction_ColorId); |
diff --git a/src/ui/listwidget.h b/src/ui/listwidget.h index e586a003..dfa24c07 100644 --- a/src/ui/listwidget.h +++ b/src/ui/listwidget.h | |||
@@ -66,6 +66,7 @@ void scrollToItem_ListWidget (iListWidget *, size_t index); | |||
66 | void scrollOffset_ListWidget (iListWidget *, int offset); | 66 | void scrollOffset_ListWidget (iListWidget *, int offset); |
67 | void updateVisible_ListWidget (iListWidget *); | 67 | void updateVisible_ListWidget (iListWidget *); |
68 | void updateMouseHover_ListWidget (iListWidget *); | 68 | void updateMouseHover_ListWidget (iListWidget *); |
69 | void setHoverItem_ListWidget (iListWidget *, size_t index); | ||
69 | 70 | ||
70 | void sort_ListWidget (iListWidget *, int (*cmp)(const iListItem **item1, const iListItem **item2)); | 71 | void sort_ListWidget (iListWidget *, int (*cmp)(const iListItem **item1, const iListItem **item2)); |
71 | 72 | ||
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 3463f1a5..20e43153 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -332,6 +332,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
332 | iRegExp *homeTag = iClob(new_RegExp("\\b" homepage_BookmarkTag "\\b", caseSensitive_RegExpOption)); | 332 | iRegExp *homeTag = iClob(new_RegExp("\\b" homepage_BookmarkTag "\\b", caseSensitive_RegExpOption)); |
333 | iRegExp *subTag = iClob(new_RegExp("\\b" subscribed_BookmarkTag "\\b", caseSensitive_RegExpOption)); | 333 | iRegExp *subTag = iClob(new_RegExp("\\b" subscribed_BookmarkTag "\\b", caseSensitive_RegExpOption)); |
334 | iRegExp *remoteSourceTag = iClob(new_RegExp("\\b" remoteSource_BookmarkTag "\\b", caseSensitive_RegExpOption)); | 334 | iRegExp *remoteSourceTag = iClob(new_RegExp("\\b" remoteSource_BookmarkTag "\\b", caseSensitive_RegExpOption)); |
335 | iRegExp *remoteTag = iClob(new_RegExp("\\b" remote_BookmarkTag "\\b", caseSensitive_RegExpOption)); | ||
335 | iRegExp *linkSplitTag = iClob(new_RegExp("\\b" linkSplit_BookmarkTag "\\b", caseSensitive_RegExpOption)); | 336 | iRegExp *linkSplitTag = iClob(new_RegExp("\\b" linkSplit_BookmarkTag "\\b", caseSensitive_RegExpOption)); |
336 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTree_Bookmark_, NULL, NULL)) { | 337 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTree_Bookmark_, NULL, NULL)) { |
337 | const iBookmark *bm = i.ptr; | 338 | const iBookmark *bm = i.ptr; |
@@ -352,6 +353,10 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
352 | appendChar_String(&item->meta, 0x1f3e0); | 353 | appendChar_String(&item->meta, 0x1f3e0); |
353 | } | 354 | } |
354 | init_RegExpMatch(&m); | 355 | init_RegExpMatch(&m); |
356 | if (matchString_RegExp(remoteTag, &bm->tags, &m)) { | ||
357 | item->listItem.isDraggable = iFalse; | ||
358 | } | ||
359 | init_RegExpMatch(&m); | ||
355 | if (matchString_RegExp(remoteSourceTag, &bm->tags, &m)) { | 360 | if (matchString_RegExp(remoteSourceTag, &bm->tags, &m)) { |
356 | appendChar_String(&item->meta, 0x2913); | 361 | appendChar_String(&item->meta, 0x2913); |
357 | item->isBold = iTrue; | 362 | item->isBold = iTrue; |
@@ -555,6 +560,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
555 | #endif | 560 | #endif |
556 | arrange_Widget(d->actions); | 561 | arrange_Widget(d->actions); |
557 | arrange_Widget(as_Widget(d)); | 562 | arrange_Widget(as_Widget(d)); |
563 | updateMouseHover_ListWidget(d->list); | ||
558 | } | 564 | } |
559 | 565 | ||
560 | static void updateItemHeight_SidebarWidget_(iSidebarWidget *d) { | 566 | static void updateItemHeight_SidebarWidget_(iSidebarWidget *d) { |
@@ -1000,6 +1006,19 @@ static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char * | |||
1000 | return iFalse; | 1006 | return iFalse; |
1001 | } | 1007 | } |
1002 | 1008 | ||
1009 | static void bookmarkMoved_SidebarWidget_(iSidebarWidget *d, size_t index, size_t beforeIndex) { | ||
1010 | const iSidebarItem *movingItem = item_ListWidget(d->list, index); | ||
1011 | const iBool isLast = (beforeIndex == numItems_ListWidget(d->list)); | ||
1012 | const iSidebarItem *dstItem = item_ListWidget(d->list, | ||
1013 | isLast ? numItems_ListWidget(d->list) - 1 | ||
1014 | : beforeIndex); | ||
1015 | const iBookmark *dst = get_Bookmarks(bookmarks_App(), dstItem->id); | ||
1016 | reorder_Bookmarks(bookmarks_App(), movingItem->id, dst->order + (isLast ? 1 : 0)); | ||
1017 | updateItems_SidebarWidget_(d); | ||
1018 | /* Don't confuse the user: keep the dragged item in hover state. */ | ||
1019 | setHoverItem_ListWidget(d->list, index < beforeIndex ? beforeIndex - 1 : beforeIndex); | ||
1020 | } | ||
1021 | |||
1003 | static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) { | 1022 | static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) { |
1004 | iWidget *w = as_Widget(d); | 1023 | iWidget *w = as_Widget(d); |
1005 | /* Handle commands. */ | 1024 | /* Handle commands. */ |
@@ -1107,6 +1126,18 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1107 | d, pointerLabel_Command(cmd, "item"), argU32Label_Command(cmd, "arg")); | 1126 | d, pointerLabel_Command(cmd, "item"), argU32Label_Command(cmd, "arg")); |
1108 | return iTrue; | 1127 | return iTrue; |
1109 | } | 1128 | } |
1129 | else if (isCommand_Widget(w, ev, "list.dragged")) { | ||
1130 | iAssert(d->mode == bookmarks_SidebarMode); | ||
1131 | if (hasLabel_Command(cmd, "before")) { | ||
1132 | bookmarkMoved_SidebarWidget_(d, | ||
1133 | argU32Label_Command(cmd, "arg"), | ||
1134 | argU32Label_Command(cmd, "before")); | ||
1135 | } | ||
1136 | else { | ||
1137 | /* Dragged onto a folder. */ | ||
1138 | } | ||
1139 | return iTrue; | ||
1140 | } | ||
1110 | else if (isCommand_Widget(w, ev, "menu.closed")) { | 1141 | else if (isCommand_Widget(w, ev, "menu.closed")) { |
1111 | // invalidateItem_ListWidget(d->list, d->contextIndex); | 1142 | // invalidateItem_ListWidget(d->list, d->contextIndex); |
1112 | } | 1143 | } |
diff --git a/src/ui/util.c b/src/ui/util.c index 2b6ff929..7fa5d675 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -337,7 +337,7 @@ void setValue_Anim(iAnim *d, float to, uint32_t span) { | |||
337 | } | 337 | } |
338 | 338 | ||
339 | void setValueSpeed_Anim(iAnim *d, float to, float unitsPerSecond) { | 339 | void setValueSpeed_Anim(iAnim *d, float to, float unitsPerSecond) { |
340 | if (iAbs(d->to - to) > 0.0001f) { | 340 | if (iAbs(d->to - to) > 0.0001f || !isFinished_Anim(d)) { |
341 | const uint32_t now = SDL_GetTicks(); | 341 | const uint32_t now = SDL_GetTicks(); |
342 | const float from = valueAt_Anim_(d, now); | 342 | const float from = valueAt_Anim_(d, now); |
343 | const float delta = to - from; | 343 | const float delta = to - from; |