Add MovableContainer: allow moving some widgets (#3636)

pull/3642/head
poire-z 6 years ago committed by Frans de Jonge
parent f7e56b408f
commit 43a6cf4b2e

@ -42,7 +42,7 @@ function ReaderSearch:onShowSearchDialog(text)
end end
end end
self.search_dialog = ButtonDialog:new{ self.search_dialog = ButtonDialog:new{
alpha = 0.5, -- alpha = 0.7,
buttons = { buttons = {
{ {
{ {

@ -12,6 +12,8 @@ local HorizontalGroup = require("ui/widget/horizontalgroup")
local HorizontalSpan = require("ui/widget/horizontalspan") local HorizontalSpan = require("ui/widget/horizontalspan")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local LineWidget = require("ui/widget/linewidget") local LineWidget = require("ui/widget/linewidget")
local Math = require("optmath")
local MovableContainer = require("ui/widget/container/movablecontainer")
local OverlapGroup = require("ui/widget/overlapgroup") local OverlapGroup = require("ui/widget/overlapgroup")
local ProgressWidget = require("ui/widget/progresswidget") local ProgressWidget = require("ui/widget/progresswidget")
local Size = require("ui/size") local Size = require("ui/size")
@ -342,9 +344,8 @@ function SkimToWidget:init()
w = self.screen_width, w = self.screen_width,
h = self.screen_height, h = self.screen_height,
}, },
FrameContainer:new{ MovableContainer:new{
bordersize = 0, -- alpha = 0.8,
padding = Size.padding.default,
self.skimto_frame, self.skimto_frame,
} }
} }
@ -403,17 +404,19 @@ function SkimToWidget:onAnyKeyPressed()
end end
function SkimToWidget:onTapProgress(arg, ges_ev) function SkimToWidget:onTapProgress(arg, ges_ev)
if ges_ev.pos:intersectWith(self.skimto_progress.dimen) then if ges_ev.pos:intersectWith(self.progress_bar.dimen) then
local width = self.screen_width * 0.89 local width = self.progress_bar.dimen.w
local pos = ges_ev.pos.x - width * 0.05 - 3 local pos = ges_ev.pos.x - self.progress_bar.dimen.x
local perc = pos / width local perc = pos / width
local page = math.floor(perc * self.page_count) local page = Math.round(perc * self.page_count)
self.ui:handleEvent(Event:new("GotoPage", page )) self.ui:handleEvent(Event:new("GotoPage", page ))
self.curr_page = page self.curr_page = page
self:update() self:update()
else elseif not ges_ev.pos:intersectWith(self.skimto_frame.dimen) then
-- close if tap outside
self:onClose() self:onClose()
end end
-- otherwise, do nothing (it's easy missing taping a button)
return true return true
end end

@ -190,9 +190,11 @@ function Trapper:info(text, fast_refresh)
-- If fast_refresh option, avoid UIManager refresh overhead -- If fast_refresh option, avoid UIManager refresh overhead
if fast_refresh and self.current_widget and self.current_widget.is_infomessage then if fast_refresh and self.current_widget and self.current_widget.is_infomessage then
local orig_moved_offset = self.current_widget.movable:getMovedOffset()
self.current_widget:free() self.current_widget:free()
self.current_widget.text = text self.current_widget.text = text
self.current_widget:init() self.current_widget:init()
self.current_widget.movable:setMovedOffset(orig_moved_offset)
local Screen = require("device").screen local Screen = require("device").screen
self.current_widget:paintTo(Screen.bb, 0,0) self.current_widget:paintTo(Screen.bb, 0,0)
local d = self.current_widget[1][1].dimen local d = self.current_widget[1][1].dimen

@ -6,6 +6,7 @@ local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange") local GestureRange = require("ui/gesturerange")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local MovableContainer = require("ui/widget/container/movablecontainer")
local Size = require("ui/size") local Size = require("ui/size")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local _ = require("gettext") local _ = require("gettext")
@ -14,6 +15,7 @@ local Screen = require("device").screen
local ButtonDialog = InputContainer:new{ local ButtonDialog = InputContainer:new{
buttons = nil, buttons = nil,
tap_close_callback = nil, tap_close_callback = nil,
alpha = nil, -- passed to MovableContainer
} }
function ButtonDialog:init() function ButtonDialog:init()
@ -36,20 +38,23 @@ function ButtonDialog:init()
end end
self[1] = CenterContainer:new{ self[1] = CenterContainer:new{
dimen = Screen:getSize(), dimen = Screen:getSize(),
FrameContainer:new{ MovableContainer:new{
ButtonTable:new{ alpha = self.alpha,
width = Screen:getWidth()*0.9, FrameContainer:new{
buttons = self.buttons, ButtonTable:new{
show_parent = self, width = Screen:getWidth()*0.9,
}, buttons = self.buttons,
background = Blitbuffer.COLOR_WHITE, show_parent = self,
bordersize = Size.border.window, },
radius = Size.radius.window, background = Blitbuffer.COLOR_WHITE,
padding = Size.padding.button, bordersize = Size.border.window,
-- No padding at top or bottom to make all buttons radius = Size.radius.window,
-- look the same size padding = Size.padding.button,
padding_top = 0, -- No padding at top or bottom to make all buttons
padding_bottom = 0, -- look the same size
padding_top = 0,
padding_bottom = 0,
}
} }
} }
end end

@ -7,6 +7,7 @@ local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange") local GestureRange = require("ui/gesturerange")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local MovableContainer = require("ui/widget/container/movablecontainer")
local Size = require("ui/size") local Size = require("ui/size")
local TextBoxWidget = require("ui/widget/textboxwidget") local TextBoxWidget = require("ui/widget/textboxwidget")
local VerticalGroup = require("ui/widget/verticalgroup") local VerticalGroup = require("ui/widget/verticalgroup")
@ -45,33 +46,35 @@ function ButtonDialogTitle:init()
end end
self[1] = CenterContainer:new{ self[1] = CenterContainer:new{
dimen = Screen:getSize(), dimen = Screen:getSize(),
FrameContainer:new{ MovableContainer:new{
VerticalGroup:new{ FrameContainer:new{
align = "center", VerticalGroup:new{
FrameContainer:new{ align = "center",
padding = self.title_padding, FrameContainer:new{
margin = self.title_margin, padding = self.title_padding,
bordersize = 0, margin = self.title_margin,
TextBoxWidget:new{ bordersize = 0,
text = self.title, TextBoxWidget:new{
width = Screen:getWidth() * 0.8 , text = self.title,
face = self.title_face, width = Screen:getWidth() * 0.8 ,
alignment = self.title_align or "left", face = self.title_face,
alignment = self.title_align or "left",
},
},
VerticalSpan:new{ width = Size.span.vertical_default },
ButtonTable:new{
width = Screen:getWidth() * 0.9,
buttons = self.buttons,
zero_sep = true,
show_parent = self,
}, },
}, },
VerticalSpan:new{ width = Size.span.vertical_default }, background = Blitbuffer.COLOR_WHITE,
ButtonTable:new{ bordersize = Size.border.window,
width = Screen:getWidth() * 0.9, radius = Size.radius.window,
buttons = self.buttons, padding = Size.padding.button,
zero_sep = true, padding_bottom = 0, -- no padding below buttontable
show_parent = self, }
},
},
background = Blitbuffer.COLOR_WHITE,
bordersize = Size.border.window,
radius = Size.radius.window,
padding = Size.padding.button,
padding_bottom = 0, -- no padding below buttontable
} }
} }
end end

@ -29,6 +29,7 @@ local HorizontalGroup = require("ui/widget/horizontalgroup")
local HorizontalSpan = require("ui/widget/horizontalspan") local HorizontalSpan = require("ui/widget/horizontalspan")
local ImageWidget = require("ui/widget/imagewidget") local ImageWidget = require("ui/widget/imagewidget")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local MovableContainer = require("ui/widget/container/movablecontainer")
local Size = require("ui/size") local Size = require("ui/size")
local TextBoxWidget = require("ui/widget/textboxwidget") local TextBoxWidget = require("ui/widget/textboxwidget")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
@ -127,17 +128,19 @@ function ConfirmBox:init()
self[1] = CenterContainer:new{ self[1] = CenterContainer:new{
dimen = Screen:getSize(), dimen = Screen:getSize(),
FrameContainer:new{ MovableContainer:new{
background = Blitbuffer.COLOR_WHITE, FrameContainer:new{
margin = self.margin, background = Blitbuffer.COLOR_WHITE,
padding = self.padding, margin = self.margin,
padding_bottom = 0, -- no padding below buttontable padding = self.padding,
VerticalGroup:new{ padding_bottom = 0, -- no padding below buttontable
align = "left", VerticalGroup:new{
content, align = "left",
-- Add same vertical space after than before content content,
VerticalSpan:new{ width = self.margin + self.padding }, -- Add same vertical space after than before content
button_table, VerticalSpan:new{ width = self.margin + self.padding },
button_table,
}
} }
} }
} }

@ -0,0 +1,295 @@
--[[--
A MovableContainer can have its content moved on screen
with Swipe/Hold/Pan.
Can optionally apply alpha transparency to its content.
With Swipe: the widget will be constrained to screen borders.
With Hold and pan, the widget can overflow the borders.
Hold with no move will reset the widget to its original position.
If the widget has not been moved or is already at its original
position, Hold will toggle between full opacity and 0.7 transparency.
This container's content is expected to not change its width and height.
]]
local BlitBuffer = require("ffi/blitbuffer")
local Device = require("device")
local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange")
local InputContainer = require("ui/widget/container/inputcontainer")
local Math = require("optmath")
local UIManager = require("ui/uimanager")
local Screen = Device.screen
local logger = require("logger")
local MovableContainer = InputContainer:new{
-- Alpha value for subwidget transparency
-- 0 = fully invisible, 1 = fully opaque (0.6 / 0.7 / 0.8 are some interesting values)
alpha = nil,
-- Move threshold (if move distance less than that, considered as a Hold
-- with no movement, used for reseting move to original position)
move_threshold = Screen:scaleBySize(5),
-- Events to ignore (ie: ignore_events={"hold", "hold_release"})
ignore_events = nil,
-- Current move offset (use getMovedOffset()/setMovedOffset() to access them)
_moved_offset_x = 0,
_moved_offset_y = 0,
-- Internal state between events
_touch_pre_pan_was_inside = false,
_moving = true,
_move_relative_x = nil,
_move_relative_y = nil,
-- Original painting position from outer widget
_orig_x = nil,
_orig_y = nil,
}
function MovableContainer:init()
if Device:isTouchDevice() then
local range = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight(),
}
-- Unflatten self.ignore_events to table keys for cleaner code below
local ignore = {}
if self.ignore_events then
for _, evname in pairs(self.ignore_events) do
ignore[evname] = true
end
end
-- The following gestures need to be supported, depending on the
-- ways a user can move things:
-- Hold happens if he holds at start
-- Pan happens if he doesn't hold at start, but holds at end
-- Swipe happens if he doesn't hold at any moment
-- Note that Swipe is tied to 0/45/90/135 degree... directions,
-- which is somehow nice and gives a kind of magnetic move that
-- stick the widget to some invisible rulers.
-- (Touch is needed for accurate pan)
self.ges_events = {}
self.ges_events.MovableTouch = not ignore.touch and { GestureRange:new{ ges = "touch", range = range } } or nil
self.ges_events.MovableSwipe = not ignore.swipe and { GestureRange:new{ ges = "swipe", range = range } } or nil
self.ges_events.MovableHold = not ignore.hold and { GestureRange:new{ ges = "hold", range = range } } or nil
self.ges_events.MovableHoldPan = not ignore.hold_pan and { GestureRange:new{ ges = "hold_pan", range = range } } or nil
self.ges_events.MovableHoldRelease = not ignore.hold_release and { GestureRange:new{ ges = "hold_release", range = range } } or nil
self.ges_events.MovablePan = not ignore.pan and { GestureRange:new{ ges = "pan", range = range } } or nil
self.ges_events.MovablePanRelease = not ignore.pan_release and { GestureRange:new{ ges = "pan_release", range = range } } or nil
end
end
function MovableContainer:getMovedOffset()
return Geom:new{
x = self._moved_offset_x,
y = self._moved_offset_y,
}
end
function MovableContainer:setMovedOffset(offset_point)
if offset_point and offset_point.x and offset_point.y then
self._moved_offset_x = offset_point.x
self._moved_offset_y = offset_point.y
end
end
function MovableContainer:paintTo(bb, x, y)
if self[1] == nil then
return
end
local content_size = self[1]:getSize()
if not self.dimen then
self.dimen = Geom:new{w = content_size.w, h = content_size.h}
end
self._orig_x = x
self._orig_y = y
-- We just need to shift painting by our _moved_offset_x/y
self.dimen.x = x + self._moved_offset_x
self.dimen.y = y + self._moved_offset_y
if self.alpha then
-- Create private blitbuffer for our child widget to paint to
local private_bb = BlitBuffer.new(bb:getWidth(), bb:getHeight(), bb:getType())
private_bb:fill(BlitBuffer.COLOR_WHITE) -- for round corners' outside to not stay black
self[1]:paintTo(private_bb, self.dimen.x, self.dimen.y)
-- And blend our private blitbuffer over the original bb
bb:addblitFrom(private_bb, self.dimen.x, self.dimen.y, self.dimen.x, self.dimen.y,
self.dimen.w, self.dimen.h, self.alpha)
private_bb:free()
else
-- No alpha, just paint
self[1]:paintTo(bb, self.dimen.x, self.dimen.y)
end
end
function MovableContainer:_moveBy(dx, dy, restrict_to_screen)
logger.dbg("MovableContainer:_moveBy:", dx, dy)
if dx and dy then
self._moved_offset_x = self._moved_offset_x + Math.round(dx)
self._moved_offset_y = self._moved_offset_y + Math.round(dy)
if restrict_to_screen then
local screen_w, screen_h = Screen:getWidth(), Screen:getHeight()
if self._orig_x + self._moved_offset_x < 0 then
self._moved_offset_x = - self._orig_x
end
if self._orig_y + self._moved_offset_y < 0 then
self._moved_offset_y = - self._orig_y
end
if self._orig_x + self._moved_offset_x + self.dimen.w > screen_w then
self._moved_offset_x = screen_w - self._orig_x - self.dimen.w
end
if self._orig_y + self._moved_offset_y + self.dimen.h > screen_h then
self._moved_offset_y = screen_h - self._orig_y - self.dimen.h
end
end
-- if not restrict_to_screen, we don't need to check anything:
-- we trust gestures' position and distances: if we started with our
-- finger on widget, and moved our finger to screen border, a part
-- of the widget should always be on the screen.
else
-- Not-moving Hold can be used to revert to original position
if self._moved_offset_x == 0 and self._moved_offset_y == 0 then
-- If we hold while already in initial position, take that
-- as a wish to toggle between alpha or no-alpha
if self.alpha then
self.orig_alpha = self.alpha
self.alpha = nil
else
self.alpha = self.orig_alpha or 0.7
-- For testing: to visually see how different alpha
-- values look: loop thru decreasing alpha values
-- self.alpha = self.orig_alpha or 1.0
-- if self.alpha > 0.55 then -- below 0.5 are too transparent
-- self.alpha = self.alpha - 0.1
-- else
-- self.alpha = 0.9
-- end
end
end
self._moved_offset_x = 0
self._moved_offset_y = 0
end
-- We need to have all widgets in the area between orig and move position
-- redraw themselves
local orig_dimen = self.dimen:copy() -- dimen before move/paintTo
UIManager:setDirty("all", function()
local update_region = orig_dimen:combine(self.dimen)
logger.dbg("MovableContainer refresh region", update_region)
return "ui", update_region
end)
end
function MovableContainer:onMovableSwipe(_, ges)
logger.dbg("MovableContainer:onMovableSwipe", ges)
if not ges.pos:intersectWith(self.dimen) then
-- with swipe, ges.pos is swipe's start position, which should
-- be on us to consider it
return false
end
self._moving = false -- could have been set by "pan" event received before "swipe"
local direction = ges.direction
local distance = ges.distance
local sq_distance = math.floor(math.sqrt(distance*distance/2))
-- Use restrict_to_screen for all move with Swipe for easy push to screen
-- borders (user can Hold and pan if he wants them outside)
if direction == "north" then self:_moveBy(0, -distance, true)
elseif direction == "south" then self:_moveBy(0, distance, true)
elseif direction == "east" then self:_moveBy(distance, 0, true)
elseif direction == "west" then self:_moveBy(-distance, 0, true)
elseif direction == "northeast" then self:_moveBy(sq_distance, -sq_distance, true)
elseif direction == "northwest" then self:_moveBy(-sq_distance, -sq_distance, true)
elseif direction == "southeast" then self:_moveBy(sq_distance, sq_distance, true)
elseif direction == "southwest" then self:_moveBy(-sq_distance, sq_distance, true)
end
return true
end
function MovableContainer:onMovableTouch(_, ges)
-- First "pan" event may already be outsise us, we need to
-- remember any "touch" event on us prior to "pan"
logger.dbg("MovableContainer:onMovableTouch", ges)
if ges.pos:intersectWith(self.dimen) then
self._touch_pre_pan_was_inside = true
self._move_relative_x = ges.pos.x
self._move_relative_y = ges.pos.y
else
self._touch_pre_pan_was_inside = false
end
return false
end
function MovableContainer:onMovableHold(_, ges)
logger.dbg("MovableContainer:onMovableHold", ges)
if ges.pos:intersectWith(self.dimen) then
self._moving = true -- start of pan
self._move_relative_x = ges.pos.x
self._move_relative_y = ges.pos.y
return true
end
return false
end
function MovableContainer:onMovableHoldPan(_, ges)
logger.dbg("MovableContainer:onMovableHoldPan", ges)
-- we may sometimes not see the "hold" event
if ges.pos:intersectWith(self.dimen) or self._moving or self._touch_pre_pan_was_inside then
self._touch_pre_pan_was_inside = false -- reset it
self._moving = true
return true
end
return false
end
function MovableContainer:onMovableHoldRelease(_, ges)
logger.dbg("MovableContainer:onMovableHoldRelease", ges)
if self._moving or self._touch_pre_pan_was_inside then
self._moving = false
if not self._move_relative_x or not self._move_relative_y then
-- no previous event gave us accurate move info, ignore it
return false
end
self._move_relative_x = ges.pos.x - self._move_relative_x
self._move_relative_y = ges.pos.y - self._move_relative_y
if math.abs(self._move_relative_x) < self.move_threshold and math.abs(self._move_relative_y) < self.move_threshold then
-- Hold with no move (or less than self.move_threshold): use this to reposition to original position
self:_moveBy()
else
self:_moveBy(self._move_relative_x, self._move_relative_y)
self._move_relative_x = nil
self._move_relative_y = nil
end
return true
end
return false
end
function MovableContainer:onMovablePan(_, ges)
logger.dbg("MovableContainer:onMovablePan", ges)
if ges.pos:intersectWith(self.dimen) or self._moving or self._touch_pre_pan_was_inside then
self._touch_pre_pan_was_inside = false -- reset it
self._moving = true
self._move_relative_x = ges.relative.x
self._move_relative_y = ges.relative.y
return true
end
return false
end
function MovableContainer:onMovablePanRelease(_, ges)
logger.dbg("MovableContainer:onMovablePanRelease", ges)
if self._moving then
self:_moveBy(self._move_relative_x, self._move_relative_y)
self._moving = false
self._move_relative_x = nil
self._move_relative_y = nil
return true
end
return false
end
return MovableContainer

@ -13,6 +13,7 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local InputDialog = require("ui/widget/inputdialog") local InputDialog = require("ui/widget/inputdialog")
local LeftContainer = require("ui/widget/container/leftcontainer") local LeftContainer = require("ui/widget/container/leftcontainer")
local LineWidget = require("ui/widget/linewidget") local LineWidget = require("ui/widget/linewidget")
local MovableContainer = require("ui/widget/container/movablecontainer")
local OverlapGroup = require("ui/widget/overlapgroup") local OverlapGroup = require("ui/widget/overlapgroup")
local ScrollHtmlWidget = require("ui/widget/scrollhtmlwidget") local ScrollHtmlWidget = require("ui/widget/scrollhtmlwidget")
local ScrollTextWidget = require("ui/widget/scrolltextwidget") local ScrollTextWidget = require("ui/widget/scrolltextwidget")
@ -187,6 +188,7 @@ end
function DictQuickLookup:update() function DictQuickLookup:update()
local orig_dimen = self.dict_frame and self.dict_frame.dimen or Geom:new{} local orig_dimen = self.dict_frame and self.dict_frame.dimen or Geom:new{}
local orig_moved_offset = self.movable and self.movable:getMovedOffset()
-- Free our previous widget and subwidgets' resources (especially -- Free our previous widget and subwidgets' resources (especially
-- definitions' TextBoxWidget bb, HtmlBoxWidget bb and MuPDF instance, -- definitions' TextBoxWidget bb, HtmlBoxWidget bb and MuPDF instance,
-- and scheduled image_update_action) -- and scheduled image_update_action)
@ -302,7 +304,7 @@ function DictQuickLookup:update()
end end
-- word definition -- word definition
local definition = FrameContainer:new{ self.definition_widget = FrameContainer:new{
padding = self.definition_padding, padding = self.definition_padding,
margin = self.definition_margin, margin = self.definition_margin,
bordersize = 0, bordersize = 0,
@ -456,7 +458,7 @@ function DictQuickLookup:update()
end end
local button_table = ButtonTable:new{ local button_table = ButtonTable:new{
width = math.max(self.width, definition:getSize().w), width = math.max(self.width, self.definition_widget:getSize().w),
button_font_face = "cfont", button_font_face = "cfont",
button_font_size = 20, button_font_size = 20,
buttons = buttons, buttons = buttons,
@ -503,9 +505,9 @@ function DictQuickLookup:update()
CenterContainer:new{ CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = title_bar:getSize().w, w = title_bar:getSize().w,
h = definition:getSize().h, h = self.definition_widget:getSize().h,
}, },
definition, self.definition_widget,
}, },
-- buttons -- buttons
CenterContainer:new{ CenterContainer:new{
@ -517,14 +519,19 @@ function DictQuickLookup:update()
} }
} }
} }
self.movable = MovableContainer:new{
-- We'll handle these events ourselves, and call appropriate
-- MovableContainer's methods when we didn't process the event
ignore_events = {"swipe", "hold", "hold_release"},
self.dict_frame,
}
self.movable:setMovedOffset(orig_moved_offset)
self[1] = WidgetContainer:new{ self[1] = WidgetContainer:new{
align = self.align, align = self.align,
dimen = self.region, dimen = self.region,
FrameContainer:new{ self.movable,
bordersize = 0,
padding = Size.padding.default,
self.dict_frame,
}
} }
UIManager:setDirty("all", function() UIManager:setDirty("all", function()
local update_region = self.dict_frame.dimen:combine(orig_dimen) local update_region = self.dict_frame.dimen:combine(orig_dimen)
@ -734,19 +741,37 @@ function DictQuickLookup:onHoldClose(no_clear)
end end
function DictQuickLookup:onSwipe(arg, ges) function DictQuickLookup:onSwipe(arg, ges)
if ges.direction == "west" then if ges.pos:intersectWith(self.definition_widget.dimen) then
self:changeToNextDict() -- if we want changeDict to still work with swipe outside window :
elseif ges.direction == "east" then -- or not ges.pos:intersectWith(self.dict_frame.dimen) then
self:changeToPrevDict() if ges.direction == "west" then
else self:changeToNextDict()
if self.refresh_callback then self.refresh_callback() end elseif ges.direction == "east" then
-- trigger full refresh self:changeToPrevDict()
UIManager:setDirty(nil, "full") else
-- a long diagonal swipe may also be used for taking a screenshot, if self.refresh_callback then self.refresh_callback() end
-- so let it propagate -- trigger full refresh
return false UIManager:setDirty(nil, "full")
-- a long diagonal swipe may also be used for taking a screenshot,
-- so let it propagate
return false
end
return true
end end
return true -- Let our MovableContainer handle swipe outside of definition
return self.movable:onMovableSwipe(arg, ges)
end
function DictQuickLookup:onHoldStartText(_, ges)
-- Forward Hold events not processed by TextBoxWidget event handler
-- to our MovableContainer
return self.movable:onMovableHold(_, ges)
end
function DictQuickLookup:onHoldReleaseText(_, ges)
-- Forward Hold events not processed by TextBoxWidget event handler
-- to our MovableContainer
return self.movable:onMovableHoldRelease(_, ges)
end end
function DictQuickLookup:lookupInputWord(hint) function DictQuickLookup:lookupInputWord(hint)

@ -33,6 +33,7 @@ local HorizontalGroup = require("ui/widget/horizontalgroup")
local HorizontalSpan = require("ui/widget/horizontalspan") local HorizontalSpan = require("ui/widget/horizontalspan")
local ImageWidget = require("ui/widget/imagewidget") local ImageWidget = require("ui/widget/imagewidget")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local MovableContainer = require("ui/widget/container/movablecontainer")
local ScrollTextWidget = require("ui/widget/scrolltextwidget") local ScrollTextWidget = require("ui/widget/scrolltextwidget")
local Size = require("ui/size") local Size = require("ui/size")
local TextBoxWidget = require("ui/widget/textboxwidget") local TextBoxWidget = require("ui/widget/textboxwidget")
@ -126,9 +127,7 @@ function InfoMessage:init()
width = text_width, width = text_width,
} }
end end
-- we construct the actual content here because self.text is only available now self.movable = MovableContainer:new{
self[1] = CenterContainer:new{
dimen = Screen:getSize(),
FrameContainer:new{ FrameContainer:new{
background = Blitbuffer.COLOR_WHITE, background = Blitbuffer.COLOR_WHITE,
HorizontalGroup:new{ HorizontalGroup:new{
@ -139,6 +138,10 @@ function InfoMessage:init()
} }
} }
} }
self[1] = CenterContainer:new{
dimen = Screen:getSize(),
self.movable,
}
end end
function InfoMessage:onCloseWidget() function InfoMessage:onCloseWidget()

@ -56,6 +56,7 @@ local Geom = require("ui/geometry")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local InputText = require("ui/widget/inputtext") local InputText = require("ui/widget/inputtext")
local LineWidget = require("ui/widget/linewidget") local LineWidget = require("ui/widget/linewidget")
local MovableContainer = require("ui/widget/container/movablecontainer")
local RenderText = require("ui/rendertext") local RenderText = require("ui/rendertext")
local Size = require("ui/size") local Size = require("ui/size")
local TextBoxWidget = require("ui/widget/textboxwidget") local TextBoxWidget = require("ui/widget/textboxwidget")
@ -200,7 +201,9 @@ function InputDialog:init()
w = Screen:getWidth(), w = Screen:getWidth(),
h = Screen:getHeight() - self._input_widget:getKeyboardDimen().h, h = Screen:getHeight() - self._input_widget:getKeyboardDimen().h,
}, },
self.dialog_frame, MovableContainer:new{
self.dialog_frame,
},
} }
end end

@ -806,7 +806,7 @@ function TextBoxWidget:onHoldReleaseText(callback, ges)
local Trapper = require("ui/trapper") local Trapper = require("ui/trapper")
UIManager:scheduleIn(0.1, function() Trapper:wrap(load_and_show_image) end) UIManager:scheduleIn(0.1, function() Trapper:wrap(load_and_show_image) end)
-- And we return without calling the "Hold on text" callback -- And we return without calling the "Hold on text" callback
return return true
end end
end end
end end

@ -19,6 +19,7 @@ local FrameContainer = require("ui/widget/container/framecontainer")
local GestureRange = require("ui/gesturerange") local GestureRange = require("ui/gesturerange")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local LineWidget = require("ui/widget/linewidget") local LineWidget = require("ui/widget/linewidget")
local MovableContainer = require("ui/widget/container/movablecontainer")
local OverlapGroup = require("ui/widget/overlapgroup") local OverlapGroup = require("ui/widget/overlapgroup")
local ScrollTextWidget = require("ui/widget/scrolltextwidget") local ScrollTextWidget = require("ui/widget/scrolltextwidget")
local Size = require("ui/size") local Size = require("ui/size")
@ -150,14 +151,14 @@ function TextViewer:init()
local textw_height = self.height - titlew:getSize().h - separator:getSize().h - button_table:getSize().h local textw_height = self.height - titlew:getSize().h - separator:getSize().h - button_table:getSize().h
self.scroll_text_w = ScrollTextWidget:new{ self.scroll_text_w = ScrollTextWidget:new{
text = self.text, text = self.text,
face = self.text_face, face = self.text_face,
width = self.width - 2*self.text_padding - 2*self.text_margin, width = self.width - 2*self.text_padding - 2*self.text_margin,
height = textw_height - 2*self.text_padding -2*self.text_margin, height = textw_height - 2*self.text_padding -2*self.text_margin,
dialog = self, dialog = self,
justified = true, justified = true,
} }
local textw = FrameContainer:new{ self.textw = FrameContainer:new{
padding = self.text_padding, padding = self.text_padding,
margin = self.text_margin, margin = self.text_margin,
bordersize = 0, bordersize = 0,
@ -176,9 +177,9 @@ function TextViewer:init()
CenterContainer:new{ CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = self.width, w = self.width,
h = textw:getSize().h, h = self.textw:getSize().h,
}, },
textw, self.textw,
}, },
CenterContainer:new{ CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
@ -189,10 +190,14 @@ function TextViewer:init()
} }
} }
} }
self.movable = MovableContainer:new{
ignore_events = {"swipe"},
self.frame,
}
self[1] = WidgetContainer:new{ self[1] = WidgetContainer:new{
align = self.align, align = self.align,
dimen = self.region, dimen = self.region,
self.frame, self.movable,
} }
UIManager:setDirty("all", function() UIManager:setDirty("all", function()
local update_region = self.frame.dimen:combine(orig_dimen) local update_region = self.frame.dimen:combine(orig_dimen)
@ -233,19 +238,23 @@ function TextViewer:onClose()
end end
function TextViewer:onSwipe(arg, ges) function TextViewer:onSwipe(arg, ges)
if ges.direction == "west" then if ges.pos:intersectWith(self.textw.dimen) then
self.scroll_text_w:scrollText(1) if ges.direction == "west" then
return true self.scroll_text_w:scrollText(1)
elseif ges.direction == "east" then return true
self.scroll_text_w:scrollText(-1) elseif ges.direction == "east" then
return true self.scroll_text_w:scrollText(-1)
else return true
-- trigger full refresh else
UIManager:setDirty(nil, "full") -- trigger full refresh
-- a long diagonal swipe may also be used for taking a screenshot, UIManager:setDirty(nil, "full")
-- so let it propagate -- a long diagonal swipe may also be used for taking a screenshot,
return false -- so let it propagate
return false
end
end end
-- Let our MovableContainer handle swipe outside of text
return self.movable:onMovableSwipe(arg, ges)
end end
return TextViewer return TextViewer

Loading…
Cancel
Save