You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koreader/frontend/ui/widget/container/widgetcontainer.lua

132 lines
3.7 KiB
Lua

--[[--
WidgetContainer is a container for one or multiple Widgets. It is the base
class for all the container widgets.
Child widgets are stored in WidgetContainer as conventional array items:
WidgetContainer:new{
ChildWidgetFoo:new{},
ChildWidgetBar:new{},
...
}
It handles event propagation and painting (with different alignments) for its children.
]]
local Geom = require("ui/geometry")
local Widget = require("ui/widget/widget")
local Device = require("device")
if Device.should_restrict_JIT then
jit.off(true, true)
end
local WidgetContainer = Widget:new()
function WidgetContainer:init()
if self.dimen then
if self.initDimen then
self:initDimen()
else
if not self.dimen.w then
self.dimen.w = self[1]:getSize().w
end
if not self.dimen.h then
self.dimen.h = self[1]:getSize().h
end
end
end
end
function WidgetContainer:getSize()
if self.dimen then
-- fixed size
return self.dimen
elseif self[1] then
-- return size of first child widget
return self[1]:getSize()
else
return Geom:new{ w = 0, h = 0 }
end
end
--[[--
Deletes all child widgets.
]]
function WidgetContainer:clear(skip_free)
-- HorizontalGroup & VerticalGroup call us after already having called free,
-- so allow skipping this one ;).
if not skip_free then
-- Make sure we free 'em before orphaning them...
self:free()
end
while table.remove(self) do end
end
function WidgetContainer:paintTo(bb, x, y)
-- default to pass request to first child widget
if self[1] then
x = x + (self.dimen.x or 0)
y = y + (self.dimen.y or 0)
if self.align == "top" then
local contentSize = self[1]:getSize()
self[1]:paintTo(bb,
x + math.floor((self.dimen.w - contentSize.w)/2), y)
elseif self.align == "bottom" then
local contentSize = self[1]:getSize()
self[1]:paintTo(bb,
x + math.floor((self.dimen.w - contentSize.w)/2),
y + (self.dimen.h - contentSize.h))
elseif self.align == "center" then
local contentSize = self[1]:getSize()
self[1]:paintTo(bb,
x + math.floor((self.dimen.w - contentSize.w)/2),
y + math.floor((self.dimen.h - contentSize.h)/2))
else
return self[1]:paintTo(bb, x, y)
end
end
end
function WidgetContainer:propagateEvent(event)
-- propagate to children
for _, widget in ipairs(self) do
if widget:handleEvent(event) then
-- stop propagating when an event handler returns true
return true
end
end
return false
end
--[[--
WidgetContainer will pass event to its children by calling their handleEvent
methods. If no child consumes the event (by returning true), it will try
to react to the event by itself.
@tparam ui.event.Event event
@treturn bool true if event is consumed, otherwise false. A consumed event will
not be sent to other widgets.
]]
function WidgetContainer:handleEvent(event)
if not self:propagateEvent(event) then
-- call our own standard event handler
return Widget.handleEvent(self, event)
else
return true
end
end
-- Honor full for TextBoxWidget's benefit...
function WidgetContainer:free(full)
for _, widget in ipairs(self) do
if widget.free then
--print("WidgetContainer: Calling free for widget", debug.getinfo(widget.free, "S").short_src, widget, "from", debug.getinfo(self.free, "S").short_src, self)
widget:free(full)
end
end
end
return WidgetContainer