rework mouse buttons, fixes #18

This commit is contained in:
airstruck
2015-12-19 23:54:57 -05:00
parent 0281944066
commit 1ee239b203
14 changed files with 158 additions and 106 deletions

View File

@@ -76,8 +76,6 @@ end)
local Backend = require 'luigi.backend' local Backend = require 'luigi.backend'
layout.menuQuit:onPress(Backend.quit) layout.menuQuit:onPress(Backend.quit)
Backend.setWindowIcon('logo.png')
-- show the main layout -- show the main layout
layout:show() layout:show()

View File

@@ -302,6 +302,18 @@ local isMouseDown = function ()
return sdl.getMouseState(nil, nil) > 0 return sdl.getMouseState(nil, nil) > 0
end end
local buttonIds = {
[sdl.BUTTON_LEFT] = 'left',
[sdl.BUTTON_MIDDLE] = 'middle',
[sdl.BUTTON_RIGHT] = 'right',
-- [sdl.BUTTON_X1] = 'x1',
-- [sdl.BUTTON_X2] = 'x2',
}
local function getMouseButtonId (value)
return value and buttonIds[value] or value
end
function Backend.show (layout) function Backend.show (layout)
local input = layout.input local input = layout.input
@@ -312,10 +324,10 @@ function Backend.show (layout)
return input:handleReshape(layout, width, height) return input:handleReshape(layout, width, height)
end) end)
hook(layout, 'mousepressed', function (x, y, button) hook(layout, 'mousepressed', function (x, y, button)
return input:handlePressStart(layout, button, x, y) return input:handlePressStart(layout, getMouseButtonId(button), x, y)
end) end)
hook(layout, 'mousereleased', function (x, y, button) hook(layout, 'mousereleased', function (x, y, button)
return input:handlePressEnd(layout, button, x, y) return input:handlePressEnd(layout, getMouseButtonId(button), x, y)
end) end)
hook(layout, 'mousemoved', function (x, y, dx, dy) hook(layout, 'mousemoved', function (x, y, dx, dy)
if isMouseDown() then if isMouseDown() then

View File

@@ -90,16 +90,22 @@ local getMouseButtonId, isMouseDown
if love._version_minor < 10 then if love._version_minor < 10 then
getMouseButtonId = function (value) getMouseButtonId = function (value)
return value == 'l' and 1 return value == 'l' and 'left'
or value == 'r' and 2 or value == 'r' and 'right'
or value == 'm' and 3 or value == 'm' and 'middle'
or value == 'x1' and 4
or value == 'x2' and 5
or value
end end
isMouseDown = function () isMouseDown = function ()
return love.mouse.isDown('l', 'r', 'm') return love.mouse.isDown('l', 'r', 'm')
end end
else else
getMouseButtonId = function (value) getMouseButtonId = function (value)
return value return value == 1 and 'left'
or value == 2 and 'right'
or value == 3 and 'middle'
or value
end end
isMouseDown = function () isMouseDown = function ()
return love.mouse.isDown(1, 2, 3) return love.mouse.isDown(1, 2, 3)

View File

@@ -12,7 +12,7 @@ local function renderSingle (self, x, y, font, text, color)
love.graphics.push('all') love.graphics.push('all')
love.graphics.setColor(color or { 0, 0, 0 }) love.graphics.setColor(color or { 0, 0, 0 })
love.graphics.setFont(font.loveFont) love.graphics.setFont(font.loveFont)
love.graphics.print(text, x, y) love.graphics.print(text, math.floor(x), math.floor(y))
love.graphics.pop() love.graphics.pop()
self.height = font:getLineHeight() self.height = font:getLineHeight()
@@ -34,11 +34,14 @@ local function renderMulti (self, x, y, font, text, color, align, limit)
local w = line.width local w = line.width
if align == 'left' then if align == 'left' then
love.graphics.print(text, x, top + y) love.graphics.print(text,
math.floor(x), math.floor(top + y))
elseif align == 'right' then elseif align == 'right' then
love.graphics.print(text, limit - w + x, top + y) love.graphics.print(text,
math.floor(limit - w + x), math.floor(top + y))
elseif align == 'center' then elseif align == 'center' then
love.graphics.print(text, (limit - w) / 2 + x, top + y) love.graphics.print(text,
math.floor((limit - w) / 2 + x), math.floor(top + y))
end end
end end

View File

@@ -111,10 +111,10 @@ function Input:handlePressedMove (layout, x, y)
hit = nil hit = nil
widget = layout.root widget = layout.root
end end
for button = 1, 3 do for _, button in ipairs { 'left', 'middle', 'right' } do
local originWidget = self.pressedWidgets[button] local originWidget = self.pressedWidgets[button]
local passedWidget = self.passedWidgets[button]
if originWidget then if originWidget then
local passedWidget = self.passedWidgets[button]
originWidget:bubbleEvent('PressDrag', { originWidget:bubbleEvent('PressDrag', {
hit = hit, hit = hit,
newTarget = widget, newTarget = widget,
@@ -129,7 +129,9 @@ function Input:handlePressedMove (layout, x, y)
x = x, y = y x = x, y = y
}) })
else else
originWidget.pressed = (widget == originWidget) or nil if button == 'left' then
originWidget.pressed = (widget == originWidget) or nil
end
if passedWidget then if passedWidget then
passedWidget:bubbleEvent('PressLeave', { passedWidget:bubbleEvent('PressLeave', {
hit = hit, hit = hit,
@@ -161,10 +163,12 @@ function Input:handlePressStart (layout, button, x, y, widget, accelerator)
widget = layout.root widget = layout.root
end end
if hit then if hit then
widget.pressed = true
self.pressedWidgets[button] = widget self.pressedWidgets[button] = widget
self.passedWidgets[button] = widget self.passedWidgets[button] = widget
widget:focus() if button == 'left' then
widget.pressed = true
widget:focus()
end
end end
widget:bubbleEvent('PressStart', { widget:bubbleEvent('PressStart', {
hit = hit, hit = hit,
@@ -184,7 +188,7 @@ function Input:handlePressEnd (layout, button, x, y, widget, accelerator)
end 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 and button == 'left' then
originWidget.pressed = nil originWidget.pressed = nil
end end
widget:bubbleEvent('PressEnd', { widget:bubbleEvent('PressEnd', {

View File

@@ -270,7 +270,7 @@ function Layout:addDefaultHandlers ()
local acceleratedWidget = entry and entry[event.key] local acceleratedWidget = entry and entry[event.key]
if acceleratedWidget then if acceleratedWidget then
acceleratedWidget.hovered = true acceleratedWidget.hovered = true
self.input:handlePressStart(self, event.key, event.x, event.y, self.input:handlePressStart(self, 'left', event.x, event.y,
acceleratedWidget, event.key) acceleratedWidget, event.key)
return false return false
end end
@@ -289,7 +289,7 @@ function Layout:addDefaultHandlers ()
local widget = self.focusedWidget local widget = self.focusedWidget
if widget and event.key == 'space' or event.key == ' ' if widget and event.key == 'space' or event.key == ' '
or event.key == 'return' then or event.key == 'return' then
self.input:handlePressStart(self, event.key, event.x, event.y, self.input:handlePressStart(self, 'left', event.x, event.y,
widget, event.key) widget, event.key)
return false return false
end end
@@ -297,25 +297,25 @@ function Layout:addDefaultHandlers ()
self:onKeyRelease(function (event) self:onKeyRelease(function (event)
-- space / enter presses focused widget
local widget = self.focusedWidget
if widget and event.key == 'space' or event.key == ' '
or event.key == 'return' then
self.input:handlePressEnd(self, event.key, event.x, event.y,
widget, event.key)
return false
end
-- accelerators -- accelerators
local entry = self.accelerators[event.modifierFlags] local entry = self.accelerators[event.modifierFlags]
local acceleratedWidget = entry and entry[event.key] local acceleratedWidget = entry and entry[event.key]
if acceleratedWidget then if acceleratedWidget then
acceleratedWidget.hovered = false acceleratedWidget.hovered = false
self.input:handlePressEnd(self, event.key, event.x, event.y, self.input:handlePressEnd(self, 'left', event.x, event.y,
acceleratedWidget, event.key) acceleratedWidget, event.key)
return false return false
end end
-- space / enter presses focused widget
local widget = self.focusedWidget
if widget and event.key == 'space' or event.key == ' '
or event.key == 'return' then
self.input:handlePressEnd(self, 'left', event.x, event.y,
widget, event.key)
return false
end
end) end)
self:onWheelMove(function (event) self:onWheelMove(function (event)

View File

@@ -8,48 +8,76 @@ return function (config)
local textColor = config.textColor or { 0, 0, 0 } local textColor = config.textColor or { 0, 0, 0 }
local highlight = config.highlight or { 0x19, 0xAE, 0xFF } local highlight = config.highlight or { 0x19, 0xAE, 0xFF }
local button_pressed = resources .. 'button_pressed.png'
local button_focused = resources .. 'button_focused.png'
local button_hovered = resources .. 'button_hovered.png'
local button = resources .. 'button.png'
local check_checked_pressed = resources .. 'check_checked_pressed.png'
local check_unchecked_pressed = resources .. 'check_unchecked_pressed.png'
local check_checked_focused = resources .. 'check_checked_focused.png'
local check_unchecked_focused = resources .. 'check_unchecked_focused.png'
local check_checked = resources .. 'check_checked.png'
local check_unchecked = resources .. 'check_unchecked.png'
local radio_checked_pressed = resources .. 'radio_checked_pressed.png'
local radio_unchecked_pressed = resources .. 'radio_unchecked_pressed.png'
local radio_checked_focused = resources .. 'radio_checked_focused.png'
local radio_unchecked_focused = resources .. 'radio_unchecked_focused.png'
local radio_checked = resources .. 'radio_checked.png'
local radio_unchecked = resources .. 'radio_unchecked.png'
local triangle_left = resources .. 'triangle_left.png'
local triangle_up = resources .. 'triangle_up.png'
local triangle_right = resources .. 'triangle_right.png'
local triangle_down = resources .. 'triangle_down.png'
local text_focused = resources .. 'text_focused.png'
local text = resources .. 'text.png'
local function getButtonSlices (self) local function getButtonSlices (self)
return self.pressed and resources .. 'button_pressed.png' return self.pressed and button_pressed
or self.focused and resources .. 'button_focused.png' or self.focused and button_focused
or self.hovered and resources .. 'button_hovered.png' or self.hovered and button_hovered
or resources .. 'button.png' or button
end end
local function getCheckOrRadioIcon (self) local function getCheckIcon (self)
local prefix = resources .. self.type
if self.pressed then if self.pressed then
if self.value then return self.value and check_checked_pressed
return prefix .. '_checked_pressed.png' or check_unchecked_pressed
else
return prefix .. '_unchecked_pressed.png'
end
elseif self.focused then
if self.value then
return prefix .. '_checked_focused.png'
else
return prefix .. '_unchecked_focused.png'
end
else
if self.value then
return prefix .. '_checked.png'
else
return prefix .. '_unchecked.png'
end
end end
if self.focused then
return self.value and check_checked_focused
or check_unchecked_focused
end
return self.value and check_checked or check_unchecked
end end
local function getControlHeight (self) local function getControlHeight (self)
return self.flow == 'x' and 32 return self.flow == 'x' and self.minheight
end end
local function getControlWidth (self) local function getControlWidth (self)
return self.flow ~= 'x' and 32 return self.flow ~= 'x' and self.minwidth
end end
local function getMenuItemBackground (self) local function getMenuItemBackground (self)
return self.active and highlight return self.active and highlight
end end
local function getRadioIcon (self)
if self.pressed then
return self.value and radio_checked_pressed
or radio_unchecked_pressed
end
if self.focused then
return self.value and radio_checked_focused
or radio_unchecked_focused
end
return self.value and radio_checked or radio_unchecked
end
local function getSashBackground (self) local function getSashBackground (self)
return self.hovered and highlight or lineColor return self.hovered and highlight or lineColor
end end
@@ -63,22 +91,22 @@ return function (config)
end end
local function getStepperBeforeIcon (self) local function getStepperBeforeIcon (self)
return self.parent.flow == 'x' and resources .. 'triangle_left.png' return self.parent.flow == 'x' and triangle_left or triangle_up
or resources .. 'triangle_up.png'
end end
local function getStepperAfterIcon (self) local function getStepperAfterIcon (self)
return self.parent.flow == 'x' and resources .. 'triangle_right.png' return self.parent.flow == 'x' and triangle_right or triangle_down
or resources .. 'triangle_down.png'
end end
local function getTextSlices (self) local function getTextSlices (self)
return self.focused and resources .. 'text_focused.png' return self.focused and text_focused or text
or resources .. 'text.png'
end end
return { return {
control = {
-- generic types for widgets to inherit
Control = {
flow = 'x', flow = 'x',
height = getControlHeight, height = getControlHeight,
width = getControlWidth, width = getControlWidth,
@@ -89,28 +117,29 @@ return function (config)
margin = 2, margin = 2,
color = textColor, color = textColor,
}, },
Line = {
minheight = 24,
margin = 0,
padding = 4,
align = 'left middle',
},
-- widget types
button = { button = {
type = 'control', type = { 'Control' },
padding = 6, padding = 6,
slices = getButtonSlices, slices = getButtonSlices,
focusable = true, focusable = true,
}, },
check = { check = {
type = 'control', type = { 'Line', 'Control' },
focusable = true, focusable = true,
icon = getCheckOrRadioIcon, icon = getCheckIcon,
margin = 0,
padding = 4,
align = 'left middle',
minheight = 24,
}, },
label = { label = {
type = 'control', type = { 'Line', 'Control' },
align = 'left bottom',
margin = 0,
padding = 4,
minheight = 24,
height = 24,
}, },
menu = { menu = {
flow = 'x', flow = 'x',
@@ -132,23 +161,18 @@ return function (config)
color = textColor, color = textColor,
}, },
progress = { progress = {
type = 'control', type = { 'Control' },
slices = resources .. 'button_pressed.png', slices = resources .. 'button_pressed.png',
}, },
['progress.bar'] = { ['progress.bar'] = {
slices = resources .. 'progress.png', slices = resources .. 'progress.png',
minwidth = 12, minwidth = 12,
minheight= 22, minheight = 22,
}, },
radio = { radio = {
type = 'control', type = { 'Line', 'Control' },
focusable = true, focusable = true,
color = textColor, icon = getRadioIcon,
icon = getCheckOrRadioIcon,
margin = 0,
padding = 4,
align = 'left middle',
minheight = 24,
}, },
sash = { sash = {
background = getSashBackground, background = getSashBackground,
@@ -156,36 +180,32 @@ return function (config)
width = getSashWidth, width = getSashWidth,
}, },
slider = { slider = {
type = 'control', type = { 'Control' },
slices = resources .. 'button_pressed.png', slices = resources .. 'button_pressed.png',
}, },
['slider.thumb'] = { ['slider.thumb'] = {
type = 'button', type = { 'button' },
align = 'middle center', align = 'middle center',
margin = 0, margin = 0,
minwidth = 32, minwidth = 32,
minheight = 32, minheight = 32,
}, },
status = { status = {
background = backColor, type = { 'Line', 'Control' },
color = textColor,
align = 'left middle',
padding = 4,
height = 22,
}, },
stepper = { stepper = {
type = 'control', type = { 'Control' },
slices = resources .. 'button_pressed.png', slices = resources .. 'button_pressed.png',
}, },
['stepper.after'] = { ['stepper.after'] = {
type = 'button', type = { 'button' },
icon = getStepperAfterIcon, icon = getStepperAfterIcon,
margin = 0, margin = 0,
minwidth = 32, minwidth = 32,
minheight = 32, minheight = 32,
}, },
['stepper.before'] = { ['stepper.before'] = {
type = 'button', type = { 'button' },
icon = getStepperBeforeIcon, icon = getStepperBeforeIcon,
margin = 0, margin = 0,
minwidth = 32, minwidth = 32,
@@ -205,7 +225,7 @@ return function (config)
color = textColor, color = textColor,
}, },
text = { text = {
type = 'control', type = { 'Control' },
align = 'left middle', align = 'left middle',
slices = getTextSlices, slices = getTextSlices,
padding = 6, padding = 6,

View File

@@ -13,7 +13,8 @@ standard themes, the widget's value should be indicated in some other way.
--]]-- --]]--
return function (self) return function (self)
self:onPress(function () self:onPress(function (event)
if event.button ~= 'left' then return end
self.value = not self.value self.value = not self.value
end) end)

View File

@@ -87,6 +87,7 @@ local function deactivateSiblings (target)
end end
local function activate (event, ignoreIfNoneOpen) local function activate (event, ignoreIfNoneOpen)
if event.button and event.button ~= 'left' then return end
local target = event.target local target = event.target
while target.parent while target.parent
@@ -120,12 +121,13 @@ local function registerLayoutEvents (self)
if self.parentMenu == self.rootMenu then if self.parentMenu == self.rootMenu then
deactivateSiblings(self.rootMenu[1]) deactivateSiblings(self.rootMenu[1])
end end
else elseif event.button == 'left' then
activate(event) activate(event)
end end
end) end)
menuLayout:onPress(function (event) menuLayout:onPress(function (event)
if event.button ~= 'left' then return end
for widget in event.target:eachAncestor(true) do for widget in event.target:eachAncestor(true) do
if widget.type == 'menu.item' and #widget.items == 0 then if widget.type == 'menu.item' and #widget.items == 0 then
menuLayout:hide() menuLayout:hide()
@@ -135,6 +137,7 @@ local function registerLayoutEvents (self)
end) end)
menuLayout:onPressEnd(function (event) menuLayout:onPressEnd(function (event)
if event.button ~= 'left' then return end
for widget in event.target:eachAncestor(true) do for widget in event.target:eachAncestor(true) do
if widget.type == 'menu.item' and #widget.items == 0 if widget.type == 'menu.item' and #widget.items == 0
and event.target ~= event.origin then and event.target ~= event.origin then

View File

@@ -64,7 +64,8 @@ in the same group change to `false`.
@section end @section end
--]]-- --]]--
self:onPress(function () self:onPress(function (event)
if event.button ~= 'left' then return end
for _, widget in ipairs(groups[self.group]) do for _, widget in ipairs(groups[self.group]) do
widget.value = widget == self widget.value = widget == self
end end

View File

@@ -63,6 +63,7 @@ return function (self)
end) end)
self:onPressDrag(function (event) self:onPressDrag(function (event)
if event.button ~= 'left' then return end
local axis = self.parent.flow local axis = self.parent.flow
if axis == 'x' then if axis == 'x' then
dimension = 'width' dimension = 'width'

View File

@@ -21,7 +21,8 @@ return function (self)
type = 'slider.thumb', type = 'slider.thumb',
} }
local function unpress () local function unpress (event)
if event.button ~= 'left' then return end
thumb.pressed = false -- don't make the thumb appear pushed in thumb.pressed = false -- don't make the thumb appear pushed in
return false -- don't press thumb on focused keyboard activation return false -- don't press thumb on focused keyboard activation
end end
@@ -39,6 +40,7 @@ return function (self)
end) end)
local function press (event) local function press (event)
if event.button ~= 'left' then return end
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
if self.flow == 'x' then if self.flow == 'x' then

View File

@@ -94,10 +94,12 @@ Contains the index in `items` of the item being displayed.
end end
before:onPress(function (event) before:onPress(function (event)
if event.button ~= 'left' then return end
if self.flow == 'x' then decrement() else increment() end if self.flow == 'x' then decrement() else increment() end
end) end)
after:onPress(function (event) after:onPress(function (event)
if event.button ~= 'left' then return end
if self.flow == 'x' then increment() else decrement() end if self.flow == 'x' then increment() else decrement() end
end) end)

View File

@@ -29,7 +29,7 @@ local function scrollToCaret (self)
end end
local function findCaretFromText (self, text) local function findCaretFromText (self, text)
local font = self.fontData local font = self:getFont()
local x = self:getRectangle(true, true) local x = self:getRectangle(true, true)
return #text, font:getAdvance(text) + x - self.scrollX return #text, font:getAdvance(text) + x - self.scrollX
end end
@@ -178,12 +178,7 @@ local function insertText (self, newText)
end end
return function (self) return function (self)
if not self.fontData then
self.fontData = Backend.Font(self.font, self.size)
end
self.value = tostring(self.value or self.text or '') self.value = tostring(self.value or self.text or '')
self.text = '' self.text = ''
--[[-- --[[--
@@ -201,12 +196,14 @@ This color is used to indicate the selected range of text.
@attrib highlight @attrib highlight
--]]-- --]]--
self:defineAttribute('highlight') self:defineAttribute('highlight')
--[[-- --[[--
@section end @section end
--]]-- --]]--
if not self.highlight then if not self.highlight then
self.highlight = { 0x80, 0x80, 0x80 } self.highlight = { 0x80, 0x80, 0x80, 0x80 }
end end
self.scrollX = 0 self.scrollX = 0
@@ -214,11 +211,13 @@ This color is used to indicate the selected range of text.
setCaretFromText(self, self.value) setCaretFromText(self, self.value)
self:onPressStart(function (event) self:onPressStart(function (event)
if event.button ~= 'left' then return end
self.startIndex, self.startX = findCaretFromPoint(self, event.x) self.startIndex, self.startX = findCaretFromPoint(self, event.x)
self.endIndex, self.endX = self.startIndex, self.startX self.endIndex, self.endX = self.startIndex, self.startX
end) end)
self:onPressDrag(function (event) self:onPressDrag(function (event)
if event.button ~= 'left' then return end
self.endIndex, self.endX = findCaretFromPoint(self, event.x) self.endIndex, self.endX = findCaretFromPoint(self, event.x)
scrollToCaret(self) scrollToCaret(self)
end) end)