2019-12-06 21:55:39 +00:00
local BD = require ( " ui/bidi " )
2021-04-16 19:59:01 +00:00
local Blitbuffer = require ( " ffi/blitbuffer " )
2014-10-14 13:33:13 +00:00
local Button = require ( " ui/widget/button " )
2017-04-29 08:38:09 +00:00
local CenterContainer = require ( " ui/widget/container/centercontainer " )
2018-06-13 22:46:52 +00:00
local ConfirmBox = require ( " ui/widget/confirmbox " )
2014-10-30 18:42:18 +00:00
local Device = require ( " device " )
2013-10-22 15:11:31 +00:00
local Event = require ( " ui/event " )
2014-06-10 13:32:49 +00:00
local Font = require ( " ui/font " )
2017-04-29 08:38:09 +00:00
local GestureRange = require ( " ui/gesturerange " )
local Geom = require ( " ui/geometry " )
2020-09-30 17:56:56 +00:00
local InfoMessage = require ( " ui/widget/infomessage " )
2017-04-29 08:38:09 +00:00
local InputContainer = require ( " ui/widget/container/inputcontainer " )
local Menu = require ( " ui/widget/menu " )
2021-04-15 17:07:34 +00:00
local Size = require ( " ui/size " )
2017-04-29 08:38:09 +00:00
local UIManager = require ( " ui/uimanager " )
2020-02-28 21:56:12 +00:00
local logger = require ( " logger " )
2020-09-30 17:56:56 +00:00
local util = require ( " util " )
2013-10-18 20:38:07 +00:00
local _ = require ( " gettext " )
2021-07-26 07:41:04 +00:00
local N_ = _.ngettext
2017-04-29 08:38:09 +00:00
local Screen = Device.screen
2020-02-28 21:56:12 +00:00
local T = require ( " ffi/util " ) . template
2013-10-18 20:38:07 +00:00
local ReaderToc = InputContainer : new {
2014-03-13 13:52:43 +00:00
toc = nil ,
2020-09-27 20:25:16 +00:00
toc_depth = nil ,
ticks = nil ,
ticks_flattened = nil ,
2021-02-20 18:05:12 +00:00
ticks_flattened_filtered = nil ,
2014-10-14 13:33:13 +00:00
toc_indent = " " ,
collapsed_toc = { } ,
collapse_depth = 2 ,
expanded_nodes = { } ,
2014-03-13 13:52:43 +00:00
toc_menu_title = _ ( " Table of contents " ) ,
2018-06-13 22:46:52 +00:00
alt_toc_menu_title = _ ( " Table of contents * " ) ,
2021-02-04 16:43:52 +00:00
toc_items_per_page_default = 14 ,
2012-05-27 11:47:22 +00:00
}
2012-12-31 00:13:46 +00:00
function ReaderToc : init ( )
2014-03-13 13:52:43 +00:00
if Device : hasKeyboard ( ) then
self.key_events = {
ShowToc = {
{ " T " } ,
2014-06-05 06:58:53 +00:00
doc = " show Table of Content menu " } ,
2014-03-13 13:52:43 +00:00
}
end
2021-02-04 16:43:52 +00:00
2021-03-06 21:44:18 +00:00
if G_reader_settings : hasNot ( " toc_items_per_page " ) then
2021-02-04 16:43:52 +00:00
-- The TOC items per page and items' font size can now be
-- configured. Previously, the ones set for the file browser
-- were used. Initialize them from these ones.
local items_per_page = G_reader_settings : readSetting ( " items_per_page " )
2021-03-06 21:44:18 +00:00
or self.toc_items_per_page_default
2021-02-04 16:43:52 +00:00
G_reader_settings : saveSetting ( " toc_items_per_page " , items_per_page )
local items_font_size = G_reader_settings : readSetting ( " items_font_size " )
if items_font_size and items_font_size ~= Menu.getItemFontSize ( items_per_page ) then
-- Keep the user items font size if it's not the default for items_per_page
G_reader_settings : saveSetting ( " toc_items_font_size " , items_font_size )
end
end
2014-10-15 12:47:13 +00:00
self : resetToc ( )
2014-03-13 13:52:43 +00:00
self.ui . menu : registerToMainMenu ( self )
2012-12-31 00:13:46 +00:00
end
2021-02-04 16:43:52 +00:00
function ReaderToc : onReadSettings ( config )
self.toc_ticks_ignored_levels = config : readSetting ( " toc_ticks_ignored_levels " ) or { }
2021-02-20 18:05:12 +00:00
self.toc_chapter_navigation_bind_to_ticks = config : readSetting ( " toc_chapter_navigation_bind_to_ticks " )
self.toc_chapter_title_bind_to_ticks = config : readSetting ( " toc_chapter_title_bind_to_ticks " )
2021-02-04 16:43:52 +00:00
end
function ReaderToc : onSaveSettings ( )
self.ui . doc_settings : saveSetting ( " toc_ticks_ignored_levels " , self.toc_ticks_ignored_levels )
2021-02-20 18:05:12 +00:00
self.ui . doc_settings : saveSetting ( " toc_chapter_navigation_bind_to_ticks " , self.toc_chapter_navigation_bind_to_ticks )
self.ui . doc_settings : saveSetting ( " toc_chapter_title_bind_to_ticks " , self.toc_chapter_title_bind_to_ticks )
2021-02-04 16:43:52 +00:00
end
2021-01-29 00:02:07 +00:00
function ReaderToc : cleanUpTocTitle ( title , replace_empty )
title = title : gsub ( " \13 " , " " )
if replace_empty and title : match ( " ^%s*$ " ) then
title = " \xE2 \x80 \x93 " -- U+2013 En-Dash
end
return title
2012-05-27 11:47:22 +00:00
end
function ReaderToc : onSetDimensions ( dimen )
2014-03-13 13:52:43 +00:00
self.dimen = dimen
2012-05-27 11:47:22 +00:00
end
2014-10-15 12:47:13 +00:00
function ReaderToc : resetToc ( )
2014-03-13 13:52:43 +00:00
self.toc = nil
2020-09-27 20:25:16 +00:00
self.toc_depth = nil
self.ticks = nil
self.ticks_flattened = nil
2021-02-20 18:05:12 +00:00
self.ticks_flattened_filtered = nil
2014-10-14 13:33:13 +00:00
self.collapsed_toc = { }
2020-09-27 20:25:16 +00:00
self.collapse_depth = 2
2016-12-04 14:13:00 +00:00
self.expanded_nodes = { }
2014-10-15 12:47:13 +00:00
end
function ReaderToc : onUpdateToc ( )
self : resetToc ( )
2020-10-31 09:40:36 +00:00
self.ui : handleEvent ( Event : new ( " TocReset " ) )
2020-10-15 03:31:21 +00:00
--- @note: Let this propagate, plugins/statistics uses it to react to changes in document pagination
--return true
2013-01-09 08:53:32 +00:00
end
2014-04-04 15:02:29 +00:00
function ReaderToc : onPageUpdate ( pageno )
2020-08-21 12:33:08 +00:00
if UIManager.FULL_REFRESH_COUNT == - 1 or G_reader_settings : isTrue ( " refresh_on_chapter_boundaries " ) then
local flash_on_second = G_reader_settings : nilOrFalse ( " no_refresh_on_second_chapter_page " )
2020-08-23 01:46:05 +00:00
local paging_forward , paging_backward
if flash_on_second then
if self.pageno then
if pageno > self.pageno then
paging_forward = true
elseif pageno < self.pageno then
paging_backward = true
end
2020-08-21 12:33:08 +00:00
end
2020-08-23 01:46:05 +00:00
end
2020-09-27 20:25:16 +00:00
if paging_backward and self : isChapterEnd ( pageno ) then
2020-08-23 01:46:05 +00:00
UIManager : setDirty ( nil , " full " )
2020-09-27 20:25:16 +00:00
elseif self : isChapterStart ( pageno ) then
2020-08-23 01:46:05 +00:00
UIManager : setDirty ( nil , " full " )
2020-09-27 20:25:16 +00:00
elseif paging_forward and self : isChapterSecondPage ( pageno ) then
Enable HW dithering in a few key places (#4541)
* Enable HW dithering on supported devices (Clara HD, Forma; Oasis 2, PW4)
* FileManager and co. (where appropriate, i.e., when covers are shown)
* Book Status
* Reader, where appropriate:
* CRe: on pages whith image content (for over 7.5% of the screen area, should hopefully leave stuff like bullet points or small scene breaks alone).
* Other engines: on user-request (in the gear tab of the bottom menu), via the new "Dithering" knob (will only appear on supported devices).
* ScreenSaver
* ImageViewer
* Minimize repaints when flash_ui is enabled (by, almost everywhere, only repainting the flashing element, and not the toplevel window which hosts it).
(The first pass of this involved fixing a few Button instances whose show_parent was wrong, in particular, chevrons in the FM & TopMenu).
* Hunted down a few redundant repaints (unneeded setDirty("all") calls),
either by switching the widget to nil when only a refresh was needed, and not a repaint,
or by passing the appropritate widget to setDirty.
(Note to self: Enable *verbose* debugging to catch broken setDirty calls via its post guard).
There were also a few instances of 'em right behind a widget close.
* Don't repaint the underlying widget when initially showing TopMenu & ConfigDialog.
We unfortunately do need to do it when switching tabs, because of their variable heights.
* On Kobo, disabled the extra and completely useless full refresh before suspend/reboot/poweroff, as well as on resume. No more double refreshes!
* Fix another debug guard in Kobo sysfs_light
* Switch ImageWidget & ImageViewer mostly to "ui" updates, which will be better suited to image content pretty much everywhere, REAGL or not.
PS: (Almost :100: commits! :D)
2019-02-07 00:14:37 +00:00
UIManager : setDirty ( nil , " full " )
2018-05-29 22:28:47 +00:00
end
end
2020-08-23 01:46:05 +00:00
self.pageno = pageno
2014-04-04 15:02:29 +00:00
end
2017-10-05 19:49:59 +00:00
function ReaderToc : onPosUpdate ( pos , pageno )
2018-11-14 19:58:56 +00:00
if pageno then
self.pageno = pageno
end
2017-10-05 19:49:59 +00:00
end
2013-01-01 19:37:36 +00:00
function ReaderToc : fillToc ( )
2020-06-25 19:19:50 +00:00
if self.toc then return end
2018-06-13 22:46:52 +00:00
if self.ui . document : canHaveAlternativeToc ( ) then
2021-03-06 21:44:18 +00:00
if self.ui . doc_settings : isTrue ( " alternative_toc " ) then
2018-06-13 22:46:52 +00:00
-- (if the document has a cache, the previously built alternative
-- TOC was saved and has been reloaded, and this will be avoided)
if not self.ui . document : isTocAlternativeToc ( ) then
self : resetToc ( )
self.ui . document : buildAlternativeToc ( )
end
end
end
2014-03-13 13:52:43 +00:00
self.toc = self.ui . document : getToc ( )
2020-02-28 21:56:12 +00:00
self : validateAndFixToc ( )
end
function ReaderToc : validateAndFixToc ( )
-- Our code expects (rightfully) the TOC items to be ordered and to have
-- increasing page numbers, but we may occasionally not get that from the
-- engines (usually, because of bugs or duplicated IDs in the document).
local toc = self.toc
local first = 1
local last = # toc
-- For testing: shuffle a bit a valid TOC and make it randomely invalid
-- for i = first, last do
-- toc[i].page = toc[i].page + math.random(10) - 5
-- end
-- Do a cheap quick scan first
logger.dbg ( " validateAndFixToc(): quick scan " )
local has_bogus
local cur_page = 0
for i = first , last do
local page = toc [ i ] . page
if page < cur_page then
has_bogus = true
break
end
cur_page = page
end
if not has_bogus then -- no TOC items, or all are valid
logger.dbg ( " validateAndFixToc(): TOC is fine " )
return
end
logger.dbg ( " validateAndFixToc(): TOC needs fixing " )
-- Bad ordering previously noticed: try to fix the wrong items' page
-- by setting it to the previous or next good item page.
local nb_bogus = 0
local nb_fixed_pages = 0
-- We fix only one bogus item per loop, taking the option that
-- changes the least nb of items.
-- Sample cases, *N* being the page noticed as bogus:
-- 1 4 57 *6* 9 13 24 best to reset 57 to 4 (or 6, or 5)
-- 1 4 57 *6* 79 84 96 best to reset 6 to 57 (or 79 or 68)
-- 1 4 55 56 57 *6* 7 8 9 10 best to reset 55,56,57 to 4
-- 1 4 55 56 57 *6* 7 60 62 best to reset 6,7 to 57
-- (These cases are met in the following code with cur_page=57 and page=6)
cur_page = 0
for i = first , last do
local page = toc [ i ] . fixed_page or toc [ i ] . page
if page >= cur_page then
cur_page = page
else
-- Bogus page (or bogus previous page)
nb_bogus = nb_bogus + 1
-- See how many pages we'd need fixing on either side
local nb_prev = 0
2020-10-31 09:40:36 +00:00
local nb_prev_main = 0
2020-02-28 21:56:12 +00:00
for j = i - 1 , first , - 1 do
local ppage = toc [ j ] . fixed_page or toc [ j ] . page
if ppage <= page then
break
else
nb_prev = nb_prev + 1
2020-10-31 09:40:36 +00:00
if self.ui . document : getPageFlow ( ppage ) == 0 then
nb_prev_main = nb_prev_main + 1
end
2020-02-28 21:56:12 +00:00
end
end
2020-10-31 09:40:36 +00:00
local nb_next = 0
local nb_next_main = 0
for j = i , last do
2020-02-28 21:56:12 +00:00
local npage = toc [ j ] . fixed_page or toc [ j ] . page
if npage >= cur_page then
break
else
nb_next = nb_next + 1
2020-10-31 09:40:36 +00:00
if self.ui . document : getPageFlow ( npage ) == 0 then
nb_next_main = nb_next_main + 1
end
2020-02-28 21:56:12 +00:00
end
end
2020-10-31 09:20:02 +00:00
logger.dbg ( " BOGUS TOC: " , i , page , " < " , i - 1 , cur_page , " - " , nb_prev , nb_next )
2020-10-31 09:40:36 +00:00
-- Note: by comparing only the entries that belong to the main (linear) flow
-- we give priority to moving non-linear bogus entries
if nb_prev_main <= nb_next_main then -- less changes when fixing previous pages
2020-02-28 21:56:12 +00:00
local fixed_page
if i - nb_prev - 1 >= 1 then
fixed_page = toc [ i - nb_prev - 1 ] . fixed_page or toc [ i - nb_prev - 1 ] . page
else
fixed_page = 1
end
for j = i - 1 , i - nb_prev , - 1 do
toc [ j ] . fixed_page = fixed_page
logger.dbg ( " fix prev " , j , toc [ j ] . page , " => " , fixed_page )
end
else
local fixed_page = cur_page -- (might be better to use next one, but not safer)
for j = i , i + nb_next - 1 do
toc [ j ] . fixed_page = fixed_page
logger.dbg ( " fix next " , j , toc [ j ] . page , " => " , fixed_page )
end
end
cur_page = toc [ i ] . fixed_page or toc [ i ] . page
end
end
if nb_bogus > 0 then
for i = first , last do
if toc [ i ] . fixed_page and toc [ i ] . fixed_page ~= toc [ i ] . page then
toc [ i ] . orig_page = toc [ i ] . page -- keep the original one, for display only
toc [ i ] . page = toc [ i ] . fixed_page
nb_fixed_pages = nb_fixed_pages + 1
end
end
end
logger.info ( string.format ( " TOC had %d bogus page numbers: fixed %d items to keep them ordered. " , nb_bogus , nb_fixed_pages ) )
2013-01-01 19:37:36 +00:00
end
2012-05-27 13:24:33 +00:00
2021-02-20 18:05:12 +00:00
function ReaderToc : getTocIndexByPage ( pn_or_xp , skip_ignored_ticks )
2014-10-07 09:09:37 +00:00
self : fillToc ( )
2015-02-01 14:50:08 +00:00
if # self.toc == 0 then return end
2014-10-07 09:09:37 +00:00
local pageno = pn_or_xp
2014-03-13 13:52:43 +00:00
if type ( pn_or_xp ) == " string " then
2021-02-20 18:05:12 +00:00
return self : getAccurateTocIndexByXPointer ( pn_or_xp , skip_ignored_ticks )
2014-03-13 13:52:43 +00:00
end
2021-02-20 18:05:12 +00:00
local prev_index = 1
2014-03-13 13:52:43 +00:00
for _k , _v in ipairs ( self.toc ) do
2021-02-20 18:05:12 +00:00
if not skip_ignored_ticks or not self.toc_ticks_ignored_levels [ _v.depth ] then
if _v.page == pageno then
-- Return the first chapter seen on the current page
prev_index = _k
break
end
if _v.page > pageno then
-- Return last chapter seen on a previous page
break
end
prev_index = _k
2014-03-13 13:52:43 +00:00
end
2015-02-01 14:50:08 +00:00
end
2021-02-20 18:05:12 +00:00
return prev_index
2015-02-01 14:50:08 +00:00
end
2021-02-20 18:05:12 +00:00
function ReaderToc : getAccurateTocIndexByXPointer ( xptr , skip_ignored_ticks )
2020-06-17 21:51:02 +00:00
local pageno = self.ui . document : getPageFromXPointer ( xptr )
-- get toc entry(index) on for the current page
-- we don't get infinite loop, because the this call is not
-- with xpointer, but with page
2021-02-20 18:05:12 +00:00
local index = self : getTocIndexByPage ( pageno , skip_ignored_ticks )
2020-06-17 21:51:02 +00:00
if not index or not self.toc [ index ] then return end
local initial_comparison = self.ui . document : compareXPointers ( self.toc [ index ] . xpointer , xptr )
if initial_comparison and initial_comparison < 0 then
local i = index - 1
while self.toc [ i ] do
2021-02-20 18:05:12 +00:00
if not skip_ignored_ticks or not self.toc_ticks_ignored_levels [ self.toc [ i ] . depth ] then
local toc_xptr = self.toc [ i ] . xpointer
local cmp = self.ui . document : compareXPointers ( toc_xptr , xptr )
if cmp and cmp >= 0 then -- toc_xptr is before xptr(xptr >= toc_xptr)
return i
end
2020-06-17 21:51:02 +00:00
end
i = i - 1
end
else
2021-02-20 18:05:12 +00:00
local prev_index = index
2020-06-17 21:51:02 +00:00
local i = index + 1
while self.toc [ i ] do
2021-02-20 18:05:12 +00:00
if not skip_ignored_ticks or not self.toc_ticks_ignored_levels [ self.toc [ i ] . depth ] then
local toc_xptr = self.toc [ i ] . xpointer
local cmp = self.ui . document : compareXPointers ( toc_xptr , xptr )
if cmp and cmp < 0 then -- toc_xptr is after xptr(xptr < toc_xptr)
return prev_index
end
prev_index = i
2020-06-17 21:51:02 +00:00
end
i = i + 1
end
end
return index
end
2015-02-01 14:50:08 +00:00
function ReaderToc : getTocTitleByPage ( pn_or_xp )
2021-02-20 18:05:12 +00:00
local index = self : getTocIndexByPage ( pn_or_xp , self.toc_chapter_title_bind_to_ticks )
2015-02-01 14:50:08 +00:00
if index then
return self : cleanUpTocTitle ( self.toc [ index ] . title )
else
return " "
2014-03-13 13:52:43 +00:00
end
2012-05-27 13:24:33 +00:00
end
function ReaderToc : getTocTitleOfCurrentPage ( )
2015-02-01 13:52:46 +00:00
if self.pageno then
return self : getTocTitleByPage ( self.pageno )
end
2012-05-27 13:24:33 +00:00
end
2014-10-07 09:09:37 +00:00
function ReaderToc : getMaxDepth ( )
2020-09-27 20:25:16 +00:00
if self.toc_depth then return self.toc_depth end
-- Not cached yet, compute it
2014-10-07 09:09:37 +00:00
self : fillToc ( )
local max_depth = 0
for _ , v in ipairs ( self.toc ) do
if v.depth > max_depth then
max_depth = v.depth
2014-07-02 05:07:18 +00:00
end
end
2020-09-27 20:25:16 +00:00
self.toc_depth = max_depth
return self.toc_depth
2014-07-02 05:07:18 +00:00
end
2014-10-07 09:09:37 +00:00
--[[
2020-09-27 20:25:16 +00:00
The ToC ticks is a list of page numbers in ascending order of ToC nodes at a particular depth level .
A positive level returns nodes at that depth level ( top - level is 1 , depth always matches level . Higher values mean deeper nesting . )
A negative level does the same , but computes the depth level in reverse ( i.e . , - 1 is the most deeply nested one ) .
Omitting the level argument returns the full hierarchical table .
2014-10-07 09:09:37 +00:00
--]]
function ReaderToc : getTocTicks ( level )
2020-09-27 20:25:16 +00:00
-- Handle negative levels
if level and level < 0 then
level = self : getMaxDepth ( ) + level + 1
end
if level then
if self.ticks and self.ticks [ level ] then
return self.ticks [ level ]
end
else
if self.ticks then
return self.ticks
end
end
-- Build ToC ticks if not found
2014-10-07 09:09:37 +00:00
self : fillToc ( )
2020-09-27 20:25:16 +00:00
self.ticks = { }
2014-07-03 16:19:28 +00:00
if # self.toc > 0 then
2020-09-27 20:25:16 +00:00
-- Start by building a simple hierarchical ToC tick table
for _ , v in ipairs ( self.toc ) do
if not self.ticks [ v.depth ] then
self.ticks [ v.depth ] = { }
2014-07-03 16:19:28 +00:00
end
2020-09-27 20:25:16 +00:00
table.insert ( self.ticks [ v.depth ] , v.page )
end
-- Normally the ticks are already sorted, but in rare cases,
-- ToC nodes may be not in ascending order
for k , _ in ipairs ( self.ticks ) do
table.sort ( self.ticks [ k ] )
2014-07-03 16:19:28 +00:00
end
end
2020-09-27 20:25:16 +00:00
if level then
return self.ticks [ level ]
else
return self.ticks
2020-06-05 08:09:44 +00:00
end
2020-09-27 20:25:16 +00:00
end
--[[
Returns a flattened list of ToC ticks , without duplicates
] ]
2021-02-20 18:05:12 +00:00
function ReaderToc : getTocTicksFlattened ( for_chapter_navigation )
local wants_filtered_ticks = true
if not next ( self.toc_ticks_ignored_levels ) then
-- No ignored level: no need to keep an additional list of filtered ticks
wants_filtered_ticks = false
elseif for_chapter_navigation then
if not self.toc_chapter_navigation_bind_to_ticks then
wants_filtered_ticks = false
end
end
if wants_filtered_ticks then
if self.ticks_flattened_filtered then
return self.ticks_flattened_filtered
end
else
if self.ticks_flattened then
return self.ticks_flattened
end
end
2020-09-27 20:25:16 +00:00
-- It hasn't been cached yet, compute it.
local ticks = self : getTocTicks ( )
local ticks_flattened = { }
-- Keep track of what we add to avoid duplicates (c.f., https://stackoverflow.com/a/20067270)
local hash = { }
2021-02-04 16:43:52 +00:00
for depth , v in ipairs ( ticks ) do
2021-02-20 18:05:12 +00:00
if not wants_filtered_ticks or not self.toc_ticks_ignored_levels [ depth ] then
2021-02-04 16:43:52 +00:00
for _ , page in ipairs ( v ) do
if not hash [ page ] then
table.insert ( ticks_flattened , page )
hash [ page ] = true
end
2020-09-27 20:25:16 +00:00
end
end
2020-06-05 08:09:44 +00:00
end
2020-09-27 20:25:16 +00:00
-- And finally, sort it again
table.sort ( ticks_flattened )
2021-02-20 18:05:12 +00:00
-- Store it in the relevant slot
if wants_filtered_ticks then
self.ticks_flattened_filtered = ticks_flattened
else
self.ticks_flattened = ticks_flattened
end
return ticks_flattened
2020-06-05 08:09:44 +00:00
end
2020-09-27 20:25:16 +00:00
function ReaderToc : getNextChapter ( cur_pageno )
2021-02-20 18:05:12 +00:00
local ticks = self : getTocTicksFlattened ( true )
2014-10-07 09:09:37 +00:00
local next_chapter = nil
2020-09-27 20:25:16 +00:00
for _ , page in ipairs ( ticks ) do
if page > cur_pageno then
next_chapter = page
2014-10-07 09:09:37 +00:00
break
2014-07-15 10:18:24 +00:00
end
end
2014-10-07 09:09:37 +00:00
return next_chapter
2014-07-15 10:18:24 +00:00
end
2020-09-27 20:25:16 +00:00
function ReaderToc : getPreviousChapter ( cur_pageno )
2021-02-20 18:05:12 +00:00
local ticks = self : getTocTicksFlattened ( true )
2014-10-07 09:09:37 +00:00
local previous_chapter = nil
2020-09-27 20:25:16 +00:00
for _ , page in ipairs ( ticks ) do
if page >= cur_pageno then
2014-10-07 09:09:37 +00:00
break
end
2020-09-27 20:25:16 +00:00
previous_chapter = page
2014-07-15 10:18:24 +00:00
end
2014-10-07 09:09:37 +00:00
return previous_chapter
end
2014-07-15 10:18:24 +00:00
2020-09-27 20:25:16 +00:00
function ReaderToc : isChapterStart ( cur_pageno )
2021-02-20 18:05:12 +00:00
local ticks = self : getTocTicksFlattened ( true )
2020-08-21 12:33:08 +00:00
local _start = false
2020-09-27 20:25:16 +00:00
for _ , page in ipairs ( ticks ) do
if page == cur_pageno then
2020-08-21 12:33:08 +00:00
_start = true
break
end
end
return _start
end
2020-09-27 20:25:16 +00:00
function ReaderToc : isChapterSecondPage ( cur_pageno )
2021-02-20 18:05:12 +00:00
local ticks = self : getTocTicksFlattened ( true )
2020-08-21 12:33:08 +00:00
local _second = false
2020-09-27 20:25:16 +00:00
for _ , page in ipairs ( ticks ) do
if page + 1 == cur_pageno then
2020-08-21 12:33:08 +00:00
_second = true
2014-10-07 09:43:48 +00:00
break
end
end
2020-08-21 12:33:08 +00:00
return _second
2014-10-07 09:43:48 +00:00
end
2020-09-27 20:25:16 +00:00
function ReaderToc : isChapterEnd ( cur_pageno )
2021-02-20 18:05:12 +00:00
local ticks = self : getTocTicksFlattened ( true )
2020-08-21 12:33:08 +00:00
local _end = false
2020-09-27 20:25:16 +00:00
for _ , page in ipairs ( ticks ) do
if page - 1 == cur_pageno then
2014-10-07 09:43:48 +00:00
_end = true
break
end
end
return _end
end
2021-06-05 18:19:01 +00:00
function ReaderToc : getChapterPageCount ( pageno )
if self.ui . document : hasHiddenFlows ( ) then
-- Count pages until new chapter, starting by going backwards to the beginning of the current chapter if necessary
local page_count = 1
if not self : isChapterStart ( pageno ) then
local test_page = self.ui . document : getPrevPage ( pageno )
while test_page > 0 do
page_count = page_count + 1
if self : isChapterStart ( test_page ) then
break
end
test_page = self.ui . document : getPrevPage ( test_page )
end
end
-- Then forward
local test_page = self.ui . document : getNextPage ( pageno )
while test_page > 0 do
page_count = page_count + 1
if self : isChapterStart ( test_page ) then
return page_count - 1
end
test_page = self.ui . document : getNextPage ( test_page )
end
else
local next_chapter = self : getNextChapter ( pageno ) or self.ui . document : getPageCount ( ) + 1
local previous_chapter = self : isChapterStart ( pageno ) and pageno or self : getPreviousChapter ( pageno ) or 1
local page_count = next_chapter - previous_chapter
return page_count
end
end
2020-09-27 20:25:16 +00:00
function ReaderToc : getChapterPagesLeft ( pageno )
2020-10-31 09:40:36 +00:00
if self.ui . document : hasHiddenFlows ( ) then
-- Count pages until new chapter
local pages_left = 0
local test_page = self.ui . document : getNextPage ( pageno )
while test_page > 0 do
pages_left = pages_left + 1
if self : isChapterStart ( test_page ) then
return pages_left - 1
end
test_page = self.ui . document : getNextPage ( test_page )
end
else
local next_chapter = self : getNextChapter ( pageno )
if next_chapter then
next_chapter = next_chapter - pageno - 1
end
return next_chapter
2014-07-15 10:18:24 +00:00
end
2014-10-07 09:09:37 +00:00
end
2014-07-15 10:18:24 +00:00
2020-09-27 20:25:16 +00:00
function ReaderToc : getChapterPagesDone ( pageno )
if self : isChapterStart ( pageno ) then return 0 end
2020-10-31 09:40:36 +00:00
if self.ui . document : hasHiddenFlows ( ) then
-- Count pages until chapter start
local pages_done = 0
local test_page = self.ui . document : getPrevPage ( pageno )
while test_page > 0 do
pages_done = pages_done + 1
if self : isChapterStart ( test_page ) then
return pages_done
end
test_page = self.ui . document : getPrevPage ( test_page )
end
else
local previous_chapter = self : getPreviousChapter ( pageno )
if previous_chapter then
previous_chapter = pageno - previous_chapter
end
return previous_chapter
2014-07-15 10:18:24 +00:00
end
end
2014-10-14 13:33:13 +00:00
function ReaderToc : updateCurrentNode ( )
2015-02-01 13:52:46 +00:00
if # self.collapsed_toc > 0 and self.pageno then
2014-10-14 13:33:13 +00:00
for i , v in ipairs ( self.collapsed_toc ) do
2021-04-02 16:12:10 +00:00
if v.page >= self.pageno then
if v.page == self.pageno then
-- Use first TOC item on current page (which may have others)
self.collapsed_toc . current = i
else
-- Use previous TOC item (if any), which is on a previous page
self.collapsed_toc . current = i > 1 and i - 1 or 1
end
2015-02-01 14:50:08 +00:00
return
end
end
self.collapsed_toc . current = # self.collapsed_toc
end
end
2015-02-03 04:10:25 +00:00
function ReaderToc : expandParentNode ( index )
if index then
local nodes_to_expand = { }
local depth = self.toc [ index ] . depth
for i = index - 1 , 1 , - 1 do
if depth > self.toc [ i ] . depth then
depth = self.toc [ i ] . depth
table.insert ( nodes_to_expand , i )
2014-10-14 13:33:13 +00:00
end
2015-02-03 04:10:25 +00:00
if depth == 1 then break end
end
for i = # nodes_to_expand , 1 , - 1 do
self : expandToc ( nodes_to_expand [ i ] )
2014-10-14 13:33:13 +00:00
end
end
end
2012-05-27 11:47:22 +00:00
function ReaderToc : onShowToc ( )
2014-10-07 09:09:37 +00:00
self : fillToc ( )
2014-03-13 13:52:43 +00:00
-- build menu items
if # self.toc > 0 and not self.toc [ 1 ] . text then
2021-04-15 17:07:34 +00:00
for _ , v in ipairs ( self.toc ) do
2021-01-29 00:02:07 +00:00
v.text = self.toc_indent : rep ( v.depth - 1 ) .. self : cleanUpTocTitle ( v.title , true )
2014-03-13 13:52:43 +00:00
v.mandatory = v.page
2020-10-31 09:40:36 +00:00
if self.ui . document : hasHiddenFlows ( ) then
local flow = self.ui . document : getPageFlow ( v.page )
if v.orig_page then -- bogus page fixed: show original page number
-- This is an ugly piece of code, which can result in an ugly TOC,
-- but it shouldn't be needed very often, only when bogus page numbers
-- are fixed, and then showing everything gets complicated
local orig_flow = self.ui . document : getPageFlow ( v.orig_page )
if flow == 0 and orig_flow == flow then
v.mandatory = T ( " (%1) %2 " , self.ui . document : getPageNumberInFlow ( v.orig_page ) , self.ui . document : getPageNumberInFlow ( v.page ) )
elseif flow == 0 and orig_flow ~= flow then
v.mandatory = T ( " [%1]%2 " , self.ui . document : getPageNumberInFlow ( v.orig_page ) , self.ui . document : getPageFlow ( v.orig_page ) )
elseif flow > 0 and orig_flow == flow then
v.mandatory = T ( " [(%1) %2]%3 " , self.ui . document : getPageNumberInFlow ( v.orig_page ) ,
self.ui . document : getPageNumberInFlow ( v.page ) , self.ui . document : getPageFlow ( v.page ) )
else
v.mandatory = T ( " ([%1]%2) [%3]%4 " , self.ui . document : getPageNumberInFlow ( v.orig_page ) , self.ui . document : getPageFlow ( v.orig_page ) ,
self.ui . document : getPageNumberInFlow ( v.page ) , self.ui . document : getPageFlow ( v.page ) )
end
else
-- Plain numbers for the linear entries,
-- for non-linear entries we use the same syntax as in the Go to dialog
if flow == 0 then
v.mandatory = self.ui . document : getPageNumberInFlow ( v.page )
else
v.mandatory = T ( " [%1]%2 " , self.ui . document : getPageNumberInFlow ( v.page ) , self.ui . document : getPageFlow ( v.page ) )
end
end
elseif v.orig_page then -- bogus page fixed: show original page number
2020-02-28 21:56:12 +00:00
v.mandatory = T ( " (%1) %2 " , v.orig_page , v.page )
end
2020-03-26 13:04:59 +00:00
if self.ui . pagemap and self.ui . pagemap : wantsPageLabels ( ) then
v.mandatory = self.ui . pagemap : getXPointerPageLabel ( v.xpointer )
end
2014-03-13 13:52:43 +00:00
end
end
2014-10-14 13:33:13 +00:00
2021-02-04 16:43:52 +00:00
local items_per_page = G_reader_settings : readSetting ( " toc_items_per_page " ) or self.toc_items_per_page_default
local items_font_size = G_reader_settings : readSetting ( " toc_items_font_size " ) or Menu.getItemFontSize ( items_per_page )
2021-05-12 23:55:35 +00:00
local items_with_dots = G_reader_settings : nilOrTrue ( " toc_items_with_dots " )
2020-12-19 11:18:30 +00:00
-- Estimate expand/collapse icon size
2021-04-15 17:07:34 +00:00
-- *2/5 to acount for Menu top title and bottom icons, and add some space between consecutive icons
2020-12-19 11:18:30 +00:00
local icon_size = math.floor ( Screen : getHeight ( ) / items_per_page * 2 / 5 )
local button_width = icon_size * 2
2014-10-14 13:33:13 +00:00
self.expand_button = Button : new {
2020-12-19 11:18:30 +00:00
icon = " control.expand " ,
2019-12-06 21:55:39 +00:00
icon_rotation_angle = BD.mirroredUILayout ( ) and 180 or 0 ,
2020-12-19 11:18:30 +00:00
width = button_width ,
icon_width = icon_size ,
icon_height = icon_size ,
2014-10-14 13:33:13 +00:00
bordersize = 0 ,
show_parent = self ,
}
self.collapse_button = Button : new {
2020-12-19 11:18:30 +00:00
icon = " control.collapse " ,
width = button_width ,
icon_width = icon_size ,
icon_height = icon_size ,
2014-10-14 13:33:13 +00:00
bordersize = 0 ,
show_parent = self ,
}
2020-12-19 11:18:30 +00:00
-- update collapsible state
2014-10-14 13:33:13 +00:00
if # self.toc > 0 and # self.collapsed_toc == 0 then
local depth = 0
for i = # self.toc , 1 , - 1 do
local v = self.toc [ i ]
-- node v has child node(s)
if v.depth < depth then
v.state = self.expand_button : new {
callback = function ( ) self : expandToc ( i ) end ,
indent = self.toc_indent : rep ( v.depth - 1 ) ,
}
end
if v.depth < self.collapse_depth then
table.insert ( self.collapsed_toc , 1 , v )
2014-04-04 15:02:29 +00:00
end
2014-10-14 13:33:13 +00:00
depth = v.depth
2014-04-04 15:02:29 +00:00
end
end
2021-04-19 00:21:58 +00:00
local can_collapse = self : getMaxDepth ( ) > 1
2014-03-13 13:52:43 +00:00
2021-04-15 17:07:34 +00:00
-- NOTE: If the ToC actually has multiple depth levels, we request smaller padding between items,
-- because we inflate the state Button's width on the left, mainly to give it a larger tap zone.
-- This yields *slightly* better alignment between state & mandatory (in terms of effective margins).
2014-10-14 13:33:13 +00:00
local button_size = self.expand_button : getSize ( )
2014-03-13 13:52:43 +00:00
local toc_menu = Menu : new {
title = _ ( " Table of Contents " ) ,
2014-10-14 13:33:13 +00:00
item_table = self.collapsed_toc ,
2021-04-15 17:07:34 +00:00
state_size = can_collapse and button_size or nil ,
2014-03-13 13:52:43 +00:00
ui = self.ui ,
2014-06-10 13:32:49 +00:00
is_borderless = true ,
2015-02-01 13:36:22 +00:00
is_popout = false ,
2014-04-04 15:37:50 +00:00
width = Screen : getWidth ( ) ,
height = Screen : getHeight ( ) ,
2017-04-29 08:38:09 +00:00
cface = Font : getFace ( " x_smallinfofont " ) ,
2018-01-13 22:38:53 +00:00
single_line = true ,
2019-07-19 19:43:05 +00:00
align_baselines = true ,
2021-05-12 23:55:35 +00:00
with_dots = items_with_dots ,
2021-02-04 16:43:52 +00:00
items_per_page = items_per_page ,
items_font_size = items_font_size ,
2021-04-15 17:07:34 +00:00
items_padding = can_collapse and math.floor ( Size.padding . fullscreen / 2 ) or nil , -- c.f., note above. Menu's default is twice that.
2021-05-12 23:55:35 +00:00
line_color = Blitbuffer.COLOR_WHITE ,
2014-06-10 13:13:21 +00:00
on_close_ges = {
GestureRange : new {
ges = " two_finger_swipe " ,
range = Geom : new {
x = 0 , y = 0 ,
w = Screen : getWidth ( ) ,
h = Screen : getHeight ( ) ,
} ,
2019-12-06 21:55:39 +00:00
direction = BD.flipDirectionIfMirroredUILayout ( " west " )
2014-06-10 13:13:21 +00:00
}
}
2014-03-13 13:52:43 +00:00
}
2014-04-04 15:37:50 +00:00
local menu_container = CenterContainer : new {
dimen = Screen : getSize ( ) ,
2018-03-17 22:02:32 +00:00
covers_fullscreen = true , -- hint for UIManager:_repaint()
2014-04-04 15:37:50 +00:00
toc_menu ,
}
2014-03-13 13:52:43 +00:00
2014-10-21 14:18:07 +00:00
function toc_menu : onMenuSelect ( item , pos )
-- if toc item has expand/collapse state and tap select on the left side
-- the state switch action is triggered, otherwise goto the linked page
2019-12-06 21:55:39 +00:00
local do_toggle_state = false
if item.state and pos and pos.x then
if BD.mirroredUILayout ( ) then
do_toggle_state = pos.x > 0.7
else
do_toggle_state = pos.x < 0.3
end
end
if do_toggle_state then
2014-10-21 14:18:07 +00:00
item.state . callback ( )
else
toc_menu : close_callback ( )
2018-01-31 12:18:37 +00:00
self.ui . link : addCurrentLocationToStack ( )
2021-01-29 00:02:05 +00:00
if item.xpointer then
self.ui : handleEvent ( Event : new ( " GotoXPointer " , item.xpointer , item.xpointer ) )
else
self.ui : handleEvent ( Event : new ( " GotoPage " , item.page ) )
end
2014-10-21 14:18:07 +00:00
end
2014-03-13 13:52:43 +00:00
end
2020-09-30 17:56:56 +00:00
function toc_menu : onMenuHold ( item )
-- Trim toc_indent
local trimmed_text = util.ltrim ( item.text )
2021-04-15 17:07:34 +00:00
-- Match the items' width
2020-09-30 17:56:56 +00:00
local infomessage = InfoMessage : new {
2021-04-15 17:07:34 +00:00
width = Screen : getWidth ( ) - ( Size.padding . fullscreen * ( can_collapse and 4 or 3 ) ) ,
alignment = " center " ,
2020-09-30 17:56:56 +00:00
show_icon = false ,
text = trimmed_text ,
2021-06-04 22:55:20 +00:00
face = Font : getFace ( " infofont " , self.items_font_size ) ,
2020-09-30 17:56:56 +00:00
}
UIManager : show ( infomessage )
return true
end
2014-03-13 13:52:43 +00:00
toc_menu.close_callback = function ( )
2014-05-31 12:43:44 +00:00
UIManager : close ( menu_container )
2014-03-13 13:52:43 +00:00
end
2014-05-31 12:43:44 +00:00
toc_menu.show_parent = menu_container
2014-10-14 13:33:13 +00:00
self.toc_menu = toc_menu
2015-02-03 07:34:35 +00:00
self : updateCurrentNode ( )
2015-02-01 14:50:08 +00:00
-- auto expand the parent node of current page
2021-02-23 00:49:59 +00:00
local idx = self : getTocIndexByPage ( self.pageno )
if idx then
self : expandParentNode ( idx )
-- Also do it for other toc items on current page
idx = idx + 1
while self.toc [ idx ] and self.toc [ idx ] . page == self.pageno do
self : expandParentNode ( idx )
idx = idx + 1
end
end
2015-02-03 07:34:35 +00:00
-- auto goto page of the current toc entry
2017-02-01 14:24:21 +00:00
self.toc_menu : switchItemTable ( nil , self.collapsed_toc , self.collapsed_toc . current or - 1 )
2015-02-01 14:50:08 +00:00
2014-05-31 12:43:44 +00:00
UIManager : show ( menu_container )
2014-05-30 14:11:46 +00:00
2014-03-13 13:52:43 +00:00
return true
2012-05-27 11:47:22 +00:00
end
2014-10-14 13:33:13 +00:00
-- expand TOC node of index in raw toc table
function ReaderToc : expandToc ( index )
2015-02-01 14:50:08 +00:00
for k , v in ipairs ( self.expanded_nodes ) do
if v == index then return end
end
2014-10-14 13:33:13 +00:00
table.insert ( self.expanded_nodes , index )
local cur_node = self.toc [ index ]
local cur_depth = cur_node.depth
local collapsed_index = nil
for i , v in ipairs ( self.collapsed_toc ) do
if v.page == cur_node.page and v.depth == cur_depth
and v.text == cur_node.text then
collapsed_index = i
break
end
end
2015-02-03 04:10:25 +00:00
-- either the toc entry of index has no child nodes
-- or it's parent nodes are not expanded yet
if not collapsed_index then return end
2014-10-14 13:33:13 +00:00
for i = index + 1 , # self.toc do
local v = self.toc [ i ]
if v.depth == cur_depth + 1 then
collapsed_index = collapsed_index + 1
table.insert ( self.collapsed_toc , collapsed_index , v )
elseif v.depth <= cur_depth then
break
end
end
-- change state of current node to expanded
cur_node.state = self.collapse_button : new {
callback = function ( ) self : collapseToc ( index ) end ,
indent = self.toc_indent : rep ( cur_depth - 1 ) ,
}
self : updateCurrentNode ( )
2017-02-01 14:24:21 +00:00
self.toc_menu : switchItemTable ( nil , self.collapsed_toc , - 1 )
2014-10-14 13:33:13 +00:00
end
-- collapse TOC node of index in raw toc table
function ReaderToc : collapseToc ( index )
2015-02-01 14:50:08 +00:00
for k , v in ipairs ( self.expanded_nodes ) do
if v == index then
table.remove ( self.expanded_nodes , k )
break
end
end
2014-10-14 13:33:13 +00:00
local cur_node = self.toc [ index ]
local cur_depth = cur_node.depth
local i = 1
local is_child_node = false
while i <= # self.collapsed_toc do
local v = self.collapsed_toc [ i ]
if v.page > cur_node.page and v.depth <= cur_depth then
is_child_node = false
end
if is_child_node then
table.remove ( self.collapsed_toc , i )
else
i = i + 1
end
if v.page == cur_node.page and v.depth == cur_depth
and v.text == cur_node.text then
is_child_node = true
end
end
-- change state of current node to collapsed
cur_node.state = self.expand_button : new {
callback = function ( ) self : expandToc ( index ) end ,
indent = self.toc_indent : rep ( cur_depth - 1 ) ,
}
self : updateCurrentNode ( )
2017-02-01 14:24:21 +00:00
self.toc_menu : switchItemTable ( nil , self.collapsed_toc , - 1 )
2014-10-14 13:33:13 +00:00
end
2017-03-04 13:46:38 +00:00
function ReaderToc : addToMainMenu ( menu_items )
2014-03-13 13:52:43 +00:00
-- insert table to main reader menu
2017-03-04 13:46:38 +00:00
menu_items.table_of_contents = {
2018-06-13 22:46:52 +00:00
text_func = function ( )
return self.ui . document : isTocAlternativeToc ( ) and self.alt_toc_menu_title or self.toc_menu_title
end ,
2014-03-13 13:52:43 +00:00
callback = function ( )
self : onShowToc ( )
end ,
2017-02-28 21:46:32 +00:00
}
2021-02-04 16:43:52 +00:00
-- ToC (and other navigation) settings
menu_items.navi_settings = {
text = _ ( " Settings " ) ,
}
-- Alternative ToC (only available with CRE documents)
2018-06-13 22:46:52 +00:00
if self.ui . document : canHaveAlternativeToc ( ) then
2021-02-04 16:43:52 +00:00
menu_items.toc_alt_toc = {
text = _ ( " Alternative table of contents " ) ,
help_text = _ ( [ [
An alternative table of contents can be built from document headings < H1 > to < H6 > .
If the document contains no headings , or all are ignored , the alternative ToC will be built from document fragments and will point to the start of each individual HTML file in the EPUB .
Some of the headings can be ignored , and hints can be set to other non - heading elements in a user style tweak , so they can be used as ToC items .
See Style tweaks → Miscellaneous → Alternative ToC hints . ] ] ) ,
checked_func = function ( )
return self.ui . document : isTocAlternativeToc ( )
end ,
callback = function ( touchmenu_instance )
if self.ui . document : isTocAlternativeToc ( ) then
UIManager : show ( ConfirmBox : new {
text = _ ( " The table of contents for this book is currently an alternative one built from the document headings. \n Do you want to get back the original table of contents? (The book will be reloaded.) " ) ,
ok_callback = function ( )
touchmenu_instance : closeMenu ( )
self.ui . doc_settings : delSetting ( " alternative_toc " )
self.ui . document : invalidateCacheFile ( )
self.toc_ticks_ignored_levels = { } -- reset this
-- Allow for ConfirmBox to be closed before showing
-- "Opening file" InfoMessage
UIManager : scheduleIn ( 0.5 , function ( )
self.ui : reloadDocument ( )
end )
end ,
} )
else
UIManager : show ( ConfirmBox : new {
text = _ ( " Do you want to use an alternative table of contents built from the document headings? " ) ,
ok_callback = function ( )
touchmenu_instance : closeMenu ( )
self : resetToc ( )
self.toc_ticks_ignored_levels = { } -- reset this
self.ui . document : buildAlternativeToc ( )
2021-03-06 21:44:18 +00:00
self.ui . doc_settings : makeTrue ( " alternative_toc " )
2021-02-04 16:43:52 +00:00
self : onShowToc ( )
self.view . footer : setTocMarkers ( true )
self.view . footer : onUpdateFooter ( )
self.ui : handleEvent ( Event : new ( " UpdateTopStatusBarMarkers " ) )
end ,
} )
end
end ,
}
end
-- Allow to have getTocTicksFlattened() get rid of all items at some depths, which
-- might be useful to have the footer and SkimTo progress bar less crowded.
-- This also affects the footer current chapter title, but leave the ToC itself unchanged.
local genTocLevelIgnoreMenuItem = function ( level )
2021-03-23 13:40:30 +00:00
local ticks = self : getTocTicks ( )
if not ticks [ level ] then
2021-02-04 16:43:52 +00:00
return
end
return {
text_func = function ( )
2021-07-26 07:41:04 +00:00
return T ( N_ ( " 1 entry at ToC depth %2 " , " %1 entries at ToC depth %2 " , # ticks [ level ] ) , # ticks [ level ] , level )
2021-02-04 16:43:52 +00:00
end ,
checked_func = function ( )
return not self.toc_ticks_ignored_levels [ level ]
end ,
callback = function ( )
2021-02-20 18:05:12 +00:00
self.toc_ticks_ignored_levels [ level ] = not self.toc_ticks_ignored_levels [ level ] or nil
2021-02-04 16:43:52 +00:00
self : onUpdateToc ( )
self.view . footer : onUpdateFooter ( self.view . footer_visible )
self.ui : handleEvent ( Event : new ( " UpdateTopStatusBarMarkers " ) )
end ,
}
end
menu_items.toc_ticks_level_ignore = {
text_func = function ( )
local nb_ticks = 0
2021-03-23 13:40:30 +00:00
local ticks = self : getTocTicks ( )
for level = 1 , # ticks do
if not self.toc_ticks_ignored_levels [ level ] then
nb_ticks = nb_ticks + # ticks [ level ]
2021-02-04 16:43:52 +00:00
end
end
2021-07-26 07:41:04 +00:00
return T ( N_ ( " Progress bars: 1 tick " , " Progress bars: %1 ticks " , nb_ticks ) , nb_ticks )
2021-02-04 16:43:52 +00:00
end ,
help_text = _ ( [[The progress bars in the footer and the skim dialog can become cramped when the table of contents is complex. This allows you to restrict the number of tick marks.]] ) ,
enabled_func = function ( )
2021-03-23 13:40:30 +00:00
local ticks = self : getTocTicks ( )
return # ticks > 0
2021-02-04 16:43:52 +00:00
end ,
sub_item_table_func = function ( )
local toc_ticks_levels = { }
local level = 1
while true do
local item = genTocLevelIgnoreMenuItem ( level )
if item then
table.insert ( toc_ticks_levels , item )
level = level + 1
else
break
end
2018-06-13 22:46:52 +00:00
end
2021-03-20 18:27:07 +00:00
if # toc_ticks_levels > 0 then
toc_ticks_levels [ # toc_ticks_levels ] . separator = true
end
2021-02-20 18:05:12 +00:00
table.insert ( toc_ticks_levels , {
text = _ ( " Bind chapter navigation to ticks " ) ,
help_text = _ ( [ [ Entries from ToC levels that are ignored in the progress bars will still be used for chapter navigation and ' page/time left until next chapter ' in the footer .
2021-02-28 09:15:10 +00:00
Enabling this option will restrict chapter navigation to progress bar ticks . ] ] ) ,
2021-02-20 18:05:12 +00:00
enabled_func = function ( )
return next ( self.toc_ticks_ignored_levels ) ~= nil
end ,
checked_func = function ( )
return self.toc_chapter_navigation_bind_to_ticks
end ,
callback = function ( )
self.toc_chapter_navigation_bind_to_ticks = not self.toc_chapter_navigation_bind_to_ticks
self : onUpdateToc ( )
self.view . footer : onUpdateFooter ( self.view . footer_visible )
end ,
} )
table.insert ( toc_ticks_levels , {
text = _ ( " Chapter titles from ticks only " ) ,
help_text = _ ( [ [ Entries from ToC levels that are ignored in the progress bars will still be used for displaying the title of the current chapter in the footer and in bookmarks .
Enabling this option will restrict display to the chapter titles of progress bar ticks . ] ] ) ,
enabled_func = function ( )
return next ( self.toc_ticks_ignored_levels ) ~= nil
end ,
checked_func = function ( )
return self.toc_chapter_title_bind_to_ticks
end ,
callback = function ( )
self.toc_chapter_title_bind_to_ticks = not self.toc_chapter_title_bind_to_ticks
self.view . footer : onUpdateFooter ( self.view . footer_visible )
end ,
} )
2021-02-04 16:43:52 +00:00
return toc_ticks_levels
end ,
}
menu_items.toc_items_per_page = {
text = _ ( " ToC entries per page " ) ,
keep_menu_open = true ,
callback = function ( )
local SpinWidget = require ( " ui/widget/spinwidget " )
local curr_perpage = G_reader_settings : readSetting ( " toc_items_per_page " ) or self.toc_items_per_page_default
local items = SpinWidget : new {
width = math.floor ( Screen : getWidth ( ) * 0.6 ) ,
value = curr_perpage ,
value_min = 6 ,
value_max = 24 ,
default_value = self.toc_items_per_page_default ,
title_text = _ ( " ToC entries per page " ) ,
callback = function ( spin )
G_reader_settings : saveSetting ( " toc_items_per_page " , spin.value )
-- We need to reset the TOC so cached expand/collapsed icons
-- instances (as item.state), which were sized for a previous
-- value or items_per_page, are forgotten.
self : resetToc ( )
end
}
UIManager : show ( items )
2018-06-13 22:46:52 +00:00
end
2021-02-04 16:43:52 +00:00
}
menu_items.toc_items_font_size = {
text = _ ( " ToC entry font size " ) ,
keep_menu_open = true ,
callback = function ( )
local SpinWidget = require ( " ui/widget/spinwidget " )
local curr_perpage = G_reader_settings : readSetting ( " toc_items_per_page " ) or self.toc_items_per_page_default
local default_font_size = Menu.getItemFontSize ( curr_perpage )
local curr_font_size = G_reader_settings : readSetting ( " toc_items_font_size " ) or default_font_size
local items_font = SpinWidget : new {
width = math.floor ( Screen : getWidth ( ) * 0.6 ) ,
value = curr_font_size ,
value_min = 10 ,
value_max = 72 ,
default_value = default_font_size ,
title_text = _ ( " ToC entry font size " ) ,
callback = function ( spin )
G_reader_settings : saveSetting ( " toc_items_font_size " , spin.value )
end
}
UIManager : show ( items_font )
end ,
}
2021-05-12 23:55:35 +00:00
menu_items.toc_items_with_dots = {
text = _ ( " With dots " ) ,
2021-04-16 19:59:01 +00:00
keep_menu_open = true ,
checked_func = function ( )
2021-05-12 23:55:35 +00:00
return G_reader_settings : nilOrTrue ( " toc_items_with_dots " )
2021-04-16 19:59:01 +00:00
end ,
callback = function ( )
2021-05-12 23:55:35 +00:00
G_reader_settings : flipNilOrTrue ( " toc_items_with_dots " )
2021-04-16 19:59:01 +00:00
end
}
2012-12-31 00:13:46 +00:00
end
2013-10-18 20:38:07 +00:00
return ReaderToc