2
0
mirror of https://github.com/koreader/koreader synced 2024-11-18 03:25:46 +00:00
koreader/frontend/ui/widget/buttonprogresswidget.lua
NiLuJe fadee1f5dc
Clarify our OOP semantics across the codebase (#9586)
Basically:

* Use `extend` for class definitions
* Use `new` for object instantiations

That includes some minor code cleanups along the way:

* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
  * ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 02:14:48 +02:00

278 lines
10 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 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 = FocusManager:extend{
width = Screen:scaleBySize(216),
height = Size.item.height_default,
padding = Size.padding.small,
font_face = "cfont",
font_size = 16,
enabled = true,
num_buttons = 2,
position = 1,
default_position = nil,
thin_grey_style = false, -- default to black
fine_tune = false, -- no -/+ buttons on the extremities by default
more_options = false, -- no "⋮" button
}
function ButtonProgressWidget:init()
self.current_button_index = self.position
self.buttonprogress_frame = FrameContainer:new{
background = Blitbuffer.COLOR_WHITE,
color = Blitbuffer.COLOR_DARK_GRAY,
radius = Size.radius.window,
bordersize = 0,
padding = self.padding,
dim = not self.enabled,
}
self.buttonprogress_content = HorizontalGroup:new{}
self.horizontal_span_width = 0
if self.fine_tune or self.more_options then
self.horizontal_span = HorizontalSpan:new{
width = Size.margin.fine_tune
}
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
local button_bordersize = self.thin_grey_style and Size.border.thin or Size.border.button
local buttons_count = self.num_buttons
local span_count = 0
if self.fine_tune then
buttons_count = buttons_count + 2
span_count = 2
end
if self.more_options then
buttons_count = buttons_count + 1
span_count = span_count + 1
end
local button_width_real = (self.width - span_count * self.horizontal_span_width) / buttons_count - 2*button_padding - 2*button_margin - 2*button_bordersize
local button_width = math.floor(button_width_real)
local button_width_adjust = button_width_real - button_width
local button_width_to_add = 0
-- Minus button on the left
if self.fine_tune then
button_width_to_add = button_width_to_add + button_width_adjust
local margin = button_margin
local extra_border_size = 0
local button = Button:new{
text = "",
radius = 0,
margin = margin,
padding = button_padding,
bordersize = button_bordersize + extra_border_size,
enabled = true,
width = button_width - 2*extra_border_size,
preselect = false,
text_font_face = self.font_face,
text_font_size = self.font_size,
callback = function()
self.callback("-")
self:update()
end,
hold_callback = self.hold_callback and function() self.hold_callback("-") end,
}
if self.thin_grey_style then
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
-- Actual progress bar
for i = 1, self.num_buttons do
button_width_to_add = button_width_to_add + button_width_adjust
local real_button_width = button_width
if button_width_to_add >= 1 then
-- One pixel wider to better align the entire widget
real_button_width = button_width + math.floor(button_width_to_add)
button_width_to_add = button_width_to_add - math.floor(button_width_to_add)
end
local highlighted = i <= self.position
local is_default = i == self.default_position
local margin = button_margin
if self.thin_grey_style and highlighted then
margin = 0 -- moved outside button so it's not inverted
end
local extra_border_size = 0
if not self.thin_grey_style and is_default then
-- make the border a bit bigger on the default button
extra_border_size = Size.border.thin
end
local button = Button:new{
text = "",
radius = 0,
margin = margin,
padding = button_padding,
bordersize = button_bordersize + extra_border_size,
enabled = true,
width = real_button_width - 2*extra_border_size,
preselect = highlighted,
text_font_face = self.font_face,
text_font_size = self.font_size,
callback = function()
self.callback(i)
self.position = i
self:update()
end,
no_focus = highlighted,
hold_callback = self.hold_callback and function() self.hold_callback(i) end,
}
if self.thin_grey_style then
if is_default then
-- use a black border as a discreet visual hint
button.frame.color = Blitbuffer.COLOR_BLACK
else
-- otherwise, gray border, same as the filled
-- button, so looking as if no border
button.frame.color = Blitbuffer.COLOR_DARK_GRAY
end
if highlighted then
-- The button and its frame background will be inverted,
-- so invert the color we want so it gets inverted back
button.frame.background = Blitbuffer.COLOR_DARK_GRAY:invert()
button = FrameContainer:new{ -- add margin back
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
if self.fine_tune then
button_width_to_add = button_width_to_add + button_width_adjust
local real_button_width = button_width
if button_width_to_add >= 1 then
-- One pixel wider to better align the entire widget
real_button_width = button_width + math.floor(button_width_to_add)
button_width_to_add = button_width_to_add - math.floor(button_width_to_add)
end
local margin = button_margin
local extra_border_size = 0
local button = Button:new{
text = "",
radius = 0,
margin = margin,
padding = button_padding,
bordersize = button_bordersize + extra_border_size,
enabled = true,
width = real_button_width - 2*extra_border_size,
preselect = false,
text_font_face = self.font_face,
text_font_size = self.font_size,
callback = function()
self.callback("+")
self:update()
end,
hold_callback = self.hold_callback and 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
button_width_to_add = button_width_to_add + button_width_adjust
local real_button_width = button_width
if button_width_to_add >= 1 then
-- One pixel wider to better align the entire widget
real_button_width = button_width + math.floor(button_width_to_add)
end
local margin = button_margin
local extra_border_size = 0
local button = Button:new{
text = "",
radius = 0,
margin = margin,
padding = button_padding,
bordersize = button_bordersize + extra_border_size,
enabled = true,
width = real_button_width - 2*extra_border_size,
preselect = false,
text_font_face = self.font_face,
text_font_size = self.font_size,
callback = function()
self.callback("")
self:update()
end,
hold_callback = self.hold_callback and 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
self:refocusWidget()
UIManager:setDirty(self.show_parent, function()
return "ui", self.dimen
end)
end
function ButtonProgressWidget:setPosition(position, default_position)
self.position = position
self.default_position = default_position
self:update()
end
function ButtonProgressWidget:onTapSelect(arg, gev)
if gev == nil then
self:circlePosition()
end
end
function ButtonProgressWidget:circlePosition()
if self.position then
self.position = self.position+1
if self.position > self.num_buttons then
self.position = 1
end
self.callback(self.position)
self:update()
end
end
return ButtonProgressWidget