mirror of
https://github.com/airstruck/luigi.git
synced 2025-11-18 12:25:06 +00:00
attrib "key" -> "shortcut", also fix #20
This commit is contained in:
@@ -124,10 +124,10 @@
|
||||
The cursor left a widget, and a button was pressed.
|
||||
</li>
|
||||
<li><span class="parameter">PressStart</span>
|
||||
A pointer button or accelerator key was pressed.
|
||||
A pointer button or keyboard shortcut was pressed.
|
||||
</li>
|
||||
<li><span class="parameter">PressEnd</span>
|
||||
A pointer button or accelerator key was released.
|
||||
A pointer button or keyboard shortcut was released.
|
||||
</li>
|
||||
<li><span class="parameter">PressDrag</span>
|
||||
A pressed cursor moved; targets originating widget.
|
||||
|
||||
@@ -106,7 +106,7 @@ to recalculate their size and position.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#key">key</a></td>
|
||||
<td class="summary">Keyboard accelerator.</td>
|
||||
<td class="summary">Keyboard shortcut.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a href="#Size_Attributes">Size Attributes </a></h2>
|
||||
@@ -362,7 +362,7 @@ its scroll position when the widget's contents overflow its boundary.
|
||||
<strong>key</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Keyboard accelerator. </p>
|
||||
Keyboard shortcut. </p>
|
||||
|
||||
<p>Should contain a string representing a key and optional modifiers,
|
||||
separated by dashes; for example <code>'ctrl-c'</code> or <code>'alt-shift-escape'</code>.</p>
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
return { id = 'mainWindow',
|
||||
{ type = 'menu',
|
||||
{ text = 'File',
|
||||
{ text = 'Save', id = 'menuSave', key = 'ctrl-s',
|
||||
{ text = 'Save', id = 'menuSave', shortcut = 'ctrl-s',
|
||||
status = 'Save to disk' },
|
||||
{ text = 'Quit', id = 'menuQuit', key = 'escape',
|
||||
{ text = 'Quit', id = 'menuQuit', shortcut = 'escape',
|
||||
status = 'Quit the demo' },
|
||||
},
|
||||
{ text = 'Edit',
|
||||
{ text = 'Cut', key = 'ctrl-c' },
|
||||
{ text = 'Copy', key = 'ctrl-x' },
|
||||
{ text = 'Paste', key = 'ctrl-v' },
|
||||
{ text = 'Cut', shortcut = 'ctrl-c' },
|
||||
{ text = 'Copy', shortcut = 'ctrl-x' },
|
||||
{ text = 'Paste', shortcut = 'ctrl-v' },
|
||||
{ type = 'slider' },
|
||||
},
|
||||
{ text = 'View',
|
||||
{ text = 'Theme',
|
||||
{ text = 'Light', key = 'ctrl-l', id = 'themeLight', },
|
||||
{ text = 'Dark', key = 'ctrl-d', id = 'themeDark' },
|
||||
{ text = 'Light', shortcut = 'ctrl-l', id = 'themeLight', },
|
||||
{ text = 'Dark', shortcut = 'ctrl-d', id = 'themeDark' },
|
||||
},
|
||||
{ text = 'Style',
|
||||
{ text = 'Default' },
|
||||
},
|
||||
},
|
||||
{ text = 'Help',
|
||||
{ id = 'about', text = 'About Luigi', icon = 'icon/16px/Book.png', key = 'f1', },
|
||||
{ id = 'aboutDemo', text = 'About Luigi Demo', icon = 'icon/16px/Book Red.png', key = 'f2' },
|
||||
{ id = 'license', text = 'License', key = 'f3' },
|
||||
{ id = 'about', text = 'About Luigi', icon = 'icon/16px/Book.png', shortcut = 'f1', },
|
||||
{ id = 'aboutDemo', text = 'About Luigi Demo', icon = 'icon/16px/Book Red.png', shortcut = 'f2' },
|
||||
{ id = 'license', text = 'License', shortcut = 'f3' },
|
||||
},
|
||||
},
|
||||
{ style = 'toolbar',
|
||||
{ id = 'newButton', style = 'toolButton', key = 'z',
|
||||
{ id = 'newButton', style = 'toolButton', shortcut = 'z',
|
||||
icon = 'icon/32px/Blueprint.png',
|
||||
status = 'Create a new thing' },
|
||||
{ id = 'loadButton', style = 'toolButton',
|
||||
@@ -88,10 +88,12 @@ return { id = 'mainWindow',
|
||||
{ type = 'label', text = 'Flow test' },
|
||||
{ type = 'check', text = 'Vertical controls', id = 'flowToggle', },
|
||||
{ type = 'label', text = 'Some radio widgets' },
|
||||
{ type = 'radio', text = 'One fish' },
|
||||
{ type = 'radio', text = 'Two fish' },
|
||||
{ type = 'radio', text = 'Red fish' },
|
||||
{ type = 'radio', text = 'Blue fish' },
|
||||
{
|
||||
{ type = 'radio', text = 'One fish' },
|
||||
{ type = 'radio', text = 'Two fish' },
|
||||
{ type = 'radio', text = 'Red fish' },
|
||||
{ type = 'radio', text = 'Blue fish' },
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -128,22 +128,9 @@ Attribute.context = {}
|
||||
|
||||
function Attribute.context.set (widget, value)
|
||||
widget.attributes.context = value
|
||||
for i = #widget, 1, -1 do
|
||||
local child = widget[i]
|
||||
if child.isContextMenu then
|
||||
table.remove(widget, i)
|
||||
end
|
||||
end
|
||||
if not value then return end
|
||||
widget:addChild {
|
||||
type = 'menu',
|
||||
isContextMenu = true,
|
||||
width = 0,
|
||||
height = 0,
|
||||
value
|
||||
}
|
||||
value.menuLayout.isContextMenu = true
|
||||
widget.contextMenu = value
|
||||
value.isContextMenu = true
|
||||
widget.layout:createWidget { type = 'menu', value }
|
||||
end
|
||||
|
||||
Attribute.context.get = cascade
|
||||
@@ -218,7 +205,7 @@ Should contain `true` if the widget can be focused by pressing the tab key.
|
||||
Attribute.focusable = {}
|
||||
|
||||
--[[--
|
||||
Keyboard accelerator.
|
||||
Keyboard shortcut.
|
||||
|
||||
Should contain a string representing a key and optional modifiers,
|
||||
separated by dashes; for example `'ctrl-c'` or `'alt-shift-escape'`.
|
||||
@@ -228,25 +215,25 @@ as if it had been pressed with a mouse or touch interface.
|
||||
|
||||
Setting this attribute re-registers the widget with its layout.
|
||||
|
||||
@attrib key
|
||||
@attrib shortcut
|
||||
--]]--
|
||||
Attribute.key = {}
|
||||
Attribute.shortcut = {}
|
||||
|
||||
function Attribute.key.set (widget, value)
|
||||
function Attribute.shortcut.set (widget, value)
|
||||
local layout = widget.layout.master or widget.layout
|
||||
local oldValue = widget.attributes.key
|
||||
local oldValue = widget.attributes.shortcut
|
||||
|
||||
if oldValue then
|
||||
local mainKey, modifierFlags = parseKeyCombo(oldValue)
|
||||
layout.accelerators[modifierFlags][mainKey] = nil
|
||||
layout.shortcuts[modifierFlags][mainKey] = nil
|
||||
end
|
||||
|
||||
if value then
|
||||
local mainKey, modifierFlags = parseKeyCombo(value)
|
||||
layout.accelerators[modifierFlags][mainKey] = widget
|
||||
layout.shortcuts[modifierFlags][mainKey] = widget
|
||||
end
|
||||
|
||||
widget.attributes.key = value
|
||||
widget.attributes.shortcut = value
|
||||
end
|
||||
|
||||
--[[--
|
||||
|
||||
@@ -56,8 +56,12 @@ local callback = {
|
||||
|
||||
Backend.run = function ()
|
||||
local event = sdl.Event()
|
||||
local tickInterval = 16 -- ~60 fps (with room)
|
||||
local nextTick = 0
|
||||
local sdl = sdl
|
||||
|
||||
while true do
|
||||
|
||||
sdl.pumpEvents()
|
||||
|
||||
while sdl.pollEvent(event) ~= 0 do
|
||||
@@ -94,8 +98,14 @@ Backend.run = function ()
|
||||
sdl.setRenderDrawColor(renderer, 0, 0, 0, 255)
|
||||
sdl.renderClear(renderer)
|
||||
callback.draw()
|
||||
|
||||
local now = sdl.getTicks()
|
||||
if nextTick > now then
|
||||
sdl.delay(nextTick - now)
|
||||
end
|
||||
nextTick = now + tickInterval
|
||||
|
||||
sdl.renderPresent(renderer)
|
||||
sdl.delay(1)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -185,9 +195,7 @@ Backend.getMousePosition = function ()
|
||||
end
|
||||
|
||||
local function SystemCursor (id)
|
||||
local cursor = sdl.createSystemCursor(id)
|
||||
ffi.gc(cursor, sdl.freeCursor)
|
||||
return cursor
|
||||
return ffi.gc(sdl.createSystemCursor(id), sdl.freeCursor)
|
||||
end
|
||||
|
||||
local systemCursors = {
|
||||
@@ -258,13 +266,17 @@ end
|
||||
local lastScissor
|
||||
|
||||
Backend.setScissor = function (x, y, w, h)
|
||||
-- y = y and Backend.getWindowHeight() - (y + h)
|
||||
lastScissor = x and sdl.Rect(x, y, w, h)
|
||||
sdl.renderSetClipRect(renderer, lastScissor)
|
||||
end
|
||||
|
||||
Backend.getScissor = function ()
|
||||
if lastScissor ~= nil then
|
||||
return lastScissor.x, lastScissor.y, lastScissor.w, lastScissor.h
|
||||
local x, y = lastScissor.x, lastScissor.y
|
||||
local w, h = lastScissor.w, lastScissor.h
|
||||
-- y = y and Backend.getWindowHeight() - (y + h)
|
||||
return x, y, w, h
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ Event.names = {
|
||||
'Leave', -- The cursor left a widget, and no button was pressed.
|
||||
'PressEnter', -- The cursor entered a widget, and a button was pressed.
|
||||
'PressLeave', -- The cursor left a widget, and a button was pressed.
|
||||
'PressStart', -- A pointer button or accelerator key was pressed.
|
||||
'PressEnd', -- A pointer button or accelerator key was released.
|
||||
'PressStart', -- A pointer button or keyboard shortcut was pressed.
|
||||
'PressEnd', -- A pointer button or keyboard shortcut was released.
|
||||
'PressDrag', -- A pressed cursor moved; targets originating widget.
|
||||
'PressMove', -- A pressed cursor moved; targets widget at cursor position.
|
||||
'Press', -- A pointer button was pressed and released on the same widget.
|
||||
|
||||
@@ -147,12 +147,12 @@ function Input:handlePressedMove (layout, x, y)
|
||||
})
|
||||
self.passedWidgets[button] = widget
|
||||
end
|
||||
end
|
||||
end
|
||||
end -- if originWidget
|
||||
end -- mouse buttons
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handlePressStart (layout, button, x, y, widget, accelerator)
|
||||
function Input:handlePressStart (layout, button, x, y, widget, shortcut)
|
||||
local widget = widget or layout:getWidgetAt(x, y)
|
||||
local hit = true
|
||||
if not widget then
|
||||
@@ -170,13 +170,13 @@ function Input:handlePressStart (layout, button, x, y, widget, accelerator)
|
||||
widget:bubbleEvent('PressStart', {
|
||||
hit = hit,
|
||||
button = button,
|
||||
accelerator = accelerator,
|
||||
shortcut = shortcut,
|
||||
x = x, y = y
|
||||
})
|
||||
return hit
|
||||
end
|
||||
|
||||
function Input:handlePressEnd (layout, button, x, y, widget, accelerator)
|
||||
function Input:handlePressEnd (layout, button, x, y, widget, shortcut)
|
||||
local widget = widget or layout:getWidgetAt(x, y)
|
||||
local hit = true
|
||||
if not widget then
|
||||
@@ -191,7 +191,7 @@ function Input:handlePressEnd (layout, button, x, y, widget, accelerator)
|
||||
widget:bubbleEvent('PressEnd', {
|
||||
hit = hit,
|
||||
origin = originWidget,
|
||||
accelerator = accelerator,
|
||||
shortcut = shortcut,
|
||||
button = button,
|
||||
x = x, y = y
|
||||
})
|
||||
@@ -199,7 +199,7 @@ function Input:handlePressEnd (layout, button, x, y, widget, accelerator)
|
||||
widget:bubbleEvent('Press', {
|
||||
hit = hit,
|
||||
button = button,
|
||||
accelerator = accelerator,
|
||||
shortcut = shortcut,
|
||||
x = x, y = y
|
||||
})
|
||||
end
|
||||
|
||||
@@ -60,6 +60,25 @@ function Layout:constructor (data, master)
|
||||
self.isReady = true
|
||||
end
|
||||
|
||||
--[[--
|
||||
Create a detached widget.
|
||||
|
||||
Internal function used to create widgets that are associated with
|
||||
a layout, but "detached" from it.
|
||||
|
||||
Used by context menus, which use their "owner" widget's layout
|
||||
for theme and style information but appear in a separate layout.
|
||||
|
||||
@tparam table data
|
||||
A tree of widget data.
|
||||
|
||||
@treturn Widget
|
||||
A widget instance.
|
||||
--]]--
|
||||
function Layout:createWidget (data)
|
||||
return Widget(self, data)
|
||||
end
|
||||
|
||||
local function clearWidget (widget)
|
||||
widget.textData = nil
|
||||
widget.fontData = nil
|
||||
@@ -97,10 +116,6 @@ Master layout
|
||||
function Layout:setMaster (layout)
|
||||
self.master = layout
|
||||
|
||||
function self:addWidget (...)
|
||||
return layout:addWidget(...)
|
||||
end
|
||||
|
||||
reset(self)
|
||||
return self
|
||||
end
|
||||
@@ -259,12 +274,12 @@ function Layout:getWidgetAt (x, y, root)
|
||||
if root:isAt(x, y) then return root end
|
||||
end
|
||||
|
||||
-- Add handlers for keyboard accelerators, tab focus, and mouse wheel scroll
|
||||
-- Add handlers for keyboard shortcuts, tab focus, and mouse wheel scroll
|
||||
function Layout:addDefaultHandlers ()
|
||||
self.accelerators = {}
|
||||
self.shortcuts = {}
|
||||
|
||||
for i = 0, 8 do
|
||||
self.accelerators[i] = {}
|
||||
self.shortcuts[i] = {}
|
||||
end
|
||||
|
||||
self:onPressStart(function (event)
|
||||
@@ -299,8 +314,8 @@ function Layout:addDefaultHandlers ()
|
||||
|
||||
self:onKeyPress(function (event)
|
||||
|
||||
-- keyboard accelerators
|
||||
local entry = self.accelerators[event.modifierFlags]
|
||||
-- keyboard shortcuts
|
||||
local entry = self.shortcuts[event.modifierFlags]
|
||||
local acceleratedWidget = entry and entry[event.key]
|
||||
if acceleratedWidget then
|
||||
acceleratedWidget.hovered = true
|
||||
@@ -331,8 +346,8 @@ function Layout:addDefaultHandlers ()
|
||||
|
||||
self:onKeyRelease(function (event)
|
||||
|
||||
-- accelerators
|
||||
local entry = self.accelerators[event.modifierFlags]
|
||||
-- shortcuts
|
||||
local entry = self.shortcuts[event.modifierFlags]
|
||||
local acceleratedWidget = entry and entry[event.key]
|
||||
|
||||
if acceleratedWidget then
|
||||
|
||||
@@ -239,6 +239,10 @@ end
|
||||
--[[--
|
||||
Define a custom attribute for this widget.
|
||||
|
||||
When an attribute is defined, the current value is stored locally and
|
||||
removed from the widget's own properties and its attributes collection.
|
||||
Then, the newly-defined setter is called with the stored value.
|
||||
|
||||
@tparam string name
|
||||
The name of the attribute.
|
||||
|
||||
@@ -249,9 +253,11 @@ A table, optionally containing `get` and `set` functions (see `Attribute`).
|
||||
Return this widget for chaining.
|
||||
--]]--
|
||||
function Widget:defineAttribute (name, descriptor)
|
||||
local value = self[name]
|
||||
local value = rawget(self, name)
|
||||
if value == nil then value = self.attributes[name] end
|
||||
self.attributeDescriptors[name] = descriptor or {}
|
||||
rawset(self, name, nil)
|
||||
self.attributes[name] = nil
|
||||
self[name] = value
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -13,10 +13,10 @@ local Backend = require(ROOT .. 'backend')
|
||||
|
||||
local Layout, Event
|
||||
|
||||
local function checkMouseButton (layout, event)
|
||||
local function checkMouseButton (self, event)
|
||||
local button = event.button
|
||||
if not button then return false end
|
||||
if layout.isContextMenu then
|
||||
if self.isContextMenu then
|
||||
return button == 'left' or button == 'right'
|
||||
end
|
||||
return button == 'left'
|
||||
@@ -133,14 +133,14 @@ local function registerLayoutEvents (self)
|
||||
if self.parentMenu == self.rootMenu then
|
||||
deactivateSiblings(self.rootMenu[1])
|
||||
end
|
||||
elseif checkMouseButton(menuLayout, event) then
|
||||
elseif checkMouseButton(self, event) then
|
||||
activate(event)
|
||||
end
|
||||
end)
|
||||
|
||||
menuLayout:onPress(function (event)
|
||||
-- if event.button ~= 'left' then return end
|
||||
if not checkMouseButton(menuLayout, event) then return end
|
||||
if not checkMouseButton(self, event) then return end
|
||||
for widget in event.target:eachAncestor(true) do
|
||||
if widget.type == 'menu.item' and #widget.items == 0 then
|
||||
menuLayout:hide()
|
||||
@@ -151,7 +151,7 @@ local function registerLayoutEvents (self)
|
||||
|
||||
menuLayout:onPressEnd(function (event)
|
||||
-- if event.button ~= 'left' then return end
|
||||
if not checkMouseButton(menuLayout, event) then return end
|
||||
if not checkMouseButton(self, event) then return end
|
||||
for widget in event.target:eachAncestor(true) do
|
||||
if widget.type == 'menu.item' and #widget.items == 0
|
||||
and event.target ~= event.origin then
|
||||
@@ -231,7 +231,6 @@ local function createLayout (self)
|
||||
end
|
||||
|
||||
return function (self)
|
||||
self.context = false
|
||||
extractChildren(self)
|
||||
initialize(self)
|
||||
registerEvents(self)
|
||||
|
||||
@@ -41,26 +41,16 @@ Contains the index in `items` of the item being displayed.
|
||||
|
||||
self.items = {}
|
||||
self.index = 1
|
||||
self.flow = 'x' -- TODO: support vertical stepper
|
||||
|
||||
local contextMenu
|
||||
|
||||
for index, child in ipairs(self) do
|
||||
child.type = child.type or 'stepper.item'
|
||||
if child.isContextMenu then
|
||||
contextMenu = child
|
||||
else
|
||||
self.items[index] = child
|
||||
end
|
||||
self.items[index] = child
|
||||
self[index] = nil
|
||||
end
|
||||
|
||||
local before = self:addChild { type = 'stepper.before' }
|
||||
local view = self:addChild { type = 'stepper.view' }
|
||||
local after = self:addChild { type = 'stepper.after' }
|
||||
if contextMenu then
|
||||
self:addChild(contextMenu)
|
||||
end
|
||||
|
||||
self:onReshape(function (event)
|
||||
if self.flow == 'x' then
|
||||
|
||||
@@ -198,13 +198,10 @@ This color is used to indicate the selected range of text.
|
||||
--]]--
|
||||
|
||||
self:defineAttribute('highlight')
|
||||
|
||||
local defaultHighlight = { 0x80, 0x80, 0x80, 0x80 }
|
||||
--[[--
|
||||
@section end
|
||||
--]]--
|
||||
if not self.highlight then
|
||||
self.highlight = { 0x80, 0x80, 0x80, 0x80 }
|
||||
end
|
||||
|
||||
self.scrollX = 0
|
||||
|
||||
@@ -286,7 +283,7 @@ This color is used to indicate the selected range of text.
|
||||
|
||||
if self.focused then
|
||||
-- draw highlighted selection
|
||||
Backend.setColor(self.highlight)
|
||||
Backend.setColor(self.highlight or defaultHighlight)
|
||||
Backend.drawRectangle('fill', startX, y, width, height)
|
||||
-- draw cursor selection
|
||||
if Backend.getTime() % 2 < 1.75 then
|
||||
|
||||
Reference in New Issue
Block a user