ReaderToc: option to show a dotted line (#7669)

A dotted line joining the ToC entry text to the
page number may make it easier to use.
(This replaces the menu item separator from d879062e.)
Also fix baselines aligment, which could be a bit off.
reviewable/pr7673/r1
poire-z 3 years ago committed by GitHub
parent a20cac6904
commit f0ecbeb1d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -212,6 +212,7 @@ function ReaderPageMap:onShowPageList()
-- We use the per-page and font-size settings set for the ToC -- We use the per-page and font-size settings set for the ToC
local items_per_page = G_reader_settings:readSetting("toc_items_per_page") or 14 local items_per_page = G_reader_settings:readSetting("toc_items_per_page") or 14
local items_font_size = G_reader_settings:readSetting("toc_items_font_size") or Menu.getItemFontSize(items_per_page) local items_font_size = G_reader_settings:readSetting("toc_items_font_size") or Menu.getItemFontSize(items_per_page)
local items_with_dots = G_reader_settings:nilOrTrue("toc_items_with_dots")
local pl_menu = Menu:new{ local pl_menu = Menu:new{
title = _("Reference page numbers list"), title = _("Reference page numbers list"),
@ -225,6 +226,8 @@ function ReaderPageMap:onShowPageList()
items_font_size = items_font_size, items_font_size = items_font_size,
line_color = require("ffi/blitbuffer").COLOR_WHITE, line_color = require("ffi/blitbuffer").COLOR_WHITE,
single_line = true, single_line = true,
align_baselines = true,
with_dots = items_with_dots,
on_close_ges = { on_close_ges = {
GestureRange:new{ GestureRange:new{
ges = "two_finger_swipe", ges = "two_finger_swipe",

@ -643,7 +643,7 @@ function ReaderToc:onShowToc()
local items_per_page = G_reader_settings:readSetting("toc_items_per_page") or self.toc_items_per_page_default 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_font_size = G_reader_settings:readSetting("toc_items_font_size") or Menu.getItemFontSize(items_per_page)
local items_show_separator = G_reader_settings:isTrue("toc_items_show_separator") local items_with_dots = G_reader_settings:nilOrTrue("toc_items_with_dots")
-- Estimate expand/collapse icon size -- Estimate expand/collapse icon size
-- *2/5 to acount for Menu top title and bottom icons, and add some space between consecutive icons -- *2/5 to acount for Menu top title and bottom icons, and add some space between consecutive icons
local icon_size = math.floor(Screen:getHeight() / items_per_page * 2/5) local icon_size = math.floor(Screen:getHeight() / items_per_page * 2/5)
@ -703,10 +703,11 @@ function ReaderToc:onShowToc()
cface = Font:getFace("x_smallinfofont"), cface = Font:getFace("x_smallinfofont"),
single_line = true, single_line = true,
align_baselines = true, align_baselines = true,
with_dots = items_with_dots,
items_per_page = items_per_page, items_per_page = items_per_page,
items_font_size = items_font_size, items_font_size = items_font_size,
items_padding = can_collapse and math.floor(Size.padding.fullscreen / 2) or nil, -- c.f., note above. Menu's default is twice that. items_padding = can_collapse and math.floor(Size.padding.fullscreen / 2) or nil, -- c.f., note above. Menu's default is twice that.
line_color = items_show_separator and Blitbuffer.COLOR_DARK_GRAY or Blitbuffer.COLOR_WHITE, line_color = Blitbuffer.COLOR_WHITE,
on_close_ges = { on_close_ges = {
GestureRange:new{ GestureRange:new{
ges = "two_finger_swipe", ges = "two_finger_swipe",
@ -1062,14 +1063,14 @@ Enabling this option will restrict display to the chapter titles of progress bar
UIManager:show(items_font) UIManager:show(items_font)
end, end,
} }
menu_items.toc_items_show_separator = { menu_items.toc_items_with_dots = {
text = _("Add a separator between ToC entries"), text = _("With dots"),
keep_menu_open = true, keep_menu_open = true,
checked_func = function() checked_func = function()
return G_reader_settings:isTrue("toc_items_show_separator") return G_reader_settings:nilOrTrue("toc_items_with_dots")
end, end,
callback = function() callback = function()
G_reader_settings:flipNilOrFalse("toc_items_show_separator") G_reader_settings:flipNilOrTrue("toc_items_with_dots")
end end
} }
end end

@ -33,7 +33,7 @@ local order = {
"----------------------------", "----------------------------",
"toc_items_per_page", "toc_items_per_page",
"toc_items_font_size", "toc_items_font_size",
"toc_items_show_separator", "toc_items_with_dots",
"----------------------------", "----------------------------",
"bookmarks_items_per_page", "bookmarks_items_per_page",
"bookmarks_items_font_size", "bookmarks_items_font_size",

@ -151,6 +151,8 @@ local MenuItem = InputContainer:new{
multilines_show_more_text = false, multilines_show_more_text = false,
-- Align text & mandatory baselines (only when single_line=true) -- Align text & mandatory baselines (only when single_line=true)
align_baselines = false, align_baselines = false,
-- Show a line of dots (also called tab or dot leaders) between text and mandatory
with_dots = false,
} }
function MenuItem:init() function MenuItem:init()
@ -265,6 +267,9 @@ function MenuItem:init()
text = self.bidi_wrap_func(text) text = self.bidi_wrap_func(text)
end end
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.single_line then -- items only in single line
-- No font size change: text will be truncated if it overflows -- No font size change: text will be truncated if it overflows
item_name = TextWidget:new{ item_name = TextWidget:new{
@ -279,21 +284,54 @@ function MenuItem:init()
-- feeling (which might make it no more truncated, but well...) -- feeling (which might make it no more truncated, but well...)
local text_max_width_if_ellipsis = available_width + text_mandatory_padding - text_ellipsis_mandatory_padding local text_max_width_if_ellipsis = available_width + text_mandatory_padding - text_ellipsis_mandatory_padding
item_name:setMaxWidth(text_max_width_if_ellipsis) item_name:setMaxWidth(text_max_width_if_ellipsis)
else
if self.with_dots then
local dots_width = available_width + text_mandatory_padding - w - dots_left_padding - dots_right_padding
if dots_width > 0 then
local dots_text, dots_min_width = self:getDotsText(self.info_face)
-- Don't show any dots if there would be less than 3
if dots_width >= dots_min_width then
dots_widget = TextWidget:new{
text = dots_text,
face = self.info_face, -- same as mandatory widget, to keep their baseline adjusted
max_width = dots_width,
truncate_with_ellipsis = false,
}
end
end
end
end end
if self.align_baselines then -- Align baselines of text and mandatory if self.align_baselines then -- Align baselines of text and mandatory
-- The container widgets would additionally center these widgets,
-- so make sure they all get a height=self.dimen.h so they don't
-- risk being shifted later and becoming misaligned
local name_baseline = item_name:getBaseline() local name_baseline = item_name:getBaseline()
local mandatory_baseline = mandatory_widget:getBaseline() local mdtr_baseline = mandatory_widget:getBaseline()
local baselines_diff = Math.round(name_baseline - mandatory_baseline) local name_height = item_name:getSize().h
local mdtr_height = mandatory_widget:getSize().h
-- Make all the TextWidgets be self.dimen.h
item_name.forced_height = self.dimen.h
mandatory_widget.forced_height = self.dimen.h
if dots_widget then
dots_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.)
local name_missing_pad_top = math.floor( (self.dimen.h - name_height) / 2)
local mdtr_missing_pad_top = math.floor( (self.dimen.h - mdtr_height) / 2)
name_baseline = name_baseline + name_missing_pad_top
mdtr_baseline = mdtr_baseline + mdtr_missing_pad_top
local baselines_diff = Math.round(name_baseline - mdtr_baseline)
if baselines_diff > 0 then if baselines_diff > 0 then
mandatory_widget = VerticalGroup:new{ mdtr_baseline = mdtr_baseline + baselines_diff
VerticalSpan:new{width = baselines_diff}, else
mandatory_widget, name_baseline = name_baseline - baselines_diff
} end
elseif baselines_diff < 0 then item_name.forced_baseline = name_baseline
item_name = VerticalGroup:new{ mandatory_widget.forced_baseline = mdtr_baseline
VerticalSpan:new{width = -baselines_diff}, if dots_widget then
item_name, dots_widget.forced_baseline = mdtr_baseline
}
end end
end end
@ -381,6 +419,13 @@ function MenuItem:init()
} }
} }
if dots_widget then
mandatory_widget = HorizontalGroup:new{
dots_widget,
HorizontalSpan:new{ width = dots_right_padding },
mandatory_widget,
}
end
local mandatory_container = RightContainer:new{ local mandatory_container = RightContainer:new{
dimen = Geom:new{w = self.content_width, h = self.dimen.h}, dimen = Geom:new{w = self.content_width, h = self.dimen.h},
mandatory_widget, mandatory_widget,
@ -427,6 +472,34 @@ function MenuItem:init()
} }
end end
local _dots_cached_info
function MenuItem:getDotsText(face)
local screen_w = Screen:getWidth()
if not _dots_cached_info or _dots_cached_info.screen_width ~= screen_w
or _dots_cached_info.face ~= face then
local unit = "."
local tmp = TextWidget:new{
text = unit,
face = face,
}
local unit_w = tmp:getSize().w
tmp:free()
-- (We assume/expect no kerning will happen between consecutive units)
local nb_units = math.ceil(screen_w / unit_w)
local min_width = unit_w * 3 -- have it not shown if smaller than this
local text = unit:rep(nb_units)
_dots_cached_info = {
text = text,
min_width = min_width,
screen_width = screen_w,
face = face,
}
end
return _dots_cached_info.text, _dots_cached_info.min_width
end
function MenuItem:onFocus(initial_focus) function MenuItem:onFocus(initial_focus)
if Device:isTouchDevice() then if Device:isTouchDevice() then
-- Devices which are Keys capable will get this onFocus called by -- Devices which are Keys capable will get this onFocus called by
@ -1079,6 +1152,7 @@ function Menu:updateItems(select_number)
single_line = self.single_line, single_line = self.single_line,
multilines_show_more_text = multilines_show_more_text, multilines_show_more_text = multilines_show_more_text,
align_baselines = self.align_baselines, align_baselines = self.align_baselines,
with_dots = self.with_dots,
line_color = self.line_color, line_color = self.line_color,
items_padding = self.items_padding, items_padding = self.items_padding,
} }

Loading…
Cancel
Save