diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/sidebarwidget.c | 330 |
1 files changed, 1 insertions, 329 deletions
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 1d53202b..8d7b47b7 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -84,73 +84,22 @@ struct Impl_SidebarWidget { | |||
84 | iWidget widget; | 84 | iWidget widget; |
85 | enum iSidebarMode mode; | 85 | enum iSidebarMode mode; |
86 | iListWidget *list; | 86 | iListWidget *list; |
87 | // iScrollWidget *scroll; | ||
88 | // int scrollY; | ||
89 | int modeScroll[max_SidebarMode]; | 87 | int modeScroll[max_SidebarMode]; |
90 | int width; | 88 | int width; |
91 | iLabelWidget *modeButtons[max_SidebarMode]; | 89 | iLabelWidget *modeButtons[max_SidebarMode]; |
92 | int itemHeight; | 90 | int itemHeight; |
93 | int maxButtonLabelWidth; | 91 | int maxButtonLabelWidth; |
94 | // iArray items; | ||
95 | // size_t hoverItem; | ||
96 | // iClick click; | ||
97 | iWidget *resizer; | 92 | iWidget *resizer; |
98 | SDL_Cursor *resizeCursor; | 93 | SDL_Cursor *resizeCursor; |
99 | iWidget *menu; | 94 | iWidget *menu; |
100 | // iIntSet invalidItems; | ||
101 | // SDL_Texture *visBuffer; | ||
102 | // iBool visBufferValid; | ||
103 | }; | 95 | }; |
104 | 96 | ||
105 | iDefineObjectConstruction(SidebarWidget) | 97 | iDefineObjectConstruction(SidebarWidget) |
106 | 98 | ||
107 | //static void invalidate_SidebarWidget_(iSidebarWidget *d) { | ||
108 | // d->visBufferValid = iFalse; | ||
109 | // refresh_Widget(as_Widget(d)); | ||
110 | // clear_IntSet(&d->invalidItems); /* all will be drawn */ | ||
111 | //} | ||
112 | |||
113 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { | 99 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { |
114 | return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0; | 100 | return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0; |
115 | } | 101 | } |
116 | 102 | ||
117 | //static void clearItems_SidebarWidget_(iSidebarWidget *d) { | ||
118 | // iForEach(Array, i, &d->items) { | ||
119 | // deinit_SidebarItem(i.value); | ||
120 | // } | ||
121 | // clear_Array(&d->items); | ||
122 | //} | ||
123 | |||
124 | #if 0 | ||
125 | static iRect contentBounds_SidebarWidget_(const iSidebarWidget *d) { | ||
126 | iRect bounds = bounds_Widget(constAs_Widget(d)); | ||
127 | const iWidget *scroll = constAs_Widget(scroll_ListWidget(d->list)); | ||
128 | adjustEdges_Rect(&bounds, | ||
129 | as_Widget(d->modeButtons[0])->rect.size.y + gap_UI, | ||
130 | isVisible_Widget(scroll) ? -scroll->rect.size.x : 0, | ||
131 | -gap_UI, | ||
132 | 0); | ||
133 | return bounds; | ||
134 | } | ||
135 | #endif | ||
136 | |||
137 | //static int scrollMax_SidebarWidget_(const iSidebarWidget *d) { | ||
138 | // return iMax(0, | ||
139 | // (int) numItems_ListWidget(d->list) * d->itemHeight - | ||
140 | // height_Rect(contentBounds_SidebarWidget_(d))); | ||
141 | //} | ||
142 | |||
143 | //static void updateVisible_SidebarWidget_(iSidebarWidget *d) { | ||
144 | // const int contentSize = size_Array(&d->items) * d->itemHeight; | ||
145 | // const iRect bounds = contentBounds_SidebarWidget_(d); | ||
146 | // setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_SidebarWidget_(d) }); | ||
147 | // setThumb_ScrollWidget(d->scroll, | ||
148 | // d->scrollY, | ||
149 | // contentSize > 0 ? height_Rect(bounds_Widget(as_Widget(d->scroll))) * | ||
150 | // height_Rect(bounds) / contentSize | ||
151 | // : 0); | ||
152 | //} | ||
153 | |||
154 | static int cmpTitle_Bookmark_(const iBookmark **a, const iBookmark **b) { | 103 | static int cmpTitle_Bookmark_(const iBookmark **a, const iBookmark **b) { |
155 | return cmpStringCase_String(&(*a)->title, &(*b)->title); | 104 | return cmpStringCase_String(&(*a)->title, &(*b)->title); |
156 | } | 105 | } |
@@ -160,18 +109,15 @@ static void updateVisible_SidebarWidget_(iSidebarWidget *d) { | |||
160 | } | 109 | } |
161 | 110 | ||
162 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { | 111 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { |
163 | // clearItems_SidebarWidget_(d); | ||
164 | clear_ListWidget(d->list); | 112 | clear_ListWidget(d->list); |
165 | destroy_Widget(d->menu); | 113 | destroy_Widget(d->menu); |
166 | d->menu = NULL; | 114 | d->menu = NULL; |
167 | // d->hoverItem = iInvalidPos; | ||
168 | switch (d->mode) { | 115 | switch (d->mode) { |
169 | case documentOutline_SidebarMode: { | 116 | case documentOutline_SidebarMode: { |
170 | const iGmDocument *doc = document_DocumentWidget(document_App()); | 117 | const iGmDocument *doc = document_DocumentWidget(document_App()); |
171 | iConstForEach(Array, i, headings_GmDocument(doc)) { | 118 | iConstForEach(Array, i, headings_GmDocument(doc)) { |
172 | const iGmHeading *head = i.value; | 119 | const iGmHeading *head = i.value; |
173 | iSidebarItem *item = new_SidebarItem(); | 120 | iSidebarItem *item = new_SidebarItem(); |
174 | // init_SidebarItem(&item); | ||
175 | item->id = index_ArrayConstIterator(&i); | 121 | item->id = index_ArrayConstIterator(&i); |
176 | setRange_String(&item->label, head->text); | 122 | setRange_String(&item->label, head->text); |
177 | item->indent = head->level * 4 * gap_UI; | 123 | item->indent = head->level * 4 * gap_UI; |
@@ -184,7 +130,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
184 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), NULL, cmpTitle_Bookmark_)) { | 130 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), NULL, cmpTitle_Bookmark_)) { |
185 | const iBookmark *bm = i.ptr; | 131 | const iBookmark *bm = i.ptr; |
186 | iSidebarItem *item = new_SidebarItem(); | 132 | iSidebarItem *item = new_SidebarItem(); |
187 | // init_SidebarItem(&item); | ||
188 | item->id = id_Bookmark(bm); | 133 | item->id = id_Bookmark(bm); |
189 | item->icon = bm->icon; | 134 | item->icon = bm->icon; |
190 | set_String(&item->url, &bm->url); | 135 | set_String(&item->url, &bm->url); |
@@ -209,7 +154,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
209 | iConstForEach(PtrArray, i, list_Visited(visited_App(), 200)) { | 154 | iConstForEach(PtrArray, i, list_Visited(visited_App(), 200)) { |
210 | const iVisitedUrl *visit = i.ptr; | 155 | const iVisitedUrl *visit = i.ptr; |
211 | iSidebarItem *item = new_SidebarItem(); | 156 | iSidebarItem *item = new_SidebarItem(); |
212 | // init_SidebarItem(&item); | ||
213 | set_String(&item->url, &visit->url); | 157 | set_String(&item->url, &visit->url); |
214 | iDate date; | 158 | iDate date; |
215 | init_Date(&date, &visit->when); | 159 | init_Date(&date, &visit->when); |
@@ -217,12 +161,10 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
217 | on = date; | 161 | on = date; |
218 | /* Date separator. */ | 162 | /* Date separator. */ |
219 | iSidebarItem *sep = new_SidebarItem(); | 163 | iSidebarItem *sep = new_SidebarItem(); |
220 | // init_SidebarItem(&sep); | ||
221 | sep->listItem.isSeparator = iTrue; | 164 | sep->listItem.isSeparator = iTrue; |
222 | set_String(&sep->meta, | 165 | set_String(&sep->meta, |
223 | collect_String(format_Date( | 166 | collect_String(format_Date( |
224 | &date, date.year != thisYear ? "%b %d %Y" : "%b %d"))); | 167 | &date, date.year != thisYear ? "%b %d %Y" : "%b %d"))); |
225 | // pushBack_Array(&d->items, &sep); | ||
226 | addItem_ListWidget(d->list, sep); | 168 | addItem_ListWidget(d->list, sep); |
227 | iRelease(sep); | 169 | iRelease(sep); |
228 | /* Date separators are two items tall. */ | 170 | /* Date separators are two items tall. */ |
@@ -231,7 +173,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
231 | addItem_ListWidget(d->list, sep); | 173 | addItem_ListWidget(d->list, sep); |
232 | iRelease(sep); | 174 | iRelease(sep); |
233 | } | 175 | } |
234 | // pushBack_Array(&d->items, &item); | ||
235 | addItem_ListWidget(d->list, item); | 176 | addItem_ListWidget(d->list, item); |
236 | iRelease(item); | 177 | iRelease(item); |
237 | } | 178 | } |
@@ -252,7 +193,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
252 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { | 193 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { |
253 | const iGmIdentity *ident = i.ptr; | 194 | const iGmIdentity *ident = i.ptr; |
254 | iSidebarItem *item = new_SidebarItem(); | 195 | iSidebarItem *item = new_SidebarItem(); |
255 | // init_SidebarItem(&item); | ||
256 | item->id = index_PtrArrayConstIterator(&i); | 196 | item->id = index_PtrArrayConstIterator(&i); |
257 | item->icon = ident->icon; | 197 | item->icon = ident->icon; |
258 | set_String(&item->label, collect_String(subject_TlsCertificate(ident->cert))); | 198 | set_String(&item->label, collect_String(subject_TlsCertificate(ident->cert))); |
@@ -281,7 +221,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
281 | cstr_String(&ident->notes)); | 221 | cstr_String(&ident->notes)); |
282 | } | 222 | } |
283 | item->listItem.isSelected = isActive; | 223 | item->listItem.isSelected = isActive; |
284 | //pushBack_Array(&d->items, &item); | ||
285 | addItem_ListWidget(d->list, item); | 224 | addItem_ListWidget(d->list, item); |
286 | iRelease(item); | 225 | iRelease(item); |
287 | } | 226 | } |
@@ -307,21 +246,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
307 | invalidate_ListWidget(d->list); | 246 | invalidate_ListWidget(d->list); |
308 | } | 247 | } |
309 | 248 | ||
310 | //static void scroll_SidebarWidget_(iSidebarWidget *d, int offset) { | ||
311 | // const int oldScroll = d->scrollY; | ||
312 | // d->scrollY += offset; | ||
313 | // if (d->scrollY < 0) { | ||
314 | // d->scrollY = 0; | ||
315 | // } | ||
316 | // const int scrollMax = scrollMax_SidebarWidget_(d); | ||
317 | // d->scrollY = iMin(d->scrollY, scrollMax); | ||
318 | // if (oldScroll != d->scrollY) { | ||
319 | // d->hoverItem = iInvalidPos; | ||
320 | // updateVisible_SidebarWidget_(d); | ||
321 | // invalidate_SidebarWidget_(d); | ||
322 | // } | ||
323 | //} | ||
324 | |||
325 | void setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { | 249 | void setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { |
326 | if (d->mode == mode) return; | 250 | if (d->mode == mode) return; |
327 | if (d->mode >= 0 && d->mode < max_SidebarMode) { | 251 | if (d->mode >= 0 && d->mode < max_SidebarMode) { |
@@ -411,44 +335,8 @@ void init_SidebarWidget(iSidebarWidget *d) { | |||
411 | 335 | ||
412 | void deinit_SidebarWidget(iSidebarWidget *d) { | 336 | void deinit_SidebarWidget(iSidebarWidget *d) { |
413 | SDL_FreeCursor(d->resizeCursor); | 337 | SDL_FreeCursor(d->resizeCursor); |
414 | //clearItems_SidebarWidget_(d); | ||
415 | // deinit_Array(&d->items); | ||
416 | } | 338 | } |
417 | 339 | ||
418 | //static int visCount_SidebarWidget_(const iSidebarWidget *d) { | ||
419 | // return iMin(height_Rect(bounds_Widget(constAs_Widget(d))) / d->itemHeight, | ||
420 | // (int) size_Array(&d->items)); | ||
421 | //} | ||
422 | |||
423 | //static iRanges visRange_SidebarWidget_(const iSidebarWidget *d) { | ||
424 | // iRanges vis = { d->scrollY / d->itemHeight, 0 }; | ||
425 | // vis.end = iMin(size_Array(&d->items), vis.start + visCount_SidebarWidget_(d)); | ||
426 | // return vis; | ||
427 | //} | ||
428 | |||
429 | //static size_t itemIndex_SidebarWidget_(const iSidebarWidget *d, iInt2 pos) { | ||
430 | // const iRect bounds = contentBounds_SidebarWidget_(d); | ||
431 | // pos.y -= top_Rect(bounds) - d->scrollY; | ||
432 | // if (pos.y < 0) return iInvalidPos; | ||
433 | // size_t index = pos.y / d->itemHeight; | ||
434 | // if (index >= size_Array(&d->items)) return iInvalidPos; | ||
435 | // return index; | ||
436 | //} | ||
437 | |||
438 | //static const iSidebarItem *constHoverItem_SidebarWidget_(const iSidebarWidget *d) { | ||
439 | // if (d->hoverItem < size_Array(&d->items)) { | ||
440 | // return constAt_Array(&d->items, d->hoverItem); | ||
441 | // } | ||
442 | // return NULL; | ||
443 | //} | ||
444 | |||
445 | //static iSidebarItem *hoverItem_SidebarWidget_(iSidebarWidget *d) { | ||
446 | // if (d->hoverItem < size_Array(&d->items)) { | ||
447 | // return at_Array(&d->items, d->hoverItem); | ||
448 | // } | ||
449 | // return NULL; | ||
450 | //} | ||
451 | |||
452 | static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) { | 340 | static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) { |
453 | if (d->mode == identities_SidebarMode) { | 341 | if (d->mode == identities_SidebarMode) { |
454 | const iSidebarItem *hoverItem = constHoverItem_ListWidget(d->list); | 342 | const iSidebarItem *hoverItem = constHoverItem_ListWidget(d->list); |
@@ -463,28 +351,8 @@ static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) { | |||
463 | return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); | 351 | return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); |
464 | } | 352 | } |
465 | 353 | ||
466 | //static void setHoverItem_SidebarWidget_(iSidebarWidget *d, size_t index) { | ||
467 | // if (index < size_Array(&d->items)) { | ||
468 | // if (constValue_Array(&d->items, index, iSidebarItem).isSeparator) { | ||
469 | // index = iInvalidPos; | ||
470 | // } | ||
471 | // } | ||
472 | // if (d->hoverItem != index) { | ||
473 | // insert_IntSet(&d->invalidItems, d->hoverItem); | ||
474 | // insert_IntSet(&d->invalidItems, index); | ||
475 | // d->hoverItem = index; | ||
476 | // refresh_Widget(as_Widget(d)); | ||
477 | // } | ||
478 | //} | ||
479 | |||
480 | //static void updateMouseHover_SidebarWidget_(iSidebarWidget *d) { | ||
481 | // const iInt2 mouse = mouseCoord_Window(get_Window()); | ||
482 | // setHoverItem_SidebarWidget_(d, itemIndex_SidebarWidget_(d, mouse)); | ||
483 | //} | ||
484 | |||
485 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, const iSidebarItem *item) { | 354 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, const iSidebarItem *item) { |
486 | setFocus_Widget(NULL); | 355 | setFocus_Widget(NULL); |
487 | // const iSidebarItem *item = constAt_Array(&d->items, index); | ||
488 | switch (d->mode) { | 356 | switch (d->mode) { |
489 | case documentOutline_SidebarMode: { | 357 | case documentOutline_SidebarMode: { |
490 | const iGmDocument *doc = document_DocumentWidget(document_App()); | 358 | const iGmDocument *doc = document_DocumentWidget(document_App()); |
@@ -795,20 +663,11 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
795 | } | 663 | } |
796 | if (ev->type == SDL_MOUSEMOTION && !isVisible_Widget(d->menu)) { | 664 | if (ev->type == SDL_MOUSEMOTION && !isVisible_Widget(d->menu)) { |
797 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); | 665 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); |
798 | // size_t hover = iInvalidPos; | ||
799 | if (contains_Widget(d->resizer, mouse)) { | 666 | if (contains_Widget(d->resizer, mouse)) { |
800 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_SIZEWE); | 667 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_SIZEWE); |
801 | } | 668 | } |
802 | // else if (contains_Widget(constAs_Widget(d->scroll), mouse)) { | ||
803 | // setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); | ||
804 | // } | ||
805 | // else if (contains_Widget(w, mouse)) { | ||
806 | // hover = itemIndex_SidebarWidget_(d, mouse); | ||
807 | // } | ||
808 | // setHoverItem_SidebarWidget_(d, hover); | ||
809 | /* Update cursor. */ | 669 | /* Update cursor. */ |
810 | else if (contains_Widget(w, mouse)) /* && !contains_Widget(d->resizer, mouse) && | 670 | else if (contains_Widget(w, mouse)) { |
811 | !contains_Widget(constAs_Widget(d->scroll), mouse))*/ { | ||
812 | const iSidebarItem *item = constHoverItem_ListWidget(d->list); | 671 | const iSidebarItem *item = constHoverItem_ListWidget(d->list); |
813 | if (item && d->mode != identities_SidebarMode) { | 672 | if (item && d->mode != identities_SidebarMode) { |
814 | setCursor_Window(get_Window(), | 673 | setCursor_Window(get_Window(), |
@@ -820,21 +679,10 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
820 | } | 679 | } |
821 | } | 680 | } |
822 | } | 681 | } |
823 | // if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { | ||
824 | //#if defined (iPlatformApple) | ||
825 | // /* Momentum scrolling. */ | ||
826 | // scroll_SidebarWidget_(d, -ev->wheel.y * get_Window()->pixelRatio); | ||
827 | //#else | ||
828 | // scroll_SidebarWidget_(d, -ev->wheel.y * 3 * d->itemHeight); | ||
829 | //#endif | ||
830 | // return iTrue; | ||
831 | // } | ||
832 | if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) { | 682 | if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) { |
833 | if (ev->button.button == SDL_BUTTON_RIGHT) { | 683 | if (ev->button.button == SDL_BUTTON_RIGHT) { |
834 | if (!isVisible_Widget(d->menu)) { | 684 | if (!isVisible_Widget(d->menu)) { |
835 | updateMouseHover_ListWidget(d->list); | 685 | updateMouseHover_ListWidget(d->list); |
836 | // setHoverItem_ListWidget( | ||
837 | // d->list, itemIndex_ListWidget(d->list, init_I2(ev->button.x, ev->button.y))); | ||
838 | } | 686 | } |
839 | if (constHoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { | 687 | if (constHoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { |
840 | /* Update menu items. */ | 688 | /* Update menu items. */ |
@@ -867,188 +715,12 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
867 | } | 715 | } |
868 | } | 716 | } |
869 | processContextMenuEvent_Widget(d->menu, ev, {}); | 717 | processContextMenuEvent_Widget(d->menu, ev, {}); |
870 | // switch (processEvent_Click(&d->click, ev)) { | ||
871 | // case started_ClickResult: | ||
872 | // //invalidate_SidebarWidget_(d); | ||
873 | // break; | ||
874 | // case finished_ClickResult: | ||
875 | // if (contains_Rect(contentBounds_SidebarWidget_(d), pos_Click(&d->click)) && | ||
876 | // d->hoverItem != iInvalidSize) { | ||
877 | // itemClicked_SidebarWidget_(d, d->hoverItem); | ||
878 | // } | ||
879 | // // invalidate_SidebarWidget_(d); | ||
880 | // break; | ||
881 | // default: | ||
882 | // break; | ||
883 | // } | ||
884 | return processEvent_Widget(w, ev); | 718 | return processEvent_Widget(w, ev); |
885 | } | 719 | } |
886 | 720 | ||
887 | static void draw_SidebarWidget_(const iSidebarWidget *d) { | 721 | static void draw_SidebarWidget_(const iSidebarWidget *d) { |
888 | const iWidget *w = constAs_Widget(d); | 722 | const iWidget *w = constAs_Widget(d); |
889 | const iRect bounds = bounds_Widget(w); | 723 | const iRect bounds = bounds_Widget(w); |
890 | #if 0 | ||
891 | const iRect bounds = contentBounds_SidebarWidget_(d); | ||
892 | const iBool isPressing = d->click.isActive && contains_Rect(bounds, pos_Click(&d->click)); | ||
893 | iPaint p; | ||
894 | init_Paint(&p); | ||
895 | const int bg = | ||
896 | d->mode == documentOutline_SidebarMode ? tmBackground_ColorId : uiBackground_ColorId; | ||
897 | fillRect_Paint(&p, bounds_Widget(w), bg); /* TODO: should do only the mode buttons area */ | ||
898 | if (!d->visBufferValid || !isEmpty_IntSet(&d->invalidItems)) { | ||
899 | allocVisBuffer_SidebarWidget_(iConstCast(iSidebarWidget *, d)); | ||
900 | iRect bufBounds = bounds; | ||
901 | bufBounds.pos = zero_I2(); | ||
902 | beginTarget_Paint(&p, d->visBuffer); | ||
903 | if (!d->visBufferValid) { | ||
904 | fillRect_Paint(&p, bufBounds, bg); | ||
905 | } | ||
906 | /* Draw the items. */ { | ||
907 | const int font = uiContent_FontId; | ||
908 | const iRanges visRange = visRange_SidebarWidget_(d); | ||
909 | iInt2 pos = addY_I2(topLeft_Rect(bufBounds), -(d->scrollY % d->itemHeight)); | ||
910 | for (size_t i = visRange.start; i < visRange.end; i++) { | ||
911 | if (d->visBufferValid && !contains_IntSet(&d->invalidItems, i)) { | ||
912 | /* TODO: Refactor to loop through invalidItems only. */ | ||
913 | pos.y += d->itemHeight; | ||
914 | continue; | ||
915 | } | ||
916 | const iSidebarItem *item = constAt_Array(&d->items, i); | ||
917 | const iRect itemRect = { pos, init_I2(width_Rect(bufBounds), d->itemHeight) }; | ||
918 | const iBool isHover = isHover_Widget(w) && (d->hoverItem == i); | ||
919 | const int iconColor = | ||
920 | isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId) | ||
921 | : uiIcon_ColorId; | ||
922 | setClip_Paint(&p, intersect_Rect(itemRect, bufBounds)); | ||
923 | if (isHover && !item->isSeparator) { | ||
924 | fillRect_Paint(&p, | ||
925 | itemRect, | ||
926 | isPressing ? uiBackgroundPressed_ColorId | ||
927 | : uiBackgroundFramelessHover_ColorId); | ||
928 | } | ||
929 | else if (d->visBufferValid) { | ||
930 | fillRect_Paint(&p, itemRect, bg); | ||
931 | } | ||
932 | if (d->mode == documentOutline_SidebarMode) { | ||
933 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId | ||
934 | : uiTextFramelessHover_ColorId) | ||
935 | : (tmHeading1_ColorId + item->indent / (4 * gap_UI)); | ||
936 | drawRange_Text(font, | ||
937 | init_I2(pos.x + 3 * gap_UI + item->indent, | ||
938 | mid_Rect(itemRect).y - lineHeight_Text(font) / 2), | ||
939 | fg, | ||
940 | range_String(&item->label)); | ||
941 | } | ||
942 | else if (d->mode == bookmarks_SidebarMode) { | ||
943 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId | ||
944 | : uiTextFramelessHover_ColorId) | ||
945 | : uiText_ColorId; | ||
946 | iString str; | ||
947 | init_String(&str); | ||
948 | appendChar_String(&str, item->icon ? item->icon : 0x1f588); | ||
949 | const iRect iconArea = { addX_I2(pos, gap_UI), | ||
950 | init_I2(7 * gap_UI, d->itemHeight) }; | ||
951 | drawCentered_Text( | ||
952 | font, | ||
953 | iconArea, | ||
954 | iTrue, | ||
955 | iconColor, | ||
956 | "%s", | ||
957 | cstr_String(&str)); | ||
958 | deinit_String(&str); | ||
959 | iInt2 textPos = addY_I2(topRight_Rect(iconArea), | ||
960 | (d->itemHeight - lineHeight_Text(font)) / 2); | ||
961 | drawRange_Text(font, textPos, fg, range_String(&item->label)); | ||
962 | } | ||
963 | else if (d->mode == history_SidebarMode) { | ||
964 | iBeginCollect(); | ||
965 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId | ||
966 | : uiTextFramelessHover_ColorId) | ||
967 | : uiText_ColorId; | ||
968 | if (item->isSeparator) { | ||
969 | if (!isEmpty_String(&item->meta)) { | ||
970 | unsetClip_Paint(&p); | ||
971 | iInt2 drawPos = addY_I2(topLeft_Rect(itemRect), d->itemHeight * 0.666f); | ||
972 | drawHLine_Paint( | ||
973 | &p, drawPos, width_Rect(itemRect), uiIcon_ColorId); | ||
974 | drawRange_Text( | ||
975 | default_FontId, | ||
976 | add_I2(drawPos, | ||
977 | init_I2(3 * gap_UI, | ||
978 | (d->itemHeight - lineHeight_Text(default_FontId)) / 2)), | ||
979 | uiIcon_ColorId, | ||
980 | range_String(&item->meta)); | ||
981 | } | ||
982 | } | ||
983 | else { | ||
984 | iUrl parts; | ||
985 | init_Url(&parts, &item->url); | ||
986 | const iBool isGemini = equalCase_Rangecc(parts.scheme, "gemini"); | ||
987 | draw_Text( | ||
988 | font, | ||
989 | add_I2(topLeft_Rect(itemRect), | ||
990 | init_I2(3 * gap_UI, (d->itemHeight - lineHeight_Text(font)) / 2)), | ||
991 | fg, | ||
992 | "%s%s%s%s%s%s", | ||
993 | isGemini ? "" : cstr_Rangecc(parts.scheme), | ||
994 | isGemini ? "" : "://", | ||
995 | escape_Color(isHover ? (isPressing ? uiTextPressed_ColorId | ||
996 | : uiTextFramelessHover_ColorId) | ||
997 | : uiTextStrong_ColorId), | ||
998 | cstr_Rangecc(parts.host), | ||
999 | escape_Color(fg), | ||
1000 | cstr_Rangecc(parts.path)); | ||
1001 | } | ||
1002 | iEndCollect(); | ||
1003 | } | ||
1004 | else if (d->mode == identities_SidebarMode) { | ||
1005 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId | ||
1006 | : uiTextFramelessHover_ColorId) | ||
1007 | : uiTextStrong_ColorId; | ||
1008 | if (item->isSelected) { | ||
1009 | drawRectThickness_Paint(&p, | ||
1010 | adjusted_Rect(itemRect, zero_I2(), init_I2(-2, -1)), | ||
1011 | gap_UI / 4, | ||
1012 | isHover && isPressing ? uiTextPressed_ColorId | ||
1013 | : uiIcon_ColorId); | ||
1014 | } | ||
1015 | iString icon; | ||
1016 | initUnicodeN_String(&icon, &item->icon, 1); | ||
1017 | iInt2 cPos = topLeft_Rect(itemRect); | ||
1018 | addv_I2(&cPos, | ||
1019 | init_I2(3 * gap_UI, | ||
1020 | (d->itemHeight - lineHeight_Text(default_FontId) * 2 - | ||
1021 | lineHeight_Text(font)) / | ||
1022 | 2)); | ||
1023 | const int metaFg = | ||
1024 | isHover ? permanent_ColorId | (isPressing ? uiTextPressed_ColorId | ||
1025 | : uiTextFramelessHover_ColorId) | ||
1026 | : uiText_ColorId; | ||
1027 | drawRange_Text( | ||
1028 | font, cPos, item->isSelected ? iconColor : metaFg, range_String(&icon)); | ||
1029 | deinit_String(&icon); | ||
1030 | drawRange_Text(font, add_I2(cPos, init_I2(6 * gap_UI, 0)), | ||
1031 | fg, range_String(&item->label)); | ||
1032 | drawRange_Text( | ||
1033 | default_FontId, | ||
1034 | add_I2(cPos, init_I2(6 * gap_UI, lineHeight_Text(font))), | ||
1035 | metaFg, | ||
1036 | range_String(&item->meta)); | ||
1037 | } | ||
1038 | unsetClip_Paint(&p); | ||
1039 | pos.y += d->itemHeight; | ||
1040 | } | ||
1041 | } | ||
1042 | endTarget_Paint(&p); | ||
1043 | /* Update state. */ { | ||
1044 | // iSidebarWidget *m = iConstCast(iSidebarWidget *, d); | ||
1045 | // m->visBufferValid = iTrue; | ||
1046 | // clear_IntSet(&m->invalidItems); | ||
1047 | } | ||
1048 | } | ||
1049 | SDL_RenderCopy( | ||
1050 | renderer_Window(get_Window()), d->visBuffer, NULL, (const SDL_Rect *) &bounds); | ||
1051 | #endif | ||
1052 | iPaint p; | 724 | iPaint p; |
1053 | init_Paint(&p); | 725 | init_Paint(&p); |
1054 | draw_Widget(w); | 726 | draw_Widget(w); |