mirror of
https://github.com/koreader/koreader
synced 2024-11-11 19:11:14 +00:00
f05e62c1fb
Lots of code was doing some renderText calls to get the size of some text string, and truncate it to some width if needed, with or without an added ellipsis, before instantiating a TextWidget with that tweaked text string. This PR fixes/adds some properties and methods to TextWidget so all that can be done by it. It makes the calling code simpler, as they don't need to use RenderText directly. (Additionally, when we go at using Harfbuzz for text rendering, we'll just have to update or replace textwidget.lua without the need to update any higher level code.) Also: - RenderText: removed the space added by truncateTextByWidth after the ellipsis, as it doesn't feel needed, and break right alignment of the ellipsis with other texts. - KeyValuePage: fix some subtle size and alignment issues. - NumberPickerWidget: fix font size (provided font size was not used)
162 lines
5.2 KiB
Lua
162 lines
5.2 KiB
Lua
--[[--
|
|
Invisible full screen widget for catching UI events.
|
|
(for use with or by Trapper to interrupt its processing).
|
|
|
|
Can optionally display a text message at bottom left of screen
|
|
(ie: "Loading…")
|
|
]]
|
|
|
|
|
|
local Blitbuffer = require("ffi/blitbuffer")
|
|
local BottomContainer = require("ui/widget/container/bottomcontainer")
|
|
local CenterContainer = require("ui/widget/container/centercontainer")
|
|
local Device = require("device")
|
|
local Event = require("ui/event")
|
|
local Font = require("ui/font")
|
|
local FrameContainer = require("ui/widget/container/framecontainer")
|
|
local Geom = require("ui/geometry")
|
|
local GestureRange = require("ui/gesturerange")
|
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
|
local LeftContainer = require("ui/widget/container/leftcontainer")
|
|
local Size = require("ui/size")
|
|
local TextBoxWidget = require("ui/widget/textboxwidget")
|
|
local TextWidget = require("ui/widget/textwidget")
|
|
local UIManager = require("ui/uimanager")
|
|
local Input = Device.input
|
|
local Screen = Device.screen
|
|
|
|
local TrapWidget = InputContainer:new{
|
|
modal = true,
|
|
dismiss_callback = function() end,
|
|
text = nil, -- will be invisible if no message given
|
|
face = Font:getFace("infofont"),
|
|
-- Whether to resend the event caught and used for dismissal
|
|
resend_event = false,
|
|
}
|
|
|
|
function TrapWidget:init()
|
|
local full_screen = Geom:new{
|
|
x = 0, y = 0,
|
|
w = Screen:getWidth(),
|
|
h = Screen:getHeight(),
|
|
}
|
|
if Device:hasKeys() then
|
|
self.key_events = {
|
|
AnyKeyPressed = { { Input.group.Any },
|
|
seqtext = "any key", doc = "dismiss" }
|
|
}
|
|
end
|
|
if Device:isTouchDevice() then
|
|
self.ges_events.TapDismiss = {
|
|
GestureRange:new{ ges = "tap", range = full_screen, }
|
|
}
|
|
self.ges_events.HoldDismiss = {
|
|
GestureRange:new{ ges = "hold", range = full_screen, }
|
|
}
|
|
self.ges_events.SwipeDismiss = {
|
|
GestureRange:new{ ges = "swipe", range = full_screen, }
|
|
}
|
|
end
|
|
if self.text then
|
|
local textw = TextWidget:new{
|
|
text = self.text,
|
|
face = self.face,
|
|
}
|
|
-- Don't make our message reach full screen width, so
|
|
-- it looks like popping from bottom left corner
|
|
if textw:getWidth() > Screen:getWidth() * 0.9 then
|
|
-- Text too wide: use TextBoxWidget for multi lines display
|
|
textw = TextBoxWidget:new{
|
|
text = self.text,
|
|
face = self.face,
|
|
width = math.floor(Screen:getWidth() * 0.9)
|
|
}
|
|
end
|
|
local border_size = Size.border.default
|
|
self.frame = FrameContainer:new{
|
|
background = Blitbuffer.COLOR_WHITE,
|
|
bordersize = border_size,
|
|
margin = 0,
|
|
padding = 0,
|
|
padding_left = Size.padding.default,
|
|
padding_right = Size.padding.default,
|
|
textw,
|
|
}
|
|
-- To have our frame message a bit prettier with its left
|
|
-- and bottom borders not displayed, we make use of this
|
|
-- combination of Containers to push them off-screen
|
|
self[1] = CenterContainer:new{
|
|
dimen = full_screen:copy(),
|
|
BottomContainer:new{
|
|
dimen = Geom:new{
|
|
w = full_screen.w,
|
|
h = full_screen.h + 2*border_size,
|
|
},
|
|
LeftContainer:new{
|
|
dimen = Geom:new{
|
|
w = full_screen.w + 2*border_size,
|
|
h = self.frame:getSize().h,
|
|
},
|
|
self.frame,
|
|
}
|
|
}
|
|
}
|
|
else
|
|
-- So that UIManager knows no refresh is needed and
|
|
-- avoids some unnecessary refreshes
|
|
self.invisible = true
|
|
end
|
|
end
|
|
|
|
function TrapWidget:_dismissAndResent(evtype, ev)
|
|
self.dismiss_callback()
|
|
UIManager:close(self)
|
|
if self.resend_event and evtype and ev then
|
|
-- There may be some timing issues that could cause crashes, as we
|
|
-- use nextTick, if the dismiss_callback uses UIManager:scheduleIn()
|
|
-- or has set up some widget that may catch that event while not being
|
|
-- yet fully initialiazed.
|
|
-- (It happened mostly when I had some bug somewhere, and it was a quite
|
|
-- reliable sign of a bug somewhere, but the stacktrace was unrelated
|
|
-- to the bug location.)
|
|
UIManager:nextTick(function() UIManager:handleInputEvent(Event:new(evtype, ev)) end)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function TrapWidget:onAnyKeyPressed(_, ev)
|
|
return self:_dismissAndResent("KeyPress", ev)
|
|
end
|
|
|
|
function TrapWidget:onTapDismiss(_, ev)
|
|
return self:_dismissAndResent("Gesture", ev)
|
|
end
|
|
|
|
function TrapWidget:onHoldDismiss(_, ev)
|
|
return self:_dismissAndResent("Gesture", ev)
|
|
end
|
|
|
|
function TrapWidget:onSwipeDismiss(_, ev)
|
|
return self:_dismissAndResent("Gesture", ev)
|
|
end
|
|
|
|
function TrapWidget:onShow()
|
|
if self.frame then
|
|
UIManager:setDirty(self, function()
|
|
return "ui", self.frame.dimen
|
|
end)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function TrapWidget:onCloseWidget()
|
|
if self.frame then
|
|
UIManager:setDirty(nil, function()
|
|
return "ui", self.frame.dimen
|
|
end)
|
|
end
|
|
return true
|
|
end
|
|
|
|
return TrapWidget
|