mirror of
https://github.com/airstruck/luigi.git
synced 2025-11-18 12:25:06 +00:00
add menus
This commit is contained in:
@@ -144,7 +144,7 @@
|
||||
</div> <!-- id="main" -->
|
||||
<div id="about">
|
||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.3</a></i>
|
||||
<i style="float:right;">Last updated 2015-11-04 15:07:53 </i>
|
||||
<i style="float:right;">Last updated 2015-11-06 00:18:26 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
|
||||
@@ -49,10 +49,16 @@
|
||||
<div id="content">
|
||||
|
||||
<h1>Class <code>Layout</code></h1>
|
||||
<p>Layout class.</p>
|
||||
<p>
|
||||
<p>A Layout contains a tree of widgets with a single <code>root</code> widget.</p>
|
||||
<p>Layouts will resize to fit the window unless a <code>top</code> or <code>left</code>
|
||||
property is found in the root widget.</p>
|
||||
|
||||
</p>
|
||||
<p>Layouts are drawn in the order that they were shown, so the
|
||||
most recently shown layout shown will always appear on top.</p>
|
||||
|
||||
<p>Other events are sent to layouts in the opposite direction,
|
||||
and are trapped by the first layout that can handle the event
|
||||
(for example, the topmost layer that is focused or hovered).</p>
|
||||
|
||||
|
||||
<h2><a href="#Functions">Functions</a></h2>
|
||||
@@ -289,7 +295,7 @@ found, and focuses that widget.
|
||||
</div> <!-- id="main" -->
|
||||
<div id="about">
|
||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.3</a></i>
|
||||
<i style="float:right;">Last updated 2015-11-04 15:07:53 </i>
|
||||
<i style="float:right;">Last updated 2015-11-06 00:18:26 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
|
||||
@@ -611,7 +611,7 @@ on the parent widget.
|
||||
</div> <!-- id="main" -->
|
||||
<div id="about">
|
||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.3</a></i>
|
||||
<i style="float:right;">Last updated 2015-11-04 15:07:53 </i>
|
||||
<i style="float:right;">Last updated 2015-11-06 00:18:26 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="classes/Layout.html">Layout</a></td>
|
||||
<td class="summary">Layout class.</td>
|
||||
<td class="summary">A Layout contains a tree of widgets with a single <code>root</code> widget.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="classes/Widget.html">Widget</a></td>
|
||||
@@ -64,7 +64,7 @@
|
||||
</div> <!-- id="main" -->
|
||||
<div id="about">
|
||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.3</a></i>
|
||||
<i style="float:right;">Last updated 2015-11-04 15:07:53 </i>
|
||||
<i style="float:right;">Last updated 2015-11-06 00:18:26 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
local Layout = require 'luigi.layout'
|
||||
|
||||
local style = {
|
||||
mainWindow = {
|
||||
width = 600,
|
||||
height = 400,
|
||||
},
|
||||
short = {
|
||||
height = 48,
|
||||
},
|
||||
@@ -36,7 +32,33 @@ local style = {
|
||||
},
|
||||
}
|
||||
|
||||
local mainForm = { title = "Test window", id = 'mainWindow', type = 'panel',
|
||||
local mainForm = { id = 'mainWindow', type = 'panel',
|
||||
{ type = 'menu', id = 'menubar', flow = 'x',
|
||||
{ text = 'File', id = 'menuFile',
|
||||
{ text = 'Save', id = 'menuFileSave', },
|
||||
{ text = 'Quit' },
|
||||
},
|
||||
{ text = 'Edit',
|
||||
{ text = 'Cut' },
|
||||
{ text = 'Copy' },
|
||||
{ text = 'Paste' },
|
||||
{ type = 'slider' },
|
||||
},
|
||||
{ text = 'View',
|
||||
{ text = 'Theme',
|
||||
{ text = 'Light' },
|
||||
{ text = 'Dark' },
|
||||
},
|
||||
{ text = 'Style',
|
||||
{ text = 'Default' },
|
||||
},
|
||||
},
|
||||
{ text = 'Help',
|
||||
{ text = 'About Luigi', icon = 'icon/16px/Book.png', key = 'backspace', },
|
||||
{ text = 'About Luigi Demo', icon = 'icon/16px/Book Red.png' },
|
||||
{ text = 'Licenses' },
|
||||
},
|
||||
},
|
||||
{ type = 'panel', id = 'toolbar', flow = 'x',
|
||||
{ type = 'button', id = 'newButton', style = 'toolButton', key = 'z',
|
||||
icon = 'icon/32px/Blueprint.png' },
|
||||
@@ -97,7 +119,8 @@ end)
|
||||
|
||||
layout:onMove(function (event)
|
||||
local w = event.target
|
||||
layout.statusbar.text = (w.id or '(unnamed)') .. ' ' ..
|
||||
layout.statusbar.text = (w.type or '(generic) ') ..
|
||||
(w.id or '(unnamed)') .. ' ' ..
|
||||
w:getX() .. ', ' .. w:getY() .. ' | ' ..
|
||||
w:getWidth() .. 'x' .. w:getHeight()
|
||||
end)
|
||||
@@ -107,6 +130,14 @@ layout.newButton:onMove(function (event)
|
||||
return false
|
||||
end)
|
||||
|
||||
local foo = Layout { float = true, height = 100,
|
||||
text = 'hello', align = 'center middle', background = {255,0,0}
|
||||
}
|
||||
|
||||
foo:onReshape(function (event)
|
||||
foo:hide()
|
||||
end)
|
||||
|
||||
layout.newButton:onPress(function (event)
|
||||
print('creating a new thing!')
|
||||
end)
|
||||
@@ -114,6 +145,11 @@ end)
|
||||
layout.aButton:onPress(function (event)
|
||||
layout.aButton.font = nil
|
||||
layout.aButton.width = layout.aButton.width + 10
|
||||
local w = layout.aButton:getWidth()
|
||||
foo.root.width = w * 2
|
||||
foo.root.left = layout.aButton:getX() - w
|
||||
foo.root.top = layout.aButton:getY() - foo.root.height
|
||||
foo:show()
|
||||
end)
|
||||
|
||||
layout.mainCanvas.font = 'font/liberation/LiberationMono-Regular.ttf'
|
||||
|
||||
@@ -37,7 +37,7 @@ function Font:setWidth (width)
|
||||
end
|
||||
|
||||
function Font:getLineHeight ()
|
||||
return self.font:getLineHeight()
|
||||
return self.font:getHeight()
|
||||
end
|
||||
|
||||
function Font:getAscender ()
|
||||
|
||||
@@ -23,7 +23,7 @@ local function unhook (item)
|
||||
item.func = nil
|
||||
end
|
||||
|
||||
local function hook (host, key, func)
|
||||
local function hook (host, key, func, atEnd)
|
||||
if not func then
|
||||
return
|
||||
end
|
||||
@@ -32,17 +32,30 @@ local function hook (host, key, func)
|
||||
hooks[host] = {}
|
||||
end
|
||||
|
||||
local next = hooks[host][key]
|
||||
local current = hooks[host][key]
|
||||
local item = {
|
||||
next = next,
|
||||
next = not atEnd and current or nil,
|
||||
unhook = unhook,
|
||||
host = host,
|
||||
key = key,
|
||||
func = func,
|
||||
}
|
||||
|
||||
if next then
|
||||
next.prev = item
|
||||
if atEnd then
|
||||
if current then
|
||||
while current.next do
|
||||
current = current.next
|
||||
end
|
||||
current.next = item
|
||||
item.prev = current
|
||||
else
|
||||
hooks[host][key] = item
|
||||
end
|
||||
return item
|
||||
end
|
||||
|
||||
if current then
|
||||
current.prev = item
|
||||
end
|
||||
|
||||
hooks[host][key] = item
|
||||
@@ -54,7 +67,7 @@ function Hooker.unhook (item)
|
||||
return unhook(item)
|
||||
end
|
||||
|
||||
function Hooker.hook (host, key, func)
|
||||
function Hooker.hook (host, key, func, atEnd)
|
||||
if not wrapped[host] then
|
||||
wrapped[host] = {}
|
||||
end
|
||||
@@ -68,16 +81,19 @@ function Hooker.hook (host, key, func)
|
||||
local item = hooks[host][key]
|
||||
|
||||
while item do
|
||||
local result = item.func(...)
|
||||
if result ~= nil then
|
||||
return result
|
||||
local nextItem = item.next
|
||||
if item.func then
|
||||
local result = item.func(...)
|
||||
if result ~= nil then
|
||||
return result
|
||||
end
|
||||
end
|
||||
item = item.next
|
||||
item = nextItem
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return hook(host, key, func)
|
||||
return hook(host, key, func, atEnd)
|
||||
end
|
||||
|
||||
return Hooker
|
||||
|
||||
127
luigi/input.lua
127
luigi/input.lua
@@ -8,62 +8,95 @@ local Input = Base:extend()
|
||||
|
||||
local weakValueMeta = { __mode = 'v' }
|
||||
|
||||
function Input:constructor (layout)
|
||||
self.layout = layout
|
||||
function Input:constructor () --(layout)
|
||||
-- layout = layout
|
||||
self.pressedWidgets = setmetatable({}, weakValueMeta)
|
||||
self.passedWidgets = setmetatable({}, weakValueMeta)
|
||||
end
|
||||
|
||||
function Input:handleDisplay ()
|
||||
local root = self.layout.root
|
||||
function Input:handleDisplay (layout)
|
||||
local root = layout.root
|
||||
if root then Renderer:render(root) end
|
||||
Event.Display:emit(self.layout)
|
||||
Event.Display:emit(layout)
|
||||
end
|
||||
|
||||
function Input:handleKeyPress (key, x, y)
|
||||
local widget = self.layout.focusedWidget or self.layout:getWidgetAt(x, y)
|
||||
function Input:handleKeyPress (layout, key, x, y)
|
||||
local widget = layout.focusedWidget or layout:getWidgetAt(x, y)
|
||||
local hit = true
|
||||
if not widget then
|
||||
hit = nil
|
||||
widget = layout.root
|
||||
end
|
||||
local result = widget:bubbleEvent('KeyPress', {
|
||||
hit = hit,
|
||||
key = key, x = x, y = y
|
||||
})
|
||||
if result ~= nil then return result end
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handleKeyRelease (key, x, y)
|
||||
local widget = self.layout.focusedWidget or self.layout:getWidgetAt(x, y)
|
||||
function Input:handleKeyRelease (layout, key, x, y)
|
||||
local widget = layout.focusedWidget or layout:getWidgetAt(x, y)
|
||||
local hit = true
|
||||
if not widget then
|
||||
hit = nil
|
||||
widget = layout.root
|
||||
end
|
||||
local result = widget:bubbleEvent('KeyRelease', {
|
||||
hit = hit,
|
||||
key = key, x = x, y = y
|
||||
})
|
||||
if result ~= nil then return result end
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handleTextInput (text, x, y)
|
||||
local widget = self.layout.focusedWidget or self.layout:getWidgetAt(x, y)
|
||||
function Input:handleTextInput (layout, text, x, y)
|
||||
local widget = layout.focusedWidget or layout:getWidgetAt(x, y)
|
||||
local hit = true
|
||||
if not widget then
|
||||
hit = nil
|
||||
widget = layout.root
|
||||
end
|
||||
widget:bubbleEvent('TextInput', {
|
||||
hit = hit,
|
||||
text = text, x = x, y = y
|
||||
})
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handleMove (x, y)
|
||||
local widget = self.layout:getWidgetAt(x, y)
|
||||
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 previousWidget = self.previousMoveWidget
|
||||
if not widget.hovered then
|
||||
if widget ~= previousWidget then
|
||||
if previousWidget then
|
||||
previousWidget.hovered = nil
|
||||
for ancestor in previousWidget:eachAncestor(true) do
|
||||
ancestor.hovered = nil
|
||||
end
|
||||
end
|
||||
for ancestor in widget:eachAncestor(true) do
|
||||
ancestor.hovered = true
|
||||
end
|
||||
widget.hovered = true
|
||||
end
|
||||
widget:bubbleEvent('Move', {
|
||||
hit = hit,
|
||||
oldTarget = previousWidget,
|
||||
x = x, y = y
|
||||
})
|
||||
if widget ~= previousWidget then
|
||||
if previousWidget then
|
||||
previousWidget:bubbleEvent('Leave', {
|
||||
hit = hit,
|
||||
newTarget = widget,
|
||||
x = x, y = y
|
||||
})
|
||||
end
|
||||
widget:bubbleEvent('Enter', {
|
||||
hit = hit,
|
||||
oldTarget = previousWidget,
|
||||
x = x, y = y
|
||||
})
|
||||
@@ -74,21 +107,29 @@ function Input:handleMove (x, y)
|
||||
end
|
||||
self.previousMoveWidget = widget
|
||||
end
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handlePressedMove (x, y)
|
||||
local widget = self.layout:getWidgetAt(x, y)
|
||||
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
|
||||
for button = 1, 3 do
|
||||
local originWidget = self.pressedWidgets[button]
|
||||
local passedWidget = self.passedWidgets[button]
|
||||
if originWidget then
|
||||
originWidget:bubbleEvent('PressDrag', {
|
||||
hit = hit,
|
||||
newTarget = widget,
|
||||
button = button,
|
||||
x = x, y = y
|
||||
})
|
||||
if (widget == passedWidget) then
|
||||
widget:bubbleEvent('PressMove', {
|
||||
hit = hit,
|
||||
origin = originWidget,
|
||||
button = button,
|
||||
x = x, y = y
|
||||
@@ -97,6 +138,7 @@ function Input:handlePressedMove (x, y)
|
||||
originWidget.pressed = (widget == originWidget) or nil
|
||||
if passedWidget then
|
||||
passedWidget:bubbleEvent('PressLeave', {
|
||||
hit = hit,
|
||||
newTarget = widget,
|
||||
origin = originWidget,
|
||||
button = button,
|
||||
@@ -104,42 +146,58 @@ function Input:handlePressedMove (x, y)
|
||||
})
|
||||
end
|
||||
widget:bubbleEvent('PressEnter', {
|
||||
oldTarget = passedWidget,
|
||||
origin = originWidget,
|
||||
button = button,
|
||||
x = x, y = y
|
||||
})
|
||||
hit = hit,
|
||||
oldTarget = passedWidget,
|
||||
origin = originWidget,
|
||||
button = button,
|
||||
x = x, y = y
|
||||
})
|
||||
self.passedWidgets[button] = widget
|
||||
end
|
||||
end
|
||||
end
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handlePressStart (button, x, y, widget, accelerator)
|
||||
local widget = widget or self.layout:getWidgetAt(x, y)
|
||||
function Input:handlePressStart (layout, button, x, y, widget, accelerator)
|
||||
local widget = widget or layout:getWidgetAt(x, y)
|
||||
local hit = true
|
||||
if not widget then
|
||||
hit = nil
|
||||
widget = layout.root
|
||||
end
|
||||
widget.pressed = true
|
||||
self.pressedWidgets[button] = widget
|
||||
self.passedWidgets[button] = widget
|
||||
widget:focus()
|
||||
widget:bubbleEvent('PressStart', {
|
||||
hit = hit,
|
||||
button = button,
|
||||
accelerator = accelerator,
|
||||
x = x, y = y
|
||||
})
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handlePressEnd (button, x, y, widget, accelerator)
|
||||
local widget = widget or self.layout:getWidgetAt(x, y)
|
||||
function Input:handlePressEnd (layout, button, x, y, widget, accelerator)
|
||||
local widget = widget or layout:getWidgetAt(x, y)
|
||||
local hit = true
|
||||
if not widget then
|
||||
hit = nil
|
||||
widget = layout.root
|
||||
end
|
||||
local originWidget = self.pressedWidgets[button]
|
||||
if not originWidget then return end
|
||||
originWidget.pressed = nil
|
||||
widget:bubbleEvent('PressEnd', {
|
||||
hit = hit,
|
||||
origin = originWidget,
|
||||
accelerator = accelerator,
|
||||
button = button, x = x, y = y
|
||||
})
|
||||
if (widget == originWidget) then
|
||||
widget:bubbleEvent('Press', {
|
||||
hit = hit,
|
||||
button = button,
|
||||
accelerator = accelerator,
|
||||
x = x, y = y
|
||||
@@ -147,13 +205,24 @@ function Input:handlePressEnd (button, x, y, widget, accelerator)
|
||||
end
|
||||
self.pressedWidgets[button] = nil
|
||||
self.passedWidgets[button] = nil
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handleReshape (width, height)
|
||||
local root = self.layout.root
|
||||
function Input:handleReshape (layout, width, height)
|
||||
local root = layout.root
|
||||
|
||||
Event.Reshape:emit(layout, {
|
||||
target = layout
|
||||
})
|
||||
|
||||
if root.float then
|
||||
return
|
||||
end
|
||||
|
||||
root.width = width
|
||||
root.height = height
|
||||
end
|
||||
|
||||
Input.default = Input()
|
||||
|
||||
return Input
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
--[[--
|
||||
Layout class.
|
||||
A Layout contains a tree of widgets with a single `root` widget.
|
||||
|
||||
Layouts will resize to fit the window unless a `top` or `left`
|
||||
property is found in the root widget.
|
||||
|
||||
Layouts are drawn in the order that they were shown, so the
|
||||
most recently shown layout shown will always appear on top.
|
||||
|
||||
Other events are sent to layouts in the opposite direction,
|
||||
and are trapped by the first layout that can handle the event
|
||||
(for example, the topmost layer that is focused or hovered).
|
||||
|
||||
@classmod Layout
|
||||
--]]--
|
||||
@@ -15,6 +25,8 @@ local Hooker = require(ROOT .. 'hooker')
|
||||
|
||||
local Layout = Base:extend()
|
||||
|
||||
Layout.isLayout = true
|
||||
|
||||
--[[--
|
||||
Layout constructor.
|
||||
|
||||
@@ -32,8 +44,7 @@ function Layout:constructor (data)
|
||||
self:setStyle()
|
||||
self:setTheme(require(ROOT .. 'theme.light'))
|
||||
|
||||
self.isMousePressed = false
|
||||
self.isManagingInput = false
|
||||
self.isShown = false
|
||||
self.hooks = {}
|
||||
self.root = data or {}
|
||||
Widget(self, self.root)
|
||||
@@ -71,20 +82,17 @@ Show the layout.
|
||||
Hooks all appropriate Love events and callbacks.
|
||||
--]]--
|
||||
function Layout:show ()
|
||||
if self.isShown then
|
||||
self:unhook() -- return
|
||||
self.isShown = nil
|
||||
end
|
||||
local root = self.root
|
||||
local width = root.width
|
||||
local height = root.height
|
||||
local title = root.title
|
||||
|
||||
if not self.input then
|
||||
self.input = Input(self)
|
||||
self.input = Input.default -- Input(self)
|
||||
end
|
||||
|
||||
local currentWidth, currentHeight, flags = love.window.getMode()
|
||||
love.window.setMode(width or currentWidth, height or currentHeight, flags)
|
||||
if title then
|
||||
love.window.setTitle(title)
|
||||
end
|
||||
self:manageInput(self.input)
|
||||
self:manageInput()
|
||||
root:reshape()
|
||||
end
|
||||
|
||||
@@ -94,10 +102,10 @@ Hide the layout.
|
||||
Unhooks Love events and callbacks.
|
||||
--]]--
|
||||
function Layout:hide ()
|
||||
if not self.isManagingInput then
|
||||
if not self.isShown then
|
||||
return
|
||||
end
|
||||
self.isManagingInput = false
|
||||
self.isShown = nil
|
||||
self:unhook()
|
||||
end
|
||||
|
||||
@@ -163,7 +171,7 @@ function Layout:getWidgetAt (x, y, root)
|
||||
if inner then return inner end
|
||||
end
|
||||
if widget:isAt(x, y) then return widget end
|
||||
if widget == self.root then return widget end
|
||||
-- if widget == self.root then return widget end
|
||||
end
|
||||
|
||||
-- Internal, called from Widget:new
|
||||
@@ -233,8 +241,8 @@ end
|
||||
|
||||
-- event stuff
|
||||
|
||||
function Layout:hook (key, method)
|
||||
self.hooks[#self.hooks + 1] = Hooker.hook(love, key, method)
|
||||
function Layout:hook (key, method, hookLast)
|
||||
self.hooks[#self.hooks + 1] = Hooker.hook(love, key, method, hookLast)
|
||||
end
|
||||
|
||||
function Layout:unhook ()
|
||||
@@ -244,7 +252,7 @@ function Layout:unhook ()
|
||||
self.hooks = {}
|
||||
end
|
||||
|
||||
local getMouseButtonId
|
||||
local getMouseButtonId, isMouseDown
|
||||
|
||||
if love._version_minor < 10 then
|
||||
getMouseButtonId = function (value)
|
||||
@@ -252,47 +260,56 @@ if love._version_minor < 10 then
|
||||
or value == 'r' and 2
|
||||
or value == 'm' and 3
|
||||
end
|
||||
isMouseDown = function ()
|
||||
return love.mouse.isDown('l', 'r', 'm')
|
||||
end
|
||||
else
|
||||
getMouseButtonId = function (value)
|
||||
return value
|
||||
end
|
||||
isMouseDown = function ()
|
||||
return love.mouse.isDown(1, 2, 3)
|
||||
end
|
||||
end
|
||||
|
||||
function Layout:manageInput (input)
|
||||
if self.isManagingInput then
|
||||
function Layout:manageInput ()
|
||||
if self.isShown then
|
||||
return
|
||||
end
|
||||
self.isManagingInput = true
|
||||
self.isShown = true
|
||||
|
||||
local input = self.input
|
||||
|
||||
self:hook('draw', function ()
|
||||
input:handleDisplay()
|
||||
end)
|
||||
input:handleDisplay(self)
|
||||
end, true)
|
||||
self:hook('resize', function (width, height)
|
||||
return input:handleReshape(width, height)
|
||||
return input:handleReshape(self, width, height)
|
||||
end)
|
||||
self:hook('mousepressed', function (x, y, button)
|
||||
self.isMousePressed = true
|
||||
return input:handlePressStart(getMouseButtonId(button), x, y)
|
||||
return input:handlePressStart(self, getMouseButtonId(button), x, y)
|
||||
end)
|
||||
self:hook('mousereleased', function (x, y, button)
|
||||
self.isMousePressed = false
|
||||
return input:handlePressEnd(getMouseButtonId(button), x, y)
|
||||
return input:handlePressEnd(self, getMouseButtonId(button), x, y)
|
||||
end)
|
||||
self:hook('mousemoved', function (x, y, dx, dy)
|
||||
if self.isMousePressed then
|
||||
return input:handlePressedMove(x, y)
|
||||
if isMouseDown() then
|
||||
return input:handlePressedMove(self, x, y)
|
||||
else
|
||||
return input:handleMove(x, y)
|
||||
return input:handleMove(self, x, y)
|
||||
end
|
||||
end)
|
||||
self:hook('keypressed', function (key, isRepeat)
|
||||
return input:handleKeyPress(key, love.mouse.getX(), love.mouse.getY())
|
||||
return input:handleKeyPress(
|
||||
self, key, love.mouse.getX(), love.mouse.getY())
|
||||
end)
|
||||
self:hook('keyreleased', function (key)
|
||||
return input:handleKeyRelease(key, love.mouse.getX(), love.mouse.getY())
|
||||
return input:handleKeyRelease(
|
||||
self, key, love.mouse.getX(), love.mouse.getY())
|
||||
end)
|
||||
self:hook('textinput', function (text)
|
||||
return input:handleTextInput(text, love.mouse.getX(), love.mouse.getY())
|
||||
return input:handleTextInput(
|
||||
self, text, love.mouse.getX(), love.mouse.getY())
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
@@ -69,7 +69,9 @@ function Style:eachName (object)
|
||||
end
|
||||
return function ()
|
||||
if not checkLookupProp() then return end
|
||||
local specialName = getSpecialName { 'pressed', 'focused', 'hovered' }
|
||||
local specialName = getSpecialName {
|
||||
'pressed', 'focused', 'hovered', 'active',
|
||||
}
|
||||
if specialName then return specialName end
|
||||
lookupPropIndex = lookupPropIndex + 1
|
||||
return lookupProp[lookupPropIndex]
|
||||
|
||||
@@ -25,6 +25,21 @@ return function (config)
|
||||
button_pressed = {
|
||||
slices = RESOURCE .. 'button_pressed.png',
|
||||
},
|
||||
menu = {
|
||||
height = 24,
|
||||
},
|
||||
['menu.item'] = {
|
||||
padding = 4,
|
||||
align = 'left middle',
|
||||
},
|
||||
['menu.item_active'] = {
|
||||
background = highlight,
|
||||
},
|
||||
submenu = {
|
||||
padding = 10,
|
||||
margin = -10,
|
||||
slices = RESOURCE .. 'submenu.png',
|
||||
},
|
||||
sash = {
|
||||
background = lineColor
|
||||
},
|
||||
@@ -46,7 +61,7 @@ return function (config)
|
||||
minwidth = 24,
|
||||
minheight = 24
|
||||
},
|
||||
progressInner = {
|
||||
['progress.bar'] = {
|
||||
slices = RESOURCE .. 'progress.png',
|
||||
padding = 0,
|
||||
minwidth = 12,
|
||||
|
||||
BIN
luigi/theme/light/submenu.png
Normal file
BIN
luigi/theme/light/submenu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 786 B |
@@ -17,6 +17,8 @@ Widget.isWidget = true
|
||||
|
||||
Widget.typeDecorators = {
|
||||
button = require(ROOT .. 'widget.button'),
|
||||
menu = require(ROOT .. 'widget.menu'),
|
||||
['menu.item'] = require(ROOT .. 'widget.menu.item'),
|
||||
progress = require(ROOT .. 'widget.progress'),
|
||||
sash = require(ROOT .. 'widget.sash'),
|
||||
slider = require(ROOT .. 'widget.slider'),
|
||||
@@ -55,14 +57,14 @@ local function metaNewIndex (self, property, value)
|
||||
end
|
||||
|
||||
if property == 'width' then
|
||||
value = math.max(value, self.minwidth or 0)
|
||||
value = value and math.max(value, self.minwidth or 0)
|
||||
self.shadowProperties[property] = value
|
||||
Widget.reshape(self.parent or self)
|
||||
return
|
||||
end
|
||||
|
||||
if property == 'height' then
|
||||
value = math.max(value, self.minheight or 0)
|
||||
value = value and math.max(value, self.minheight or 0)
|
||||
self.shadowProperties[property] = value
|
||||
Widget.reshape(self.parent or self)
|
||||
return
|
||||
@@ -89,7 +91,7 @@ A Widget instance.
|
||||
local function metaCall (Widget, layout, self)
|
||||
self = self or {}
|
||||
self.layout = layout
|
||||
self.children = {}
|
||||
self.children = self.children or {}
|
||||
self.position = { x = nil, y = nil }
|
||||
self.dimensions = { width = nil, height = nil }
|
||||
self.shadowProperties = {}
|
||||
@@ -295,6 +297,7 @@ function Widget:addChild (data)
|
||||
|
||||
table.insert(self.children, child)
|
||||
child.parent = self
|
||||
child.layout = self.layout
|
||||
|
||||
return child
|
||||
end
|
||||
@@ -375,8 +378,9 @@ function Widget:calculatePosition (axis)
|
||||
end
|
||||
local parent = self.parent
|
||||
if not parent then
|
||||
self.position[axis] = 0
|
||||
return 0
|
||||
self.position[axis] = axis == 'x' and (self.left or 0)
|
||||
or axis == 'y' and (self.top or 0)
|
||||
return self.position[axis]
|
||||
end
|
||||
local parentPos = parent:calculatePosition(axis)
|
||||
local p = parentPos
|
||||
@@ -555,7 +559,7 @@ function Widget:isAt (x, y)
|
||||
checkReshape(self)
|
||||
|
||||
local x1, y1, x2, y2 = self:getRectangle()
|
||||
return (x1 < x) and (x2 > x) and (y1 < y) and (y2 > y)
|
||||
return (x1 <= x) and (x2 >= x) and (y1 <= y) and (y2 >= y)
|
||||
end
|
||||
|
||||
function Widget:eachAncestor (includeSelf)
|
||||
|
||||
9
luigi/widget/menu.lua
Normal file
9
luigi/widget/menu.lua
Normal file
@@ -0,0 +1,9 @@
|
||||
return function (self)
|
||||
|
||||
for index, child in ipairs(self) do
|
||||
child.type = child.type or 'menu.item'
|
||||
child.parentMenu = self
|
||||
child.rootMenu = self
|
||||
end
|
||||
|
||||
end
|
||||
169
luigi/widget/menu/item.lua
Normal file
169
luigi/widget/menu/item.lua
Normal file
@@ -0,0 +1,169 @@
|
||||
local ROOT = (...):gsub('[^.]*.[^.]*.[^.]*$', '')
|
||||
|
||||
local Layout
|
||||
|
||||
local show
|
||||
|
||||
local function deactivateSiblings (target)
|
||||
local sibling = target.parent and target.parent.children[1]
|
||||
local wasSiblingOpen
|
||||
|
||||
if not sibling then
|
||||
return
|
||||
end
|
||||
|
||||
while sibling do
|
||||
local layout = sibling.menuLayout
|
||||
|
||||
sibling.active = nil
|
||||
|
||||
if layout and layout.isShown then
|
||||
wasSiblingOpen = true
|
||||
layout:hide()
|
||||
end
|
||||
|
||||
if sibling.items and sibling.items[1] then
|
||||
deactivateSiblings(sibling.items[1])
|
||||
end
|
||||
|
||||
sibling = sibling:getNextSibling()
|
||||
end
|
||||
|
||||
return wasSiblingOpen
|
||||
end
|
||||
|
||||
local function activate (event, ignoreIfNoneOpen)
|
||||
local target = event.target
|
||||
|
||||
while target.parent
|
||||
and target.parent.type ~= 'menu' and target.parent.type ~= 'submenu' do
|
||||
target = target.parent
|
||||
if not target then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local wasSiblingOpen = deactivateSiblings(target)
|
||||
local ignore = ignoreIfNoneOpen and not wasSiblingOpen
|
||||
|
||||
if not ignore then
|
||||
show(target)
|
||||
target.active = true
|
||||
end
|
||||
end
|
||||
|
||||
show = function (self)
|
||||
if not self.items or #self.items < 1 then
|
||||
return
|
||||
end
|
||||
if self.menuLayout then
|
||||
self.menuLayout:show()
|
||||
return
|
||||
end
|
||||
|
||||
local Layout = Layout or require(ROOT .. 'layout')
|
||||
|
||||
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
|
||||
|
||||
local x = isSubmenu and self:getWidth() or 0
|
||||
local y = isSubmenu and 0 or self:getHeight()
|
||||
|
||||
local menuLayout = Layout {
|
||||
type = 'submenu',
|
||||
left = self:getX() + x,
|
||||
top = self:getY() + y,
|
||||
width = 0,
|
||||
height = 0,
|
||||
}
|
||||
|
||||
local root = menuLayout.root
|
||||
|
||||
local rootPad = root.padding or 0
|
||||
|
||||
local textWidth = 0
|
||||
local keyWidth = 0
|
||||
|
||||
for index, child in ipairs(self.items) do
|
||||
child.type = child.type or 'menu.item'
|
||||
root:addChild(child)
|
||||
local h = child:getHeight()
|
||||
root.height = root:getHeight() + h
|
||||
if child.type == 'menu.item' then
|
||||
local pad = child.padding or 0
|
||||
local tw = child.fontData:getAdvance(child.children[2].text)
|
||||
+ pad * 2 + h
|
||||
local kw = child.fontData:getAdvance(child.children[3].text)
|
||||
+ pad * 2
|
||||
textWidth = math.max(textWidth, tw)
|
||||
keyWidth = math.max(keyWidth, kw)
|
||||
end
|
||||
end
|
||||
|
||||
root.width = textWidth + keyWidth + rootPad
|
||||
|
||||
menuLayout:onReshape(function (event)
|
||||
menuLayout:hide()
|
||||
deactivateSiblings(self.rootMenu.children[1])
|
||||
end)
|
||||
|
||||
menuLayout:onPressStart(function (event)
|
||||
if not event.hit then
|
||||
menuLayout:hide()
|
||||
deactivateSiblings(self.rootMenu.children[1])
|
||||
end
|
||||
activate(event)
|
||||
end)
|
||||
|
||||
menuLayout:onEnter(activate)
|
||||
|
||||
menuLayout:onPressEnter(activate)
|
||||
|
||||
menuLayout:show()
|
||||
|
||||
self.menuLayout = menuLayout
|
||||
end
|
||||
|
||||
local function extractChild (self, index, child)
|
||||
self[index] = nil
|
||||
self.items[#self.items + 1] = child
|
||||
child.parentMenu = self
|
||||
child.rootMenu = self.rootMenu
|
||||
child.type = child.type or 'menu.item'
|
||||
end
|
||||
|
||||
return function (self)
|
||||
local pad = self.padding or 0
|
||||
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
|
||||
local text, key, icon = self.text or '', self.key or '', self.icon
|
||||
local textWidth = self.fontData:getAdvance(text) + pad * 2
|
||||
|
||||
self.items = self.items or {}
|
||||
|
||||
for index, child in ipairs(self) do
|
||||
extractChild(self, index, child)
|
||||
end
|
||||
|
||||
if isSubmenu then
|
||||
self.height = self.fontData:getLineHeight() + pad * 2
|
||||
self.flow = 'x'
|
||||
self:addChild({ icon = icon, width = self.height })
|
||||
self:addChild({ text = text, width = textWidth })
|
||||
self:addChild({ text = key, align = 'right', minwidth = self.height })
|
||||
|
||||
self.icon = nil
|
||||
self.text = nil
|
||||
else
|
||||
self.width = textWidth
|
||||
end
|
||||
|
||||
self:onPressStart(activate)
|
||||
|
||||
self:onEnter(function (event)
|
||||
activate(event, true)
|
||||
end)
|
||||
|
||||
self:onPressEnter(function (event)
|
||||
activate(event, true)
|
||||
end)
|
||||
|
||||
end
|
||||
@@ -3,7 +3,7 @@ return function (self)
|
||||
self.flow = 'x' -- TODO: support vertical progress?
|
||||
|
||||
local bar = self:addChild {
|
||||
type = 'progressInner',
|
||||
type = 'progress.bar',
|
||||
width = 0,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user