adjust children for parent padding and margin

This commit is contained in:
airstruck
2015-10-25 16:01:41 -04:00
parent 8f604fb79d
commit 995825b9b3
11 changed files with 108 additions and 84 deletions

View File

@@ -6,19 +6,23 @@ local style = {
height = 400, height = 400,
}, },
short = { short = {
height = 36, height = 48,
}, },
toolbar = { toolbar = {
style = { 'short' }, style = { 'short' },
}, },
toolButton = { toolButton = {
align = 'center middle', align = 'center middle',
width = 36, width = 48,
margin = 4, margin = 4,
padding = 0,
}, },
toolButton_not_hovered = { toolButton_not_hovered = {
background = false, background = false,
outline = { 200, 200, 200 }, outline = false,
},
toolButton_hovered = {
tint = { 200, 255, 200 },
}, },
statusbar = { statusbar = {
style = 'panel', style = 'panel',
@@ -58,17 +62,19 @@ local mainForm = { title = "Test window", id = 'mainWindow', type = 'panel',
{ id = 'mainCanvas' }, { id = 'mainCanvas' },
{ type = 'sash', width = 4, }, { type = 'sash', width = 4, },
{ type = 'panel', id = 'rightSideBox', width = 200, { type = 'panel', id = 'rightSideBox', width = 200,
{ type = 'panel', text = 'A slider', align = 'bottom', height = 24 }, { type = 'panel', text = 'A slider', align = 'bottom', height = 24, padding = 4 },
{ type = 'slider', height = 48, }, { type = 'slider', height = 32, padding = 4 },
{ type = 'panel', text = 'A stepper', align = 'bottom', height = 24, padding = 4 },
{ type = 'stepper', height = 32, padding = 4 },
}, },
}, },
{ type = 'sash', height = 4, }, { type = 'sash', height = 4, },
{ type = 'panel', flow = 'x', height = 48, { type = 'panel', flow = 'x', height = 48, padding = 2,
{ type = 'text', id = 'aTextField', text = 'a text field', { type = 'text', id = 'aTextField', text = 'a text field',
font = 'font/liberation/LiberationMono-Regular.ttf' }, font = 'font/liberation/LiberationMono-Regular.ttf' },
{ type = 'button', width = 80, id = 'aButton', text = 'Styling!' }, { type = 'button', width = 80, id = 'aButton', text = 'Styling!' },
}, },
{ type = 'panel', height = 24, id = 'statusbar', textColor = { 255, 0, 0 } }, { type = 'panel', id = 'statusbar', height = 24, padding = 4, textColor = { 255, 0, 0 } },
} }
local layout = Layout(mainForm) local layout = Layout(mainForm)
@@ -99,19 +105,19 @@ layout:onKeyboard(function(event)
end) end)
]] ]]
layout:onMotion(function(event) layout:onMotion(function (event)
local w = event.target local w = event.target
layout.statusbar.text = (w.id or '(unnamed)') .. ' ' .. layout.statusbar.text = (w.id or '(unnamed)') .. ' ' ..
w:getX() .. ', ' .. w:getY() .. ' | ' .. w:getX() .. ', ' .. w:getY() .. ' | ' ..
w:getWidth() .. 'x' .. w:getHeight() w:getWidth() .. 'x' .. w:getHeight()
end) end)
layout.newButton:onMotion(function(event) layout.newButton:onMotion(function (event)
layout.statusbar.text = 'Create a new thing' layout.statusbar.text = 'Create a new thing'
return false return false
end) end)
layout.newButton:onPress(function(event) layout.newButton:onPress(function (event)
print('creating a new thing!') print('creating a new thing!')
end) end)

View File

@@ -1,6 +1,7 @@
local ROOT = (...):gsub('[^.]*$', '') local ROOT = (...):gsub('[^.]*$', '')
local Base = require(ROOT .. 'base') local Base = require(ROOT .. 'base')
local Hooker = require(ROOT .. 'hooker')
local Event = Base:extend({ name = 'Event' }) local Event = Base:extend({ name = 'Event' })
@@ -10,19 +11,14 @@ function Event:emit (observer, data, defaultAction)
if defaultAction then defaultAction() end if defaultAction then defaultAction() end
return return
end end
for i, callback in ipairs(callbacks) do local result = callbacks(data or {})
local result = callback(data or {}) if result ~= nil then return result end
if result ~= nil then return result end
end
if defaultAction then defaultAction() end if defaultAction then defaultAction() end
end end
function Event:bind (observer, callback) function Event:bind (observer, callback)
local registry = self.registry local registry = self.registry
if not registry[observer] then return Hooker.hook(registry, observer, callback)
registry[observer] = {}
end
table.insert(registry[observer], callback)
end end
local eventNames = { local eventNames = {

View File

@@ -1,25 +1,8 @@
local Hooker = {} local Hooker = {}
local wrapped = {} local wrapped = setmetatable({}, { __mode = 'k' })
local hooks = {} local hooks = setmetatable({}, { __mode = 'k' })
local function hook (key, func)
if not func then
return
end
local next = hooks[key]
local item = { next = next, unhook = unhook, key = key, func = func }
if next then
next.prev = item
end
hooks[key] = item
return item
end
local function unhook (item) local function unhook (item)
if item.prev then if item.prev then
@@ -30,36 +13,71 @@ local function unhook (item)
item.next.prev = item.prev item.next.prev = item.prev
end end
if hooks[item.key] == item then if hooks[item.host][item.key] == item then
hooks[item.key] = item.next hooks[item.host][item.key] = item.next
end end
item.host = nil
item.prev = nil item.prev = nil
item.next = nil item.next = nil
item.func = nil item.func = nil
end end
function Hooker.hook (key, func) local function hook (host, key, func)
if not wrapped[key] then if not func then
wrapped[key] = true return
hook(key, love[key])
love[key] = function (...)
local item = hooks[key]
while item do
item.func(...)
item = item.next
end
end
end end
return hook(key, func) if not hooks[host] then
hooks[host] = {}
end
local next = hooks[host][key]
local item = {
next = next,
unhook = unhook,
host = host,
key = key,
func = func,
}
if next then
next.prev = item
end
hooks[host][key] = item
return item
end end
function Hooker.unhook (item) function Hooker.unhook (item)
return unhook(item) return unhook(item)
end end
function Hooker.hook (host, key, func)
if not wrapped[host] then
wrapped[host] = {}
end
if not wrapped[host][key] then
wrapped[host][key] = true
hook(host, key, host[key])
host[key] = function (...)
local item = hooks[host][key]
while item do
local result = item.func(...)
if result ~= nil then
return result
end
item = item.next
end
end
end
return hook(host, key, func)
end
return Hooker return Hooker

View File

@@ -147,10 +147,6 @@ function Input:handleReshape (width, height)
layout.root:reflow() layout.root:reflow()
root.width = width root.width = width
root.height = height root.height = height
Event.Reshape:emit(root, {
target = root,
width = width, height = height
})
end end
return Input return Input

View File

@@ -51,6 +51,7 @@ function Layout:show ()
love.window.setTitle(title) love.window.setTitle(title)
end end
self:manageInput(self.input) self:manageInput(self.input)
root:reflow()
end end
function Layout:hide () function Layout:hide ()
@@ -90,7 +91,7 @@ end
-- event stuff -- event stuff
function Layout:hook (key, method) function Layout:hook (key, method)
self.hooks[#self.hooks + 1] = Hooker.hook(key, method) self.hooks[#self.hooks + 1] = Hooker.hook(love, key, method)
end end
function Layout:unhook () function Layout:unhook ()

View File

@@ -32,7 +32,7 @@ function Renderer:renderOutline (widget, window)
love.graphics.push('all') love.graphics.push('all')
love.graphics.setColor(widget.outline) love.graphics.setColor(widget.outline)
love.graphics.rectangle('line', x1 - 0.5, y1 - 0.5, x2 - x1, y2 - y1) love.graphics.rectangle('line', x1 + 0.5, y1 + 0.5, x2 - x1, y2 - y1)
love.graphics.pop() love.graphics.pop()
end end
@@ -162,6 +162,7 @@ function Renderer:renderIconAndText (widget, window)
if icon then if icon then
iconX, iconY = math.floor(iconX), math.floor(iconY) iconX, iconY = math.floor(iconX), math.floor(iconY)
if widget.tint then if widget.tint then
love.graphics.setBlendMode('alpha', true)
love.graphics.setColor(widget.tint) love.graphics.setColor(widget.tint)
end end
love.graphics.draw(icon, iconX, iconY) love.graphics.draw(icon, iconX, iconY)

View File

@@ -9,14 +9,13 @@ return function (config)
return { return {
panel = { panel = {
background = backColor, background = backColor,
padding = 4,
}, },
button = { button = {
type = 'panel', type = 'panel',
align = 'center middle', align = 'center middle',
outline = lineColor, outline = lineColor,
bend = 0.1, bend = 0.1,
margin = 4, margin = 2,
}, },
button_hovered = { button_hovered = {
background = white, background = white,
@@ -30,9 +29,8 @@ return function (config)
align = 'left middle', align = 'left middle',
background = { 255, 255, 255 }, background = { 255, 255, 255 },
outline = lineColor, outline = lineColor,
bend = -0.1, margin = 2,
margin = 4, padding = 2,
padding = 4,
}, },
sash = { sash = {
background = lineColor background = lineColor
@@ -45,6 +43,9 @@ return function (config)
outline = lineColor, outline = lineColor,
background = white, background = white,
}, },
stepper = {
type = 'panel',
},
slider_hovered = { slider_hovered = {
outline = highlight, outline = highlight,
}, },

View File

@@ -10,6 +10,7 @@ Widget.isWidget = true
Widget.registeredTypes = { Widget.registeredTypes = {
sash = ROOT .. 'widget.sash', sash = ROOT .. 'widget.sash',
slider = ROOT .. 'widget.slider', slider = ROOT .. 'widget.slider',
stepper = ROOT .. 'widget.stepper',
text = ROOT .. 'widget.text', text = ROOT .. 'widget.text',
} }
@@ -79,6 +80,8 @@ function Widget:addChild (data)
table.insert(self.children, child) table.insert(self.children, child)
child.parent = self child.parent = self
layout:addWidget(child) layout:addWidget(child)
return child
end end
function Widget:calculateDimension (name) function Widget:calculateDimension (name)
@@ -101,6 +104,8 @@ function Widget:calculateDimension (name)
return self.layout return self.layout
end end
local parentDimension = parent:calculateDimension(name) local parentDimension = parent:calculateDimension(name)
parentDimension = parentDimension - (parent.margin or 0) * 2
parentDimension = parentDimension - (parent.padding or 0) * 2
local parentFlow = parent.flow or 'y' local parentFlow = parent.flow or 'y'
if (parentFlow == 'y' and name == 'width') or if (parentFlow == 'y' and name == 'width') or
(parentFlow == 'x' and name == 'height') (parentFlow == 'x' and name == 'height')
@@ -121,7 +126,7 @@ function Widget:calculateDimension (name)
end end
end end
end end
local size = (self.parent:calculateDimension(name) - claimed) / unsized local size = (parentDimension - claimed) / unsized
self.dimensions[name] = clamp(size, 0, self.layout.root[name]) self.dimensions[name] = clamp(size, 0, self.layout.root[name])
return size return size
end end
@@ -137,6 +142,8 @@ function Widget:calculatePosition (axis)
end end
local parentPos = parent:calculatePosition(axis) local parentPos = parent:calculatePosition(axis)
local p = parentPos local p = parentPos
p = p + (parent.margin or 0)
p = p + (parent.padding or 0)
local parentFlow = parent.flow or 'y' local parentFlow = parent.flow or 'y'
for i, widget in ipairs(parent.children) do for i, widget in ipairs(parent.children) do
if widget == self then if widget == self then
@@ -236,6 +243,9 @@ end
function Widget:reflow () function Widget:reflow ()
self.position = {} self.position = {}
self.dimensions = {} self.dimensions = {}
Event.Reshape:emit(self, {
target = self
})
for i, widget in ipairs(self.children) do for i, widget in ipairs(self.children) do
widget:reflow() widget:reflow()
end end

View File

@@ -2,10 +2,10 @@ local Widget = require((...):gsub('%.[^.]*$', ''))
local Sash = Widget:extend() local Sash = Widget:extend()
function Sash:constructor(layout, data) function Sash:constructor (layout, data)
Widget.constructor(self, layout, data) Widget.constructor(self, layout, data)
self:onPressDrag(function(event) self:onPressDrag(function (event)
local axis = self.parent.flow local axis = self.parent.flow
if axis == 'x' then if axis == 'x' then
dimension = 'width' dimension = 'width'

View File

@@ -2,29 +2,24 @@ local Widget = require((...):gsub('%.[^.]*$', ''))
local Slider = Widget:extend() local Slider = Widget:extend()
function Slider:constructor(layout, data) function Slider:constructor (layout, data)
Widget.constructor(self, layout, data) Widget.constructor(self, layout, data)
local function getCenter() self.value = 0.5
return self:getX() + self:getWidth() / 2
end
local position = 0.5 self:onPressDrag(function (event)
self:onPressDrag(function(event)
local x1, y1, x2, y2 = self:getRectangle(true, true) local x1, y1, x2, y2 = self:getRectangle(true, true)
position = (event.x - x1) / (x2 - x1) self.value = (event.x - x1) / (x2 - x1)
if position < 0 then position = 0 end if self.value < 0 then self.value = 0 end
if position > 1 then position = 1 end if self.value > 1 then self.value = 1 end
end) end)
self:onDisplay(function(event) self:onDisplay(function (event)
local x1, y1, x2, y2 = self:getRectangle(true, true) local x1, y1, x2, y2 = self:getRectangle(true, true)
local padding = self.padding or 0 local padding = self.padding or 0
local sx1 = math.floor(x1 + self.value * (x2 - x1) - padding) + 0.5
local sx1 = math.floor(x1 + position * (x2 - x1) - padding) - 0.5 local sy1 = math.floor(y1 + padding) + 0.5
local sy1 = math.floor(y1 + padding) - 0.5
local sx2 = padding * 2 local sx2 = padding * 2
local sy2 = y2 - y1 - padding local sy2 = y2 - y1 - padding
@@ -34,7 +29,7 @@ function Slider:constructor(layout, data)
love.graphics.rectangle('fill', love.graphics.rectangle('fill',
x1, x1,
y1 + ((y2 - y1) / 2) - padding / 2, y1 + ((y2 - y1) / 2),
x2 - x1, x2 - x1,
padding padding
) )

View File

@@ -2,7 +2,7 @@ local Widget = require((...):gsub('%.[^.]*$', ''))
local Text = Widget:extend() local Text = Widget:extend()
function Text:constructor(layout, data) function Text:constructor (layout, data)
Widget.constructor(self, layout, data) Widget.constructor(self, layout, data)
end end