[RFC] Pagination UI shenanigans (#7335)

* Menu/KeyValuePage/ReaderGoTo: Unify the dialogs. (Generally, "Enter page number" as title, and "Go to page" as OK button).
* Allow *tapping* on pagination buttons, too. Added spacers around the text to accommodate for that.
* Disable input handlers when <= 1 pages, while still printing the label in black.
* Always display both the label and the chevrons, even on single page content. (Menu being an exception, because it can handle showing no content at all, in which case we hide the chevrons).
* KVP: Tweak the pagination buttons layout in order to have consistent centering, regardless of whether the return arrow is enabled or not. (Also, match Menu's layout, more or less).
* Menu: Minor layout tweaks to follow the KVP tweaks above. Fixes, among possibly other things, buttons in (non-FM) "List" menus overlapping the final entry (e.g., OPDS), and popout menus with a border being misaligned (e.g., Calibre, Find a file).
* CalendarView: Minor layout tweaks to follow the KVP tweaks. Ensures the pagination buttons are laid out in the same way as everywhere else (they used to be a wee bit higher).
pull/7349/head
NiLuJe 3 years ago committed by GitHub
parent d243097d75
commit 525b1957b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,6 +5,7 @@ local InfoMessage = require("ui/widget/infomessage")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local InputDialog = require("ui/widget/inputdialog") local InputDialog = require("ui/widget/inputdialog")
local Menu = require("ui/widget/menu") local Menu = require("ui/widget/menu")
local Size = require("ui/size")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local lfs = require("libs/libkoreader-lfs") local lfs = require("libs/libkoreader-lfs")
local BaseUtil = require("ffi/util") local BaseUtil = require("ffi/util")
@ -165,8 +166,8 @@ function FileSearcher:showSearchResults()
dimen = Screen:getSize(), dimen = Screen:getSize(),
} }
self.search_menu = Menu:new{ self.search_menu = Menu:new{
width = Screen:getWidth()-15, width = Screen:getWidth() - (Size.margin.fullscreen_popout * 2),
height = Screen:getHeight()-15, height = Screen:getHeight() - (Size.margin.fullscreen_popout * 2),
show_parent = menu_container, show_parent = menu_container,
onMenuHold = self.onMenuHold, onMenuHold = self.onMenuHold,
cface = Font:getFace("smallinfofont"), cface = Font:getFace("smallinfofont"),

@ -8,6 +8,7 @@ local FFIUtil = require("ffi/util")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local PluginLoader = require("pluginloader") local PluginLoader = require("pluginloader")
local SetDefaults = require("apps/filemanager/filemanagersetdefaults") local SetDefaults = require("apps/filemanager/filemanagersetdefaults")
local Size = require("ui/size")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local Screen = Device.screen local Screen = Device.screen
local dbg = require("dbg") local dbg = require("dbg")
@ -130,7 +131,9 @@ function FileManagerMenu:onOpenLastDoc()
end end
local FileManager = require("apps/filemanager/filemanager") local FileManager = require("apps/filemanager/filemanager")
FileManager.instance:onClose() if FileManager.instance then
FileManager.instance:onClose()
end
end end
function FileManagerMenu:setUpdateItemTable() function FileManagerMenu:setUpdateItemTable()
@ -738,7 +741,7 @@ function FileManagerMenu:onShowMenu(tab_index)
main_menu = Menu:new{ main_menu = Menu:new{
title = _("File manager menu"), title = _("File manager menu"),
item_table = Menu.itemTableFromTouchMenu(self.tab_item_table), item_table = Menu.itemTableFromTouchMenu(self.tab_item_table),
width = Screen:getWidth()-10, width = Screen:getWidth() - (Size.margin.fullscreen_popout * 2),
show_parent = menu_container, show_parent = menu_container,
} }
end end

@ -8,6 +8,7 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local InputDialog = require("ui/widget/inputdialog") local InputDialog = require("ui/widget/inputdialog")
local Menu = require("ui/widget/menu") local Menu = require("ui/widget/menu")
local MultiInputDialog = require("ui/widget/multiinputdialog") local MultiInputDialog = require("ui/widget/multiinputdialog")
local Size = require("ui/size")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local dump = require("dump") local dump = require("dump")
local isAndroid, android = pcall(require, "android") local isAndroid, android = pcall(require, "android")
@ -89,8 +90,8 @@ function SetDefaults:init()
end end
self.defaults_menu = Menu:new{ self.defaults_menu = Menu:new{
width = Screen:getWidth()-15, width = Screen:getWidth() - (Size.margin.fullscreen_popout * 2),
height = Screen:getHeight()-15, height = Screen:getHeight() - (Size.margin.fullscreen_popout * 2),
cface = Font:getFace("smallinfofont"), cface = Font:getFace("smallinfofont"),
show_parent = menu_container, show_parent = menu_container,
_manager = self, _manager = self,

@ -47,7 +47,7 @@ function ReaderGoto:onShowGotoDialog()
input_hint = T("@%1 (1 - %2)", curr_page, self.document:getPageCount()) input_hint = T("@%1 (1 - %2)", curr_page, self.document:getPageCount())
end end
self.goto_dialog = InputDialog:new{ self.goto_dialog = InputDialog:new{
title = _("Go to page"), title = _("Enter page number"),
input_hint = input_hint, input_hint = input_hint,
description = self.document:hasHiddenFlows() and description = self.document:hasHiddenFlows() and
_([[ _([[
@ -65,7 +65,7 @@ x for an absolute page number
end, end,
}, },
{ {
text = _("Skim mode"), text = _("Skim"),
enabled = true, enabled = true,
callback = function() callback = function()
self:close() self:close()
@ -82,7 +82,7 @@ x for an absolute page number
end, end,
}, },
{ {
text = _("Page"), text = _("Go to page"),
enabled = true, enabled = true,
is_enter_default = true, is_enter_default = true,
callback = function() self:gotoPage() end, callback = function() self:gotoPage() end,

@ -43,6 +43,7 @@ local Size = {
small = Screen:scaleBySize(2), small = Screen:scaleBySize(2),
title = Screen:scaleBySize(2), title = Screen:scaleBySize(2),
fine_tune = Screen:scaleBySize(3), fine_tune = Screen:scaleBySize(3),
fullscreen_popout = Screen:scaleBySize(3), -- Size.border.window * 2
button = 0, button = 0,
}, },
padding = { padding = {

@ -64,6 +64,11 @@ function Button:init()
self.text = self.text_func() self.text = self.text_func()
end end
-- Point tap_input to hold_input if requested
if self.call_hold_input_on_tap then
self.tap_input = self.hold_input
end
if not self.padding_h then if not self.padding_h then
self.padding_h = self.padding self.padding_h = self.padding
end end
@ -198,6 +203,17 @@ function Button:disable()
end end
end end
-- This is used by pagination buttons with a hold_input registered that we want to *sometimes* inhibit,
-- meaning we want the Button disabled, but *without* dimming the text...
function Button:disableWithoutDimming()
self.enabled = false
if self.text then
self.label_widget.fgcolor = Blitbuffer.COLOR_BLACK
else
self.label_widget.dim = false
end
end
function Button:enableDisable(enable) function Button:enableDisable(enable)
if enable then if enable then
self:enable() self:enable()
@ -286,72 +302,74 @@ function Button:_undoFeedbackHighlight(is_translucent)
end end
function Button:onTapSelectButton() function Button:onTapSelectButton()
if self.enabled and self.callback then if self.enabled or self.allow_tap_when_disabled then
if G_reader_settings:isFalse("flash_ui") then if self.callback then
self.callback() if G_reader_settings:isFalse("flash_ui") then
else self.callback()
-- NOTE: We have a few tricks up our sleeve in case our parent is inside a translucent MovableContainer... else
local is_translucent = self.show_parent and self.show_parent.movable and self.show_parent.movable.alpha -- NOTE: We have a few tricks up our sleeve in case our parent is inside a translucent MovableContainer...
local is_translucent = self.show_parent and self.show_parent.movable and self.show_parent.movable.alpha
-- Highlight
-- -- Highlight
self:_doFeedbackHighlight() --
self:_doFeedbackHighlight()
-- Force the refresh by draining the refresh queue *now*, so we have a chance to see the highlight on its own, before whatever the callback will do.
if not self.vsync then -- Force the refresh by draining the refresh queue *now*, so we have a chance to see the highlight on its own, before whatever the callback will do.
-- NOTE: Except when a Button is flagged vsync, in which case we *want* to bundle the highlight with the callback, to prevent further delays if not self.vsync then
UIManager:forceRePaint() -- NOTE: Except when a Button is flagged vsync, in which case we *want* to bundle the highlight with the callback, to prevent further delays
UIManager:forceRePaint()
-- NOTE: Yield to the kernel for a tiny slice of time, otherwise, writing to the same fb region as the refresh we've just requested may be race-y,
-- causing mild variants of our friend the papercut refresh glitch ;). -- NOTE: Yield to the kernel for a tiny slice of time, otherwise, writing to the same fb region as the refresh we've just requested may be race-y,
-- Remember that the whole eInk refresh dance is completely asynchronous: we *request* a refresh from the kernel, -- causing mild variants of our friend the papercut refresh glitch ;).
-- but it's up to the EPDC to schedule that however it sees fit... -- Remember that the whole eInk refresh dance is completely asynchronous: we *request* a refresh from the kernel,
-- The other approach would be to *ask* the EPDC to block until it's *completely* done, -- but it's up to the EPDC to schedule that however it sees fit...
-- but that's too much (because we only care about it being done *reading* the fb), -- The other approach would be to *ask* the EPDC to block until it's *completely* done,
-- and that could take upwards of 300ms, which is also way too much ;). -- but that's too much (because we only care about it being done *reading* the fb),
UIManager:yieldToEPDC() -- and that could take upwards of 300ms, which is also way too much ;).
end UIManager:yieldToEPDC()
end
-- Unhighlight
-- -- Unhighlight
-- We'll *paint* the unhighlight now, because at this point we can still be sure that our widget exists, --
-- and that anything we do will not impact whatever the callback does (i.e., that we draw *below* whatever the callback might show). -- We'll *paint* the unhighlight now, because at this point we can still be sure that our widget exists,
-- We won't *fence* the refresh (i.e., it's queued, but we don't actually drain the queue yet), though, to ensure that we do not delay the callback, and that the unhighlight essentially blends into whatever the callback does. -- and that anything we do will not impact whatever the callback does (i.e., that we draw *below* whatever the callback might show).
-- Worst case scenario, we'll simply have "wasted" a tiny subwidget repaint if the callback closed us, -- We won't *fence* the refresh (i.e., it's queued, but we don't actually drain the queue yet), though, to ensure that we do not delay the callback, and that the unhighlight essentially blends into whatever the callback does.
-- but doing it this way allows us to avoid a large array of potential interactions with whatever the callback may paint/refresh if we were to handle the unhighlight post-callback, -- Worst case scenario, we'll simply have "wasted" a tiny subwidget repaint if the callback closed us,
-- which would require a number of possibly brittle heuristics to handle. -- but doing it this way allows us to avoid a large array of potential interactions with whatever the callback may paint/refresh if we were to handle the unhighlight post-callback,
-- NOTE: If a Button is marked vsync, we want to keep it highlighted for now (in order for said highlight to be visible during the callback refresh), we'll remove the highlight post-callback. -- which would require a number of possibly brittle heuristics to handle.
if not self.vsync then -- NOTE: If a Button is marked vsync, we want to keep it highlighted for now (in order for said highlight to be visible during the callback refresh), we'll remove the highlight post-callback.
self:_undoFeedbackHighlight(is_translucent) if not self.vsync then
end self:_undoFeedbackHighlight(is_translucent)
end
-- Callback
-- -- Callback
self.callback() --
self.callback()
-- Check if the callback reset transparency...
is_translucent = is_translucent and self.show_parent.movable.alpha -- Check if the callback reset transparency...
is_translucent = is_translucent and self.show_parent.movable.alpha
UIManager:forceRePaint() -- Ensures whatever the callback wanted to paint will be shown *now*...
if self.vsync then UIManager:forceRePaint() -- Ensures whatever the callback wanted to paint will be shown *now*...
-- NOTE: This is mainly useful when the callback caused a REAGL update that we do not explicitly fence via MXCFB_WAIT_FOR_UPDATE_COMPLETE already, (i.e., Kobo Mk. 7). if self.vsync then
UIManager:waitForVSync() -- ...and that the EPDC will not wait to coalesce it with the *next* update, -- NOTE: This is mainly useful when the callback caused a REAGL update that we do not explicitly fence via MXCFB_WAIT_FOR_UPDATE_COMPLETE already, (i.e., Kobo Mk. 7).
-- because that would have a chance to noticeably delay it until the unhighlight. UIManager:waitForVSync() -- ...and that the EPDC will not wait to coalesce it with the *next* update,
end -- because that would have a chance to noticeably delay it until the unhighlight.
end
-- Unhighlight
-- -- Unhighlight
-- NOTE: If a Button is marked vsync, we have a guarantee from the programmer that the widget it belongs to is still alive and top-level post-callback, --
-- so we can do this safely without risking UI glitches. -- NOTE: If a Button is marked vsync, we have a guarantee from the programmer that the widget it belongs to is still alive and top-level post-callback,
if self.vsync then -- so we can do this safely without risking UI glitches.
self:_undoFeedbackHighlight(is_translucent) if self.vsync then
UIManager:forceRePaint() self:_undoFeedbackHighlight(is_translucent)
UIManager:forceRePaint()
end
end end
elseif self.tap_input then
self:onInput(self.tap_input)
elseif type(self.tap_input_func) == "function" then
self:onInput(self.tap_input_func())
end end
elseif self.tap_input then
self:onInput(self.tap_input)
elseif type(self.tap_input_func) == "function" then
self:onInput(self.tap_input_func())
end end
if self.readonly ~= true then if self.readonly ~= true then

@ -275,7 +275,7 @@ function InputContainer:onInput(input, ignore_first_hold_release)
input = input.input_func and input.input_func() or input.input, input = input.input_func and input.input_func() or input.input,
input_hint = input.hint_func and input.hint_func() or input.hint or "", input_hint = input.hint_func and input.hint_func() or input.hint or "",
input_type = input.type or "number", input_type = input.type or "number",
buttons = input.buttons or { buttons = input.buttons or {
{ {
{ {
text = input.cancel_text or _("Cancel"), text = input.cancel_text or _("Cancel"),

@ -41,6 +41,7 @@ local TextWidget = require("ui/widget/textwidget")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup") local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan") local VerticalSpan = require("ui/widget/verticalspan")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local Input = Device.input local Input = Device.input
local Screen = Device.screen local Screen = Device.screen
local T = require("ffi/util").template local T = require("ffi/util").template
@ -406,15 +407,18 @@ function KeyValuePage:init()
self.page_info_spacer = HorizontalSpan:new{ self.page_info_spacer = HorizontalSpan:new{
width = Screen:scaleBySize(32), width = Screen:scaleBySize(32),
} }
self.page_return_spacer = HorizontalSpan:new{
width = self.page_return_arrow:getSize().w
}
if self.callback_return == nil and self.return_button == nil then if self.callback_return == nil and self.return_button == nil then
self.page_return_arrow:hide() self.page_return_arrow:hide()
elseif self.callback_return == nil then elseif self.callback_return == nil then
self.page_return_arrow:disable() self.page_return_arrow:disable()
end end
self.return_button = HorizontalGroup:new{
HorizontalSpan:new{
width = Size.span.horizontal_small,
},
self.page_return_arrow,
}
self.page_info_left_chev:hide() self.page_info_left_chev:hide()
self.page_info_right_chev:hide() self.page_info_right_chev:hide()
@ -435,31 +439,47 @@ function KeyValuePage:init()
self:goToPage(page) self:goToPage(page)
end end
end, end,
ok_text = "Go to page",
}, },
call_hold_input_on_tap = true,
bordersize = 0, bordersize = 0,
margin = Screen:scaleBySize(20),
text_font_face = "pgfont", text_font_face = "pgfont",
text_font_bold = false, text_font_bold = false,
} }
self.page_info = HorizontalGroup:new{ self.page_info = HorizontalGroup:new{
self.page_return_arrow,
self.page_info_first_chev, self.page_info_first_chev,
self.page_info_spacer, self.page_info_spacer,
self.page_info_left_chev, self.page_info_left_chev,
self.page_info_spacer,
self.page_info_text, self.page_info_text,
self.page_info_spacer,
self.page_info_right_chev, self.page_info_right_chev,
self.page_info_spacer, self.page_info_spacer,
self.page_info_last_chev, self.page_info_last_chev,
self.page_return_spacer,
} }
local padding = Size.padding.large
self.inner_dimen = Geom:new{
w = self.dimen.w - 2 * padding,
h = self.dimen.h - padding, -- no bottom padding
}
self.item_width = self.inner_dimen.w
local footer = BottomContainer:new{ local footer = BottomContainer:new{
dimen = self.dimen:copy(), dimen = self.inner_dimen:copy(),
self.page_info, self.page_info,
} }
local page_return = BottomContainer:new{
dimen = self.inner_dimen:copy(),
WidgetContainer:new{
dimen = Geom:new{
w = self.inner_dimen.w,
h = self.return_button:getSize().h,
},
self.return_button,
}
}
local padding = Size.padding.large
self.item_width = self.dimen.w - 2 * padding
-- setup title bar -- setup title bar
self.title_bar = KeyValueTitle:new{ self.title_bar = KeyValueTitle:new{
title = self.title, title = self.title,
@ -468,9 +488,11 @@ function KeyValuePage:init()
use_top_page_count = self.use_top_page_count, use_top_page_count = self.use_top_page_count,
kv_page = self, kv_page = self,
} }
-- setup main content -- setup main content
local available_height = self.dimen.h local available_height = self.inner_dimen.h
- self.title_bar:getSize().h - self.title_bar:getSize().h
- Size.span.vertical_large -- for above page_info (as title_bar adds one itself)
- self.page_info:getSize().h - self.page_info:getSize().h
- 2*Size.line.thick - 2*Size.line.thick
-- account for possibly 2 separator lines added -- account for possibly 2 separator lines added
@ -478,7 +500,7 @@ function KeyValuePage:init()
self.items_per_page = G_reader_settings:readSetting("keyvalues_per_page") or self:getDefaultKeyValuesPerPage() self.items_per_page = G_reader_settings:readSetting("keyvalues_per_page") or self:getDefaultKeyValuesPerPage()
self.item_height = math.floor(available_height / self.items_per_page) self.item_height = math.floor(available_height / self.items_per_page)
-- Put half of the pixels lost by floor'ing between title and content -- Put half of the pixels lost by floor'ing between title and content
local span_height = math.floor((available_height - (self.items_per_page * (self.item_height ))) / 2) local span_height = math.floor((available_height - (self.items_per_page * (self.item_height))) / 2)
-- Font size is not configurable: we can get a good one from the following -- Font size is not configurable: we can get a good one from the following
local TextBoxWidget = require("ui/widget/textboxwidget") local TextBoxWidget = require("ui/widget/textboxwidget")
@ -496,20 +518,23 @@ function KeyValuePage:init()
self:_populateItems() self:_populateItems()
local content = OverlapGroup:new{ local content = OverlapGroup:new{
dimen = self.dimen:copy(),
allow_mirroring = false, allow_mirroring = false,
dimen = self.inner_dimen:copy(),
VerticalGroup:new{ VerticalGroup:new{
align = "left", align = "left",
self.title_bar, self.title_bar,
VerticalSpan:new{ width = span_height }, VerticalSpan:new{ width = span_height },
self.main_content, self.main_content,
}, },
page_return,
footer, footer,
} }
-- assemble page -- assemble page
self[1] = FrameContainer:new{ self[1] = FrameContainer:new{
height = self.dimen.h, height = self.dimen.h,
padding = padding, padding = padding,
padding_bottom = 0,
margin = 0,
bordersize = 0, bordersize = 0,
background = Blitbuffer.COLOR_WHITE, background = Blitbuffer.COLOR_WHITE,
content content
@ -549,6 +574,7 @@ end
-- make sure self.item_margin and self.item_height are set before calling this -- make sure self.item_margin and self.item_height are set before calling this
function KeyValuePage:_populateItems() function KeyValuePage:_populateItems()
self.page_info:resetLayout() self.page_info:resetLayout()
self.return_button:resetLayout()
self.main_content:clear() self.main_content:clear()
local idx_offset = (self.show_page - 1) * self.items_per_page local idx_offset = (self.show_page - 1) * self.items_per_page
for idx = 1, self.items_per_page do for idx = 1, self.items_per_page do
@ -597,11 +623,18 @@ function KeyValuePage:_populateItems()
end end
end end
end end
-- update page information
self.page_info_text:setText(T(_("Page %1 of %2"), self.show_page, self.pages)) self.page_info_text:setText(T(_("Page %1 of %2"), self.show_page, self.pages))
self.page_info_left_chev:showHide(self.pages > 1) if self.pages > 1 then
self.page_info_right_chev:showHide(self.pages > 1) self.page_info_text:enable()
self.page_info_first_chev:showHide(self.pages > 2) else
self.page_info_last_chev:showHide(self.pages > 2) self.page_info_text:disableWithoutDimming()
end
self.page_info_left_chev:show()
self.page_info_right_chev:show()
self.page_info_first_chev:show()
self.page_info_last_chev:show()
self.page_info_left_chev:enableDisable(self.show_page > 1) self.page_info_left_chev:enableDisable(self.show_page > 1)
self.page_info_right_chev:enableDisable(self.show_page < self.pages) self.page_info_right_chev:enableDisable(self.show_page < self.pages)

@ -51,7 +51,7 @@ function ItemShortCutIcon:init()
local radius = 0 local radius = 0
local background = Blitbuffer.COLOR_WHITE local background = Blitbuffer.COLOR_WHITE
if self.style == "rounded_corner" then if self.style == "rounded_corner" then
radius = math.floor(self.width/2) radius = math.floor(self.width / 2)
elseif self.style == "grey_square" then elseif self.style == "grey_square" then
background = Blitbuffer.COLOR_LIGHT_GRAY background = Blitbuffer.COLOR_LIGHT_GRAY
end end
@ -100,7 +100,7 @@ function MenuCloseButton:init()
-- diagonally aligned with the top right corner (assuming padding_right=0, -- diagonally aligned with the top right corner (assuming padding_right=0,
-- or padding_right = padding_top so the diagonal aligment is preserved). -- or padding_right = padding_top so the diagonal aligment is preserved).
local text_size = text_widget:getSize() local text_size = text_widget:getSize()
local text_width_pad = (text_size.h - text_size.w) / 2 local text_width_pad = math.floor((text_size.h - text_size.w) / 2)
self[1] = FrameContainer:new{ self[1] = FrameContainer:new{
bordersize = 0, bordersize = 0,
@ -157,7 +157,7 @@ function MenuItem:init()
self.content_width = self.dimen.w - 2 * Size.padding.fullscreen self.content_width = self.dimen.w - 2 * Size.padding.fullscreen
local shortcut_icon_dimen = Geom:new() local shortcut_icon_dimen = Geom:new()
if self.shortcut then if self.shortcut then
shortcut_icon_dimen.w = math.floor(self.dimen.h*4/5) shortcut_icon_dimen.w = math.floor(self.dimen.h * 4/5)
shortcut_icon_dimen.h = shortcut_icon_dimen.w shortcut_icon_dimen.h = shortcut_icon_dimen.w
self.content_width = self.content_width - shortcut_icon_dimen.w - Size.span.horizontal_default self.content_width = self.content_width - shortcut_icon_dimen.w - Size.span.horizontal_default
end end
@ -216,7 +216,7 @@ function MenuItem:init()
} }
local state_indent = self.state and self.state.indent or "" local state_indent = self.state and self.state.indent or ""
local state_container = LeftContainer:new{ local state_container = LeftContainer:new{
dimen = Geom:new{w = self.content_width/2, h = self.dimen.h}, dimen = Geom:new{w = math.floor(self.content_width / 2), h = self.dimen.h},
HorizontalGroup:new{ HorizontalGroup:new{
TextWidget:new{ TextWidget:new{
text = state_indent, text = state_indent,
@ -457,8 +457,8 @@ end
function MenuItem:getGesPosition(ges) function MenuItem:getGesPosition(ges)
local dimen = self[1].dimen local dimen = self[1].dimen
return { return {
x = (ges.pos.x - dimen.x)/dimen.w, x = math.floor((ges.pos.x - dimen.x) / dimen.w),
y = (ges.pos.y - dimen.y)/dimen.h, y = math.floor((ges.pos.y - dimen.y) / dimen.h),
} }
end end
@ -590,8 +590,12 @@ function Menu:_recalculateDimen()
if self.dimen.h > Screen:getHeight() or self.dimen.h == nil then if self.dimen.h > Screen:getHeight() or self.dimen.h == nil then
self.dimen.h = Screen:getHeight() self.dimen.h = Screen:getHeight()
end end
self.inner_dimen = Geom:new{
w = self.dimen.w - 2 * self.border_size,
h = self.dimen.h - 2 * self.border_size,
}
self.item_dimen = Geom:new{ self.item_dimen = Geom:new{
w = self.dimen.w, w = self.inner_dimen.w,
h = Screen:scaleBySize(46), h = Screen:scaleBySize(46),
} }
local height_dim local height_dim
@ -602,11 +606,11 @@ function Menu:_recalculateDimen()
+ 2 * Size.padding.button + 2 * Size.padding.button
end end
if self.menu_title and not self.no_title then if self.menu_title and not self.no_title then
top_height = self.menu_title_group:getSize().h + 2 * Size.padding.small top_height = self.menu_title_group:getSize().h + self.header_padding
end end
height_dim = self.dimen.h - bottom_height - top_height height_dim = self.inner_dimen.h - bottom_height - top_height
self.item_dimen.h = math.floor(height_dim / self.perpage) self.item_dimen.h = math.floor(height_dim / self.perpage)
self.span_width = math.floor((height_dim - (self.perpage * (self.item_dimen.h ))) / 2 -1 ) self.span_width = math.floor((height_dim - (self.perpage * (self.item_dimen.h ))) / 2 - 1)
self.page_num = math.ceil(#self.item_table / self.perpage) self.page_num = math.ceil(#self.item_table / self.perpage)
-- fix current page if out of range -- fix current page if out of range
if self.page_num > 0 and self.page > self.page_num then self.page = self.page_num end if self.page_num > 0 and self.page > self.page_num then self.page = self.page_num end
@ -620,6 +624,13 @@ function Menu:init()
if self.dimen.h > Screen:getHeight() or self.dimen.h == nil then if self.dimen.h > Screen:getHeight() or self.dimen.h == nil then
self.dimen.h = Screen:getHeight() self.dimen.h = Screen:getHeight()
end end
self.border_size = self.is_borderless and 0 or Size.border.window
self.inner_dimen = Geom:new{
w = self.dimen.w - 2 * self.border_size,
h = self.dimen.h - 2 * self.border_size,
}
self.page = 1 self.page = 1
self.paths = {} -- per instance table to trace navigation path self.paths = {} -- per instance table to trace navigation path
@ -634,7 +645,7 @@ function Menu:init()
} }
local menu_title_container = CenterContainer:new{ local menu_title_container = CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = self.dimen.w, w = self.inner_dimen.w,
h = self.menu_title:getSize().h, h = self.menu_title:getSize().h,
}, },
self.menu_title, self.menu_title,
@ -645,12 +656,12 @@ function Menu:init()
self.path_text = TextWidget:new{ self.path_text = TextWidget:new{
face = Font:getFace("xx_smallinfofont"), face = Font:getFace("xx_smallinfofont"),
text = BD.directory(self.path), text = BD.directory(self.path),
max_width = self.dimen.w - 2*Size.padding.small, max_width = self.inner_dimen.w - 2*Size.padding.small,
truncate_left = true, truncate_left = true,
} }
path_text_container = CenterContainer:new{ path_text_container = CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = self.dimen.w, w = self.inner_dimen.w,
h = self.path_text:getSize().h, h = self.path_text:getSize().h,
}, },
self.path_text, self.path_text,
@ -668,7 +679,7 @@ function Menu:init()
end end
-- group for title bar -- group for title bar
self.title_bar = OverlapGroup:new{ self.title_bar = OverlapGroup:new{
dimen = {w = self.dimen.w, h = self.menu_title_group:getSize().h}, dimen = {w = self.inner_dimen.w, h = self.menu_title_group:getSize().h},
self.menu_title_group, self.menu_title_group,
} }
-- group for items -- group for items
@ -776,6 +787,7 @@ function Menu:init()
hint_func = hint_func, hint_func = hint_func,
buttons = buttons, buttons = buttons,
}, },
call_hold_input_on_tap = true,
bordersize = 0, bordersize = 0,
text_font_face = "cfont", text_font_face = "cfont",
text_font_size = 20, text_font_size = 20,
@ -785,7 +797,9 @@ function Menu:init()
self.page_info_first_chev, self.page_info_first_chev,
self.page_info_spacer, self.page_info_spacer,
self.page_info_left_chev, self.page_info_left_chev,
self.page_info_spacer,
self.page_info_text, self.page_info_text,
self.page_info_spacer,
self.page_info_right_chev, self.page_info_right_chev,
self.page_info_spacer, self.page_info_spacer,
self.page_info_last_chev, self.page_info_last_chev,
@ -815,11 +829,11 @@ function Menu:init()
} }
local body = self.item_group local body = self.item_group
local footer = BottomContainer:new{ local footer = BottomContainer:new{
dimen = self.dimen:copy(), dimen = self.inner_dimen:copy(),
self.page_info, self.page_info,
} }
local page_return = BottomContainer:new{ local page_return = BottomContainer:new{
dimen = self.dimen:copy(), dimen = self.inner_dimen:copy(),
WidgetContainer:new{ WidgetContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = Screen:getWidth(), w = Screen:getWidth(),
@ -852,7 +866,7 @@ function Menu:init()
-- to have this complex Menu, and all widgets based on it, -- to have this complex Menu, and all widgets based on it,
-- be mirrored correctly with RTL languages -- be mirrored correctly with RTL languages
allow_mirroring = false, allow_mirroring = false,
dimen = self.dimen:copy(), dimen = self.inner_dimen:copy(),
self.content_group, self.content_group,
page_return, page_return,
footer, footer,
@ -860,10 +874,10 @@ function Menu:init()
self[1] = FrameContainer:new{ self[1] = FrameContainer:new{
background = Blitbuffer.COLOR_WHITE, background = Blitbuffer.COLOR_WHITE,
bordersize = self.is_borderless and 0 or Size.border.window, bordersize = self.border_size,
padding = 0, padding = 0,
margin = 0, margin = 0,
radius = self.is_popout and math.floor(self.dimen.w/20) or 0, radius = self.is_popout and math.floor(self.dimen.w / 20) or 0,
content content
} }
------------------------------------------ ------------------------------------------
@ -967,16 +981,16 @@ function Menu:updatePageInfo(select_number)
self.selected = { x = 1, y = select_number } self.selected = { x = 1, y = select_number }
end end
-- update page information -- update page information
self.page_info_text:setText(FFIUtil.template(_("Page %1 of %2"), self.page, self.page_num))
if self.page_num > 1 then if self.page_num > 1 then
self.page_info_text:setText(FFIUtil.template(_("Page %1 of %2"), self.page, self.page_num))
self.page_info_text:enable() self.page_info_text:enable()
else else
self.page_info_text:setText(""); self.page_info_text:disableWithoutDimming()
end end
self.page_info_left_chev:showHide(self.page_num > 1) self.page_info_left_chev:show()
self.page_info_right_chev:showHide(self.page_num > 1) self.page_info_right_chev:show()
self.page_info_first_chev:showHide(self.page_num > 2) self.page_info_first_chev:show()
self.page_info_last_chev:showHide(self.page_num > 2) self.page_info_last_chev:show()
self.page_return_arrow:showHide(self.onReturn ~= nil) self.page_return_arrow:showHide(self.onReturn ~= nil)
self.page_info_left_chev:enableDisable(self.page > 1) self.page_info_left_chev:enableDisable(self.page > 1)
@ -986,7 +1000,7 @@ function Menu:updatePageInfo(select_number)
self.page_return_arrow:enableDisable(#self.paths > 0) self.page_return_arrow:enableDisable(#self.paths > 0)
else else
self.page_info_text:setText(_("No choices available")) self.page_info_text:setText(_("No choices available"))
self.page_info_text:disable() self.page_info_text:disableWithoutDimming()
end end
end end
@ -1069,12 +1083,6 @@ function Menu:updateItems(select_number)
local refresh_dimen = local refresh_dimen =
old_dimen and old_dimen:combine(self.dimen) old_dimen and old_dimen:combine(self.dimen)
or self.dimen or self.dimen
if not self.is_borderless then
refresh_dimen = refresh_dimen:copy()
local bordersize = Size.border.window
refresh_dimen.w = refresh_dimen.w + bordersize*2
refresh_dimen.h = refresh_dimen.h + bordersize*2
end
return "ui", refresh_dimen return "ui", refresh_dimen
end) end)
end end
@ -1353,7 +1361,7 @@ end
function Menu.getItemFontSize(perpage) function Menu.getItemFontSize(perpage)
-- Get adjusted font size for the given nb of items per page: -- Get adjusted font size for the given nb of items per page:
-- item font size between 14 and 24 for better matching -- item font size between 14 and 24 for better matching
return math.floor(24 - ((perpage - 6)/ 18) * 10 ) return math.floor(24 - ((perpage - 6) / 18) * 10)
end end
function Menu.getItemMandatoryFontSize(perpage) function Menu.getItemMandatoryFontSize(perpage)

@ -15,6 +15,7 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local Menu = require("ui/widget/menu") local Menu = require("ui/widget/menu")
local Persist = require("persist") local Persist = require("persist")
local Screen = require("device").screen local Screen = require("device").screen
local Size = require("ui/size")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local logger = require("logger") local logger = require("logger")
local socket = require("socket") local socket = require("socket")
@ -384,8 +385,8 @@ function CalibreSearch:browse(option, run, chosen)
dimen = Screen:getSize(), dimen = Screen:getSize(),
} }
self.search_menu = Menu:new{ self.search_menu = Menu:new{
width = Screen:getWidth()-15, width = Screen:getWidth() - (Size.margin.fullscreen_popout * 2),
height = Screen:getHeight()-15, height = Screen:getHeight() - (Size.margin.fullscreen_popout * 2),
show_parent = menu_container, show_parent = menu_container,
onMenuHold = self.onMenuHold, onMenuHold = self.onMenuHold,
cface = Font:getFace("smallinfofont"), cface = Font:getFace("smallinfofont"),
@ -444,8 +445,8 @@ function CalibreSearch:showresults(t, title)
dimen = Screen:getSize(), dimen = Screen:getSize(),
} }
self.search_menu = Menu:new{ self.search_menu = Menu:new{
width = Screen:getWidth()-15, width = Screen:getWidth() - (Size.margin.fullscreen_popout * 2),
height = Screen:getHeight()-15, height = Screen:getHeight() - (Size.margin.fullscreen_popout * 2),
show_parent = menu_container, show_parent = menu_container,
onMenuHold = self.onMenuHold, onMenuHold = self.onMenuHold,
cface = Font:getFace("smallinfofont"), cface = Font:getFace("smallinfofont"),

@ -43,7 +43,11 @@ end
local function updateDir(dir) local function updateDir(dir)
local FileManager = require("apps/filemanager/filemanager") local FileManager = require("apps/filemanager/filemanager")
if FileManager:getCurrentDir() == dir then if FileManager:getCurrentDir() == dir then
FileManager.instance:reinit(dir) -- getCurrentDir() will return nil (well, nothing, technically) if there isn't an FM instance, so,
-- unless we were passed a nil, this is technically redundant.
if FileManager.instance then
FileManager.instance:reinit(dir)
end
end end
end end

@ -883,6 +883,11 @@ local ListMenu = {}
function ListMenu:_recalculateDimen() function ListMenu:_recalculateDimen()
self.dimen.w = self.width self.dimen.w = self.width
self.dimen.h = self.height or Screen:getHeight() self.dimen.h = self.height or Screen:getHeight()
-- NOTE: inner_dimen should match dimen because we're generally (always?) borderless
self.inner_dimen = Geom:new{
w = self.dimen.w - 2 * self.border_size,
h = self.dimen.h - 2 * self.border_size,
}
-- Find out available height from other UI elements made in Menu -- Find out available height from other UI elements made in Menu
self.others_height = 0 self.others_height = 0
@ -908,7 +913,7 @@ function ListMenu:_recalculateDimen()
self.itemnum_orig = self.path_items[self.path] self.itemnum_orig = self.path_items[self.path]
self.focused_path_orig = self.focused_path self.focused_path_orig = self.focused_path
end end
local available_height = self.dimen.h - self.others_height - Size.line.thin local available_height = self.inner_dimen.h - self.others_height - Size.line.thin
-- (Note: we can't assign directly to self.perpage and expect it to -- (Note: we can't assign directly to self.perpage and expect it to
-- be 'nil' if it was not defined, as we'll find instead the value -- be 'nil' if it was not defined, as we'll find instead the value
@ -943,7 +948,7 @@ function ListMenu:_recalculateDimen()
-- menu item height based on number of items per page -- menu item height based on number of items per page
-- add space for the separator -- add space for the separator
self.item_height = math.floor(available_height / self.perpage) - Size.line.thin self.item_height = math.floor(available_height / self.perpage) - Size.line.thin
self.item_width = self.dimen.w self.item_width = self.inner_dimen.w
self.item_dimen = Geom:new{ self.item_dimen = Geom:new{
w = self.item_width, w = self.item_width,
h = self.item_height h = self.item_height

@ -799,6 +799,11 @@ local MosaicMenu = {}
function MosaicMenu:_recalculateDimen() function MosaicMenu:_recalculateDimen()
self.dimen.w = self.width self.dimen.w = self.width
self.dimen.h = self.height or Screen:getHeight() self.dimen.h = self.height or Screen:getHeight()
-- NOTE: inner_dimen should match dimen because we're generally (always?) borderless
self.inner_dimen = Geom:new{
w = self.dimen.w - 2 * self.border_size,
h = self.dimen.h - 2 * self.border_size,
}
local portrait_mode = true local portrait_mode = true
if Screen:getWidth() > Screen:getHeight() then if Screen:getWidth() > Screen:getHeight() then
@ -834,8 +839,8 @@ function MosaicMenu:_recalculateDimen()
-- Set our items target size -- Set our items target size
self.item_margin = Screen:scaleBySize(10) self.item_margin = Screen:scaleBySize(10)
self.item_height = math.floor((self.dimen.h - self.others_height - (1+self.nb_rows)*self.item_margin) / self.nb_rows) self.item_height = math.floor((self.inner_dimen.h - self.others_height - (1+self.nb_rows)*self.item_margin) / self.nb_rows)
self.item_width = math.floor((self.dimen.w - (1+self.nb_cols)*self.item_margin) / self.nb_cols) self.item_width = math.floor((self.inner_dimen.w - (1+self.nb_cols)*self.item_margin) / self.nb_cols)
self.item_dimen = Geom:new{ self.item_dimen = Geom:new{
w = self.item_width, w = self.item_width,
h = self.item_height h = self.item_height
@ -873,7 +878,7 @@ function MosaicMenu:_updateItemsBuildUI()
local container = self._do_center_partial_rows and CenterContainer or LeftContainer local container = self._do_center_partial_rows and CenterContainer or LeftContainer
table.insert(self.item_group, container:new{ table.insert(self.item_group, container:new{
dimen = Geom:new{ dimen = Geom:new{
w = self.dimen.w, w = self.inner_dimen.w,
h = self.item_height h = self.item_height
}, },
cur_row cur_row

@ -443,14 +443,19 @@ function CalendarView:init()
} }
end end
local outer_padding = Size.padding.large self.outer_padding = Size.padding.large
self.inner_padding = Size.padding.small self.inner_padding = Size.padding.small
-- 7 days in a week -- 7 days in a week
self.day_width = math.floor((self.dimen.w - 2*outer_padding - 6*self.inner_padding) / 7) self.day_width = math.floor((self.dimen.w - 2*self.outer_padding - 6*self.inner_padding) / 7)
-- Put back the possible 7px lost in rounding into outer_padding -- Put back the possible 7px lost in rounding into outer_padding
outer_padding = math.floor((self.dimen.w - 7*self.day_width - 6*self.inner_padding) / 2) self.outer_padding = math.floor((self.dimen.w - 7*self.day_width - 6*self.inner_padding) / 2)
self.content_width = self.dimen.w - 2*outer_padding
self.inner_dimen = Geom:new{
w = self.dimen.w - 2*self.outer_padding,
h = self.dimen.h - self.outer_padding, -- no bottom padding
}
self.content_width = self.inner_dimen.w
local now_ts = os.time() local now_ts = os.time()
if not MIN_MONTH then if not MIN_MONTH then
@ -523,8 +528,8 @@ function CalendarView:init()
}) })
end, end,
}, },
call_hold_input_on_tap = true,
bordersize = 0, bordersize = 0,
margin = Screen:scaleBySize(20),
text_font_face = "pgfont", text_font_face = "pgfont",
text_font_bold = false, text_font_bold = false,
} }
@ -532,7 +537,9 @@ function CalendarView:init()
self.page_info_first_chev, self.page_info_first_chev,
self.page_info_spacer, self.page_info_spacer,
self.page_info_left_chev, self.page_info_left_chev,
self.page_info_spacer,
self.page_info_text, self.page_info_text,
self.page_info_spacer,
self.page_info_right_chev, self.page_info_right_chev,
self.page_info_spacer, self.page_info_spacer,
self.page_info_last_chev, self.page_info_last_chev,
@ -540,8 +547,8 @@ function CalendarView:init()
local footer = BottomContainer:new{ local footer = BottomContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = self.content_width, w = self.inner_dimen.w,
h = self.dimen.h, h = self.inner_dimen.h,
}, },
self.page_info, self.page_info,
} }
@ -575,9 +582,9 @@ function CalendarView:init()
end end
-- At most 6 weeks in a month -- At most 6 weeks in a month
local available_height = self.dimen.h - self.title_bar:getSize().h local available_height = self.inner_dimen.h - self.title_bar:getSize().h
- self.page_info:getSize().h - self.day_names:getSize().h - self.page_info:getSize().h - self.day_names:getSize().h
self.week_height = math.floor((available_height - 5*self.inner_padding) / 6) self.week_height = math.floor((available_height - 7*self.inner_padding) / 6)
self.day_border = Size.border.default self.day_border = Size.border.default
if self.show_hourly_histogram then if self.show_hourly_histogram then
-- day num + nb_book_spans + histogram: ceil() as histogram rarely -- day num + nb_book_spans + histogram: ceil() as histogram rarely
@ -611,8 +618,8 @@ function CalendarView:init()
local content = OverlapGroup:new{ local content = OverlapGroup:new{
dimen = Geom:new{ dimen = Geom:new{
w = self.content_width, w = self.inner_dimen.w,
h = self.dimen.h, h = self.inner_dimen.h,
}, },
allow_mirroring = false, allow_mirroring = false,
VerticalGroup:new{ VerticalGroup:new{
@ -627,7 +634,9 @@ function CalendarView:init()
self[1] = FrameContainer:new{ self[1] = FrameContainer:new{
width = self.dimen.w, width = self.dimen.w,
height = self.dimen.h, height = self.dimen.h,
padding = outer_padding, padding = self.outer_padding,
padding_bottom = 0,
margin = 0,
bordersize = 0, bordersize = 0,
background = Blitbuffer.COLOR_WHITE, background = Blitbuffer.COLOR_WHITE,
content content

Loading…
Cancel
Save