Non-touch: highlight movement improvement and enable page crop (#8947)

reviewable/pr9004/r1
Philip Chan 2 years ago committed by GitHub
parent bd17119d07
commit 77accf6546
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,7 +9,8 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local Math = require("optmath")
local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup")
local Screen = require("device").screen
local Device = require("device")
local Screen = Device.screen
local _ = require("gettext")
local ReaderCropping = InputContainer:new{}
@ -85,7 +86,11 @@ function ReaderCropping:onPageCrop(mode)
}
}
-- height available for page
local page_container_h = Screen:getHeight() - button_table:getSize().h
local page_container_h = Screen:getHeight()
if Device:isTouchDevice() then
-- non-touch devices do not need cancel and apply buttons
page_container_h = page_container_h - button_table:getSize().h
end
local page_dimen = Geom:new{
w = Screen:getWidth(),
h = page_container_h,
@ -102,9 +107,8 @@ function ReaderCropping:onPageCrop(mode)
self.crop_dialog = VerticalGroup:new{
align = "left",
self.bbox_widget,
button_container,
(Device:isTouchDevice() and button_container) or nil, -- button bar only availble for touch devices
}
UIManager:show(self.crop_dialog)
return true
end

@ -51,6 +51,7 @@ function ReaderHighlight:init()
self._start_indicator_highlight = false
self._current_indicator_pos = nil
self._previous_indicator_pos = nil
self._last_indicator_move_args = {dx = 0, dy = 0, distance = 0, time = TimeVal:now()}
if Device:hasDPad() then
-- Used for text selection with dpad/keys
@ -63,10 +64,10 @@ function ReaderHighlight:init()
self.key_events.RightHighlightIndicator = { {"Right"}, doc = "move indicator right", event = "MoveHighlightIndicator", args = {1, 0} }
self.key_events.HighlightPress = { {"Press"}, doc = "highlight start or end" }
if Device:hasKeys() then
self.key_events.QuicklyUpHighlightIndicator = { {"Shift", "Up"}, doc = "quick move indicator up", event = "MoveHighlightIndicator", args = {0, -1, QUICK_INDICTOR_MOVE} }
self.key_events.QuicklyDownHighlightIndicator = { {"Shift", "Down"}, doc = "quick move indicator down", event = "MoveHighlightIndicator", args = {0, 1, QUICK_INDICTOR_MOVE} }
self.key_events.QuicklyLeftHighlightIndicator = { {"Shift", "Left"}, doc = "quick move indicator left", event = "MoveHighlightIndicator", args = {-1, 0, QUICK_INDICTOR_MOVE} }
self.key_events.QuicklyRightHighlightIndicator = { {"Shift", "Right"}, doc = "quick move indicator right", event = "MoveHighlightIndicator", args = {1, 0, QUICK_INDICTOR_MOVE} }
self.key_events.QuickUpHighlightIndicator = { {"Shift", "Up"}, doc = "quick move indicator up", event = "MoveHighlightIndicator", args = {0, -1, QUICK_INDICTOR_MOVE} }
self.key_events.QuickDownHighlightIndicator = { {"Shift", "Down"}, doc = "quick move indicator down", event = "MoveHighlightIndicator", args = {0, 1, QUICK_INDICTOR_MOVE} }
self.key_events.QuickLeftHighlightIndicator = { {"Shift", "Left"}, doc = "quick move indicator left", event = "MoveHighlightIndicator", args = {-1, 0, QUICK_INDICTOR_MOVE} }
self.key_events.QuickRightHighlightIndicator = { {"Shift", "Right"}, doc = "quick move indicator right", event = "MoveHighlightIndicator", args = {1, 0, QUICK_INDICTOR_MOVE} }
self.key_events.StartHighlightIndicator = { {"H"}, doc = "start non-touch highlight" }
end
end
@ -1938,18 +1939,33 @@ end
function ReaderHighlight:onMoveHighlightIndicator(args)
if self.view.visible_area and self._current_indicator_pos then
local dx, dy, quick_move = unpack(args)
local step_distance = self.view.visible_area.w / 5 -- quick move distance: fifth of visible_area
local y_step_distance = self.view.visible_area.h / 5
if step_distance > y_step_distance then
-- take the smaller, make all direction move distance much predictable
step_distance = y_step_distance
end
if not quick_move then
step_distance = step_distance / 4 -- twentieth of visible_area
end
local quick_move_distance_dx = self.view.visible_area.w / 5 -- quick move distance: fifth of visible_area
local quick_move_distance_dy = self.view.visible_area.h / 5
-- single move distance, small and capable to move on word with small font size and narrow line height
local move_distance = Size.item.height_default / 4
local rect = self._current_indicator_pos:copy()
rect.x = rect.x + step_distance * dx
rect.y = rect.y + step_distance * dy
if quick_move then
rect.x = rect.x + quick_move_distance_dx * dx
rect.y = rect.y + quick_move_distance_dy * dy
else
local now = TimeVal:now()
if dx == self._last_indicator_move_args.dx and dy == self._last_indicator_move_args.dy then
local diff = now - self._last_indicator_move_args.time
-- if press same arrow key in 1 second, speed up
-- double press: 4 single move distances, usually move to next word or line
-- triple press: 16 single distances, usually skip several words or lines
-- quadruple press: 54 single distances, almost move to screen edge
if diff < TimeVal:new{ sec = 1, usec = 0 } then
move_distance = self._last_indicator_move_args.distance * 4
end
end
rect.x = rect.x + move_distance * dx
rect.y = rect.y + move_distance * dy
self._last_indicator_move_args.distance = move_distance
self._last_indicator_move_args.dx = dx
self._last_indicator_move_args.dy = dy
self._last_indicator_move_args.time = now
end
if rect.x < 0 then
rect.x = 0
end

@ -87,7 +87,7 @@ local KoptOptions = {
alternate = false,
values = {3, 1, 2, 0},
default_value = DKOPTREADER_CONFIG_TRIM_PAGE,
enabled_func = Device.isTouchDevice,
enabled_func = function() return Device:isTouchDevice() or Device:hasDPad() end,
event = "PageCrop",
args = {"none", "auto", "semi-auto", "manual"},
name_text_hold_callback = optionsutil.showValues,

@ -8,6 +8,7 @@ local Event = require("ui/event")
local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange")
local Math = require("optmath")
local Screen = Device.screen
local Size = require("ui/size")
local UIManager = require("ui/uimanager")
@ -48,6 +49,12 @@ function BBoxWidget:init()
}
}
}
else
self._confirm_stage = 1 -- 1 for left-top, 2 for right-bottom
self.key_events.MoveIndicatorUp = { { "Up" }, doc="Move indicator up", event="MoveIndicator", args = { 0, -1 } }
self.key_events.MoveIndicatorDown = { { "Down" }, doc="Move indicator down", event="MoveIndicator", args = { 0, 1 } }
self.key_events.MoveIndicatorLeft = { { "Left" }, doc="Move indicator left", event="MoveIndicator", args = { -1, 0 } }
self.key_events.MoveIndicatorRight = { { "Right" }, doc="Move indicator right", event="MoveIndicator", args = { 1, 0 } }
end
if Device:hasKeys() then
self.key_events.Close = { {Device.input.group.Back}, doc = "close windows" }
@ -74,6 +81,35 @@ function BBoxWidget:paintTo(bb, x, y)
bb:invertRect(bbox.x0, bbox.y0, self.linesize, bbox.y1 - bbox.y0 + self.linesize)
-- right edge
bb:invertRect(bbox.x1, bbox.y0 + self.linesize, self.linesize, bbox.y1 - bbox.y0)
if self._confirm_stage == 1 then
-- left top indicator
self:_drawIndicator(bb, bbox.x0, bbox.y0)
elseif self._confirm_stage == 2 then
-- right bottom indicator
self:_drawIndicator(bb, bbox.x1, bbox.y1)
end
end
function BBoxWidget:_drawIndicator(bb, x, y)
local rect = Geom:new({
x = x - Size.item.height_default / 2,
y = y - Size.item.height_default / 2,
w = Size.item.height_default,
h = Size.item.height_default,
})
-- paint big cross line +
bb:invertRect(
rect.x,
rect.y + rect.h / 2 - Size.border.thick / 2,
rect.w,
Size.border.thick
)
bb:invertRect(
rect.x + rect.w / 2 - Size.border.thick / 2,
rect.y,
Size.border.thick,
rect.h
)
end
-- transform page bbox to screen bbox
@ -194,7 +230,82 @@ function BBoxWidget:adjustScreenBBox(ges, relative)
y1 = Math.round(bottom_right.y)
}
UIManager:setDirty("all")
UIManager:setDirty(self.ui, "ui")
end
function BBoxWidget:onMoveIndicator(args)
local dx, dy = unpack(args)
local bbox = self.screen_bbox
local move_distance = Size.item.height_default / 4
local half_indicator_size = move_distance * 2
-- mark edges dirty to redraw
-- top edge
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x0 - move_distance,
y = bbox.y0 - move_distance,
w = bbox.x1 - bbox.x0 + move_distance,
h = move_distance * 2
})
-- left edge
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x0 - move_distance,
y = bbox.y0 - move_distance,
w = move_distance * 2,
h = bbox.y1 - bbox.y0 + move_distance,
})
-- right edge
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x1 - move_distance,
y = bbox.y0 - move_distance,
w = move_distance * 2,
h = bbox.y1 - bbox.y0 + move_distance,
})
-- bottom edge
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x0 - move_distance,
y = bbox.y1 - move_distance,
w = bbox.x1 - bbox.x0 + move_distance,
h = move_distance * 2,
})
-- left top indicator
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x0 - half_indicator_size - move_distance,
y = bbox.y0 - half_indicator_size - move_distance,
w = half_indicator_size * 2 + move_distance,
h = half_indicator_size * 2 + move_distance
})
-- bottom right indicator
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x1 - half_indicator_size,
y = bbox.y1 - half_indicator_size,
w = half_indicator_size * 2 + move_distance,
h = half_indicator_size * 2 + move_distance
})
if self._confirm_stage == 1 then
local x = self.screen_bbox.x0 + dx * Size.item.height_default / 4
local y = self.screen_bbox.y0 + dy * Size.item.height_default / 4
local max_x = self.screen_bbox.x1 - Size.item.height_default
local max_y = self.screen_bbox.y1 - Size.item.height_default
x = (x > 0 and x) or 0
x = (x < max_x and x) or max_x
y = (y > 0 and y) or 0
y = (y < max_y and y) or max_y
self.screen_bbox.x0 = Math.round(x)
self.screen_bbox.y0 = Math.round(y)
return true
elseif self._confirm_stage == 2 then
local x = self.screen_bbox.x1 + dx * Size.item.height_default / 4
local y = self.screen_bbox.y1 + dy * Size.item.height_default / 4
local min_x = self.screen_bbox.x0 + Size.item.height_default
local min_y = self.screen_bbox.y0 + Size.item.height_default
x = (x > min_x and x) or min_x
x = (x < Screen:getWidth() and x) or Screen:getWidth()
y = (y > min_y and y) or min_y
y = (y < Screen:getHeight() and y) or Screen:getHeight()
self.screen_bbox.x1 = Math.round(x)
self.screen_bbox.y1 = Math.round(y)
return true
end
end
function BBoxWidget:getModifiedPageBBox()
@ -228,10 +339,31 @@ end
function BBoxWidget:onClose()
self.ui:handleEvent(Event:new("CancelPageCrop"))
return true
end
function BBoxWidget:onSelect()
self.ui:handleEvent(Event:new("ConfirmPageCrop"))
if not self._confirm_stage or self._confirm_stage == 2 then
self.ui:handleEvent(Event:new("ConfirmPageCrop"))
else
local bbox = self.screen_bbox
self._confirm_stage = self._confirm_stage + 1
-- left top indicator
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x0 - Size.item.height_default / 2,
y = bbox.y0 - Size.item.height_default / 2,
w = Size.item.height_default,
h = Size.item.height_default,
})
-- right bottom indicator
UIManager:setDirty(self.ui, "ui", Geom:new{
x = bbox.x1 - Size.item.height_default / 2,
y = bbox.y1 - Size.item.height_default / 2,
w = Size.item.height_default,
h = Size.item.height_default,
})
end
return true
end

Loading…
Cancel
Save