diff options
Diffstat (limited to 'src/ui/sidebarwidget.c')
-rw-r--r-- | src/ui/sidebarwidget.c | 200 |
1 files changed, 150 insertions, 50 deletions
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 86410d11..27646b22 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -148,6 +148,65 @@ static iLabelWidget *addActionButton_SidebarWidget_(iSidebarWidget *d, const cha | |||
148 | return btn; | 148 | return btn; |
149 | } | 149 | } |
150 | 150 | ||
151 | static iGmIdentity *menuIdentity_SidebarWidget_(const iSidebarWidget *d) { | ||
152 | if (d->mode == identities_SidebarMode) { | ||
153 | if (d->contextItem) { | ||
154 | return identity_GmCerts(certs_App(), d->contextItem->id); | ||
155 | } | ||
156 | } | ||
157 | return NULL; | ||
158 | } | ||
159 | |||
160 | static void updateContextMenu_SidebarWidget_(iSidebarWidget *d) { | ||
161 | if (d->mode != identities_SidebarMode) { | ||
162 | return; | ||
163 | } | ||
164 | iArray *items = collectNew_Array(sizeof(iMenuItem)); | ||
165 | pushBackN_Array(items, (iMenuItem[]){ | ||
166 | { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" }, | ||
167 | { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" }, | ||
168 | { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" }, | ||
169 | { "---", 0, 0, NULL }, | ||
170 | { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" }, | ||
171 | { "${ident.fingerprint}", 0, 0, "ident.fingerprint" }, | ||
172 | { export_Icon " ${ident.export}", 0, 0, "ident.export" }, | ||
173 | { "---", 0, 0, NULL }, | ||
174 | { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" }, | ||
175 | }, 9); | ||
176 | /* Used URLs. */ | ||
177 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
178 | if (ident) { | ||
179 | size_t insertPos = 3; | ||
180 | if (!isEmpty_StringSet(ident->useUrls)) { | ||
181 | insert_Array(items, insertPos++, &(iMenuItem){ "---", 0, 0, NULL }); | ||
182 | } | ||
183 | const iString *docUrl = url_DocumentWidget(document_App()); | ||
184 | iBool usedOnCurrentPage = iFalse; | ||
185 | iConstForEach(StringSet, i, ident->useUrls) { | ||
186 | const iString *url = i.value; | ||
187 | usedOnCurrentPage |= equalCase_String(docUrl, url); | ||
188 | iRangecc urlStr = range_String(url); | ||
189 | if (startsWith_Rangecc(urlStr, "gemini://")) { | ||
190 | urlStr.start += 9; /* omit the default scheme */ | ||
191 | } | ||
192 | if (endsWith_Rangecc(urlStr, "/")) { | ||
193 | urlStr.end--; /* looks cleaner */ | ||
194 | } | ||
195 | insert_Array(items, | ||
196 | insertPos++, | ||
197 | &(iMenuItem){ format_CStr(globe_Icon " %s", cstr_Rangecc(urlStr)), | ||
198 | 0, | ||
199 | 0, | ||
200 | format_CStr("!open url:%s", cstr_String(url)) }); | ||
201 | } | ||
202 | if (!usedOnCurrentPage) { | ||
203 | remove_Array(items, 1); | ||
204 | } | ||
205 | } | ||
206 | destroy_Widget(d->menu); | ||
207 | d->menu = makeMenu_Widget(as_Widget(d), data_Array(items), size_Array(items)); | ||
208 | } | ||
209 | |||
151 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { | 210 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { |
152 | clear_ListWidget(d->list); | 211 | clear_ListWidget(d->list); |
153 | releaseChildren_Widget(d->blank); | 212 | releaseChildren_Widget(d->blank); |
@@ -375,13 +434,14 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
375 | } | 434 | } |
376 | case identities_SidebarMode: { | 435 | case identities_SidebarMode: { |
377 | const iString *tabUrl = url_DocumentWidget(document_App()); | 436 | const iString *tabUrl = url_DocumentWidget(document_App()); |
437 | const iRangecc tabHost = urlHost_String(tabUrl); | ||
378 | isEmpty = iTrue; | 438 | isEmpty = iTrue; |
379 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { | 439 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { |
380 | const iGmIdentity *ident = i.ptr; | 440 | const iGmIdentity *ident = i.ptr; |
381 | iSidebarItem *item = new_SidebarItem(); | 441 | iSidebarItem *item = new_SidebarItem(); |
382 | item->id = (uint32_t) index_PtrArrayConstIterator(&i); | 442 | item->id = (uint32_t) index_PtrArrayConstIterator(&i); |
383 | item->icon = ident->icon; | 443 | item->icon = 0x1f464; /* person */ |
384 | set_String(&item->label, collect_String(subject_TlsCertificate(ident->cert))); | 444 | set_String(&item->label, name_GmIdentity(ident)); |
385 | iDate until; | 445 | iDate until; |
386 | validUntil_TlsCertificate(ident->cert, &until); | 446 | validUntil_TlsCertificate(ident->cert, &until); |
387 | const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl); | 447 | const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl); |
@@ -406,6 +466,9 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
406 | cstr_String(&ident->notes)); | 466 | cstr_String(&ident->notes)); |
407 | } | 467 | } |
408 | item->listItem.isSelected = isActive; | 468 | item->listItem.isSelected = isActive; |
469 | if (isUsedOnDomain_GmIdentity(ident, tabHost)) { | ||
470 | item->indent = 1; /* will be highlighted */ | ||
471 | } | ||
409 | addItem_ListWidget(d->list, item); | 472 | addItem_ListWidget(d->list, item); |
410 | iRelease(item); | 473 | iRelease(item); |
411 | isEmpty = iFalse; | 474 | isEmpty = iFalse; |
@@ -415,11 +478,11 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
415 | addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); | 478 | addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); |
416 | addActionButton_SidebarWidget_(d, "${sidebar.action.ident.import}", "ident.import", 0); | 479 | addActionButton_SidebarWidget_(d, "${sidebar.action.ident.import}", "ident.import", 0); |
417 | } | 480 | } |
481 | /* | ||
418 | const iMenuItem menuItems[] = { | 482 | const iMenuItem menuItems[] = { |
419 | { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" }, | 483 | { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" }, |
420 | { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" }, | 484 | { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" }, |
421 | { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" }, | 485 | { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" }, |
422 | { "${ident.showuse}", 0, 0, "ident.showuse" }, | ||
423 | { "---", 0, 0, NULL }, | 486 | { "---", 0, 0, NULL }, |
424 | { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" }, | 487 | { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" }, |
425 | { "${ident.fingerprint}", 0, 0, "ident.fingerprint" }, | 488 | { "${ident.fingerprint}", 0, 0, "ident.fingerprint" }, |
@@ -429,6 +492,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
429 | { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" }, | 492 | { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" }, |
430 | }; | 493 | }; |
431 | d->menu = makeMenu_Widget(as_Widget(d), menuItems, iElemCount(menuItems)); | 494 | d->menu = makeMenu_Widget(as_Widget(d), menuItems, iElemCount(menuItems)); |
495 | */ | ||
432 | break; | 496 | break; |
433 | } | 497 | } |
434 | default: | 498 | default: |
@@ -697,20 +761,11 @@ static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget | |||
697 | return NULL; | 761 | return NULL; |
698 | } | 762 | } |
699 | 763 | ||
700 | static iGmIdentity *menuIdentity_SidebarWidget_(const iSidebarWidget *d) { | ||
701 | if (d->mode == identities_SidebarMode) { | ||
702 | if (d->contextItem) { | ||
703 | return identity_GmCerts(certs_App(), d->contextItem->id); | ||
704 | } | ||
705 | } | ||
706 | return NULL; | ||
707 | } | ||
708 | |||
709 | static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) { | 764 | static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) { |
710 | return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); | 765 | return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); |
711 | } | 766 | } |
712 | 767 | ||
713 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, const iSidebarItem *item) { | 768 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, size_t itemIndex) { |
714 | setFocus_Widget(NULL); | 769 | setFocus_Widget(NULL); |
715 | switch (d->mode) { | 770 | switch (d->mode) { |
716 | case documentOutline_SidebarMode: { | 771 | case documentOutline_SidebarMode: { |
@@ -735,17 +790,19 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, const iSidebarItem *it | |||
735 | break; | 790 | break; |
736 | } | 791 | } |
737 | case identities_SidebarMode: { | 792 | case identities_SidebarMode: { |
738 | iGmIdentity *ident = hoverIdentity_SidebarWidget_(d); | 793 | d->contextItem = item; |
739 | if (ident) { | 794 | if (d->contextIndex != iInvalidPos) { |
740 | const iString *tabUrl = url_DocumentWidget(document_App()); | 795 | invalidateItem_ListWidget(d->list, d->contextIndex); |
741 | if (isUsedOn_GmIdentity(ident, tabUrl)) { | 796 | } |
742 | signOut_GmCerts(certs_App(), tabUrl); | 797 | d->contextIndex = itemIndex; |
743 | } | 798 | if (itemIndex < numItems_ListWidget(d->list)) { |
744 | else { | 799 | updateContextMenu_SidebarWidget_(d); |
745 | signIn_GmCerts(certs_App(), ident, tabUrl); | 800 | arrange_Widget(d->menu); |
746 | } | 801 | openMenu_Widget(d->menu, |
747 | updateItems_SidebarWidget_(d); | 802 | d->side == left_SideBarSide |
748 | updateMouseHover_ListWidget(d->list); | 803 | ? topRight_Rect(itemRect_ListWidget(d->list, itemIndex)) |
804 | : addX_I2(topLeft_Rect(itemRect_ListWidget(d->list, itemIndex)), | ||
805 | -width_Widget(d->menu))); | ||
749 | } | 806 | } |
750 | break; | 807 | break; |
751 | } | 808 | } |
@@ -848,6 +905,7 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c | |||
848 | isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit"))); | 905 | isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit"))); |
849 | postCommand_App("bookmarks.changed"); | 906 | postCommand_App("bookmarks.changed"); |
850 | } | 907 | } |
908 | setupSheetTransition_Mobile(editor, iFalse); | ||
851 | destroy_Widget(editor); | 909 | destroy_Widget(editor); |
852 | return iTrue; | 910 | return iTrue; |
853 | } | 911 | } |
@@ -878,7 +936,8 @@ static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char * | |||
878 | if (arg_Command(cmd) && isVisible_Widget(w)) { | 936 | if (arg_Command(cmd) && isVisible_Widget(w)) { |
879 | return iTrue; | 937 | return iTrue; |
880 | } | 938 | } |
881 | const iBool isAnimated = argLabel_Command(cmd, "noanim") == 0 && | 939 | const iBool isAnimated = prefs_App()->uiAnimations && |
940 | argLabel_Command(cmd, "noanim") == 0 && | ||
882 | (deviceType_App() != phone_AppDeviceType); | 941 | (deviceType_App() != phone_AppDeviceType); |
883 | int visX = 0; | 942 | int visX = 0; |
884 | if (isVisible_Widget(w)) { | 943 | if (isVisible_Widget(w)) { |
@@ -1008,7 +1067,8 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1008 | return iTrue; | 1067 | return iTrue; |
1009 | } | 1068 | } |
1010 | else if (isCommand_Widget(w, ev, "list.clicked")) { | 1069 | else if (isCommand_Widget(w, ev, "list.clicked")) { |
1011 | itemClicked_SidebarWidget_(d, pointerLabel_Command(cmd, "item")); | 1070 | itemClicked_SidebarWidget_( |
1071 | d, pointerLabel_Command(cmd, "item"), argU32Label_Command(cmd, "arg")); | ||
1012 | return iTrue; | 1072 | return iTrue; |
1013 | } | 1073 | } |
1014 | else if (isCommand_Widget(w, ev, "menu.closed")) { | 1074 | else if (isCommand_Widget(w, ev, "menu.closed")) { |
@@ -1190,23 +1250,17 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1190 | } | 1250 | } |
1191 | else if (arg_Command(cmd)) { | 1251 | else if (arg_Command(cmd)) { |
1192 | signIn_GmCerts(certs_App(), ident, tabUrl); | 1252 | signIn_GmCerts(certs_App(), ident, tabUrl); |
1253 | postCommand_App("navigate.reload"); | ||
1193 | } | 1254 | } |
1194 | else { | 1255 | else { |
1195 | signOut_GmCerts(certs_App(), tabUrl); | 1256 | signOut_GmCerts(certs_App(), tabUrl); |
1257 | postCommand_App("navigate.reload"); | ||
1196 | } | 1258 | } |
1197 | saveIdentities_GmCerts(certs_App()); | 1259 | saveIdentities_GmCerts(certs_App()); |
1198 | updateItems_SidebarWidget_(d); | 1260 | updateItems_SidebarWidget_(d); |
1199 | } | 1261 | } |
1200 | return iTrue; | 1262 | return iTrue; |
1201 | } | 1263 | } |
1202 | else if (isCommand_Widget(w, ev, "ident.showuse")) { | ||
1203 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
1204 | if (ident) { | ||
1205 | makeSimpleMessage_Widget(uiHeading_ColorEscape "${heading.ident.use}", | ||
1206 | cstrCollect_String(joinCStr_StringSet(ident->useUrls, "\n"))); | ||
1207 | } | ||
1208 | return iTrue; | ||
1209 | } | ||
1210 | else if (isCommand_Widget(w, ev, "ident.edit")) { | 1264 | else if (isCommand_Widget(w, ev, "ident.edit")) { |
1211 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | 1265 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); |
1212 | if (ident) { | 1266 | if (ident) { |
@@ -1228,6 +1282,20 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1228 | } | 1282 | } |
1229 | return iTrue; | 1283 | return iTrue; |
1230 | } | 1284 | } |
1285 | else if (isCommand_Widget(w, ev, "ident.export")) { | ||
1286 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
1287 | if (ident) { | ||
1288 | iString *pem = collect_String(pem_TlsCertificate(ident->cert)); | ||
1289 | append_String(pem, collect_String(privateKeyPem_TlsCertificate(ident->cert))); | ||
1290 | iDocumentWidget *expTab = newTab_App(NULL, iTrue); | ||
1291 | setUrlAndSource_DocumentWidget( | ||
1292 | expTab, | ||
1293 | collectNewFormat_String("file:%s.pem", cstr_String(name_GmIdentity(ident))), | ||
1294 | collectNewCStr_String("text/plain"), | ||
1295 | utf8_String(pem)); | ||
1296 | } | ||
1297 | return iTrue; | ||
1298 | } | ||
1231 | else if (isCommand_Widget(w, ev, "ident.setnotes")) { | 1299 | else if (isCommand_Widget(w, ev, "ident.setnotes")) { |
1232 | iGmIdentity *ident = pointerLabel_Command(cmd, "ident"); | 1300 | iGmIdentity *ident = pointerLabel_Command(cmd, "ident"); |
1233 | if (ident) { | 1301 | if (ident) { |
@@ -1336,20 +1404,21 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1336 | d->contextIndex = iInvalidPos; | 1404 | d->contextIndex = iInvalidPos; |
1337 | } | 1405 | } |
1338 | } | 1406 | } |
1339 | if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) { | 1407 | if ((d->menu || d->mode == identities_SidebarMode )&& ev->type == SDL_MOUSEBUTTONDOWN) { |
1340 | if (ev->button.button == SDL_BUTTON_RIGHT) { | 1408 | if (ev->button.button == SDL_BUTTON_RIGHT) { |
1341 | d->contextItem = NULL; | 1409 | d->contextItem = NULL; |
1342 | if (!isVisible_Widget(d->menu)) { | 1410 | if (!isVisible_Widget(d->menu)) { |
1343 | updateMouseHover_ListWidget(d->list); | 1411 | updateMouseHover_ListWidget(d->list); |
1344 | } | 1412 | } |
1345 | if (constHoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { | 1413 | if (constHoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { |
1346 | d->contextItem = hoverItem_ListWidget(d->list); | 1414 | d->contextItem = hoverItem_ListWidget(d->list); |
1347 | /* Context is drawn in hover state. */ | 1415 | /* Context is drawn in hover state. */ |
1348 | if (d->contextIndex != iInvalidPos) { | 1416 | if (d->contextIndex != iInvalidPos) { |
1349 | invalidateItem_ListWidget(d->list, d->contextIndex); | 1417 | invalidateItem_ListWidget(d->list, d->contextIndex); |
1350 | } | 1418 | } |
1351 | d->contextIndex = hoverItemIndex_ListWidget(d->list); | 1419 | d->contextIndex = hoverItemIndex_ListWidget(d->list); |
1352 | /* Update menu items. */ | 1420 | /* Update menu items. */ |
1421 | updateContextMenu_SidebarWidget_(d); | ||
1353 | /* TODO: Some callback-based mechanism would be nice for updating menus right | 1422 | /* TODO: Some callback-based mechanism would be nice for updating menus right |
1354 | before they open? */ | 1423 | before they open? */ |
1355 | if (d->mode == bookmarks_SidebarMode && d->contextItem) { | 1424 | if (d->mode == bookmarks_SidebarMode && d->contextItem) { |
@@ -1407,11 +1476,13 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1407 | (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) || | 1476 | (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) || |
1408 | (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl))); | 1477 | (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl))); |
1409 | } | 1478 | } |
1479 | /* | ||
1410 | else if (equal_Command(cmdItem, "ident.showuse")) { | 1480 | else if (equal_Command(cmdItem, "ident.showuse")) { |
1411 | setFlags_Widget(as_Widget(menuItem), | 1481 | setFlags_Widget(as_Widget(menuItem), |
1412 | disabled_WidgetFlag, | 1482 | disabled_WidgetFlag, |
1413 | !isUsed_GmIdentity(ident)); | 1483 | !isUsed_GmIdentity(ident)); |
1414 | } | 1484 | } |
1485 | */ | ||
1415 | } | 1486 | } |
1416 | } | 1487 | } |
1417 | } | 1488 | } |
@@ -1423,10 +1494,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1423 | const int kmods = keyMods_Sym(ev->key.keysym.mod); | 1494 | const int kmods = keyMods_Sym(ev->key.keysym.mod); |
1424 | /* Hide the sidebar when Escape is pressed. */ | 1495 | /* Hide the sidebar when Escape is pressed. */ |
1425 | if (kmods == 0 && key == SDLK_ESCAPE && isVisible_Widget(d)) { | 1496 | if (kmods == 0 && key == SDLK_ESCAPE && isVisible_Widget(d)) { |
1426 | setFlags_Widget(w, hidden_WidgetFlag, iTrue); | 1497 | postCommand_Widget(d, "%s.toggle", cstr_String(id_Widget(w))); |
1427 | arrange_Widget(w->parent); | ||
1428 | updateSize_DocumentWidget(document_App()); | ||
1429 | refresh_Widget(w->parent); | ||
1430 | return iTrue; | 1498 | return iTrue; |
1431 | } | 1499 | } |
1432 | } | 1500 | } |
@@ -1460,7 +1528,8 @@ static void draw_SidebarWidget_(const iSidebarWidget *d) { | |||
1460 | const iRect bounds = bounds_Widget(w); | 1528 | const iRect bounds = bounds_Widget(w); |
1461 | iPaint p; | 1529 | iPaint p; |
1462 | init_Paint(&p); | 1530 | init_Paint(&p); |
1463 | if (flags_Widget(w) & visualOffset_WidgetFlag && isVisible_Widget(w)) { | 1531 | if (flags_Widget(w) & visualOffset_WidgetFlag && |
1532 | flags_Widget(w) & horizontalOffset_WidgetFlag && isVisible_Widget(w)) { | ||
1464 | fillRect_Paint(&p, boundsWithoutVisualOffset_Widget(w), tmBackground_ColorId); | 1533 | fillRect_Paint(&p, boundsWithoutVisualOffset_Widget(w), tmBackground_ColorId); |
1465 | } | 1534 | } |
1466 | draw_Widget(w); | 1535 | draw_Widget(w); |
@@ -1493,6 +1562,7 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
1493 | const int itemHeight = height_Rect(itemRect); | 1562 | const int itemHeight = height_Rect(itemRect); |
1494 | const int iconColor = isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId) | 1563 | const int iconColor = isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId) |
1495 | : uiIcon_ColorId; | 1564 | : uiIcon_ColorId; |
1565 | const int altIconColor = isPressing ? uiTextPressed_ColorId : uiTextCaution_ColorId; | ||
1496 | const int font = sidebar->itemFonts[d->isBold ? 1 : 0]; | 1566 | const int font = sidebar->itemFonts[d->isBold ? 1 : 0]; |
1497 | int bg = uiBackgroundSidebar_ColorId; | 1567 | int bg = uiBackgroundSidebar_ColorId; |
1498 | if (isHover) { | 1568 | if (isHover) { |
@@ -1611,7 +1681,7 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
1611 | : uiText_ColorId; | 1681 | : uiText_ColorId; |
1612 | iString str; | 1682 | iString str; |
1613 | init_String(&str); | 1683 | init_String(&str); |
1614 | appendChar_String(&str, d->icon ? d->icon : 0x1f588); | 1684 | appendChar_String(&str, d->icon ? d->icon : 0x1f588); |
1615 | const iRect iconArea = { addX_I2(pos, gap_UI), | 1685 | const iRect iconArea = { addX_I2(pos, gap_UI), |
1616 | init_I2(1.75f * lineHeight_Text(font), itemHeight) }; | 1686 | init_I2(1.75f * lineHeight_Text(font), itemHeight) }; |
1617 | drawCentered_Text(font, | 1687 | drawCentered_Text(font, |
@@ -1625,9 +1695,13 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
1625 | deinit_String(&str); | 1695 | deinit_String(&str); |
1626 | const iInt2 textPos = addY_I2(topRight_Rect(iconArea), (itemHeight - lineHeight_Text(font)) / 2); | 1696 | const iInt2 textPos = addY_I2(topRight_Rect(iconArea), (itemHeight - lineHeight_Text(font)) / 2); |
1627 | drawRange_Text(font, textPos, fg, range_String(&d->label)); | 1697 | drawRange_Text(font, textPos, fg, range_String(&d->label)); |
1698 | const int metaFont = default_FontId; | ||
1699 | const int metaIconWidth = 4.5f * gap_UI; | ||
1628 | const iInt2 metaPos = | 1700 | const iInt2 metaPos = |
1629 | init_I2(right_Rect(itemRect) - advanceRange_Text(font, range_String(&d->meta)).x - | 1701 | init_I2(right_Rect(itemRect) - |
1630 | 2 * gap_UI - (scrollBarWidth ? scrollBarWidth - gap_UI : 0), | 1702 | length_String(&d->meta) * |
1703 | metaIconWidth | ||
1704 | - 2 * gap_UI - (blankWidth ? blankWidth - 1.5f * gap_UI : (gap_UI / 2)), | ||
1631 | textPos.y); | 1705 | textPos.y); |
1632 | fillRect_Paint(p, | 1706 | fillRect_Paint(p, |
1633 | init_Rect(metaPos.x, | 1707 | init_Rect(metaPos.x, |
@@ -1635,10 +1709,22 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
1635 | right_Rect(itemRect) - metaPos.x, | 1709 | right_Rect(itemRect) - metaPos.x, |
1636 | height_Rect(itemRect)), | 1710 | height_Rect(itemRect)), |
1637 | bg); | 1711 | bg); |
1638 | drawRange_Text(font, | 1712 | iInt2 mpos = metaPos; |
1639 | metaPos, | 1713 | iStringConstIterator iter; |
1640 | isHover && isPressing ? fg : uiTextCaution_ColorId, | 1714 | init_StringConstIterator(&iter, &d->meta); |
1641 | range_String(&d->meta)); | 1715 | iRangecc range = { cstr_String(&d->meta), iter.pos }; |
1716 | while (iter.value) { | ||
1717 | next_StringConstIterator(&iter); | ||
1718 | range.end = iter.pos; | ||
1719 | iRect iconArea = { mpos, init_I2(metaIconWidth, lineHeight_Text(metaFont)) }; | ||
1720 | iRect visBounds = visualBounds_Text(metaFont, range); | ||
1721 | drawRange_Text(metaFont, | ||
1722 | sub_I2(mid_Rect(iconArea), mid_Rect(visBounds)), | ||
1723 | isHover && isPressing ? fg : uiTextCaution_ColorId, | ||
1724 | range); | ||
1725 | mpos.x += metaIconWidth; | ||
1726 | range.start = range.end; | ||
1727 | } | ||
1642 | } | 1728 | } |
1643 | else if (sidebar->mode == history_SidebarMode) { | 1729 | else if (sidebar->mode == history_SidebarMode) { |
1644 | iBeginCollect(); | 1730 | iBeginCollect(); |
@@ -1683,6 +1769,7 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
1683 | else if (sidebar->mode == identities_SidebarMode) { | 1769 | else if (sidebar->mode == identities_SidebarMode) { |
1684 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) | 1770 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) |
1685 | : uiTextStrong_ColorId; | 1771 | : uiTextStrong_ColorId; |
1772 | const iBool isUsedOnDomain = (d->indent != 0); | ||
1686 | iString icon; | 1773 | iString icon; |
1687 | initUnicodeN_String(&icon, &d->icon, 1); | 1774 | initUnicodeN_String(&icon, &d->icon, 1); |
1688 | iInt2 cPos = topLeft_Rect(itemRect); | 1775 | iInt2 cPos = topLeft_Rect(itemRect); |
@@ -1694,8 +1781,21 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
1694 | const int metaFg = isHover ? permanent_ColorId | (isPressing ? uiTextPressed_ColorId | 1781 | const int metaFg = isHover ? permanent_ColorId | (isPressing ? uiTextPressed_ColorId |
1695 | : uiTextFramelessHover_ColorId) | 1782 | : uiTextFramelessHover_ColorId) |
1696 | : uiTextDim_ColorId; | 1783 | : uiTextDim_ColorId; |
1697 | drawRange_Text( | 1784 | if (!d->listItem.isSelected && !isUsedOnDomain) { |
1698 | font, cPos, d->listItem.isSelected ? iconColor : metaFg, range_String(&icon)); | 1785 | /* Draw an outline of the icon. */ |
1786 | for (int off = 0; off < 4; ++off) { | ||
1787 | drawRange_Text(font, | ||
1788 | add_I2(cPos, init_I2(off % 2 == 0 ? -1 : 1, off / 2 == 0 ? -1 : 1)), | ||
1789 | metaFg, | ||
1790 | range_String(&icon)); | ||
1791 | } | ||
1792 | } | ||
1793 | drawRange_Text(font, | ||
1794 | cPos, | ||
1795 | d->listItem.isSelected ? iconColor | ||
1796 | : isUsedOnDomain ? altIconColor | ||
1797 | : uiBackgroundSidebar_ColorId, | ||
1798 | range_String(&icon)); | ||
1699 | deinit_String(&icon); | 1799 | deinit_String(&icon); |
1700 | drawRange_Text(d->listItem.isSelected ? sidebar->itemFonts[1] : font, | 1800 | drawRange_Text(d->listItem.isSelected ? sidebar->itemFonts[1] : font, |
1701 | add_I2(cPos, init_I2(indent, 0)), | 1801 | add_I2(cPos, init_I2(indent, 0)), |