From 92bce18537a79f65899a6230d4fa04657d9e9f4b Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Sun, 9 Dec 2012 01:18:40 +0800 Subject: [PATCH] bug fix in InputContainer and menu widget * add _init callback for all widgets, which is used for base widget initialization. see comment in Widget:new(o) for more information. * new ges_events and key_events are created for each InputContainer widget, previously, they shared the same tables. * remove hardcoded menu widget dimen * recalculate menu dimen on table item changes * add CloseAllMenus for menu widget --- frontend/ui/menu.lua | 67 ++++++++++++++++++++++++++++++++---------- frontend/ui/widget.lua | 17 +++++++---- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/frontend/ui/menu.lua b/frontend/ui/menu.lua index b5934c74a..9d4c0dcaa 100644 --- a/frontend/ui/menu.lua +++ b/frontend/ui/menu.lua @@ -204,7 +204,7 @@ Menu = FocusManager:new{ sface = Font:getFace("scfont", 20), title = "No Title", - dimen = Geom:new{ w = 500, h = 500 }, + dimen = Geom:new{}, item_table = {}, item_shortcuts = { "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", @@ -222,17 +222,29 @@ Menu = FocusManager:new{ -- set this to true to not paint as popup menu is_borderless = false, + -- close_callback is a function, which is executed when menu is closed + -- it is usually set by the widget which creates the menu + close_callback = nil } -function Menu:init() +function Menu:_recalculateDimen() + self.dimen.w = self.width + self.dimen.h = (#self.item_table + 2) * 36 self.item_dimen = Geom:new{ w = self.dimen.w, h = 36, -- hardcoded for now } - + if not self.is_borderless then + -- we need to substract border, margin and padding + self.item_dimen.w = self.item_dimen.w - 14 + end self.perpage = math.floor(self.dimen.h / self.item_dimen.h) - 2 - self.page = 1 self.page_num = math.ceil(#self.item_table / self.perpage) +end + +function Menu:init() + self:_recalculateDimen() + self.page = 1 ----------------------------------- -- start to set up widget layout -- @@ -262,16 +274,12 @@ function Menu:init() self.content_group = content if not self.is_borderless then - self[1] = CenterContainer:new{ - FrameContainer:new{ - background = 0, - radius = math.floor(self.dimen.w/20), - content - }, - dimen = Screen:getSize(), + self[1] = FrameContainer:new{ + dimen = self.dimen, + background = 0, + radius = math.floor(self.dimen.w/20), + content } - -- we need to substract border, margin and padding - self.item_dimen.w = self.item_dimen.w - 14 else -- no border for the menu self[1] = FrameContainer:new{ @@ -279,7 +287,7 @@ function Menu:init() bordersize = 0, padding = 0, margin = 0, - dimen = Screen:getSize(), + dimen = self.dimen, content } end @@ -292,6 +300,16 @@ function Menu:init() MenuCloseButton:new{ menu = self, }) + self.ges_events.TapCloseAllMenus = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight(), + } + } + } else -- set up keyboard events self.key_events.Close = { {"Back"}, doc = "close menu" } @@ -323,6 +341,7 @@ function Menu:updateItems(select_number) self.layout = {} self.item_group:clear() self.content_group:resetLayout() + self:_recalculateDimen() for c = 1, self.perpage do local i = (self.page - 1) * self.perpage + c @@ -365,7 +384,7 @@ function Menu:updateItems(select_number) self.page_info.text = "no choices available" end - -- FIXME: this is a dirty hack to clear the previous menu + -- FIXME: this is a dirty hack to clear previous menus UIManager.repaint_all = true --UIManager:setDirty(self) end @@ -465,7 +484,7 @@ end function Menu:onClose() local table_length = #self.item_table_stack if table_length == 0 then - UIManager:close(self) + self:onCloseAllMenus() else -- back to parent menu parent_item_table = table.remove(self.item_table_stack, table_length) @@ -474,3 +493,19 @@ function Menu:onClose() return true end +function Menu:onCloseAllMenus() + UIManager:close(self) + if self.close_callback then + self.close_callback() + end + return true +end + +function Menu:onTapCloseAllMenus(arg, ges_ev) + if ges_ev.pos:notIntersectWith(self.dimen) then + self:onCloseAllMenus() + return true + end +end + + diff --git a/frontend/ui/widget.lua b/frontend/ui/widget.lua index 7da05bc46..6abd6f2c4 100644 --- a/frontend/ui/widget.lua +++ b/frontend/ui/widget.lua @@ -24,6 +24,11 @@ function Widget:new(o) local o = o or {} setmetatable(o, self) self.__index = self + -- Both o._init and o.init are called on object create. But o._init is used + -- for base widget initialization (basic component used to build other + -- widgets). While o.init is for higher level widgets, for example Menu + -- Widget + if o._init then o:_init() end if o.init then o:init() end return o end @@ -92,7 +97,7 @@ end --[[ Containers will pass events to children or react on them themselves -]] +]]-- function WidgetContainer:handleEvent(event) if not self:propagateEvent(event) then -- call our own standard event handler @@ -582,10 +587,12 @@ an example for a key_event is this: it is suggested to reference configurable sequences from another table and store that table as configuration setting ]] -InputContainer = WidgetContainer:new{ - key_events = {}, - ges_events = {}, -} +InputContainer = WidgetContainer:new{} + +function InputContainer:_init() + self.key_events = {} + self.ges_events = {} +end function InputContainer:paintTo(bb, x, y) self.dimen.x = x