2
0
mirror of https://github.com/koreader/koreader synced 2024-11-04 12:00:25 +00:00
koreader/frontend/ui/widget/inputtext.lua

315 lines
9.3 KiB
Lua
Raw Normal View History

2017-04-29 08:38:09 +00:00
local Blitbuffer = require("ffi/blitbuffer")
local CheckButton = require("ui/widget/checkbutton")
2017-04-29 08:38:09 +00:00
local Device = require("device")
local FrameContainer = require("ui/widget/container/framecontainer")
2017-04-29 08:38:09 +00:00
local Font = require("ui/font")
local GestureRange = require("ui/gesturerange")
local InputContainer = require("ui/widget/container/inputcontainer")
2013-10-18 20:38:07 +00:00
local ScrollTextWidget = require("ui/widget/scrolltextwidget")
local TextBoxWidget = require("ui/widget/textboxwidget")
local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup")
2016-04-21 14:13:10 +00:00
local util = require("util")
local _ = require("gettext")
local Screen = Device.screen
2017-04-29 08:38:09 +00:00
local Keyboard
2013-07-30 15:07:33 +00:00
2013-10-18 20:38:07 +00:00
local InputText = InputContainer:new{
2014-03-13 13:52:43 +00:00
text = "",
hint = "demo hint",
charlist = nil, -- table to store input string
2016-04-21 14:13:10 +00:00
charpos = nil, -- position to insert a new char, or the position of the cursor
2014-03-13 13:52:43 +00:00
input_type = nil,
text_type = nil,
2016-05-15 09:18:38 +00:00
text_widget = nil, -- Text Widget for cursor movement
show_password_toggle = true,
2014-03-13 13:52:43 +00:00
width = nil,
height = nil,
2017-04-29 08:38:09 +00:00
face = Font:getFace("smallinfofont"),
padding = Screen:scaleBySize(5),
margin = Screen:scaleBySize(5),
bordersize = Screen:scaleBySize(2),
2014-03-13 13:52:43 +00:00
parent = nil, -- parent dialog that will be set dirty
scroll = false,
focused = true,
2013-07-30 15:07:33 +00:00
}
-- only use PhysicalKeyboard if the device does not have touch screen
if Device.isTouchDevice() then
Keyboard = require("ui/widget/virtualkeyboard")
function InputText:initEventListener()
self.ges_events = {
TapTextBox = {
GestureRange:new{
ges = "tap",
range = self.dimen
}
},
HoldTextBox = {
GestureRange:new{
ges = "hold",
range = self.dimen
}
},
}
end
2016-04-21 14:13:10 +00:00
function InputText:onTapTextBox(arg, ges)
if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self)
end
local x = ges.pos.x - self._frame_textwidget.dimen.x - self.bordersize - self.padding
local y = ges.pos.y - self._frame_textwidget.dimen.y - self.bordersize - self.padding
if x > 0 and y > 0 then
self.charpos = self.text_widget:moveCursor(x, y)
UIManager:setDirty(self.parent, function()
2017-08-20 19:39:00 +00:00
return "ui", self.dimen
end)
end
end
function InputText:onHoldTextBox(arg, ges)
if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self)
end
local x = ges.pos.x - self._frame_textwidget.dimen.x - self.bordersize - self.padding
local y = ges.pos.y - self._frame_textwidget.dimen.y - self.bordersize - self.padding
if x > 0 and y > 0 then
self.charpos = self.text_widget:moveCursor(x, y)
if Device:hasClipboard() and Device.input.hasClipboardText() then
self:addChars(Device.input.getClipboardText())
end
UIManager:setDirty(self.parent, function()
return "ui", self.dimen
end)
end
end
elseif not Device.hasKeyboard() then
Keyboard = require("ui/widget/virtualkeyboard")
function InputText:initEventListener() end --do nothing but doesn't crash for now
else
Keyboard = require("ui/widget/physicalkeyboard")
function InputText:initEventListener() end
end
function InputText:init()
self:initTextBox(self.text)
if self.readonly ~= true then
self:initKeyboard()
self:initEventListener()
end
2013-07-30 15:07:33 +00:00
end
function InputText:initTextBox(text, char_added, is_password_type)
self.text = text
if self.text_type == "password" then
is_password_type = true
end
local fgcolor
local show_charlist
local show_text = text
if show_text == "" or show_text == nil then
-- no preset value, use hint text if set
show_text = self.hint
fgcolor = Blitbuffer.COLOR_GREY
self.charlist = {}
self.charpos = 1
else
fgcolor = Blitbuffer.COLOR_BLACK
if self.text_type == "password" then
show_text = self.text:gsub(
"(.-).", function() return "*" end)
if char_added then
show_text = show_text:gsub(
"(.)$", function() return self.text:sub(-1) end)
end
end
self.charlist = util.splitToChars(text)
if self.charpos == nil then
self.charpos = #self.charlist + 1
end
end
if is_password_type and self.show_password_toggle then
self._check_button = self._check_button or CheckButton:new{
text = _("Show password"),
callback = function()
if self.text_type == "text" then
self.text_type = "password"
self._check_button:unCheck()
else
self.text_type = "text"
self._check_button:check()
end
self:setText(self:getText(), is_password_type)
end,
width = self.width,
height = self.height,
padding = self.padding,
margin = self.margin,
bordersize = self.bordersize,
}
self._password_toggle = FrameContainer:new{
bordersize = 0,
padding = self.padding,
margin = self.margin,
self._check_button,
}
else
self._password_toggle = nil
end
show_charlist = util.splitToChars(show_text)
2014-03-13 13:52:43 +00:00
if self.scroll then
2016-04-21 14:13:10 +00:00
self.text_widget = ScrollTextWidget:new{
text = show_text,
charlist = show_charlist,
2016-05-15 09:18:38 +00:00
charpos = self.charpos,
editable = self.focused,
2014-03-13 13:52:43 +00:00
face = self.face,
fgcolor = fgcolor,
width = self.width,
height = self.height,
2017-04-02 06:50:24 +00:00
dialog = self.parent,
2014-03-13 13:52:43 +00:00
}
else
2016-04-21 14:13:10 +00:00
self.text_widget = TextBoxWidget:new{
text = show_text,
charlist = show_charlist,
2016-05-15 09:18:38 +00:00
charpos = self.charpos,
editable = self.focused,
2014-03-13 13:52:43 +00:00
face = self.face,
fgcolor = fgcolor,
width = self.width,
height = self.height,
}
end
self._frame_textwidget = FrameContainer:new{
2014-03-13 13:52:43 +00:00
bordersize = self.bordersize,
padding = self.padding,
margin = self.margin,
color = self.focused and Blitbuffer.COLOR_BLACK or Blitbuffer.COLOR_GREY,
2016-04-21 14:13:10 +00:00
self.text_widget,
2014-03-13 13:52:43 +00:00
}
self._verticalgroup = VerticalGroup:new{
align = "left",
self._frame_textwidget,
self._password_toggle,
}
self._frame = FrameContainer:new{
bordersize = 0,
margin = 0,
padding = 0,
self._verticalgroup,
}
self[1] = self._frame
self.dimen = self._frame:getSize()
-- FIXME: self.parent is not always in the widget stack (BookStatusWidget)
UIManager:setDirty(self.parent, function()
return "ui", self.dimen
end)
2013-07-30 15:07:33 +00:00
end
function InputText:initKeyboard()
2014-03-13 13:52:43 +00:00
local keyboard_layout = 2
if self.input_type == "number" then
keyboard_layout = 4
2014-03-13 13:52:43 +00:00
end
self.keyboard = Keyboard:new{
2014-03-13 13:52:43 +00:00
layout = keyboard_layout,
inputbox = self,
width = Screen:getWidth(),
}
2013-07-30 15:07:33 +00:00
end
function InputText:unfocus()
self.focused = false
self.text_widget:unfocus()
self[1].color = Blitbuffer.COLOR_GREY
end
function InputText:focus()
self.focused = true
self.text_widget:focus()
self[1].color = Blitbuffer.COLOR_BLACK
end
2013-07-30 15:07:33 +00:00
function InputText:onShowKeyboard()
2014-03-13 13:52:43 +00:00
UIManager:show(self.keyboard)
2013-07-30 15:07:33 +00:00
end
function InputText:onCloseKeyboard()
2014-03-13 13:52:43 +00:00
UIManager:close(self.keyboard)
2013-07-30 15:07:33 +00:00
end
function InputText:getKeyboardDimen()
2014-03-13 13:52:43 +00:00
return self.keyboard.dimen
2013-07-30 15:07:33 +00:00
end
function InputText:addChars(char)
2014-03-13 13:52:43 +00:00
if self.enter_callback and char == '\n' then
UIManager:scheduleIn(0.3, function() self.enter_callback() end)
return
end
table.insert(self.charlist, self.charpos, char)
self.charpos = self.charpos + #util.splitToChars(char)
self:initTextBox(table.concat(self.charlist), true)
2013-07-30 15:07:33 +00:00
end
function InputText:delChar()
2014-03-13 13:52:43 +00:00
if self.charpos == 1 then return end
self.charpos = self.charpos - 1
table.remove(self.charlist, self.charpos)
self:initTextBox(table.concat(self.charlist))
2013-07-30 15:07:33 +00:00
end
function InputText:leftChar()
if self.charpos == 1 then return end
self.charpos = self.charpos -1
self:initTextBox(table.concat(self.charlist))
end
function InputText:rightChar()
if self.charpos > #table.concat(self.charlist) then return end
self.charpos = self.charpos +1
self:initTextBox(table.concat(self.charlist))
end
function InputText:upLine()
if self.text_widget.moveCursorUp then
self.text_widget:moveCursorUp()
end
end
function InputText:downLine()
if self.text_widget.moveCursorDown then
self.text_widget:moveCursorDown()
end
end
function InputText:clear()
2016-06-26 14:43:40 +00:00
self.charpos = nil
self:initTextBox("")
UIManager:setDirty(self.parent, function()
return "ui", self[1][1].dimen
end)
end
2013-07-30 15:07:33 +00:00
function InputText:getText()
2014-03-13 13:52:43 +00:00
return self.text
2013-07-30 15:07:33 +00:00
end
function InputText:setText(text, is_password_type)
self.charpos = nil
self:initTextBox(text, nil, is_password_type)
UIManager:setDirty(self.parent, function()
return "partial", self[1].dimen
end)
end
2013-10-18 20:38:07 +00:00
return InputText