2
-- This is like a <Text> object, only it listens to user input and
3
-- adjusts its text property accordingly.
9
-- onChange - Occurs when the input's text has changed, either by a
10
-- user's input or programmtically.
11
-- onType - Occurs when the input is about to accept input from a key.
12
-- This event handler is passed the key about to be inserted.
13
-- If the handler returns false, *not* nil or any other value,
14
-- then the key is ignored.
16
TextInput = Text:extend{
19
-- Property: listening
20
-- Whether the input is currently listening to input.
24
-- This shows the current insert position.
27
-- Property: blinkRate
28
-- How quickly the caret blinks, in seconds.
31
-- internal property: _blinkTimer
32
-- Used to keep track of caret blinking.
35
-- internal property: _repeatKey
36
-- Used to keep track of what movement key is being held down.
38
-- internal property: _repeatTimer
39
-- Used to keep track of how quickly movement keys repeat.
41
-- internal property: _caretHeight
42
-- How tall the caret is onscreen, based on the font.
44
-- internal property: _caretX
45
-- Where to draw the caret, relative to the sprite's x position.
47
update = function (self, elapsed)
48
if self.listening then
49
-- listen to normal keys
51
if the.keys.typed ~= '' then
52
if (self.onType and self:onType(the.keys.typed)) or not self.onType then
53
self.text = string.sub(self.text, 1, self.caret) .. the.keys.typed
54
.. string.sub(self.text, self.caret + 1)
55
self.caret = self.caret + string.len(the.keys.typed)
59
if the.keys:justPressed('home') then
63
if the.keys:justPressed('end') then
64
self.caret = string.len(self.text)
67
-- handle movement keys that repeat
68
-- we have to simulate repeat rates manually :(
70
local delay, rate = love.keyboard.getKeyRepeat()
73
for _, key in pairs{'backspace', 'delete', 'left', 'right'} do
74
if the.keys:pressed(key) then
75
if self._repeatKey == key then
76
self._repeatTimer = self._repeatTimer + elapsed
78
-- if we've made it past the maximum delay, then
79
-- we reset the timer and take action
81
if self._repeatTimer > delay + rate then
82
self._repeatTimer = delay
86
-- we've just started holding down the key
93
if self._repeatKey == key then
99
if frameAction == 'backspace' and self.caret > 0 then
100
self.text = string.sub(self.text, 1, self.caret - 1) .. string.sub(self.text, self.caret + 1)
101
self.caret = self.caret - 1
104
if frameAction == 'delete' and self.caret < string.len(self.text) then
105
self.text = string.sub(self.text, 1, self.caret) .. string.sub(self.text, self.caret + 2)
108
if frameAction == 'left' and self.caret > 0 then
109
self.caret = self.caret - 1
112
if frameAction == 'right' and self.caret < string.len(self.text) then
113
self.caret = self.caret + 1
117
-- update caret position
119
if self._set.caret ~= self.caret and self._fontObj then
120
self._caretX = self._fontObj:getWidth(string.sub(self.text, 1, self.caret))
121
self._caretHeight = self._fontObj:getHeight()
122
self._set.caret = self.caret
125
-- update caret timer
127
self._blinkTimer = self._blinkTimer + elapsed
128
if self._blinkTimer > self.blinkRate * 2 then self._blinkTimer = 0 end
130
-- call onChange handler as needed
132
if self.text ~= self._set.text then
133
if self.onChange then self:onChange() end
134
self._set.text = self.text
137
Text.update(self, elapsed)
140
draw = function (self, x, y)
145
Text.draw(self, x, y)
149
if (self._repeatKey or self._blinkTimer < self.blinkRate) and
150
(self._caretX and self._caretHeight) then
151
love.graphics.setLineWidth(1)
152
love.graphics.line(x + self._caretX, y, x + self._caretX, y + self._caretHeight)