diff options
-rw-r--r-- | res/about/version.gmi | 1 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 110 |
2 files changed, 60 insertions, 51 deletions
diff --git a/res/about/version.gmi b/res/about/version.gmi index 6b4a302d..36e23492 100644 --- a/res/about/version.gmi +++ b/res/about/version.gmi | |||
@@ -16,6 +16,7 @@ New features: | |||
16 | * Windows: Automatic updates using the WinSparkle library. | 16 | * Windows: Automatic updates using the WinSparkle library. |
17 | 17 | ||
18 | Changes and enhancements: | 18 | Changes and enhancements: |
19 | * Sidebar context menus also appear when clicking over the sidebar background. In this case the menu contains general functions not related to any item. | ||
19 | * Feeds tab in the sidebar has a redesigned action toolbar with "Mark All as Read", and dropdown menu and keyboard shortcuts for changing the filter mode. | 20 | * Feeds tab in the sidebar has a redesigned action toolbar with "Mark All as Read", and dropdown menu and keyboard shortcuts for changing the filter mode. |
20 | * Feeds tab remembers the unread/all filter mode persistently. | 21 | * Feeds tab remembers the unread/all filter mode persistently. |
21 | * ANSI foreground colors are modified to match colored theme backgrounds (e.g., Sepia). | 22 | * ANSI foreground colors are modified to match colored theme backgrounds (e.g., Sepia). |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 7982841d..69e4fb01 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -105,7 +105,8 @@ struct Impl_SidebarWidget { | |||
105 | int itemFonts[2]; | 105 | int itemFonts[2]; |
106 | size_t numUnreadEntries; | 106 | size_t numUnreadEntries; |
107 | iWidget * resizer; | 107 | iWidget * resizer; |
108 | iWidget * menu; | 108 | iWidget * menu; /* context menu for an item */ |
109 | iWidget * modeMenu; /* context menu for the sidebar mode (no item) */ | ||
109 | iSidebarItem * contextItem; /* list item accessed in the context menu */ | 110 | iSidebarItem * contextItem; /* list item accessed in the context menu */ |
110 | size_t contextIndex; /* index of list item accessed in the context menu */ | 111 | size_t contextIndex; /* index of list item accessed in the context menu */ |
111 | iIntSet * closedFolders; /* otherwise open */ | 112 | iIntSet * closedFolders; /* otherwise open */ |
@@ -269,7 +270,9 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
269 | releaseChildren_Widget(d->actions); | 270 | releaseChildren_Widget(d->actions); |
270 | d->actions->rect.size.y = 0; | 271 | d->actions->rect.size.y = 0; |
271 | destroy_Widget(d->menu); | 272 | destroy_Widget(d->menu); |
272 | d->menu = NULL; | 273 | destroy_Widget(d->modeMenu); |
274 | d->menu = NULL; | ||
275 | d->modeMenu = NULL; | ||
273 | iBool isEmpty = iFalse; /* show blank? */ | 276 | iBool isEmpty = iFalse; /* show blank? */ |
274 | switch (d->mode) { | 277 | switch (d->mode) { |
275 | case feeds_SidebarMode: { | 278 | case feeds_SidebarMode: { |
@@ -380,6 +383,12 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
380 | { check_Icon " ${feeds.markallread}", SDLK_a, KMOD_SHIFT, "feeds.markallread" }, | 383 | { check_Icon " ${feeds.markallread}", SDLK_a, KMOD_SHIFT, "feeds.markallread" }, |
381 | { reload_Icon " ${feeds.refresh}", SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh" } }, | 384 | { reload_Icon " ${feeds.refresh}", SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh" } }, |
382 | 10); | 385 | 10); |
386 | d->modeMenu = makeMenu_Widget( | ||
387 | as_Widget(d), | ||
388 | (iMenuItem[]){ | ||
389 | { check_Icon " ${feeds.markallread}", SDLK_a, KMOD_SHIFT, "feeds.markallread" }, | ||
390 | { reload_Icon " ${feeds.refresh}", SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh" } }, | ||
391 | 2); | ||
383 | break; | 392 | break; |
384 | } | 393 | } |
385 | case documentOutline_SidebarMode: { | 394 | case documentOutline_SidebarMode: { |
@@ -467,6 +476,15 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
467 | { "---", 0, 0, NULL }, | 476 | { "---", 0, 0, NULL }, |
468 | { reload_Icon " ${bookmarks.reload}", 0, 0, "bookmarks.reload.remote" } }, | 477 | { reload_Icon " ${bookmarks.reload}", 0, 0, "bookmarks.reload.remote" } }, |
469 | 17); | 478 | 17); |
479 | d->modeMenu = makeMenu_Widget( | ||
480 | as_Widget(d), | ||
481 | (iMenuItem[]){ { bookmark_Icon " ${menu.page.bookmark}", SDLK_d, KMOD_PRIMARY, "bookmark.add" }, | ||
482 | { add_Icon " ${menu.newfolder}", 0, 0, "bookmark.addfolder" }, | ||
483 | { "---", 0, 0, NULL }, | ||
484 | { upDownArrow_Icon " ${menu.sort.alpha}", 0, 0, "bookmark.sortfolder" }, | ||
485 | { "---", 0, 0, NULL }, | ||
486 | { reload_Icon " ${bookmarks.reload}", 0, 0, "bookmarks.reload.remote" } }, | ||
487 | 6); | ||
470 | break; | 488 | break; |
471 | } | 489 | } |
472 | case history_SidebarMode: { | 490 | case history_SidebarMode: { |
@@ -521,6 +539,11 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
521 | { "---", 0, 0, NULL }, | 539 | { "---", 0, 0, NULL }, |
522 | { delete_Icon " " uiTextCaution_ColorEscape "${history.clear}", 0, 0, "history.clear confirm:1" }, | 540 | { delete_Icon " " uiTextCaution_ColorEscape "${history.clear}", 0, 0, "history.clear confirm:1" }, |
523 | }, 6); | 541 | }, 6); |
542 | d->modeMenu = makeMenu_Widget( | ||
543 | as_Widget(d), | ||
544 | (iMenuItem[]){ | ||
545 | { delete_Icon " " uiTextCaution_ColorEscape "${history.clear}", 0, 0, "history.clear confirm:1" }, | ||
546 | }, 1); | ||
524 | break; | 547 | break; |
525 | } | 548 | } |
526 | case identities_SidebarMode: { | 549 | case identities_SidebarMode: { |
@@ -569,21 +592,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
569 | addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); | 592 | addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); |
570 | addActionButton_SidebarWidget_(d, "${sidebar.action.ident.import}", "ident.import", 0); | 593 | addActionButton_SidebarWidget_(d, "${sidebar.action.ident.import}", "ident.import", 0); |
571 | } | 594 | } |
572 | /* | ||
573 | const iMenuItem menuItems[] = { | ||
574 | { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" }, | ||
575 | { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" }, | ||
576 | { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" }, | ||
577 | { "---", 0, 0, NULL }, | ||
578 | { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" }, | ||
579 | { "${ident.fingerprint}", 0, 0, "ident.fingerprint" }, | ||
580 | // { "Pick Icon...", 0, 0, "ident.pickicon" }, | ||
581 | { "---", 0, 0, NULL }, | ||
582 | //{ "Reveal Files", 0, 0, "ident.reveal" }, | ||
583 | { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" }, | ||
584 | }; | ||
585 | d->menu = makeMenu_Widget(as_Widget(d), menuItems, iElemCount(menuItems)); | ||
586 | */ | ||
587 | break; | 595 | break; |
588 | } | 596 | } |
589 | default: | 597 | default: |
@@ -850,7 +858,8 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { | |||
850 | } | 858 | } |
851 | setId_Widget(d->resizer, side == left_SidebarSide ? "sidebar.grab" : "sidebar2.grab"); | 859 | setId_Widget(d->resizer, side == left_SidebarSide ? "sidebar.grab" : "sidebar2.grab"); |
852 | setBackgroundColor_Widget(d->resizer, none_ColorId); | 860 | setBackgroundColor_Widget(d->resizer, none_ColorId); |
853 | d->menu = NULL; | 861 | d->menu = NULL; |
862 | d->modeMenu = NULL; | ||
854 | addAction_Widget(w, SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh"); | 863 | addAction_Widget(w, SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh"); |
855 | updateMetrics_SidebarWidget_(d); | 864 | updateMetrics_SidebarWidget_(d); |
856 | if (side == left_SidebarSide) { | 865 | if (side == left_SidebarSide) { |
@@ -1678,7 +1687,8 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1678 | return iTrue; | 1687 | return iTrue; |
1679 | } | 1688 | } |
1680 | } | 1689 | } |
1681 | if (ev->type == SDL_MOUSEMOTION && !isVisible_Widget(d->menu)) { | 1690 | if (ev->type == SDL_MOUSEMOTION && |
1691 | (!isVisible_Widget(d->menu) && !isVisible_Widget(d->modeMenu))) { | ||
1682 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); | 1692 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); |
1683 | if (contains_Widget(d->resizer, mouse)) { | 1693 | if (contains_Widget(d->resizer, mouse)) { |
1684 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_SIZEWE); | 1694 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_SIZEWE); |
@@ -1700,7 +1710,8 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1700 | d->contextIndex = iInvalidPos; | 1710 | d->contextIndex = iInvalidPos; |
1701 | } | 1711 | } |
1702 | } | 1712 | } |
1703 | if ((d->menu || d->mode == identities_SidebarMode )&& ev->type == SDL_MOUSEBUTTONDOWN) { | 1713 | /* Update context menu items. */ |
1714 | if ((d->menu || d->mode == identities_SidebarMode) && ev->type == SDL_MOUSEBUTTONDOWN) { | ||
1704 | if (ev->button.button == SDL_BUTTON_RIGHT) { | 1715 | if (ev->button.button == SDL_BUTTON_RIGHT) { |
1705 | d->contextItem = NULL; | 1716 | d->contextItem = NULL; |
1706 | if (!isVisible_Widget(d->menu)) { | 1717 | if (!isVisible_Widget(d->menu)) { |
@@ -1713,10 +1724,9 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1713 | invalidateItem_ListWidget(d->list, d->contextIndex); | 1724 | invalidateItem_ListWidget(d->list, d->contextIndex); |
1714 | } | 1725 | } |
1715 | d->contextIndex = hoverItemIndex_ListWidget(d->list); | 1726 | d->contextIndex = hoverItemIndex_ListWidget(d->list); |
1716 | /* Update menu items. */ | ||
1717 | updateContextMenu_SidebarWidget_(d); | 1727 | updateContextMenu_SidebarWidget_(d); |
1718 | /* TODO: Some callback-based mechanism would be nice for updating menus right | 1728 | /* TODO: Some callback-based mechanism would be nice for updating menus right |
1719 | before they open? */ | 1729 | before they open? At least move these to `updateContextMenu_ */ |
1720 | if (d->mode == bookmarks_SidebarMode && d->contextItem) { | 1730 | if (d->mode == bookmarks_SidebarMode && d->contextItem) { |
1721 | const iBookmark *bm = get_Bookmarks(bookmarks_App(), d->contextItem->id); | 1731 | const iBookmark *bm = get_Bookmarks(bookmarks_App(), d->contextItem->id); |
1722 | if (bm) { | 1732 | if (bm) { |
@@ -1761,13 +1771,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1761 | (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) || | 1771 | (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) || |
1762 | (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl))); | 1772 | (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl))); |
1763 | } | 1773 | } |
1764 | /* | ||
1765 | else if (equal_Command(cmdItem, "ident.showuse")) { | ||
1766 | setFlags_Widget(as_Widget(menuItem), | ||
1767 | disabled_WidgetFlag, | ||
1768 | !isUsed_GmIdentity(ident)); | ||
1769 | } | ||
1770 | */ | ||
1771 | } | 1774 | } |
1772 | } | 1775 | } |
1773 | } | 1776 | } |
@@ -1784,28 +1787,33 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1784 | } | 1787 | } |
1785 | } | 1788 | } |
1786 | if (ev->type == SDL_MOUSEBUTTONDOWN && | 1789 | if (ev->type == SDL_MOUSEBUTTONDOWN && |
1787 | contains_Widget(as_Widget(d->list), init_I2(ev->button.x, ev->button.y)) && | 1790 | contains_Widget(as_Widget(d->list), init_I2(ev->button.x, ev->button.y))) { |
1788 | (hoverItem_ListWidget(d->list) || isVisible_Widget(d->menu))) { | 1791 | if (hoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { |
1789 | /* Update the menu before opening. */ | 1792 | /* Update the menu before opening. */ |
1790 | if (d->mode == bookmarks_SidebarMode && !isVisible_Widget(d->menu)) { | 1793 | /* TODO: This kind of updating is already done above, and in `updateContextMenu_`... */ |
1791 | /* Remote bookmarks have limitations. */ | 1794 | if (d->mode == bookmarks_SidebarMode && !isVisible_Widget(d->menu)) { |
1792 | const iSidebarItem *hoverItem = hoverItem_ListWidget(d->list); | 1795 | /* Remote bookmarks have limitations. */ |
1793 | iAssert(hoverItem); | 1796 | const iSidebarItem *hoverItem = hoverItem_ListWidget(d->list); |
1794 | const iBookmark * bm = get_Bookmarks(bookmarks_App(), hoverItem->id); | 1797 | iAssert(hoverItem); |
1795 | const iBool isRemote = hasTag_Bookmark(bm, remote_BookmarkTag); | 1798 | const iBookmark * bm = get_Bookmarks(bookmarks_App(), hoverItem->id); |
1796 | static const char *localOnlyCmds[] = { "bookmark.edit", | 1799 | const iBool isRemote = hasTag_Bookmark(bm, remote_BookmarkTag); |
1797 | "bookmark.delete", | 1800 | static const char *localOnlyCmds[] = { "bookmark.edit", |
1798 | "bookmark.tag tag:" subscribed_BookmarkTag, | 1801 | "bookmark.delete", |
1799 | "bookmark.tag tag:" homepage_BookmarkTag, | 1802 | "bookmark.tag tag:" subscribed_BookmarkTag, |
1800 | "bookmark.tag tag:" remoteSource_BookmarkTag, | 1803 | "bookmark.tag tag:" homepage_BookmarkTag, |
1801 | "bookmark.tag tag:" subscribed_BookmarkTag }; | 1804 | "bookmark.tag tag:" remoteSource_BookmarkTag, |
1802 | iForIndices(i, localOnlyCmds) { | 1805 | "bookmark.tag tag:" subscribed_BookmarkTag }; |
1803 | setFlags_Widget(as_Widget(findMenuItem_Widget(d->menu, localOnlyCmds[i])), | 1806 | iForIndices(i, localOnlyCmds) { |
1804 | disabled_WidgetFlag, | 1807 | setFlags_Widget(as_Widget(findMenuItem_Widget(d->menu, localOnlyCmds[i])), |
1805 | isRemote); | 1808 | disabled_WidgetFlag, |
1806 | } | 1809 | isRemote); |
1807 | } | 1810 | } |
1808 | processContextMenuEvent_Widget(d->menu, ev, {}); | 1811 | } |
1812 | processContextMenuEvent_Widget(d->menu, ev, {}); | ||
1813 | } | ||
1814 | else if (!constHoverItem_ListWidget(d->list) || isVisible_Widget(d->modeMenu)) { | ||
1815 | processContextMenuEvent_Widget(d->modeMenu, ev, {}); | ||
1816 | } | ||
1809 | } | 1817 | } |
1810 | return processEvent_Widget(w, ev); | 1818 | return processEvent_Widget(w, ev); |
1811 | } | 1819 | } |