mirror of
https://github.com/koreader/koreader
synced 2024-11-04 12:00:25 +00:00
3060dc81af
* Wherever possible, do an actual dumb invert on the Screen BB instead of repainting the widget, *then* inverting it (which is what the "invert" flag does). * Instead of playing with nextTick/tickAfterNext delays, explicitly fence stuff with forceRePaint * And, in the few cases where said Mk. 7 quirk kicks in, make the fences more marked by using a well-placed WAIT_FOR_UPDATE_COMPLETE * Fix an issue in Button where show/hide & enable/disable where actually all toggles, which meant that duplicate calls or timing issues would do the wrong thing. (This broke dimming some icons, and mistakenly dropped the background from FM chevrons, for example). * Speaking of, fix Button's hide/show to actually restore the background properly (there was a stupid typo in the variable name) * Still in Button, fix the insanity of the double repaint on rounded buttons. Turns out it made sense, after all (and was related to said missing background, and bad interaction with invert & text with no background). * KeyValuePage suffered from a similar issue with broken highlights (all black) because of missing backgrounds. * In ConfigDialog, only instanciate IconButtons once (because every tab switch causes a full instantiation; and the initial display implies a full instanciation and an initial tab switch). Otherwise, both instances linger, and catch taps, and as such, double highlights. * ConfigDialog: Restore the "don't repaint ReaderUI" when switching between similarly sized tabs (re #6131). I never could reproduce that on eInk, and I can't now on the emulator, so I'm assuming @poire-z fixed it during the swap to SVG icons. * KeyValuePage: Only instanciate Buttons once (again, this is a widget that goes through a full init every page). Again, caused highlight/dimming issues because buttons were stacked. * Menu: Ditto. * TouchMenu: Now home of the gnarliest unhilight heuristics, because of the sheer amount of different things that can happen (and/or thanks to stuff not flagged covers_fullscreen properly ;p). * Bump base https://github.com/koreader/koreader-base/pull/1280 https://github.com/koreader/koreader-base/pull/1282 https://github.com/koreader/koreader-base/pull/1283 https://github.com/koreader/koreader-base/pull/1284 * Bump android-luajit-launcher https://github.com/koreader/android-luajit-launcher/pull/284 https://github.com/koreader/android-luajit-launcher/pull/285 https://github.com/koreader/android-luajit-launcher/pull/286 https://github.com/koreader/android-luajit-launcher/pull/287
151 lines
4.9 KiB
Lua
151 lines
4.9 KiB
Lua
--[[--
|
|
Button with a big icon image! Designed for touch devices.
|
|
--]]
|
|
|
|
local Device = require("device")
|
|
local HorizontalGroup = require("ui/widget/horizontalgroup")
|
|
local HorizontalSpan = require("ui/widget/horizontalspan")
|
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
|
local IconWidget = require("ui/widget/iconwidget")
|
|
local GestureRange = require("ui/gesturerange")
|
|
local UIManager = require("ui/uimanager")
|
|
local VerticalGroup = require("ui/widget/verticalgroup")
|
|
local VerticalSpan = require("ui/widget/verticalspan")
|
|
local Screen = Device.screen
|
|
|
|
local IconButton = InputContainer:new{
|
|
icon = "notice-warning",
|
|
dimen = nil,
|
|
-- show_parent is used for UIManager:setDirty, so we can trigger repaint
|
|
show_parent = nil,
|
|
width = Screen:scaleBySize(DGENERIC_ICON_SIZE), -- our icons are square
|
|
height = Screen:scaleBySize(DGENERIC_ICON_SIZE),
|
|
padding = 0,
|
|
padding_top = nil,
|
|
padding_right = nil,
|
|
padding_bottom = nil,
|
|
padding_left = nil,
|
|
enabled = true,
|
|
callback = nil,
|
|
}
|
|
|
|
function IconButton:init()
|
|
self.image = IconWidget:new{
|
|
icon = self.icon,
|
|
width = self.width,
|
|
height = self.height,
|
|
}
|
|
|
|
self.show_parent = self.show_parent or self
|
|
|
|
self.horizontal_group = HorizontalGroup:new{}
|
|
table.insert(self.horizontal_group, HorizontalSpan:new{})
|
|
table.insert(self.horizontal_group, self.image)
|
|
table.insert(self.horizontal_group, HorizontalSpan:new{})
|
|
|
|
self.button = VerticalGroup:new{}
|
|
table.insert(self.button, VerticalSpan:new{})
|
|
table.insert(self.button, self.horizontal_group)
|
|
table.insert(self.button, VerticalSpan:new{})
|
|
|
|
self[1] = self.button
|
|
self:update()
|
|
end
|
|
|
|
function IconButton:update()
|
|
if not self.padding_top then self.padding_top = self.padding end
|
|
if not self.padding_right then self.padding_right = self.padding end
|
|
if not self.padding_bottom then self.padding_bottom = self.padding end
|
|
if not self.padding_left then self.padding_left = self.padding end
|
|
|
|
self.horizontal_group[1].width = self.padding_left
|
|
self.horizontal_group[3].width = self.padding_right
|
|
self.dimen = self.image:getSize()
|
|
self.dimen.w = self.dimen.w + self.padding_left+self.padding_right
|
|
|
|
self.button[1].width = self.padding_top
|
|
self.button[3].width = self.padding_bottom
|
|
self.dimen.h = self.dimen.h + self.padding_top+self.padding_bottom
|
|
self:initGesListener()
|
|
end
|
|
|
|
function IconButton:initGesListener()
|
|
if Device:isTouchDevice() then
|
|
self.ges_events = {
|
|
TapIconButton = {
|
|
GestureRange:new{
|
|
ges = "tap",
|
|
range = self.dimen,
|
|
},
|
|
doc = "Tap IconButton",
|
|
},
|
|
HoldIconButton = {
|
|
GestureRange:new{
|
|
ges = "hold",
|
|
range = self.dimen,
|
|
},
|
|
doc = "Hold IconButton",
|
|
}
|
|
}
|
|
end
|
|
end
|
|
|
|
function IconButton:onTapIconButton()
|
|
if not self.callback then return end
|
|
if G_reader_settings:isFalse("flash_ui") then
|
|
self.callback()
|
|
else
|
|
self.image.invert = true
|
|
-- For ConfigDialog icons, we can't avoid that initial repaint...
|
|
UIManager:widgetInvert(self.image, self.dimen.x + self.padding_left, self.dimen.y + self.padding_top)
|
|
UIManager:setDirty(nil, function()
|
|
return "fast", self.dimen
|
|
end)
|
|
|
|
-- Force the repaint *now*, so we don't have to delay the callback to see the invert...
|
|
UIManager:forceRePaint()
|
|
self.callback()
|
|
UIManager:forceRePaint()
|
|
--UIManager:waitForVSync()
|
|
|
|
-- If the callback closed our parent (which may not always be the top-level widget, or even *a* window-level widget; e.g., the Home/+ buttons in the FM), we're done
|
|
if UIManager:getTopWidget() == self.show_parent or UIManager:isSubwidgetShown(self.show_parent) then
|
|
self.image.invert = false
|
|
UIManager:widgetInvert(self.image, self.dimen.x + self.padding_left, self.dimen.y + self.padding_top)
|
|
UIManager:setDirty(nil, function()
|
|
return "fast", self.dimen
|
|
end)
|
|
--UIManager:forceRePaint()
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function IconButton:onHoldIconButton()
|
|
if self.enabled and self.hold_callback then
|
|
self.hold_callback()
|
|
elseif self.hold_input then
|
|
self:onInput(self.hold_input)
|
|
elseif type(self.hold_input_func) == "function" then
|
|
self:onInput(self.hold_input_func())
|
|
elseif self.hold_callback == nil then return end
|
|
return true
|
|
end
|
|
|
|
function IconButton:onFocus()
|
|
--quick and dirty, need better way to show focus
|
|
self.image.invert = true
|
|
return true
|
|
end
|
|
|
|
function IconButton:onUnfocus()
|
|
self.image.invert = false
|
|
return true
|
|
end
|
|
|
|
function IconButton:onTapSelect()
|
|
self:onTapIconButton()
|
|
end
|
|
|
|
return IconButton
|