add master layouts

This commit is contained in:
airstruck
2015-11-11 14:25:50 -05:00
parent a1ab534d6d
commit 68a250e273
3 changed files with 110 additions and 60 deletions

View File

@@ -38,30 +38,62 @@ A tree of widget data.
@treturn Layout
A Layout instance.
--]]--
function Layout:constructor (data)
function Layout:constructor (data, master)
data = data or {}
self.accelerators = {}
if master then
self:setMaster(master)
else
self:setTheme(require(ROOT .. 'theme.light'))
self:setStyle()
end
self:addDefaultHandlers()
self:setStyle()
self:setTheme(require(ROOT .. 'theme.light'))
self.isShown = false
self.hooks = {}
self.root = data
Widget(self, data)
end
--[[--
Set the master layout for this layout.
This layout's theme and style will be set the same as the master layout, and
widgets added to this layout will be indexed and keyboard-accelerated by the
master layout instead of this layout.
@tparam Layout layout
Master layout
@treturn Layout Self
--]]--
function Layout:setMaster (layout)
self.master = layout
function self:addWidget (...)
return layout:addWidget(...)
end
return self
end
--[[--
Set the style from a definition table or function.
@tparam table|function rules
Style definition.
@treturn Layout Self
--]]--
function Layout:setStyle (rules)
if type(rules) == 'function' then
rules = rules()
end
self.style = Style(rules or {}, { 'id', 'style' })
return self
end
--[[--
@@ -77,6 +109,26 @@ function Layout:setTheme (rules)
self.theme = Style(rules or {}, { 'type' })
end
--[[--
Get the style from master layout or this layout.
@treturn table
Style table.
--]]--
function Layout:getStyle ()
return self.master and self.master:getStyle() or self.style
end
--[[--
Get the theme from master layout or this layout.
@treturn table
Theme table.
--]]--
function Layout:getTheme ()
return self.master and self.master:getTheme() or self.theme
end
--[[--
Show the layout.
@@ -187,6 +239,8 @@ end
-- Add handlers for keyboard accelerators and tab focus
function Layout:addDefaultHandlers ()
self.accelerators = {}
self:onKeyPress(function (event)
-- tab / shift-tab cycles focused widget
@@ -210,7 +264,6 @@ function Layout:addDefaultHandlers ()
-- accelerators
local acceleratedWidget = self.accelerators[event.key]
if acceleratedWidget then
acceleratedWidget.hovered = true
self.input:handlePressStart(self, event.key, event.x, event.y,

View File

@@ -38,11 +38,12 @@ local function metaIndex (self, property)
local value = Widget[property]
if value ~= nil then return value end
local style = self.layout.style
local layout = self.layout
local style = layout:getStyle()
value = style and style:getProperty(self, property)
if value ~= nil and value ~= 'defer' then return value end
local theme = self.layout.theme
local theme = layout:getTheme()
return theme and theme:getProperty(self, property)
end

View File

@@ -2,7 +2,49 @@ local ROOT = (...):gsub('[^.]*.[^.]*.[^.]*$', '')
local Layout, Event
local show
local function addLayoutChildren (self)
local root = self.menuLayout.root
local textWidth = 0
local keyWidth = 0
local height = 0
while #root > 0 do rawset(root, #root, nil) end
root.height = 0
root.width = 0
for index, child in ipairs(self.items) do
child.type = child.type or 'menu.item'
root:addChild(child)
local childHeight = child:getHeight()
height = height + childHeight
if child.type == 'menu.item' then
local pad = child.padding or 0
local tw = child.fontData:getAdvance(child[2].text)
+ pad * 2 + childHeight
local kw = child.fontData:getAdvance(child[3].text)
+ pad * 2 + childHeight
textWidth = math.max(textWidth, tw)
keyWidth = math.max(keyWidth, kw)
end
end
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
local x = isSubmenu and self:getWidth() or 0
local y = isSubmenu and 0 or self:getHeight()
root.left = self:getX() + x
root.top = self:getY() + y
root.height = height
root.width = textWidth + keyWidth + (root.padding or 0)
end
local function show (self)
if not self.items or #self.items < 1 then return end
addLayoutChildren(self)
self.menuLayout:show()
end
local function deactivateSiblings (target)
local sibling = target.parent and target.parent[1]
@@ -76,56 +118,6 @@ local function registerLayoutEvents (self)
menuLayout:onPressEnter(activate)
end
local function addLayoutChildren (self)
local root = self.menuLayout.root
local textWidth = 0
local keyWidth = 0
local height = 0
while #root > 0 do rawset(root, #root, nil) end
root.height = 0
root.width = 0
for index, child in ipairs(self.items) do
child.type = child.type or 'menu.item'
root:addChild(child)
local childHeight = child:getHeight()
height = height + childHeight
if child.type == 'menu.item' then
local pad = child.padding or 0
local tw = child.fontData:getAdvance(child[2].text)
+ pad * 2 + childHeight
local kw = child.fontData:getAdvance(child[3].text)
+ pad * 2 + childHeight
textWidth = math.max(textWidth, tw)
keyWidth = math.max(keyWidth, kw)
end
end
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
local x = isSubmenu and self:getWidth() or 0
local y = isSubmenu and 0 or self:getHeight()
root.left = self:getX() + x
root.top = self:getY() + y
root.height = height
root.width = textWidth + keyWidth + (root.padding or 0)
end
local function createLayout (self)
Layout = Layout or require(ROOT .. 'layout')
self.menuLayout = Layout { type = 'submenu' }
end
show = function (self)
if not self.items or #self.items < 1 then return end
addLayoutChildren(self)
self.menuLayout:show()
end
local function initialize (self)
local pad = self.padding or 0
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
@@ -180,13 +172,17 @@ local function registerEvents (self)
end)
end
local function createLayout (self)
Layout = Layout or require(ROOT .. 'layout')
self.menuLayout = Layout({ type = 'submenu' }, self.rootMenu.layout)
end
return function (self)
extractChildren(self)
initialize(self)
registerEvents(self)
self.rootMenu.layout:addWidget(self)
if not self.items or #self.items < 1 then return end
createLayout(self)
registerLayoutEvents(self)