[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
pull/3795/head
onde2rock 6 years ago committed by Frans de Jonge
parent 7e6de30889
commit dfd87447da

@ -14,7 +14,7 @@ function ReaderConfig:init()
if not self.dimen then self.dimen = Geom:new{} end if not self.dimen then self.dimen = Geom:new{} end
if Device:hasKeyboard() then if Device:hasKeyboard() then
self.key_events = { self.key_events = {
ShowConfigMenu = { { "AA" }, doc = "show config dialog" }, ShowConfigMenu = { {{"Press","AA"}}, doc = "show config dialog" },
} }
end end
if Device:isTouchDevice() then if Device:isTouchDevice() then

@ -1,5 +1,6 @@
local Device = require("device")
local S = require("ui/data/strings") local S = require("ui/data/strings")
local Screen = require("device").screen local Screen = Device.screen
local _ = require("gettext") local _ = require("gettext")
@ -101,7 +102,8 @@ local CreOptions = {
{ {
name = "font_fine_tune", name = "font_fine_tune",
name_text = S.FONTSIZE_FINE_TUNING, 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", event = "ChangeSize",
args = {"decrease", "increase"}, args = {"decrease", "increase"},
alternate = false, alternate = false,

@ -1,6 +1,7 @@
local Device = require("device")
local S = require("ui/data/strings") local S = require("ui/data/strings")
local _ = require("gettext") local _ = require("gettext")
local Screen = require("device").screen local Screen = Device.screen
local function enable_if_equals(configurable, option, value) local function enable_if_equals(configurable, option, value)
return configurable[option] == value return configurable[option] == value
@ -33,6 +34,7 @@ local KoptOptions = {
alternate = false, alternate = false,
values = {0, 1, 2}, values = {0, 1, 2},
default_value = DKOPTREADER_CONFIG_TRIM_PAGE, default_value = DKOPTREADER_CONFIG_TRIM_PAGE,
enabled_func = Device.isTouchDevice,
event = "PageCrop", event = "PageCrop",
args = {"manual", "auto", "semi-auto"}, args = {"manual", "auto", "semi-auto"},
} }
@ -129,7 +131,8 @@ local KoptOptions = {
{ {
name = "font_fine_tune", name = "font_fine_tune",
name_text = S.FONTSIZE_FINE_TUNING, 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}, values = {-0.05, 0.05},
default_value = 0.05, default_value = 0.05,
event = "FineTuningFontSize", event = "FineTuningFontSize",

@ -7,6 +7,7 @@ local ConfirmBox = require("ui/widget/confirmbox")
local Device = require("device") local Device = require("device")
local Event = require("ui/event") local Event = require("ui/event")
local FixedTextWidget = require("ui/widget/fixedtextwidget") local FixedTextWidget = require("ui/widget/fixedtextwidget")
local FocusManager = require("ui/widget/focusmanager")
local Font = require("ui/font") local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer") local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
@ -59,13 +60,17 @@ function OptionTextItem:init()
doc = "Hold Option Item", doc = "Hold Option Item",
}, },
} }
else
self.active_key_events = {
Select = { {"Press"}, doc = "chose selected item" },
}
end end
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() function OptionTextItem:onTapSelect()
if not self.enabled then return true end if not self.enabled then return true end
for _, item in pairs(self.items) do for _, item in pairs(self.items) do
@ -119,6 +124,14 @@ function OptionIconItem:init()
end end
end end
function OptionIconItem:onFocus()
self.icon.invert = true
end
function OptionIconItem:onUnfocus()
self.icon.invert = false
end
function OptionIconItem:onTapSelect() function OptionIconItem:onTapSelect()
if not self.enabled then return true end if not self.enabled then return true end
for _, item in pairs(self.items) do for _, item in pairs(self.items) do
@ -455,6 +468,8 @@ function ConfigOption:init()
table.insert(option_items_group, switch) table.insert(option_items_group, switch)
end end
table.insert(option_items_container, option_items_group) 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(horizontal_group, option_items_container)
table.insert(vertical_group, horizontal_group) table.insert(vertical_group, horizontal_group)
end -- if end -- if
@ -464,6 +479,23 @@ function ConfigOption:init()
self.dimen = vertical_group:getSize() self.dimen = vertical_group:getSize()
end 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, } local ConfigPanel = FrameContainer:new{ background = Blitbuffer.COLOR_WHITE, bordersize = 0, }
function ConfigPanel:init() function ConfigPanel:init()
local config_options = self.config_dialog.config_options local config_options = self.config_dialog.config_options
@ -504,7 +536,7 @@ function MenuBar:init()
} }
menu_items[c] = menu_icon menu_items[c] = menu_icon
end end
table.insert(self.config_dialog.layout,menu_items) --for the focusmanager
local available_width = Screen:getWidth() - icons_width 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) -- all for padding
-- local padding = math.floor(available_width / #menu_items / 2 / 2) -- half padding, half spacing ? -- 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, --is_borderless = false,
panel_index = 1, panel_index = 1,
} }
@ -650,10 +682,8 @@ function ConfigDialog:init()
if Device:hasKeys() then if Device:hasKeys() then
-- set up keyboard events -- set up keyboard events
self.key_events.Close = { {"Back"}, doc = "close config menu" } self.key_events.Close = { {"Back"}, doc = "close config menu" }
-- we won't catch presses to "Right" self.key_events.Select = { {"Press"}, doc = "select current menu item" }
self.key_events.FocusRight = nil
end end
self.key_events.Select = { {"Press"}, doc = "select current menu item" }
end end
function ConfigDialog:updateConfigPanel(index) function ConfigDialog:updateConfigPanel(index)
@ -661,6 +691,7 @@ function ConfigDialog:updateConfigPanel(index)
end end
function ConfigDialog:update() function ConfigDialog:update()
self.layout = {}
self.config_menubar = MenuBar:new{ self.config_menubar = MenuBar:new{
config_dialog = self, config_dialog = self,
panel_index = self.panel_index, panel_index = self.panel_index,
@ -676,6 +707,9 @@ function ConfigDialog:update()
self.config_menubar, self.config_menubar,
}, },
} }
--reset the focusmanager cursor
self.selected.y=#self.layout
self.selected.x=self.panel_index
self[1] = BottomContainer:new{ self[1] = BottomContainer:new{
dimen = Screen:getSize(), dimen = Screen:getSize(),
@ -791,4 +825,9 @@ function ConfigDialog:onClose()
return true return true
end end
function ConfigDialog:onSelect()
self:getFocusItem():handleEvent(Event:new("TapSelect"))
return true
end
return ConfigDialog return ConfigDialog

@ -171,11 +171,6 @@ function MenuItem:init()
}, },
} }
end end
if Device:hasKeys() then
self.active_key_events = {
Select = { {"Press"}, doc = "chose selected item" },
}
end
local text_mandatory_padding = 0 local text_mandatory_padding = 0
local text_ellipsis_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 my_text = self.text and ""..self.text or ""
local w = RenderText:sizeUtf8Text(0, self.dimen.w, self.face, my_text, true, self.bold).x 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 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 = "\226\128\166 " -- an ellipsis
local indicator_w = RenderText:sizeUtf8Text(0, self.dimen.w, self.face, local indicator_w = RenderText:sizeUtf8Text(0, self.dimen.w, self.face,
indicator, true, self.bold).x indicator, true, self.bold).x
@ -382,13 +372,11 @@ function MenuItem:onFocus(initial_focus)
else else
self._underline_container.color = Blitbuffer.COLOR_BLACK self._underline_container.color = Blitbuffer.COLOR_BLACK
end end
self.key_events = self.active_key_events
return true return true
end end
function MenuItem:onUnfocus() function MenuItem:onUnfocus()
self._underline_container.color = self.line_color self._underline_container.color = self.line_color
self.key_events = {}
return true return true
end end

@ -154,6 +154,14 @@ function ToggleSwitch:togglePosition(position)
self:update() self:update()
end 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) function ToggleSwitch:calculatePosition(gev)
local x = (gev.pos.x - self.dimen.x) / self.dimen.w * self.n_pos 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 local y = (gev.pos.y - self.dimen.y) / self.dimen.h * self.row_count
@ -168,8 +176,13 @@ function ToggleSwitch:onTapSelect(arg, gev)
return return
end end
end end
local position = self:calculatePosition(gev) if gev then
self:togglePosition(position) local position = self:calculatePosition(gev)
self:togglePosition(position)
else
self:circlePosition()
end
--[[ --[[
if self.values then if self.values then
self.values = self.values or {} self.values = self.values or {}
@ -198,4 +211,14 @@ function ToggleSwitch:onHoldSelect(arg, gev)
return true return true
end 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 return ToggleSwitch

@ -1,5 +1,6 @@
local Device = require("device") local Device = require("device")
local DocumentRegistry = require("document/documentregistry") local DocumentRegistry = require("document/documentregistry")
local Event = require("ui/event")
local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo")
local ImageViewer = require("ui/widget/imageviewer") local ImageViewer = require("ui/widget/imageviewer")
local Menu = require("ui/widget/menu") local Menu = require("ui/widget/menu")
@ -93,7 +94,7 @@ function CoverMenu:updateItems(select_number)
-- reset focus manager accordingly -- reset focus manager accordingly
self.selected = { x = 1, y = select_number } self.selected = { x = 1, y = select_number }
-- set focus to requested menu item -- 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 -- This will not work with our MosaicMenu, as a MosaicMenuItem is
-- not a direct child of item_group (which contains VerticalSpans -- not a direct child of item_group (which contains VerticalSpans
-- and HorizontalGroup...) -- and HorizontalGroup...)

@ -146,11 +146,6 @@ function ListMenuItem:init()
}, },
} }
end 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() -- We now build the minimal widget container that won't change after udpate()
@ -654,13 +649,11 @@ end
-- As done in MenuItem -- As done in MenuItem
function ListMenuItem:onFocus() function ListMenuItem:onFocus()
self._underline_container.color = Blitbuffer.COLOR_BLACK self._underline_container.color = Blitbuffer.COLOR_BLACK
self.key_events = self.active_key_events
return true return true
end end
function ListMenuItem:onUnfocus() function ListMenuItem:onUnfocus()
self._underline_container.color = Blitbuffer.COLOR_WHITE self._underline_container.color = Blitbuffer.COLOR_WHITE
self.key_events = {}
return true return true
end end

@ -334,11 +334,6 @@ function MosaicMenuItem:init()
}, },
} }
end 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() -- We now build the minimal widget container that won't change after udpate()
@ -642,13 +637,11 @@ end
-- As done in MenuItem -- As done in MenuItem
function MosaicMenuItem:onFocus() function MosaicMenuItem:onFocus()
self._underline_container.color = Blitbuffer.COLOR_BLACK self._underline_container.color = Blitbuffer.COLOR_BLACK
self.key_events = self.active_key_events
return true return true
end end
function MosaicMenuItem:onUnfocus() function MosaicMenuItem:onUnfocus()
self._underline_container.color = Blitbuffer.COLOR_WHITE self._underline_container.color = Blitbuffer.COLOR_WHITE
self.key_events = {}
return true return true
end end

Loading…
Cancel
Save