diff --git a/frontend/ui/filechooser.lua b/frontend/ui/filechooser.lua index 2ab853bb7..dbfbf044f 100644 --- a/frontend/ui/filechooser.lua +++ b/frontend/ui/filechooser.lua @@ -1,6 +1,8 @@ require "ui/menu" FileChooser = Menu:new{ + height = Screen:getHeight(), + width = Screen:getWidth(), path = ".", parent = nil, show_hidden = false, diff --git a/frontend/ui/menu.lua b/frontend/ui/menu.lua index b5934c74a..3f0a807c5 100644 --- a/frontend/ui/menu.lua +++ b/frontend/ui/menu.lua @@ -204,7 +204,11 @@ Menu = FocusManager:new{ sface = Font:getFace("scfont", 20), title = "No Title", - dimen = Geom:new{ w = 500, h = 500 }, + -- default width and height + width = 500, + -- height will be calculated according to item number if not given + height = nil, + dimen = Geom:new{}, item_table = {}, item_shortcuts = { "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", @@ -222,17 +226,33 @@ 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 + -- if height not given, dynamically calculate it + self.dimen.h = self.height or (#self.item_table + 2) * 36 + if self.dimen.h > Screen:getHeight() then + self.dimen.h = Screen:getHeight() + end 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 +282,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 +295,7 @@ function Menu:init() bordersize = 0, padding = 0, margin = 0, - dimen = Screen:getSize(), + dimen = self.dimen, content } end @@ -292,6 +308,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,8 +349,10 @@ function Menu:updateItems(select_number) self.layout = {} self.item_group:clear() self.content_group:resetLayout() + self:_recalculateDimen() for c = 1, self.perpage do + -- calculate index in item_table local i = (self.page - 1) * self.perpage + c if i <= #self.item_table then local item_shortcut = nil @@ -351,7 +379,15 @@ function Menu:updateItems(select_number) menu = self, } table.insert(self.item_group, item_tmp) + -- this is for focus manager table.insert(self.layout, {item_tmp}) + else + -- item not enough to fill the whole page, break out of loop + table.insert(self.item_group, + VerticalSpan:new{ + width = (self.item_dimen.h * (self.perpage - c + 1)) + }) + break end -- if i <= self.items end -- for c=1, self.perpage if self.item_group[1] then @@ -365,7 +401,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 +501,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 +510,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/reader/readermenu.lua b/frontend/ui/reader/readermenu.lua index ecfae4130..d19c55f83 100644 --- a/frontend/ui/reader/readermenu.lua +++ b/frontend/ui/reader/readermenu.lua @@ -12,7 +12,7 @@ function ReaderMenu:init() h = Screen:getHeight()/2 } } - } + }, } else self.key_events = { @@ -94,6 +94,7 @@ function ReaderMenu:onShowMenu() table.insert(item_table, { text = "Return to file browser", callback = function() + UIManager:close(self.menu_container) self.ui:onClose() end }) @@ -101,17 +102,25 @@ function ReaderMenu:onShowMenu() local main_menu = Menu:new{ title = "Document menu", item_table = item_table, - width = 300, - height = #item_table + 3 * 28 + width = Screen:getWidth() - 100, } - function main_menu:onMenuChoice(item) if item.callback then item.callback() end end - UIManager:show(main_menu) + local menu_container = CenterContainer:new{ + main_menu, + dimen = Screen:getSize(), + } + main_menu.close_callback = function () + UIManager:close(menu_container) + end + -- maintain a reference to menu_container + self.menu_container = menu_container + + UIManager:show(menu_container) return true end @@ -121,3 +130,8 @@ function ReaderMenu:onTapShowMenu() return true end +function ReaderMenu:onSetDimensions(dimen) + -- update gesture listenning range according to new screen orientation + self:init() +end + diff --git a/frontend/ui/ui.lua b/frontend/ui/ui.lua index 896804dd9..5ac088bc2 100644 --- a/frontend/ui/ui.lua +++ b/frontend/ui/ui.lua @@ -155,16 +155,8 @@ function UIManager:run() -- repaint dirty widgets local dirty = false - local update_area = Geom:new{} for _, widget in ipairs(self._window_stack) do if self.repaint_all or self._dirty[widget.widget] then - widget_dimen = widget.widget:getSize() - if widget_dimen then - widget_area = Geom:new{ - x = widget.x, y = widget.y, - w = widget_dimen.w, h = widget_dimen.h} - update_area = update_area:combine(widget_area) - end widget.widget:paintTo(Screen.fb.bb, widget.x, widget.y) if self._dirty[widget.widget] == "full" then self.refresh_type = 0 @@ -176,8 +168,6 @@ function UIManager:run() end end self.repaint_all = false - -- @TODO make use of update_area on refresh 19.06 2012 (houqp) - --DEBUG(update_area) if dirty then -- refresh FB 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