summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-11-25 21:30:49 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-11-25 21:30:49 +0200
commitc19be4f64f2f38f692b9987a7b5268bdb87fa8be (patch)
treee3070566cd7f6cecec41f960e4fa47fa03d938ff /src/ui
parent9c1fac30f92eadc292ca0b4326b93d4cf9b4008c (diff)
SidebarWidget: Bookmark tag icons; Feeds presentation
Special tags of bookmarks are now visualized with icons. Feed items show an indicator if the currently open document matches the entry URL.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/listwidget.c11
-rw-r--r--src/ui/listwidget.h1
-rw-r--r--src/ui/sidebarwidget.c81
3 files changed, 72 insertions, 21 deletions
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c
index 39b9bfe5..b27107df 100644
--- a/src/ui/listwidget.c
+++ b/src/ui/listwidget.c
@@ -139,6 +139,10 @@ void setItemHeight_ListWidget(iListWidget *d, int itemHeight) {
139 invalidate_ListWidget(d); 139 invalidate_ListWidget(d);
140} 140}
141 141
142int scrollBarWidth_ListWidget(const iListWidget *d) {
143 return isVisible_Widget(d->scroll) ? width_Widget(d->scroll) : 0;
144}
145
142int itemHeight_ListWidget(const iListWidget *d) { 146int itemHeight_ListWidget(const iListWidget *d) {
143 return d->itemHeight; 147 return d->itemHeight;
144} 148}
@@ -318,6 +322,7 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) {
318 return processEvent_Widget(w, ev); 322 return processEvent_Widget(w, ev);
319} 323}
320 324
325#if 0
321static void drawItem_ListWidget_(const iListWidget *d, iPaint *p, size_t index, iInt2 pos) { 326static void drawItem_ListWidget_(const iListWidget *d, iPaint *p, size_t index, iInt2 pos) {
322 const iWidget * w = constAs_Widget(d); 327 const iWidget * w = constAs_Widget(d);
323 const iRect bounds = innerBounds_Widget(w); 328 const iRect bounds = innerBounds_Widget(w);
@@ -325,6 +330,7 @@ static void drawItem_ListWidget_(const iListWidget *d, iPaint *p, size_t index,
325 const iRect itemRect = { pos, init_I2(width_Rect(bounds), d->itemHeight) }; 330 const iRect itemRect = { pos, init_I2(width_Rect(bounds), d->itemHeight) };
326 class_ListItem(item)->draw(item, p, itemRect, d); 331 class_ListItem(item)->draw(item, p, itemRect, d);
327} 332}
333#endif
328 334
329static const iListItem *item_ListWidget_(const iListWidget *d, size_t pos) { 335static const iListItem *item_ListWidget_(const iListWidget *d, size_t pos) {
330 return constAt_PtrArray(&d->items, pos); 336 return constAt_PtrArray(&d->items, pos);
@@ -364,6 +370,9 @@ static void draw_ListWidget_(const iListWidget *d) {
364 beginTarget_Paint(&p, buf->texture); 370 beginTarget_Paint(&p, buf->texture);
365 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBuf->texSize }, bg[i]); 371 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBuf->texSize }, bg[i]);
366 } 372 }
373 const iRect sbBlankRect =
374 { init_I2(d->visBuf->texSize.x - scrollBarWidth_ListWidget(d), 0),
375 init_I2(scrollBarWidth_ListWidget(d), d->itemHeight) };
367 iConstForEach(IntSet, v, &d->invalidItems) { 376 iConstForEach(IntSet, v, &d->invalidItems) {
368 const size_t index = *v.value; 377 const size_t index = *v.value;
369 if (contains_Range(&drawItems, index)) { 378 if (contains_Range(&drawItems, index)) {
@@ -373,6 +382,7 @@ static void draw_ListWidget_(const iListWidget *d) {
373 beginTarget_Paint(&p, buf->texture); 382 beginTarget_Paint(&p, buf->texture);
374 fillRect_Paint(&p, itemRect, bg[i]); 383 fillRect_Paint(&p, itemRect, bg[i]);
375 class_ListItem(item)->draw(item, &p, itemRect, d); 384 class_ListItem(item)->draw(item, &p, itemRect, d);
385 fillRect_Paint(&p, moved_Rect(sbBlankRect, init_I2(0, top_Rect(itemRect))), bg[i]);
376 } 386 }
377 } 387 }
378 /* Visible range is not fully covered. Fill in the new items. */ 388 /* Visible range is not fully covered. Fill in the new items. */
@@ -386,6 +396,7 @@ static void draw_ListWidget_(const iListWidget *d) {
386 init_I2(d->visBuf->texSize.x, d->itemHeight) }; 396 init_I2(d->visBuf->texSize.x, d->itemHeight) };
387 fillRect_Paint(&p, itemRect, bg[i]); 397 fillRect_Paint(&p, itemRect, bg[i]);
388 class_ListItem(item)->draw(item, &p, itemRect, d); 398 class_ListItem(item)->draw(item, &p, itemRect, d);
399 fillRect_Paint(&p, moved_Rect(sbBlankRect, init_I2(0, top_Rect(itemRect))), bg[i]);
389 } 400 }
390 } 401 }
391 endTarget_Paint(&p); 402 endTarget_Paint(&p);
diff --git a/src/ui/listwidget.h b/src/ui/listwidget.h
index 26c1ac9e..16adf664 100644
--- a/src/ui/listwidget.h
+++ b/src/ui/listwidget.h
@@ -55,6 +55,7 @@ void addItem_ListWidget (iListWidget *, iAnyObject *item);
55 55
56iScrollWidget * scroll_ListWidget (iListWidget *); 56iScrollWidget * scroll_ListWidget (iListWidget *);
57 57
58int scrollBarWidth_ListWidget (const iListWidget *); /* returns zero if hidden */
58int itemHeight_ListWidget (const iListWidget *); 59int itemHeight_ListWidget (const iListWidget *);
59int scrollPos_ListWidget (const iListWidget *); 60int scrollPos_ListWidget (const iListWidget *);
60 61
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 12c5e847..7cde5d7b 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
38#include "visited.h" 38#include "visited.h"
39 39
40#include <the_Foundation/intset.h> 40#include <the_Foundation/intset.h>
41#include <the_Foundation/regexp.h>
41#include <the_Foundation/stringarray.h> 42#include <the_Foundation/stringarray.h>
42#include <SDL_clipboard.h> 43#include <SDL_clipboard.h>
43#include <SDL_mouse.h> 44#include <SDL_mouse.h>
@@ -113,6 +114,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
113 d->menu = NULL; 114 d->menu = NULL;
114 switch (d->mode) { 115 switch (d->mode) {
115 case feeds_SidebarMode: { 116 case feeds_SidebarMode: {
117 const iString *docUrl = url_DocumentWidget(document_App());
116 iDate on; 118 iDate on;
117 initCurrent_Date(&on); 119 initCurrent_Date(&on);
118 const int thisYear = on.year; 120 const int thisYear = on.year;
@@ -135,6 +137,9 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
135 } 137 }
136 } 138 }
137 iSidebarItem *item = new_SidebarItem(); 139 iSidebarItem *item = new_SidebarItem();
140 if (equal_String(docUrl, &entry->url)) {
141 item->listItem.isSelected = iTrue; /* currently being viewed */
142 }
138 item->icon = 0; 143 item->icon = 0;
139 const iTime visitTime = urlVisitTime_Visited(visited_App(), &entry->url); 144 const iTime visitTime = urlVisitTime_Visited(visited_App(), &entry->url);
140 if (!isValid_Time(&visitTime)) { 145 if (!isValid_Time(&visitTime)) {
@@ -169,6 +174,8 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
169 break; 174 break;
170 } 175 }
171 case bookmarks_SidebarMode: { 176 case bookmarks_SidebarMode: {
177 iRegExp *homeTag = iClob(new_RegExp("\\bhomepage\\b", caseSensitive_RegExpOption));
178 iRegExp *subTag = iClob(new_RegExp("\\bsubscribed\\b", caseSensitive_RegExpOption));
172 iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTitle_Bookmark_, NULL, NULL)) { 179 iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTitle_Bookmark_, NULL, NULL)) {
173 const iBookmark *bm = i.ptr; 180 const iBookmark *bm = i.ptr;
174 iSidebarItem *item = new_SidebarItem(); 181 iSidebarItem *item = new_SidebarItem();
@@ -176,7 +183,17 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
176 item->icon = bm->icon; 183 item->icon = bm->icon;
177 set_String(&item->url, &bm->url); 184 set_String(&item->url, &bm->url);
178 set_String(&item->label, &bm->title); 185 set_String(&item->label, &bm->title);
179 set_String(&item->meta, &bm->tags); 186 /* Icons for special tags. */ {
187 iRegExpMatch m;
188 init_RegExpMatch(&m);
189 if (matchString_RegExp(subTag, &bm->tags, &m)) {
190 appendChar_String(&item->meta, 0x2605);
191 }
192 init_RegExpMatch(&m);
193 if (matchString_RegExp(homeTag, &bm->tags, &m)) {
194 appendChar_String(&item->meta, 0x1f3e0);
195 }
196 }
180 addItem_ListWidget(d->list, item); 197 addItem_ListWidget(d->list, item);
181 iRelease(item); 198 iRelease(item);
182 } 199 }
@@ -185,8 +202,9 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
185 (iMenuItem[]){ { "Edit Bookmark...", 0, 0, "bookmark.edit" }, 202 (iMenuItem[]){ { "Edit Bookmark...", 0, 0, "bookmark.edit" },
186 { "Copy URL", 0, 0, "bookmark.copy" }, 203 { "Copy URL", 0, 0, "bookmark.copy" },
187 { "---", 0, 0, NULL }, 204 { "---", 0, 0, NULL },
205 { "---", 0, 0, NULL },
188 { uiTextCaution_ColorEscape "Delete Bookmark", 0, 0, "bookmark.delete" } }, 206 { uiTextCaution_ColorEscape "Delete Bookmark", 0, 0, "bookmark.delete" } },
189 4); 207 5);
190 break; 208 break;
191 } 209 }
192 case history_SidebarMode: { 210 case history_SidebarMode: {
@@ -639,7 +657,8 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
639 } 657 }
640 return iTrue; 658 return iTrue;
641 } 659 }
642 else if (equal_Command(cmd, "visited.changed") && d->mode == history_SidebarMode) { 660 else if (equal_Command(cmd, "visited.changed") &&
661 (d->mode == history_SidebarMode || d->mode == feeds_SidebarMode)) {
643 updateItems_SidebarWidget_(d); 662 updateItems_SidebarWidget_(d);
644 } 663 }
645 else if (equal_Command(cmd, "bookmarks.changed") && d->mode == bookmarks_SidebarMode) { 664 else if (equal_Command(cmd, "bookmarks.changed") && d->mode == bookmarks_SidebarMode) {
@@ -852,22 +871,31 @@ static void draw_SidebarWidget_(const iSidebarWidget *d) {
852 871
853static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, 872static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
854 const iListWidget *list) { 873 const iListWidget *list) {
855 const int font = uiContent_FontId; 874 const iSidebarWidget *sidebar =
856 const iSidebarWidget *sidebar = findParentClass_Widget(constAs_Widget(list), 875 findParentClass_Widget(constAs_Widget(list), &Class_SidebarWidget);
857 &Class_SidebarWidget); 876 const iBool isPressing = isMouseDown_ListWidget(list);
858 const iBool isPressing = isMouseDown_ListWidget(list); 877 const iBool isHover =
859 const iBool isHover =
860 isHover_Widget(constAs_Widget(list)) && constHoverItem_ListWidget(list) == d; 878 isHover_Widget(constAs_Widget(list)) && constHoverItem_ListWidget(list) == d;
861 const int itemHeight = height_Rect(itemRect); 879 const int scrollBarWidth = scrollBarWidth_ListWidget(list);
880 const int itemHeight = height_Rect(itemRect);
862 const int iconColor = 881 const int iconColor =
863 isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId) : uiIcon_ColorId; 882 isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId) : uiIcon_ColorId;
883 const int font = uiContent_FontId;
884 int bg = uiBackground_ColorId;
864 if (isHover) { 885 if (isHover) {
865 fillRect_Paint(p, 886 bg = isPressing ? uiBackgroundPressed_ColorId
866 itemRect, 887 : uiBackgroundFramelessHover_ColorId;
867 isPressing ? uiBackgroundPressed_ColorId 888 fillRect_Paint(p, itemRect, bg);
868 : uiBackgroundFramelessHover_ColorId);
869 } 889 }
870 iInt2 pos = itemRect.pos; 890 iInt2 pos = itemRect.pos;
891 /* Selection indicator. */
892 if (d->listItem.isSelected && (sidebar->mode == feeds_SidebarMode ||
893 sidebar->mode == identities_SidebarMode)) {
894 drawRectThickness_Paint(p,
895 adjusted_Rect(itemRect, zero_I2(), init_I2(-2 - scrollBarWidth, -1)),
896 gap_UI / 4,
897 isHover && isPressing ? uiTextPressed_ColorId : uiIcon_ColorId);
898 }
871 if (sidebar->mode == documentOutline_SidebarMode) { 899 if (sidebar->mode == documentOutline_SidebarMode) {
872 const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) 900 const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId)
873 : (tmHeading1_ColorId + d->indent / (4 * gap_UI)); 901 : (tmHeading1_ColorId + d->indent / (4 * gap_UI));
@@ -949,8 +977,22 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
949 const iRect iconArea = { addX_I2(pos, gap_UI), init_I2(7 * gap_UI, itemHeight) }; 977 const iRect iconArea = { addX_I2(pos, gap_UI), init_I2(7 * gap_UI, itemHeight) };
950 drawCentered_Text(font, iconArea, iTrue, iconColor, "%s", cstr_String(&str)); 978 drawCentered_Text(font, iconArea, iTrue, iconColor, "%s", cstr_String(&str));
951 deinit_String(&str); 979 deinit_String(&str);
952 iInt2 textPos = addY_I2(topRight_Rect(iconArea), (itemHeight - lineHeight_Text(font)) / 2); 980 const iInt2 textPos = addY_I2(topRight_Rect(iconArea), (itemHeight - lineHeight_Text(font)) / 2);
953 drawRange_Text(font, textPos, fg, range_String(&d->label)); 981 drawRange_Text(font, textPos, fg, range_String(&d->label));
982 const iInt2 metaPos =
983 init_I2(right_Rect(itemRect) - advanceRange_Text(font, range_String(&d->meta)).x -
984 2 * gap_UI - (scrollBarWidth ? scrollBarWidth - gap_UI : 0),
985 textPos.y);
986 fillRect_Paint(p,
987 init_Rect(metaPos.x,
988 top_Rect(itemRect),
989 right_Rect(itemRect) - metaPos.x,
990 height_Rect(itemRect)),
991 bg);
992 drawRange_Text(font,
993 metaPos,
994 isHover && isPressing ? fg : uiTextCaution_ColorId,
995 range_String(&d->meta));
954 } 996 }
955 else if (sidebar->mode == history_SidebarMode) { 997 else if (sidebar->mode == history_SidebarMode) {
956 iBeginCollect(); 998 iBeginCollect();
@@ -959,7 +1001,10 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
959 if (d->listItem.isSeparator) { 1001 if (d->listItem.isSeparator) {
960 if (!isEmpty_String(&d->meta)) { 1002 if (!isEmpty_String(&d->meta)) {
961 iInt2 drawPos = addY_I2(topLeft_Rect(itemRect), d->id); 1003 iInt2 drawPos = addY_I2(topLeft_Rect(itemRect), d->id);
962 drawHLine_Paint(p, addY_I2(drawPos, -gap_UI), width_Rect(itemRect), uiIcon_ColorId); 1004 drawHLine_Paint(p,
1005 addY_I2(drawPos, -gap_UI),
1006 width_Rect(itemRect) - scrollBarWidth,
1007 uiIcon_ColorId);
963 drawRange_Text( 1008 drawRange_Text(
964 uiLabelLarge_FontId, 1009 uiLabelLarge_FontId,
965 add_I2(drawPos, 1010 add_I2(drawPos,
@@ -991,12 +1036,6 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
991 else if (sidebar->mode == identities_SidebarMode) { 1036 else if (sidebar->mode == identities_SidebarMode) {
992 const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) 1037 const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId)
993 : uiTextStrong_ColorId; 1038 : uiTextStrong_ColorId;
994 if (d->listItem.isSelected) {
995 drawRectThickness_Paint(p,
996 adjusted_Rect(itemRect, zero_I2(), init_I2(-2, -1)),
997 gap_UI / 4,
998 isHover && isPressing ? uiTextPressed_ColorId : uiIcon_ColorId);
999 }
1000 iString icon; 1039 iString icon;
1001 initUnicodeN_String(&icon, &d->icon, 1); 1040 initUnicodeN_String(&icon, &d->icon, 1);
1002 iInt2 cPos = topLeft_Rect(itemRect); 1041 iInt2 cPos = topLeft_Rect(itemRect);