2
0
mirror of https://github.com/koreader/koreader synced 2024-10-31 21:20:20 +00:00
koreader/frontend/ui/widget/scrollhtmlwidget.lua
poire-z f9086a2ba9
EPUB links: show footnotes in popup, larger tap area (#4261)
Adds new options to the Links> submenu, for now only
available and used with CRE documents.
- Allow larger tap area around links
- Ignore external links
- Show footnotes in popup
- Show more links as footnotes

(This last item is mostly for testing and loosening the
footnote detection algorithm, and see how it would behave
with glossary-like links and inter glossary terms links.)

Fix distance computation from gesture position to link by
using segments.
Code for detecting if a link is a footnote is in cre.cpp, and
tweakable a bit with flags in ReaderLink:showAsFoonotePopup().

Footnotes HTML content is displayed by a new FootnoteWidget,
which uses MuPDF for its rendering.
From it, swipe south or tap outside to close, swipe to the left
to follow the original link and jump to the footnote location
in the book.

Also fix tap on highlights after the recent change to use segments
for displaying: use segments also when checking taps.
2018-10-10 18:50:24 +02:00

172 lines
5.3 KiB
Lua

--[[--
HTML widget with vertical scroll bar.
--]]
local Device = require("device")
local HtmlBoxWidget = require("ui/widget/htmlboxwidget")
local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange")
local HorizontalGroup = require("ui/widget/horizontalgroup")
local HorizontalSpan = require("ui/widget/horizontalspan")
local InputContainer = require("ui/widget/container/inputcontainer")
local UIManager = require("ui/uimanager")
local VerticalScrollBar = require("ui/widget/verticalscrollbar")
local Math = require("optmath")
local Input = Device.input
local Screen = Device.screen
local ScrollHtmlWidget = InputContainer:new{
html_body = nil,
css = nil,
default_font_size = 18,
htmlbox_widget = nil,
v_scroll_bar = nil,
dialog = nil,
html_link_tapped_callback = nil,
dimen = nil,
width = 0,
height = 0,
scroll_bar_width = Screen:scaleBySize(6),
text_scroll_span = Screen:scaleBySize(12),
}
function ScrollHtmlWidget:init()
self.htmlbox_widget = HtmlBoxWidget:new{
dimen = Geom:new{
w = self.width - self.scroll_bar_width - self.text_scroll_span,
h = self.height,
},
html_link_tapped_callback = self.html_link_tapped_callback,
}
self.htmlbox_widget:setContent(self.html_body, self.css, self.default_font_size)
self.v_scroll_bar = VerticalScrollBar:new{
enable = self.htmlbox_widget.page_count > 1,
width = self.scroll_bar_width,
height = self.height,
}
self.v_scroll_bar:set((self.htmlbox_widget.page_number-1) / self.htmlbox_widget.page_count, self.htmlbox_widget.page_number / self.htmlbox_widget.page_count)
local horizontal_group = HorizontalGroup:new{}
table.insert(horizontal_group, self.htmlbox_widget)
table.insert(horizontal_group, HorizontalSpan:new{width=self.text_scroll_span})
table.insert(horizontal_group, self.v_scroll_bar)
self[1] = horizontal_group
self.dimen = Geom:new(self[1]:getSize())
if Device:isTouchDevice() then
self.ges_events = {
ScrollText = {
GestureRange:new{
ges = "swipe",
range = function() return self.dimen end,
},
},
TapScrollText = { -- allow scrolling with tap
GestureRange:new{
ges = "tap",
range = function() return self.dimen end,
},
},
}
end
if Device:hasKeyboard() or Device:hasKeys() then
self.key_events = {
ScrollDown = {{Input.group.PgFwd}, doc = "scroll down"},
ScrollUp = {{Input.group.PgBack}, doc = "scroll up"},
}
end
end
function ScrollHtmlWidget:getSinglePageHeight()
return self.htmlbox_widget:getSinglePageHeight()
end
function ScrollHtmlWidget:scrollToRatio(ratio)
ratio = math.max(0, math.min(1, ratio)) -- ensure ratio is between 0 and 1 (100%)
local page_num = 1 + Math.round((self.htmlbox_widget.page_count - 1) * ratio)
if page_num == self.htmlbox_widget.page_number then
return
end
self.htmlbox_widget.page_number = page_num
self.v_scroll_bar:set((page_num-1) / self.htmlbox_widget.page_count, page_num / self.htmlbox_widget.page_count)
self.htmlbox_widget:freeBb()
self.htmlbox_widget:_render()
UIManager:setDirty(self.dialog, function()
return "partial", self.dimen
end)
end
function ScrollHtmlWidget:scrollText(direction)
if direction == 0 then
return
end
if direction > 0 then
if self.htmlbox_widget.page_number >= self.htmlbox_widget.page_count then
return
end
self.htmlbox_widget.page_number = self.htmlbox_widget.page_number + 1
elseif direction < 0 then
if self.htmlbox_widget.page_number <= 1 then
return
end
self.htmlbox_widget.page_number = self.htmlbox_widget.page_number - 1
end
self.v_scroll_bar:set((self.htmlbox_widget.page_number-1) / self.htmlbox_widget.page_count, self.htmlbox_widget.page_number / self.htmlbox_widget.page_count)
self.htmlbox_widget:freeBb()
self.htmlbox_widget:_render()
UIManager:setDirty(self.dialog, function()
return "partial", self.dimen
end)
end
function ScrollHtmlWidget:onScrollText(arg, ges)
if ges.direction == "north" then
self:scrollText(1)
return true
elseif ges.direction == "south" then
self:scrollText(-1)
return true
end
-- if swipe west/east, let it propagate up (e.g. for quickdictlookup to
-- go to next/prev result)
end
function ScrollHtmlWidget:onTapScrollText(arg, ges)
if ges.pos.x < Screen:getWidth()/2 then
if self.htmlbox_widget.page_number > 1 then
self:scrollText(-1)
return true
end
else
if self.htmlbox_widget.page_number < self.htmlbox_widget.page_count then
self:scrollText(1)
return true
end
end
-- if we couldn't scroll (because we're already at top or bottom),
-- let it propagate up (e.g. for quickdictlookup to go to next/prev result)
end
function ScrollHtmlWidget:onScrollDown()
self:scrollText(1)
return true
end
function ScrollHtmlWidget:onScrollUp()
self:scrollText(-1)
return true
end
return ScrollHtmlWidget