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 }) widget:bubbleEvent('Change', { value = value, oldValue = oldValue })
end 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. Context menu.

View File

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

View File

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

View File

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