From 5d247c7fafddcb46d83572af788a04f835d48d42 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 1 Jan 2022 10:04:06 +0200 Subject: Mobile: User-configurable phone toolbar buttons Actions for the first two mobile portrait phone toolbar buttons can be chosen in Settings. --- src/app.c | 22 +++++++++++++++ src/defs.h | 17 ++++++++++++ src/prefs.c | 2 ++ src/prefs.h | 1 + src/ui/mobile.c | 16 +++++++++++ src/ui/mobile.h | 11 ++++++++ src/ui/root.c | 83 +++++++++++++++++++++++++-------------------------------- src/ui/util.c | 13 ++++++++- 8 files changed, 118 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/app.c b/src/app.c index 58eecf51..1e66c6cf 100644 --- a/src/app.c +++ b/src/app.c @@ -248,6 +248,10 @@ static iString *serializePrefs_App_(const iApp *d) { appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); appendFormat_String(str, "linespacing.set arg:%f\n", d->prefs.lineSpacing); appendFormat_String(str, "returnkey.set arg:%d\n", d->prefs.returnKey); +#if defined (iPlatformMobile) + appendFormat_String(str, "toolbar.action.set arg:%d button:0\n", d->prefs.toolbarActions[0]); + appendFormat_String(str, "toolbar.action.set arg:%d button:1\n", d->prefs.toolbarActions[1]); +#endif iConstForEach(StringSet, fp, d->prefs.disabledFontPacks) { appendFormat_String(str, "fontpack.disable id:%s\n", cstr_String(fp.value)); } @@ -1870,6 +1874,12 @@ static void updatePrefsPinSplitButtons_(iWidget *d, int value) { } } +static void updatePrefsToolBarActionButton_(iWidget *prefs, int buttonIndex, int action) { + updateDropdownSelection_LabelWidget( + findChild_Widget(prefs, format_CStr("prefs.toolbaraction%d", buttonIndex + 1)), + format_CStr(" arg:%d button:%d", action, buttonIndex)); +} + static void updateScrollSpeedButtons_(iWidget *d, enum iScrollType type, const int value) { const char *typeStr = (type == mouse_ScrollType ? "mouse" : "keyboard"); for (int i = 0; i <= 40; i++) { @@ -1960,6 +1970,10 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { format_CStr("returnkey.set arg:%d", arg_Command(cmd))); return iFalse; } + else if (equal_Command(cmd, "toolbar.action.set")) { + updatePrefsToolBarActionButton_(d, argLabel_Command(cmd, "button"), arg_Command(cmd)); + return iFalse; + } else if (equal_Command(cmd, "pinsplit.set")) { updatePrefsPinSplitButtons_(d, arg_Command(cmd)); return iFalse; @@ -2268,6 +2282,12 @@ iBool handleCommand_App(const char *cmd) { } return iTrue; } + else if (equal_Command(cmd, "toolbar.action.set")) { + d->prefs.toolbarActions[iClamp(argLabel_Command(cmd, "button"), 0, 1)] = + iClamp(arg_Command(cmd), 0, max_ToolbarAction - 1); + postCommand_App("~toolbar.actions.changed"); + return iTrue; + } else if (equal_Command(cmd, "translation.languages")) { d->prefs.langFrom = argLabel_Command(cmd, "from"); d->prefs.langTo = argLabel_Command(cmd, "to"); @@ -3006,6 +3026,8 @@ iBool handleCommand_App(const char *cmd) { updateDropdownSelection_LabelWidget( findChild_Widget(dlg, "prefs.returnkey"), format_CStr("returnkey.set arg:%d", d->prefs.returnKey)); + updatePrefsToolBarActionButton_(dlg, 0, d->prefs.toolbarActions[0]); + updatePrefsToolBarActionButton_(dlg, 1, d->prefs.toolbarActions[1]); setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), collectNewFormat_String("%g", uiScale_Window(as_Window(d->window)))); diff --git a/src/defs.h b/src/defs.h index 9a466674..25c0ceeb 100644 --- a/src/defs.h +++ b/src/defs.h @@ -66,6 +66,23 @@ enum iReturnKeyFlag { accept_ReturnKeyFlag = 4, /* shift */ }; +enum iToolbarAction { + back_ToolbarAction = 0, + forward_ToolbarAction = 1, + home_ToolbarAction = 2, + parent_ToolbarAction = 3, + reload_ToolbarAction = 4, + newTab_ToolbarAction = 5, + closeTab_ToolbarAction = 6, + addBookmark_ToolbarAction = 7, + translate_ToolbarAction = 8, + upload_ToolbarAction = 9, + editPage_ToolbarAction = 10, + findText_ToolbarAction = 11, + settings_ToolbarAction = 12, + max_ToolbarAction +}; + /* Return key behavior is not handled via normal bindings because only certain combinations are valid. */ enum iReturnKeyBehavior { diff --git a/src/prefs.c b/src/prefs.c index 6b0164b6..426b7212 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -44,6 +44,8 @@ void init_Prefs(iPrefs *d) { d->uiAnimations = iTrue; d->uiScale = 1.0f; /* default set elsewhere */ d->zoomPercent = 100; + d->toolbarActions[0] = back_ToolbarAction; + d->toolbarActions[1] = forward_ToolbarAction; d->sideIcon = iTrue; d->hideToolbarOnScroll = iTrue; d->blinkingCursor = iTrue; diff --git a/src/prefs.h b/src/prefs.h index 6c79a3e1..43f7fc0e 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -159,6 +159,7 @@ struct Impl_Prefs { enum iColorAccent accent; /* Window and User Interface */ float uiScale; + enum iToolbarAction toolbarActions[2]; /* Document presentation */ int zoomPercent; /* Behavior */ diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 08d8dba2..e34cad3a 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c @@ -37,6 +37,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ # include "ios.h" #endif +const iToolbarActionSpec toolbarActions_Mobile[max_ToolbarAction] = { + { backArrow_Icon, "${menu.back}", "navigate.back" }, + { forwardArrow_Icon, "${menu.forward}", "navigate.forward" }, + { home_Icon, "${menu.home}", "navigate.home" }, + { upArrow_Icon, "${menu.parent}", "navigate.parent" }, + { reload_Icon, "${menu.reload}", "navigate.reload" }, + { openTab_Icon, "${menu.newtab}", "tabs.new" }, + { close_Icon, "${menu.closetab}", "tabs.close" }, + { bookmark_Icon, "${menu.page.bookmark}", "bookmark.add" }, + { globe_Icon, "${menu.page.translate}", "document.translate" }, + { upload_Icon, "${menu.page.upload}", "document.upload" }, + { edit_Icon, "${menu.page.upload.edit}", "document.upload copy:1" }, + { magnifyingGlass_Icon, "${menu.find}", "focus.set id:find.input" }, + { gear_Icon, "${menu.settings}", "preferences" }, +}; + iBool isUsingPanelLayout_Mobile(void) { return deviceType_App() != desktop_AppDeviceType; } diff --git a/src/ui/mobile.h b/src/ui/mobile.h index 54f55fd2..c19623f9 100644 --- a/src/ui/mobile.h +++ b/src/ui/mobile.h @@ -22,8 +22,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#include "defs.h" #include +iDeclareType(ToolbarActionSpec) + +struct Impl_ToolbarActionSpec { + const char *icon; + const char *label; + const char *command; +}; + +const iToolbarActionSpec toolbarActions_Mobile[max_ToolbarAction]; + iDeclareType(Widget) iDeclareType(MenuItem) diff --git a/src/ui/root.c b/src/ui/root.c index bc2bc0fb..31176115 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -592,14 +592,21 @@ static void updateNavBarIdentity_(iWidget *navBar) { static void updateNavDirButtons_(iWidget *navBar) { const iHistory *history = history_DocumentWidget(document_App()); - const iBool atOldest = atOldest_History(history); - const iBool atNewest = atNewest_History(history); + iBool atOldest = atOldest_History(history); + iBool atNewest = atNewest_History(history); setFlags_Widget(findChild_Widget(navBar, "navbar.back"), disabled_WidgetFlag, atOldest); setFlags_Widget(findChild_Widget(navBar, "navbar.forward"), disabled_WidgetFlag, atNewest); iWidget *toolBar = findWidget_App("toolbar"); if (toolBar) { - iLabelWidget *back = findChild_Widget(toolBar, "toolbar.back"); - iLabelWidget *fwd = findChild_Widget(toolBar, "toolbar.forward"); + /* Reset the state. */ + for (int i = 0; i < 2; i++) { + const char *id = (i == 0 ? "toolbar.action1" : "toolbar.action2"); + setFlags_Widget(findChild_Widget(toolBar, id), disabled_WidgetFlag, iFalse); + setOutline_LabelWidget(findChild_Widget(toolBar, id), iFalse); + } + /* Disable certain actions. */ + iLabelWidget *back = findMenuItem_Widget(toolBar, "navigate.back"); + iLabelWidget *fwd = findMenuItem_Widget(toolBar, "navigate.forward"); setFlags_Widget(as_Widget(back), disabled_WidgetFlag, atOldest); setOutline_LabelWidget(back, atOldest); setFlags_Widget(as_Widget(fwd), disabled_WidgetFlag, atNewest); @@ -1062,14 +1069,23 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) { } #if defined (iPlatformMobile) -static void dismissSidebar_(iWidget *sidebar, const char *toolButtonId) { - if (isVisible_Widget(sidebar)) { - postCommandf_App("%s.toggle", cstr_String(id_Widget(sidebar))); -// if (toolButtonId) { - // setFlags_Widget(findWidget_App(toolButtonId), noBackground_WidgetFlag, iTrue); -// } - setVisualOffset_Widget(sidebar, height_Widget(sidebar), 250, easeIn_AnimFlag); + +static void updateToolBarActions_(iWidget *toolBar) { + const iPrefs *prefs = prefs_App(); + for (int i = 0; i < 2; i++) { + int action = prefs->toolbarActions[i] + ? prefs->toolbarActions[i] + : (i == 0 ? back_ToolbarAction : forward_ToolbarAction); + iLabelWidget *button = + findChild_Widget(toolBar, i == 0 ? "toolbar.action1" : "toolbar.action2"); + if (button) { + setFlags_Widget(as_Widget(button), disabled_WidgetFlag, iFalse); + setOutline_LabelWidget(button, iFalse); + updateTextCStr_LabelWidget(button, toolbarActions_Mobile[action].icon); + setCommand_LabelWidget(button, collectNewCStr_String(toolbarActions_Mobile[action].command)); + } } + refresh_Widget(toolBar); } static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { @@ -1081,13 +1097,6 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { return iTrue; } else if (equal_Command(cmd, "toolbar.showview")) { - /* TODO: Clean this up. */ -// iWidget *sidebar = findWidget_App("sidebar"); -// iWidget *sidebar2 = findWidget_App("sidebar2"); -// dismissSidebar_(sidebar2, "toolbar.ident"); -// const iBool isVisible = isVisible_Widget(sidebar); - /* If a sidebar hasn't been shown yet, it's height is zero. */ -// const int viewHeight = size_Root(get_Root()).y; if (arg_Command(cmd) >= 0) { postCommandf_App("sidebar.mode arg:%d show:1", arg_Command(cmd)); } @@ -1102,29 +1111,6 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { 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)) { - postCommandf_App("sidebar.toggle"); - } - const iBool isVisible = isVisible_Widget(sidebar2); - // setFlags_Widget(findChild_Widget(toolBar, "toolbar.ident"), noBackground_WidgetFlag, - // isVisible); - /* If a sidebar hasn't been shown yet, it's height is zero. */ - const int viewHeight = size_Root(get_Root()).y; - if (isVisible) { - dismissSidebar_(sidebar2, NULL); - } - else { - postCommand_App("sidebar2.mode arg:3 show:1"); - int offset = height_Widget(sidebar2); - if (offset == 0) offset = size_Root(get_Root()).y; - 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")) { @@ -1132,8 +1118,13 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { updateTextCStr_LabelWidget(viewTool, icon_SidebarMode(arg_Command(cmd))); return iFalse; } + else if (equal_Command(cmd, "toolbar.actions.changed")) { + updateToolBarActions_(toolBar); + return iFalse; + } return iFalse; } + #endif /* defined (iPlatformMobile) */ static iLabelWidget *newLargeIcon_LabelWidget(const char *text, const char *cmd) { @@ -1552,14 +1543,14 @@ void createUserInterface_Root(iRoot *d) { "toolbar.close"); #else setId_Widget(addChildFlags_Widget(toolBar, - iClob(newLargeIcon_LabelWidget(backArrow_Icon, "navigate.back")), + iClob(newLargeIcon_LabelWidget("", "...")), frameless_WidgetFlag), - "toolbar.back"); + "toolbar.action1"); #endif setId_Widget(addChildFlags_Widget(toolBar, - iClob(newLargeIcon_LabelWidget(forwardArrow_Icon, "navigate.forward")), + iClob(newLargeIcon_LabelWidget("", "...")), frameless_WidgetFlag), - "toolbar.forward"); + "toolbar.action2"); iWidget *identButton; setId_Widget(identButton = addChildFlags_Widget( toolBar, @@ -1589,10 +1580,10 @@ void createUserInterface_Root(iRoot *d) { setId_Widget(as_Widget(menuButton), "toolbar.navmenu"); addChildFlags_Widget(toolBar, iClob(menuButton), frameless_WidgetFlag); iForEach(ObjectList, i, children_Widget(toolBar)) { - iLabelWidget *btn = i.object; setFlags_Widget(i.object, noBackground_WidgetFlag, iTrue); } updateToolbarColors_Root(d); + updateToolBarActions_(toolBar); const iMenuItem items[] = { { book_Icon " ${sidebar.bookmarks}", 0, 0, "toolbar.showview arg:0" }, { star_Icon " ${sidebar.feeds}", 0, 0, "toolbar.showview arg:1" }, diff --git a/src/ui/util.c b/src/ui/util.c index ab7e9ebf..6add5c89 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -2383,6 +2383,15 @@ iWidget *makePreferences_Widget(void) { format_CStr("returnkey.set arg:%d", acceptWithPrimaryMod_ReturnKeyBehavior) }, { NULL } }; + iMenuItem toolbarActionItems[2][max_ToolbarAction + 1]; + iZap(toolbarActionItems); + for (int j = 0; j < 2; j++) { + for (int i = 0; i < max_ToolbarAction; i++) { + toolbarActionItems[j][i].label = toolbarActions_Mobile[i].label; + toolbarActionItems[j][i].command = + format_CStr("toolbar.action.set arg:%d button:%d", i, j); + } + } iMenuItem docThemes[2][max_GmDocumentTheme + 1]; for (int i = 0; i < 2; ++i) { const iBool isDark = (i == 0); @@ -2476,8 +2485,10 @@ iWidget *makePreferences_Widget(void) { { "title id:heading.prefs.interface" }, { "dropdown device:0 id:prefs.returnkey", 0, 0, (const void *) returnKeyBehaviors }, { "padding device:1" }, - //{ "toggle id:prefs.hoverlink" }, { "toggle device:2 id:prefs.hidetoolbarscroll" }, + { "heading device:2 id:heading.prefs.toolbaractions" }, + { "dropdown device:2 id:prefs.toolbaraction1", 0, 0, (const void *) toolbarActionItems[0] }, + { "dropdown device:2 id:prefs.toolbaraction2", 0, 0, (const void *) toolbarActionItems[1] }, { "heading id:heading.prefs.sizing" }, { "input id:prefs.uiscale maxlen:8" }, { NULL } -- cgit v1.2.3