From 8269c38f074cb991e79430bd2ae9fe892d412635 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 2 Dec 2021 14:48:56 +0200 Subject: Mobile: Button group style; upload dialog tweaks Use checkmarks for selections in button groups. --- src/ui/labelwidget.c | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index f6ddfd43..9ef62262 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -44,14 +44,15 @@ struct Impl_LabelWidget { iString command; iClick click; struct { - uint8_t alignVisual : 1; /* align according to visible bounds, not font metrics */ - uint8_t noAutoMinHeight : 1; /* minimum height is not set automatically */ - uint8_t drawAsOutline : 1; /* draw as outline, filled with background color */ - uint8_t noTopFrame : 1; - uint8_t wrap : 1; - uint8_t allCaps : 1; - uint8_t removeTrailingColon : 1; - uint8_t chevron : 1; + uint16_t alignVisual : 1; /* align according to visible bounds, not font metrics */ + uint16_t noAutoMinHeight : 1; /* minimum height is not set automatically */ + uint16_t drawAsOutline : 1; /* draw as outline, filled with background color */ + uint16_t noTopFrame : 1; + uint16_t wrap : 1; + uint16_t allCaps : 1; + uint16_t removeTrailingColon : 1; + uint16_t chevron : 1; + uint16_t checkMark : 1; } flags; }; @@ -204,6 +205,9 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int *bg = isButton && ~flags & noBackground_WidgetFlag ? (d->widget.bgColor != none_ColorId ? d->widget.bgColor : uiBackground_ColorId) : none_ColorId; + if (d->flags.checkMark) { + *bg = none_ColorId; + } *fg = uiText_ColorId; *frame1 = isButton ? uiEmboss1_ColorId : d->widget.frameColor; *frame2 = isButton ? uiEmboss2_ColorId : *frame1; @@ -215,13 +219,15 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int *meta = uiTextDisabled_ColorId; } if (isSel) { - *bg = uiBackgroundSelected_ColorId; + if (!d->flags.checkMark) { + *bg = uiBackgroundSelected_ColorId; // if (!isKeyRoot) { // *bg = uiEmbossSelected1_ColorId; //uiBackgroundUnfocusedSelection_ColorId; // } - if (!isKeyRoot) { - *bg = isDark_ColorTheme(colorTheme_App()) ? uiBackgroundUnfocusedSelection_ColorId - : uiMarked_ColorId ; + if (!isKeyRoot) { + *bg = isDark_ColorTheme(colorTheme_App()) ? uiBackgroundUnfocusedSelection_ColorId + : uiMarked_ColorId; + } } *fg = uiTextSelected_ColorId; if (isButton) { @@ -429,14 +435,23 @@ static void draw_LabelWidget_(const iLabelWidget *d) { "%s", cstr_String(&d->label)); } - if (d->flags.chevron) { + if (d->flags.chevron || (flags & selected_WidgetFlag && d->flags.checkMark)) { const iRect chRect = rect; const int chSize = lineHeight_Text(d->font); + int offset = 0; + if (d->flags.chevron) { + offset = -iconPad; + } + else { + offset = -10 * gap_UI; + } drawCentered_Text(d->font, - (iRect){ addX_I2(topRight_Rect(chRect), -iconPad), + (iRect){ addX_I2(topRight_Rect(chRect), offset), init_I2(chSize, height_Rect(chRect)) }, - iTrue, iconColor, rightAngle_Icon); - } + iTrue, + iconColor, + d->flags.chevron ? rightAngle_Icon : check_Icon); + } unsetClip_Paint(&p); drawChildren_Widget(w); } @@ -580,6 +595,10 @@ void setChevron_LabelWidget(iLabelWidget *d, iBool chevron) { d->flags.chevron = chevron; } +void setCheckMark_LabelWidget(iLabelWidget *d, iBool checkMark) { + d->flags.checkMark = checkMark; +} + void setWrap_LabelWidget(iLabelWidget *d, iBool wrap) { d->flags.wrap = wrap; } -- cgit v1.2.3 From 8e7c651faa2e7525cc2e4251516585f89b822ab8 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 2 Dec 2021 19:33:57 +0200 Subject: Widget: Widget rearrangement issues There were issues where popup menus would only get wider and never narrower. Arrangements should not be dependent on the results of a previous one. --- src/ui/labelwidget.c | 4 ++-- src/ui/util.c | 50 +++++++++++++++++++++++++++++++------------------- src/ui/widget.c | 16 ++++++++++++++++ 3 files changed, 49 insertions(+), 21 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 9ef62262..947d5daa 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -491,9 +491,9 @@ int font_LabelWidget(const iLabelWidget *d) { } void updateSize_LabelWidget(iLabelWidget *d) { - iWidget *w = as_Widget(d); + iWidget *w = as_Widget(d); const int64_t flags = flags_Widget(w); - const iInt2 size = defaultSize_LabelWidget(d); + const iInt2 size = defaultSize_LabelWidget(d); if (!d->flags.noAutoMinHeight) { w->minSize.y = size.y; /* vertically text must remain visible */ } diff --git a/src/ui/util.c b/src/ui/util.c index 91b67e06..61d3e9bb 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -861,12 +861,8 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { setFlags_Widget(menu, keepOnTop_WidgetFlag | collapse_WidgetFlag | hidden_WidgetFlag | arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag | - resizeChildrenToWidestChild_WidgetFlag | overflowScrollable_WidgetFlag | - (isPortraitPhone_App() ? drawBackgroundToVerticalSafeArea_WidgetFlag : 0), + resizeChildrenToWidestChild_WidgetFlag | overflowScrollable_WidgetFlag, iTrue); - if (!isPortraitPhone_App()) { - setFrameColor_Widget(menu, uiBackgroundSelected_ColorId); - } makeMenuItems_Widget(menu, items, n); addChild_Widget(parent, menu); iRelease(menu); /* owned by parent now */ @@ -884,6 +880,7 @@ void openMenu_Widget(iWidget *d, iInt2 windowCoord) { static void updateMenuItemFonts_Widget_(iWidget *d) { const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App()); + const iBool isMobile = (deviceType_App() != desktop_AppDeviceType); const iBool isSlidePanel = (flags_Widget(d) & horizontalOffset_WidgetFlag) != 0; iForEach(ObjectList, i, children_Widget(d)) { if (isInstance_Object(i.object, &Class_LabelWidget)) { @@ -895,14 +892,14 @@ static void updateMenuItemFonts_Widget_(iWidget *d) { if (deviceType_App() == desktop_AppDeviceType) { setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId); } - else if (isPortraitPhone) { - if (!isSlidePanel) { - setFont_LabelWidget(label, isCaution ? uiLabelBigBold_FontId : uiLabelBig_FontId); - } - } - else { - setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId); + else { //if (isPortraitPhone) { + //if (!isSlidePanel) { + setFont_LabelWidget(label, isCaution ? uiLabelBigBold_FontId : uiLabelBig_FontId); + // } } +// else { +// setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId); +// } } else if (childCount_Widget(i.object)) { updateMenuItemFonts_Widget_(i.object); @@ -1034,6 +1031,12 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { setFlags_Widget(d, hidden_WidgetFlag, iFalse); setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue); setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse); + if (!isPortraitPhone) { + setFrameColor_Widget(d, uiBackgroundSelected_ColorId); + } + else { + setFrameColor_Widget(d, none_ColorId); + } arrange_Widget(d); /* need to know the height */ iBool allowOverflow = iFalse; /* A vertical offset determined by a possible selected label in the menu. */ @@ -1104,13 +1107,22 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { } #endif raise_Widget(d); - if (isPortraitPhone) { - setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, iFalse); - setFlags_Widget(d, resizeWidthOfChildren_WidgetFlag | drawBackgroundToBottom_WidgetFlag, iTrue); - if (!isSlidePanel) { - setFlags_Widget(d, borderTop_WidgetFlag, iTrue); + if (deviceType_App() != desktop_AppDeviceType) { + setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, + !isPortraitPhone); + setFlags_Widget(d, + resizeWidthOfChildren_WidgetFlag | drawBackgroundToBottom_WidgetFlag | + drawBackgroundToVerticalSafeArea_WidgetFlag, + isPortraitPhone); + if (isPortraitPhone) { + if (!isSlidePanel) { + setFlags_Widget(d, borderTop_WidgetFlag, iTrue); + } + d->rect.size.x = rootSize.x; + } + else { + d->rect.size.x = 0; } - d->rect.size.x = rootSize.x; } updateMenuItemFonts_Widget_(d); arrange_Widget(d); @@ -2458,7 +2470,7 @@ iWidget *makePreferences_Widget(void) { { "title id:heading.settings" }, { "panel text:" gear_Icon " ${heading.prefs.general}", 0, 0, (const void *) generalPanelItems }, { "panel icon:0x1f5a7 id:heading.prefs.network", 0, 0, (const void *) networkPanelItems }, - { "panel text:" person_Icon " ${sidebar.identities}", 0, 0, (const void *) identityPanelItems }, + { "panel noscroll:1 text:" person_Icon " ${sidebar.identities}", 0, 0, (const void *) identityPanelItems }, { "padding" }, { "panel icon:0x1f4f1 id:heading.prefs.interface", 0, 0, (const void *) uiPanelItems }, { "panel icon:0x1f3a8 id:heading.prefs.colors", 0, 0, (const void *) colorPanelItems }, diff --git a/src/ui/widget.c b/src/ui/widget.c index cedda461..254c2590 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "util.h" #include "window.h" +#include "labelwidget.h" + #include #include #include @@ -836,6 +838,12 @@ static void arrange_Widget_(iWidget *d) { } static void resetArrangement_Widget_(iWidget *d) { + if (d->flags & resizeToParentWidth_WidgetFlag) { + d->rect.size.x = 0; + } + if (d->flags & resizeToParentHeight_WidgetFlag) { + d->rect.size.y = 0; + } iForEach(ObjectList, i, children_Widget(d)) { iWidget *child = as_Widget(i.object); resetArrangement_Widget_(child); @@ -847,6 +855,14 @@ static void resetArrangement_Widget_(iWidget *d) { ~child->flags & fixedWidth_WidgetFlag) { child->rect.size.x = 0; } + if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { + if (isInstance_Object(child, &Class_LabelWidget)) { + updateSize_LabelWidget((iLabelWidget *) child); + } + else { + child->rect.size.x = 0; + } + } if (d->flags & arrangeVertical_WidgetFlag) { child->rect.pos.y = 0; } -- cgit v1.2.3 From 6e917280380316eba77b1dfa983daf488510e70f Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 3 Dec 2021 07:46:16 +0200 Subject: Mobile: Manage Identities via Settings --- po/en.po | 5 ++- res/lang/cs.bin | Bin 31054 -> 31087 bytes res/lang/de.bin | Bin 30061 -> 30094 bytes res/lang/en.bin | Bin 26158 -> 26191 bytes res/lang/eo.bin | Bin 25112 -> 25145 bytes res/lang/es.bin | Bin 29885 -> 29918 bytes res/lang/es_MX.bin | Bin 27217 -> 27250 bytes res/lang/fi.bin | Bin 29718 -> 29751 bytes res/lang/fr.bin | Bin 30865 -> 30898 bytes res/lang/gl.bin | Bin 29070 -> 29103 bytes res/lang/hu.bin | Bin 30890 -> 30923 bytes res/lang/ia.bin | Bin 28217 -> 28250 bytes res/lang/ie.bin | Bin 28805 -> 28838 bytes res/lang/isv.bin | Bin 24878 -> 24911 bytes res/lang/pl.bin | Bin 29493 -> 29526 bytes res/lang/ru.bin | Bin 44253 -> 44286 bytes res/lang/sk.bin | Bin 25214 -> 25247 bytes res/lang/sr.bin | Bin 43679 -> 43712 bytes res/lang/tok.bin | Bin 26927 -> 26960 bytes res/lang/tr.bin | Bin 29111 -> 29144 bytes res/lang/uk.bin | Bin 43598 -> 43631 bytes res/lang/zh_Hans.bin | Bin 25112 -> 25145 bytes res/lang/zh_Hant.bin | Bin 25310 -> 25343 bytes src/app.c | 8 +++++ src/ui/labelwidget.c | 17 ++++++---- src/ui/labelwidget.h | 1 + src/ui/mobile.c | 11 ++++--- src/ui/mobile.h | 1 + src/ui/root.c | 88 +++++++++++++++++++++++++++++++++++-------------- src/ui/sidebarwidget.c | 20 ++++++----- src/ui/uploadwidget.c | 7 +++- src/ui/util.c | 9 +++++ src/ui/util.h | 3 +- src/ui/widget.c | 10 +++--- 34 files changed, 129 insertions(+), 51 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/po/en.po b/po/en.po index c6fa98be..4e013941 100644 --- a/po/en.po +++ b/po/en.po @@ -395,6 +395,9 @@ msgstr "New Identity…" msgid "menu.identity.import" msgstr "Import…" +msgid "menu.identities" +msgstr "Manage Identities" + msgid "menu.identity.notactive" msgstr "No Active Identity" @@ -988,7 +991,7 @@ msgid "upload.id" msgstr "Identity:" msgid "heading.upload.id" -msgstr "Identification" +msgstr "Authorization" msgid "dlg.upload.id.none" msgstr "None" diff --git a/res/lang/cs.bin b/res/lang/cs.bin index 8f8b3a6f..7c08bcfe 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/de.bin b/res/lang/de.bin index 2df7f11f..e3f45a34 100644 Binary files a/res/lang/de.bin and b/res/lang/de.bin differ diff --git a/res/lang/en.bin b/res/lang/en.bin index 0129d019..0c65ffd3 100644 Binary files a/res/lang/en.bin and b/res/lang/en.bin differ diff --git a/res/lang/eo.bin b/res/lang/eo.bin index 4acb5f16..9edecafe 100644 Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index 5d04443c..9e7d0585 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin index 3fcecd44..1dd95a4e 100644 Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ diff --git a/res/lang/fi.bin b/res/lang/fi.bin index 53449c30..1d5e4624 100644 Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ diff --git a/res/lang/fr.bin b/res/lang/fr.bin index 2ccda4da..c0202489 100644 Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ diff --git a/res/lang/gl.bin b/res/lang/gl.bin index 9f37b384..34d16341 100644 Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ diff --git a/res/lang/hu.bin b/res/lang/hu.bin index 4de98a70..2ab5484b 100644 Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ diff --git a/res/lang/ia.bin b/res/lang/ia.bin index f9e134fc..c43aec10 100644 Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ diff --git a/res/lang/ie.bin b/res/lang/ie.bin index 3324bb69..8a1d71e4 100644 Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ diff --git a/res/lang/isv.bin b/res/lang/isv.bin index 6b98e1f8..e9978815 100644 Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ diff --git a/res/lang/pl.bin b/res/lang/pl.bin index 33ed890b..b6de49f1 100644 Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index 82c43ffc..7f153025 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sk.bin b/res/lang/sk.bin index 6dbeb129..35fdb2b1 100644 Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index 7f058106..bd9ca450 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tok.bin b/res/lang/tok.bin index 206fe02c..cb34ada6 100644 Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index 430ab02c..99dc6431 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index 49d58f42..edcafb7e 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin index cfa284be..488cc64f 100644 Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin index f0f6fe97..edab200b 100644 Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ diff --git a/src/app.c b/src/app.c index 540c46d8..5b2e88bf 100644 --- a/src/app.c +++ b/src/app.c @@ -2667,6 +2667,9 @@ iBool handleCommand_App(const char *cmd) { if (!urlArg) { return iTrue; /* invalid command */ } + if (findWidget_App("prefs")) { + postCommand_App("prefs.dismiss"); + } iString *url = collectNewCStr_String(urlArg); const iBool noProxy = argLabel_Command(cmd, "noproxy") != 0; const iBool fromSidebar = argLabel_Command(cmd, "fromsidebar") != 0; @@ -2979,6 +2982,11 @@ iBool handleCommand_App(const char *cmd) { showTabPage_Widget(tabs, tabPage_Widget(tabs, d->prefs.dialogTab)); } setCommandHandler_Widget(dlg, handlePrefsCommands_); + if (argLabel_Command(cmd, "idents") && deviceType_App() != desktop_AppDeviceType) { + iWidget *idPanel = panel_Mobile(dlg, 2); + iWidget *button = findUserData_Widget(findChild_Widget(dlg, "panel.top"), idPanel); + postCommand_Widget(button, "panel.open"); + } } else if (equal_Command(cmd, "navigate.home")) { /* Look for bookmarks tagged "homepage". */ diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 947d5daa..d00733e1 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -36,6 +36,7 @@ struct Impl_LabelWidget { iWidget widget; iString srcLabel; iString label; + iInt2 labelOffset; int font; int key; int kmods; @@ -362,10 +363,6 @@ static void draw_LabelWidget_(const iLabelWidget *d) { } setClip_Paint(&p, rect); const int iconPad = iconPadding_LabelWidget_(d); -// const int iconColor = isCaution ? uiTextCaution_ColorId -// : flags & (disabled_WidgetFlag | pressed_WidgetFlag) ? fg -// : isHover ? uiIconHover_ColorId -// : uiIcon_ColorId; if (d->icon && d->icon != 0x20) { /* no need to draw an empty icon */ iString str; initUnicodeN_String(&str, &d->icon, 1); @@ -427,8 +424,11 @@ static void draw_LabelWidget_(const iLabelWidget *d) { else { drawCenteredOutline_Text( d->font, - adjusted_Rect(bounds, init_I2(iconPad * (flags & tight_WidgetFlag ? 1.0f : 1.5f), 0), - init_I2(-iconPad * (flags & tight_WidgetFlag ? 0.5f : 1.0f), 0)), + moved_Rect( + adjusted_Rect(bounds, + init_I2(iconPad * (flags & tight_WidgetFlag ? 1.0f : 1.5f), 0), + init_I2(-iconPad * (flags & tight_WidgetFlag ? 0.5f : 1.0f), 0)), + d->labelOffset), d->flags.alignVisual, d->flags.drawAsOutline ? fg : none_ColorId, d->flags.drawAsOutline ? d->widget.bgColor : fg, @@ -523,6 +523,7 @@ void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { d->font = uiLabel_FontId; d->forceFg = none_ColorId; d->icon = 0; + d->labelOffset = zero_I2(); initCStr_String(&d->srcLabel, label); initCopy_String(&d->label, &d->srcLabel); replaceVariables_LabelWidget_(d); @@ -623,6 +624,10 @@ void setRemoveTrailingColon_LabelWidget(iLabelWidget *d, iBool removeTrailingCol } } +void setTextOffset_LabelWidget(iLabelWidget *d, iInt2 offset) { + d->labelOffset = offset; +} + void updateText_LabelWidget(iLabelWidget *d, const iString *text) { set_String(&d->label, text); set_String(&d->srcLabel, text); diff --git a/src/ui/labelwidget.h b/src/ui/labelwidget.h index 6f1b7902..4f605d6b 100644 --- a/src/ui/labelwidget.h +++ b/src/ui/labelwidget.h @@ -38,6 +38,7 @@ void setWrap_LabelWidget (iLabelWidget *, iBool wrap); void setOutline_LabelWidget (iLabelWidget *, iBool drawAsOutline); void setAllCaps_LabelWidget (iLabelWidget *, iBool allCaps); void setRemoveTrailingColon_LabelWidget (iLabelWidget *, iBool removeTrailingColon); +void setTextOffset_LabelWidget (iLabelWidget *, iInt2 offset); void setFont_LabelWidget (iLabelWidget *, int fontId); void setTextColor_LabelWidget (iLabelWidget *, int color); void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 5382cbce..ab282a86 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c @@ -180,13 +180,16 @@ size_t currentPanelIndex_Mobile(const iWidget *panels) { return iInvalidPos; } +iWidget *panel_Mobile(const iWidget *panels, size_t index) { + return child_Widget(findChild_Widget(panels, "detailstack"), index); +} + static iBool topPanelHandler_(iWidget *topPanel, const char *cmd) { const iBool isPortrait = !isSideBySideLayout_(); if (equal_Command(cmd, "panel.open")) { - iWidget *button = pointer_Command(cmd); + /* This command is sent by the button that opens the panel. */ + iWidget *button = pointer_Command(cmd); iWidget *panel = userData_Object(button); -// openMenu_Widget(panel, innerToWindow_Widget(panel, zero_I2())); -// setFlags_Widget(panel, hidden_WidgetFlag, iFalse); unselectAllPanelButtons_(topPanel); int panelIndex = -1; size_t childIndex = 0; @@ -208,8 +211,6 @@ static iBool topPanelHandler_(iWidget *topPanel, const char *cmd) { setText_LabelWidget(detailTitle, text_LabelWidget((iLabelWidget *) findTitleLabel_(panel))); setFlags_Widget(button, selected_WidgetFlag, iTrue); postCommand_Widget(topPanel, "panel.changed arg:%d", panelIndex); - //printTree_Widget(findDetailStack_(topPanel)); -// updateVisible_ListWidget(findChild_Widget(findDetailStack_(topPanel), "certlist")); updateCertListHeight_(findDetailStack_(topPanel)); return iTrue; } diff --git a/src/ui/mobile.h b/src/ui/mobile.h index 9d7ac8e4..06955945 100644 --- a/src/ui/mobile.h +++ b/src/ui/mobile.h @@ -39,6 +39,7 @@ void initPanels_Mobile (iWidget *panels, iWidget *parentWidget, const iMenuItem *itemsNullTerminated, const iMenuItem *actions, size_t numActions); +iWidget * panel_Mobile (const iWidget *panels, size_t index); size_t currentPanelIndex_Mobile (const iWidget *panels); enum iTransitionFlags { diff --git a/src/ui/root.c b/src/ui/root.c index b7a2e5c8..5df4b36f 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -333,19 +333,28 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { } else if (equal_Command(cmd, "identmenu.open")) { iWidget *toolBar = findWidget_Root("toolbar"); - iWidget *button = findWidget_Root(toolBar ? "toolbar.ident" : "navbar.ident"); + iWidget *button = findWidget_Root(toolBar && isPortraitPhone_App() ? "toolbar.ident" : "navbar.ident"); iArray items; init_Array(&items, sizeof(iMenuItem)); /* Current identity. */ const iString *docUrl = url_DocumentWidget(document_App()); const iGmIdentity *ident = identityForUrl_GmCerts(certs_App(), docUrl); const iString *fp = ident ? collect_String(hexEncode_Block(&ident->fingerprint)) : NULL; - pushBackN_Array(&items, - (iMenuItem[]){ { format_CStr("///" uiHeading_ColorEscape "%s", - ident ? cstr_String(name_GmIdentity(ident)) - : "${menu.identity.notactive}") }, - { "---" } }, - 2); + iString *str = NULL; + if (ident) { + str = copy_String(name_GmIdentity(ident)); + if (!isEmpty_String(&ident->notes)) { + appendFormat_String(str, "\n%s%s", escape_Color(uiAnnotation_ColorId), + cstr_String(&ident->notes)); + } + } + pushBackN_Array( + &items, + (iMenuItem[]){ { format_CStr("///" uiHeading_ColorEscape "%s", + str ? cstr_String(str) : "${menu.identity.notactive}") }, + { "---" } }, + 2); + delete_String(str); /* Alternate identities. */ if (ident) { const iString *site = collectNewRange_String(urlRoot_String(docUrl)); @@ -385,8 +394,8 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { : leftHalf_Icon " ${menu.show.identities}", 0, 0, - deviceType_App() == phone_AppDeviceType ? "toolbar.showident" - : "sidebar.mode arg:3 toggle:1" }); + //deviceType_App() == phone_AppDeviceType ? "toolbar.showident" + "sidebar.mode arg:3 toggle:1" }); } else { pushBack_Array(&items, &(iMenuItem){ gear_Icon " ${menu.identities}", 0, 0, @@ -517,9 +526,21 @@ static void updateNavBarIdentity_(iWidget *navBar) { iLabelWidget *toolName = findWidget_App("toolbar.name"); if (toolName) { setOutline_LabelWidget(toolButton, ident == NULL); - updateTextCStr_LabelWidget(toolName, subjectName ? cstr_String(subjectName) : ""); + /* Fit the name in the widget. */ + if (subjectName) { + const char *endPos; + tryAdvanceNoWrap_Text(uiLabelTiny_FontId, range_String(subjectName), width_Widget(toolName), + &endPos); + updateText_LabelWidget( + toolName, + collectNewRange_String((iRangecc){ constBegin_String(subjectName), endPos })); + } + else { + updateTextCStr_LabelWidget(toolName, ""); + } setFont_LabelWidget(toolButton, subjectName ? uiLabelMedium_FontId : uiLabelLarge_FontId); - arrange_Widget(parent_Widget(toolButton)); + setTextOffset_LabelWidget(toolButton, init_I2(0, subjectName ? -1.5f * gap_UI : 0)); + arrange_Widget(parent_Widget(toolButton)); } } @@ -604,11 +625,13 @@ void updateToolbarColors_Root(iRoot *d) { tmBannerBackground_ColorId; setBackgroundColor_Widget(toolBar, bg); iForEach(ObjectList, i, children_Widget(toolBar)) { - iLabelWidget *btn = i.object; +// iLabelWidget *btn = i.object; setTextColor_LabelWidget(i.object, isSidebarVisible ? uiTextDim_ColorId : tmBannerIcon_ColorId); setBackgroundColor_Widget(i.object, bg); /* using noBackground, but ident has outline */ } + setTextColor_LabelWidget(findChild_Widget(toolBar, "toolbar.name"), + isSidebarVisible ? uiTextDim_ColorId : tmBannerIcon_ColorId); } #else iUnused(d); @@ -1014,8 +1037,13 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { return iTrue; } else if (equal_Command(cmd, "toolbar.showident")) { - /* TODO: Clean this up. */ iWidget *sidebar = findWidget_App("sidebar"); + if (isVisible_Widget(sidebar)) { + postCommandf_App("sidebar.toggle"); + } + postCommand_App("preferences idents:1"); +#if 0 + /* TODO: Clean this up. */ iWidget *sidebar2 = findWidget_App("sidebar2"); //dismissSidebar_(sidebar, "toolbar.view"); if (isVisible_Widget(sidebar)) { @@ -1036,6 +1064,7 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { setVisualOffset_Widget(sidebar2, offset, 0, 0); setVisualOffset_Widget(sidebar2, 0, 400, easeOut_AnimFlag | softer_AnimFlag); } +#endif return iTrue; } else if (equal_Command(cmd, "sidebar.mode.changed")) { @@ -1099,15 +1128,16 @@ void updateMetrics_Root(iRoot *d) { const iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); const iWidget *viewButton = findChild_Widget(d->widget, "toolbar.view"); const iWidget *idButton = findChild_Widget(toolBar, "toolbar.ident"); - const int font = uiLabelTiny_FontId; - setFont_LabelWidget(idName, font); - setPos_Widget(as_Widget(idName), +// const int font = uiLabelTiny_FontId; + setFixedSize_Widget(as_Widget(idName), init_I2(-1, 2 * gap_UI + lineHeight_Text(uiLabelTiny_FontId))); +// setFont_LabelWidget(idName, font); + /*setPos_Widget(as_Widget(idName), windowToLocal_Widget(as_Widget(idName), init_I2(left_Rect(bounds_Widget(idButton)), bottom_Rect(bounds_Widget(viewButton)) - lineHeight_Text(font) - gap_UI / 2))); setFixedSize_Widget(as_Widget(idName), init_I2(width_Widget(idButton), - lineHeight_Text(font))); + lineHeight_Text(font)));*/ } } postRefresh_App(); @@ -1413,15 +1443,17 @@ void createUserInterface_Root(iRoot *d) { iWidget *content = findChild_Widget(root, "tabs.content"); iSidebarWidget *sidebar1 = new_SidebarWidget(left_SidebarSide); addChildPos_Widget(content, iClob(sidebar1), front_WidgetAddPos); - iSidebarWidget *sidebar2 = new_SidebarWidget(right_SidebarSide); if (deviceType_App() != phone_AppDeviceType) { + iSidebarWidget *sidebar2 = new_SidebarWidget(right_SidebarSide); addChildPos_Widget(content, iClob(sidebar2), back_WidgetAddPos); } +#if 0 else { /* The identities sidebar is always in the main area. */ addChild_Widget(findChild_Widget(root, "stack"), iClob(sidebar2)); setFlags_Widget(as_Widget(sidebar2), hidden_WidgetFlag, iTrue); } +#endif } /* Lookup results. */ { iLookupWidget *lookup = new_LookupWidget(); @@ -1481,23 +1513,29 @@ void createUserInterface_Root(iRoot *d) { iClob(newLargeIcon_LabelWidget(forwardArrow_Icon, "navigate.forward")), frameless_WidgetFlag), "toolbar.forward"); - setId_Widget(addChildFlags_Widget(toolBar, - iClob(newLargeIcon_LabelWidget("\U0001f464", "identmenu.open")), - frameless_WidgetFlag), + iWidget *identButton; + setId_Widget(identButton = addChildFlags_Widget( + toolBar, + iClob(newLargeIcon_LabelWidget("\U0001f464", "identmenu.open")), + frameless_WidgetFlag | fixedHeight_WidgetFlag), "toolbar.ident"); setId_Widget(addChildFlags_Widget(toolBar, iClob(newLargeIcon_LabelWidget(book_Icon, "toolbar.showview arg:-1")), frameless_WidgetFlag | commandOnClick_WidgetFlag), "toolbar.view"); - setId_Widget(addChildFlags_Widget(toolBar, - iClob(new_LabelWidget("", "toolbar.showident")), + iLabelWidget *idName; + setId_Widget(addChildFlags_Widget(identButton, + iClob(idName = new_LabelWidget("", NULL)), frameless_WidgetFlag | noBackground_WidgetFlag | - fixedPosition_WidgetFlag | + moveToParentBottomEdge_WidgetFlag | + resizeToParentWidth_WidgetFlag + /*fixedPosition_WidgetFlag | fixedSize_WidgetFlag | ignoreForParentWidth_WidgetFlag | - ignoreForParentHeight_WidgetFlag), + ignoreForParentHeight_WidgetFlag*/), "toolbar.name"); + setFont_LabelWidget(idName, uiLabelTiny_FontId); iLabelWidget *menuButton = makeMenuButton_LabelWidget(menu_Icon, phoneNavMenuItems_, iElemCount(phoneNavMenuItems_)); setFont_LabelWidget(menuButton, uiLabelLarge_FontId); diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 674e2b7c..9b94f4d9 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -608,8 +608,10 @@ iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { } void setClosedFolders_SidebarWidget(iSidebarWidget *d, const iIntSet *closedFolders) { - delete_IntSet(d->closedFolders); - d->closedFolders = copy_IntSet(closedFolders); + if (d) { + delete_IntSet(d->closedFolders); + d->closedFolders = copy_IntSet(closedFolders); + } } enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) { @@ -625,7 +627,7 @@ float width_SidebarWidget(const iSidebarWidget *d) { } const iIntSet *closedFolders_SidebarWidget(const iSidebarWidget *d) { - return d->closedFolders; + return d ? d->closedFolders : collect_IntSet(new_IntSet()); } static const char *normalModeLabels_[max_SidebarMode] = { @@ -710,7 +712,8 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { setId_Widget(buttons, "buttons"); setDrawBufferEnabled_Widget(buttons, iTrue); for (int i = 0; i < max_SidebarMode; i++) { - if (deviceType_App() == phone_AppDeviceType && i == identities_SidebarMode) { + if (i == identities_SidebarMode && deviceType_App() != desktop_AppDeviceType) { + /* On mobile, identities are managed via Settings. */ continue; } d->modeButtons[i] = addChildFlags_Widget( @@ -911,6 +914,7 @@ static void checkModeButtonLayout_SidebarWidget_(iSidebarWidget *d) { } void setWidth_SidebarWidget(iSidebarWidget *d, float widthAsGaps) { + if (!d) return; iWidget *w = as_Widget(d); const iBool isFixedWidth = deviceType_App() == phone_AppDeviceType; int width = widthAsGaps * gap_UI; /* in pixels */ @@ -1148,10 +1152,10 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) } } } - else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) { - postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode); - return iTrue; - } +// else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) { +// postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode); +// return iTrue; +// } else if (isPortraitPhone_App() && isVisible_Widget(w) && d->side == left_SidebarSide && equal_Command(cmd, "swipe.forward")) { postCommand_App("sidebar.toggle"); diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index c22bfe86..89376633 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c @@ -123,9 +123,14 @@ static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) { pushBack_Array(items, &(iMenuItem){ "---" }); iConstForEach(PtrArray, i, listIdentities_GmCerts(certs_App(), NULL, NULL)) { const iGmIdentity *id = i.ptr; + iString *str = collect_String(copy_String(name_GmIdentity(id))); + if (!isEmpty_String(&id->notes)) { + appendFormat_String( + str, "\n%s%s", escape_Color(uiAnnotation_ColorId), cstr_String(&id->notes)); + } pushBack_Array( items, - &(iMenuItem){ cstr_String(name_GmIdentity(id)), 0, 0, + &(iMenuItem){ cstr_String(str), 0, 0, format_CStr("upload.setid fp:%s", cstrCollect_String(hexEncode_Block(&id->fingerprint))) }); } diff --git a/src/ui/util.c b/src/ui/util.c index 61d3e9bb..de838769 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -1215,6 +1215,15 @@ iLabelWidget *findMenuItem_Widget(iWidget *menu, const char *command) { return NULL; } +iWidget *findUserData_Widget(iWidget *d, void *userData) { + iForEach(ObjectList, i, children_Widget(d)) { + if (userData_Object(i.object) == userData) { + return i.object; + } + } + return NULL; +} + void setMenuItemDisabled_Widget(iWidget *menu, const char *command, iBool disable) { if (flags_Widget(menu) & nativeMenu_WidgetFlag) { setDisabled_NativeMenuItem(findNativeMenuItem_Widget(menu, command), disable); diff --git a/src/ui/util.h b/src/ui/util.h index 81fb1cbd..7ee94f1d 100644 --- a/src/ui/util.h +++ b/src/ui/util.h @@ -249,7 +249,8 @@ void setMenuItemDisabled_Widget (iWidget *menu, const char *comm void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable); void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel); void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel); -void setNativeMenuItems_Widget (iWidget *, const iMenuItem *items, size_t n); +void setNativeMenuItems_Widget (iWidget *menu, const iMenuItem *items, size_t n); +iWidget * findUserData_Widget (iWidget *, void *userData); int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ diff --git a/src/ui/widget.c b/src/ui/widget.c index 254c2590..210fe899 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -271,10 +271,12 @@ void setMinSize_Widget(iWidget *d, iInt2 minSize) { } void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) { - d->padding[0] = left; - d->padding[1] = top; - d->padding[2] = right; - d->padding[3] = bottom; + if (d) { + d->padding[0] = left; + d->padding[1] = top; + d->padding[2] = right; + d->padding[3] = bottom; + } } iWidget *root_Widget(const iWidget *d) { -- cgit v1.2.3 From c17fe5ed17c906b0c0bc21e07d87d281d04e10e6 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 9 Dec 2021 11:35:03 +0200 Subject: UploadWidget: Improved Identity dropdown Better colors, keep the menu button fixed-height. --- src/ui/labelwidget.c | 17 +++++++---------- src/ui/uploadwidget.c | 25 +++++++++++++++---------- src/ui/util.c | 14 +++++++++++--- 3 files changed, 33 insertions(+), 23 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index d00733e1..9e0d37e4 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -195,6 +195,7 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int int *icon, int *meta) { const iWidget *w = constAs_Widget(d); const int64_t flags = flags_Widget(w); + const iBool isHover = isHover_LabelWidget_(d); const iBool isFocus = (flags & focusable_WidgetFlag && isFocused_Widget(d)); const iBool isPress = (flags & pressed_WidgetFlag) != 0; const iBool isSel = (flags & selected_WidgetFlag) != 0; @@ -222,9 +223,6 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int if (isSel) { if (!d->flags.checkMark) { *bg = uiBackgroundSelected_ColorId; -// if (!isKeyRoot) { -// *bg = uiEmbossSelected1_ColorId; //uiBackgroundUnfocusedSelection_ColorId; -// } if (!isKeyRoot) { *bg = isDark_ColorTheme(colorTheme_App()) ? uiBackgroundUnfocusedSelection_ColorId : uiMarked_ColorId; @@ -249,7 +247,7 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int if (colorEscape == uiTextCaution_ColorId) { *icon = *meta = colorEscape; } - if (isHover_LabelWidget_(d)) { + if (isHover) { if (isFrameless) { *bg = uiBackgroundFramelessHover_ColorId; *fg = uiTextFramelessHover_ColorId; @@ -275,7 +273,7 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int } } if (d->forceFg >= 0) { - *fg = /* *icon = */ *meta = d->forceFg; + *fg = *meta = d->forceFg; } if (isPress) { if (colorEscape == uiTextAction_ColorId || colorEscape == uiTextCaution_ColorId) { @@ -290,14 +288,13 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int *frame1 = uiEmbossPressed1_ColorId; *frame2 = colorEscape != none_ColorId ? colorEscape : uiEmbossPressed2_ColorId; } - //if (colorEscape == none_ColorId || colorEscape == uiTextAction_ColorId) { *fg = *icon = *meta = uiTextPressed_ColorId | permanent_ColorId; - // } - // else { - // *fg = (isDark_ColorTheme(colorTheme_App()) ? white_ColorId : black_ColorId) | permanent_ColorId; - // } } } + if (((isSel || isHover) && isFrameless) || isPress) { + /* Ensure that the full label text remains readable. */ + *fg |= permanent_ColorId; + } } iLocalDef int iconPadding_LabelWidget_(const iLabelWidget *d) { diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index ef407b6d..e0bc3755 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c @@ -58,6 +58,7 @@ struct Impl_UploadWidget { iLabelWidget * info; iInputWidget * mime; iInputWidget * token; + iLabelWidget * ident; iInputWidget * input; iLabelWidget * filePathLabel; iLabelWidget * fileSizeLabel; @@ -124,9 +125,10 @@ static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) { iConstForEach(PtrArray, i, listIdentities_GmCerts(certs_App(), NULL, NULL)) { const iGmIdentity *id = i.ptr; iString *str = collect_String(copy_String(name_GmIdentity(id))); + prependCStr_String(str, uiTextStrong_ColorEscape); if (!isEmpty_String(&id->notes)) { appendFormat_String( - str, "\n%s%s", escape_Color(uiAnnotation_ColorId), cstr_String(&id->notes)); + str, "\n%s%s", escape_Color(uiTextDim_ColorId), cstr_String(&id->notes)); } pushBack_Array( items, @@ -259,19 +261,20 @@ void init_UploadWidget(iUploadWidget *d) { /* Identity and Token. */ { addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); iWidget *page = makeTwoColumns_Widget(&headings, &values); - /* Token. */ - d->token = addTwoColumnDialogInputField_Widget( - headings, values, "${upload.token}", "upload.token", iClob(new_InputWidget(0))); - setHint_InputWidget(d->token, "${hint.upload.token}"); - setFixedSize_Widget(as_Widget(d->token), init_I2(50 * gap_UI, -1)); /* Identity. */ const iArray * identItems = makeIdentityItems_UploadWidget_(d); const iMenuItem *items = constData_Array(identItems); const size_t numItems = size_Array(identItems); - iLabelWidget * ident = makeMenuButton_LabelWidget("${upload.id}", items, numItems); - setTextCStr_LabelWidget(ident, items[findWidestLabel_MenuItem(items, numItems)].label); + d->ident = makeMenuButton_LabelWidget("${upload.id}", items, numItems); + setTextCStr_LabelWidget(d->ident, items[findWidestLabel_MenuItem(items, numItems)].label); + //setFixedSize_Widget(as_Widget(d->ident), init_I2(50 * gap_UI, )); addChild_Widget(headings, iClob(makeHeading_Widget("${upload.id}"))); - setId_Widget(addChildFlags_Widget(values, iClob(ident), alignLeft_WidgetFlag), "upload.id"); + setId_Widget(addChildFlags_Widget(values, iClob(d->ident), alignLeft_WidgetFlag), "upload.id"); + /* Token. */ + d->token = addTwoColumnDialogInputField_Widget( + headings, values, "${upload.token}", "upload.token", iClob(new_InputWidget(0))); + setHint_InputWidget(d->token, "${hint.upload.token}"); + setFixedSize_Widget(as_Widget(d->token), init_I2(50 * gap_UI, -1)); addChild_Widget(w, iClob(page)); } /* Buttons. */ { @@ -287,6 +290,8 @@ void init_UploadWidget(iUploadWidget *d) { resizeToLargestPage_Widget(tabs); arrange_Widget(w); setFixedSize_Widget(as_Widget(d->token), init_I2(width_Widget(tabs) - left_Rect(parent_Widget(d->token)->rect), -1)); + setFixedSize_Widget(as_Widget(d->ident), init_I2(width_Widget(d->token), + lineHeight_Text(uiLabel_FontId) + 2 * gap_UI)); setFlags_Widget(as_Widget(d->token), expand_WidgetFlag, iTrue); setFocus_Widget(as_Widget(d->input)); } @@ -560,7 +565,7 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { destroy_Widget(w); return iTrue; } - else if (isCommand_Widget(w, ev, "input.resized")) { + else if (!isUsingPanelLayout_Mobile() && isCommand_Widget(w, ev, "input.resized")) { resizeToLargestPage_Widget(findChild_Widget(w, "upload.tabs")); arrange_Widget(w); refresh_Widget(w); diff --git a/src/ui/util.c b/src/ui/util.c index 21067bf4..73fafe84 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -1327,6 +1327,12 @@ const iString *removeMenuItemLabelPrefixes_String(const iString *d) { return collect_String(str); } +static const iString *replaceNewlinesWithDash_(const iString *str) { + iString *mod = copy_String(str); + replace_String(mod, "\n", " "); + return collect_String(mod); +} + void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *selectedCommand) { if (!dropButton) { return; @@ -1337,8 +1343,9 @@ void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *s iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand); if (item) { setSelected_NativeMenuItem(item, iTrue); - updateText_LabelWidget( - dropButton, removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label))); + updateText_LabelWidget(dropButton, + replaceNewlinesWithDash_(removeMenuItemLabelPrefixes_String( + collectNewCStr_String(item->label)))); checkIcon_LabelWidget(dropButton); } return; @@ -1349,7 +1356,8 @@ void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *s const iBool isSelected = endsWith_String(command_LabelWidget(item), selectedCommand); setFlags_Widget(as_Widget(item), selected_WidgetFlag, isSelected); if (isSelected) { - updateText_LabelWidget(dropButton, sourceText_LabelWidget(item)); + updateText_LabelWidget(dropButton, + replaceNewlinesWithDash_(text_LabelWidget(item))); checkIcon_LabelWidget(dropButton); } } -- cgit v1.2.3 From a265ab290cc9bce2f0c305a3eaf9d743380b967b Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 9 Dec 2021 15:06:02 +0200 Subject: iOS: Fixes and new edit menu for UploadWidget The sizing and behavior of the input field on the plain text upload page is much improved. --- po/en.po | 9 +++++ src/ios.h | 7 ++-- src/ios.m | 37 +++++++++++++++++++-- src/ui/inputwidget.c | 25 +++++++++----- src/ui/labelwidget.c | 4 +++ src/ui/uploadwidget.c | 92 +++++++++++++++++++++++++++++++++++++++------------ src/ui/util.c | 1 + 7 files changed, 139 insertions(+), 36 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/po/en.po b/po/en.po index 8e690649..89a05939 100644 --- a/po/en.po +++ b/po/en.po @@ -1017,6 +1017,15 @@ msgstr "Default" msgid "heading.upload.text" msgstr "Text" +msgid "menu.upload.export" +msgstr "Export Text" + +msgid "menu.upload.delete" +msgstr "Delete All" + +msgid "menu.upload.delete.confirm" +msgstr "Really Delete All (No Undo)" + msgid "hint.upload.text" msgstr "enter text to upload" diff --git a/src/ios.h b/src/ios.h index 6c5ec8d5..fbe7c2eb 100644 --- a/src/ios.h +++ b/src/ios.h @@ -38,6 +38,7 @@ void playHapticEffect_iOS (enum iHapticEffect effect); void exportDownloadedFile_iOS(const iString *path); void pickFileForOpening_iOS (void); void pickFile_iOS (const char *command); /* ` path:%s` will be appended */ +void openTextActivityView_iOS(const iString *text); iBool isPhone_iOS (void); void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom); @@ -79,9 +80,11 @@ iDeclareType(SystemTextInput) iDeclareTypeConstructionArgs(SystemTextInput, iRect rect, int flags) void setRect_SystemTextInput (iSystemTextInput *, iRect rect); -void setText_SystemTextInput (iSystemTextInput *, const iString *text); +void setText_SystemTextInput (iSystemTextInput *, const iString *text, iBool allowUndo); void setFont_SystemTextInput (iSystemTextInput *, int fontId); -void setTextChangedFunc_SystemTextInput (iSystemTextInput *, void (*textChangedFunc)(iSystemTextInput *, void *), void *); +void setTextChangedFunc_SystemTextInput + (iSystemTextInput *, void (*textChangedFunc)(iSystemTextInput *, void *), void *); +void selectAll_SystemTextInput(iSystemTextInput *); const iString * text_SystemTextInput (const iSystemTextInput *); int preferredHeight_SystemTextInput (const iSystemTextInput *); diff --git a/src/ios.m b/src/ios.m index 2705a350..b6fbdec0 100644 --- a/src/ios.m +++ b/src/ios.m @@ -536,6 +536,15 @@ void pickFile_iOS(const char *command) { [viewController_(get_Window()) presentViewController:picker animated:YES completion:nil]; } +void openTextActivityView_iOS(const iString *text) { + UIActivityViewController *actView = + [[UIActivityViewController alloc] + initWithActivityItems:@[ + [NSString stringWithUTF8String:cstr_String(text)]] + applicationActivities:nil]; + [viewController_(get_Window()) presentViewController:actView animated:YES completion:nil]; +} + /*----------------------------------------------------------------------------------------------*/ enum iAVFAudioPlayerState { @@ -784,7 +793,16 @@ void deinit_SystemTextInput(iSystemTextInput *d) { } } -void setText_SystemTextInput(iSystemTextInput *d, const iString *text) { +void selectAll_SystemTextInput(iSystemTextInput *d) { + if (d->field) { + [REF_d_field selectAll:nil]; + } + if (d->view) { + [REF_d_view selectAll:nil]; + } +} + +void setText_SystemTextInput(iSystemTextInput *d, const iString *text, iBool allowUndo) { NSString *str = [NSString stringWithUTF8String:cstr_String(text)]; if (d->field) { [REF_d_field setText:str]; @@ -793,9 +811,22 @@ void setText_SystemTextInput(iSystemTextInput *d, const iString *text) { } } else { - [REF_d_view setText:str]; + UITextView *view = REF_d_view; +// if (allowUndo) { +// [view selectAll:nil]; +// if ([view shouldChangeTextInRange:[view selectedTextRange] replacementText:@""]) { +// [[view textStorage] beginEditing]; +// [[view textStorage] replaceCharactersInRange:[view selectedRange] withString:@""]; +// [[view textStorage] endEditing]; +// } +// } +// else { + // TODO: How to implement `allowUndo`, given that UITextView does not exist when unfocused? + // Maybe keep the UITextStorage (if it has the undo?)? + [view setText:str]; +// } if (d->flags & selectAll_SystemTextInputFlags) { - [REF_d_view selectAll:nil]; + [view selectAll:nil]; } } } diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 3be6a383..22f983eb 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c @@ -715,7 +715,8 @@ static void updateAllLinesAndResizeHeight_InputWidget_(iInputWidget *d) { const int height = measure_WrapText(&wt, d->font).bounds.size.y; /* We use this to store the number wrapped lines for determining widget height. */ d->visWrapLines.start = 0; - d->visWrapLines.end = iMin(d->maxWrapLines, height / lineHeight_Text(d->font)); + d->visWrapLines.end = iMax(d->minWrapLines, + iMin(d->maxWrapLines, height / lineHeight_Text(d->font))); updateMetrics_InputWidget_(d); } @@ -733,8 +734,10 @@ static int contentHeight_InputWidget_(const iInputWidget *d) { if (d->buffered && ~d->inFlags & needUpdateBuffer_InputWidgetFlag) { return iClamp(d->buffered->size.y, minHeight, maxHeight); } -#endif + return minHeight; +#else return (int) size_Range(&d->visWrapLines) * lineHeight; +#endif } static void updateTextInputRect_InputWidget_(const iInputWidget *d) { @@ -1111,7 +1114,7 @@ void setText_InputWidget(iInputWidget *d, const iString *text) { #else set_String(&d->text, nfcText); if (d->sysCtrl) { - setText_SystemTextInput(d->sysCtrl, nfcText); + setText_SystemTextInput(d->sysCtrl, nfcText, iTrue); } else { updateAllLinesAndResizeHeight_InputWidget_(d); /* need to know the new height */ @@ -1134,7 +1137,11 @@ void setTextCStr_InputWidget(iInputWidget *d, const char *cstr) { } void selectAll_InputWidget(iInputWidget *d) { -#if !LAGRANGE_USE_SYSTEM_TEXT_INPUT +#if LAGRANGE_USE_SYSTEM_TEXT_INPUT + if (d->sysCtrl) { + selectAll_SystemTextInput(d->sysCtrl); + } +#else d->mark = (iRanges){ 0, lastLine_InputWidget_(d)->range.end }; refresh_Widget(as_Widget(d)); #endif @@ -1177,7 +1184,7 @@ void begin_InputWidget(iInputWidget *d) { (isAllowedToInsertNewline_InputWidget_(d) ? insertNewlines_SystemTextInputFlag : 0) | (d->inFlags & selectAllOnFocus_InputWidgetFlag ? selectAll_SystemTextInputFlags : 0)); setFont_SystemTextInput(d->sysCtrl, d->font); - setText_SystemTextInput(d->sysCtrl, &d->oldText); + setText_SystemTextInput(d->sysCtrl, &d->oldText, iFalse); setTextChangedFunc_SystemTextInput(d->sysCtrl, systemInputChanged_InputWidget_, d); iConnect(Root, w->root, visualOffsetsChanged, d, updateAfterVisualOffsetChange_InputWidget_); updateTextInputRect_InputWidget_(d); @@ -2157,10 +2164,6 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { } return iTrue; } - else if (isCommand_UserEvent(ev, "input.selectall") && isEditing_InputWidget_(d)) { - selectAll_InputWidget(d); - return iTrue; - } else if (isCommand_UserEvent(ev, "text.insert")) { pushUndo_InputWidget_(d); deleteMarked_InputWidget_(d); @@ -2169,6 +2172,10 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { return iTrue; } #endif + else if (isCommand_UserEvent(ev, "input.selectall") && isEditing_InputWidget_(d)) { + selectAll_InputWidget(d); + return iTrue; + } else if (isCommand_UserEvent(ev, "theme.changed")) { if (d->buffered) { d->inFlags |= needUpdateBuffer_InputWidgetFlag; diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 9e0d37e4..5ad43b0e 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -134,6 +134,10 @@ static iBool processEvent_LabelWidget_(iLabelWidget *d, const SDL_Event *ev) { refresh_Widget(d); return iFalse; } + else if (isCommand_Widget(w, ev, "trigger")) { + trigger_LabelWidget_(d); + return iTrue; + } if (!isEmpty_String(&d->command)) { #if 0 && defined (iPlatformAppleMobile) /* Touch allows activating any button on release. */ diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index e11970ec..58106dcb 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c @@ -92,17 +92,19 @@ static void updateProgress_UploadWidget_(iGmRequest *request, size_t current, si static void updateInputMaxHeight_UploadWidget_(iUploadWidget *d) { iWidget *w = as_Widget(d); /* Calculate how many lines fits vertically in the view. */ - const iInt2 inputPos = topLeft_Rect(bounds_Widget(as_Widget(d->input))); - const int footerHeight = isUsingPanelLayout_Mobile() ? 0 : - (height_Widget(d->token) + - height_Widget(findChild_Widget(w, "dialogbuttons")) + - 12 * gap_UI); - const int avail = bottom_Rect(safeRect_Root(w->root)) - footerHeight - - get_MainWindow()->keyboardHeight; - setLineLimits_InputWidget(d->input, - minLines_InputWidget(d->input), - iMaxi(minLines_InputWidget(d->input), - (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input)))); + const iInt2 inputPos = topLeft_Rect(bounds_Widget(as_Widget(d->input))); + int footerHeight = 0; + if (!isUsingPanelLayout_Mobile()) { + footerHeight = (height_Widget(d->token) + + height_Widget(findChild_Widget(w, "dialogbuttons")) + + 12 * gap_UI); + } + const int avail = bottom_Rect(visibleRect_Root(w->root)) - footerHeight - inputPos.y; + /* On desktop, retain the previously set minLines value. */ + int minLines = isUsingPanelLayout_Mobile() ? 1 : minLines_InputWidget(d->input); + int maxLines = iMaxi(minLines, avail / lineHeight_Text(font_InputWidget(d->input))); + /* On mobile, the height is fixed to the available space. */ + setLineLimits_InputWidget(d->input, isUsingPanelLayout_Mobile() ? maxLines : minLines, maxLines); } static const iGmIdentity *titanIdentityForUrl_(const iString *url) { @@ -208,11 +210,7 @@ void init_UploadWidget(iUploadWidget *d) { enableUploadButton_UploadWidget_(d, iFalse); } iWidget *title = findChild_Widget(w, "heading.upload.text"); - iLabelWidget *menu = makeMenuButton_LabelWidget(midEllipsis_Icon, (iMenuItem[]){ - { export_Icon " ${upload.text.export}", 0, 0, "upload.text.export" }, - { "---" }, - { delete_Icon " " uiTextCaution_ColorEscape "${menu.delete}", 0, 0, "upload.text.delete" } - }, 3); + iLabelWidget *menu = new_LabelWidget(midEllipsis_Icon, "upload.editmenu.open"); setTextColor_LabelWidget(menu, uiTextAction_ColorId); setFont_LabelWidget(menu, uiLabelBigBold_FontId); addChildFlags_Widget(title, iClob(menu), frameless_WidgetFlag | moveToParentRightEdge_WidgetFlag); @@ -428,12 +426,19 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { } else if (equal_Command(cmd, "panel.changed")) { showOrHideUploadButton_UploadWidget_(d); - setFocus_Widget(NULL); + if (currentPanelIndex_Mobile(w) == 0) { + setFocus_Widget(as_Widget(d->input)); + } + else { + setFocus_Widget(NULL); + } + refresh_Widget(d->input); return iFalse; } #if defined (iPlatformAppleMobile) else if (deviceType_App() != desktop_AppDeviceType && equal_Command(cmd, "menu.opened")) { setFocus_Widget(NULL); /* overlaid text fields! */ + refresh_Widget(d->input); return iFalse; } #endif @@ -474,6 +479,44 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { updateIdentityDropdown_UploadWidget_(d); return iTrue; } + if (isCommand_Widget(w, ev, "upload.editmenu.open")) { + setFocus_Widget(NULL); + refresh_Widget(as_Widget(d->input)); + iWidget *editMenu = makeMenu_Widget(root_Widget(w), (iMenuItem[]){ + { select_Icon " ${menu.selectall}", 0, 0, "upload.text.selectall" }, + { export_Icon " ${menu.upload.export}", 0, 0, "upload.text.export" }, + { "---" }, + { delete_Icon " " uiTextCaution_ColorEscape "${menu.upload.delete}", 0, 0, "upload.text.delete" } + }, 4); + openMenu_Widget(editMenu, topLeft_Rect(bounds_Widget(as_Widget(d->input)))); + return iTrue; + } + if (isCommand_UserEvent(ev, "upload.text.export")) { +#if defined (iPlatformAppleMobile) + openTextActivityView_iOS(text_InputWidget(d->input)); +#endif + return iTrue; + } + if (isCommand_UserEvent(ev, "upload.text.delete")) { + if (argLabel_Command(command_UserEvent(ev), "confirmed")) { + setTextCStr_InputWidget(d->input, ""); + setFocus_Widget(as_Widget(d->input)); + } + else { + iWidget *confirm = makeMenu_Widget(root_Widget(w), (iMenuItem[]){ + { delete_Icon " " uiTextCaution_ColorEscape "${menu.upload.delete.confirm}", 0, 0, + "upload.text.delete confirmed:1" } + }, 1); + openMenu_Widget(confirm, zero_I2()); + } + return iTrue; + } + if (isCommand_UserEvent(ev, "upload.text.selectall")) { + setFocus_Widget(as_Widget(d->input)); + refresh_Widget(as_Widget(d->input)); + postCommand_Widget(d->input, "input.selectall"); + return iTrue; + } if (isCommand_Widget(w, ev, "upload.accept")) { iBool isText; iWidget *tabs = findChild_Widget(w, "upload.tabs"); @@ -569,11 +612,16 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { destroy_Widget(w); return iTrue; } - else if (!isUsingPanelLayout_Mobile() && isCommand_Widget(w, ev, "input.resized")) { - resizeToLargestPage_Widget(findChild_Widget(w, "upload.tabs")); - arrange_Widget(w); - refresh_Widget(w); - return iTrue; + else if (isCommand_Widget(w, ev, "input.resized")) { + if (!isUsingPanelLayout_Mobile()) { + resizeToLargestPage_Widget(findChild_Widget(w, "upload.tabs")); + arrange_Widget(w); + refresh_Widget(w); + return iTrue; + } + else { + refresh_Widget(as_Widget(d->input)); + } } else if (isCommand_Widget(w, ev, "upload.pickfile")) { #if defined (iPlatformAppleMobile) diff --git a/src/ui/util.c b/src/ui/util.c index 73fafe84..daefc279 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -671,6 +671,7 @@ static iBool isCommandIgnoredByMenus_(const char *cmd) { equal_Command(cmd, "window.reload.update") || equal_Command(cmd, "window.mouse.exited") || equal_Command(cmd, "window.mouse.entered") || + equal_Command(cmd, "input.backup") || (equal_Command(cmd, "mouse.clicked") && !arg_Command(cmd)); /* button released */ } -- cgit v1.2.3 From 8bd055049a7878f4509dff5bcd0e152890665976 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sun, 12 Dec 2021 13:52:57 +0200 Subject: Mobile: Crash when dismissing sidebar during Edit mode --- src/ui/labelwidget.c | 21 +++++++++++++-------- src/ui/sidebarwidget.c | 17 +++++++++++------ 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 5ad43b0e..4ace6204 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -492,6 +492,7 @@ int font_LabelWidget(const iLabelWidget *d) { } void updateSize_LabelWidget(iLabelWidget *d) { + if (!d) return; iWidget *w = as_Widget(d); const int64_t flags = flags_Widget(w); const iInt2 size = defaultSize_LabelWidget(d); @@ -562,18 +563,22 @@ void setTextColor_LabelWidget(iLabelWidget *d, int color) { } void setText_LabelWidget(iLabelWidget *d, const iString *text) { - updateText_LabelWidget(d, text); - updateSize_LabelWidget(d); - if (isWrapped_LabelWidget(d)) { - sizeChanged_LabelWidget_(d); + if (d) { + updateText_LabelWidget(d, text); + updateSize_LabelWidget(d); + if (isWrapped_LabelWidget(d)) { + sizeChanged_LabelWidget_(d); + } } } void setTextCStr_LabelWidget(iLabelWidget *d, const char *text) { - updateTextCStr_LabelWidget(d, text); - updateSize_LabelWidget(d); - if (isWrapped_LabelWidget(d)) { - sizeChanged_LabelWidget_(d); + if (d) { + updateTextCStr_LabelWidget(d, text); + updateSize_LabelWidget(d); + if (isWrapped_LabelWidget(d)) { + sizeChanged_LabelWidget_(d); + } } } diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index fa0e16ea..07f1908c 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -251,12 +251,14 @@ static iBool isSlidingSheet_SidebarWidget_(const iSidebarWidget *d) { static void setMobileEditMode_SidebarWidget_(iSidebarWidget *d, iBool editing) { iWidget *w = as_Widget(d); d->isEditing = editing; - setFlags_Widget(findChild_Widget(w, "sidebar.close"), hidden_WidgetFlag, editing); - setFlags_Widget(child_Widget(d->actions, 0), hidden_WidgetFlag, !editing); - setTextCStr_LabelWidget(child_Widget(as_Widget(d->actions), 2), - editing ? "${sidebar.close}" : "${sidebar.action.bookmarks.edit}"); - setDragHandleWidth_ListWidget(d->list, editing ? itemHeight_ListWidget(d->list) * 3 / 2 : 0); - arrange_Widget(d->actions); + if (d->actions) { + setFlags_Widget(findChild_Widget(w, "sidebar.close"), hidden_WidgetFlag, editing); + setFlags_Widget(child_Widget(d->actions, 0), hidden_WidgetFlag, !editing); + setTextCStr_LabelWidget(child_Widget(as_Widget(d->actions), 2), + editing ? "${sidebar.close}" : "${sidebar.action.bookmarks.edit}"); + setDragHandleWidth_ListWidget(d->list, editing ? itemHeight_ListWidget(d->list) * 3 / 2 : 0); + arrange_Widget(d->actions); + } } static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepActions) { @@ -698,6 +700,9 @@ iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { d->mode == documentOutline_SidebarMode ? tmBannerBackground_ColorId : uiBackgroundSidebar_ColorId); updateItemHeight_SidebarWidget_(d); + if (deviceType_App() != desktop_AppDeviceType && mode != bookmarks_SidebarMode) { + setMobileEditMode_SidebarWidget_(d, iFalse); + } /* Restore previous scroll position. */ setScrollPos_ListWidget(list_SidebarWidget_(d), d->modeScroll[mode]); /* Title of the mobile sliding sheet. */ -- cgit v1.2.3 From e6a1ff50654f251d6f7b495e46d78d48a0f2a754 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 25 Dec 2021 06:42:56 +0200 Subject: SDL line drawing regression was fixed in 2.0.18 --- src/ui/labelwidget.c | 2 +- src/ui/paint.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 4ace6204..446cdc8a 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -349,7 +349,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { bottomRight_Rect(frameRect), bottomLeft_Rect(frameRect) }; -#if SDL_VERSION_ATLEAST(2, 0, 16) +#if SDL_COMPILEDVERSION == SDL_VERSIONNUM(2, 0, 16) if (isOpenGLRenderer_Window()) { /* A very curious regression in SDL 2.0.16. */ points[3].x--; diff --git a/src/ui/paint.c b/src/ui/paint.c index 439bdd37..c3b22343 100644 --- a/src/ui/paint.c +++ b/src/ui/paint.c @@ -113,7 +113,7 @@ void drawRect_Paint(const iPaint *d, iRect rect, int color) { { left_Rect(rect), br.y }, { left_Rect(rect), top_Rect(rect) } }; -#if SDL_VERSION_ATLEAST(2, 0, 16) +#if SDL_COMPILEDVERSION == SDL_VERSIONNUM(2, 0, 16) if (isOpenGLRenderer_Window()) { /* A very curious regression in SDL 2.0.16. */ edges[3].y--; -- cgit v1.2.3 From 2007dc961480151721e646aac468a0ae5639b18f Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 25 Dec 2021 14:36:57 +0200 Subject: Mobile: Link info in context menu --- src/ui/documentwidget.c | 4 +- src/ui/labelwidget.c | 4 +- src/ui/linkinfo.c | 141 ++++++++++++++++++++++++------------------------ src/ui/linkinfo.h | 2 + src/ui/util.c | 4 +- 5 files changed, 82 insertions(+), 73 deletions(-) (limited to 'src/ui/labelwidget.c') diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 313fe2ee..81aa382f 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -4851,8 +4851,10 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e iBool isNative = iFalse; if (deviceType_App() != desktop_AppDeviceType) { /* Show the link as the first, non-interactive item. */ + iString *infoText = collectNew_String(); + infoText_LinkInfo(d->view.doc, d->contextLink->linkId, infoText); pushBack_Array(&items, &(iMenuItem){ - format_CStr("```%s", cstr_String(linkUrl)), + format_CStr("```%s", cstr_String(infoText)), 0, 0, NULL }); } if (willUseProxy_App(scheme) || isGemini || diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 446cdc8a..44ae3eec 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -330,6 +330,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { init_Paint(&p); int bg, fg, frame, frame2, iconColor, metaColor; getColors_LabelWidget_(d, &bg, &fg, &frame, &frame2, &iconColor, &metaColor); + setBaseAttributes_Text(d->font, fg); const enum iColorId colorEscape = parseEscape_Color(cstr_String(&d->label), NULL); const iBool isCaution = (colorEscape == uiTextCaution_ColorId); if (bg >= 0) { @@ -452,7 +453,8 @@ static void draw_LabelWidget_(const iLabelWidget *d) { iTrue, iconColor, d->flags.chevron ? rightAngle_Icon : check_Icon); - } + } + setBaseAttributes_Text(-1, -1); unsetClip_Paint(&p); drawChildren_Widget(w); } diff --git a/src/ui/linkinfo.c b/src/ui/linkinfo.c index 89c7fbf3..cb48c7ea 100644 --- a/src/ui/linkinfo.c +++ b/src/ui/linkinfo.c @@ -51,6 +51,73 @@ iInt2 size_LinkInfo(const iLinkInfo *d) { return add_I2(d->buf->size, init_I2(2 * hPad_LinkInfo_, 2 * vPad_LinkInfo_)); } +void infoText_LinkInfo(const iGmDocument *doc, iGmLinkId linkId, iString *text_out) { + const iString *url = linkUrl_GmDocument(doc, linkId); + iUrl parts; + init_Url(&parts, url); + const int flags = linkFlags_GmDocument(doc, linkId); + const enum iGmLinkScheme scheme = scheme_GmLinkFlag(flags); + const iBool isImage = (flags & imageFileExtension_GmLinkFlag) != 0; + const iBool isAudio = (flags & audioFileExtension_GmLinkFlag) != 0; + /* Most important info first: the identity that will be used. */ + const iGmIdentity *ident = identityForUrl_GmCerts(certs_App(), url); + if (ident) { + appendFormat_String(text_out, person_Icon " %s", + //escape_Color(tmBannerItemTitle_ColorId), + cstr_String(name_GmIdentity(ident))); + } + /* Possibly inlined content. */ + if (isImage || isAudio) { + if (!isEmpty_String(text_out)) { + appendCStr_String(text_out, "\n"); + } + appendCStr_String( + text_out, + format_CStr(isImage ? photo_Icon " %s " : "\U0001f3b5 %s", + cstr_Lang(isImage ? "link.hint.image" : "link.hint.audio"))); + } + if (!isEmpty_String(text_out)) { + appendCStr_String(text_out, " \u2014 "); + } + /* Indicate non-Gemini schemes. */ + if (scheme == mailto_GmLinkScheme) { + appendCStr_String(text_out, envelope_Icon " "); + append_String(text_out, url); + } + else if (scheme != gemini_GmLinkScheme && !isEmpty_Range(&parts.host)) { + appendCStr_String(text_out, globe_Icon " \x1b[1m"); + appendRange_String(text_out, (iRangecc){ constBegin_String(url), + parts.host.end }); + appendCStr_String(text_out, "\x1b[0m"); + appendRange_String(text_out, (iRangecc){ parts.path.start, constEnd_String(url) }); + } + else if (scheme != gemini_GmLinkScheme) { + appendCStr_String(text_out, globe_Icon " "); + append_String(text_out, url); + } + else { + appendCStr_String(text_out, "\x1b[1m"); + appendRange_String(text_out, parts.host); + if (!isEmpty_Range(&parts.port)) { + appendCStr_String(text_out, ":"); + appendRange_String(text_out, parts.port); + } + appendCStr_String(text_out, "\x1b[0m"); + appendRange_String(text_out, (iRangecc){ parts.path.start, constEnd_String(url) }); + } + /* Date of last visit. */ + if (flags & visited_GmLinkFlag) { + iDate date; + init_Date(&date, linkTime_GmDocument(doc, linkId)); + if (!isEmpty_String(text_out)) { + appendCStr_String(text_out, " \u2014 "); + } + iString *dateStr = format_Date(&date, "%b %d"); + append_String(text_out, dateStr); + delete_String(dateStr); + } +} + iBool update_LinkInfo(iLinkInfo *d, const iGmDocument *doc, iGmLinkId linkId, int maxWidth) { if (!d) { return iFalse; @@ -61,80 +128,14 @@ iBool update_LinkInfo(iLinkInfo *d, const iGmDocument *doc, iGmLinkId linkId, in d->maxWidth = maxWidth; invalidate_LinkInfo(d); if (linkId) { - /* Measure and draw. */ - if (targetValue_Anim(&d->opacity) < 1) { - setValue_Anim(&d->opacity, 1, isAnimated ? 75 : 0); - } - const int avail = iMax(minWidth_LinkInfo_, maxWidth) - 2 * hPad_LinkInfo_; - const iString *url = linkUrl_GmDocument(doc, linkId); - iUrl parts; - init_Url(&parts, url); - const int flags = linkFlags_GmDocument(doc, linkId); - const enum iGmLinkScheme scheme = scheme_GmLinkFlag(flags); - const iBool isImage = (flags & imageFileExtension_GmLinkFlag) != 0; - const iBool isAudio = (flags & audioFileExtension_GmLinkFlag) != 0; - // int fg = linkColor_GmDocument(doc, linkId, - // textHover_GmLinkPart); iString str; init_String(&str); - /* Most important info first: the identity that will be used. */ - const iGmIdentity *ident = identityForUrl_GmCerts(certs_App(), url); - if (ident) { - appendFormat_String(&str, person_Icon " %s", - //escape_Color(tmBannerItemTitle_ColorId), - cstr_String(name_GmIdentity(ident))); - } - /* Possibly inlined content. */ - if (isImage || isAudio) { - if (!isEmpty_String(&str)) { - appendCStr_String(&str, "\n"); - } - appendCStr_String( - &str, - format_CStr(isImage ? photo_Icon " %s " : "\U0001f3b5 %s", - cstr_Lang(isImage ? "link.hint.image" : "link.hint.audio"))); - } - if (!isEmpty_String(&str)) { - appendCStr_String(&str, " \u2014 "); - } - /* Indicate non-Gemini schemes. */ - if (scheme == mailto_GmLinkScheme) { - appendCStr_String(&str, envelope_Icon " "); - append_String(&str, url); - } - else if (scheme != gemini_GmLinkScheme && !isEmpty_Range(&parts.host)) { - appendCStr_String(&str, globe_Icon " \x1b[1m"); - appendRange_String(&str, (iRangecc){ constBegin_String(url), - parts.host.end }); - appendCStr_String(&str, "\x1b[0m"); - appendRange_String(&str, (iRangecc){ parts.path.start, constEnd_String(url) }); - } - else if (scheme != gemini_GmLinkScheme) { - appendCStr_String(&str, globe_Icon " "); - append_String(&str, url); - } - else { - appendCStr_String(&str, "\x1b[1m"); - appendRange_String(&str, parts.host); - if (!isEmpty_Range(&parts.port)) { - appendCStr_String(&str, ":"); - appendRange_String(&str, parts.port); - } - appendCStr_String(&str, "\x1b[0m"); - appendRange_String(&str, (iRangecc){ parts.path.start, constEnd_String(url) }); - } - /* Date of last visit. */ - if (flags & visited_GmLinkFlag) { - iDate date; - init_Date(&date, linkTime_GmDocument(doc, linkId)); - if (!isEmpty_String(&str)) { - appendCStr_String(&str, " \u2014 "); - } - iString *dateStr = format_Date(&date, "%b %d"); - append_String(&str, dateStr); - delete_String(dateStr); + infoText_LinkInfo(doc, linkId, &str); + if (targetValue_Anim(&d->opacity) < 1) { + setValue_Anim(&d->opacity, 1, isAnimated ? 75 : 0); } /* Draw to a buffer, wrapped. */ + const int avail = iMax(minWidth_LinkInfo_, maxWidth) - 2 * hPad_LinkInfo_; iWrapText wt = { .text = range_String(&str), .maxWidth = avail, .mode = word_WrapTextMode }; d->buf = new_TextBuf(&wt, uiLabel_FontId, tmQuote_ColorId); deinit_String(&str); diff --git a/src/ui/linkinfo.h b/src/ui/linkinfo.h index a1669f95..38b90b87 100644 --- a/src/ui/linkinfo.h +++ b/src/ui/linkinfo.h @@ -41,5 +41,7 @@ iBool update_LinkInfo (iLinkInfo *, const iGmDocument *doc, iGmLinkId link int maxWidth); /* returns true if changed */ void invalidate_LinkInfo (iLinkInfo *); +void infoText_LinkInfo (const iGmDocument *doc, iGmLinkId linkId, iString *text_out); + iInt2 size_LinkInfo (const iLinkInfo *); void draw_LinkInfo (const iLinkInfo *, iInt2 topLeft); diff --git a/src/ui/util.c b/src/ui/util.c index 4ce40ae4..ff127f25 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -774,7 +774,9 @@ void makeMenuItems_Widget(iWidget *menu, const iMenuItem *items, size_t n) { noBackground_WidgetFlag | frameless_WidgetFlag | alignLeft_WidgetFlag | drawKey_WidgetFlag | itemFlags); setWrap_LabelWidget(label, isInfo); - haveIcons |= checkIcon_LabelWidget(label); + if (!isInfo) { + haveIcons |= checkIcon_LabelWidget(label); + } setFlags_Widget(as_Widget(label), disabled_WidgetFlag, isDisabled); if (isInfo) { setFlags_Widget(as_Widget(label), resizeToParentWidth_WidgetFlag | -- cgit v1.2.3