Files
koreader-mirror/frontend/ui/widget/container/custompositioncontainer.lua

81 lines
2.9 KiB
Lua

--[[
CustomPositionContainer contains its content (1 widget) at a custom position within its own
dimensions
--]]
local Blitbuffer = require("ffi/blitbuffer")
local Screen = require("device").screen
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local CustomPositionContainer = WidgetContainer:extend{
vertical_position = 0.5, -- 0.0 = topmost, 1.0 = bottommost
horizontal_position = 0.5, -- 0.0 = leftmost, 1.0 = rightmost
widget = nil,
alpha = nil, -- 1 = fully opaque, 0 = fully transparent
compose_bb = nil, -- cache for alpha composition
}
function CustomPositionContainer:paintTo(bb, x, y)
if not self.widget then return end
local content_size = self.widget:getSize()
local container_w = (self.dimen and self.dimen.w) or Screen:getWidth()
local container_h = (self.dimen and self.dimen.h) or Screen:getHeight()
-- calculate desired position
local desired_x = math.floor((container_w - content_size.w) * self.horizontal_position)
local desired_y = math.floor((container_h - content_size.h) * self.vertical_position)
-- clamp to container bounds
local x_pos = x + math.max(0, math.min(desired_x, container_w - content_size.w))
local y_pos = y + math.max(0, math.min(desired_y, container_h - content_size.h))
-- Handle transparency similar to MovableContainer
if self.alpha and self.alpha < 1.0 then
-- Create/recreate compose canvas if needed
if not self.compose_bb
or self.compose_bb:getWidth() ~= bb:getWidth()
or self.compose_bb:getHeight() ~= bb:getHeight()
then
if self.compose_bb then
self.compose_bb:free()
end
self.compose_bb = Blitbuffer.new(bb:getWidth(), bb:getHeight(), bb:getType())
end
-- Copy the relevant portion of the background from the target buffer to compose buffer
-- This gives us the actual background (cover image, solid color, etc.) so rounded corners
-- don't show artifacts.
self.compose_bb:blitFrom(bb, x_pos, y_pos, x_pos, y_pos, content_size.w, content_size.h)
-- Paint widget to compose canvas
self.widget:paintTo(self.compose_bb, x_pos, y_pos)
-- Blit with alpha to target
bb:addblitFrom(self.compose_bb, x_pos, y_pos, x_pos, y_pos, content_size.w, content_size.h, self.alpha)
else
-- No alpha, direct paint
self.widget:paintTo(bb, x_pos, y_pos)
end
end
function CustomPositionContainer:onCloseWidget()
if self.compose_bb then
self.compose_bb:free()
self.compose_bb = nil
end
end
function CustomPositionContainer:getSize()
if self.dimen then
return self.dimen
end
-- return widget size if no dimen set
if self.widget then
return self.widget:getSize()
end
return { w = 0, h = 0 }
end
return CustomPositionContainer