232 lines
5.9 KiB
Lua
232 lines
5.9 KiB
Lua
-- On-screen keyboard with hooks for standard key input events
|
|
|
|
local List = require("gfx.list")
|
|
local Padding = require("gfx.padding")
|
|
local Text = require("gfx.text")
|
|
local Orientation = require("gfx.prop.orientation")
|
|
local Children = require("gfx.prop.children")
|
|
|
|
local DEFAULT_COLOR_BG = colors.gray
|
|
local DEFAULT_COLOR_KEY = colors.gray
|
|
local DEFAULT_PADDING_H = 1
|
|
local DEFAULT_PADDING_V = 1
|
|
local HANDLER_IGNORE_CLICK = function() return true end
|
|
|
|
local ID_KEY_LIST = "$Keyboard$List"
|
|
local ID_PADDED_KEY = "$Keyboard$List$Padding"
|
|
|
|
local Keyboard = Padding:new{
|
|
bgColor = DEFAULT_COLOR_BG,
|
|
keyColor = DEFAULT_COLOR_KEY,
|
|
left = DEFAULT_PADDING_H,
|
|
right = DEFAULT_PADDING_H,
|
|
top = DEFAULT_PADDING_V,
|
|
bottom = DEFAULT_PADDING_V,
|
|
onKeyPress = function(key) end,
|
|
onBackspace = function() end
|
|
}
|
|
|
|
function Keyboard:new(o)
|
|
local template = o or {}
|
|
|
|
if type(template.layout) == "function" then
|
|
template.layout = template.layout()
|
|
elseif type(template.layout) ~= "table" then
|
|
template.layout = Keyboard.Layout.English()
|
|
end
|
|
|
|
template.colorKey = template.colorKey or DEFAULT_COLOR_KEY
|
|
template.keySlop = not not template.keySlop
|
|
template.onClick = HANDLER_IGNORE_CLICK
|
|
template.onKey = function(_, keyCode, _)
|
|
if keyCode == keys.backspace then
|
|
template.onBackspace()
|
|
return true
|
|
elseif keyCode == keys.enter then
|
|
template.onKeyPress("\n")
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
template.onChar = function(_, charCode)
|
|
template.onKeyPress(charCode)
|
|
return true
|
|
end
|
|
|
|
template.element = List:new{
|
|
bgColor = template.bgColor,
|
|
[Orientation:getId()] = Orientation.VERTICAL,
|
|
[Children:getId()] = {}
|
|
}
|
|
|
|
local obj = Padding.new(self, template)
|
|
|
|
self:setLayout(self.layout)
|
|
|
|
return obj
|
|
end
|
|
|
|
function Keyboard:setLayout(layout)
|
|
self.layout = layout
|
|
|
|
local this = self
|
|
|
|
local KEY_BACKSPACE = "backspace"
|
|
local KEY_ENTER = "enter"
|
|
local function charInputKeyList(chars, backspace, enter, spacebar)
|
|
local keysEntries = { }
|
|
for i=1,#chars do
|
|
local key = chars:sub(i, i)
|
|
local keyFunc = function()
|
|
this.onKeyPress(key)
|
|
return true
|
|
end
|
|
local keySlopFunc = this.keySlop and keyFunc or HANDLER_IGNORE_CLICK
|
|
|
|
-- ((not backspace) and i == #keys and 0) or 1
|
|
table.insert(keysEntries, Padding:new{ onClick = keySlopFunc, bgColor = this.bgColor, right = 1, element = Text:new{
|
|
id = key,
|
|
text = key,
|
|
bgColor = this.colorKey,
|
|
onClick = keyFunc
|
|
}})
|
|
end
|
|
if enter then
|
|
table.insert(keysEntries, Text:new{
|
|
id = KEY_ENTER,
|
|
text = "[<]",
|
|
bgColor = this.colorKey,
|
|
onClick = function()
|
|
this.onKeyPress("\n")
|
|
return true
|
|
end
|
|
})
|
|
end
|
|
if backspace then
|
|
table.insert(keysEntries, Text:new{
|
|
id = KEY_BACKSPACE,
|
|
text = "[x]",
|
|
bgColor = this.colorKey,
|
|
onClick = function()
|
|
this.onBackspace()
|
|
return true
|
|
end
|
|
})
|
|
end
|
|
if spacebar then
|
|
table.insert(keysEntries, Text:new{
|
|
id = " ",
|
|
text = "[SPACE]",
|
|
bgColor = this.colorKey,
|
|
onClick = function()
|
|
this.onKeyPress(" ")
|
|
return true
|
|
end
|
|
})
|
|
end
|
|
return List:new{
|
|
id = ID_KEY_LIST,
|
|
bgColor = this.colorBg,
|
|
[Orientation:getId()] = Orientation.HORIZONTAL,
|
|
[Children:getId()] = keysEntries
|
|
}
|
|
end
|
|
|
|
local keyboardLines = {}
|
|
for _,line in ipairs(this.layout) do
|
|
local keyLineList = charInputKeyList(line[1], line.backspace, line.enter)
|
|
table.insert(keyboardLines, keyLineList)
|
|
end
|
|
|
|
self.element[Children:getId()] = keyboardLines
|
|
self:setDirty()
|
|
end
|
|
|
|
function Keyboard:setKeyColor(color)
|
|
if color ~= self.keyColor then
|
|
self.keyColor = color
|
|
self:setDirty()
|
|
end
|
|
end
|
|
|
|
function Keyboard:setDirty(fullInvalidate)
|
|
local keyList = self:findById(ID_KEY_LIST)
|
|
for _,key in pairs(keyList[Children:getId()]) do
|
|
if key:getId() == ID_PADDED_KEY then
|
|
key:setBgColor(self.bgColor)
|
|
key.element:setBgColor(self.keyColor)
|
|
else
|
|
key:setBgColor(self.keyColor)
|
|
end
|
|
end
|
|
Padding.setDirty(self, fullInvalidate)
|
|
end
|
|
|
|
local function layoutNumbers(layout)
|
|
table.insert(layout, 1, { "1234567890" })
|
|
return layout
|
|
end
|
|
|
|
local function layoutEnter(rowIndex, layout)
|
|
for index,layoutRow in pairs(layout) do
|
|
if index == rowIndex then
|
|
layoutRow.enter = true
|
|
else
|
|
layoutRow.enter = nil
|
|
end
|
|
end
|
|
return layout
|
|
end
|
|
|
|
local function layoutBackspace(rowIndex, layout)
|
|
for index,layoutRow in pairs(layout) do
|
|
if index == rowIndex then
|
|
layoutRow.backspace = true
|
|
else
|
|
layoutRow.backspace = nil
|
|
end
|
|
end
|
|
return layout
|
|
end
|
|
|
|
local function layoutSpacebar(layout)
|
|
table.insert(layout, { spacebar = true, "" })
|
|
return layout
|
|
end
|
|
|
|
local function appendNumberLayout(cond, layout)
|
|
return cond and layoutNumbers(layout) or layout
|
|
end
|
|
|
|
Keyboard.Layout = {
|
|
ItemSearch = function()
|
|
return layoutBackspace(1, layoutNumbers({
|
|
{ "qwertyuiop" },
|
|
{ "asdfghjkl" },
|
|
{ "zxcvbnm_:" }
|
|
}))
|
|
end,
|
|
English = function(numberRow)
|
|
return layoutSpacebar(layoutBackspace(1, appendNumberLayout(numberRow, layoutEnter(2, {
|
|
{ "qwertyuiop" },
|
|
{ "asdfghjkl" },
|
|
{ "zxcvbnm" }
|
|
}))))
|
|
end,
|
|
Swedish = function(numberRow)
|
|
return layoutSpacebar(layoutBackspace(1, appendNumberLayout(numberRow, layoutEnter(2, {
|
|
{ "qwertyuiopå" },
|
|
{ "asdfghjklöä" },
|
|
{ "zxcvbnm" }
|
|
}))))
|
|
end,
|
|
Special = function(numberRow)
|
|
return layoutSpacebar(layoutBackspace(1, appendNumberLayout(numberRow, {
|
|
{ "!\"#¤%&/()=?" },
|
|
{ "@£${[]}\\+^" },
|
|
{ "§<>|;:,.-_'*" }
|
|
})))
|
|
end
|
|
}
|
|
|
|
return Keyboard |