2017-11-04 14:31:41 +00:00
|
|
|
|
local Blitbuffer = require("ffi/blitbuffer")
|
|
|
|
|
local Button = require("ui/widget/button")
|
|
|
|
|
local Device = require("device")
|
2022-01-25 00:32:46 +00:00
|
|
|
|
local FocusManager = require("ui/widget/focusmanager")
|
2017-11-04 14:31:41 +00:00
|
|
|
|
local Geom = require("ui/geometry")
|
|
|
|
|
local HorizontalGroup = require("ui/widget/horizontalgroup")
|
2019-09-26 09:46:23 +00:00
|
|
|
|
local HorizontalSpan = require("ui/widget/horizontalspan")
|
2017-11-04 14:31:41 +00:00
|
|
|
|
local FrameContainer = require("ui/widget/container/framecontainer")
|
|
|
|
|
local Size = require("ui/size")
|
|
|
|
|
local UIManager = require("ui/uimanager")
|
|
|
|
|
local _ = require("gettext")
|
|
|
|
|
local Screen = Device.screen
|
|
|
|
|
|
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 00:14:48 +00:00
|
|
|
|
local ButtonProgressWidget = FocusManager:extend{
|
2017-11-04 14:31:41 +00:00
|
|
|
|
width = Screen:scaleBySize(216),
|
|
|
|
|
height = Size.item.height_default,
|
2019-01-15 19:39:33 +00:00
|
|
|
|
padding = Size.padding.small,
|
2017-11-04 14:31:41 +00:00
|
|
|
|
font_face = "cfont",
|
|
|
|
|
font_size = 16,
|
|
|
|
|
enabled = true,
|
|
|
|
|
num_buttons = 2,
|
|
|
|
|
position = 1,
|
2019-03-15 22:15:05 +00:00
|
|
|
|
default_position = nil,
|
2019-03-02 11:24:15 +00:00
|
|
|
|
thin_grey_style = false, -- default to black
|
2019-05-01 00:09:01 +00:00
|
|
|
|
fine_tune = false, -- no -/+ buttons on the extremities by default
|
2019-09-14 14:30:25 +00:00
|
|
|
|
more_options = false, -- no "⋮" button
|
2017-11-04 14:31:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ButtonProgressWidget:init()
|
2022-01-25 00:32:46 +00:00
|
|
|
|
self.current_button_index = self.position
|
|
|
|
|
|
2017-11-04 14:31:41 +00:00
|
|
|
|
self.buttonprogress_frame = FrameContainer:new{
|
|
|
|
|
background = Blitbuffer.COLOR_WHITE,
|
2019-03-14 19:58:45 +00:00
|
|
|
|
color = Blitbuffer.COLOR_DARK_GRAY,
|
2017-11-04 14:31:41 +00:00
|
|
|
|
radius = Size.radius.window,
|
|
|
|
|
bordersize = 0,
|
2019-01-15 19:39:33 +00:00
|
|
|
|
padding = self.padding,
|
2017-11-04 14:31:41 +00:00
|
|
|
|
dim = not self.enabled,
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-26 09:46:23 +00:00
|
|
|
|
|
2017-11-04 14:31:41 +00:00
|
|
|
|
self.buttonprogress_content = HorizontalGroup:new{}
|
2019-09-26 09:46:23 +00:00
|
|
|
|
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
|
2017-11-04 14:31:41 +00:00
|
|
|
|
self:update()
|
2022-01-25 00:32:46 +00:00
|
|
|
|
if self.fine_tune then
|
|
|
|
|
self.current_button_index = self.current_button_index + 1
|
|
|
|
|
end
|
2017-11-04 14:31:41 +00:00
|
|
|
|
self.buttonprogress_frame[1] = self.buttonprogress_content
|
|
|
|
|
self[1] = self.buttonprogress_frame
|
|
|
|
|
self.dimen = Geom:new(self.buttonprogress_frame:getSize())
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function ButtonProgressWidget:update()
|
2022-01-25 00:32:46 +00:00
|
|
|
|
self.layout = {{}}
|
|
|
|
|
|
2017-11-04 14:31:41 +00:00
|
|
|
|
self.buttonprogress_content:clear()
|
|
|
|
|
local button_margin = Size.margin.tiny
|
|
|
|
|
local button_padding = Size.padding.button
|
2019-03-02 11:24:15 +00:00
|
|
|
|
local button_bordersize = self.thin_grey_style and Size.border.thin or Size.border.button
|
2019-05-01 00:09:01 +00:00
|
|
|
|
local buttons_count = self.num_buttons
|
2019-09-26 09:46:23 +00:00
|
|
|
|
local span_count = 0
|
2019-05-01 00:09:01 +00:00
|
|
|
|
if self.fine_tune then
|
2019-09-26 09:46:23 +00:00
|
|
|
|
buttons_count = buttons_count + 2
|
|
|
|
|
span_count = 2
|
2019-05-01 00:09:01 +00:00
|
|
|
|
end
|
2019-09-14 14:30:25 +00:00
|
|
|
|
if self.more_options then
|
|
|
|
|
buttons_count = buttons_count + 1
|
2019-09-26 09:46:23 +00:00
|
|
|
|
span_count = span_count + 1
|
2019-09-14 14:30:25 +00:00
|
|
|
|
end
|
2019-09-26 09:46:23 +00:00
|
|
|
|
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
|
2019-05-01 00:09:01 +00:00
|
|
|
|
|
|
|
|
|
-- Minus button on the left
|
|
|
|
|
if self.fine_tune then
|
2019-09-26 09:46:23 +00:00
|
|
|
|
button_width_to_add = button_width_to_add + button_width_adjust
|
|
|
|
|
local margin = button_margin
|
2019-05-01 00:09:01 +00:00
|
|
|
|
local extra_border_size = 0
|
|
|
|
|
local button = Button:new{
|
2020-12-02 15:21:52 +00:00
|
|
|
|
text = "−",
|
2019-05-01 00:09:01 +00:00
|
|
|
|
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,
|
2022-03-22 19:38:23 +00:00
|
|
|
|
hold_callback = self.hold_callback and function() self.hold_callback("-") end,
|
2019-05-01 00:09:01 +00:00
|
|
|
|
}
|
|
|
|
|
if self.thin_grey_style then
|
|
|
|
|
button.frame.color = Blitbuffer.COLOR_DARK_GRAY
|
|
|
|
|
end
|
|
|
|
|
table.insert(self.buttonprogress_content, button)
|
2022-01-25 00:32:46 +00:00
|
|
|
|
table.insert(self.layout[1], button)
|
2019-09-26 09:46:23 +00:00
|
|
|
|
table.insert(self.buttonprogress_content, self.horizontal_span)
|
2019-05-01 00:09:01 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Actual progress bar
|
2017-11-04 14:31:41 +00:00
|
|
|
|
for i = 1, self.num_buttons do
|
2019-09-26 09:46:23 +00:00
|
|
|
|
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
|
2019-03-02 11:24:15 +00:00
|
|
|
|
local highlighted = i <= self.position
|
2019-03-15 22:15:05 +00:00
|
|
|
|
local is_default = i == self.default_position
|
2019-03-02 11:24:15 +00:00
|
|
|
|
local margin = button_margin
|
|
|
|
|
if self.thin_grey_style and highlighted then
|
|
|
|
|
margin = 0 -- moved outside button so it's not inverted
|
2017-11-04 14:31:41 +00:00
|
|
|
|
end
|
2019-03-15 22:15:05 +00:00
|
|
|
|
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
|
2017-11-04 14:31:41 +00:00
|
|
|
|
local button = Button:new{
|
|
|
|
|
text = "",
|
|
|
|
|
radius = 0,
|
2019-03-02 11:24:15 +00:00
|
|
|
|
margin = margin,
|
2017-11-04 14:31:41 +00:00
|
|
|
|
padding = button_padding,
|
2019-03-15 22:15:05 +00:00
|
|
|
|
bordersize = button_bordersize + extra_border_size,
|
2017-11-04 14:31:41 +00:00
|
|
|
|
enabled = true,
|
2019-09-26 09:46:23 +00:00
|
|
|
|
width = real_button_width - 2*extra_border_size,
|
2019-03-02 11:24:15 +00:00
|
|
|
|
preselect = highlighted,
|
2017-11-04 14:31:41 +00:00
|
|
|
|
text_font_face = self.font_face,
|
|
|
|
|
text_font_size = self.font_size,
|
|
|
|
|
callback = function()
|
|
|
|
|
self.callback(i)
|
|
|
|
|
self.position = i
|
|
|
|
|
self:update()
|
|
|
|
|
end,
|
2022-01-25 00:32:46 +00:00
|
|
|
|
no_focus = highlighted,
|
2022-03-22 19:38:23 +00:00
|
|
|
|
hold_callback = self.hold_callback and function() self.hold_callback(i) end,
|
2017-11-04 14:31:41 +00:00
|
|
|
|
}
|
2019-03-02 11:24:15 +00:00
|
|
|
|
if self.thin_grey_style then
|
2019-03-15 22:15:05 +00:00
|
|
|
|
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
|
2019-03-02 11:24:15 +00:00
|
|
|
|
if highlighted then
|
2019-03-14 21:09:55 +00:00
|
|
|
|
-- 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()
|
2019-03-02 11:24:15 +00:00
|
|
|
|
button = FrameContainer:new{ -- add margin back
|
|
|
|
|
margin = button_margin,
|
|
|
|
|
padding = 0,
|
|
|
|
|
bordersize = 0,
|
2022-01-25 00:32:46 +00:00
|
|
|
|
focusable = true,
|
|
|
|
|
focus_border_size = Size.border.thin,
|
2019-03-02 11:24:15 +00:00
|
|
|
|
button,
|
|
|
|
|
}
|
|
|
|
|
end
|
2019-05-01 00:09:01 +00:00
|
|
|
|
end
|
|
|
|
|
table.insert(self.buttonprogress_content, button)
|
2022-01-25 00:32:46 +00:00
|
|
|
|
table.insert(self.layout[1], button)
|
2019-05-01 00:09:01 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Plus button on the right
|
|
|
|
|
if self.fine_tune then
|
2019-09-26 09:46:23 +00:00
|
|
|
|
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
|
2019-05-01 00:09:01 +00:00
|
|
|
|
local extra_border_size = 0
|
|
|
|
|
local button = Button:new{
|
2020-12-20 19:47:40 +00:00
|
|
|
|
text = "+",
|
2019-05-01 00:09:01 +00:00
|
|
|
|
radius = 0,
|
|
|
|
|
margin = margin,
|
|
|
|
|
padding = button_padding,
|
|
|
|
|
bordersize = button_bordersize + extra_border_size,
|
|
|
|
|
enabled = true,
|
2019-09-26 09:46:23 +00:00
|
|
|
|
width = real_button_width - 2*extra_border_size,
|
2019-05-01 00:09:01 +00:00
|
|
|
|
preselect = false,
|
|
|
|
|
text_font_face = self.font_face,
|
|
|
|
|
text_font_size = self.font_size,
|
|
|
|
|
callback = function()
|
|
|
|
|
self.callback("+")
|
|
|
|
|
self:update()
|
|
|
|
|
end,
|
2022-03-22 19:38:23 +00:00
|
|
|
|
hold_callback = self.hold_callback and function() self.hold_callback("+") end,
|
2019-05-01 00:09:01 +00:00
|
|
|
|
}
|
2022-01-25 00:32:46 +00:00
|
|
|
|
|
2019-05-01 00:09:01 +00:00
|
|
|
|
if self.thin_grey_style then
|
|
|
|
|
button.frame.color = Blitbuffer.COLOR_DARK_GRAY
|
2019-09-14 14:30:25 +00:00
|
|
|
|
end
|
2019-09-26 09:46:23 +00:00
|
|
|
|
table.insert(self.buttonprogress_content, self.horizontal_span)
|
2019-09-14 14:30:25 +00:00
|
|
|
|
table.insert(self.buttonprogress_content, button)
|
2022-01-25 00:32:46 +00:00
|
|
|
|
table.insert(self.layout[1], button)
|
2019-09-14 14:30:25 +00:00
|
|
|
|
end
|
|
|
|
|
-- More option button on the right
|
|
|
|
|
if self.more_options then
|
2019-09-26 09:46:23 +00:00
|
|
|
|
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
|
2019-09-14 14:30:25 +00:00
|
|
|
|
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,
|
2019-09-26 09:46:23 +00:00
|
|
|
|
width = real_button_width - 2*extra_border_size,
|
2019-09-14 14:30:25 +00:00
|
|
|
|
preselect = false,
|
|
|
|
|
text_font_face = self.font_face,
|
|
|
|
|
text_font_size = self.font_size,
|
|
|
|
|
callback = function()
|
|
|
|
|
self.callback("⋮")
|
|
|
|
|
self:update()
|
|
|
|
|
end,
|
2022-03-22 19:38:23 +00:00
|
|
|
|
hold_callback = self.hold_callback and function() self.hold_callback("⋮") end,
|
2019-09-14 14:30:25 +00:00
|
|
|
|
}
|
|
|
|
|
if self.thin_grey_style then
|
|
|
|
|
button.frame.color = Blitbuffer.COLOR_DARK_GRAY
|
2019-03-02 11:24:15 +00:00
|
|
|
|
end
|
2019-09-26 09:46:23 +00:00
|
|
|
|
table.insert(self.buttonprogress_content, self.horizontal_span)
|
2017-11-04 14:31:41 +00:00
|
|
|
|
table.insert(self.buttonprogress_content, button)
|
2022-01-25 00:32:46 +00:00
|
|
|
|
table.insert(self.layout[1], button)
|
2017-11-04 14:31:41 +00:00
|
|
|
|
end
|
|
|
|
|
|
2022-03-04 20:20:00 +00:00
|
|
|
|
self:refocusWidget()
|
2022-03-14 18:56:18 +00:00
|
|
|
|
UIManager:setDirty(self.show_parent, function()
|
2017-11-04 14:31:41 +00:00
|
|
|
|
return "ui", self.dimen
|
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
|
2019-03-15 22:15:05 +00:00
|
|
|
|
function ButtonProgressWidget:setPosition(position, default_position)
|
2017-11-04 14:31:41 +00:00
|
|
|
|
self.position = position
|
2019-03-15 22:15:05 +00:00
|
|
|
|
self.default_position = default_position
|
2017-11-04 14:31:41 +00:00
|
|
|
|
self:update()
|
|
|
|
|
end
|
|
|
|
|
|
2018-09-13 11:49:23 +00:00
|
|
|
|
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
|
|
|
|
|
|
2017-11-04 14:31:41 +00:00
|
|
|
|
return ButtonProgressWidget
|