2
0
mirror of https://github.com/koreader/koreader synced 2024-10-31 21:20:20 +00:00
koreader/frontend/ui/widget/container/widgetcontainer.lua
2016-12-11 12:20:59 -08:00

120 lines
3.2 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")
if require("device"):isAndroid() then
require("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
--[[--
Delete all child widgets
]]
function WidgetContainer:clear()
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, othewise 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
function WidgetContainer:free()
for _, widget in ipairs(self) do
if widget.free then widget:free() end
end
end
return WidgetContainer