From f67469bab46e831246d59364955227cddc8c4178 Mon Sep 17 00:00:00 2001 From: hius07 <62179190+hius07@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:51:57 +0300 Subject: [PATCH] Highlight: add note marker (#9395) --- .../apps/reader/modules/readerbookmark.lua | 6 +- .../apps/reader/modules/readerhighlight.lua | 48 ++++++++ frontend/apps/reader/modules/readerview.lua | 104 +++++++++++++++++- 3 files changed, 151 insertions(+), 7 deletions(-) diff --git a/frontend/apps/reader/modules/readerbookmark.lua b/frontend/apps/reader/modules/readerbookmark.lua index e600264ae..e3a09c143 100644 --- a/frontend/apps/reader/modules/readerbookmark.lua +++ b/frontend/apps/reader/modules/readerbookmark.lua @@ -1098,7 +1098,11 @@ function ReaderBookmark:renameBookmark(item, from_highlight, is_new_note, new_te end end UIManager:close(self.input) - if not from_highlight then + if from_highlight then + if self.view.highlight.note_mark then + UIManager:setDirty(self.dialog, "ui") -- refresh note marker + end + else bookmark.type = self:getBookmarkType(bookmark) bookmark.text_orig = bookmark.text bookmark.text = DISPLAY_PREFIX[bookmark.type] .. bookmark.text diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 6fb04fe4a..7f0789a8b 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -307,6 +307,13 @@ local highlight_style = { {_("Invert"), "invert"}, } +local note_mark = { + {_("None"), "none"}, + {_("Underline"), "underline"}, + {_("Side line"), "sideline"}, + {_("Side mark"), "sidemark"}, +} + local long_press_action = { {_("Ask with popup dialog"), "ask"}, {_("Do nothing"), "nothing"}, @@ -386,6 +393,47 @@ function ReaderHighlight:addToMainMenu(menu_items) UIManager:show(spin_widget) end, }) + table.insert(menu_items.highlight_options.sub_item_table, { + text_func = function() + local notemark = self.view.highlight.note_mark or "none" + for __, v in ipairs(note_mark) do + if v[2] == notemark then + return T(_("Note marker: %1"), string.lower(v[1])) + end + end + end, + callback = function(touchmenu_instance) + local notemark = self.view.highlight.note_mark or "none" + local radio_buttons = {} + for _, v in ipairs(note_mark) do + table.insert(radio_buttons, { + { + text = v[1], + checked = v[2] == notemark, + provider = v[2], + }, + }) + end + UIManager:show(require("ui/widget/radiobuttonwidget"):new{ + title_text = _("Note marker"), + width_factor = 0.5, + keep_shown_on_apply = true, + radio_buttons = radio_buttons, + callback = function(radio) + if radio.provider == "none" then + self.view.highlight.note_mark = nil + G_reader_settings:delSetting("highlight_note_marker") + else + self.view.highlight.note_mark = radio.provider + G_reader_settings:saveSetting("highlight_note_marker", radio.provider) + end + self.view:setupNoteMarkPosition() + UIManager:setDirty(self.dialog, "ui") + if touchmenu_instance then touchmenu_instance:updateItems() end + end, + }) + end, + }) if self.document.info.has_pages then menu_items.panel_zoom_options = { text = _("Panel zoom (manga/comic)"), diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua index 4e71fa640..f4c02781c 100644 --- a/frontend/apps/reader/modules/readerview.lua +++ b/frontend/apps/reader/modules/readerview.lua @@ -5,6 +5,7 @@ ReaderView module handles all the screen painting for document browsing. local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local Device = require("device") +local Font = require("ui/font") local Geom = require("ui/geometry") local Event = require("ui/event") local IconWidget = require("ui/widget/iconwidget") @@ -14,6 +15,7 @@ local OverlapGroup = require("ui/widget/overlapgroup") local ReaderDogear = require("apps/reader/modules/readerdogear") local ReaderFlipping = require("apps/reader/modules/readerflipping") local ReaderFooter = require("apps/reader/modules/readerfooter") +local TextWidget = require("ui/widget/textwidget") local UIManager = require("ui/uimanager") local dbg = require("dbg") local logger = require("logger") @@ -41,6 +43,7 @@ local ReaderView = OverlapGroup:extend{ -- highlight with "lighten" or "underscore" or "strikeout" or "invert" highlight = { lighten_factor = G_reader_settings:readSetting("highlight_lighten_factor", 0.2), + note_mark = G_reader_settings:readSetting("highlight_note_marker"), temp_drawer = "invert", temp = {}, saved_drawer = "lighten", @@ -48,6 +51,10 @@ local ReaderView = OverlapGroup:extend{ indicator = nil, -- geom: non-touch highlight position indicator: {x = 50, y=50} }, highlight_visible = true, + note_mark_line_w = 3, -- side line thickness + note_mark_sign = nil, + note_mark_pos_x1 = nil, -- page 1 + note_mark_pos_x2 = nil, -- page 2 in two-page mode -- PDF/DjVu continuous paging page_scroll = nil, page_bgcolor = Blitbuffer.gray(DBACKGROUND_COLOR / 15), @@ -504,10 +511,16 @@ function ReaderView:drawPageSavedHighlight(bb, x, y) local pos0, pos1 = item.pos0, item.pos1 local boxes = self.document:getPageBoxesFromPositions(page, pos0, pos1) if boxes then + local drawer = item.drawer or self.highlight.saved_drawer + local draw_note_mark = self.highlight.note_mark and + self.ui.bookmark:getBookmarkNote({ page = page, datetime = item.datetime, }) for _, box in pairs(boxes) do local rect = self:pageToScreenTransform(page, box) if rect then - self:drawHighlightRect(bb, x, y, rect, item.drawer or self.highlight.saved_drawer) + self:drawHighlightRect(bb, x, y, rect, drawer, draw_note_mark) + if draw_note_mark and self.highlight.note_mark == "sidemark" then + draw_note_mark = false -- side mark in the first line only + end end end -- end for each box end -- end if boxes @@ -522,7 +535,7 @@ function ReaderView:drawXPointerSavedHighlight(bb, x, y) -- clear that cache when page layout change or highlights are added -- or removed). local cur_view_top, cur_view_bottom - for page, items in pairs(self.highlight.saved) do + for _, items in pairs(self.highlight.saved) do if items then for j = 1, #items do local item = items[j] @@ -547,10 +560,13 @@ function ReaderView:drawXPointerSavedHighlight(bb, x, y) if start_pos <= cur_view_bottom and end_pos >= cur_view_top then local boxes = self.document:getScreenBoxesFromPositions(pos0, pos1, true) -- get_segments=true if boxes then + local drawer = item.drawer or self.highlight.saved_drawer + local draw_note_mark = self.highlight.note_mark and + self.ui.bookmark:getBookmarkNote({ page = item.pos0, datetime = item.datetime, }) for _, box in pairs(boxes) do - local rect = self:pageToScreenTransform(page, box) - if rect then - self:drawHighlightRect(bb, x, y, rect, item.drawer or self.highlight.saved_drawer) + self:drawHighlightRect(bb, x, y, box, drawer, draw_note_mark) + if draw_note_mark and self.highlight.note_mark == "sidemark" then + draw_note_mark = false -- side mark in the first line only end end -- end for each box end -- end if boxes @@ -560,7 +576,7 @@ function ReaderView:drawXPointerSavedHighlight(bb, x, y) end -- end for all saved highlight end -function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer) +function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer, draw_note_mark) local x, y, w, h = rect.x, rect.y, rect.w, rect.h if drawer == "lighten" then bb:lightenRect(x, y, w, h, self.highlight.lighten_factor) @@ -575,6 +591,25 @@ function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer) elseif drawer == "invert" then bb:invertRect(x, y, w, h) end + if draw_note_mark then + if self.highlight.note_mark == "underline" then + bb:paintRect(x, y + h - 1, w, 2, Blitbuffer.COLOR_BLACK) + else + local note_mark_pos_x + if self.ui.paging or + (self.ui.document:getVisiblePageCount() == 1) or -- one-page mode + (x < Screen:getWidth() / 2) then -- page 1 in two-page mode + note_mark_pos_x = self.note_mark_pos_x1 + else + note_mark_pos_x = self.note_mark_pos_x2 + end + if self.highlight.note_mark == "sideline" then + bb:paintRect(note_mark_pos_x, y, self.note_mark_line_w, h, Blitbuffer.COLOR_BLACK) + elseif self.highlight.note_mark == "sidemark" then + self.note_mark_sign:paintTo(bb, note_mark_pos_x, y) + end + end + end end function ReaderView:getPageArea(page, zoom, rotation) @@ -638,6 +673,9 @@ function ReaderView:recalculate() if self.dimen.w > self.visible_area.w then self.state.offset.x = (self.dimen.w - self.visible_area.w) / 2 end + + self:setupNoteMarkPosition() + -- Flag a repaint so self:paintTo will be called -- NOTE: This is also unfortunately called during panning, essentially making sure we'll never be using "fast" for pans ;). UIManager:setDirty(self.dialog, self.currently_scrolling and "fast" or "partial") @@ -1141,4 +1179,58 @@ function ReaderView:getTapZones() return forward_zone, backward_zone end +function ReaderView:setupNoteMarkPosition() + local is_sidemark = self.highlight.note_mark == "sidemark" + + -- set/free note marker sign + if is_sidemark then + if not self.note_mark_sign then + self.note_mark_sign = TextWidget:new{ + text = "\u{F040}", -- pencil + face = Font:getFace("smallinfofont", 14), + padding = 0, + } + end + else + if self.note_mark_sign then + self.note_mark_sign:free() + self.note_mark_sign = nil + end + end + + -- calculate position x of the note side line/mark + if is_sidemark or self.highlight.note_mark == "sideline" then + local screen_w = Screen:getWidth() + local sign_w = is_sidemark and self.note_mark_sign:getWidth() or self.note_mark_line_w + local sign_gap = Screen:scaleBySize(5) -- to the text (cre) or to the screen edge (pdf) + if self.ui.paging then + if BD.mirroredUILayout() then + self.note_mark_pos_x1 = sign_gap + else + self.note_mark_pos_x1 = screen_w - sign_gap - sign_w + end + else + local doc_margins = self.ui.document:getPageMargins() + local pos_x_r = screen_w - doc_margins["right"] + sign_gap -- mark in the right margin + local pos_x_l = doc_margins["left"] - sign_gap - sign_w -- mark in the left margin + if self.ui.document:getVisiblePageCount() == 1 then + if BD.mirroredUILayout() then + self.note_mark_pos_x1 = pos_x_l + else + self.note_mark_pos_x1 = pos_x_r + end + else -- two-page mode + local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage(true)+1) + if BD.mirroredUILayout() then + self.note_mark_pos_x1 = pos_x_l + self.note_mark_pos_x2 = pos_x_l + page2_x + else + self.note_mark_pos_x1 = pos_x_r - page2_x + self.note_mark_pos_x2 = pos_x_r + end + end + end + end +end + return ReaderView