From dfd87447da29c124ca8cfa296f114f1d8764ba09 Mon Sep 17 00:00:00 2001 From: onde2rock Date: Thu, 22 Mar 2018 21:01:38 +0100 Subject: [PATCH] [UX] Make the reader bottom menu compatible with key navigation (#3785) * [toggleswitch] Add support for key navigation to this widget Add the onFocus an onUnfocus event handler add a new function that just circle the switch if not touch event is detected * Add key navigation to the readermenu The shortcut is still Alt-gr on sdl, to be defined on Kindle * Remove the old method of handling the Press key. Now the event is handled by the main widget who implement focusmanager and then dispatched to the currently focused item. Modify the fine font tuning only for non touch-devices See : https://github.com/koreader/koreader/pull/3785#issuecomment-375306466 --- frontend/apps/reader/modules/readerconfig.lua | 2 +- frontend/ui/data/creoptions.lua | 6 +- frontend/ui/data/koptoptions.lua | 7 ++- frontend/ui/widget/configdialog.lua | 57 ++++++++++++++++--- frontend/ui/widget/menu.lua | 12 ---- frontend/ui/widget/toggleswitch.lua | 27 ++++++++- plugins/coverbrowser.koplugin/covermenu.lua | 3 +- plugins/coverbrowser.koplugin/listmenu.lua | 7 --- plugins/coverbrowser.koplugin/mosaicmenu.lua | 7 --- 9 files changed, 85 insertions(+), 43 deletions(-) diff --git a/frontend/apps/reader/modules/readerconfig.lua b/frontend/apps/reader/modules/readerconfig.lua index 8ed725c3a..ea388c3e1 100644 --- a/frontend/apps/reader/modules/readerconfig.lua +++ b/frontend/apps/reader/modules/readerconfig.lua @@ -14,7 +14,7 @@ function ReaderConfig:init() if not self.dimen then self.dimen = Geom:new{} end if Device:hasKeyboard() then self.key_events = { - ShowConfigMenu = { { "AA" }, doc = "show config dialog" }, + ShowConfigMenu = { {{"Press","AA"}}, doc = "show config dialog" }, } end if Device:isTouchDevice() then diff --git a/frontend/ui/data/creoptions.lua b/frontend/ui/data/creoptions.lua index 80a4b6fc4..6fb7913a0 100644 --- a/frontend/ui/data/creoptions.lua +++ b/frontend/ui/data/creoptions.lua @@ -1,5 +1,6 @@ +local Device = require("device") local S = require("ui/data/strings") -local Screen = require("device").screen +local Screen = Device.screen local _ = require("gettext") @@ -101,7 +102,8 @@ local CreOptions = { { name = "font_fine_tune", name_text = S.FONTSIZE_FINE_TUNING, - toggle = {S.DECREASE, S.INCREASE}, + toggle = Device:isTouchDevice() and {S.DECREASE, S.INCREASE} or nil, + item_text = not Device:isTouchDevice() and {S.DECREASE, S.INCREASE} or nil, event = "ChangeSize", args = {"decrease", "increase"}, alternate = false, diff --git a/frontend/ui/data/koptoptions.lua b/frontend/ui/data/koptoptions.lua index 90ac4728f..3e2cfdfa9 100644 --- a/frontend/ui/data/koptoptions.lua +++ b/frontend/ui/data/koptoptions.lua @@ -1,6 +1,7 @@ +local Device = require("device") local S = require("ui/data/strings") local _ = require("gettext") -local Screen = require("device").screen +local Screen = Device.screen local function enable_if_equals(configurable, option, value) return configurable[option] == value @@ -33,6 +34,7 @@ local KoptOptions = { alternate = false, values = {0, 1, 2}, default_value = DKOPTREADER_CONFIG_TRIM_PAGE, + enabled_func = Device.isTouchDevice, event = "PageCrop", args = {"manual", "auto", "semi-auto"}, } @@ -129,7 +131,8 @@ local KoptOptions = { { name = "font_fine_tune", name_text = S.FONTSIZE_FINE_TUNING, - toggle = {S.DECREASE, S.INCREASE}, + toggle = Device:isTouchDevice() and {S.DECREASE, S.INCREASE} or nil, + item_text = not Device:isTouchDevice() and {S.DECREASE, S.INCREASE} or nil, values = {-0.05, 0.05}, default_value = 0.05, event = "FineTuningFontSize", diff --git a/frontend/ui/widget/configdialog.lua b/frontend/ui/widget/configdialog.lua index 332383615..85953a1fe 100644 --- a/frontend/ui/widget/configdialog.lua +++ b/frontend/ui/widget/configdialog.lua @@ -7,6 +7,7 @@ local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") local Event = require("ui/event") local FixedTextWidget = require("ui/widget/fixedtextwidget") +local FocusManager = require("ui/widget/focusmanager") local Font = require("ui/font") local FrameContainer = require("ui/widget/container/framecontainer") local Geom = require("ui/geometry") @@ -59,13 +60,17 @@ function OptionTextItem:init() doc = "Hold Option Item", }, } - else - self.active_key_events = { - Select = { {"Press"}, doc = "chose selected item" }, - } end end +function OptionTextItem:onFocus() + self[1].color = Blitbuffer.COLOR_BLACK +end + +function OptionTextItem:onUnfocus() + self[1].color = Blitbuffer.COLOR_WHITE +end + function OptionTextItem:onTapSelect() if not self.enabled then return true end for _, item in pairs(self.items) do @@ -119,6 +124,14 @@ function OptionIconItem:init() end end +function OptionIconItem:onFocus() + self.icon.invert = true +end + +function OptionIconItem:onUnfocus() + self.icon.invert = false +end + function OptionIconItem:onTapSelect() if not self.enabled then return true end for _, item in pairs(self.items) do @@ -455,6 +468,8 @@ function ConfigOption:init() table.insert(option_items_group, switch) end table.insert(option_items_container, option_items_group) + --add line of item to the second last place in the focusmanager so the menubar stay at the bottom + table.insert(self.config.layout, #self.config.layout,self:_itemGroupToLayoutLine(option_items_group)) table.insert(horizontal_group, option_items_container) table.insert(vertical_group, horizontal_group) end -- if @@ -464,6 +479,23 @@ function ConfigOption:init() self.dimen = vertical_group:getSize() end +function ConfigOption:_itemGroupToLayoutLine(option_items_group) + local layout_line = {} + for k, v in pairs(option_items_group) do + --pad the beginning of the line in the layout to align it with the current selected tab + if type(k) == "number" then + layout_line[k + self.config.panel_index-1] = v + end + end + for k, v in pairs(layout_line) do + --remove item_spacing (all widget have the name property) + if not v.name then + table.remove(layout_line,k) + end + end + return layout_line +end + local ConfigPanel = FrameContainer:new{ background = Blitbuffer.COLOR_WHITE, bordersize = 0, } function ConfigPanel:init() local config_options = self.config_dialog.config_options @@ -504,7 +536,7 @@ function MenuBar:init() } menu_items[c] = menu_icon end - + table.insert(self.config_dialog.layout,menu_items) --for the focusmanager local available_width = Screen:getWidth() - icons_width -- local padding = math.floor(available_width / #menu_items / 2) -- all for padding -- local padding = math.floor(available_width / #menu_items / 2 / 2) -- half padding, half spacing ? @@ -612,7 +644,7 @@ Widget that displays config menubar and config panel --]] -local ConfigDialog = InputContainer:new{ +local ConfigDialog = FocusManager:new{ --is_borderless = false, panel_index = 1, } @@ -650,10 +682,8 @@ function ConfigDialog:init() if Device:hasKeys() then -- set up keyboard events self.key_events.Close = { {"Back"}, doc = "close config menu" } - -- we won't catch presses to "Right" - self.key_events.FocusRight = nil + self.key_events.Select = { {"Press"}, doc = "select current menu item" } end - self.key_events.Select = { {"Press"}, doc = "select current menu item" } end function ConfigDialog:updateConfigPanel(index) @@ -661,6 +691,7 @@ function ConfigDialog:updateConfigPanel(index) end function ConfigDialog:update() + self.layout = {} self.config_menubar = MenuBar:new{ config_dialog = self, panel_index = self.panel_index, @@ -676,6 +707,9 @@ function ConfigDialog:update() self.config_menubar, }, } + --reset the focusmanager cursor + self.selected.y=#self.layout + self.selected.x=self.panel_index self[1] = BottomContainer:new{ dimen = Screen:getSize(), @@ -791,4 +825,9 @@ function ConfigDialog:onClose() return true end +function ConfigDialog:onSelect() + self:getFocusItem():handleEvent(Event:new("TapSelect")) + return true +end + return ConfigDialog diff --git a/frontend/ui/widget/menu.lua b/frontend/ui/widget/menu.lua index 97ceb522c..af095e11d 100644 --- a/frontend/ui/widget/menu.lua +++ b/frontend/ui/widget/menu.lua @@ -171,11 +171,6 @@ function MenuItem:init() }, } end - if Device:hasKeys() then - self.active_key_events = { - Select = { {"Press"}, doc = "chose selected item" }, - } - end local text_mandatory_padding = 0 local text_ellipsis_mandatory_padding = 0 @@ -203,11 +198,6 @@ function MenuItem:init() local my_text = self.text and ""..self.text or "" local w = RenderText:sizeUtf8Text(0, self.dimen.w, self.face, my_text, true, self.bold).x if w + mandatory_w + state_button_width + text_mandatory_padding >= self.content_width then - if Device:hasKeyboard() then - self.active_key_events.ShowItemDetail = { - {"Right"}, doc = "show item detail" - } - end local indicator = "\226\128\166 " -- an ellipsis local indicator_w = RenderText:sizeUtf8Text(0, self.dimen.w, self.face, indicator, true, self.bold).x @@ -382,13 +372,11 @@ function MenuItem:onFocus(initial_focus) else self._underline_container.color = Blitbuffer.COLOR_BLACK end - self.key_events = self.active_key_events return true end function MenuItem:onUnfocus() self._underline_container.color = self.line_color - self.key_events = {} return true end diff --git a/frontend/ui/widget/toggleswitch.lua b/frontend/ui/widget/toggleswitch.lua index 179f58d3d..a479bd723 100644 --- a/frontend/ui/widget/toggleswitch.lua +++ b/frontend/ui/widget/toggleswitch.lua @@ -154,6 +154,14 @@ function ToggleSwitch:togglePosition(position) self:update() end +function ToggleSwitch:circlePosition() + if self.position then + self.position = (self.position+1)%self.n_pos + self.position = self.position == 0 and self.n_pos or self.position + self:update() + end +end + function ToggleSwitch:calculatePosition(gev) local x = (gev.pos.x - self.dimen.x) / self.dimen.w * self.n_pos local y = (gev.pos.y - self.dimen.y) / self.dimen.h * self.row_count @@ -168,8 +176,13 @@ function ToggleSwitch:onTapSelect(arg, gev) return end end - local position = self:calculatePosition(gev) - self:togglePosition(position) + if gev then + local position = self:calculatePosition(gev) + self:togglePosition(position) + else + self:circlePosition() + end + --[[ if self.values then self.values = self.values or {} @@ -198,4 +211,14 @@ function ToggleSwitch:onHoldSelect(arg, gev) return true end +function ToggleSwitch:onFocus() + self.toggle_frame.background = Blitbuffer.COLOR_BLACK + return true +end + +function ToggleSwitch:onUnfocus() + self.toggle_frame.background = Blitbuffer.COLOR_WHITE + return true +end + return ToggleSwitch diff --git a/plugins/coverbrowser.koplugin/covermenu.lua b/plugins/coverbrowser.koplugin/covermenu.lua index 01477162c..8fdbc2c7e 100644 --- a/plugins/coverbrowser.koplugin/covermenu.lua +++ b/plugins/coverbrowser.koplugin/covermenu.lua @@ -1,5 +1,6 @@ local Device = require("device") local DocumentRegistry = require("document/documentregistry") +local Event = require("ui/event") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") local ImageViewer = require("ui/widget/imageviewer") local Menu = require("ui/widget/menu") @@ -93,7 +94,7 @@ function CoverMenu:updateItems(select_number) -- reset focus manager accordingly self.selected = { x = 1, y = select_number } -- set focus to requested menu item - self.item_group[select_number]:onFocus() + self:getFocusItem():handleEvent(Event:new("Focus")) -- This will not work with our MosaicMenu, as a MosaicMenuItem is -- not a direct child of item_group (which contains VerticalSpans -- and HorizontalGroup...) diff --git a/plugins/coverbrowser.koplugin/listmenu.lua b/plugins/coverbrowser.koplugin/listmenu.lua index f5ad4e5ff..af226eb78 100644 --- a/plugins/coverbrowser.koplugin/listmenu.lua +++ b/plugins/coverbrowser.koplugin/listmenu.lua @@ -146,11 +146,6 @@ function ListMenuItem:init() }, } end - if Device:hasKeys() then - self.active_key_events = { - Select = { {"Press"}, doc = "chose selected item" }, - } - end -- We now build the minimal widget container that won't change after udpate() @@ -654,13 +649,11 @@ end -- As done in MenuItem function ListMenuItem:onFocus() self._underline_container.color = Blitbuffer.COLOR_BLACK - self.key_events = self.active_key_events return true end function ListMenuItem:onUnfocus() self._underline_container.color = Blitbuffer.COLOR_WHITE - self.key_events = {} return true end diff --git a/plugins/coverbrowser.koplugin/mosaicmenu.lua b/plugins/coverbrowser.koplugin/mosaicmenu.lua index 0064c9154..31b0ca4e4 100644 --- a/plugins/coverbrowser.koplugin/mosaicmenu.lua +++ b/plugins/coverbrowser.koplugin/mosaicmenu.lua @@ -334,11 +334,6 @@ function MosaicMenuItem:init() }, } end - if Device:hasKeys() then - self.active_key_events = { - Select = { {"Press"}, doc = "chose selected item" }, - } - end -- We now build the minimal widget container that won't change after udpate() @@ -642,13 +637,11 @@ end -- As done in MenuItem function MosaicMenuItem:onFocus() self._underline_container.color = Blitbuffer.COLOR_BLACK - self.key_events = self.active_key_events return true end function MosaicMenuItem:onUnfocus() self._underline_container.color = Blitbuffer.COLOR_WHITE - self.key_events = {} return true end