diff options
Diffstat (limited to 'src/ui/sidebarwidget.c')
-rw-r--r-- | src/ui/sidebarwidget.c | 607 |
1 files changed, 352 insertions, 255 deletions
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index a919fca6..8dada9eb 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
30 | #include "gmdocument.h" | 30 | #include "gmdocument.h" |
31 | #include "inputwidget.h" | 31 | #include "inputwidget.h" |
32 | #include "labelwidget.h" | 32 | #include "labelwidget.h" |
33 | #include "listwidget.h" | ||
33 | #include "paint.h" | 34 | #include "paint.h" |
34 | #include "scrollwidget.h" | 35 | #include "scrollwidget.h" |
35 | #include "util.h" | 36 | #include "util.h" |
@@ -41,27 +42,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
41 | #include <SDL_mouse.h> | 42 | #include <SDL_mouse.h> |
42 | 43 | ||
43 | iDeclareType(SidebarItem) | 44 | iDeclareType(SidebarItem) |
45 | typedef iListItemClass iSidebarItemClass; | ||
44 | 46 | ||
45 | struct Impl_SidebarItem { | 47 | struct Impl_SidebarItem { |
46 | uint32_t id; | 48 | iListItem listItem; |
47 | int indent; | 49 | uint32_t id; |
48 | iChar icon; | 50 | int indent; |
49 | iString label; | 51 | iChar icon; |
50 | iString meta; | 52 | iString label; |
51 | iString url; | 53 | iString meta; |
52 | iBool isSeparator; | 54 | iString url; |
53 | iBool isSelected; | ||
54 | }; | 55 | }; |
55 | 56 | ||
56 | void init_SidebarItem(iSidebarItem *d) { | 57 | void init_SidebarItem(iSidebarItem *d) { |
58 | init_ListItem(&d->listItem); | ||
57 | d->id = 0; | 59 | d->id = 0; |
58 | d->indent = 0; | 60 | d->indent = 0; |
59 | d->icon = 0; | 61 | d->icon = 0; |
60 | init_String(&d->label); | 62 | init_String(&d->label); |
61 | init_String(&d->meta); | 63 | init_String(&d->meta); |
62 | init_String(&d->url); | 64 | init_String(&d->url); |
63 | d->isSeparator = iFalse; | ||
64 | d->isSelected = iFalse; | ||
65 | } | 65 | } |
66 | 66 | ||
67 | void deinit_SidebarItem(iSidebarItem *d) { | 67 | void deinit_SidebarItem(iSidebarItem *d) { |
@@ -70,53 +70,60 @@ void deinit_SidebarItem(iSidebarItem *d) { | |||
70 | deinit_String(&d->label); | 70 | deinit_String(&d->label); |
71 | } | 71 | } |
72 | 72 | ||
73 | iDefineTypeConstruction(SidebarItem) | 73 | static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, const iListWidget *list); |
74 | |||
75 | iBeginDefineSubclass(SidebarItem, ListItem) | ||
76 | .draw = (iAny *) draw_SidebarItem_, | ||
77 | iEndDefineSubclass(SidebarItem) | ||
78 | |||
79 | iDefineObjectConstruction(SidebarItem) | ||
74 | 80 | ||
75 | /*----------------------------------------------------------------------------------------------*/ | 81 | /*----------------------------------------------------------------------------------------------*/ |
76 | 82 | ||
77 | struct Impl_SidebarWidget { | 83 | struct Impl_SidebarWidget { |
78 | iWidget widget; | 84 | iWidget widget; |
79 | enum iSidebarMode mode; | 85 | enum iSidebarMode mode; |
80 | iScrollWidget *scroll; | 86 | iListWidget *list; |
81 | int scrollY; | 87 | // iScrollWidget *scroll; |
88 | // int scrollY; | ||
82 | int modeScroll[max_SidebarMode]; | 89 | int modeScroll[max_SidebarMode]; |
83 | int width; | 90 | int width; |
84 | iLabelWidget *modeButtons[max_SidebarMode]; | 91 | iLabelWidget *modeButtons[max_SidebarMode]; |
85 | int itemHeight; | 92 | int itemHeight; |
86 | int maxButtonLabelWidth; | 93 | int maxButtonLabelWidth; |
87 | iArray items; | 94 | // iArray items; |
88 | size_t hoverItem; | 95 | // size_t hoverItem; |
89 | iClick click; | 96 | // iClick click; |
90 | iWidget *resizer; | 97 | iWidget *resizer; |
91 | SDL_Cursor *resizeCursor; | 98 | SDL_Cursor *resizeCursor; |
92 | iWidget *menu; | 99 | iWidget *menu; |
93 | iIntSet invalidItems; | 100 | // iIntSet invalidItems; |
94 | SDL_Texture *visBuffer; | 101 | // SDL_Texture *visBuffer; |
95 | iBool visBufferValid; | 102 | // iBool visBufferValid; |
96 | }; | 103 | }; |
97 | 104 | ||
98 | iDefineObjectConstruction(SidebarWidget) | 105 | iDefineObjectConstruction(SidebarWidget) |
99 | 106 | ||
100 | static void invalidate_SidebarWidget_(iSidebarWidget *d) { | 107 | //static void invalidate_SidebarWidget_(iSidebarWidget *d) { |
101 | d->visBufferValid = iFalse; | 108 | // d->visBufferValid = iFalse; |
102 | refresh_Widget(as_Widget(d)); | 109 | // refresh_Widget(as_Widget(d)); |
103 | clear_IntSet(&d->invalidItems); /* all will be drawn */ | 110 | // clear_IntSet(&d->invalidItems); /* all will be drawn */ |
104 | } | 111 | //} |
105 | 112 | ||
106 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { | 113 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { |
107 | return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0; | 114 | return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0; |
108 | } | 115 | } |
109 | 116 | ||
110 | static void clearItems_SidebarWidget_(iSidebarWidget *d) { | 117 | //static void clearItems_SidebarWidget_(iSidebarWidget *d) { |
111 | iForEach(Array, i, &d->items) { | 118 | // iForEach(Array, i, &d->items) { |
112 | deinit_SidebarItem(i.value); | 119 | // deinit_SidebarItem(i.value); |
113 | } | 120 | // } |
114 | clear_Array(&d->items); | 121 | // clear_Array(&d->items); |
115 | } | 122 | //} |
116 | 123 | ||
117 | static iRect contentBounds_SidebarWidget_(const iSidebarWidget *d) { | 124 | static iRect contentBounds_SidebarWidget_(const iSidebarWidget *d) { |
118 | iRect bounds = bounds_Widget(constAs_Widget(d)); | 125 | iRect bounds = bounds_Widget(constAs_Widget(d)); |
119 | const iWidget *scroll = constAs_Widget(d->scroll); | 126 | const iWidget *scroll = constAs_Widget(scroll_ListWidget(d->list)); |
120 | adjustEdges_Rect(&bounds, | 127 | adjustEdges_Rect(&bounds, |
121 | as_Widget(d->modeButtons[0])->rect.size.y + gap_UI, | 128 | as_Widget(d->modeButtons[0])->rect.size.y + gap_UI, |
122 | isVisible_Widget(scroll) ? -scroll->rect.size.x : 0, | 129 | isVisible_Widget(scroll) ? -scroll->rect.size.x : 0, |
@@ -125,57 +132,60 @@ static iRect contentBounds_SidebarWidget_(const iSidebarWidget *d) { | |||
125 | return bounds; | 132 | return bounds; |
126 | } | 133 | } |
127 | 134 | ||
128 | static int scrollMax_SidebarWidget_(const iSidebarWidget *d) { | 135 | //static int scrollMax_SidebarWidget_(const iSidebarWidget *d) { |
129 | return iMax(0, | 136 | // return iMax(0, |
130 | (int) size_Array(&d->items) * d->itemHeight - | 137 | // (int) numItems_ListWidget(d->list) * d->itemHeight - |
131 | height_Rect(contentBounds_SidebarWidget_(d))); | 138 | // height_Rect(contentBounds_SidebarWidget_(d))); |
132 | } | 139 | //} |
133 | 140 | ||
134 | static void updateVisible_SidebarWidget_(iSidebarWidget *d) { | 141 | //static void updateVisible_SidebarWidget_(iSidebarWidget *d) { |
135 | const int contentSize = size_Array(&d->items) * d->itemHeight; | 142 | // const int contentSize = size_Array(&d->items) * d->itemHeight; |
136 | const iRect bounds = contentBounds_SidebarWidget_(d); | 143 | // const iRect bounds = contentBounds_SidebarWidget_(d); |
137 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_SidebarWidget_(d) }); | 144 | // setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_SidebarWidget_(d) }); |
138 | setThumb_ScrollWidget(d->scroll, | 145 | // setThumb_ScrollWidget(d->scroll, |
139 | d->scrollY, | 146 | // d->scrollY, |
140 | contentSize > 0 ? height_Rect(bounds_Widget(as_Widget(d->scroll))) * | 147 | // contentSize > 0 ? height_Rect(bounds_Widget(as_Widget(d->scroll))) * |
141 | height_Rect(bounds) / contentSize | 148 | // height_Rect(bounds) / contentSize |
142 | : 0); | 149 | // : 0); |
143 | } | 150 | //} |
144 | 151 | ||
145 | static int cmpTitle_Bookmark_(const iBookmark **a, const iBookmark **b) { | 152 | static int cmpTitle_Bookmark_(const iBookmark **a, const iBookmark **b) { |
146 | return cmpStringCase_String(&(*a)->title, &(*b)->title); | 153 | return cmpStringCase_String(&(*a)->title, &(*b)->title); |
147 | } | 154 | } |
148 | 155 | ||
149 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { | 156 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { |
150 | clearItems_SidebarWidget_(d); | 157 | // clearItems_SidebarWidget_(d); |
158 | clear_ListWidget(d->list); | ||
151 | destroy_Widget(d->menu); | 159 | destroy_Widget(d->menu); |
152 | d->menu = NULL; | 160 | d->menu = NULL; |
153 | d->hoverItem = iInvalidPos; | 161 | // d->hoverItem = iInvalidPos; |
154 | switch (d->mode) { | 162 | switch (d->mode) { |
155 | case documentOutline_SidebarMode: { | 163 | case documentOutline_SidebarMode: { |
156 | const iGmDocument *doc = document_DocumentWidget(document_App()); | 164 | const iGmDocument *doc = document_DocumentWidget(document_App()); |
157 | iConstForEach(Array, i, headings_GmDocument(doc)) { | 165 | iConstForEach(Array, i, headings_GmDocument(doc)) { |
158 | const iGmHeading *head = i.value; | 166 | const iGmHeading *head = i.value; |
159 | iSidebarItem item; | 167 | iSidebarItem *item = new_SidebarItem(); |
160 | init_SidebarItem(&item); | 168 | // init_SidebarItem(&item); |
161 | item.id = index_ArrayConstIterator(&i); | 169 | item->id = index_ArrayConstIterator(&i); |
162 | setRange_String(&item.label, head->text); | 170 | setRange_String(&item->label, head->text); |
163 | item.indent = head->level * 4 * gap_UI; | 171 | item->indent = head->level * 4 * gap_UI; |
164 | pushBack_Array(&d->items, &item); | 172 | addItem_ListWidget(d->list, item); |
173 | iRelease(item); | ||
165 | } | 174 | } |
166 | break; | 175 | break; |
167 | } | 176 | } |
168 | case bookmarks_SidebarMode: { | 177 | case bookmarks_SidebarMode: { |
169 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), NULL, cmpTitle_Bookmark_)) { | 178 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), NULL, cmpTitle_Bookmark_)) { |
170 | const iBookmark *bm = i.ptr; | 179 | const iBookmark *bm = i.ptr; |
171 | iSidebarItem item; | 180 | iSidebarItem *item = new_SidebarItem(); |
172 | init_SidebarItem(&item); | 181 | // init_SidebarItem(&item); |
173 | item.id = id_Bookmark(bm); | 182 | item->id = id_Bookmark(bm); |
174 | item.icon = bm->icon; | 183 | item->icon = bm->icon; |
175 | set_String(&item.url, &bm->url); | 184 | set_String(&item->url, &bm->url); |
176 | set_String(&item.label, &bm->title); | 185 | set_String(&item->label, &bm->title); |
177 | set_String(&item.meta, &bm->tags); | 186 | set_String(&item->meta, &bm->tags); |
178 | pushBack_Array(&d->items, &item); | 187 | addItem_ListWidget(d->list, item); |
188 | iRelease(item); | ||
179 | } | 189 | } |
180 | d->menu = makeMenu_Widget( | 190 | d->menu = makeMenu_Widget( |
181 | as_Widget(d), | 191 | as_Widget(d), |
@@ -192,27 +202,32 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
192 | const int thisYear = on.year; | 202 | const int thisYear = on.year; |
193 | iConstForEach(PtrArray, i, list_Visited(visited_App(), 200)) { | 203 | iConstForEach(PtrArray, i, list_Visited(visited_App(), 200)) { |
194 | const iVisitedUrl *visit = i.ptr; | 204 | const iVisitedUrl *visit = i.ptr; |
195 | iSidebarItem item; | 205 | iSidebarItem *item = new_SidebarItem(); |
196 | init_SidebarItem(&item); | 206 | // init_SidebarItem(&item); |
197 | set_String(&item.url, &visit->url); | 207 | set_String(&item->url, &visit->url); |
198 | iDate date; | 208 | iDate date; |
199 | init_Date(&date, &visit->when); | 209 | init_Date(&date, &visit->when); |
200 | if (date.day != on.day || date.month != on.month || date.year != on.year) { | 210 | if (date.day != on.day || date.month != on.month || date.year != on.year) { |
201 | on = date; | 211 | on = date; |
202 | /* Date separator. */ | 212 | /* Date separator. */ |
203 | iSidebarItem sep; | 213 | iSidebarItem *sep = new_SidebarItem(); |
204 | init_SidebarItem(&sep); | 214 | // init_SidebarItem(&sep); |
205 | sep.isSeparator = iTrue; | 215 | sep->listItem.isSeparator = iTrue; |
206 | set_String(&sep.meta, | 216 | set_String(&sep->meta, |
207 | collect_String(format_Date( | 217 | collect_String(format_Date( |
208 | &date, date.year != thisYear ? "%b %d %Y" : "%b %d"))); | 218 | &date, date.year != thisYear ? "%b %d %Y" : "%b %d"))); |
209 | pushBack_Array(&d->items, &sep); | 219 | // pushBack_Array(&d->items, &sep); |
220 | addItem_ListWidget(d->list, sep); | ||
221 | iRelease(sep); | ||
210 | /* Date separators are two items tall. */ | 222 | /* Date separators are two items tall. */ |
211 | init_SidebarItem(&sep); | 223 | sep = new_SidebarItem(); |
212 | sep.isSeparator = iTrue; | 224 | sep->listItem.isSeparator = iTrue; |
213 | pushBack_Array(&d->items, &sep); | 225 | addItem_ListWidget(d->list, sep); |
226 | iRelease(sep); | ||
214 | } | 227 | } |
215 | pushBack_Array(&d->items, &item); | 228 | // pushBack_Array(&d->items, &item); |
229 | addItem_ListWidget(d->list, item); | ||
230 | iRelease(item); | ||
216 | } | 231 | } |
217 | d->menu = makeMenu_Widget( | 232 | d->menu = makeMenu_Widget( |
218 | as_Widget(d), | 233 | as_Widget(d), |
@@ -230,16 +245,16 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
230 | const iString *tabUrl = url_DocumentWidget(document_App()); | 245 | const iString *tabUrl = url_DocumentWidget(document_App()); |
231 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { | 246 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { |
232 | const iGmIdentity *ident = i.ptr; | 247 | const iGmIdentity *ident = i.ptr; |
233 | iSidebarItem item; | 248 | iSidebarItem *item = new_SidebarItem(); |
234 | init_SidebarItem(&item); | 249 | // init_SidebarItem(&item); |
235 | item.id = index_PtrArrayConstIterator(&i); | 250 | item->id = index_PtrArrayConstIterator(&i); |
236 | item.icon = ident->icon; | 251 | item->icon = ident->icon; |
237 | set_String(&item.label, collect_String(subject_TlsCertificate(ident->cert))); | 252 | set_String(&item->label, collect_String(subject_TlsCertificate(ident->cert))); |
238 | iDate until; | 253 | iDate until; |
239 | validUntil_TlsCertificate(ident->cert, &until); | 254 | validUntil_TlsCertificate(ident->cert, &until); |
240 | const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl); | 255 | const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl); |
241 | format_String( | 256 | format_String( |
242 | &item.meta, | 257 | &item->meta, |
243 | "%s", | 258 | "%s", |
244 | isActive ? "Using" | 259 | isActive ? "Using" |
245 | : isUsed_GmIdentity(ident) | 260 | : isUsed_GmIdentity(ident) |
@@ -250,17 +265,19 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
250 | ? "Temporary" | 265 | ? "Temporary" |
251 | : cstrCollect_String(format_Date(&until, "Expires %b %d, %Y")); | 266 | : cstrCollect_String(format_Date(&until, "Expires %b %d, %Y")); |
252 | if (isEmpty_String(&ident->notes)) { | 267 | if (isEmpty_String(&ident->notes)) { |
253 | appendFormat_String(&item.meta, "\n%s", expiry); | 268 | appendFormat_String(&item->meta, "\n%s", expiry); |
254 | } | 269 | } |
255 | else { | 270 | else { |
256 | appendFormat_String(&item.meta, | 271 | appendFormat_String(&item->meta, |
257 | " \u2014 %s\n%s%s", | 272 | " \u2014 %s\n%s%s", |
258 | expiry, | 273 | expiry, |
259 | escape_Color(uiHeading_ColorId), | 274 | escape_Color(uiHeading_ColorId), |
260 | cstr_String(&ident->notes)); | 275 | cstr_String(&ident->notes)); |
261 | } | 276 | } |
262 | item.isSelected = isActive; | 277 | item->listItem.isSelected = isActive; |
263 | pushBack_Array(&d->items, &item); | 278 | //pushBack_Array(&d->items, &item); |
279 | addItem_ListWidget(d->list, item); | ||
280 | iRelease(item); | ||
264 | } | 281 | } |
265 | const iMenuItem menuItems[] = { | 282 | const iMenuItem menuItems[] = { |
266 | { "Use on This Page", 0, 0, "ident.use arg:1" }, | 283 | { "Use on This Page", 0, 0, "ident.use arg:1" }, |
@@ -280,39 +297,38 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
280 | default: | 297 | default: |
281 | break; | 298 | break; |
282 | } | 299 | } |
283 | updateVisible_SidebarWidget_(d); | 300 | updateVisible_ListWidget(d->list); |
284 | invalidate_SidebarWidget_(d); | 301 | invalidate_ListWidget(d->list); |
285 | } | 302 | } |
286 | 303 | ||
287 | static void scroll_SidebarWidget_(iSidebarWidget *d, int offset) { | 304 | //static void scroll_SidebarWidget_(iSidebarWidget *d, int offset) { |
288 | const int oldScroll = d->scrollY; | 305 | // const int oldScroll = d->scrollY; |
289 | d->scrollY += offset; | 306 | // d->scrollY += offset; |
290 | if (d->scrollY < 0) { | 307 | // if (d->scrollY < 0) { |
291 | d->scrollY = 0; | 308 | // d->scrollY = 0; |
292 | } | 309 | // } |
293 | const int scrollMax = scrollMax_SidebarWidget_(d); | 310 | // const int scrollMax = scrollMax_SidebarWidget_(d); |
294 | d->scrollY = iMin(d->scrollY, scrollMax); | 311 | // d->scrollY = iMin(d->scrollY, scrollMax); |
295 | if (oldScroll != d->scrollY) { | 312 | // if (oldScroll != d->scrollY) { |
296 | d->hoverItem = iInvalidPos; | 313 | // d->hoverItem = iInvalidPos; |
297 | updateVisible_SidebarWidget_(d); | 314 | // updateVisible_SidebarWidget_(d); |
298 | invalidate_SidebarWidget_(d); | 315 | // invalidate_SidebarWidget_(d); |
299 | } | 316 | // } |
300 | } | 317 | //} |
301 | 318 | ||
302 | void setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { | 319 | void setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { |
303 | if (d->mode == mode) return; | 320 | if (d->mode == mode) return; |
304 | if (d->mode >= 0 && d->mode < max_SidebarMode) { | 321 | if (d->mode >= 0 && d->mode < max_SidebarMode) { |
305 | d->modeScroll[d->mode] = d->scrollY; /* saved for later */ | 322 | d->modeScroll[d->mode] = scrollPos_ListWidget(d->list); /* saved for later */ |
306 | } | 323 | } |
307 | d->mode = mode; | 324 | d->mode = mode; |
308 | for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) { | 325 | for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) { |
309 | setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode); | 326 | setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode); |
310 | } | 327 | } |
311 | const float heights[max_SidebarMode] = { 1.333f, 1.333f, 3.5f, 1.2f }; | 328 | const float heights[max_SidebarMode] = { 1.333f, 1.333f, 3.5f, 1.2f }; |
312 | d->itemHeight = heights[mode] * lineHeight_Text(uiContent_FontId); | 329 | setItemHeight_ListWidget(d->list, heights[mode] * lineHeight_Text(uiContent_FontId)); |
313 | invalidate_SidebarWidget_(d); | ||
314 | /* Restore previous scroll position. */ | 330 | /* Restore previous scroll position. */ |
315 | d->scrollY = d->modeScroll[mode]; | 331 | setScrollPos_ListWidget(d->list, d->modeScroll[mode]); |
316 | } | 332 | } |
317 | 333 | ||
318 | enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) { | 334 | enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) { |
@@ -343,18 +359,15 @@ void init_SidebarWidget(iSidebarWidget *d) { | |||
343 | setId_Widget(w, "sidebar"); | 359 | setId_Widget(w, "sidebar"); |
344 | setBackgroundColor_Widget(w, none_ColorId); | 360 | setBackgroundColor_Widget(w, none_ColorId); |
345 | setFlags_Widget(w, | 361 | setFlags_Widget(w, |
346 | hidden_WidgetFlag | hover_WidgetFlag | arrangeHorizontal_WidgetFlag | | 362 | hidden_WidgetFlag | arrangeVertical_WidgetFlag | |
347 | resizeWidthOfChildren_WidgetFlag | collapse_WidgetFlag, | 363 | resizeChildren_WidgetFlag | collapse_WidgetFlag, |
348 | iTrue); | 364 | iTrue); |
349 | d->scrollY = 0; | ||
350 | iZap(d->modeScroll); | 365 | iZap(d->modeScroll); |
351 | d->mode = -1; | 366 | d->mode = -1; |
352 | d->width = 60 * gap_UI; | 367 | d->width = 60 * gap_UI; |
353 | init_Array(&d->items, sizeof(iSidebarItem)); | ||
354 | d->hoverItem = iInvalidPos; | ||
355 | init_Click(&d->click, d, SDL_BUTTON_LEFT); | ||
356 | setFlags_Widget(w, fixedWidth_WidgetFlag, iTrue); | 368 | setFlags_Widget(w, fixedWidth_WidgetFlag, iTrue); |
357 | d->maxButtonLabelWidth = 0; | 369 | d->maxButtonLabelWidth = 0; |
370 | /* TODO: Add a parent h-div for the mode buttons. */ | ||
358 | for (int i = 0; i < max_SidebarMode; i++) { | 371 | for (int i = 0; i < max_SidebarMode; i++) { |
359 | d->modeButtons[i] = addChildFlags_Widget( | 372 | d->modeButtons[i] = addChildFlags_Widget( |
360 | w, | 373 | w, |
@@ -365,8 +378,7 @@ void init_SidebarWidget(iSidebarWidget *d) { | |||
365 | iMaxi(d->maxButtonLabelWidth, | 378 | iMaxi(d->maxButtonLabelWidth, |
366 | 3 * gap_UI + measure_Text(uiLabel_FontId, normalModeLabels_[i]).x); | 379 | 3 * gap_UI + measure_Text(uiLabel_FontId, normalModeLabels_[i]).x); |
367 | } | 380 | } |
368 | addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); | 381 | addChildFlags_Widget(w, iClob(d->list = new_ListWidget()), expand_WidgetFlag); |
369 | setThumb_ScrollWidget(d->scroll, 0, 0); | ||
370 | setMode_SidebarWidget(d, documentOutline_SidebarMode); | 382 | setMode_SidebarWidget(d, documentOutline_SidebarMode); |
371 | d->resizer = addChildFlags_Widget( | 383 | d->resizer = addChildFlags_Widget( |
372 | w, | 384 | w, |
@@ -378,55 +390,51 @@ void init_SidebarWidget(iSidebarWidget *d) { | |||
378 | setBackgroundColor_Widget(d->resizer, none_ColorId); | 390 | setBackgroundColor_Widget(d->resizer, none_ColorId); |
379 | d->resizeCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); | 391 | d->resizeCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); |
380 | d->menu = NULL; | 392 | d->menu = NULL; |
381 | init_IntSet(&d->invalidItems); | ||
382 | d->visBuffer = NULL; | ||
383 | d->visBufferValid = iFalse; | ||
384 | } | 393 | } |
385 | 394 | ||
386 | void deinit_SidebarWidget(iSidebarWidget *d) { | 395 | void deinit_SidebarWidget(iSidebarWidget *d) { |
387 | SDL_FreeCursor(d->resizeCursor); | 396 | SDL_FreeCursor(d->resizeCursor); |
388 | clearItems_SidebarWidget_(d); | 397 | //clearItems_SidebarWidget_(d); |
389 | deinit_Array(&d->items); | 398 | // deinit_Array(&d->items); |
390 | SDL_DestroyTexture(d->visBuffer); | ||
391 | } | 399 | } |
392 | 400 | ||
393 | static int visCount_SidebarWidget_(const iSidebarWidget *d) { | 401 | //static int visCount_SidebarWidget_(const iSidebarWidget *d) { |
394 | return iMin(height_Rect(bounds_Widget(constAs_Widget(d))) / d->itemHeight, | 402 | // return iMin(height_Rect(bounds_Widget(constAs_Widget(d))) / d->itemHeight, |
395 | (int) size_Array(&d->items)); | 403 | // (int) size_Array(&d->items)); |
396 | } | 404 | //} |
397 | 405 | ||
398 | static iRanges visRange_SidebarWidget_(const iSidebarWidget *d) { | 406 | //static iRanges visRange_SidebarWidget_(const iSidebarWidget *d) { |
399 | iRanges vis = { d->scrollY / d->itemHeight, 0 }; | 407 | // iRanges vis = { d->scrollY / d->itemHeight, 0 }; |
400 | vis.end = iMin(size_Array(&d->items), vis.start + visCount_SidebarWidget_(d)); | 408 | // vis.end = iMin(size_Array(&d->items), vis.start + visCount_SidebarWidget_(d)); |
401 | return vis; | 409 | // return vis; |
402 | } | 410 | //} |
403 | 411 | ||
404 | static size_t itemIndex_SidebarWidget_(const iSidebarWidget *d, iInt2 pos) { | 412 | //static size_t itemIndex_SidebarWidget_(const iSidebarWidget *d, iInt2 pos) { |
405 | const iRect bounds = contentBounds_SidebarWidget_(d); | 413 | // const iRect bounds = contentBounds_SidebarWidget_(d); |
406 | pos.y -= top_Rect(bounds) - d->scrollY; | 414 | // pos.y -= top_Rect(bounds) - d->scrollY; |
407 | if (pos.y < 0) return iInvalidPos; | 415 | // if (pos.y < 0) return iInvalidPos; |
408 | size_t index = pos.y / d->itemHeight; | 416 | // size_t index = pos.y / d->itemHeight; |
409 | if (index >= size_Array(&d->items)) return iInvalidPos; | 417 | // if (index >= size_Array(&d->items)) return iInvalidPos; |
410 | return index; | 418 | // return index; |
411 | } | 419 | //} |
412 | 420 | ||
413 | static const iSidebarItem *constHoverItem_SidebarWidget_(const iSidebarWidget *d) { | 421 | //static const iSidebarItem *constHoverItem_SidebarWidget_(const iSidebarWidget *d) { |
414 | if (d->hoverItem < size_Array(&d->items)) { | 422 | // if (d->hoverItem < size_Array(&d->items)) { |
415 | return constAt_Array(&d->items, d->hoverItem); | 423 | // return constAt_Array(&d->items, d->hoverItem); |
416 | } | 424 | // } |
417 | return NULL; | 425 | // return NULL; |
418 | } | 426 | //} |
419 | 427 | ||
420 | static iSidebarItem *hoverItem_SidebarWidget_(iSidebarWidget *d) { | 428 | //static iSidebarItem *hoverItem_SidebarWidget_(iSidebarWidget *d) { |
421 | if (d->hoverItem < size_Array(&d->items)) { | 429 | // if (d->hoverItem < size_Array(&d->items)) { |
422 | return at_Array(&d->items, d->hoverItem); | 430 | // return at_Array(&d->items, d->hoverItem); |
423 | } | 431 | // } |
424 | return NULL; | 432 | // return NULL; |
425 | } | 433 | //} |
426 | 434 | ||
427 | static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) { | 435 | static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) { |
428 | if (d->mode == identities_SidebarMode) { | 436 | if (d->mode == identities_SidebarMode) { |
429 | const iSidebarItem *hoverItem = constHoverItem_SidebarWidget_(d); | 437 | const iSidebarItem *hoverItem = constHoverItem_ListWidget(d->list); |
430 | if (hoverItem) { | 438 | if (hoverItem) { |
431 | return identity_GmCerts(certs_App(), hoverItem->id); | 439 | return identity_GmCerts(certs_App(), hoverItem->id); |
432 | } | 440 | } |
@@ -438,28 +446,28 @@ static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) { | |||
438 | return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); | 446 | return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); |
439 | } | 447 | } |
440 | 448 | ||
441 | static void setHoverItem_SidebarWidget_(iSidebarWidget *d, size_t index) { | 449 | //static void setHoverItem_SidebarWidget_(iSidebarWidget *d, size_t index) { |
442 | if (index < size_Array(&d->items)) { | 450 | // if (index < size_Array(&d->items)) { |
443 | if (constValue_Array(&d->items, index, iSidebarItem).isSeparator) { | 451 | // if (constValue_Array(&d->items, index, iSidebarItem).isSeparator) { |
444 | index = iInvalidPos; | 452 | // index = iInvalidPos; |
445 | } | 453 | // } |
446 | } | 454 | // } |
447 | if (d->hoverItem != index) { | 455 | // if (d->hoverItem != index) { |
448 | insert_IntSet(&d->invalidItems, d->hoverItem); | 456 | // insert_IntSet(&d->invalidItems, d->hoverItem); |
449 | insert_IntSet(&d->invalidItems, index); | 457 | // insert_IntSet(&d->invalidItems, index); |
450 | d->hoverItem = index; | 458 | // d->hoverItem = index; |
451 | refresh_Widget(as_Widget(d)); | 459 | // refresh_Widget(as_Widget(d)); |
452 | } | 460 | // } |
453 | } | 461 | //} |
454 | 462 | ||
455 | static void updateMouseHover_SidebarWidget_(iSidebarWidget *d) { | 463 | //static void updateMouseHover_SidebarWidget_(iSidebarWidget *d) { |
456 | const iInt2 mouse = mouseCoord_Window(get_Window()); | 464 | // const iInt2 mouse = mouseCoord_Window(get_Window()); |
457 | setHoverItem_SidebarWidget_(d, itemIndex_SidebarWidget_(d, mouse)); | 465 | // setHoverItem_SidebarWidget_(d, itemIndex_SidebarWidget_(d, mouse)); |
458 | } | 466 | //} |
459 | 467 | ||
460 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, size_t index) { | 468 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, const iSidebarItem *item) { |
461 | setFocus_Widget(NULL); | 469 | setFocus_Widget(NULL); |
462 | const iSidebarItem *item = constAt_Array(&d->items, index); | 470 | // const iSidebarItem *item = constAt_Array(&d->items, index); |
463 | switch (d->mode) { | 471 | switch (d->mode) { |
464 | case documentOutline_SidebarMode: { | 472 | case documentOutline_SidebarMode: { |
465 | const iGmDocument *doc = document_DocumentWidget(document_App()); | 473 | const iGmDocument *doc = document_DocumentWidget(document_App()); |
@@ -485,7 +493,7 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, size_t index) { | |||
485 | signIn_GmCerts(certs_App(), ident, tabUrl); | 493 | signIn_GmCerts(certs_App(), ident, tabUrl); |
486 | } | 494 | } |
487 | updateItems_SidebarWidget_(d); | 495 | updateItems_SidebarWidget_(d); |
488 | updateMouseHover_SidebarWidget_(d); | 496 | updateMouseHover_ListWidget(d->list); |
489 | } | 497 | } |
490 | break; | 498 | break; |
491 | } | 499 | } |
@@ -520,7 +528,7 @@ void setWidth_SidebarWidget(iSidebarWidget *d, int width) { | |||
520 | checkModeButtonLayout_SidebarWidget_(d); | 528 | checkModeButtonLayout_SidebarWidget_(d); |
521 | if (!isRefreshPending_App()) { | 529 | if (!isRefreshPending_App()) { |
522 | updateSize_DocumentWidget(document_App()); | 530 | updateSize_DocumentWidget(document_App()); |
523 | invalidate_SidebarWidget_(d); | 531 | invalidate_ListWidget(d->list); |
524 | } | 532 | } |
525 | } | 533 | } |
526 | 534 | ||
@@ -531,7 +539,7 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c | |||
531 | const iString *title = text_InputWidget(findChild_Widget(editor, "bmed.title")); | 539 | const iString *title = text_InputWidget(findChild_Widget(editor, "bmed.title")); |
532 | const iString *url = text_InputWidget(findChild_Widget(editor, "bmed.url")); | 540 | const iString *url = text_InputWidget(findChild_Widget(editor, "bmed.url")); |
533 | const iString *tags = text_InputWidget(findChild_Widget(editor, "bmed.tags")); | 541 | const iString *tags = text_InputWidget(findChild_Widget(editor, "bmed.tags")); |
534 | const iSidebarItem *item = hoverItem_SidebarWidget_(d); | 542 | const iSidebarItem *item = hoverItem_ListWidget(d->list); |
535 | iAssert(item); /* hover item cannot have been changed */ | 543 | iAssert(item); /* hover item cannot have been changed */ |
536 | iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id); | 544 | iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id); |
537 | set_String(&bm->title, title); | 545 | set_String(&bm->title, title); |
@@ -550,9 +558,9 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
550 | iWidget *w = as_Widget(d); | 558 | iWidget *w = as_Widget(d); |
551 | /* Handle commands. */ | 559 | /* Handle commands. */ |
552 | if (isResize_UserEvent(ev)) { | 560 | if (isResize_UserEvent(ev)) { |
553 | updateVisible_SidebarWidget_(d); | 561 | updateVisible_ListWidget(d->list); |
554 | checkModeButtonLayout_SidebarWidget_(d); | 562 | checkModeButtonLayout_SidebarWidget_(d); |
555 | invalidate_SidebarWidget_(d); | 563 | invalidate_ListWidget(d->list); |
556 | } | 564 | } |
557 | else if (ev->type == SDL_USEREVENT && ev->user.code == command_UserEventCode) { | 565 | else if (ev->type == SDL_USEREVENT && ev->user.code == command_UserEventCode) { |
558 | const char *cmd = command_UserEvent(ev); | 566 | const char *cmd = command_UserEvent(ev); |
@@ -580,6 +588,10 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
580 | } | 588 | } |
581 | return iTrue; | 589 | return iTrue; |
582 | } | 590 | } |
591 | else if (isCommand_Widget(w, ev, "list.clicked")) { | ||
592 | itemClicked_SidebarWidget_(d, pointerLabel_Command(cmd, "item")); | ||
593 | return iTrue; | ||
594 | } | ||
583 | else if (equal_Command(cmd, "sidebar.width")) { | 595 | else if (equal_Command(cmd, "sidebar.width")) { |
584 | setWidth_SidebarWidget(d, arg_Command(cmd)); | 596 | setWidth_SidebarWidget(d, arg_Command(cmd)); |
585 | return iTrue; | 597 | return iTrue; |
@@ -590,7 +602,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
590 | if (argLabel_Command(cmd, "show") && !isVisible_Widget(w)) { | 602 | if (argLabel_Command(cmd, "show") && !isVisible_Widget(w)) { |
591 | postCommand_App("sidebar.toggle arg:1"); | 603 | postCommand_App("sidebar.toggle arg:1"); |
592 | } | 604 | } |
593 | scroll_SidebarWidget_(d, 0); | 605 | scrollOffset_ListWidget(d->list, 0); |
594 | return iTrue; | 606 | return iTrue; |
595 | } | 607 | } |
596 | else if (equal_Command(cmd, "sidebar.toggle")) { | 608 | else if (equal_Command(cmd, "sidebar.toggle")) { |
@@ -600,34 +612,25 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
600 | setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w)); | 612 | setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w)); |
601 | if (isVisible_Widget(w)) { | 613 | if (isVisible_Widget(w)) { |
602 | w->rect.size.x = d->width; | 614 | w->rect.size.x = d->width; |
603 | invalidate_SidebarWidget_(d); | 615 | invalidate_ListWidget(d->list); |
604 | } | 616 | } |
605 | arrange_Widget(w->parent); | 617 | arrange_Widget(w->parent); |
606 | updateSize_DocumentWidget(document_App()); | 618 | updateSize_DocumentWidget(document_App()); |
607 | refresh_Widget(w->parent); | 619 | refresh_Widget(w->parent); |
608 | return iTrue; | 620 | return iTrue; |
609 | } | 621 | } |
610 | else if (equal_Command(cmd, "scroll.moved")) { | ||
611 | d->scrollY = arg_Command(command_UserEvent(ev)); | ||
612 | d->hoverItem = iInvalidPos; | ||
613 | invalidate_SidebarWidget_(d); | ||
614 | return iTrue; | ||
615 | } | ||
616 | else if (equal_Command(cmd, "tabs.changed") || equal_Command(cmd, "document.changed")) { | 622 | else if (equal_Command(cmd, "tabs.changed") || equal_Command(cmd, "document.changed")) { |
617 | updateItems_SidebarWidget_(d); | 623 | updateItems_SidebarWidget_(d); |
618 | } | 624 | } |
619 | else if (equal_Command(cmd, "theme.changed")) { | ||
620 | invalidate_SidebarWidget_(d); | ||
621 | } | ||
622 | else if (equal_Command(cmd, "bookmark.copy")) { | 625 | else if (equal_Command(cmd, "bookmark.copy")) { |
623 | const iSidebarItem *item = hoverItem_SidebarWidget_(d); | 626 | const iSidebarItem *item = hoverItem_ListWidget(d->list); |
624 | if (d->mode == bookmarks_SidebarMode && item) { | 627 | if (d->mode == bookmarks_SidebarMode && item) { |
625 | SDL_SetClipboardText(cstr_String(&item->url)); | 628 | SDL_SetClipboardText(cstr_String(&item->url)); |
626 | } | 629 | } |
627 | return iTrue; | 630 | return iTrue; |
628 | } | 631 | } |
629 | else if (equal_Command(cmd, "bookmark.edit")) { | 632 | else if (equal_Command(cmd, "bookmark.edit")) { |
630 | const iSidebarItem *item = hoverItem_SidebarWidget_(d); | 633 | const iSidebarItem *item = hoverItem_ListWidget(d->list); |
631 | if (d->mode == bookmarks_SidebarMode && item) { | 634 | if (d->mode == bookmarks_SidebarMode && item) { |
632 | setFlags_Widget(w, disabled_WidgetFlag, iTrue); | 635 | setFlags_Widget(w, disabled_WidgetFlag, iTrue); |
633 | iWidget *dlg = makeBookmarkEditor_Widget(); | 636 | iWidget *dlg = makeBookmarkEditor_Widget(); |
@@ -641,7 +644,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
641 | return iTrue; | 644 | return iTrue; |
642 | } | 645 | } |
643 | else if (equal_Command(cmd, "bookmark.delete")) { | 646 | else if (equal_Command(cmd, "bookmark.delete")) { |
644 | const iSidebarItem *item = hoverItem_SidebarWidget_(d); | 647 | const iSidebarItem *item = hoverItem_ListWidget(d->list); |
645 | if (d->mode == bookmarks_SidebarMode && item && remove_Bookmarks(bookmarks_App(), item->id)) { | 648 | if (d->mode == bookmarks_SidebarMode && item && remove_Bookmarks(bookmarks_App(), item->id)) { |
646 | postCommand_App("bookmarks.changed"); | 649 | postCommand_App("bookmarks.changed"); |
647 | } | 650 | } |
@@ -712,7 +715,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
712 | return iTrue; | 715 | return iTrue; |
713 | } | 716 | } |
714 | else if (equal_Command(cmd, "ident.delete")) { | 717 | else if (equal_Command(cmd, "ident.delete")) { |
715 | iSidebarItem *item = hoverItem_SidebarWidget_(d); | 718 | iSidebarItem *item = hoverItem_ListWidget(d->list); |
716 | if (argLabel_Command(cmd, "confirm")) { | 719 | if (argLabel_Command(cmd, "confirm")) { |
717 | makeQuestion_Widget(uiTextCaution_ColorEscape "DELETE IDENTITY", | 720 | makeQuestion_Widget(uiTextCaution_ColorEscape "DELETE IDENTITY", |
718 | format_CStr("Do you really want to delete the identity\n" | 721 | format_CStr("Do you really want to delete the identity\n" |
@@ -732,23 +735,23 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
732 | return iTrue; | 735 | return iTrue; |
733 | } | 736 | } |
734 | else if (equal_Command(cmd, "history.delete")) { | 737 | else if (equal_Command(cmd, "history.delete")) { |
735 | const iSidebarItem *item = hoverItem_SidebarWidget_(d); | 738 | const iSidebarItem *item = hoverItem_ListWidget(d->list); |
736 | if (item && !isEmpty_String(&item->url)) { | 739 | if (item && !isEmpty_String(&item->url)) { |
737 | removeUrl_Visited(visited_App(), &item->url); | 740 | removeUrl_Visited(visited_App(), &item->url); |
738 | updateItems_SidebarWidget_(d); | 741 | updateItems_SidebarWidget_(d); |
739 | scroll_SidebarWidget_(d, 0); | 742 | scrollOffset_ListWidget(d->list, 0); |
740 | } | 743 | } |
741 | return iTrue; | 744 | return iTrue; |
742 | } | 745 | } |
743 | else if (equal_Command(cmd, "history.copy")) { | 746 | else if (equal_Command(cmd, "history.copy")) { |
744 | const iSidebarItem *item = hoverItem_SidebarWidget_(d); | 747 | const iSidebarItem *item = hoverItem_ListWidget(d->list); |
745 | if (item && !isEmpty_String(&item->url)) { | 748 | if (item && !isEmpty_String(&item->url)) { |
746 | SDL_SetClipboardText(cstr_String(&item->url)); | 749 | SDL_SetClipboardText(cstr_String(&item->url)); |
747 | } | 750 | } |
748 | return iTrue; | 751 | return iTrue; |
749 | } | 752 | } |
750 | else if (equal_Command(cmd, "history.addbookmark")) { | 753 | else if (equal_Command(cmd, "history.addbookmark")) { |
751 | const iSidebarItem *item = hoverItem_SidebarWidget_(d); | 754 | const iSidebarItem *item = hoverItem_ListWidget(d->list); |
752 | if (!isEmpty_String(&item->url)) { | 755 | if (!isEmpty_String(&item->url)) { |
753 | makeBookmarkCreation_Widget( | 756 | makeBookmarkCreation_Widget( |
754 | &item->url, | 757 | &item->url, |
@@ -768,53 +771,55 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
768 | else { | 771 | else { |
769 | clear_Visited(visited_App()); | 772 | clear_Visited(visited_App()); |
770 | updateItems_SidebarWidget_(d); | 773 | updateItems_SidebarWidget_(d); |
771 | scroll_SidebarWidget_(d, 0); | 774 | scrollOffset_ListWidget(d->list, 0); |
772 | } | 775 | } |
773 | return iTrue; | 776 | return iTrue; |
774 | } | 777 | } |
775 | } | 778 | } |
776 | if (ev->type == SDL_MOUSEMOTION && !isVisible_Widget(d->menu)) { | 779 | if (ev->type == SDL_MOUSEMOTION && !isVisible_Widget(d->menu)) { |
777 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); | 780 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); |
778 | size_t hover = iInvalidPos; | 781 | // size_t hover = iInvalidPos; |
779 | if (contains_Widget(d->resizer, mouse)) { | 782 | if (contains_Widget(d->resizer, mouse)) { |
780 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_SIZEWE); | 783 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_SIZEWE); |
781 | } | 784 | } |
782 | else if (contains_Widget(constAs_Widget(d->scroll), mouse)) { | 785 | // else if (contains_Widget(constAs_Widget(d->scroll), mouse)) { |
783 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); | 786 | // setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); |
784 | } | 787 | // } |
785 | else if (contains_Widget(w, mouse)) { | 788 | // else if (contains_Widget(w, mouse)) { |
786 | hover = itemIndex_SidebarWidget_(d, mouse); | 789 | // hover = itemIndex_SidebarWidget_(d, mouse); |
787 | } | 790 | // } |
788 | setHoverItem_SidebarWidget_(d, hover); | 791 | // setHoverItem_SidebarWidget_(d, hover); |
789 | /* Update cursor. */ | 792 | /* Update cursor. */ |
790 | if (contains_Widget(w, mouse) && !contains_Widget(d->resizer, mouse) && | 793 | else if (contains_Widget(w, mouse)) /* && !contains_Widget(d->resizer, mouse) && |
791 | !contains_Widget(constAs_Widget(d->scroll), mouse)) { | 794 | !contains_Widget(constAs_Widget(d->scroll), mouse))*/ { |
792 | const iSidebarItem *item = constHoverItem_SidebarWidget_(d); | 795 | const iSidebarItem *item = constHoverItem_ListWidget(d->list); |
793 | if (item && d->mode != identities_SidebarMode) { | 796 | if (item && d->mode != identities_SidebarMode) { |
794 | setCursor_Window(get_Window(), item->isSeparator ? SDL_SYSTEM_CURSOR_ARROW | 797 | setCursor_Window(get_Window(), |
795 | : SDL_SYSTEM_CURSOR_HAND); | 798 | item->listItem.isSeparator ? SDL_SYSTEM_CURSOR_ARROW |
799 | : SDL_SYSTEM_CURSOR_HAND); | ||
796 | } | 800 | } |
797 | else { | 801 | else { |
798 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); | 802 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); |
799 | } | 803 | } |
800 | } | 804 | } |
801 | } | 805 | } |
802 | if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { | 806 | // if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { |
803 | #if defined (iPlatformApple) | 807 | //#if defined (iPlatformApple) |
804 | /* Momentum scrolling. */ | 808 | // /* Momentum scrolling. */ |
805 | scroll_SidebarWidget_(d, -ev->wheel.y * get_Window()->pixelRatio); | 809 | // scroll_SidebarWidget_(d, -ev->wheel.y * get_Window()->pixelRatio); |
806 | #else | 810 | //#else |
807 | scroll_SidebarWidget_(d, -ev->wheel.y * 3 * d->itemHeight); | 811 | // scroll_SidebarWidget_(d, -ev->wheel.y * 3 * d->itemHeight); |
808 | #endif | 812 | //#endif |
809 | return iTrue; | 813 | // return iTrue; |
810 | } | 814 | // } |
811 | if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) { | 815 | if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) { |
812 | if (ev->button.button == SDL_BUTTON_RIGHT) { | 816 | if (ev->button.button == SDL_BUTTON_RIGHT) { |
813 | if (!isVisible_Widget(d->menu)) { | 817 | if (!isVisible_Widget(d->menu)) { |
814 | setHoverItem_SidebarWidget_( | 818 | updateMouseHover_ListWidget(d->list); |
815 | d, itemIndex_SidebarWidget_(d, init_I2(ev->button.x, ev->button.y))); | 819 | // setHoverItem_ListWidget( |
820 | // d->list, itemIndex_ListWidget(d->list, init_I2(ev->button.x, ev->button.y))); | ||
816 | } | 821 | } |
817 | if (d->hoverItem != iInvalidPos || isVisible_Widget(d->menu)) { | 822 | if (constHoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { |
818 | /* Update menu items. */ | 823 | /* Update menu items. */ |
819 | if (d->mode == identities_SidebarMode) { | 824 | if (d->mode == identities_SidebarMode) { |
820 | const iGmIdentity *ident = constHoverIdentity_SidebarWidget_(d); | 825 | const iGmIdentity *ident = constHoverIdentity_SidebarWidget_(d); |
@@ -845,41 +850,27 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
845 | } | 850 | } |
846 | } | 851 | } |
847 | processContextMenuEvent_Widget(d->menu, ev, {}); | 852 | processContextMenuEvent_Widget(d->menu, ev, {}); |
848 | switch (processEvent_Click(&d->click, ev)) { | 853 | // switch (processEvent_Click(&d->click, ev)) { |
849 | case started_ClickResult: | 854 | // case started_ClickResult: |
850 | //invalidate_SidebarWidget_(d); | 855 | // //invalidate_SidebarWidget_(d); |
851 | break; | 856 | // break; |
852 | case finished_ClickResult: | 857 | // case finished_ClickResult: |
853 | if (contains_Rect(contentBounds_SidebarWidget_(d), pos_Click(&d->click)) && | 858 | // if (contains_Rect(contentBounds_SidebarWidget_(d), pos_Click(&d->click)) && |
854 | d->hoverItem != iInvalidSize) { | 859 | // d->hoverItem != iInvalidSize) { |
855 | itemClicked_SidebarWidget_(d, d->hoverItem); | 860 | // itemClicked_SidebarWidget_(d, d->hoverItem); |
856 | } | 861 | // } |
857 | // invalidate_SidebarWidget_(d); | 862 | // // invalidate_SidebarWidget_(d); |
858 | break; | 863 | // break; |
859 | default: | 864 | // default: |
860 | break; | 865 | // break; |
861 | } | 866 | // } |
862 | return processEvent_Widget(w, ev); | 867 | return processEvent_Widget(w, ev); |
863 | } | 868 | } |
864 | 869 | ||
865 | static void allocVisBuffer_SidebarWidget_(iSidebarWidget *d) { | ||
866 | const iInt2 size = contentBounds_SidebarWidget_(d).size; | ||
867 | if (!d->visBuffer || !isEqual_I2(size_SDLTexture(d->visBuffer), size)) { | ||
868 | if (d->visBuffer) { | ||
869 | SDL_DestroyTexture(d->visBuffer); | ||
870 | } | ||
871 | d->visBuffer = SDL_CreateTexture(renderer_Window(get_Window()), | ||
872 | SDL_PIXELFORMAT_RGBA8888, | ||
873 | SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, | ||
874 | size.x, | ||
875 | size.y); | ||
876 | SDL_SetTextureBlendMode(d->visBuffer, SDL_BLENDMODE_NONE); | ||
877 | d->visBufferValid = iFalse; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | static void draw_SidebarWidget_(const iSidebarWidget *d) { | 870 | static void draw_SidebarWidget_(const iSidebarWidget *d) { |
882 | const iWidget *w = constAs_Widget(d); | 871 | const iWidget *w = constAs_Widget(d); |
872 | const iRect bounds = bounds_Widget(w); | ||
873 | #if 0 | ||
883 | const iRect bounds = contentBounds_SidebarWidget_(d); | 874 | const iRect bounds = contentBounds_SidebarWidget_(d); |
884 | const iBool isPressing = d->click.isActive && contains_Rect(bounds, pos_Click(&d->click)); | 875 | const iBool isPressing = d->click.isActive && contains_Rect(bounds, pos_Click(&d->click)); |
885 | iPaint p; | 876 | iPaint p; |
@@ -1033,18 +1024,124 @@ static void draw_SidebarWidget_(const iSidebarWidget *d) { | |||
1033 | } | 1024 | } |
1034 | endTarget_Paint(&p); | 1025 | endTarget_Paint(&p); |
1035 | /* Update state. */ { | 1026 | /* Update state. */ { |
1036 | iSidebarWidget *m = iConstCast(iSidebarWidget *, d); | 1027 | // iSidebarWidget *m = iConstCast(iSidebarWidget *, d); |
1037 | m->visBufferValid = iTrue; | 1028 | // m->visBufferValid = iTrue; |
1038 | clear_IntSet(&m->invalidItems); | 1029 | // clear_IntSet(&m->invalidItems); |
1039 | } | 1030 | } |
1040 | } | 1031 | } |
1041 | SDL_RenderCopy( | 1032 | SDL_RenderCopy( |
1042 | renderer_Window(get_Window()), d->visBuffer, NULL, (const SDL_Rect *) &bounds); | 1033 | renderer_Window(get_Window()), d->visBuffer, NULL, (const SDL_Rect *) &bounds); |
1034 | #endif | ||
1035 | iPaint p; | ||
1036 | init_Paint(&p); | ||
1043 | draw_Widget(w); | 1037 | draw_Widget(w); |
1044 | drawVLine_Paint(&p, | 1038 | drawVLine_Paint( |
1045 | addX_I2(topRight_Rect(bounds_Widget(w)), -1), | 1039 | &p, addX_I2(topRight_Rect(bounds), -1), height_Rect(bounds), uiSeparator_ColorId); |
1046 | height_Rect(bounds_Widget(w)), | 1040 | } |
1047 | uiSeparator_ColorId); | 1041 | |
1042 | static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | ||
1043 | const iListWidget *list) { | ||
1044 | const iSidebarWidget *sidebar = (const iSidebarWidget *) constAs_Widget(list)->parent; | ||
1045 | const iBool isPressing = isMouseDown_ListWidget(list); | ||
1046 | const int font = uiContent_FontId; | ||
1047 | const iBool isHover = | ||
1048 | isHover_Widget(constAs_Widget(list)) && constHoverItem_ListWidget(list) == d; | ||
1049 | const int itemHeight = height_Rect(itemRect); | ||
1050 | const int iconColor = | ||
1051 | isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId) : uiIcon_ColorId; | ||
1052 | if (isHover && !d->listItem.isSeparator) { | ||
1053 | fillRect_Paint(p, | ||
1054 | itemRect, | ||
1055 | isPressing ? uiBackgroundPressed_ColorId | ||
1056 | : uiBackgroundFramelessHover_ColorId); | ||
1057 | } | ||
1058 | iInt2 pos = itemRect.pos; | ||
1059 | if (sidebar->mode == documentOutline_SidebarMode) { | ||
1060 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) | ||
1061 | : (tmHeading1_ColorId + d->indent / (4 * gap_UI)); | ||
1062 | drawRange_Text(font, | ||
1063 | init_I2(pos.x + 3 * gap_UI + d->indent, | ||
1064 | mid_Rect(itemRect).y - lineHeight_Text(font) / 2), | ||
1065 | fg, | ||
1066 | range_String(&d->label)); | ||
1067 | } | ||
1068 | else if (sidebar->mode == bookmarks_SidebarMode) { | ||
1069 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) | ||
1070 | : uiText_ColorId; | ||
1071 | iString str; | ||
1072 | init_String(&str); | ||
1073 | appendChar_String(&str, d->icon ? d->icon : 0x1f588); | ||
1074 | const iRect iconArea = { addX_I2(pos, gap_UI), init_I2(7 * gap_UI, itemHeight) }; | ||
1075 | drawCentered_Text(font, iconArea, iTrue, iconColor, "%s", cstr_String(&str)); | ||
1076 | deinit_String(&str); | ||
1077 | iInt2 textPos = addY_I2(topRight_Rect(iconArea), (itemHeight - lineHeight_Text(font)) / 2); | ||
1078 | drawRange_Text(font, textPos, fg, range_String(&d->label)); | ||
1079 | } | ||
1080 | else if (sidebar->mode == history_SidebarMode) { | ||
1081 | iBeginCollect(); | ||
1082 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) | ||
1083 | : uiText_ColorId; | ||
1084 | if (d->listItem.isSeparator) { | ||
1085 | if (!isEmpty_String(&d->meta)) { | ||
1086 | unsetClip_Paint(p); | ||
1087 | iInt2 drawPos = addY_I2(topLeft_Rect(itemRect), itemHeight * 0.666f); | ||
1088 | drawHLine_Paint(p, drawPos, width_Rect(itemRect), uiIcon_ColorId); | ||
1089 | drawRange_Text( | ||
1090 | default_FontId, | ||
1091 | add_I2(drawPos, | ||
1092 | init_I2(3 * gap_UI, (itemHeight - lineHeight_Text(default_FontId)) / 2)), | ||
1093 | uiIcon_ColorId, | ||
1094 | range_String(&d->meta)); | ||
1095 | } | ||
1096 | } | ||
1097 | else { | ||
1098 | iUrl parts; | ||
1099 | init_Url(&parts, &d->url); | ||
1100 | const iBool isGemini = equalCase_Rangecc(parts.scheme, "gemini"); | ||
1101 | draw_Text(font, | ||
1102 | add_I2(topLeft_Rect(itemRect), | ||
1103 | init_I2(3 * gap_UI, (itemHeight - lineHeight_Text(font)) / 2)), | ||
1104 | fg, | ||
1105 | "%s%s%s%s%s%s", | ||
1106 | isGemini ? "" : cstr_Rangecc(parts.scheme), | ||
1107 | isGemini ? "" : "://", | ||
1108 | escape_Color(isHover ? (isPressing ? uiTextPressed_ColorId | ||
1109 | : uiTextFramelessHover_ColorId) | ||
1110 | : uiTextStrong_ColorId), | ||
1111 | cstr_Rangecc(parts.host), | ||
1112 | escape_Color(fg), | ||
1113 | cstr_Rangecc(parts.path)); | ||
1114 | } | ||
1115 | iEndCollect(); | ||
1116 | } | ||
1117 | else if (sidebar->mode == identities_SidebarMode) { | ||
1118 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) | ||
1119 | : uiTextStrong_ColorId; | ||
1120 | if (d->listItem.isSelected) { | ||
1121 | drawRectThickness_Paint(p, | ||
1122 | adjusted_Rect(itemRect, zero_I2(), init_I2(-2, -1)), | ||
1123 | gap_UI / 4, | ||
1124 | isHover && isPressing ? uiTextPressed_ColorId : uiIcon_ColorId); | ||
1125 | } | ||
1126 | iString icon; | ||
1127 | initUnicodeN_String(&icon, &d->icon, 1); | ||
1128 | iInt2 cPos = topLeft_Rect(itemRect); | ||
1129 | addv_I2(&cPos, | ||
1130 | init_I2(3 * gap_UI, | ||
1131 | (itemHeight - lineHeight_Text(default_FontId) * 2 - lineHeight_Text(font)) / | ||
1132 | 2)); | ||
1133 | const int metaFg = isHover ? permanent_ColorId | (isPressing ? uiTextPressed_ColorId | ||
1134 | : uiTextFramelessHover_ColorId) | ||
1135 | : uiText_ColorId; | ||
1136 | drawRange_Text( | ||
1137 | font, cPos, d->listItem.isSelected ? iconColor : metaFg, range_String(&icon)); | ||
1138 | deinit_String(&icon); | ||
1139 | drawRange_Text(font, add_I2(cPos, init_I2(6 * gap_UI, 0)), fg, range_String(&d->label)); | ||
1140 | drawRange_Text(default_FontId, | ||
1141 | add_I2(cPos, init_I2(6 * gap_UI, lineHeight_Text(font))), | ||
1142 | metaFg, | ||
1143 | range_String(&d->meta)); | ||
1144 | } | ||
1048 | } | 1145 | } |
1049 | 1146 | ||
1050 | iBeginDefineSubclass(SidebarWidget, Widget) | 1147 | iBeginDefineSubclass(SidebarWidget, Widget) |