mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #657 from houqp/new_ui_menu_close
bug fixes and new feature for menu widget
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
require "ui/menu"
|
||||
|
||||
FileChooser = Menu:new{
|
||||
height = Screen:getHeight(),
|
||||
width = Screen:getWidth(),
|
||||
path = ".",
|
||||
parent = nil,
|
||||
show_hidden = false,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user