summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-04 22:24:26 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-04 22:24:43 +0200
commit35f60fa0da324ee79923d8a730cf4f10dbb6ccdb (patch)
tree3de80c1a65333a62e3cebedce339a9386f4ce8dc /src
parent900b449a5dbe8cbf08c7ad54662b1c3067093356 (diff)
LabelWidget: Added an optional icon
Label icons are intended for context menus.
Diffstat (limited to 'src')
-rw-r--r--src/ui/labelwidget.c64
-rw-r--r--src/ui/labelwidget.h3
-rw-r--r--src/ui/util.c46
-rw-r--r--src/ui/widget.h1
-rw-r--r--src/ui/window.c8
5 files changed, 100 insertions, 22 deletions
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c
index 87c33562..83deafe2 100644
--- a/src/ui/labelwidget.c
+++ b/src/ui/labelwidget.c
@@ -30,7 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
30 30
31iLocalDef iInt2 padding_(int64_t flags) { 31iLocalDef iInt2 padding_(int64_t flags) {
32#if defined (iPlatformAppleMobile) 32#if defined (iPlatformAppleMobile)
33 return init_I2(flags & tight_WidgetFlag ? 4 * gap_UI / 2 : (4 * gap_UI), 3 * gap_UI / 2); 33 return init_I2(flags & tight_WidgetFlag ? 2 * gap_UI : (4 * gap_UI),
34 (flags & extraPadding_WidgetFlag ? 1.5f : 1) * 3 * gap_UI / 2);
34#else 35#else
35 return init_I2(flags & tight_WidgetFlag ? 3 * gap_UI / 2 : (3 * gap_UI), gap_UI); 36 return init_I2(flags & tight_WidgetFlag ? 3 * gap_UI / 2 : (3 * gap_UI), gap_UI);
36#endif 37#endif
@@ -42,6 +43,7 @@ struct Impl_LabelWidget {
42 int font; 43 int font;
43 int key; 44 int key;
44 int kmods; 45 int kmods;
46 iChar icon;
45 int forceFg; 47 int forceFg;
46 iString command; 48 iString command;
47 iBool alignVisual; /* align according to visible bounds, not typography */ 49 iBool alignVisual; /* align according to visible bounds, not typography */
@@ -201,6 +203,10 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int
201 } 203 }
202} 204}
203 205
206iLocalDef int iconPadding_LabelWidget_(const iLabelWidget *d) {
207 return d->icon ? iRound(lineHeight_Text(d->font) * 1.5f) : 0;
208}
209
204static void draw_LabelWidget_(const iLabelWidget *d) { 210static void draw_LabelWidget_(const iLabelWidget *d) {
205 const iWidget *w = constAs_Widget(d); 211 const iWidget *w = constAs_Widget(d);
206 draw_Widget(w); 212 draw_Widget(w);
@@ -208,6 +214,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) {
208 const int64_t flags = flags_Widget(w); 214 const int64_t flags = flags_Widget(w);
209 const iRect bounds = bounds_Widget(w); 215 const iRect bounds = bounds_Widget(w);
210 iRect rect = bounds; 216 iRect rect = bounds;
217 const iBool isHover = isHover_Widget(w);
211 if (isButton) { 218 if (isButton) {
212 shrink_Rect(&rect, divi_I2(gap2_UI, 4)); 219 shrink_Rect(&rect, divi_I2(gap2_UI, 4));
213 adjustEdges_Rect(&rect, gap_UI / 8, 0, -gap_UI / 8, 0); 220 adjustEdges_Rect(&rect, gap_UI / 8, 0, -gap_UI / 8, 0);
@@ -228,17 +235,32 @@ static void draw_LabelWidget_(const iLabelWidget *d) {
228 }; 235 };
229 drawLines_Paint(&p, points + 2, 3, frame2); 236 drawLines_Paint(&p, points + 2, 3, frame2);
230 drawLines_Paint( 237 drawLines_Paint(
231 &p, points, !isHover_Widget(w) && flags & noTopFrame_WidgetFlag ? 2 : 3, frame); 238 &p, points, !isHover && flags & noTopFrame_WidgetFlag ? 2 : 3, frame);
232 } 239 }
233 } 240 }
234 setClip_Paint(&p, rect); 241 setClip_Paint(&p, rect);
242 const int iconPad = iconPadding_LabelWidget_(d);
243 if (d->icon && d->icon != 0x20) { /* no need to draw an empty icon */
244 iString str;
245 initUnicodeN_String(&str, &d->icon, 1);
246 drawCentered_Text(d->font,
247 (iRect){ addX_I2(add_I2(bounds.pos, padding_(flags)), -2 * gap_UI),
248 init_I2(iconPad, lineHeight_Text(d->font)) },
249 iTrue,
250 flags & pressed_WidgetFlag ? fg
251 : isHover ? uiIconHover_ColorId
252 : uiIcon_ColorId,
253 "%s",
254 cstr_String(&str));
255 deinit_String(&str);
256 }
235 if (flags & wrapText_WidgetFlag) { 257 if (flags & wrapText_WidgetFlag) {
236 const iRect inner = innerBounds_Widget(w); 258 const iRect inner = adjusted_Rect(innerBounds_Widget(w), init_I2(iconPad, 0), zero_I2());
237 const int wrap = inner.size.x; 259 const int wrap = inner.size.x;
238 drawWrapRange_Text(d->font, topLeft_Rect(inner), wrap, fg, range_String(&d->label)); 260 drawWrapRange_Text(d->font, topLeft_Rect(inner), wrap, fg, range_String(&d->label));
239 } 261 }
240 else if (flags & alignLeft_WidgetFlag) { 262 else if (flags & alignLeft_WidgetFlag) {
241 draw_Text(d->font, add_I2(bounds.pos, padding_(flags)), fg, cstr_String(&d->label)); 263 draw_Text(d->font, add_I2(bounds.pos, addX_I2(padding_(flags), iconPad)), fg, cstr_String(&d->label));
242 if ((flags & drawKey_WidgetFlag) && d->key) { 264 if ((flags & drawKey_WidgetFlag) && d->key) {
243 iString str; 265 iString str;
244 init_String(&str); 266 init_String(&str);
@@ -260,7 +282,11 @@ static void draw_LabelWidget_(const iLabelWidget *d) {
260 cstr_String(&d->label)); 282 cstr_String(&d->label));
261 } 283 }
262 else { 284 else {
263 drawCentered_Text(d->font, bounds, d->alignVisual, fg, cstr_String(&d->label)); 285 drawCentered_Text(d->font,
286 adjusted_Rect(bounds, init_I2(iconPad, 0), zero_I2()),
287 d->alignVisual,
288 fg,
289 cstr_String(&d->label));
264 } 290 }
265 unsetClip_Paint(&p); 291 unsetClip_Paint(&p);
266} 292}
@@ -288,6 +314,7 @@ iInt2 defaultSize_LabelWidget(const iLabelWidget *d) {
288 size.x += 2 * gap_UI + measure_Text(uiShortcuts_FontId, cstr_String(&str)).x; 314 size.x += 2 * gap_UI + measure_Text(uiShortcuts_FontId, cstr_String(&str)).x;
289 deinit_String(&str); 315 deinit_String(&str);
290 } 316 }
317 size.x += iconPadding_LabelWidget_(d);
291 return size; 318 return size;
292} 319}
293 320
@@ -312,6 +339,7 @@ void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) {
312 init_Widget(&d->widget); 339 init_Widget(&d->widget);
313 d->font = uiLabel_FontId; 340 d->font = uiLabel_FontId;
314 d->forceFg = none_ColorId; 341 d->forceFg = none_ColorId;
342 d->icon = 0;
315 initCStr_String(&d->label, label); 343 initCStr_String(&d->label, label);
316 if (cmd) { 344 if (cmd) {
317 initCStr_String(&d->command, cmd); 345 initCStr_String(&d->command, cmd);
@@ -374,6 +402,32 @@ void setCommand_LabelWidget(iLabelWidget *d, const iString *command) {
374 set_String(&d->command, command); 402 set_String(&d->command, command);
375} 403}
376 404
405void setIcon_LabelWidget(iLabelWidget *d, iChar icon) {
406 if (d->icon != icon) {
407 d->icon = icon;
408 updateSize_LabelWidget(d);
409 }
410}
411
412iBool checkIcon_LabelWidget(iLabelWidget *d) {
413 if (!d->icon) {
414 iStringConstIterator iter;
415 init_StringConstIterator(&iter, &d->label);
416 const iChar icon = iter.value;
417 next_StringConstIterator(&iter);
418 if (iter.value == ' ' && icon >= 0x100) {
419 d->icon = icon;
420 remove_Block(&d->label.chars, 0, iter.next - constBegin_String(&d->label));
421 return iTrue;
422 }
423 }
424 return iFalse;
425}
426
427iChar icon_LabelWidget(const iLabelWidget *d) {
428 return d->icon;
429}
430
377const iString *text_LabelWidget(const iLabelWidget *d) { 431const iString *text_LabelWidget(const iLabelWidget *d) {
378 return &d->label; 432 return &d->label;
379} 433}
diff --git a/src/ui/labelwidget.h b/src/ui/labelwidget.h
index 83dd66e5..7a1d4de8 100644
--- a/src/ui/labelwidget.h
+++ b/src/ui/labelwidget.h
@@ -35,7 +35,9 @@ void setTextColor_LabelWidget (iLabelWidget *, int color);
35void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ 35void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */
36void setTextCStr_LabelWidget (iLabelWidget *, const char *text); 36void setTextCStr_LabelWidget (iLabelWidget *, const char *text);
37void setCommand_LabelWidget (iLabelWidget *, const iString *command); 37void setCommand_LabelWidget (iLabelWidget *, const iString *command);
38void setIcon_LabelWidget (iLabelWidget *, iChar icon);
38 39
40iBool checkIcon_LabelWidget (iLabelWidget *);
39void updateSize_LabelWidget (iLabelWidget *); 41void updateSize_LabelWidget (iLabelWidget *);
40void updateText_LabelWidget (iLabelWidget *, const iString *text); /* not resized */ 42void updateText_LabelWidget (iLabelWidget *, const iString *text); /* not resized */
41void updateTextCStr_LabelWidget (iLabelWidget *, const char *text); /* not resized */ 43void updateTextCStr_LabelWidget (iLabelWidget *, const char *text); /* not resized */
@@ -44,6 +46,7 @@ iInt2 defaultSize_LabelWidget (const iLabelWidget *);
44int font_LabelWidget (const iLabelWidget *); 46int font_LabelWidget (const iLabelWidget *);
45const iString * text_LabelWidget (const iLabelWidget *); 47const iString * text_LabelWidget (const iLabelWidget *);
46const iString * command_LabelWidget (const iLabelWidget *); 48const iString * command_LabelWidget (const iLabelWidget *);
49iChar icon_LabelWidget (const iLabelWidget *);
47 50
48iLabelWidget *newKeyMods_LabelWidget(const char *label, int key, int kmods, const char *command); 51iLabelWidget *newKeyMods_LabelWidget(const char *label, int key, int kmods, const char *command);
49iLabelWidget *newColor_LabelWidget (const char *text, int color); 52iLabelWidget *newColor_LabelWidget (const char *text, int color);
diff --git a/src/ui/util.c b/src/ui/util.c
index 055191c7..a36eb1a7 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -458,13 +458,17 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
458 setFrameColor_Widget(menu, uiSeparator_ColorId); 458 setFrameColor_Widget(menu, uiSeparator_ColorId);
459 setBackgroundColor_Widget(menu, uiBackground_ColorId); 459 setBackgroundColor_Widget(menu, uiBackground_ColorId);
460 if (deviceType_App() != desktop_AppDeviceType) { 460 if (deviceType_App() != desktop_AppDeviceType) {
461 setPadding1_Widget(menu, gap_UI); 461 setPadding1_Widget(menu, 2 * gap_UI);
462 } 462 }
463 setFlags_Widget(menu, 463 setFlags_Widget(menu,
464 keepOnTop_WidgetFlag | collapse_WidgetFlag | hidden_WidgetFlag | 464 keepOnTop_WidgetFlag | collapse_WidgetFlag | hidden_WidgetFlag |
465 arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag | 465 arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag |
466 resizeChildrenToWidestChild_WidgetFlag | overflowScrollable_WidgetFlag, 466 resizeChildrenToWidestChild_WidgetFlag | overflowScrollable_WidgetFlag,
467 iTrue); 467 iTrue);
468 const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App());
469 int64_t itemFlags = (deviceType_App() != desktop_AppDeviceType ? 0 : 0) |
470 (isPortraitPhone ? extraPadding_WidgetFlag : 0);
471 iBool haveIcons = iFalse;
468 for (size_t i = 0; i < n; ++i) { 472 for (size_t i = 0; i < n; ++i) {
469 const iMenuItem *item = &items[i]; 473 const iMenuItem *item = &items[i];
470 if (equal_CStr(item->label, "---")) { 474 if (equal_CStr(item->label, "---")) {
@@ -474,22 +478,27 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
474 iLabelWidget *label = addChildFlags_Widget( 478 iLabelWidget *label = addChildFlags_Widget(
475 menu, 479 menu,
476 iClob(newKeyMods_LabelWidget(item->label, item->key, item->kmods, item->command)), 480 iClob(newKeyMods_LabelWidget(item->label, item->key, item->kmods, item->command)),
477 frameless_WidgetFlag | alignLeft_WidgetFlag | drawKey_WidgetFlag); 481 frameless_WidgetFlag | alignLeft_WidgetFlag | drawKey_WidgetFlag | itemFlags);
482 haveIcons |= checkIcon_LabelWidget(label);
478 updateSize_LabelWidget(label); /* drawKey was set */ 483 updateSize_LabelWidget(label); /* drawKey was set */
479 const iBool isCaution = startsWith_CStr(item->label, uiTextCaution_ColorEscape);
480 if (deviceType_App() == tablet_AppDeviceType) {
481 setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId);
482 }
483 else if (deviceType_App() == desktop_AppDeviceType) {
484 setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId);
485 }
486 } 484 }
487 } 485 }
488 if (deviceType_App() == phone_AppDeviceType) { 486 if (deviceType_App() == phone_AppDeviceType) {
489 addChild_Widget(menu, iClob(makeMenuSeparator_())); 487 addChild_Widget(menu, iClob(makeMenuSeparator_()));
490 setFont_LabelWidget(addChildFlags_Widget(menu, iClob(new_LabelWidget("Cancel", "cancel")), 488 addChildFlags_Widget(menu,
491 frameless_WidgetFlag | alignLeft_WidgetFlag), 489 iClob(new_LabelWidget("Cancel", "cancel")),
492 defaultBig_FontId); 490 itemFlags | frameless_WidgetFlag | alignLeft_WidgetFlag);
491 }
492 if (haveIcons) {
493 /* All items must have icons if at least one of them has. */
494 iForEach(ObjectList, i, children_Widget(menu)) {
495 if (isInstance_Object(i.object, &Class_LabelWidget)) {
496 iLabelWidget *label = i.object;
497 if (icon_LabelWidget(label) == 0) {
498 setIcon_LabelWidget(label, ' ');
499 }
500 }
501 }
493 } 502 }
494 addChild_Widget(parent, iClob(menu)); 503 addChild_Widget(parent, iClob(menu));
495 setCommandHandler_Widget(menu, menuHandler_); 504 setCommandHandler_Widget(menu, menuHandler_);
@@ -512,10 +521,21 @@ void openMenu_Widget(iWidget *d, iInt2 coord) {
512 setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, iFalse); 521 setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, iFalse);
513 setFlags_Widget(d, resizeWidthOfChildren_WidgetFlag, iTrue); 522 setFlags_Widget(d, resizeWidthOfChildren_WidgetFlag, iTrue);
514 d->rect.size.x = rootSize_Window(get_Window()).x; 523 d->rect.size.x = rootSize_Window(get_Window()).x;
524 }
525 /* Update item fonts. */ {
515 iForEach(ObjectList, i, children_Widget(d)) { 526 iForEach(ObjectList, i, children_Widget(d)) {
516 if (isInstance_Object(i.object, &Class_LabelWidget)) { 527 if (isInstance_Object(i.object, &Class_LabelWidget)) {
517 iLabelWidget *label = i.object; 528 iLabelWidget *label = i.object;
518 setFont_LabelWidget(label, defaultBig_FontId); 529 const iBool isCaution = startsWith_String(text_LabelWidget(label), uiTextCaution_ColorEscape);
530 if (deviceType_App() == desktop_AppDeviceType) {
531 setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId);
532 }
533 else if (isPortraitPhone) {
534 setFont_LabelWidget(label, isCaution ? defaultBigBold_FontId : defaultBig_FontId);
535 }
536 else {
537 setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId);
538 }
519 } 539 }
520 } 540 }
521 } 541 }
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 955abf5d..5bd82183 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -101,6 +101,7 @@ enum iWidgetFlag {
101#define parentCannotResize_WidgetFlag iBit64(46) 101#define parentCannotResize_WidgetFlag iBit64(46)
102#define noTopFrame_WidgetFlag iBit64(47) 102#define noTopFrame_WidgetFlag iBit64(47)
103#define unpadded_WidgetFlag iBit64(48) /* ignore parent's padding */ 103#define unpadded_WidgetFlag iBit64(48) /* ignore parent's padding */
104#define extraPadding_WidgetFlag iBit64(49)
104 105
105enum iWidgetAddPos { 106enum iWidgetAddPos {
106 back_WidgetAddPos, 107 back_WidgetAddPos,
diff --git a/src/ui/window.c b/src/ui/window.c
index 60813312..008290b9 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1092,10 +1092,10 @@ static void setupUserInterface_Window(iWindow *d) {
1092// setBackgroundColor_Widget(i.object, tmBannerSideTitle_ColorId); 1092// setBackgroundColor_Widget(i.object, tmBannerSideTitle_ColorId);
1093 } 1093 }
1094 const iMenuItem items[] = { 1094 const iMenuItem items[] = {
1095 { "Bookmarks", 0, 0, "toolbar.showview arg:0" }, 1095 { "\U0001f588 Bookmarks", 0, 0, "toolbar.showview arg:0" },
1096 { "Feeds", 0, 0, "toolbar.showview arg:1" }, 1096 { "\U00002605 Feeds", 0, 0, "toolbar.showview arg:1" },
1097 { "History", 0, 0, "toolbar.showview arg:2" }, 1097 { "\U0001f553 History", 0, 0, "toolbar.showview arg:2" },
1098 { "Page Outline", 0, 0, "toolbar.showview arg:4" }, 1098 { "\U0001f5b9 Page Outline", 0, 0, "toolbar.showview arg:4" },
1099 }; 1099 };
1100 iWidget *menu = makeMenu_Widget(findChild_Widget(toolBar, "toolbar.view"), 1100 iWidget *menu = makeMenu_Widget(findChild_Widget(toolBar, "toolbar.view"),
1101 items, iElemCount(items)); 1101 items, iElemCount(items));