Add solid and modal attributes.

The `solid` attribute determines whether to propagate events downwards.
When the widget being interacted with is not solid, events propagate down
to the next layout or to underlying handlers (for example love callbacks).
This is set by the theme and works mostly behind the scenes.

The `modal` attribute can be placed on a layout root to prevent input events
from propagating downwards, even those that fall outside of the layout.
This commit is contained in:
airstruck
2016-01-19 12:20:19 -05:00
parent d0628a8d1d
commit ab43dabcb9
4 changed files with 39 additions and 45 deletions

View File

@@ -117,6 +117,21 @@ function Attribute.value.set (widget, value)
widget:bubbleEvent('Change', { value = value, oldValue = oldValue })
end
--[[--
Solidity.
Should true or false.
@attrib icon
--]]--
Attribute.solid = {}
function Attribute.solid.set (widget, value)
widget.attributes.solid = value
end
Attribute.solid.get = cascade
--[[--
Context menu.

View File

@@ -35,6 +35,7 @@ function Input:handleKeyPress (layout, key, x, y)
x = x, y = y
})
if result ~= nil then return result end
if layout.root.modal then return false end
end
function Input:handleKeyRelease (layout, key, x, y)
@@ -45,25 +46,26 @@ function Input:handleKeyRelease (layout, key, x, y)
x = x, y = y
})
if result ~= nil then return result end
if layout.root.modal then return false end
end
function Input:handleTextInput (layout, text, x, y)
local widget = layout.focusedWidget or layout.root
local result = widget:bubbleEvent('TextInput', {
hit = hit,
text = text,
x = x, y = y
})
if result ~= nil then return result end
if layout.root.modal then return false end
end
local function checkHit (widget, layout)
local root = layout.root
return widget and widget.solid or root.modal, widget or root
end
function Input:handleMove (layout, x, y)
local widget = layout:getWidgetAt(x, y)
local hit = true
if not widget then
hit = nil
widget = layout.root
end
local hit, widget = checkHit(layout:getWidgetAt(x, y), layout)
local previousWidget = self.previousMoveWidget
if widget ~= previousWidget then
if previousWidget then
@@ -104,12 +106,7 @@ function Input:handleMove (layout, x, y)
end
function Input:handlePressedMove (layout, x, y)
local widget = layout:getWidgetAt(x, y)
local hit = true
if not widget then
hit = nil
widget = layout.root
end
local hit, widget = checkHit(layout:getWidgetAt(x, y), layout)
for _, button in ipairs { 'left', 'middle', 'right' } do
local originWidget = self.pressedWidgets[button]
if originWidget then
@@ -153,20 +150,15 @@ function Input:handlePressedMove (layout, x, y)
end
function Input:handlePressStart (layout, button, x, y, widget, shortcut)
local widget = widget or layout:getWidgetAt(x, y)
local hit = true
if not widget then
hit = nil
widget = layout.root
end
if hit then
local hit, widget = checkHit(widget or layout:getWidgetAt(x, y), layout)
-- if hit then
self.pressedWidgets[button] = widget
self.passedWidgets[button] = widget
widget.pressed[button] = true
if button == 'left' then
widget:focus()
end
end
-- end
widget:bubbleEvent('PressStart', {
hit = hit,
button = button,
@@ -177,12 +169,7 @@ function Input:handlePressStart (layout, button, x, y, widget, shortcut)
end
function Input:handlePressEnd (layout, button, x, y, widget, shortcut)
local widget = widget or layout:getWidgetAt(x, y)
local hit = true
if not widget then
hit = nil
widget = layout.root
end
local hit, widget = checkHit(widget or layout:getWidgetAt(x, y), layout)
local originWidget = self.pressedWidgets[button]
if not originWidget then return end
if hit then
@@ -233,13 +220,7 @@ end
function Input:handleWheelMove (layout, x, y)
local mx, my = Backend.getMousePosition()
local widget = layout:getWidgetAt(mx, my)
local hit = true
if not widget then
hit = nil
widget = layout.root
end
local hit, widget = checkHit(layout:getWidgetAt(x, y), layout)
widget:bubbleEvent('WheelMove', { hit = hit, x = x, y = y })

View File

@@ -55,11 +55,11 @@ return function (config)
end
local function getControlHeight (self)
return self.flow == 'x' and self.minheight
return self.flow == 'x' and self._defaultDimension
end
local function getControlWidth (self)
return self.flow ~= 'x' and self.minwidth
return self.flow ~= 'x' and self._defaultDimension
end
local function getMenuItemBackground (self)
@@ -111,18 +111,18 @@ return function (config)
height = getControlHeight,
width = getControlWidth,
color = textColor,
minheight = 36,
minwidth = 36,
align = 'center middle',
margin = 2,
color = textColor,
solid = true,
_defaultDimension = 36,
},
Line = {
minheight = 24,
margin = 0,
padding = 4,
align = 'left middle',
_defaultDimension = 24,
},
-- widget types
@@ -159,6 +159,7 @@ return function (config)
padding = 2,
background = backColor,
color = textColor,
solid = true,
},
progress = {
type = { 'Control' },
@@ -187,8 +188,6 @@ return function (config)
type = { 'button' },
align = 'middle center',
margin = 0,
minwidth = 32,
minheight = 32,
},
status = {
type = { 'Line', 'Control' },
@@ -225,6 +224,7 @@ return function (config)
margin = -10,
slices = resources .. 'submenu.png',
color = textColor,
solid = true,
},
text = {
type = { 'Control' },

View File

@@ -73,16 +73,14 @@ return function (self)
self:onReshape(function (event)
local x1, y1, w, h = self:getRectangle(true, true)
local x2, y2 = x1 + w, y1 + h
local dim = math.min(w, h)
thumb.width, thumb.height = dim, dim
if self.flow == 'x' then
thumb.width = 0
thumb.height = false
local halfThumb = thumb:getWidth() / 2
x1, x2 = x1 + halfThumb, x2 - halfThumb
spacer.width = self.value * (x2 - x1)
spacer.height = false
else
thumb.width = false
thumb.height = 0
local halfThumb = thumb:getHeight() / 2
y1, y2 = y1 + halfThumb, y2 - halfThumb
spacer.width = false