From 35f60fa0da324ee79923d8a730cf4f10dbb6ccdb Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 4 Mar 2021 22:24:26 +0200 Subject: LabelWidget: Added an optional icon Label icons are intended for context menus. --- src/ui/labelwidget.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/ui/labelwidget.h | 3 +++ src/ui/util.c | 46 ++++++++++++++++++++++++++----------- src/ui/widget.h | 1 + src/ui/window.c | 8 +++---- 5 files changed, 100 insertions(+), 22 deletions(-) (limited to 'src') 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. */ iLocalDef iInt2 padding_(int64_t flags) { #if defined (iPlatformAppleMobile) - return init_I2(flags & tight_WidgetFlag ? 4 * gap_UI / 2 : (4 * gap_UI), 3 * gap_UI / 2); + return init_I2(flags & tight_WidgetFlag ? 2 * gap_UI : (4 * gap_UI), + (flags & extraPadding_WidgetFlag ? 1.5f : 1) * 3 * gap_UI / 2); #else return init_I2(flags & tight_WidgetFlag ? 3 * gap_UI / 2 : (3 * gap_UI), gap_UI); #endif @@ -42,6 +43,7 @@ struct Impl_LabelWidget { int font; int key; int kmods; + iChar icon; int forceFg; iString command; 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 } } +iLocalDef int iconPadding_LabelWidget_(const iLabelWidget *d) { + return d->icon ? iRound(lineHeight_Text(d->font) * 1.5f) : 0; +} + static void draw_LabelWidget_(const iLabelWidget *d) { const iWidget *w = constAs_Widget(d); draw_Widget(w); @@ -208,6 +214,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { const int64_t flags = flags_Widget(w); const iRect bounds = bounds_Widget(w); iRect rect = bounds; + const iBool isHover = isHover_Widget(w); if (isButton) { shrink_Rect(&rect, divi_I2(gap2_UI, 4)); adjustEdges_Rect(&rect, gap_UI / 8, 0, -gap_UI / 8, 0); @@ -228,17 +235,32 @@ static void draw_LabelWidget_(const iLabelWidget *d) { }; drawLines_Paint(&p, points + 2, 3, frame2); drawLines_Paint( - &p, points, !isHover_Widget(w) && flags & noTopFrame_WidgetFlag ? 2 : 3, frame); + &p, points, !isHover && flags & noTopFrame_WidgetFlag ? 2 : 3, frame); } } setClip_Paint(&p, rect); + const int iconPad = iconPadding_LabelWidget_(d); + if (d->icon && d->icon != 0x20) { /* no need to draw an empty icon */ + iString str; + initUnicodeN_String(&str, &d->icon, 1); + drawCentered_Text(d->font, + (iRect){ addX_I2(add_I2(bounds.pos, padding_(flags)), -2 * gap_UI), + init_I2(iconPad, lineHeight_Text(d->font)) }, + iTrue, + flags & pressed_WidgetFlag ? fg + : isHover ? uiIconHover_ColorId + : uiIcon_ColorId, + "%s", + cstr_String(&str)); + deinit_String(&str); + } if (flags & wrapText_WidgetFlag) { - const iRect inner = innerBounds_Widget(w); + const iRect inner = adjusted_Rect(innerBounds_Widget(w), init_I2(iconPad, 0), zero_I2()); const int wrap = inner.size.x; drawWrapRange_Text(d->font, topLeft_Rect(inner), wrap, fg, range_String(&d->label)); } else if (flags & alignLeft_WidgetFlag) { - draw_Text(d->font, add_I2(bounds.pos, padding_(flags)), fg, cstr_String(&d->label)); + draw_Text(d->font, add_I2(bounds.pos, addX_I2(padding_(flags), iconPad)), fg, cstr_String(&d->label)); if ((flags & drawKey_WidgetFlag) && d->key) { iString str; init_String(&str); @@ -260,7 +282,11 @@ static void draw_LabelWidget_(const iLabelWidget *d) { cstr_String(&d->label)); } else { - drawCentered_Text(d->font, bounds, d->alignVisual, fg, cstr_String(&d->label)); + drawCentered_Text(d->font, + adjusted_Rect(bounds, init_I2(iconPad, 0), zero_I2()), + d->alignVisual, + fg, + cstr_String(&d->label)); } unsetClip_Paint(&p); } @@ -288,6 +314,7 @@ iInt2 defaultSize_LabelWidget(const iLabelWidget *d) { size.x += 2 * gap_UI + measure_Text(uiShortcuts_FontId, cstr_String(&str)).x; deinit_String(&str); } + size.x += iconPadding_LabelWidget_(d); return size; } @@ -312,6 +339,7 @@ void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { init_Widget(&d->widget); d->font = uiLabel_FontId; d->forceFg = none_ColorId; + d->icon = 0; initCStr_String(&d->label, label); if (cmd) { initCStr_String(&d->command, cmd); @@ -374,6 +402,32 @@ void setCommand_LabelWidget(iLabelWidget *d, const iString *command) { set_String(&d->command, command); } +void setIcon_LabelWidget(iLabelWidget *d, iChar icon) { + if (d->icon != icon) { + d->icon = icon; + updateSize_LabelWidget(d); + } +} + +iBool checkIcon_LabelWidget(iLabelWidget *d) { + if (!d->icon) { + iStringConstIterator iter; + init_StringConstIterator(&iter, &d->label); + const iChar icon = iter.value; + next_StringConstIterator(&iter); + if (iter.value == ' ' && icon >= 0x100) { + d->icon = icon; + remove_Block(&d->label.chars, 0, iter.next - constBegin_String(&d->label)); + return iTrue; + } + } + return iFalse; +} + +iChar icon_LabelWidget(const iLabelWidget *d) { + return d->icon; +} + const iString *text_LabelWidget(const iLabelWidget *d) { return &d->label; } 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); void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ void setTextCStr_LabelWidget (iLabelWidget *, const char *text); void setCommand_LabelWidget (iLabelWidget *, const iString *command); +void setIcon_LabelWidget (iLabelWidget *, iChar icon); +iBool checkIcon_LabelWidget (iLabelWidget *); void updateSize_LabelWidget (iLabelWidget *); void updateText_LabelWidget (iLabelWidget *, const iString *text); /* not resized */ void updateTextCStr_LabelWidget (iLabelWidget *, const char *text); /* not resized */ @@ -44,6 +46,7 @@ iInt2 defaultSize_LabelWidget (const iLabelWidget *); int font_LabelWidget (const iLabelWidget *); const iString * text_LabelWidget (const iLabelWidget *); const iString * command_LabelWidget (const iLabelWidget *); +iChar icon_LabelWidget (const iLabelWidget *); iLabelWidget *newKeyMods_LabelWidget(const char *label, int key, int kmods, const char *command); iLabelWidget *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) { setFrameColor_Widget(menu, uiSeparator_ColorId); setBackgroundColor_Widget(menu, uiBackground_ColorId); if (deviceType_App() != desktop_AppDeviceType) { - setPadding1_Widget(menu, gap_UI); + setPadding1_Widget(menu, 2 * gap_UI); } setFlags_Widget(menu, keepOnTop_WidgetFlag | collapse_WidgetFlag | hidden_WidgetFlag | arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag | overflowScrollable_WidgetFlag, iTrue); + const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App()); + int64_t itemFlags = (deviceType_App() != desktop_AppDeviceType ? 0 : 0) | + (isPortraitPhone ? extraPadding_WidgetFlag : 0); + iBool haveIcons = iFalse; for (size_t i = 0; i < n; ++i) { const iMenuItem *item = &items[i]; if (equal_CStr(item->label, "---")) { @@ -474,22 +478,27 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { iLabelWidget *label = addChildFlags_Widget( menu, iClob(newKeyMods_LabelWidget(item->label, item->key, item->kmods, item->command)), - frameless_WidgetFlag | alignLeft_WidgetFlag | drawKey_WidgetFlag); + frameless_WidgetFlag | alignLeft_WidgetFlag | drawKey_WidgetFlag | itemFlags); + haveIcons |= checkIcon_LabelWidget(label); updateSize_LabelWidget(label); /* drawKey was set */ - const iBool isCaution = startsWith_CStr(item->label, uiTextCaution_ColorEscape); - if (deviceType_App() == tablet_AppDeviceType) { - setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId); - } - else if (deviceType_App() == desktop_AppDeviceType) { - setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId); - } } } if (deviceType_App() == phone_AppDeviceType) { addChild_Widget(menu, iClob(makeMenuSeparator_())); - setFont_LabelWidget(addChildFlags_Widget(menu, iClob(new_LabelWidget("Cancel", "cancel")), - frameless_WidgetFlag | alignLeft_WidgetFlag), - defaultBig_FontId); + addChildFlags_Widget(menu, + iClob(new_LabelWidget("Cancel", "cancel")), + itemFlags | frameless_WidgetFlag | alignLeft_WidgetFlag); + } + if (haveIcons) { + /* All items must have icons if at least one of them has. */ + iForEach(ObjectList, i, children_Widget(menu)) { + if (isInstance_Object(i.object, &Class_LabelWidget)) { + iLabelWidget *label = i.object; + if (icon_LabelWidget(label) == 0) { + setIcon_LabelWidget(label, ' '); + } + } + } } addChild_Widget(parent, iClob(menu)); setCommandHandler_Widget(menu, menuHandler_); @@ -512,10 +521,21 @@ void openMenu_Widget(iWidget *d, iInt2 coord) { setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, iFalse); setFlags_Widget(d, resizeWidthOfChildren_WidgetFlag, iTrue); d->rect.size.x = rootSize_Window(get_Window()).x; + } + /* Update item fonts. */ { iForEach(ObjectList, i, children_Widget(d)) { if (isInstance_Object(i.object, &Class_LabelWidget)) { iLabelWidget *label = i.object; - setFont_LabelWidget(label, defaultBig_FontId); + const iBool isCaution = startsWith_String(text_LabelWidget(label), uiTextCaution_ColorEscape); + if (deviceType_App() == desktop_AppDeviceType) { + setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId); + } + else if (isPortraitPhone) { + setFont_LabelWidget(label, isCaution ? defaultBigBold_FontId : defaultBig_FontId); + } + else { + setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId); + } } } } 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 { #define parentCannotResize_WidgetFlag iBit64(46) #define noTopFrame_WidgetFlag iBit64(47) #define unpadded_WidgetFlag iBit64(48) /* ignore parent's padding */ +#define extraPadding_WidgetFlag iBit64(49) enum iWidgetAddPos { 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) { // setBackgroundColor_Widget(i.object, tmBannerSideTitle_ColorId); } const iMenuItem items[] = { - { "Bookmarks", 0, 0, "toolbar.showview arg:0" }, - { "Feeds", 0, 0, "toolbar.showview arg:1" }, - { "History", 0, 0, "toolbar.showview arg:2" }, - { "Page Outline", 0, 0, "toolbar.showview arg:4" }, + { "\U0001f588 Bookmarks", 0, 0, "toolbar.showview arg:0" }, + { "\U00002605 Feeds", 0, 0, "toolbar.showview arg:1" }, + { "\U0001f553 History", 0, 0, "toolbar.showview arg:2" }, + { "\U0001f5b9 Page Outline", 0, 0, "toolbar.showview arg:4" }, }; iWidget *menu = makeMenu_Widget(findChild_Widget(toolBar, "toolbar.view"), items, iElemCount(items)); -- cgit v1.2.3