lua hotkeys system

This commit is contained in:
Eduardo Bart 2012-01-07 18:00:07 -02:00
parent c4b2dd18d6
commit 060d8740f5
13 changed files with 320 additions and 69 deletions

3
TODO
View File

@ -1,5 +1,4 @@
== Core == Core
[bart] a class for binding hotkeys
[bart] review directories loading search [bart] review directories loading search
[bart] load modules from zip packages [bart] load modules from zip packages
[bart] create a class for reading binary files [bart] create a class for reading binary files
@ -44,12 +43,10 @@
[bart] padding [bart] padding
[bart] review and make more error prone with more warnings [bart] review and make more error prone with more warnings
[bart] a real working border and background property in otui [bart] a real working border and background property in otui
[bart] merge states declared in inherited styles
[bart] reapply anchor styles when adding new childs [bart] reapply anchor styles when adding new childs
== Client modules == Client modules
[bart] modules managment interface [bart] modules managment interface
[bart] restore Console key binding
[bart] console history, text selection, scrolling [bart] console history, text selection, scrolling
== Client == Client

View File

@ -124,7 +124,8 @@ function Terminal.init()
terminalWidget = displayUI('terminal.otui') terminalWidget = displayUI('terminal.otui')
terminalWidget:setVisible(false) terminalWidget:setVisible(false)
terminalButton = TopMenu.addButton('terminalButton', 'Terminal', '/core_styles/icons/terminal.png', Terminal.show) terminalButton = TopMenu.addButton('terminalButton', 'Terminal (Ctrl + T)', '/core_styles/icons/terminal.png', Terminal.toggle)
Hotkeys.bind('Ctrl+T', Terminal.toggle)
commandLineEdit = terminalWidget:getChildById('commandLineEdit') commandLineEdit = terminalWidget:getChildById('commandLineEdit')
connect(commandLineEdit, { onKeyPress = onCommandLineKeyPress }) connect(commandLineEdit, { onKeyPress = onCommandLineKeyPress })
@ -135,6 +136,7 @@ function Terminal.init()
end end
function Terminal.terminate() function Terminal.terminate()
Hotkeys.unbind('Ctrl+T')
Logger.setOnLog(nil) Logger.setOnLog(nil)
terminalButton:destroy() terminalButton:destroy()
terminalButton = nil terminalButton = nil
@ -145,6 +147,14 @@ function Terminal.terminate()
commandEnv = nil commandEnv = nil
end end
function Terminal.toggle()
if terminalWidget:isVisible() then
Terminal.hide()
else
Terminal.show()
end
end
function Terminal.show() function Terminal.show()
terminalWidget:show() terminalWidget:show()
terminalWidget:lock() terminalWidget:lock()

View File

@ -7,6 +7,7 @@ RectPanel
background-color: #000000 background-color: #000000
opacity: 216 opacity: 216
anchors.fill: parent anchors.fill: parent
@onEscape: Terminal.hide()
Panel Panel
id: terminalBuffer id: terminalBuffer

View File

@ -54,7 +54,8 @@ end
-- public functions -- public functions
function EnterGame.init() function EnterGame.init()
enterGameButton = TopMenu.addButton('enterGameButton', 'Login', '/core_styles/icons/login.png', EnterGame.openWindow) enterGameButton = TopMenu.addButton('enterGameButton', 'Login (Ctrl + G)', '/core_styles/icons/login.png', EnterGame.openWindow)
Hotkeys.bind('Ctrl+G', EnterGame.openWindow)
motdButton = TopMenu.addButton('motdButton', 'Message of the day', '/core_styles/icons/motd.png', EnterGame.displayMotd) motdButton = TopMenu.addButton('motdButton', 'Message of the day', '/core_styles/icons/motd.png', EnterGame.displayMotd)
motdButton:hide() motdButton:hide()
enterGame = displayUI('entergame.otui') enterGame = displayUI('entergame.otui')
@ -79,6 +80,7 @@ function EnterGame.init()
end end
function EnterGame.terminate() function EnterGame.terminate()
Hotkeys.unbind('Ctrl+G')
enterGame:destroy() enterGame:destroy()
enterGame = nil enterGame = nil
enterGameButton:destroy() enterGameButton:destroy()

View File

@ -1,17 +1,15 @@
Options = {} Options = {}
local optionsWindow
local optionsButton local optionsButton
function Options.init() function Options.init()
optionsButton = TopMenu.addButton('settingsButton', 'Options', '/core_styles/icons/settings.png', Options.show) optionsWindow = displayUI('options.otui')
Options.load() optionsWindow:setVisible(false)
end optionsButton = TopMenu.addButton('settingsButton', 'Options (Ctrl+O)', '/core_styles/icons/settings.png', Options.toggle)
Hotkeys.bind('Ctrl+O', Options.toggle)
function Options.terminate() -- load settings
TopMenu.removeButton(optionsButton)
end
function Options.load()
local booleanOptions = { vsync = true, local booleanOptions = { vsync = true,
showfps = true, showfps = true,
fullscreen = false, fullscreen = false,
@ -23,8 +21,30 @@ function Options.load()
end end
end end
function Options.terminate()
Hotkeys.unbind('Ctrl+O')
optionsWindow:destroy()
optionsWindow = nil
optionsButton:destroy()
optionsButton = nil
end
function Options.toggle()
if optionsWindow:isVisible() then
Options.hide()
else
Options.show()
end
end
function Options.show() function Options.show()
displayUI('options.otui', { locked = true }) optionsWindow:show()
optionsWindow:lock()
end
function Options.hide()
optionsWindow:unlock()
optionsWindow:hide()
end end
function Options.openWebpage() function Options.openWebpage()

View File

@ -20,6 +20,8 @@ MainWindow
id: optionsWindow id: optionsWindow
title: Options title: Options
size: 286 140 size: 286 140
@onEnter: Options.hide()
@onEscape: Options.hide()
OptionCheckBox OptionCheckBox
id: vsync id: vsync
@ -45,4 +47,4 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin-right: 10 margin-right: 10
margin-bottom: 10 margin-bottom: 10
@onClick: self:getParent():destroy() @onClick: Options.hide()

View File

@ -5,24 +5,27 @@ local topMenu
local leftButtonsPanel local leftButtonsPanel
local rightButtonsPanel local rightButtonsPanel
-- private functions
local function onLogout()
if Game.isOnline() then
Game.logout(false)
else
exit()
end
end
-- public functions -- public functions
function TopMenu.init() function TopMenu.init()
topMenu = displayUI('topmenu.otui') topMenu = displayUI('topmenu.otui')
leftButtonsPanel = topMenu:getChildById('leftButtonsPanel') leftButtonsPanel = topMenu:getChildById('leftButtonsPanel')
rightButtonsPanel = topMenu:getChildById('rightButtonsPanel') rightButtonsPanel = topMenu:getChildById('rightButtonsPanel')
TopMenu.addRightButton('logoutButton', 'Logout', '/core_styles/icons/logout.png', TopMenu.addRightButton('logoutButton', 'Logout (Ctrl+Q)', '/core_styles/icons/logout.png', onLogout)
function() Hotkeys.bind('Ctrl+Q', onLogout)
if Game.isOnline() then
Game.logout(false)
else
exit()
end
end
)
end end
function TopMenu.terminate() function TopMenu.terminate()
Hotkeys.unbind('Ctrl+Q')
leftButtonsPanel = nil leftButtonsPanel = nil
rightButtonsPanel = nil rightButtonsPanel = nil
topMenu:destroy() topMenu:destroy()

Binary file not shown.

View File

@ -14,6 +14,38 @@ LogFatal = 4
ActiveFocusReason = 2 ActiveFocusReason = 2
KeyboardNoModifier = 0
KeyboardCtrlModifier = 1
KeyboardAltModifier = 2
KeyboardCtrlAltModifier = 3
KeyboardShiftModifier = 4
KeyboardCtrlShiftModifier = 5
KeyboardAltShiftModifier = 6
KeyboardCtrlAltShiftModifier = 7
MouseNoButton = 0
MouseLeftButton = 1
MouseRightButton = 2
MouseMidButton = 3
AlignNone = 0
AlignLeft = 1
AlignRight = 2
AlignTop = 4
AlignBottom = 8
AlignHorizontalCenter = 16
AlignVerticalCenter = 32
AlignTopLeft = 5
AlignTopRight = 6
AlignBottomLeft = 9
AlignBottomRight = 10
AlignLeftCenter = 33
AlignRightCenter = 34
AlignTopCenter = 20
AlignBottomCenter = 24
AlignCenter = 48
KeyUnknown = 0 KeyUnknown = 0
KeyEscape = 1 KeyEscape = 1
KeyTab = 2 KeyTab = 2
@ -123,29 +155,113 @@ KeyF10 = 138
KeyF11 = 139 KeyF11 = 139
KeyF12 = 140 KeyF12 = 140
KeyboardNoModifier = 0 KeyCodeDescs = {
KeyboardCtrlModifier = 1 [KeyUnknown] = 'Unknown',
KeyboardAltModifier = 2 [KeyEscape] = 'Escape',
KeyboardShiftModifier = 4 [KeyTab] = 'Tab',
[KeyBackspace] = 'Backspace',
MouseNoButton = 0 [KeyReturn] = 'Return',
MouseLeftButton = 1 [KeyEnter] = 'Enter',
MouseRightButton = 2 [KeyInsert] = 'Insert',
MouseMidButton = 3 [KeyDelete] = 'Delete',
[KeyPause] = 'Pause',
AlignNone = 0 [KeyPrintScreen] = 'PrintScreen',
AlignLeft = 1 [KeyHome] = 'Home',
AlignRight = 2 [KeyEnd] = 'End',
AlignTop = 4 [KeyPageUp] = 'PageUp',
AlignBottom = 8 [KeyPageDown] = 'PageDown',
AlignHorizontalCenter = 16 [KeyUp] = 'Up',
AlignVerticalCenter = 32 [KeyDown] = 'Down',
AlignTopLeft = 5 [KeyLeft] = 'Left',
AlignTopRight = 6 [KeyRight] = 'Right',
AlignBottomLeft = 9 [KeyNumLock] = 'NumLock',
AlignBottomRight = 10 [KeyScrollLock] = 'ScrollLock',
AlignLeftCenter = 33 [KeyCapsLock] = 'CapsLock',
AlignRightCenter = 34 [KeyCtrl] = 'Ctrl',
AlignTopCenter = 20 [KeyShift] = 'Shift',
AlignBottomCenter = 24 [KeyAlt] = 'Alt',
AlignCenter = 48 [KeyAltGr] = 'AltGr',
[KeyMeta] = 'Meta',
[KeyMenu] = 'Menu',
[KeySpace] = 'Space',
[KeyExclamation] = '!',
[KeyQuote] = '\"',
[KeyNumberSign] = '#',
[KeyDollar] = '$',
[KeyPercent] = '%',
[KeyAmpersand] = '&',
[KeyApostrophe] = '\'',
[KeyLeftParen] = '(',
[KeyRightParen] = ')',
[KeyAsterisk] = '*',
[KeyPlus] = '+',
[KeyComma] = ',',
[KeyMinus] = '-',
[KeyPeriod] = '.',
[KeySlash] = '/',
[Key0] = '0',
[Key1] = '1',
[Key2] = '2',
[Key3] = '3',
[Key4] = '4',
[Key5] = '5',
[Key6] = '6',
[Key7] = '7',
[Key8] = '8',
[Key9] = '9',
[KeyColon] = ':',
[KeySemicolon] = ';',
[KeyLess] = '<',
[KeyEqual] = '=',
[KeyGreater] = '>',
[KeyQuestion] = '?',
[KeyAtSign] = '@',
[KeyA] = 'A',
[KeyB] = 'B',
[KeyC] = 'C',
[KeyD] = 'D',
[KeyE] = 'E',
[KeyF] = 'F',
[KeyG] = 'G',
[KeyH] = 'H',
[KeyI] = 'I',
[KeyJ] = 'J',
[KeyK] = 'K',
[KeyL] = 'L',
[KeyM] = 'M',
[KeyN] = 'N',
[KeyO] = 'O',
[KeyP] = 'P',
[KeyQ] = 'Q',
[KeyR] = 'R',
[KeyS] = 'S',
[KeyT] = 'T',
[KeyU] = 'U',
[KeyV] = 'V',
[KeyW] = 'W',
[KeyX] = 'X',
[KeyY] = 'Y',
[KeyZ] = 'Z',
[KeyLeftBracket] = '[',
[KeyBackslash] = '\\',
[KeyRightBracket] = ']',
[KeyCaret] = '^',
[KeyUnderscore] = '_',
[KeyGrave] = '`',
[KeyLeftCurly] = '{',
[KeyBar] = '|',
[KeyRightCurly] = '}',
[KeyTilde] = '~',
[KeyF1] = 'F1',
[KeyF2] = 'F2',
[KeyF3] = 'F3',
[KeyF4] = 'F4',
[KeyF5] = 'F5',
[KeyF6] = 'F6',
[KeyF7] = 'F7',
[KeyF8] = 'F8',
[KeyF9] = 'F9',
[KeyF10] = 'F10',
[KeyF11] = 'F11',
[KeyF12] = 'F12'
}

View File

@ -17,3 +17,4 @@ Module
require 'dispatcher' require 'dispatcher'
require 'effects' require 'effects'
require 'settings' require 'settings'
require 'hotkeys'

View File

@ -1,18 +1,23 @@
function string:split(sep) function string.split(s, delim)
local t = { } local start = 1
local function helper(word) local results = {}
table.insert(t, word) while true do
return "" local pos = string.find(s, delim, start, true)
if not pos then
break
end end
if not self:gsub("%w+", helper):find("%S") then table.insert(results, string.sub(s, start, pos-1))
return t start = pos + string.len(delim)
end end
table.insert(results, string.sub(s, start))
table.removevalue(results, '')
return results
end end
function string:starts(start) function string.starts(s, start)
return self:sub(1, #start) == start return string.sub(s, 1, #start) == start
end end
function string:trim() function string.trim(s)
return self:match('^%s*(.*%S)') or '' return string.match(s, '^%s*(.*%S)') or ''
end end

View File

@ -40,13 +40,17 @@ function table.find(t, value)
end end
function table.removevalue(t, value) function table.removevalue(t, value)
local queue = {}
for k,v in pairs(t) do for k,v in pairs(t) do
if v == value then if v == value then
table.insert(queue, k) table.remove(t, k)
end end
end end
for i,v in pairs(queue) do end
table.remove(t, i)
end function table.compare(t, other)
if #t ~= #other then return false end
for k,v in pairs(t) do
if v ~= other[k] then return false end
end
return true
end end

View File

@ -1,6 +1,96 @@
Hotkeys = {} Hotkeys = {}
function Hotkeys.bindKey(keyDesc, func) -- private functions
local function translateKeyCombo(keyCombo)
if not keyCombo or #keyCombo == 0 then return nil end
table.sort(keyCombo)
local keyComboDesc = ''
for k,v in pairs(keyCombo) do
local keyDesc = KeyCodeDescs[v]
if keyDesc == nil then return nil end
keyComboDesc = keyComboDesc .. '+' .. keyDesc
end
keyComboDesc = keyComboDesc:sub(2)
return keyComboDesc
end end
local function retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc == nil then return nil end
local keyCombo = {}
for i,currentKeyDesc in ipairs(keyComboDesc:split('+')) do
for keyCode, keyDesc in pairs(KeyCodeDescs) do
if keyDesc:lower() == currentKeyDesc:trim():lower() then
table.insert(keyCombo, keyCode)
end
end
end
return translateKeyCombo(keyCombo)
end
local function determineKeyComboDesc(keyCode, keyboardModifiers)
local keyCombo = {}
if keyCode == KeyShift or keyCode == KeyAlt or keyCode == KeyAltGr then
table.insert(keyCombo, keyCode)
elseif KeyCodeDescs[keyCode] ~= nil then
if keyboardModifiers == KeyboardCtrlModifier then
table.insert(keyCombo, KeyCtrl)
elseif keyboardModifiers == KeyboardAltModifier then
table.insert(keyCombo, KeyAlt)
elseif keyboardModifiers == KeyboardCtrlAltModifier then
table.insert(keyCombo, KeyCtrl)
table.insert(keyCombo, KeyAlt)
elseif keyboardModifiers == KeyboardShiftModifier then
table.insert(keyCombo, KeyShift)
elseif keyboardModifiers == KeyboardCtrlShiftModifier then
table.insert(keyCombo, KeyCtrl)
table.insert(keyCombo, KeyShift)
elseif keyboardModifiers == KeyboardAltShiftModifier then
table.insert(keyCombo, KeyAlt)
table.insert(keyCombo, KeyShift)
elseif keyboardModifiers == KeyboardCtrlAltShiftModifier then
table.insert(keyCombo, KeyCtrl)
table.insert(keyCombo, KeyAlt)
table.insert(keyCombo, KeyShift)
end
table.insert(keyCombo, keyCode)
end
table.sort(keyCombo)
return translateKeyCombo(keyCombo)
end
local function onWidgetKeyPress(widget, keyCode, keyText, keyboardModifiers)
local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers)
local callback = widget.boundKeyCombos[keyComboDesc]
if callback then
callback()
return true
end
return false
end
local function connectWidgetHotkeyEvent(widget)
if widget.boundKeyCombos then return end
connect(widget, { onKeyPress = onWidgetKeyPress })
widget.boundKeyCombos = {}
end
-- public functions
function Hotkeys.bind(keyComboDesc, callback, widget)
widget = widget or rootWidget
connectWidgetHotkeyEvent(widget)
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc then
widget.boundKeyCombos[keyComboDesc] = callback
else
error('key combo \'' .. keyComboDesc .. '\' is failed')
end
end
function Hotkeys.unbind(keyComboDesc, widget)
widget = widget or rootWidget
if widget.boundKeyCombos == nil then return end
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc then
widget.boundKeyCombos[keyComboDesc] = nil
end
end