2
0
mirror of https://github.com/koreader/koreader synced 2024-11-13 19:11:25 +00:00
koreader/frontend/ui/widget/buttonprogresswidget.lua
2019-09-26 11:46:23 +02:00

284 lines
10 KiB
Lua

local Blitbuffer = require("ffi/blitbuffer")
local Button = require("ui/widget/button")
local Device = require("device")
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{
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.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()
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.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,
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, 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 = true,
hold_callback = 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,
button,
}
end
end
table.insert(self.buttonprogress_content, 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,
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)
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,
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)
end
UIManager:setDirty(self.show_parrent, 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: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()
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