2017-09-11 08:32:12 +00:00
|
|
|
local Event = require("ui/event")
|
2013-10-18 20:38:07 +00:00
|
|
|
local InputDialog = require("ui/widget/inputdialog")
|
2021-02-20 18:09:57 +00:00
|
|
|
local SkimToWidget = require("ui/widget/skimtowidget")
|
2017-09-11 08:32:12 +00:00
|
|
|
local UIManager = require("ui/uimanager")
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
2013-10-18 20:38:07 +00:00
|
|
|
local _ = require("gettext")
|
2020-03-26 13:04:59 +00:00
|
|
|
local T = require("ffi/util").template
|
2013-07-30 15:09:08 +00:00
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local ReaderGoto = WidgetContainer:extend{}
|
2013-07-30 15:09:08 +00:00
|
|
|
|
|
|
|
function ReaderGoto:init()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui.menu:registerToMainMenu(self)
|
2013-07-31 05:51:01 +00:00
|
|
|
end
|
|
|
|
|
2017-03-04 13:46:38 +00:00
|
|
|
function ReaderGoto:addToMainMenu(menu_items)
|
|
|
|
menu_items.go_to = {
|
2021-08-14 19:29:25 +00:00
|
|
|
text = _("Go to page"),
|
2014-03-13 13:52:43 +00:00
|
|
|
callback = function()
|
|
|
|
self:onShowGotoDialog()
|
|
|
|
end,
|
2017-02-28 21:46:32 +00:00
|
|
|
}
|
2017-03-04 13:46:38 +00:00
|
|
|
menu_items.skim_to = {
|
2021-08-14 19:29:25 +00:00
|
|
|
text = _("Skim document"),
|
2016-12-29 07:27:48 +00:00
|
|
|
callback = function()
|
|
|
|
self:onShowSkimtoDialog()
|
|
|
|
end,
|
2017-02-28 21:46:32 +00:00
|
|
|
}
|
2013-07-31 05:51:01 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderGoto:onShowGotoDialog()
|
2021-02-20 18:09:59 +00:00
|
|
|
local curr_page
|
2016-02-26 07:50:12 +00:00
|
|
|
if self.document.info.has_pages then
|
2016-02-26 08:04:21 +00:00
|
|
|
curr_page = self.ui.paging.current_page
|
2016-02-26 07:50:12 +00:00
|
|
|
else
|
2016-02-26 08:04:21 +00:00
|
|
|
curr_page = self.document:getCurrentPage()
|
2016-02-26 07:50:12 +00:00
|
|
|
end
|
2020-03-26 13:04:59 +00:00
|
|
|
local input_hint
|
|
|
|
if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then
|
|
|
|
input_hint = T("@%1 (%2 - %3)", self.ui.pagemap:getCurrentPageLabel(true),
|
|
|
|
self.ui.pagemap:getFirstPageLabel(true),
|
|
|
|
self.ui.pagemap:getLastPageLabel(true))
|
|
|
|
else
|
|
|
|
input_hint = T("@%1 (1 - %2)", curr_page, self.document:getPageCount())
|
|
|
|
end
|
2021-11-07 18:26:07 +00:00
|
|
|
input_hint = input_hint .. string.format(" %.2f%%", curr_page / self.document:getPageCount() * 100)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.goto_dialog = InputDialog:new{
|
2021-11-07 18:26:07 +00:00
|
|
|
title = _("Enter page number or percentage"),
|
2020-03-26 13:04:59 +00:00
|
|
|
input_hint = input_hint,
|
2020-10-31 09:40:36 +00:00
|
|
|
description = self.document:hasHiddenFlows() and
|
|
|
|
_([[
|
|
|
|
x for an absolute page number
|
|
|
|
[x] for a page number in the main (linear) flow
|
|
|
|
[x]y for a page number in the non-linear fragment y]])
|
|
|
|
or nil,
|
2014-03-13 13:52:43 +00:00
|
|
|
buttons = {
|
2015-03-12 07:45:58 +00:00
|
|
|
{
|
2014-03-13 13:52:43 +00:00
|
|
|
{
|
2021-11-07 18:26:07 +00:00
|
|
|
text = _("Skim"),
|
2014-03-13 13:52:43 +00:00
|
|
|
callback = function()
|
|
|
|
self:close()
|
2021-11-07 18:26:07 +00:00
|
|
|
self.skimto = SkimToWidget:new{
|
|
|
|
document = self.document,
|
|
|
|
ui = self.ui,
|
|
|
|
callback_switch_to_goto = function()
|
|
|
|
UIManager:close(self.skimto)
|
|
|
|
self:onShowGotoDialog()
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
UIManager:show(self.skimto)
|
|
|
|
|
2014-03-13 13:52:43 +00:00
|
|
|
end,
|
|
|
|
},
|
2016-12-29 07:27:48 +00:00
|
|
|
{
|
2021-11-07 18:26:07 +00:00
|
|
|
text = _("Go to %"),
|
2021-08-14 19:29:25 +00:00
|
|
|
callback = function()
|
2021-11-07 18:26:07 +00:00
|
|
|
self:gotoPercent()
|
2021-08-14 19:29:25 +00:00
|
|
|
end,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
2021-11-07 18:26:07 +00:00
|
|
|
text = _("Cancel"),
|
2022-03-04 20:20:00 +00:00
|
|
|
id = "close",
|
2016-12-29 07:27:48 +00:00
|
|
|
callback = function()
|
|
|
|
self:close()
|
|
|
|
end,
|
|
|
|
},
|
2021-11-07 18:26:07 +00:00
|
|
|
{
|
|
|
|
text = _("Go to page"),
|
|
|
|
is_enter_default = true,
|
|
|
|
callback = function()
|
|
|
|
self:gotoPage()
|
|
|
|
end,
|
|
|
|
}
|
2014-03-13 13:52:43 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
input_type = "number",
|
|
|
|
}
|
|
|
|
UIManager:show(self.goto_dialog)
|
2018-03-30 10:46:36 +00:00
|
|
|
self.goto_dialog:onShowKeyboard()
|
2013-07-30 15:09:08 +00:00
|
|
|
end
|
|
|
|
|
2016-12-29 07:27:48 +00:00
|
|
|
function ReaderGoto:onShowSkimtoDialog()
|
|
|
|
self.skimto = SkimToWidget:new{
|
|
|
|
document = self.document,
|
|
|
|
ui = self.ui,
|
|
|
|
callback_switch_to_goto = function()
|
|
|
|
UIManager:close(self.skimto)
|
|
|
|
self:onShowGotoDialog()
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
UIManager:show(self.skimto)
|
|
|
|
end
|
|
|
|
|
2013-07-30 15:37:51 +00:00
|
|
|
function ReaderGoto:close()
|
2014-03-13 13:52:43 +00:00
|
|
|
UIManager:close(self.goto_dialog)
|
2013-07-30 15:09:08 +00:00
|
|
|
end
|
|
|
|
|
2013-07-30 15:37:51 +00:00
|
|
|
function ReaderGoto:gotoPage()
|
2015-03-12 07:45:58 +00:00
|
|
|
local page_number = self.goto_dialog:getInputText()
|
|
|
|
local relative_sign = page_number:sub(1, 1)
|
|
|
|
local number = tonumber(page_number)
|
2014-03-13 13:52:43 +00:00
|
|
|
if number then
|
2018-08-15 13:22:55 +00:00
|
|
|
self.ui.link:addCurrentLocationToStack()
|
2015-03-12 07:45:58 +00:00
|
|
|
if relative_sign == "+" or relative_sign == "-" then
|
|
|
|
self.ui:handleEvent(Event:new("GotoRelativePage", number))
|
|
|
|
else
|
2020-03-26 13:04:59 +00:00
|
|
|
if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then
|
|
|
|
number = self.ui.pagemap:getRenderedPageNumber(page_number, true)
|
|
|
|
if number then -- found
|
|
|
|
self.ui:handleEvent(Event:new("GotoPage", number))
|
|
|
|
else
|
|
|
|
return -- avoid self:close()
|
|
|
|
end
|
|
|
|
else
|
|
|
|
self.ui:handleEvent(Event:new("GotoPage", number))
|
|
|
|
end
|
2015-03-12 07:45:58 +00:00
|
|
|
end
|
|
|
|
self:close()
|
2020-10-31 09:40:36 +00:00
|
|
|
elseif self.ui.document:hasHiddenFlows() then
|
|
|
|
-- if there are hidden flows, we accept the syntax [x]y
|
|
|
|
-- for page number x in flow number y (y defaults to 0 if not present)
|
|
|
|
local flow
|
|
|
|
number, flow = string.match(page_number, "^ *%[(%d+)%](%d*) *$")
|
|
|
|
flow = tonumber(flow) or 0
|
|
|
|
number = tonumber(number)
|
|
|
|
if number then
|
|
|
|
if self.ui.document.flows[flow] ~= nil then
|
|
|
|
if number < 1 or number > self.ui.document:getTotalPagesInFlow(flow) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local page = 0
|
|
|
|
-- in flow 0 (linear), we count pages skipping non-linear flows,
|
|
|
|
-- in a non-linear flow the target page is immediate
|
|
|
|
if flow == 0 then
|
|
|
|
for i=1, number do
|
|
|
|
page = self.ui.document:getNextPage(page)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
page = self.ui.document:getFirstPageInFlow(flow) + number - 1
|
|
|
|
end
|
|
|
|
if page > 0 then
|
|
|
|
self.ui:handleEvent(Event:new("GotoPage", page))
|
|
|
|
self:close()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
end
|
2013-07-30 15:09:08 +00:00
|
|
|
end
|
2013-10-18 20:38:07 +00:00
|
|
|
|
2021-11-07 18:26:07 +00:00
|
|
|
function ReaderGoto:gotoPercent()
|
|
|
|
local number = self.goto_dialog:getInputValue()
|
|
|
|
if number then
|
|
|
|
self.ui.link:addCurrentLocationToStack()
|
|
|
|
self.ui:handleEvent(Event:new("GotoPercent", number))
|
|
|
|
self:close()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-02-05 07:19:35 +00:00
|
|
|
function ReaderGoto:onGoToBeginning()
|
2020-10-31 09:40:36 +00:00
|
|
|
local new_page = self.ui.document:getNextPage(0)
|
|
|
|
if new_page then
|
|
|
|
self.ui.link:addCurrentLocationToStack()
|
|
|
|
self.ui:handleEvent(Event:new("GotoPage", new_page))
|
|
|
|
end
|
2020-02-05 07:19:35 +00:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderGoto:onGoToEnd()
|
2020-10-31 09:40:36 +00:00
|
|
|
local new_page = self.ui.document:getPrevPage(0)
|
|
|
|
if new_page then
|
2020-02-05 07:19:35 +00:00
|
|
|
self.ui.link:addCurrentLocationToStack()
|
2020-10-31 09:40:36 +00:00
|
|
|
self.ui:handleEvent(Event:new("GotoPage", new_page))
|
2020-02-05 07:19:35 +00:00
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2013-10-18 20:38:07 +00:00
|
|
|
return ReaderGoto
|