mirror of
https://github.com/airstruck/luigi.git
synced 2026-01-11 08:48:23 +00:00
text entry, more keyboard support
This commit is contained in:
@@ -75,8 +75,7 @@ local mainForm = { title = "Test window", id = 'mainWindow', type = 'panel',
|
|||||||
},
|
},
|
||||||
{ type = 'sash', height = 4, },
|
{ type = 'sash', height = 4, },
|
||||||
{ type = 'panel', flow = 'x', height = 48, padding = 2,
|
{ type = 'panel', flow = 'x', height = 48, padding = 2,
|
||||||
{ type = 'text', id = 'aTextField', text = 'a text field',
|
{ type = 'text', id = 'aTextField', text = 'a text field' },
|
||||||
font = 'font/liberation/LiberationMono-Regular.ttf' },
|
|
||||||
{ type = 'button', key='return', width = 80, id = 'aButton', text = 'Styling!' },
|
{ type = 'button', key='return', width = 80, id = 'aButton', text = 'Styling!' },
|
||||||
},
|
},
|
||||||
{ type = 'panel', id = 'statusbar', height = 24, padding = 4, textColor = { 255, 0, 0 } },
|
{ type = 'panel', id = 'statusbar', height = 24, padding = 4, textColor = { 255, 0, 0 } },
|
||||||
@@ -131,6 +130,8 @@ layout.newButton:onPress(function (event)
|
|||||||
print('creating a new thing!')
|
print('creating a new thing!')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
layout.mainCanvas.font = 'font/liberation/LiberationMono-Regular.ttf'
|
||||||
|
|
||||||
layout.mainCanvas.text = [[Abedede sdfsdf asfdsdfdsfs sdfsdfsdf
|
layout.mainCanvas.text = [[Abedede sdfsdf asfdsdfdsfs sdfsdfsdf
|
||||||
sfsdfdfbv db er erg rth tryj ty j fgh dfgv
|
sfsdfdfbv db er erg rth tryj ty j fgh dfgv
|
||||||
wefwef rgh erh rth e rgs dvg eh tyj rt h erg
|
wefwef rgh erh rth e rgs dvg eh tyj rt h erg
|
||||||
|
|||||||
@@ -3,19 +3,28 @@ local utf8 = require 'utf8'
|
|||||||
local blendMultiply = love._version_minor < 10 and 'multiplicative'
|
local blendMultiply = love._version_minor < 10 and 'multiplicative'
|
||||||
or 'multiply'
|
or 'multiply'
|
||||||
|
|
||||||
local function setCaretPosition (self, text)
|
local function getCaretPosition (self, text)
|
||||||
local font = self.fontData.font
|
local font = self.fontData.font
|
||||||
local x1, y1, x2, y2 = self:getRectangle(true, true)
|
local x1, y1, x2, y2 = self:getRectangle(true, true)
|
||||||
self.startIndex = #text
|
return #text, font:getWidth(text) + x1
|
||||||
self.startX = font:getWidth(text) + x1
|
end
|
||||||
self.endIndex, self.endX = self.startIndex, self.startX
|
|
||||||
|
local function setCaretPosition (self, text, mode)
|
||||||
|
local index, x = getCaretPosition(self, text)
|
||||||
|
|
||||||
|
if mode == 'start' or not mode then
|
||||||
|
self.startIndex, self.startX = index, x
|
||||||
|
end
|
||||||
|
if mode == 'end' or not mode then
|
||||||
|
self.endIndex, self.endX = index, x
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- return caret index and x position
|
-- return caret index and x position
|
||||||
local function getCaretFromEvent (self, event)
|
local function getCaretFromPoint (self, x, y)
|
||||||
local x1, y1, x2, y2 = self:getRectangle(true, true)
|
local x1, y1, x2, y2 = self:getRectangle(true, true)
|
||||||
|
|
||||||
if event.x <= x1 then
|
if x <= x1 then
|
||||||
return 0, x1
|
return 0, x1
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -27,7 +36,7 @@ local function getCaretFromEvent (self, event)
|
|||||||
text = self.value:sub(1, index)
|
text = self.value:sub(1, index)
|
||||||
lastWidth = width
|
lastWidth = width
|
||||||
width = font:getWidth(text)
|
width = font:getWidth(text)
|
||||||
if width > event.x - x1 then
|
if width > x - x1 then
|
||||||
if position == 1 then
|
if position == 1 then
|
||||||
return 0, x1
|
return 0, x1
|
||||||
end
|
end
|
||||||
@@ -38,6 +47,39 @@ local function getCaretFromEvent (self, event)
|
|||||||
return #self.value, width + x1
|
return #self.value, width + x1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- move the caret one character to the left
|
||||||
|
local function moveCaretLeft (self, alterRange)
|
||||||
|
local text, endIndex = self.value, self.endIndex
|
||||||
|
|
||||||
|
-- if cursor is at beginning, do nothing
|
||||||
|
if endIndex < 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- move left
|
||||||
|
local mode = alterRange and 'end'
|
||||||
|
local offset = utf8.offset(text, -1, endIndex) or 0
|
||||||
|
|
||||||
|
setCaretPosition(self, text:sub(1, offset), mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- move the caret one character to the right
|
||||||
|
local function moveCaretRight (self, alterRange)
|
||||||
|
local text, endIndex = self.value, self.endIndex
|
||||||
|
|
||||||
|
-- if cursor is at end, do nothing
|
||||||
|
if endIndex == #text then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local mode = alterRange and 'end'
|
||||||
|
local offset = endIndex < 1 and utf8.offset(text, 1)
|
||||||
|
or utf8.offset(text, 2, endIndex) or #text
|
||||||
|
|
||||||
|
-- move right
|
||||||
|
setCaretPosition(self, text:sub(1, offset), mode)
|
||||||
|
end
|
||||||
|
|
||||||
local function getRange (self)
|
local function getRange (self)
|
||||||
if self.startIndex <= self.endIndex then
|
if self.startIndex <= self.endIndex then
|
||||||
return self.startIndex, self.endIndex
|
return self.startIndex, self.endIndex
|
||||||
@@ -46,6 +88,65 @@ local function getRange (self)
|
|||||||
return self.endIndex, self.startIndex
|
return self.endIndex, self.startIndex
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function deleteRange (self)
|
||||||
|
local text = self.value
|
||||||
|
local first, last = getRange(self)
|
||||||
|
|
||||||
|
-- if expanded range is selected, delete text in range
|
||||||
|
if first ~= last then
|
||||||
|
local left = text:sub(1, first)
|
||||||
|
text = left .. text:sub(last + 1)
|
||||||
|
self:setValue(text)
|
||||||
|
setCaretPosition(self, left)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function deleteCharacterLeft (self)
|
||||||
|
local text = self.value
|
||||||
|
local first, last = getRange(self)
|
||||||
|
|
||||||
|
-- if cursor is at beginning, do nothing
|
||||||
|
if first < 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- delete character to the left
|
||||||
|
local offset = utf8.offset(text, -1, first) or 0
|
||||||
|
local left = text:sub(1, offset)
|
||||||
|
text = left .. text:sub(first + 1)
|
||||||
|
self:setValue(text)
|
||||||
|
setCaretPosition(self, left)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function copyRangeToClipboard (self)
|
||||||
|
local text = self.value
|
||||||
|
local first, last = getRange(self)
|
||||||
|
if last >= first + 1 then
|
||||||
|
love.system.setClipboardText(text:sub(first + 1, last))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pasteFromClipboard (self)
|
||||||
|
local text = self.value
|
||||||
|
local pasted = love.system.getClipboardText() or ''
|
||||||
|
local first, last = getRange(self)
|
||||||
|
local left = text:sub(1, first) .. pasted
|
||||||
|
text = left .. text:sub(last + 1)
|
||||||
|
self:setValue(text)
|
||||||
|
setCaretPosition(self, left)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function insertText (self, newText)
|
||||||
|
local text = self.value
|
||||||
|
local first, last = getRange(self)
|
||||||
|
local left = text:sub(1, first) .. newText
|
||||||
|
|
||||||
|
self.value = left .. text:sub(last + 1)
|
||||||
|
self:setValue(self.value)
|
||||||
|
setCaretPosition(self, left)
|
||||||
|
end
|
||||||
|
|
||||||
return function (self)
|
return function (self)
|
||||||
self.value = self.value or self.text or ''
|
self.value = self.value or self.text or ''
|
||||||
self.text = ''
|
self.text = ''
|
||||||
@@ -53,79 +154,45 @@ return function (self)
|
|||||||
self.highlight = self.highlight or { 0x80, 0x80, 0x80 }
|
self.highlight = self.highlight or { 0x80, 0x80, 0x80 }
|
||||||
|
|
||||||
self:onPressStart(function (event)
|
self:onPressStart(function (event)
|
||||||
self.startIndex, self.startX = getCaretFromEvent(self, event)
|
self.startIndex, self.startX = getCaretFromPoint(self, event.x)
|
||||||
self.endIndex, self.endX = self.startIndex, self.startX
|
self.endIndex, self.endX = self.startIndex, self.startX
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self:onPressMove(function (event)
|
self:onPressMove(function (event)
|
||||||
self.endIndex, self.endX = getCaretFromEvent(self, event)
|
self.endIndex, self.endX = getCaretFromPoint(self, event.x)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self:onTextInput(function (event)
|
self:onTextInput(function (event)
|
||||||
local text = self.value
|
insertText(self, event.text)
|
||||||
local first, last = getRange(self)
|
|
||||||
local left = text:sub(1, first) .. event.text
|
|
||||||
|
|
||||||
self.value = left .. text:sub(last + 1)
|
|
||||||
self:setValue(self.value)
|
|
||||||
setCaretPosition(self, left)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self:onKeyPress(function (event)
|
self:onKeyPress(function (event)
|
||||||
if event.key == 'backspace' then
|
if event.key == 'backspace' then
|
||||||
|
|
||||||
local text = self.value
|
if not deleteRange(self) then
|
||||||
local first, last = getRange(self)
|
deleteCharacterLeft(self)
|
||||||
|
|
||||||
-- if expanded range is selected, delete text in range
|
|
||||||
if first ~= last then
|
|
||||||
local left = text:sub(1, first)
|
|
||||||
self.value = left .. text:sub(last + 1)
|
|
||||||
self:setValue(self.value)
|
|
||||||
setCaretPosition(self, left)
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- if cursor is at beginning, do nothing
|
|
||||||
if first < 1 then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- delete character to the left
|
|
||||||
local offset = utf8.offset(self.value, -1, first) or 0
|
|
||||||
local left = self.value:sub(1, offset)
|
|
||||||
self.value = left .. self.value:sub(first + 1)
|
|
||||||
self:setValue(self.value)
|
|
||||||
setCaretPosition(self, left)
|
|
||||||
|
|
||||||
elseif event.key == 'left' then
|
elseif event.key == 'left' then
|
||||||
|
|
||||||
local text, endIndex = self.value, self.endIndex
|
moveCaretLeft(self, love.keyboard.isDown('lshift', 'rshift'))
|
||||||
|
|
||||||
-- if cursor is at beginning, do nothing
|
|
||||||
if endIndex < 1 then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- move cursor left
|
|
||||||
local offset = utf8.offset(text, -1, endIndex) or 0
|
|
||||||
|
|
||||||
setCaretPosition(self, text:sub(1, offset))
|
|
||||||
|
|
||||||
elseif event.key == 'right' then
|
elseif event.key == 'right' then
|
||||||
|
|
||||||
local text, endIndex = self.value, self.endIndex
|
moveCaretRight(self, love.keyboard.isDown('lshift', 'rshift'))
|
||||||
|
|
||||||
-- if cursor is at end, do nothing
|
elseif event.key == 'x' and love.keyboard.isDown('lctrl', 'rctrl') then
|
||||||
if endIndex == #text then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local offset = endIndex < 1 and utf8.offset(text, 1)
|
copyRangeToClipboard(self)
|
||||||
or utf8.offset(text, 2, endIndex) or #text
|
deleteRange(self)
|
||||||
|
|
||||||
-- move cursor right
|
elseif event.key == 'c' and love.keyboard.isDown('lctrl', 'rctrl') then
|
||||||
setCaretPosition(self, text:sub(1, offset))
|
|
||||||
|
copyRangeToClipboard(self)
|
||||||
|
|
||||||
|
elseif event.key == 'v' and love.keyboard.isDown('lctrl', 'rctrl') then
|
||||||
|
|
||||||
|
pasteFromClipboard(self)
|
||||||
|
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@@ -141,6 +208,7 @@ return function (self)
|
|||||||
local textTop = math.floor(y1 + ((y2 - y1) - font:getHeight()) / 2)
|
local textTop = math.floor(y1 + ((y2 - y1) - font:getHeight()) / 2)
|
||||||
|
|
||||||
love.graphics.push('all')
|
love.graphics.push('all')
|
||||||
|
love.graphics.setScissor(x1, y1, x2 - x1, y2 - y1)
|
||||||
love.graphics.setFont(font)
|
love.graphics.setFont(font)
|
||||||
love.graphics.setColor(textColor)
|
love.graphics.setColor(textColor)
|
||||||
love.graphics.print(self.value, x1, textTop)
|
love.graphics.print(self.value, x1, textTop)
|
||||||
|
|||||||
Reference in New Issue
Block a user