scrap widget inheritance

This commit is contained in:
airstruck
2015-10-27 19:27:14 -04:00
parent ca67432b66
commit f19ef288ca
7 changed files with 101 additions and 125 deletions

View File

@@ -3,26 +3,22 @@ local ROOT = (...):gsub('[^.]*$', '')
local Base = require(ROOT .. 'base') local Base = require(ROOT .. 'base')
local Hooker = require(ROOT .. 'hooker') local Hooker = require(ROOT .. 'hooker')
local Event = Base:extend { name = 'Event' } local Event = Base:extend({ name = 'Event' })
function Event:emit (target, data, defaultAction) function Event:emit (target, data, defaultAction)
while target do local callbacks = self.registry[target]
local handlers = rawget(target, 'eventHandlers') if not callbacks then
local callbacks = handlers and handlers[self.name] if defaultAction then defaultAction() end
if callbacks then return
local result = callbacks(data or {})
if result ~= nil then return result end
end
target = target.widgetClass
end end
local result = callbacks(data or {})
if result ~= nil then return result end
if defaultAction then defaultAction() end if defaultAction then defaultAction() end
end end
function Event:bind (target, callback) function Event:bind (target, callback)
if not rawget(target, 'eventHandlers') then local registry = self.registry
target.eventHandlers = {} return Hooker.hook(registry, target, callback)
end
return Hooker.hook(target.eventHandlers, self.name, callback)
end end
local eventNames = { local eventNames = {
@@ -34,7 +30,10 @@ local eventNames = {
local weakKeyMeta = { __mode = 'k' } local weakKeyMeta = { __mode = 'k' }
for i, name in ipairs(eventNames) do for i, name in ipairs(eventNames) do
Event[name] = Event:extend { name = name } Event[name] = Event:extend({
name = name,
registry = setmetatable({}, weakKeyMeta),
})
end end
function Event.injectBinders (t) function Event.injectBinders (t)

View File

@@ -13,7 +13,7 @@ local weakValueMeta = { __mode = 'v' }
function Layout:constructor (data) function Layout:constructor (data)
self.widgets = setmetatable({}, weakValueMeta) self.widgets = setmetatable({}, weakValueMeta)
self.root = Widget.create(self, data or {}) self.root = Widget(self, data or {})
self:setStyle() self:setStyle()
self:setTheme() self:setTheme()

View File

@@ -7,21 +7,15 @@ local Widget = Base:extend()
Widget.isWidget = true Widget.isWidget = true
Widget.registeredTypes = { Widget.typeDecorators = {
sash = ROOT .. 'widget.sash', sash = require(ROOT .. 'widget.sash'),
slider = ROOT .. 'widget.slider', slider = require(ROOT .. 'widget.slider'),
stepper = ROOT .. 'widget.stepper', stepper = require(ROOT .. 'widget.stepper'),
text = ROOT .. 'widget.text', text = require(ROOT .. 'widget.text'),
} }
function Widget.create (layout, data) function Widget.register (name, decorator)
local path = data.type and Widget.registeredTypes[data.type] Widget.typeDecorators[name] = decorator
if path then
return require(path)(layout, data)
end
return Widget(layout, data)
end end
function Widget:constructor (layout, data) function Widget:constructor (layout, data)
@@ -45,6 +39,12 @@ function Widget:constructor (layout, data)
local theme = widget.layout.theme local theme = widget.layout.theme
return theme and theme:getProperty(self, property) return theme and theme:getProperty(self, property)
end end
local decorate = self.type and Widget.typeDecorators[self.type]
if decorate then
decorate(widget)
end
end end
function Widget:extract (data) function Widget:extract (data)
@@ -52,7 +52,7 @@ function Widget:extract (data)
-- TODO: get rid of pairs somehow -- TODO: get rid of pairs somehow
for k, v in pairs(data) do for k, v in pairs(data) do
if type(k) == 'number' then if type(k) == 'number' then
children[k] = v.isWidget and v or Widget.create(self.layout, v) children[k] = v.isWidget and v or Widget(self.layout, v)
children[k].parent = self children[k].parent = self
else else
self[k] = v self[k] = v
@@ -76,7 +76,7 @@ end
function Widget:addChild (data) function Widget:addChild (data)
local layout = self.layout local layout = self.layout
local child = Widget.create(layout, data) local child = Widget(layout, data)
table.insert(self.children, child) table.insert(self.children, child)
child.parent = self child.parent = self

View File

@@ -1,33 +1,30 @@
local Widget = require((...):gsub('%.[^.]*$', '')) return function (self)
local Sash = Widget:extend() self:onPressDrag(function (event)
local axis = self.parent.flow
if axis == 'x' then
dimension = 'width'
else
axis = 'y'
dimension = 'height'
end
local prevSibling = self:getPrevious()
local nextSibling = self:getNext()
local prevSize = prevSibling and prevSibling[dimension]
local nextSize = nextSibling and nextSibling[dimension]
if prevSize then
prevSibling:setDimension(dimension,
event[axis] - prevSibling:calculatePosition(axis))
end
if nextSize then
nextSibling:setDimension(dimension,
nextSibling:calculatePosition(axis) +
nextSibling[dimension] - event[axis])
end
Sash:onPressDrag(function (event) prevSibling:reflow()
local self = event.target nextSibling:reflow()
local axis = self.parent.flow self:reflow()
if axis == 'x' then end)
dimension = 'width'
else
axis = 'y'
dimension = 'height'
end
local prevSibling = self:getPrevious()
local nextSibling = self:getNext()
local prevSize = prevSibling and prevSibling[dimension]
local nextSize = nextSibling and nextSibling[dimension]
if prevSize then
prevSibling:setDimension(dimension,
event[axis] - prevSibling:calculatePosition(axis))
end
if nextSize then
nextSibling:setDimension(dimension,
nextSibling:calculatePosition(axis) +
nextSibling[dimension] - event[axis])
end
prevSibling:reflow() end
nextSibling:reflow()
self:reflow()
end)
return Sash

View File

@@ -1,53 +1,45 @@
local Widget = require((...):gsub('%.[^.]*$', '')) return function (self)
local Slider = Widget:extend()
function Slider:constructor (layout, data)
Widget.constructor(self, layout, data)
self.value = 0.5 self.value = 0.5
self:onPressDrag(function (event)
local x1, y1, x2, y2 = self:getRectangle(true, true)
self.value = (event.x - x1) / (x2 - x1)
if self.value < 0 then self.value = 0 end
if self.value > 1 then self.value = 1 end
end)
self:onDisplay(function (event)
local x1, y1, x2, y2 = self:getRectangle(true, true)
local padding = self.padding or 0
local sx1 = math.floor(x1 + self.value * (x2 - x1) - padding) + 0.5
local sy1 = math.floor(y1 + padding) + 0.5
local sx2 = padding * 2
local sy2 = y2 - y1 - padding
love.graphics.push('all')
love.graphics.setColor(self.outline)
love.graphics.rectangle('fill',
x1,
y1 + ((y2 - y1) / 2),
x2 - x1,
padding
)
love.graphics.setColor(self.background)
love.graphics.rectangle('fill', sx1, sy1, sx2, sy2)
love.graphics.setColor(self.outline)
love.graphics.rectangle('line', sx1, sy1, sx2, sy2)
love.graphics.pop()
return false
end)
end end
Slider:onPressDrag(function (event)
local self = event.target
local x1, y1, x2, y2 = self:getRectangle(true, true)
self.value = (event.x - x1) / (x2 - x1)
if self.value < 0 then self.value = 0 end
if self.value > 1 then self.value = 1 end
end)
Slider:onDisplay(function (event)
local self = event.target
local x1, y1, x2, y2 = self:getRectangle(true, true)
local padding = self.padding or 0
local sx1 = math.floor(x1 + self.value * (x2 - x1) - padding) + 0.5
local sy1 = math.floor(y1 + padding) + 0.5
local sx2 = padding * 2
local sy2 = y2 - y1 - padding
love.graphics.push('all')
love.graphics.setColor(self.outline)
love.graphics.rectangle('fill',
x1,
y1 + ((y2 - y1) / 2),
x2 - x1,
padding
)
love.graphics.setColor(self.background)
love.graphics.rectangle('fill', sx1, sy1, sx2, sy2)
love.graphics.setColor(self.outline)
love.graphics.rectangle('line', sx1, sy1, sx2, sy2)
love.graphics.pop()
return false
end)
return Slider

View File

@@ -1,9 +1,4 @@
local Widget = require((...):gsub('%.[^.]*$', '')) return function (self)
local Stepper = Widget:extend()
function Stepper:constructor (layout, data)
Widget.constructor(self, layout, data)
self.flow = 'x' self.flow = 'x'
self.index = 1 self.index = 1
@@ -58,6 +53,5 @@ function Stepper:constructor (layout, data)
end) end)
updateValue() updateValue()
end
return Stepper end

View File

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