mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Non-Touch: improve bottom menu usability (#8712)
- FocusManager: allow managing sub widgets by merging their "layout" in the main one; make "press" support simpler by handling it as a fake tap event at the center of the focused widget. - Setup gestures on non-touch devices for new focus manager. - ToggleSwitch: use child layout. - ButtonProgressWidget: use child layout. - SpinWidget and DoubleSpinWidget: add keyboard navigation.
This commit is contained in:
@@ -26,9 +26,7 @@ function ReaderConfig:init()
|
||||
ShowConfigMenu = { {{"Press","AA"}}, doc = "show config dialog" },
|
||||
}
|
||||
end
|
||||
if Device:isTouchDevice() then
|
||||
self:initGesListener()
|
||||
end
|
||||
self:initGesListener()
|
||||
if G_reader_settings:has("activate_menu") then
|
||||
self.activation_menu = G_reader_settings:readSetting("activate_menu")
|
||||
else
|
||||
|
||||
@@ -165,31 +165,29 @@ function Button:init()
|
||||
end
|
||||
self.dimen = self.frame:getSize()
|
||||
self[1] = self.frame
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
TapSelectButton = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Tap Button",
|
||||
self.ges_events = {
|
||||
TapSelectButton = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
HoldSelectButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Button",
|
||||
doc = "Tap Button",
|
||||
},
|
||||
HoldSelectButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Button",
|
||||
},
|
||||
-- Safe-guard for when used inside a MovableContainer
|
||||
HoldReleaseSelectButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold_release",
|
||||
range = self.dimen,
|
||||
},
|
||||
-- Safe-guard for when used inside a MovableContainer
|
||||
HoldReleaseSelectButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold_release",
|
||||
range = self.dimen,
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
function Button:setText(text, width)
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
local Blitbuffer = require("ffi/blitbuffer")
|
||||
local Button = require("ui/widget/button")
|
||||
local Device = require("device")
|
||||
local FocusManager = require("ui/widget/focusmanager")
|
||||
local Geom = require("ui/geometry")
|
||||
local HorizontalGroup = require("ui/widget/horizontalgroup")
|
||||
local HorizontalSpan = require("ui/widget/horizontalspan")
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local FrameContainer = require("ui/widget/container/framecontainer")
|
||||
local Size = require("ui/size")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local _ = require("gettext")
|
||||
local Screen = Device.screen
|
||||
|
||||
local ButtonProgressWidget = InputContainer:new{
|
||||
local ButtonProgressWidget = FocusManager:new{
|
||||
width = Screen:scaleBySize(216),
|
||||
height = Size.item.height_default,
|
||||
padding = Size.padding.small,
|
||||
@@ -27,6 +27,8 @@ local ButtonProgressWidget = InputContainer:new{
|
||||
}
|
||||
|
||||
function ButtonProgressWidget:init()
|
||||
self.current_button_index = self.position
|
||||
|
||||
self.buttonprogress_frame = FrameContainer:new{
|
||||
background = Blitbuffer.COLOR_WHITE,
|
||||
color = Blitbuffer.COLOR_DARK_GRAY,
|
||||
@@ -46,12 +48,17 @@ function ButtonProgressWidget:init()
|
||||
self.horizontal_span_width = self.horizontal_span.width
|
||||
end
|
||||
self:update()
|
||||
if self.fine_tune then
|
||||
self.current_button_index = self.current_button_index + 1
|
||||
end
|
||||
self.buttonprogress_frame[1] = self.buttonprogress_content
|
||||
self[1] = self.buttonprogress_frame
|
||||
self.dimen = Geom:new(self.buttonprogress_frame:getSize())
|
||||
end
|
||||
|
||||
function ButtonProgressWidget:update()
|
||||
self.layout = {{}}
|
||||
|
||||
self.buttonprogress_content:clear()
|
||||
local button_margin = Size.margin.tiny
|
||||
local button_padding = Size.padding.button
|
||||
@@ -91,7 +98,6 @@ function ButtonProgressWidget:update()
|
||||
self.callback("-")
|
||||
self:update()
|
||||
end,
|
||||
no_focus = true,
|
||||
hold_callback = function()
|
||||
self.hold_callback("-")
|
||||
end,
|
||||
@@ -100,6 +106,7 @@ function ButtonProgressWidget:update()
|
||||
button.frame.color = Blitbuffer.COLOR_DARK_GRAY
|
||||
end
|
||||
table.insert(self.buttonprogress_content, button)
|
||||
table.insert(self.layout[1], button)
|
||||
table.insert(self.buttonprogress_content, self.horizontal_span)
|
||||
end
|
||||
|
||||
@@ -139,7 +146,7 @@ function ButtonProgressWidget:update()
|
||||
self.position = i
|
||||
self:update()
|
||||
end,
|
||||
no_focus = true,
|
||||
no_focus = highlighted,
|
||||
hold_callback = function()
|
||||
self.hold_callback(i)
|
||||
end,
|
||||
@@ -161,11 +168,14 @@ function ButtonProgressWidget:update()
|
||||
margin = button_margin,
|
||||
padding = 0,
|
||||
bordersize = 0,
|
||||
focusable = true,
|
||||
focus_border_size = Size.border.thin,
|
||||
button,
|
||||
}
|
||||
end
|
||||
end
|
||||
table.insert(self.buttonprogress_content, button)
|
||||
table.insert(self.layout[1], button)
|
||||
end
|
||||
|
||||
-- Plus button on the right
|
||||
@@ -194,16 +204,17 @@ function ButtonProgressWidget:update()
|
||||
self.callback("+")
|
||||
self:update()
|
||||
end,
|
||||
no_focus = true,
|
||||
hold_callback = function()
|
||||
self.hold_callback("+")
|
||||
end,
|
||||
}
|
||||
|
||||
if self.thin_grey_style then
|
||||
button.frame.color = Blitbuffer.COLOR_DARK_GRAY
|
||||
end
|
||||
table.insert(self.buttonprogress_content, self.horizontal_span)
|
||||
table.insert(self.buttonprogress_content, button)
|
||||
table.insert(self.layout[1], button)
|
||||
end
|
||||
-- More option button on the right
|
||||
if self.more_options then
|
||||
@@ -230,7 +241,6 @@ function ButtonProgressWidget:update()
|
||||
self.callback("⋮")
|
||||
self:update()
|
||||
end,
|
||||
no_focus = true,
|
||||
hold_callback = function()
|
||||
self.hold_callback("⋮")
|
||||
end,
|
||||
@@ -240,6 +250,7 @@ function ButtonProgressWidget:update()
|
||||
end
|
||||
table.insert(self.buttonprogress_content, self.horizontal_span)
|
||||
table.insert(self.buttonprogress_content, button)
|
||||
table.insert(self.layout[1], button)
|
||||
end
|
||||
|
||||
UIManager:setDirty(self.show_parrent, function()
|
||||
@@ -253,16 +264,6 @@ function ButtonProgressWidget:setPosition(position, default_position)
|
||||
self:update()
|
||||
end
|
||||
|
||||
function ButtonProgressWidget:onFocus()
|
||||
self.buttonprogress_frame.background = Blitbuffer.COLOR_BLACK
|
||||
return true
|
||||
end
|
||||
|
||||
function ButtonProgressWidget:onUnfocus()
|
||||
self.buttonprogress_frame.background = Blitbuffer.COLOR_WHITE
|
||||
return true
|
||||
end
|
||||
|
||||
function ButtonProgressWidget:onTapSelect(arg, gev)
|
||||
if gev == nil then
|
||||
self:circlePosition()
|
||||
|
||||
@@ -24,6 +24,7 @@ local ButtonTable = FocusManager:new{
|
||||
zero_sep = false,
|
||||
button_font_face = "cfont",
|
||||
button_font_size = 20,
|
||||
auto_focus_first_button = true,
|
||||
}
|
||||
|
||||
function ButtonTable:init()
|
||||
@@ -99,7 +100,9 @@ function ButtonTable:init()
|
||||
self:addHorizontalSep(true, false, false)
|
||||
if Device:hasDPad() then
|
||||
self.layout = self.buttons_layout
|
||||
self.layout[1][1]:onFocus()
|
||||
if self.auto_focus_first_button then
|
||||
self.layout[1][1]:onFocus()
|
||||
end
|
||||
self.key_events.SelectByKeyPress = { {{"Press"}} }
|
||||
else
|
||||
self.key_events = {} -- deregister all key press event listeners
|
||||
@@ -128,9 +131,11 @@ end
|
||||
|
||||
function ButtonTable:onSelectByKeyPress()
|
||||
local item = self:getFocusItem()
|
||||
if item.enabled then
|
||||
if item and item.enabled then
|
||||
item.callback()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ButtonTable:getButtonById(id)
|
||||
|
||||
@@ -52,24 +52,22 @@ function OptionTextItem:init()
|
||||
}
|
||||
self.dimen = self[1]:getSize()
|
||||
-- we need this table per-instance, so we declare it here
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
TapSelect = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Select Option Item",
|
||||
self.ges_events = {
|
||||
TapSelect = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
HoldSelect = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Option Item",
|
||||
doc = "Select Option Item",
|
||||
},
|
||||
HoldSelect = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
}
|
||||
end
|
||||
doc = "Hold Option Item",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function OptionTextItem:onFocus()
|
||||
@@ -128,25 +126,23 @@ function OptionIconItem:init()
|
||||
}
|
||||
self.dimen = self[1]:getSize()
|
||||
-- we need this table per-instance, so we declare it here
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
TapSelect = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Select Option Item",
|
||||
self.ges_events = {
|
||||
TapSelect = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
HoldSelect = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Option Item",
|
||||
doc = "Select Option Item",
|
||||
},
|
||||
HoldSelect = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Option Item",
|
||||
},
|
||||
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
function OptionIconItem:onFocus()
|
||||
@@ -674,8 +670,21 @@ function ConfigOption:_itemGroupToLayoutLine(option_items_group)
|
||||
local j = self.config.panel_index
|
||||
for i, v in ipairs(option_items_group) do
|
||||
if v.name then
|
||||
layout_line[j] = v
|
||||
j = j + 1
|
||||
if v.layout and v.disableFocusManagement then -- it is a FocusManager
|
||||
-- merge child layout to one row layout
|
||||
-- currently child widgets are all one row
|
||||
-- need improved if two or more rows widget existed
|
||||
for _, row in ipairs(v.layout) do
|
||||
for _, widget in ipairs(row) do
|
||||
layout_line[j] = widget
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
v:disableFocusManagement()
|
||||
else
|
||||
layout_line[j] = v
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return layout_line
|
||||
@@ -849,28 +858,26 @@ function ConfigDialog:init()
|
||||
------------------------------------------
|
||||
-- start to set up input event callback --
|
||||
------------------------------------------
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events.TapCloseMenu = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
self.ges_events.TapCloseMenu = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
}
|
||||
self.ges_events.SwipeCloseMenu = {
|
||||
GestureRange:new{
|
||||
ges = "swipe",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
}
|
||||
self.ges_events.SwipeCloseMenu = {
|
||||
GestureRange:new{
|
||||
ges = "swipe",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
}
|
||||
end
|
||||
}
|
||||
if Device:hasKeys() then
|
||||
-- set up keyboard events
|
||||
local close_keys = Device:hasFewKeys() and { "Back", "Left" } or Device.input.group.Back
|
||||
@@ -1457,8 +1464,7 @@ function ConfigDialog:onClose()
|
||||
end
|
||||
|
||||
function ConfigDialog:onSelect()
|
||||
self:getFocusItem():handleEvent(Event:new("TapSelect"))
|
||||
return true
|
||||
return self:sendTapEventToFocusedWidget()
|
||||
end
|
||||
|
||||
return ConfigDialog
|
||||
|
||||
@@ -41,6 +41,9 @@ local FrameContainer = WidgetContainer:new{
|
||||
invert = false,
|
||||
allow_mirroring = true,
|
||||
_mirroredUI = BD.mirroredUILayout(),
|
||||
focusable = false,
|
||||
focus_border_size = Size.border.window * 2,
|
||||
focus_border_color = Blitbuffer.COLOR_BLACK,
|
||||
}
|
||||
|
||||
function FrameContainer:getSize()
|
||||
@@ -58,6 +61,27 @@ function FrameContainer:getSize()
|
||||
}
|
||||
end
|
||||
|
||||
function FrameContainer:onFocus()
|
||||
if not self.focusable then
|
||||
return
|
||||
end
|
||||
self._origin_bordersize = self.bordersize
|
||||
self._origin_border_color = self.color
|
||||
self.bordersize = self.focus_border_size
|
||||
self.color = self.focus_border_color
|
||||
return true
|
||||
end
|
||||
|
||||
function FrameContainer:onUnfocus()
|
||||
if not self.focusable then
|
||||
return
|
||||
end
|
||||
self.bordersize = self._origin_bordersize
|
||||
self.color = self._origin_border_color
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function FrameContainer:paintTo(bb, x, y)
|
||||
local my_size = self:getSize()
|
||||
self.dimen = Geom:new{
|
||||
|
||||
@@ -2,12 +2,12 @@ local Blitbuffer = require("ffi/blitbuffer")
|
||||
local ButtonTable = require("ui/widget/buttontable")
|
||||
local CenterContainer = require("ui/widget/container/centercontainer")
|
||||
local Device = require("device")
|
||||
local FocusManager = require("ui/widget/focusmanager")
|
||||
local FrameContainer = require("ui/widget/container/framecontainer")
|
||||
local Geom = require("ui/geometry")
|
||||
local GestureRange = require("ui/gesturerange")
|
||||
local Font = require("ui/font")
|
||||
local HorizontalGroup = require("ui/widget/horizontalgroup")
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local MovableContainer = require("ui/widget/container/movablecontainer")
|
||||
local NumberPickerWidget = require("ui/widget/numberpickerwidget")
|
||||
local Size = require("ui/size")
|
||||
@@ -20,7 +20,7 @@ local _ = require("gettext")
|
||||
local Screen = Device.screen
|
||||
local T = require("ffi/util").template
|
||||
|
||||
local DoubleSpinWidget = InputContainer:new{
|
||||
local DoubleSpinWidget = FocusManager:new{
|
||||
title_text = "",
|
||||
title_face = Font:getFace("x_smalltfont"),
|
||||
info_text = nil,
|
||||
@@ -65,9 +65,8 @@ function DoubleSpinWidget:init()
|
||||
self.width = math.floor(math.min(self.screen_width, self.screen_height) * self.width_factor)
|
||||
end
|
||||
if Device:hasKeys() then
|
||||
self.key_events = {
|
||||
Close = { {Device.input.group.Back}, doc = "close doublespin widget" }
|
||||
}
|
||||
self.key_events.Close = { {Device.input.group.Back}, doc = "close doublespin widget" }
|
||||
self.key_events.Press = { {"Press"}, doc = "press button" }
|
||||
end
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
@@ -88,6 +87,7 @@ function DoubleSpinWidget:init()
|
||||
end
|
||||
|
||||
function DoubleSpinWidget:update(numberpicker_left_value, numberpicker_right_value)
|
||||
self.layout = {}
|
||||
local left_widget = NumberPickerWidget:new{
|
||||
show_parent = self,
|
||||
value = numberpicker_left_value or self.left_value,
|
||||
@@ -98,6 +98,7 @@ function DoubleSpinWidget:update(numberpicker_left_value, numberpicker_right_val
|
||||
precision = self.left_precision,
|
||||
wrap = self.left_wrap,
|
||||
}
|
||||
self:mergeLayoutInHorizontal(left_widget)
|
||||
local right_widget = NumberPickerWidget:new{
|
||||
show_parent = self,
|
||||
value = numberpicker_right_value or self.right_value,
|
||||
@@ -108,6 +109,7 @@ function DoubleSpinWidget:update(numberpicker_left_value, numberpicker_right_val
|
||||
precision = self.right_precision,
|
||||
wrap = self.right_wrap,
|
||||
}
|
||||
self:mergeLayoutInHorizontal(right_widget)
|
||||
left_widget.picker_updated_callback = function(value)
|
||||
self:update(value, right_widget:getValue())
|
||||
end
|
||||
@@ -227,7 +229,9 @@ function DoubleSpinWidget:update(numberpicker_left_value, numberpicker_right_val
|
||||
buttons = buttons,
|
||||
zero_sep = true,
|
||||
show_parent = self,
|
||||
auto_focus_first_button = false,
|
||||
}
|
||||
self:mergeLayoutInVertical(button_table)
|
||||
|
||||
self.widget_frame = FrameContainer:new{
|
||||
radius = Size.radius.window,
|
||||
@@ -265,6 +269,7 @@ function DoubleSpinWidget:update(numberpicker_left_value, numberpicker_right_val
|
||||
},
|
||||
self.movable,
|
||||
}
|
||||
self:focusTopLeftWidget()
|
||||
UIManager:setDirty(self, function()
|
||||
return "ui", self.widget_frame.dimen
|
||||
end)
|
||||
@@ -308,4 +313,8 @@ function DoubleSpinWidget:onClose()
|
||||
return true
|
||||
end
|
||||
|
||||
function DoubleSpinWidget:onPress()
|
||||
return self:sendTapEventToFocusedWidget()
|
||||
end
|
||||
|
||||
return DoubleSpinWidget
|
||||
|
||||
@@ -27,7 +27,7 @@ it rather defines an abstract layout.
|
||||
local FocusManager = InputContainer:new{
|
||||
selected = nil, -- defaults to x=1, y=1
|
||||
layout = nil, -- mandatory
|
||||
movement_allowed = { x = true, y = true }
|
||||
movement_allowed = { x = true, y = true },
|
||||
}
|
||||
|
||||
function FocusManager:init()
|
||||
@@ -50,6 +50,9 @@ function FocusManager:init()
|
||||
end
|
||||
|
||||
function FocusManager:onFocusMove(args)
|
||||
if not self.layout then -- allow parent focus manger to handle the event
|
||||
return false
|
||||
end
|
||||
local dx, dy = unpack(args)
|
||||
|
||||
if (dx ~= 0 and not self.movement_allowed.x)
|
||||
@@ -57,7 +60,7 @@ function FocusManager:onFocusMove(args)
|
||||
return true
|
||||
end
|
||||
|
||||
if not self.layout or not self.layout[self.selected.y] or not self.layout[self.selected.y][self.selected.x] then
|
||||
if not self.layout[self.selected.y] or not self.layout[self.selected.y][self.selected.x] then
|
||||
return true
|
||||
end
|
||||
local current_item = self.layout[self.selected.y][self.selected.x]
|
||||
@@ -159,7 +162,64 @@ function FocusManager:_verticalStep(dy)
|
||||
end
|
||||
|
||||
function FocusManager:getFocusItem()
|
||||
if not self.layout then
|
||||
return nil
|
||||
end
|
||||
return self.layout[self.selected.y][self.selected.x]
|
||||
end
|
||||
|
||||
function FocusManager:sendTapEventToFocusedWidget()
|
||||
local focused_widget = self:getFocusItem()
|
||||
if focused_widget then
|
||||
-- center of widget position
|
||||
local point = focused_widget.dimen:copy()
|
||||
point.x = point.x + point.w / 2
|
||||
point.y = point.y + point.h / 2
|
||||
point.w = 0
|
||||
point.h = 0
|
||||
UIManager:sendEvent(Event:new("Gesture", {
|
||||
ges = "tap",
|
||||
pos = point,
|
||||
}))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function FocusManager:mergeLayoutInVertical(child)
|
||||
if not child.layout then
|
||||
return
|
||||
end
|
||||
for _, row in ipairs(child.layout) do
|
||||
table.insert(self.layout, row)
|
||||
end
|
||||
child:disableFocusManagement()
|
||||
end
|
||||
|
||||
function FocusManager:mergeLayoutInHorizontal(child)
|
||||
if not child.layout then
|
||||
return
|
||||
end
|
||||
for i, row in ipairs(child.layout) do
|
||||
local prow = self.layout[i]
|
||||
if not prow then
|
||||
prow = {}
|
||||
self.layout[i] = prow
|
||||
end
|
||||
for _, widget in ipairs(row) do
|
||||
table.insert(prow, widget)
|
||||
end
|
||||
end
|
||||
child:disableFocusManagement()
|
||||
end
|
||||
|
||||
function FocusManager:disableFocusManagement()
|
||||
self.layout = nil -- turn off focus feature
|
||||
end
|
||||
|
||||
--- Container call this method after init to let first widget render in focus style
|
||||
function FocusManager:focusTopLeftWidget()
|
||||
self:onFocusMove({0, 0})
|
||||
end
|
||||
|
||||
return FocusManager
|
||||
|
||||
@@ -73,31 +73,29 @@ function IconButton:update()
|
||||
end
|
||||
|
||||
function IconButton:initGesListener()
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
TapIconButton = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Tap IconButton",
|
||||
self.ges_events = {
|
||||
TapIconButton = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
HoldIconButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold IconButton",
|
||||
doc = "Tap IconButton",
|
||||
},
|
||||
HoldIconButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
HoldReleaseIconButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold_release",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Release IconButton",
|
||||
}
|
||||
doc = "Hold IconButton",
|
||||
},
|
||||
HoldReleaseIconButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold_release",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Release IconButton",
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
function IconButton:onTapIconButton()
|
||||
|
||||
@@ -18,11 +18,11 @@ Example:
|
||||
local Button = require("ui/widget/button")
|
||||
local CenterContainer = require("ui/widget/container/centercontainer")
|
||||
local Device = require("device")
|
||||
local FocusManager = require("ui/widget/focusmanager")
|
||||
local FrameContainer = require("ui/widget/container/framecontainer")
|
||||
local Geom = require("ui/geometry")
|
||||
local Font = require("ui/font")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local InputDialog = require("ui/widget/inputdialog")
|
||||
local Size = require("ui/size")
|
||||
local UIManager = require("ui/uimanager")
|
||||
@@ -32,7 +32,7 @@ local _ = require("gettext")
|
||||
local T = require("ffi/util").template
|
||||
local Screen = Device.screen
|
||||
|
||||
local NumberPickerWidget = InputContainer:new{
|
||||
local NumberPickerWidget = FocusManager:new{
|
||||
spinner_face = Font:getFace("smalltfont"),
|
||||
precision = "%02d",
|
||||
width = nil,
|
||||
@@ -60,6 +60,7 @@ function NumberPickerWidget:init()
|
||||
self.value_index = self.value_index or 1
|
||||
self.value = self.value_table[self.value_index]
|
||||
end
|
||||
self.layout = {}
|
||||
|
||||
-- Widget layout
|
||||
local bordersize = Size.border.default
|
||||
@@ -87,6 +88,7 @@ function NumberPickerWidget:init()
|
||||
self:update()
|
||||
end
|
||||
}
|
||||
table.insert(self.layout, {button_up})
|
||||
local button_down = Button:new{
|
||||
text = "▼",
|
||||
bordersize = bordersize,
|
||||
@@ -110,6 +112,7 @@ function NumberPickerWidget:init()
|
||||
self:update()
|
||||
end
|
||||
}
|
||||
table.insert(self.layout, {button_down})
|
||||
|
||||
local empty_space = VerticalSpan:new{ width = Size.padding.large }
|
||||
|
||||
@@ -207,6 +210,9 @@ function NumberPickerWidget:init()
|
||||
}
|
||||
self.dimen = self.frame:getSize()
|
||||
self[1] = self.frame
|
||||
if Device:hasDPad() then
|
||||
self.key_events.Press = { {"Press"}, doc = "press button" }
|
||||
end
|
||||
UIManager:setDirty(self.show_parent, function()
|
||||
return "ui", self.dimen
|
||||
end)
|
||||
@@ -283,4 +289,8 @@ function NumberPickerWidget:getValue()
|
||||
return self.value, self.value_index
|
||||
end
|
||||
|
||||
function NumberPickerWidget:onPress()
|
||||
return self:sendTapEventToFocusedWidget()
|
||||
end
|
||||
|
||||
return NumberPickerWidget
|
||||
|
||||
@@ -147,7 +147,12 @@ function RadioButtonTable:addHorizontalSep(vspan_before, add_line, vspan_after,
|
||||
end
|
||||
|
||||
function RadioButtonTable:onSelectByKeyPress()
|
||||
self:getFocusItem().callback()
|
||||
local item = self:getFocusItem()
|
||||
if item then
|
||||
item.callback()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function RadioButtonTable:_checkButton(button)
|
||||
|
||||
@@ -380,7 +380,11 @@ end
|
||||
|
||||
function SkimToWidget:onSelectByKeyPress()
|
||||
local item = self:getFocusItem()
|
||||
item.callback()
|
||||
if item then
|
||||
item.callback()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function SkimToWidget:onFirstRowKeyPress(percent)
|
||||
|
||||
@@ -2,11 +2,11 @@ local Blitbuffer = require("ffi/blitbuffer")
|
||||
local ButtonTable = require("ui/widget/buttontable")
|
||||
local CenterContainer = require("ui/widget/container/centercontainer")
|
||||
local Device = require("device")
|
||||
local FocusManager = require("ui/widget/focusmanager")
|
||||
local FrameContainer = require("ui/widget/container/framecontainer")
|
||||
local Geom = require("ui/geometry")
|
||||
local GestureRange = require("ui/gesturerange")
|
||||
local HorizontalGroup = require("ui/widget/horizontalgroup")
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local MovableContainer = require("ui/widget/container/movablecontainer")
|
||||
local NumberPickerWidget = require("ui/widget/numberpickerwidget")
|
||||
local Size = require("ui/size")
|
||||
@@ -18,7 +18,7 @@ local _ = require("gettext")
|
||||
local Screen = Device.screen
|
||||
local T = require("ffi/util").template
|
||||
|
||||
local SpinWidget = InputContainer:new{
|
||||
local SpinWidget = FocusManager:new{
|
||||
title_text = "",
|
||||
info_text = nil,
|
||||
width = nil,
|
||||
@@ -64,9 +64,8 @@ function SpinWidget:init()
|
||||
self.width = math.floor(math.min(self.screen_width, self.screen_height) * self.width_factor)
|
||||
end
|
||||
if Device:hasKeys() then
|
||||
self.key_events = {
|
||||
Close = { {Device.input.group.Back}, doc = "close spin widget" }
|
||||
}
|
||||
self.key_events.Close = { {Device.input.group.Back}, doc = "close spin widget" }
|
||||
self.key_events.Press = { {"Press"}, doc = "press button" }
|
||||
end
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
@@ -87,6 +86,7 @@ function SpinWidget:init()
|
||||
end
|
||||
|
||||
function SpinWidget:update(numberpicker_value, numberpicker_value_index)
|
||||
self.layout = {}
|
||||
local value_widget = NumberPickerWidget:new{
|
||||
show_parent = self,
|
||||
value = numberpicker_value or self.value,
|
||||
@@ -102,6 +102,7 @@ function SpinWidget:update(numberpicker_value, numberpicker_value_index)
|
||||
self:update(value, value_index)
|
||||
end,
|
||||
}
|
||||
self:mergeLayoutInVertical(value_widget)
|
||||
local value_group = HorizontalGroup:new{
|
||||
align = "center",
|
||||
value_widget,
|
||||
@@ -195,8 +196,9 @@ function SpinWidget:update(numberpicker_value, numberpicker_value_index)
|
||||
buttons = buttons,
|
||||
zero_sep = true,
|
||||
show_parent = self,
|
||||
auto_focus_first_button = false,
|
||||
}
|
||||
|
||||
self:mergeLayoutInVertical(ok_cancel_buttons)
|
||||
local vgroup = VerticalGroup:new{
|
||||
align = "left",
|
||||
title_bar,
|
||||
@@ -234,6 +236,7 @@ function SpinWidget:update(numberpicker_value, numberpicker_value_index)
|
||||
},
|
||||
self.movable,
|
||||
}
|
||||
self:focusTopLeftWidget()
|
||||
UIManager:setDirty(self, function()
|
||||
return "ui", self.spin_frame.dimen
|
||||
end)
|
||||
@@ -277,4 +280,8 @@ function SpinWidget:onClose()
|
||||
return true
|
||||
end
|
||||
|
||||
function SpinWidget:onPress()
|
||||
return self:sendTapEventToFocusedWidget()
|
||||
end
|
||||
|
||||
return SpinWidget
|
||||
|
||||
@@ -9,11 +9,11 @@ local BD = require("ui/bidi")
|
||||
local Blitbuffer = require("ffi/blitbuffer")
|
||||
local CenterContainer = require("ui/widget/container/centercontainer")
|
||||
local Device = require("device")
|
||||
local FocusManager = require("ui/widget/focusmanager")
|
||||
local Font = require("ui/font")
|
||||
local Geom = require("ui/geometry")
|
||||
local GestureRange = require("ui/gesturerange")
|
||||
local HorizontalGroup = require("ui/widget/horizontalgroup")
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local FrameContainer = require("ui/widget/container/framecontainer")
|
||||
local Notification = require("ui/widget/notification")
|
||||
local Size = require("ui/size")
|
||||
@@ -29,7 +29,7 @@ local ToggleLabel = TextWidget:new{
|
||||
fgcolor = Blitbuffer.COLOR_BLACK,
|
||||
}
|
||||
|
||||
local ToggleSwitch = InputContainer:new{
|
||||
local ToggleSwitch = FocusManager:new{
|
||||
width = Screen:scaleBySize(216),
|
||||
height = Size.item.height_default,
|
||||
bgcolor = Blitbuffer.COLOR_WHITE, -- unfocused item color
|
||||
@@ -41,6 +41,7 @@ local ToggleSwitch = InputContainer:new{
|
||||
}
|
||||
|
||||
function ToggleSwitch:init()
|
||||
self.layout = {{}}
|
||||
-- Item count per row
|
||||
self.n_pos = math.ceil(#self.toggle / self.row_count)
|
||||
self.position = nil
|
||||
@@ -100,31 +101,33 @@ function ToggleSwitch:init()
|
||||
radius = Size.radius.window,
|
||||
bordersize = item_border_size,
|
||||
padding = 0,
|
||||
focusable = true,
|
||||
focus_border_size = item_border_size,
|
||||
focus_border_color = Blitbuffer.COLOR_BLACK,
|
||||
content,
|
||||
}
|
||||
table.insert(self.toggle_content[math.ceil(i / self.n_pos)], button)
|
||||
table.insert(self.layout[1], button)
|
||||
end
|
||||
self.toggle_frame[1] = self.toggle_content
|
||||
self[1] = self.toggle_frame
|
||||
self.dimen = Geom:new(self.toggle_frame:getSize())
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events = {
|
||||
TapSelect = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Toggle switch",
|
||||
self.ges_events = {
|
||||
TapSelect = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = self.dimen,
|
||||
},
|
||||
HoldSelect = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold switch",
|
||||
doc = "Toggle switch",
|
||||
},
|
||||
HoldSelect = {
|
||||
GestureRange:new{
|
||||
ges = "hold",
|
||||
range = self.dimen,
|
||||
},
|
||||
}
|
||||
end
|
||||
doc = "Hold switch",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function ToggleSwitch:update()
|
||||
@@ -250,14 +253,4 @@ 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
|
||||
|
||||
@@ -963,7 +963,12 @@ function TouchMenu:onBack()
|
||||
end
|
||||
|
||||
function TouchMenu:onPress()
|
||||
self:getFocusItem():handleEvent(Event:new("TapSelect"))
|
||||
local item = self:getFocusItem()
|
||||
if item then
|
||||
item:handleEvent(Event:new("TapSelect"))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
return TouchMenu
|
||||
|
||||
@@ -472,8 +472,12 @@ function VirtualKeyPopup:onCloseWidget()
|
||||
end
|
||||
|
||||
function VirtualKeyPopup:onPressKey()
|
||||
self:getFocusItem():handleEvent(Event:new("TapSelect"))
|
||||
return true
|
||||
local item = self:getFocusItem()
|
||||
if item then
|
||||
item:handleEvent(Event:new("TapSelect"))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VirtualKeyPopup:init()
|
||||
@@ -848,8 +852,12 @@ function VirtualKeyboard:onClose()
|
||||
end
|
||||
|
||||
function VirtualKeyboard:onPressKey()
|
||||
self:getFocusItem():handleEvent(Event:new("TapSelect"))
|
||||
return true
|
||||
local item = self:getFocusItem()
|
||||
if item then
|
||||
item:handleEvent(Event:new("TapSelect"))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VirtualKeyboard:_refresh(want_flash, fullscreen)
|
||||
|
||||
Reference in New Issue
Block a user