first demo of touch menu

pull/2/merge
Qingping Hou 11 years ago
parent e0813ad789
commit 44d0a99efd

@ -0,0 +1,310 @@
require "ui/widget/container"
require "ui/widget/group"
require "ui/widget/line"
require "ui/widget/iconbutton"
--[[
TouchMenuItem widget
--]]
TouchMenuItem = InputContainer:new{
menu = nil,
vertical_align = "center",
item = nil,
dimen = nil,
face = Font:getFace("cfont", 22),
}
function TouchMenuItem:init()
self.ges_events = {
TapSelect = {
GestureRange:new{
ges = "tap",
range = self.dimen,
},
doc = "Select Menu Item",
},
}
self.item_frame = FrameContainer:new{
width = self.dimen.w,
bordersize = 0,
color = 15,
HorizontalGroup:new {
align = "center",
HorizontalSpan:new{ width = 10 },
TextWidget:new{
text = self.item.text,
face = self.face,
},
},
}
self[1] = self.item_frame
end
function TouchMenuItem:onTapSelect(arg, ges)
self.item_frame.invert = true
UIManager:setDirty(self.menu, "partial")
UIManager:scheduleIn(0.5, function()
self.item_frame.invert = false
UIManager:setDirty(self.menu, "partial")
end)
self.menu:onMenuSelect(self.item)
return true
end
--[[
TouchMenuBar widget
--]]
TouchMenuBar = InputContainer:new{
height = 70,
width = Screen:getWidth(),
icon = {},
-- touch menu that holds the bar, used for trigger repaint on icons
parent = nil,
menu = nil,
}
function TouchMenuBar:init()
self.parent = self.parent or self
self.dimen = Geom:new{
w = self.width,
h = self.height,
}
local icon_sep = LineWidget:new{
dimen = Geom:new{
w = 2,
h = self.height,
}
}
local icon_span = HorizontalSpan:new{ width = 20 }
-- build up image widget for menu icon bar
self.icon_widgets = {}
-- the start_seg for first icon_widget should be 0
-- we asign negative here to offset it in the loop
start_seg = -icon_sep:getSize().w
end_seg = start_seg
for k, v in ipairs(self.icons) do
local ib = IconButton:new{
parent = self.parent,
icon_file = v,
callback = nil,
}
table.insert(self.icon_widgets, HorizontalGroup:new{
icon_span,
ib,
icon_span,
})
-- we have to use local variable here for closure callback
local _start_seg = end_seg + icon_sep:getSize().w
local _end_seg = _start_seg + self.icon_widgets[k]:getSize().w
if k == 1 then
self.bar_sep = LineWidget:new{
dimen = Geom:new{
w = self.width,
h = 2,
},
empty_segments = {
{
s = _start_seg, e = _end_seg
}
},
}
end
ib.callback = function()
self.bar_sep.empty_segments = {
{
s = _start_seg, e = _end_seg
}
}
self.menu:switchMenuTab(k)
end
start_seg = _start_seg
end_seg = _end_seg
end
self.bar_icon_group = HorizontalGroup:new{
self.icon_widgets[1],
icon_sep,
self.icon_widgets[2],
icon_sep,
}
self[1] = FrameContainer:new{
bordersize = 0,
padding = 0,
VerticalGroup:new{
align = "left",
-- bar icons
self.bar_icon_group,
-- separate line
self.bar_sep
},
}
end
--[[
TouchMenu widget
--]]
TouchMenu = InputContainer:new{
title = "Untitled",
item_table = {},
item_height = 50,
bordersize = 2,
padding = 5,
width = Screen:getWidth(),
height = nil,
page = 1,
max_per_page = 10,
-- for UIManager:setDirty
parent = nil,
cur_tab = 1,
close_callback = nil,
}
function TouchMenu:init()
self.parent = self.parent or self
if not self.close_callback then
self.close_callback = function()
UIManager:close(self.parent)
end
end
self.ges_events.TapCloseAllMenus = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight(),
}
}
}
local icons = {}
for _,v in ipairs(self.item_table) do
table.insert(icons, v.icon)
end
self.bar = TouchMenuBar:new{
width = self.width - self.padding * 2 - self.bordersize * 2,
icons = icons,
parent = self.parent,
menu = self,
}
self.item_group = VerticalGroup:new{}
self[1] = FrameContainer:new{
padding = self.padding,
bordersize = self.bordersize,
background = 0,
self.item_group
}
self:updateItems()
end
function TouchMenu:_recalculateDimen()
self.dimen.w = self.width
-- if height not given, dynamically calculate it
if not self.height then
self.dimen.h = (#self.item_table[self.cur_tab] + 2) * self.item_height
+ self.bar:getSize().h
else
self.dimen.h = self.height
end
if self.dimen.h > Screen:getHeight() then
self.dimen.h = Screen:getHeight()
end
self.perpage = math.floor(self.dimen.h / self.item_height) - 2
if self.perpage > self.max_per_page then
self.perpage = self.max_per_page
end
self.page_num = math.ceil(#self.item_table / self.perpage)
end
function TouchMenu:updateItems()
self:_recalculateDimen()
self.item_group:clear()
table.insert(self.item_group, self.bar)
local item_width = self.dimen.w - self.padding*2 - self.bordersize*2
local item_table = self.item_table[self.cur_tab]
for c = 1, self.perpage do
-- calculate index in item_table
local i = (self.page - 1) * self.perpage + c
if i <= #item_table then
local item_tmp = TouchMenuItem:new{
item = item_table[i],
menu = self,
dimen = Geom:new{
w = item_width,
h = self.item_height,
},
}
table.insert(self.item_group, item_tmp)
-- insert split line
if c ~= self.perpage then
table.insert(self.item_group, LineWidget:new{
style = "dashed",
dimen = Geom:new{
w = item_width - 20,
h = 1,
}
})
end
else
-- item not enough to fill the whole page, break out of loop
table.insert(self.item_group,
VerticalSpan:new{
width = self.item_height
})
break
end -- if i <= self.items
end -- for c=1, self.perpage
-- FIXME: this is a dirty hack to clear previous menus
-- refert to issue #664
UIManager.repaint_all = true
end
function TouchMenu:switchMenuTab(tab_num)
if self.cur_tab ~= tab_num then
self.cur_tab = tab_num
self:updateItems()
end
return true
end
function TouchMenu:closeMenu()
self.close_callback()
end
function TouchMenu:onMenuSelect(item)
if item.sub_item_table == nil then
self:closeMenu()
if item.callback then
item.callback()
end
end
return true
end
function TouchMenu:onTapCloseAllMenus(arg, ges_ev)
if ges_ev.pos:notIntersectWith(self.dimen) then
self:closeMenu()
return true
end
end
Loading…
Cancel
Save