ReaderToc: add option to show chapter lengths (#11546)

reviewable/pr11578/r1
poire-z 1 month ago committed by GitHub
parent c8c4e0301a
commit 67cd647d1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -104,6 +104,7 @@ end
function ReaderToc:resetToc()
self.toc = nil
self.toc_menu_items_built = false
self.toc_depth = nil
self.ticks = nil
self.ticks_flattened = nil
@ -314,6 +315,37 @@ function ReaderToc:validateAndFixToc()
self.toc_depth = max_depth
end
function ReaderToc:completeTocWithChapterLengths()
local toc = self.toc
local first = 1
local last = #toc
if last == 0 then
return
end
local prev_item_by_level = {}
for i = first, last do
local item = toc[i]
local page = item.page
local depth = item.depth
for j=#prev_item_by_level, depth, -1 do
local prev_item = prev_item_by_level[j]
if prev_item then
prev_item.chapter_length = page - prev_item.page
end
prev_item_by_level[j] = nil
end
prev_item_by_level[depth] = item
end
-- Set the length of the last ones
local page = self.ui.document:getPageCount()
for j=#prev_item_by_level, 0, -1 do
local prev_item = prev_item_by_level[j]
if prev_item then
prev_item.chapter_length = page - prev_item.page
end
end
end
function ReaderToc:getTocIndexByPage(pn_or_xp, skip_ignored_ticks)
self:fillToc()
if #self.toc == 0 then return end
@ -661,11 +693,16 @@ function ReaderToc:onShowToc()
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)
local items_show_chapter_length = G_reader_settings:isTrue("toc_items_show_chapter_length")
local items_with_dots = G_reader_settings:nilOrTrue("toc_items_with_dots")
self:fillToc()
-- build menu items
if #self.toc > 0 and not self.toc[1].text then
if #self.toc > 0 and not self.toc_menu_items_built then
self.toc_menu_items_built = true
if items_show_chapter_length then
self:completeTocWithChapterLengths()
end
-- Have the width of 4 spaces be the unit of indentation
local tmp = TextWidget:new{
text = " ",
@ -679,6 +716,11 @@ function ReaderToc:onShowToc()
v.index = k
v.indent = toc_indent * (v.depth-1)
v.text = self:cleanUpTocTitle(v.title, true)
if items_show_chapter_length then
v.post_text = T("(%1)", v.chapter_length)
else
v.post_text = nil
end
v.bidi_wrap_func = BD.auto
v.mandatory = v.page
if has_hidden_flows then
@ -1147,6 +1189,17 @@ Enabling this option will restrict display to the chapter titles of progress bar
UIManager:show(items_font)
end,
}
menu_items.toc_items_show_chapter_length = {
text = _("Show chapter length"),
keep_menu_open = true,
checked_func = function()
return not G_reader_settings:nilOrFalse("toc_items_show_chapter_length")
end,
callback = function()
G_reader_settings:flipNilOrFalse("toc_items_show_chapter_length")
self.toc_menu_items_built = false
end
}
menu_items.toc_items_with_dots = {
text = _("With dots"),
keep_menu_open = true,

@ -35,6 +35,7 @@ local order = {
"----------------------------",
"toc_items_per_page",
"toc_items_font_size",
"toc_items_show_chapter_length",
"toc_items_with_dots",
"----------------------------",
"toc_alt_toc",

@ -184,6 +184,12 @@ function MenuItem:init()
self.face = Font:getFace(self.font, self.font_size)
-- Font for "mandatory" on the right
self.info_face = Font:getFace(self.infont, self.infont_size)
-- Font for post_text if any: for now, this is only used with TOC, showing
-- the chapter length: if feels best to use the face of the main text, but
-- with the size of the mandatory font (which shows some number too).
if self.post_text then
self.post_text_face = Font:getFace(self.font, self.infont_size)
end
-- "mandatory" is the text on the right: file size, page number...
-- Padding before mandatory
@ -219,10 +225,23 @@ function MenuItem:init()
text = self.bidi_wrap_func(text)
end
-- Note: support for post_text is currently implemented only when single_line=true
local post_text_widget
local post_text_left_padding = Size.padding.large
local post_text_right_padding = self.with_dots and 0 or Size.padding.large
local dots_widget
local dots_left_padding = Size.padding.small
local dots_right_padding = Size.padding.small
if self.single_line then -- items only in single line
if self.post_text then
post_text_widget = TextWidget:new{
text = self.post_text,
face = self.post_text_face,
bold = self.bold,
fgcolor = self.dim and Blitbuffer.COLOR_DARK_GRAY or nil,
}
available_width = available_width - post_text_widget:getWidth() - post_text_left_padding - post_text_right_padding
end
-- No font size change: text will be truncated if it overflows
item_name = TextWidget:new{
text = text,
@ -271,6 +290,9 @@ function MenuItem:init()
if dots_widget then
dots_widget.forced_height = self.dimen.h
end
if post_text_widget then
post_text_widget.forced_height = self.dimen.h
end
-- And adjust their baselines for proper centering and alignment
-- (We made sure the font sizes wouldn't exceed self.dimen.h, so we
-- get only non-negative pad_top here, and we're moving them down.)
@ -289,6 +311,9 @@ function MenuItem:init()
if dots_widget then
dots_widget.forced_baseline = mdtr_baseline
end
if post_text_widget then
post_text_widget.forced_baseline = mdtr_baseline
end
end
elseif self.multilines_show_more_text then
@ -374,6 +399,8 @@ function MenuItem:init()
width = state_width,
},
item_name,
post_text_widget and HorizontalSpan:new{ width = post_text_left_padding },
post_text_widget,
}
}
@ -1083,6 +1110,7 @@ function Menu:updateItems(select_number)
state_w = self.state_w or 0,
text = Menu.getMenuText(self.item_table[i]),
bidi_wrap_func = self.item_table[i].bidi_wrap_func,
post_text = self.item_table[i].post_text,
mandatory = self.item_table[i].mandatory,
mandatory_func = self.item_table[i].mandatory_func,
mandatory_dim = self.item_table[i].mandatory_dim or self.item_table[i].dim,

Loading…
Cancel
Save