From 7666644362ed172043bc3c034f823aeb6a3b5ef8 Mon Sep 17 00:00:00 2001 From: poire-z Date: Thu, 19 Jul 2018 08:18:55 +0200 Subject: [PATCH] Bookmarks, CoverBrowser: scale dogear icon (#4081) The Dogear icon is 20x20 pixels and was never scaled where used. Now: - The bookmark icon (top right of screen) is scaled to 1/32th of the screen width (previously, it was 1/30th on a 600px wide emulator, 1/53th on a GloHD). On CreDocument, furthermore decrease its size if needed depending on the selected margins so it never overwrite the text. - CoverBrowser list view: scale it to the available room under the "N % of P page" text, so it does not cover "page". - CoverBrowser mosaic view: scale it to 1/16th of the cover rectangle, which should prevent if from overwritting the text thanks to a max text width of 7/8 of the cover rectangle. Also for CoverBrowser: don't index metadata for unsupported document (which could happen when browsing files with PathChooser) and show full filename for such documents. Also: ImageWidget: small fix in case we use both scale_factor and scale_for_dpi. --- frontend/apps/reader/modules/readerdogear.lua | 63 ++++++++++++++++--- frontend/ui/widget/imagewidget.lua | 4 +- .../coverbrowser.koplugin/bookinfomanager.lua | 20 ++++++ plugins/coverbrowser.koplugin/listmenu.lua | 32 ++++++++-- plugins/coverbrowser.koplugin/mosaicmenu.lua | 26 ++++++-- 5 files changed, 125 insertions(+), 20 deletions(-) diff --git a/frontend/apps/reader/modules/readerdogear.lua b/frontend/apps/reader/modules/readerdogear.lua index 2f7bfa585..7f5f15f9e 100644 --- a/frontend/apps/reader/modules/readerdogear.lua +++ b/frontend/apps/reader/modules/readerdogear.lua @@ -10,17 +10,64 @@ local Screen = require("device").screen local ReaderDogear = InputContainer:new{} function ReaderDogear:init() - local widget = ImageWidget:new{ - file = "resources/icons/dogear.png", - alpha = true, - } - self[1] = RightContainer:new{ - dimen = Geom:new{w = Screen:getWidth(), h = widget:getSize().h}, - widget, - } + -- This image could be scaled for DPI (with scale_for_dpi=true, scale_factor=0.7), + -- but it's as good to scale it to a fraction (1/32) of the screen size. + -- For CreDocument, we should additionally take care of not exceeding margins + -- to not overwrite the book text. + -- For other documents, there is no easy way to know if valuable content + -- may be hidden by the icon (kopt's page_margin is quite obscure). + self.dogear_max_size = math.ceil( math.min(Screen:getWidth(), Screen:getHeight()) / 32) + self.dogear_size = nil + self:setupDogear() self:resetLayout() end +function ReaderDogear:setupDogear(new_dogear_size) + if not new_dogear_size then + new_dogear_size = self.dogear_max_size + end + if new_dogear_size ~= self.dogear_size then + self.dogear_size = new_dogear_size + if self[1] then + self[1]:free() + end + self[1] = RightContainer:new{ + dimen = Geom:new{w = Screen:getWidth(), h = self.dogear_size}, + ImageWidget:new{ + file = "resources/icons/dogear.png", + alpha = true, + width = self.dogear_size, + height = self.dogear_size, + } + } + end +end + +function ReaderDogear:onReadSettings(config) + if not self.ui.document.info.has_pages then + -- Adjust to CreDocument margins (as done in ReaderTypeset) + self:onSetPageMargins( + config:readSetting("copt_page_margins") or + G_reader_settings:readSetting("copt_page_margins") or + DCREREADER_CONFIG_MARGIN_SIZES_MEDIUM) + end +end + +function ReaderDogear:onSetPageMargins(margins) + if self.ui.document.info.has_pages then + -- we may get called by readerfooter (when hiding the footer) + -- on pdf documents and get margins=nil + return + end + local margin_top, margin_right = margins[2], margins[3] + -- As the icon is squared, we can take the max() instead of the min() of + -- top & right margins and be sure no text is hidden by the icon + -- (the provided margins are not scaled, so do as ReaderTypeset) + local margin = Screen:scaleBySize(math.max(margin_top, margin_right)) + local new_dogear_size = math.min(self.dogear_max_size, margin) + self:setupDogear(new_dogear_size) +end + function ReaderDogear:resetLayout() local new_screen_width = Screen:getWidth() if new_screen_width == self._last_screen_width then return end diff --git a/frontend/ui/widget/imagewidget.lua b/frontend/ui/widget/imagewidget.lua index 68f0bc364..2bebba8c5 100644 --- a/frontend/ui/widget/imagewidget.lua +++ b/frontend/ui/widget/imagewidget.lua @@ -142,9 +142,9 @@ function ImageWidget:_loadfile() end local hash = "image|"..self.file.."|"..(width or "").."|"..(height or "") -- Do the scaling for DPI here, so it can be cached and not re-done - -- each time in _render() + -- each time in _render() (but not if scale_factor, to avoid double scaling) local scale_for_dpi_here = false - if self.scale_for_dpi and DPI_SCALE ~= 1 then + if self.scale_for_dpi and DPI_SCALE ~= 1 and not self.scale_factor then scale_for_dpi_here = true -- we'll do it before caching hash = hash .. "|d" self.already_scaled_for_dpi = true -- so we don't do it again in _render() diff --git a/plugins/coverbrowser.koplugin/bookinfomanager.lua b/plugins/coverbrowser.koplugin/bookinfomanager.lua index d956867b4..1885ec710 100644 --- a/plugins/coverbrowser.koplugin/bookinfomanager.lua +++ b/plugins/coverbrowser.koplugin/bookinfomanager.lua @@ -255,6 +255,26 @@ end -- Bookinfo management function BookInfoManager:getBookInfo(filepath, get_cover) local directory, filename = splitFilePathName(filepath) + + -- CoverBrowser may be used by PathChooser, which will not filter out + -- files with unknown book extension. If not a supported extension, + -- returns a bookinfo like-object enough for a correct display and + -- to not trigger extraction, so we don't clutter DB with such files. + if not DocumentRegistry:hasProvider(filepath) then + return { + directory = directory, + filename = filename, + in_progress = 0, + cover_fetched = "Y", + has_meta = nil, + has_cover = nil, + ignore_meta = "Y", + ignore_cover = "Y", + -- for ListMenu to show the filename *with* suffix: + _no_provider = true + } + end + self:openDbConnection() local row = self.get_stmt:bind(directory, filename):step() self.get_stmt:clearbind():reset() -- get ready for next query diff --git a/plugins/coverbrowser.koplugin/listmenu.lua b/plugins/coverbrowser.koplugin/listmenu.lua index ebe07d50f..e32259ba4 100644 --- a/plugins/coverbrowser.koplugin/listmenu.lua +++ b/plugins/coverbrowser.koplugin/listmenu.lua @@ -37,10 +37,10 @@ local BookInfoManager = require("bookinfomanager") -- We will show a rotated dogear at bottom right corner of cover widget for -- opened files (the dogear will make it look like a "used book") -local corner_mark = ImageWidget:new{ - file = "resources/icons/dogear.png", - rotation_angle = 270 -} +-- The ImageWidget Will be created when we know the available height (and +-- recreated if height changes) +local corner_mark_size = -1 +local corner_mark -- ItemShortCutIcon (for keyboard navigation) is private to menu.lua and can't be accessed, -- so we need to redefine it @@ -314,6 +314,12 @@ function ListMenuItem:update() if self.mandatory then fileinfo_str = self.mandatory .. " " .. fileinfo_str end + if bookinfo._no_provider then + -- for unspported files: don't show extension on the right, + -- keep it in filename + filename_without_suffix = filename + fileinfo_str = self.mandatory + end -- Current page / pages are available or more accurate in .sdr/metadata.lua -- We use a cache (cleaned at end of this browsing session) to store -- page, percent read and book status from sidecar files, to avoid @@ -400,6 +406,22 @@ function ListMenuItem:update() } } + -- Create or replace corner_mark if needed + local wright_bottom_pad_available = math.ceil( (dimen.h - wright[1]:getSize().h) *2/3 ) + -- We should normally use 1/2 because of CenterContainer, but there's + -- some space inside the text widget that we can use for a larger marker + if wright_bottom_pad_available ~= corner_mark_size then + corner_mark_size = wright_bottom_pad_available + if corner_mark then + corner_mark:free() + end + corner_mark = ImageWidget:new{ + file = "resources/icons/dogear.png", + rotation_angle = 270, + width = corner_mark_size, + height = corner_mark_size, + } + end -- Build the middle main widget, in the space available local wmain_left_padding = Screen:scaleBySize(10) @@ -623,7 +645,7 @@ function ListMenuItem:paintTo(bb, x, y) end -- to which we paint over a dogear if needed - if self.do_hint_opened and self.been_opened then + if corner_mark and self.do_hint_opened and self.been_opened then -- align it on bottom right corner of widget local ix = self.width - corner_mark:getSize().w local iy = self.height - corner_mark:getSize().h diff --git a/plugins/coverbrowser.koplugin/mosaicmenu.lua b/plugins/coverbrowser.koplugin/mosaicmenu.lua index 1a67415f4..f18aa97b2 100644 --- a/plugins/coverbrowser.koplugin/mosaicmenu.lua +++ b/plugins/coverbrowser.koplugin/mosaicmenu.lua @@ -36,10 +36,10 @@ local BookInfoManager = require("bookinfomanager") -- We will show a rotated dogear at bottom right corner of cover widget for -- opened files (the dogear will make it look like a "used book") -local corner_mark = ImageWidget:new{ - file = "resources/icons/dogear.png", - rotation_angle = 270 -} +-- The ImageWidget Will be created when we know the available height (and +-- recreated if height changes) +local corner_mark_size = -1 +local corner_mark -- ItemShortCutIcon (for keyboard navigation) is private to menu.lua and can't be accessed, -- so we need to redefine it @@ -605,7 +605,7 @@ function MosaicMenuItem:paintTo(bb, x, y) end -- to which we paint over a dogear if needed - if self.do_hint_opened and self.been_opened then + if corner_mark and self.do_hint_opened and self.been_opened then -- align it on bottom right corner of sub-widget local target = self[1][1][1] local ix = self.width - math.ceil((self.width - target.dimen.w)/2) - corner_mark:getSize().w @@ -713,6 +713,22 @@ function MosaicMenu:_recalculateDimen() w = self.item_width, h = self.item_height } + + -- Create or replace corner_mark if needed + -- 1/12 (larger) or 1/16 (smaller) of cover looks allright + local mark_size = math.floor(math.min(self.item_width, self.item_height) / 16) + if mark_size ~= corner_mark_size then + corner_mark_size = mark_size + if corner_mark then + corner_mark:free() + end + corner_mark = ImageWidget:new{ + file = "resources/icons/dogear.png", + rotation_angle = 270, + width = corner_mark_size, + height = corner_mark_size, + } + end end function MosaicMenu:_updateItemsBuildUI()