summaryrefslogtreecommitdiff
path: root/src/ui/sidebarwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/sidebarwidget.c')
-rw-r--r--src/ui/sidebarwidget.c335
1 files changed, 37 insertions, 298 deletions
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 9cfc507a..8440a597 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
25#include "app.h" 25#include "app.h"
26#include "defs.h" 26#include "defs.h"
27#include "bookmarks.h" 27#include "bookmarks.h"
28#include "certlistwidget.h"
28#include "command.h" 29#include "command.h"
29#include "documentwidget.h" 30#include "documentwidget.h"
30#include "feeds.h" 31#include "feeds.h"
@@ -96,6 +97,7 @@ struct Impl_SidebarWidget {
96 iString cmdPrefix; 97 iString cmdPrefix;
97 iWidget * blank; 98 iWidget * blank;
98 iListWidget * list; 99 iListWidget * list;
100 iCertListWidget * certList;
99 iWidget * actions; /* below the list, area for buttons */ 101 iWidget * actions; /* below the list, area for buttons */
100 int modeScroll[max_SidebarMode]; 102 int modeScroll[max_SidebarMode];
101 iLabelWidget * modeButtons[max_SidebarMode]; 103 iLabelWidget * modeButtons[max_SidebarMode];
@@ -114,6 +116,10 @@ struct Impl_SidebarWidget {
114 116
115iDefineObjectConstructionArgs(SidebarWidget, (enum iSidebarSide side), side) 117iDefineObjectConstructionArgs(SidebarWidget, (enum iSidebarSide side), side)
116 118
119iLocalDef iListWidget *list_SidebarWidget_(iSidebarWidget *d) {
120 return d->mode == identities_SidebarMode ? (iListWidget *) d->certList : d->list;
121}
122
117static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { 123static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) {
118 return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0; 124 return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0;
119} 125}
@@ -195,65 +201,6 @@ static iLabelWidget *addActionButton_SidebarWidget_(iSidebarWidget *d, const cha
195 return btn; 201 return btn;
196} 202}
197 203
198static iGmIdentity *menuIdentity_SidebarWidget_(const iSidebarWidget *d) {
199 if (d->mode == identities_SidebarMode) {
200 if (d->contextItem) {
201 return identity_GmCerts(certs_App(), d->contextItem->id);
202 }
203 }
204 return NULL;
205}
206
207static void updateContextMenu_SidebarWidget_(iSidebarWidget *d) {
208 if (d->mode != identities_SidebarMode) {
209 return;
210 }
211 iArray *items = collectNew_Array(sizeof(iMenuItem));
212 pushBackN_Array(items, (iMenuItem[]){
213 { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" },
214 { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" },
215 { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" },
216 { "---", 0, 0, NULL },
217 { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" },
218 { "${ident.fingerprint}", 0, 0, "ident.fingerprint" },
219 { export_Icon " ${ident.export}", 0, 0, "ident.export" },
220 { "---", 0, 0, NULL },
221 { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" },
222 }, 9);
223 /* Used URLs. */
224 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d);
225 if (ident) {
226 size_t insertPos = 3;
227 if (!isEmpty_StringSet(ident->useUrls)) {
228 insert_Array(items, insertPos++, &(iMenuItem){ "---", 0, 0, NULL });
229 }
230 const iString *docUrl = url_DocumentWidget(document_App());
231 iBool usedOnCurrentPage = iFalse;
232 iConstForEach(StringSet, i, ident->useUrls) {
233 const iString *url = i.value;
234 usedOnCurrentPage |= equalCase_String(docUrl, url);
235 iRangecc urlStr = range_String(url);
236 if (startsWith_Rangecc(urlStr, "gemini://")) {
237 urlStr.start += 9; /* omit the default scheme */
238 }
239 if (endsWith_Rangecc(urlStr, "/")) {
240 urlStr.end--; /* looks cleaner */
241 }
242 insert_Array(items,
243 insertPos++,
244 &(iMenuItem){ format_CStr(globe_Icon " %s", cstr_Rangecc(urlStr)),
245 0,
246 0,
247 format_CStr("!open url:%s", cstr_String(url)) });
248 }
249 if (!usedOnCurrentPage) {
250 remove_Array(items, 1);
251 }
252 }
253 destroy_Widget(d->menu);
254 d->menu = makeMenu_Widget(as_Widget(d), data_Array(items), size_Array(items));
255}
256
257static iBool isBookmarkFolded_SidebarWidget_(const iSidebarWidget *d, const iBookmark *bm) { 204static iBool isBookmarkFolded_SidebarWidget_(const iSidebarWidget *d, const iBookmark *bm) {
258 while (bm->parentId) { 205 while (bm->parentId) {
259 if (contains_IntSet(d->closedFolders, bm->parentId)) { 206 if (contains_IntSet(d->closedFolders, bm->parentId)) {
@@ -547,46 +494,7 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
547 break; 494 break;
548 } 495 }
549 case identities_SidebarMode: { 496 case identities_SidebarMode: {
550 const iString *tabUrl = url_DocumentWidget(document_App()); 497 isEmpty = !updateItems_CertListWidget(d->certList);
551 const iRangecc tabHost = urlHost_String(tabUrl);
552 isEmpty = iTrue;
553 iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) {
554 const iGmIdentity *ident = i.ptr;
555 iSidebarItem *item = new_SidebarItem();
556 item->id = (uint32_t) index_PtrArrayConstIterator(&i);
557 item->icon = 0x1f464; /* person */
558 set_String(&item->label, name_GmIdentity(ident));
559 iDate until;
560 validUntil_TlsCertificate(ident->cert, &until);
561 const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl);
562 format_String(&item->meta,
563 "%s",
564 isActive ? cstr_Lang("ident.using")
565 : isUsed_GmIdentity(ident)
566 ? formatCStrs_Lang("ident.usedonurls.n", size_StringSet(ident->useUrls))
567 : cstr_Lang("ident.notused"));
568 const char *expiry =
569 ident->flags & temporary_GmIdentityFlag
570 ? cstr_Lang("ident.temporary")
571 : cstrCollect_String(format_Date(&until, cstr_Lang("ident.expiry")));
572 if (isEmpty_String(&ident->notes)) {
573 appendFormat_String(&item->meta, "\n%s", expiry);
574 }
575 else {
576 appendFormat_String(&item->meta,
577 " \u2014 %s\n%s%s",
578 expiry,
579 escape_Color(uiHeading_ColorId),
580 cstr_String(&ident->notes));
581 }
582 item->listItem.isSelected = isActive;
583 if (isUsedOnDomain_GmIdentity(ident, tabHost)) {
584 item->indent = 1; /* will be highlighted */
585 }
586 addItem_ListWidget(d->list, item);
587 iRelease(item);
588 isEmpty = iFalse;
589 }
590 /* Actions. */ 498 /* Actions. */
591 if (!isEmpty) { 499 if (!isEmpty) {
592 addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); 500 addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0);
@@ -597,9 +505,11 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
597 default: 505 default:
598 break; 506 break;
599 } 507 }
600 scrollOffset_ListWidget(d->list, 0); 508 setFlags_Widget(as_Widget(d->list), hidden_WidgetFlag, d->mode == identities_SidebarMode);
601 updateVisible_ListWidget(d->list); 509 setFlags_Widget(as_Widget(d->certList), hidden_WidgetFlag, d->mode != identities_SidebarMode);
602 invalidate_ListWidget(d->list); 510 scrollOffset_ListWidget(list_SidebarWidget_(d), 0);
511 updateVisible_ListWidget(list_SidebarWidget_(d));
512 invalidate_ListWidget(list_SidebarWidget_(d));
603 /* Content for a blank tab. */ 513 /* Content for a blank tab. */
604 if (isEmpty) { 514 if (isEmpty) {
605 if (d->mode == feeds_SidebarMode) { 515 if (d->mode == feeds_SidebarMode) {
@@ -649,7 +559,7 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
649#endif 559#endif
650 arrange_Widget(d->actions); 560 arrange_Widget(d->actions);
651 arrange_Widget(as_Widget(d)); 561 arrange_Widget(as_Widget(d));
652 updateMouseHover_ListWidget(d->list); 562 updateMouseHover_ListWidget(list_SidebarWidget_(d));
653} 563}
654 564
655static void updateItems_SidebarWidget_(iSidebarWidget *d) { 565static void updateItems_SidebarWidget_(iSidebarWidget *d) {
@@ -668,10 +578,11 @@ static size_t findItem_SidebarWidget_(const iSidebarWidget *d, int id) {
668} 578}
669 579
670static void updateItemHeight_SidebarWidget_(iSidebarWidget *d) { 580static void updateItemHeight_SidebarWidget_(iSidebarWidget *d) {
581 const float heights[max_SidebarMode] = { 1.333f, 2.333f, 1.333f, 3.5f, 1.2f };
671 if (d->list) { 582 if (d->list) {
672 const float heights[max_SidebarMode] = { 1.333f, 2.333f, 1.333f, 3.5f, 1.2f };
673 setItemHeight_ListWidget(d->list, heights[d->mode] * lineHeight_Text(d->itemFonts[0])); 583 setItemHeight_ListWidget(d->list, heights[d->mode] * lineHeight_Text(d->itemFonts[0]));
674 } 584 }
585 updateItemHeight_CertListWidget(d->certList);
675} 586}
676 587
677iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { 588iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) {
@@ -679,18 +590,18 @@ iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) {
679 return iFalse; 590 return iFalse;
680 } 591 }
681 if (d->mode >= 0 && d->mode < max_SidebarMode) { 592 if (d->mode >= 0 && d->mode < max_SidebarMode) {
682 d->modeScroll[d->mode] = scrollPos_ListWidget(d->list); /* saved for later */ 593 d->modeScroll[d->mode] = scrollPos_ListWidget(list_SidebarWidget_(d)); /* saved for later */
683 } 594 }
684 d->mode = mode; 595 d->mode = mode;
685 for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) { 596 for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) {
686 setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode); 597 setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode);
687 } 598 }
688 setBackgroundColor_Widget(as_Widget(d->list), 599 setBackgroundColor_Widget(as_Widget(list_SidebarWidget_(d)),
689 d->mode == documentOutline_SidebarMode ? tmBannerBackground_ColorId 600 d->mode == documentOutline_SidebarMode ? tmBannerBackground_ColorId
690 : uiBackgroundSidebar_ColorId); 601 : uiBackgroundSidebar_ColorId);
691 updateItemHeight_SidebarWidget_(d); 602 updateItemHeight_SidebarWidget_(d);
692 /* Restore previous scroll position. */ 603 /* Restore previous scroll position. */
693 setScrollPos_ListWidget(d->list, d->modeScroll[mode]); 604 setScrollPos_ListWidget(list_SidebarWidget_(d), d->modeScroll[mode]);
694 return iTrue; 605 return iTrue;
695} 606}
696 607
@@ -787,6 +698,7 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) {
787 iZap(d->modeButtons); 698 iZap(d->modeButtons);
788 d->resizer = NULL; 699 d->resizer = NULL;
789 d->list = NULL; 700 d->list = NULL;
701 d->certList = NULL;
790 d->actions = NULL; 702 d->actions = NULL;
791 d->closedFolders = new_IntSet(); 703 d->closedFolders = new_IntSet();
792 /* On a phone, the right sidebar is used exclusively for Identities. */ 704 /* On a phone, the right sidebar is used exclusively for Identities. */
@@ -829,10 +741,16 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) {
829 setFlags_Widget(content, resizeChildren_WidgetFlag, iTrue); 741 setFlags_Widget(content, resizeChildren_WidgetFlag, iTrue);
830 iWidget *listAndActions = makeVDiv_Widget(); 742 iWidget *listAndActions = makeVDiv_Widget();
831 addChild_Widget(content, iClob(listAndActions)); 743 addChild_Widget(content, iClob(listAndActions));
832 d->list = new_ListWidget(); 744 iWidget *listArea = new_Widget();
745 setFlags_Widget(listArea, resizeChildren_WidgetFlag, iTrue);
746 d->list = new_ListWidget();
833 setPadding_Widget(as_Widget(d->list), 0, gap_UI, 0, gap_UI); 747 setPadding_Widget(as_Widget(d->list), 0, gap_UI, 0, gap_UI);
748 addChild_Widget(listArea, iClob(d->list));
749 d->certList = new_CertListWidget();
750 setPadding_Widget(as_Widget(d->certList), 0, gap_UI, 0, gap_UI);
751 addChild_Widget(listArea, iClob(d->certList));
834 addChildFlags_Widget(listAndActions, 752 addChildFlags_Widget(listAndActions,
835 iClob(d->list), 753 iClob(listArea),
836 expand_WidgetFlag); // | drawBackgroundToHorizontalSafeArea_WidgetFlag); 754 expand_WidgetFlag); // | drawBackgroundToHorizontalSafeArea_WidgetFlag);
837 setId_Widget(addChildPosFlags_Widget(listAndActions, 755 setId_Widget(addChildPosFlags_Widget(listAndActions,
838 iClob(d->actions = new_Widget()), 756 iClob(d->actions = new_Widget()),
@@ -892,16 +810,16 @@ iBool setButtonFont_SidebarWidget(iSidebarWidget *d, int font) {
892 810
893static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) { 811static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) {
894 if (d->mode == identities_SidebarMode) { 812 if (d->mode == identities_SidebarMode) {
895 const iSidebarItem *hoverItem = constHoverItem_ListWidget(d->list); 813 return constHoverIdentity_CertListWidget(d->certList);
896 if (hoverItem) {
897 return identity_GmCerts(certs_App(), hoverItem->id);
898 }
899 } 814 }
900 return NULL; 815 return NULL;
901} 816}
902 817
903static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) { 818static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) {
904 return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); 819 if (d->mode == identities_SidebarMode) {
820 return hoverIdentity_CertListWidget(d->certList);
821 }
822 return NULL;
905} 823}
906 824
907static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, size_t itemIndex) { 825static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, size_t itemIndex) {
@@ -944,23 +862,6 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, si
944 } 862 }
945 break; 863 break;
946 } 864 }
947 case identities_SidebarMode: {
948 d->contextItem = item;
949 if (d->contextIndex != iInvalidPos) {
950 invalidateItem_ListWidget(d->list, d->contextIndex);
951 }
952 d->contextIndex = itemIndex;
953 if (itemIndex < numItems_ListWidget(d->list)) {
954 updateContextMenu_SidebarWidget_(d);
955 arrange_Widget(d->menu);
956 openMenu_Widget(d->menu,
957 d->side == left_SidebarSide
958 ? topRight_Rect(itemRect_ListWidget(d->list, itemIndex))
959 : addX_I2(topLeft_Rect(itemRect_ListWidget(d->list, itemIndex)),
960 -width_Widget(d->menu)));
961 }
962 break;
963 }
964 default: 865 default:
965 break; 866 break;
966 } 867 }
@@ -1245,9 +1146,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1245 } 1146 }
1246 } 1147 }
1247 } 1148 }
1248 else if (equal_Command(cmd, "idents.changed") && d->mode == identities_SidebarMode) {
1249 updateItems_SidebarWidget_(d);
1250 }
1251 else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) { 1149 else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) {
1252 postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode); 1150 postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode);
1253 return iTrue; 1151 return iTrue;
@@ -1316,9 +1214,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1316 } 1214 }
1317 return iTrue; 1215 return iTrue;
1318 } 1216 }
1319// else if (isCommand_Widget(w, ev, "menu.closed")) {
1320 // invalidateItem_ListWidget(d->list, d->contextIndex);
1321// }
1322 else if (isCommand_Widget(w, ev, "bookmark.open")) { 1217 else if (isCommand_Widget(w, ev, "bookmark.open")) {
1323 const iSidebarItem *item = d->contextItem; 1218 const iSidebarItem *item = d->contextItem;
1324 if (d->mode == bookmarks_SidebarMode && item) { 1219 if (d->mode == bookmarks_SidebarMode && item) {
@@ -1548,103 +1443,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1548 } 1443 }
1549 } 1444 }
1550 } 1445 }
1551 else if (isCommand_Widget(w, ev, "ident.use")) {
1552 iGmIdentity * ident = menuIdentity_SidebarWidget_(d);
1553 const iString *tabUrl = url_DocumentWidget(document_App());
1554 if (ident) {
1555 if (argLabel_Command(cmd, "clear")) {
1556 clearUse_GmIdentity(ident);
1557 }
1558 else if (arg_Command(cmd)) {
1559 signIn_GmCerts(certs_App(), ident, tabUrl);
1560 postCommand_App("navigate.reload");
1561 }
1562 else {
1563 signOut_GmCerts(certs_App(), tabUrl);
1564 postCommand_App("navigate.reload");
1565 }
1566 saveIdentities_GmCerts(certs_App());
1567 updateItems_SidebarWidget_(d);
1568 }
1569 return iTrue;
1570 }
1571 else if (isCommand_Widget(w, ev, "ident.edit")) {
1572 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d);
1573 if (ident) {
1574 makeValueInput_Widget(get_Root()->widget,
1575 &ident->notes,
1576 uiHeading_ColorEscape "${heading.ident.notes}",
1577 format_CStr(cstr_Lang("dlg.ident.notes"), cstr_String(name_GmIdentity(ident))),
1578 uiTextAction_ColorEscape "${dlg.default}",
1579 format_CStr("!ident.setnotes ident:%p ptr:%p", ident, d));
1580 }
1581 return iTrue;
1582 }
1583 else if (isCommand_Widget(w, ev, "ident.fingerprint")) {
1584 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d);
1585 if (ident) {
1586 const iString *fps = collect_String(
1587 hexEncode_Block(collect_Block(fingerprint_TlsCertificate(ident->cert))));
1588 SDL_SetClipboardText(cstr_String(fps));
1589 }
1590 return iTrue;
1591 }
1592 else if (isCommand_Widget(w, ev, "ident.export")) {
1593 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d);
1594 if (ident) {
1595 iString *pem = collect_String(pem_TlsCertificate(ident->cert));
1596 append_String(pem, collect_String(privateKeyPem_TlsCertificate(ident->cert)));
1597 iDocumentWidget *expTab = newTab_App(NULL, iTrue);
1598 setUrlAndSource_DocumentWidget(
1599 expTab,
1600 collectNewFormat_String("file:%s.pem", cstr_String(name_GmIdentity(ident))),
1601 collectNewCStr_String("text/plain"),
1602 utf8_String(pem));
1603 }
1604 return iTrue;
1605 }
1606 else if (isCommand_Widget(w, ev, "ident.setnotes")) {
1607 iGmIdentity *ident = pointerLabel_Command(cmd, "ident");
1608 if (ident) {
1609 setCStr_String(&ident->notes, suffixPtr_Command(cmd, "value"));
1610 updateItems_SidebarWidget_(d);
1611 }
1612 return iTrue;
1613 }
1614 else if (isCommand_Widget(w, ev, "ident.pickicon")) {
1615 return iTrue;
1616 }
1617 else if (isCommand_Widget(w, ev, "ident.reveal")) {
1618 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d);
1619 if (ident) {
1620 const iString *crtPath = certificatePath_GmCerts(certs_App(), ident);
1621 if (crtPath) {
1622 revealPath_App(crtPath);
1623 }
1624 }
1625 return iTrue;
1626 }
1627 else if (isCommand_Widget(w, ev, "ident.delete")) {
1628 iSidebarItem *item = d->contextItem;
1629 if (argLabel_Command(cmd, "confirm")) {
1630 makeQuestion_Widget(
1631 uiTextCaution_ColorEscape "${heading.ident.delete}",
1632 format_CStr(cstr_Lang("dlg.confirm.ident.delete"),
1633 uiTextAction_ColorEscape,
1634 cstr_String(&item->label),
1635 uiText_ColorEscape),
1636 (iMenuItem[]){ { "${cancel}", 0, 0, NULL },
1637 { uiTextCaution_ColorEscape "${dlg.ident.delete}",
1638 0,
1639 0,
1640 format_CStr("!ident.delete confirm:0 ptr:%p", d) } },
1641 2);
1642 return iTrue;
1643 }
1644 deleteIdentity_GmCerts(certs_App(), menuIdentity_SidebarWidget_(d));
1645 postCommand_App("idents.changed");
1646 return iTrue;
1647 }
1648 else if (isCommand_Widget(w, ev, "history.delete")) { 1446 else if (isCommand_Widget(w, ev, "history.delete")) {
1649 if (d->contextItem && !isEmpty_String(&d->contextItem->url)) { 1447 if (d->contextItem && !isEmpty_String(&d->contextItem->url)) {
1650 removeUrl_Visited(visited_App(), &d->contextItem->url); 1448 removeUrl_Visited(visited_App(), &d->contextItem->url);
@@ -1698,14 +1496,10 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1698 /* Update cursor. */ 1496 /* Update cursor. */
1699 else if (contains_Widget(w, mouse)) { 1497 else if (contains_Widget(w, mouse)) {
1700 const iSidebarItem *item = constHoverItem_ListWidget(d->list); 1498 const iSidebarItem *item = constHoverItem_ListWidget(d->list);
1701 if (item && d->mode != identities_SidebarMode) { 1499 setCursor_Window(get_Window(),
1702 setCursor_Window(get_Window(), 1500 item ? (item->listItem.isSeparator ? SDL_SYSTEM_CURSOR_ARROW
1703 item->listItem.isSeparator ? SDL_SYSTEM_CURSOR_ARROW 1501 : SDL_SYSTEM_CURSOR_HAND)
1704 : SDL_SYSTEM_CURSOR_HAND); 1502 : SDL_SYSTEM_CURSOR_ARROW);
1705 }
1706 else {
1707 setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW);
1708 }
1709 } 1503 }
1710 if (d->contextIndex != iInvalidPos) { 1504 if (d->contextIndex != iInvalidPos) {
1711 invalidateItem_ListWidget(d->list, d->contextIndex); 1505 invalidateItem_ListWidget(d->list, d->contextIndex);
@@ -1713,7 +1507,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1713 } 1507 }
1714 } 1508 }
1715 /* Update context menu items. */ 1509 /* Update context menu items. */
1716 if ((d->menu || d->mode == identities_SidebarMode) && ev->type == SDL_MOUSEBUTTONDOWN) { 1510 if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) {
1717 if (ev->button.button == SDL_BUTTON_RIGHT) { 1511 if (ev->button.button == SDL_BUTTON_RIGHT) {
1718 d->contextItem = NULL; 1512 d->contextItem = NULL;
1719 if (!isVisible_Widget(d->menu)) { 1513 if (!isVisible_Widget(d->menu)) {
@@ -1726,7 +1520,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1726 invalidateItem_ListWidget(d->list, d->contextIndex); 1520 invalidateItem_ListWidget(d->list, d->contextIndex);
1727 } 1521 }
1728 d->contextIndex = hoverItemIndex_ListWidget(d->list); 1522 d->contextIndex = hoverItemIndex_ListWidget(d->list);
1729 updateContextMenu_SidebarWidget_(d);
1730 /* TODO: Some callback-based mechanism would be nice for updating menus right 1523 /* TODO: Some callback-based mechanism would be nice for updating menus right
1731 before they open? At least move these to `updateContextMenu_ */ 1524 before they open? At least move these to `updateContextMenu_ */
1732 if (d->mode == bookmarks_SidebarMode && d->contextItem) { 1525 if (d->mode == bookmarks_SidebarMode && d->contextItem) {
@@ -1756,26 +1549,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1756 isRead ? circle_Icon " ${feeds.entry.markunread}" 1549 isRead ? circle_Icon " ${feeds.entry.markunread}"
1757 : circleWhite_Icon " ${feeds.entry.markread}"); 1550 : circleWhite_Icon " ${feeds.entry.markread}");
1758 } 1551 }
1759 else if (d->mode == identities_SidebarMode) {
1760 const iGmIdentity *ident = constHoverIdentity_SidebarWidget_(d);
1761 const iString * docUrl = url_DocumentWidget(document_App());
1762 iForEach(ObjectList, i, children_Widget(d->menu)) {
1763 if (isInstance_Object(i.object, &Class_LabelWidget)) {
1764 iLabelWidget *menuItem = i.object;
1765 const char * cmdItem = cstr_String(command_LabelWidget(menuItem));
1766 if (equal_Command(cmdItem, "ident.use")) {
1767 const iBool cmdUse = arg_Command(cmdItem) != 0;
1768 const iBool cmdClear = argLabel_Command(cmdItem, "clear") != 0;
1769 setFlags_Widget(
1770 as_Widget(menuItem),
1771 disabled_WidgetFlag,
1772 (cmdClear && !isUsed_GmIdentity(ident)) ||
1773 (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) ||
1774 (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl)));
1775 }
1776 }
1777 }
1778 }
1779 } 1552 }
1780 } 1553 }
1781 } 1554 }
@@ -2077,40 +1850,6 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
2077 } 1850 }
2078 iEndCollect(); 1851 iEndCollect();
2079 } 1852 }
2080 else if (sidebar->mode == identities_SidebarMode) {
2081 const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId)
2082 : uiTextStrong_ColorId;
2083 const iBool isUsedOnDomain = (d->indent != 0);
2084 iString icon;
2085 initUnicodeN_String(&icon, &d->icon, 1);
2086 iInt2 cPos = topLeft_Rect(itemRect);
2087 const int indent = 1.4f * lineHeight_Text(font);
2088 addv_I2(&cPos,
2089 init_I2(3 * gap_UI,
2090 (itemHeight - lineHeight_Text(uiLabel_FontId) * 2 - lineHeight_Text(font)) /
2091 2));
2092 const int metaFg = isHover ? permanent_ColorId | (isPressing ? uiTextPressed_ColorId
2093 : uiTextFramelessHover_ColorId)
2094 : uiTextDim_ColorId;
2095 if (!d->listItem.isSelected && !isUsedOnDomain) {
2096 drawOutline_Text(font, cPos, metaFg, none_ColorId, range_String(&icon));
2097 }
2098 drawRange_Text(font,
2099 cPos,
2100 d->listItem.isSelected ? iconColor
2101 : isUsedOnDomain ? altIconColor
2102 : uiBackgroundSidebar_ColorId,
2103 range_String(&icon));
2104 deinit_String(&icon);
2105 drawRange_Text(d->listItem.isSelected ? sidebar->itemFonts[1] : font,
2106 add_I2(cPos, init_I2(indent, 0)),
2107 fg,
2108 range_String(&d->label));
2109 drawRange_Text(uiLabel_FontId,
2110 add_I2(cPos, init_I2(indent, lineHeight_Text(font))),
2111 metaFg,
2112 range_String(&d->meta));
2113 }
2114} 1853}
2115 1854
2116iBeginDefineSubclass(SidebarWidget, Widget) 1855iBeginDefineSubclass(SidebarWidget, Widget)