[UX] Add CheckButton and use it for show password

Normal textinputs stay the same, password textinputs automatically gain a show password checkbutton underneath.

Thanks to @robert00s for the idea.
pull/3107/head
Frans de Jonge 7 years ago
parent 9f3ec235ff
commit 63241a20ea

@ -0,0 +1,137 @@
--[[--
Button widget that shows a checkmark (``) when checked and an empty box (``)
when unchecked.
Example:
local CheckButton = require("ui/widget/CheckButton")
local parent_widget = OverlapGroup:new{}
table.insert(parent_widget, CheckButton:new{
text = _("Show password"),
callback = function() end,
})
UIManager:show(parent_widget)
]]
local CheckMark = require("ui/widget/checkmark")
local Device = require("device")
local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer")
local GestureRange = require("ui/gesturerange")
local HorizontalGroup = require("ui/widget/horizontalgroup")
local InputContainer = require("ui/widget/container/inputcontainer")
local TextWidget = require("ui/widget/textwidget")
local UIManager = require("ui/uimanager")
local Screen = Device.screen
local CheckButton = InputContainer:new{
callback = nil,
hold_callback = nil,
checked = false,
enabled = true,
face = Font:getFace("cfont"),
overlap_align = "right",
text = nil,
toggle_text = nil,
window = nil,
padding = Screen:scaleBySize(5),
margin = Screen:scaleBySize(5),
bordersize = Screen:scaleBySize(3),
}
function CheckButton:init()
self:initCheckButton(self.checked)
end
function CheckButton:initCheckButton(checked)
self.checked = checked
self._checkmark = CheckMark:new{
checked = self.checked,
}
self._textwidget = TextWidget:new{
text = self.text,
face = self.face,
}
self._horizontalgroup = HorizontalGroup:new{
self._checkmark,
self._textwidget,
}
self._frame = FrameContainer:new{
bordersize = 0,
margin = 0,
padding = 0,
self._horizontalgroup,
}
self[1] = self._frame
self.dimen = self._frame:getSize()
if Device:isTouchDevice() then
self.ges_events = {
TapCheckButton = {
GestureRange:new{
ges = "tap",
range = self.dimen,
},
doc = "Tap Button",
},
HoldCheckButton = {
GestureRange:new{
ges = "hold",
range = self.dimen,
},
doc = "Hold Button",
}
}
end
end
function CheckButton:onTapCheckButton()
if self.enabled and self.callback then
UIManager:scheduleIn(0.0, function()
self.invert = true
UIManager:setDirty(self.show_parent, function()
return "ui", self.dimen
end)
end)
UIManager:scheduleIn(0.1, function()
self.callback()
self.invert = false
UIManager:setDirty(self.show_parent, function()
return "ui", self.dimen
end)
end)
elseif self.tap_input then
self:onInput(self.tap_input)
elseif type(self.tap_input_func) == "function" then
self:onInput(self.tap_input_func())
end
return true
end
function CheckButton:onHoldCheckButton()
if self.enabled and self.hold_callback then
self.hold_callback()
elseif self.hold_input then
self:onInput(self.hold_input)
elseif type(self.hold_input_func) == "function" then
self:onInput(self.hold_input_func())
end
return true
end
function CheckButton:check()
self:initCheckButton(true)
UIManager:setDirty(self.parent, function()
return "partial", self.dimen
end)
end
function CheckButton:unCheck()
self:initCheckButton(false)
UIManager:setDirty(self.parent, function()
return "partial", self.dimen
end)
end
return CheckButton

@ -29,7 +29,7 @@ local CheckMark = InputContainer:new{
function CheckMark:init()
local checked_widget = TextWidget:new{
text = "",
text = " ✓", -- preceded by thin space for better alignment
face = self.face,
}
local unchecked_widget = TextWidget:new{
@ -45,6 +45,8 @@ function CheckMark:init()
unchecked_widget
}
or empty_widget
self.dimen = unchecked_widget:getSize()
end
return CheckMark

@ -63,7 +63,6 @@ local VerticalGroup = require("ui/widget/verticalgroup")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local UIManager = require("ui/uimanager")
local Screen = require("device").screen
local _ = require("gettext")
local InputDialog = InputContainer:new{
title = "",
@ -73,7 +72,6 @@ local InputDialog = InputContainer:new{
buttons = nil,
input_type = nil,
enter_callback = nil,
show_password_toggle = true,
width = nil,
@ -149,26 +147,6 @@ function InputDialog:init()
scroll = false,
parent = self,
}
local is_password_type = false
if self._input_widget.text_type == "password" then
is_password_type = true
end
if self.show_password_toggle and is_password_type then
local button_switch = {
{
text = _("Show password"),
callback = function()
if self._input_widget.text_type == "text" then
self._input_widget.text_type = "password"
else
self._input_widget.text_type = "text"
end
self._input_widget:setText(self._input_widget:getText())
end,
},
}
table.insert(self.buttons[1], button_switch[1])
end
self.button_table = ButtonTable:new{
width = self.width,
button_font_face = "cfont",

@ -1,4 +1,5 @@
local Blitbuffer = require("ffi/blitbuffer")
local CheckButton = require("ui/widget/checkbutton")
local Device = require("device")
local FrameContainer = require("ui/widget/container/framecontainer")
local Font = require("ui/font")
@ -7,8 +8,10 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local ScrollTextWidget = require("ui/widget/scrolltextwidget")
local TextBoxWidget = require("ui/widget/textboxwidget")
local UIManager = require("ui/uimanager")
local Screen = Device.screen
local VerticalGroup = require("ui/widget/verticalgroup")
local util = require("util")
local _ = require("gettext")
local Screen = Device.screen
local Keyboard
@ -20,14 +23,15 @@ local InputText = InputContainer:new{
input_type = nil,
text_type = nil,
text_widget = nil, -- Text Widget for cursor movement
show_password_toggle = true,
width = nil,
height = nil,
face = Font:getFace("smallinfofont"),
padding = 5,
margin = 5,
bordersize = 2,
padding = Screen:scaleBySize(5),
margin = Screen:scaleBySize(5),
bordersize = Screen:scaleBySize(2),
parent = nil, -- parent dialog that will be set dirty
scroll = false,
@ -52,12 +56,12 @@ if Device.isTouchDevice() then
if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self)
end
local x = ges.pos.x - self.dimen.x - self.bordersize - self.padding
local y = ges.pos.y - self.dimen.y - self.bordersize - self.padding
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()
return "ui", self[1].dimen
return "ui", self.text_widget.dimen
end)
end
end
@ -72,8 +76,11 @@ function InputText:init()
self:initEventListener()
end
function InputText:initTextBox(text, char_added)
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
@ -98,6 +105,36 @@ function InputText:initTextBox(text, char_added)
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)
if self.scroll then
self.text_widget = ScrollTextWidget:new{
@ -123,17 +160,29 @@ function InputText:initTextBox(text, char_added)
height = self.height,
}
end
self[1] = FrameContainer:new{
self._frame_textwidget = FrameContainer:new{
bordersize = self.bordersize,
padding = self.padding,
margin = self.margin,
color = self.focused and Blitbuffer.COLOR_BLACK or Blitbuffer.COLOR_GREY,
self.text_widget,
}
self.dimen = self[1]:getSize()
-- FIXME: self.parent is not always in the widget statck (BookStatusWidget)
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[1].dimen
return "ui", self.dimen
end)
end
@ -202,9 +251,9 @@ function InputText:getText()
return self.text
end
function InputText:setText(text)
function InputText:setText(text, is_password_type)
self.charpos = nil
self:initTextBox(text)
self:initTextBox(text, nil, is_password_type)
UIManager:setDirty(self.parent, function()
return "partial", self[1].dimen
end)

Loading…
Cancel
Save