summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-11-24 18:28:13 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-11-24 18:45:22 +0200
commit0bfa17f463a8ef8b7ea5e3fc97a474bf60ce19da (patch)
tree59aa4635f515bc872fc30c83b6c3a65112b9ad26
parentd665405d5eafb48e442bf0de6fc499d91aa410d1 (diff)
SidebarWidget: Non-item-related context menus
IssueID #388
-rw-r--r--res/about/version.gmi1
-rw-r--r--src/ui/sidebarwidget.c110
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
18Changes and enhancements: 18Changes 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}