mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
ProgressWidget: Add an optional marker on the initial position (#10114)
* Enable it on SkimToWidget * Optional on ReaderFooter (toggle in the progress bar > style submenu)
This commit is contained in:
@@ -437,7 +437,6 @@ local ReaderFooter = WidgetContainer:extend{
|
||||
mode = MODE.page_progress,
|
||||
pageno = nil,
|
||||
pages = nil,
|
||||
progress_percentage = 0.0,
|
||||
footer_text = nil,
|
||||
text_font_face = "ffont",
|
||||
height = Screen:scaleBySize(G_defaults:readSetting("DMINIBAR_CONTAINER_HEIGHT")),
|
||||
@@ -496,6 +495,7 @@ ReaderFooter.default_settings = {
|
||||
progress_pct_format = "0",
|
||||
progress_margin = false,
|
||||
pages_left_includes_current_page = false,
|
||||
initial_marker = false,
|
||||
}
|
||||
|
||||
function ReaderFooter:init()
|
||||
@@ -584,10 +584,11 @@ function ReaderFooter:init()
|
||||
self.progress_bar = ProgressWidget:new{
|
||||
width = nil,
|
||||
height = nil,
|
||||
percentage = self.progress_percentage,
|
||||
percentage = nil,
|
||||
tick_width = Screen:scaleBySize(self.settings.toc_markers_width),
|
||||
ticks = nil, -- ticks will be populated in self:updateFooterText
|
||||
last = nil, -- last will be initialized in self:updateFooterText
|
||||
initial_pos_marker = self.settings.initial_marker,
|
||||
}
|
||||
|
||||
if self.settings.progress_style_thin then
|
||||
@@ -1840,6 +1841,17 @@ With this enabled, the current page is included, so the count goes from n to 1 i
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
text = _("Show initial position marker"),
|
||||
checked_func = function()
|
||||
return self.settings.initial_marker == true
|
||||
end,
|
||||
callback = function()
|
||||
self.settings.initial_marker = not self.settings.initial_marker
|
||||
self.progress_bar.initial_pos_marker = self.settings.initial_marker
|
||||
self:refreshFooter(true)
|
||||
end
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -2120,16 +2132,16 @@ function ReaderFooter:updateFooterPage(force_repaint, full_repaint)
|
||||
local flow = self.ui.document:getPageFlow(self.pageno)
|
||||
local page = self.ui.document:getPageNumberInFlow(self.pageno)
|
||||
local pages = self.ui.document:getTotalPagesInFlow(flow)
|
||||
self.progress_bar.percentage = page / pages
|
||||
self.progress_bar:setPercentage(page / pages)
|
||||
else
|
||||
self.progress_bar.percentage = self.pageno / self.pages
|
||||
self.progress_bar:setPercentage(self.pageno / self.pages)
|
||||
end
|
||||
self:updateFooterText(force_repaint, full_repaint)
|
||||
end
|
||||
|
||||
function ReaderFooter:updateFooterPos(force_repaint, full_repaint)
|
||||
if type(self.position) ~= "number" then return end
|
||||
self.progress_bar.percentage = self.position / self.doc_height
|
||||
self.progress_bar:setPercentage(self.position / self.doc_height)
|
||||
self:updateFooterText(force_repaint, full_repaint)
|
||||
end
|
||||
|
||||
@@ -2466,6 +2478,8 @@ end
|
||||
|
||||
function ReaderFooter:onSuspend()
|
||||
self:unscheduleFooterAutoRefresh()
|
||||
-- Reset the initial marker
|
||||
self.progress_bar.inital_percentage = nil
|
||||
end
|
||||
|
||||
ReaderFooter.onEnterStandby = ReaderFooter.onSuspend
|
||||
@@ -2527,4 +2541,8 @@ function ReaderFooter:onTimeFormatChanged()
|
||||
self:refreshFooter(true, true)
|
||||
end
|
||||
|
||||
function ReaderFooter:onCloseWidget()
|
||||
self:free()
|
||||
end
|
||||
|
||||
return ReaderFooter
|
||||
|
||||
@@ -31,9 +31,14 @@ Example:
|
||||
local BD = require("ui/bidi")
|
||||
local Blitbuffer = require("ffi/blitbuffer")
|
||||
local Geom = require("ui/geometry")
|
||||
local IconWidget = require("ui/widget/iconwidget")
|
||||
local Math = require("optmath")
|
||||
local Widget = require("ui/widget/widget")
|
||||
local Screen = require("device").screen
|
||||
|
||||
-- Somewhat empirically chosen threshold to switch between the two designs ;o)
|
||||
local INITIAL_MARKER_HEIGHT_THRESHOLD = Screen:scaleBySize(12)
|
||||
|
||||
local ProgressWidget = Widget:extend{
|
||||
width = nil,
|
||||
height = nil,
|
||||
@@ -54,8 +59,51 @@ local ProgressWidget = Widget:extend{
|
||||
alt = nil, -- table with alternate pages to mark with different color (in the form {{ini1, len1}, {ini2, len2}, ...})
|
||||
_orig_margin_v = nil,
|
||||
_orig_bordersize = nil,
|
||||
initial_pos_marker = false, -- overlay a marker at the initial percentage position
|
||||
inital_percentage = nil,
|
||||
}
|
||||
|
||||
function ProgressWidget:init()
|
||||
if self.initial_pos_marker then
|
||||
if not self.inital_percentage then
|
||||
self.inital_percentage = self.percentage
|
||||
end
|
||||
|
||||
self:renderMarkerIcon()
|
||||
end
|
||||
end
|
||||
|
||||
function ProgressWidget:renderMarkerIcon()
|
||||
if not self.initial_pos_marker then
|
||||
return
|
||||
end
|
||||
|
||||
if self.initial_pos_icon then
|
||||
self.initial_pos_icon:free()
|
||||
end
|
||||
|
||||
-- Can't do anything if we don't have a proper height yet...
|
||||
if not self.height then
|
||||
return
|
||||
end
|
||||
|
||||
if self.height <= INITIAL_MARKER_HEIGHT_THRESHOLD then
|
||||
self.initial_pos_icon = IconWidget:new{
|
||||
icon = "position.marker.top",
|
||||
width = Math.round(self.height / 2),
|
||||
height = Math.round(self.height / 2),
|
||||
alpha = true,
|
||||
}
|
||||
else
|
||||
self.initial_pos_icon = IconWidget:new{
|
||||
icon = "position.marker",
|
||||
width = self.height,
|
||||
height = self.height,
|
||||
alpha = true,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function ProgressWidget:getSize()
|
||||
return { w = self.width, h = self.height }
|
||||
end
|
||||
@@ -127,6 +175,15 @@ function ProgressWidget:paintTo(bb, x, y)
|
||||
math.ceil(fill_width * self.percentage),
|
||||
math.ceil(fill_height),
|
||||
self.fillcolor)
|
||||
|
||||
-- Overlay the initial position marker on top of that
|
||||
if self.initial_pos_marker then
|
||||
if self.height <= INITIAL_MARKER_HEIGHT_THRESHOLD then
|
||||
self.initial_pos_icon:paintTo(bb, Math.round(fill_x + math.ceil(fill_width * self.inital_percentage) - self.height / 4), y - Math.round(self.height / 6))
|
||||
else
|
||||
self.initial_pos_icon:paintTo(bb, Math.round(fill_x + math.ceil(fill_width * self.inital_percentage) - self.height / 2), y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ...then the tick(s).
|
||||
@@ -149,6 +206,11 @@ end
|
||||
|
||||
function ProgressWidget:setPercentage(percentage)
|
||||
self.percentage = percentage
|
||||
if self.initial_pos_marker then
|
||||
if not self.inital_percentage then
|
||||
self.inital_percentage = self.percentage
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ProgressWidget:getPercentageFromPosition(pos)
|
||||
@@ -178,6 +240,9 @@ function ProgressWidget:setHeight(height)
|
||||
self.margin_v = math.max(self.margin_v, margin_v_min)
|
||||
self.bordersize = math.min(self._orig_bordersize, math.floor((self.height - 2*self.margin_v - 1) / 2))
|
||||
self.bordersize = math.max(self.bordersize, bordersize_min)
|
||||
|
||||
-- Re-render marker, if any
|
||||
self:renderMarkerIcon()
|
||||
end
|
||||
|
||||
function ProgressWidget:updateStyle(thick, height)
|
||||
@@ -209,4 +274,10 @@ function ProgressWidget:updateStyle(thick, height)
|
||||
end
|
||||
end
|
||||
|
||||
function ProgressWidget:free()
|
||||
if self.initial_pos_icon then
|
||||
self.initial_pos_icon:free()
|
||||
end
|
||||
end
|
||||
|
||||
return ProgressWidget
|
||||
|
||||
@@ -71,6 +71,7 @@ function SkimToWidget:init()
|
||||
tick_width = Size.line.medium,
|
||||
last = self.page_count,
|
||||
alt = self.ui.document.flows,
|
||||
initial_pos_marker = true,
|
||||
}
|
||||
|
||||
-- Bottom row buttons
|
||||
@@ -335,6 +336,8 @@ function SkimToWidget:onCloseWidget()
|
||||
UIManager:setDirty(nil, function()
|
||||
return "ui", self.skimto_frame.dimen
|
||||
end)
|
||||
|
||||
self:free()
|
||||
end
|
||||
|
||||
function SkimToWidget:onShow()
|
||||
|
||||
86
resources/icons/mdlight/position.marker.svg
Normal file
86
resources/icons/mdlight/position.marker.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 48 48"
|
||||
enable-background="new 0 0 76.00 76.00"
|
||||
xml:space="preserve"
|
||||
id="svg4"
|
||||
sodipodi:docname="position.marker.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
|
||||
id="metadata10"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs8" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1381"
|
||||
id="namedview6"
|
||||
showgrid="true"
|
||||
inkscape:zoom="21"
|
||||
inkscape:cx="22.404762"
|
||||
inkscape:cy="24.047619"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid835"
|
||||
originx="0"
|
||||
originy="0" /></sodipodi:namedview>
|
||||
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#000000;fill-opacity:0.80000001;fill-rule:evenodd"
|
||||
id="path1002"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="6"
|
||||
sodipodi:cy="6"
|
||||
sodipodi:r1="16.552944"
|
||||
sodipodi:r2="8.276473"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="1.5707963"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 20.33527,14.276472 -28.6705402,0 14.3352703,-24.829416 z"
|
||||
inkscape:transform-center-y="-4.0000005"
|
||||
transform="matrix(0.96659542,0,0,0.96659542,18.200427,43.200428)" /><path
|
||||
sodipodi:type="star"
|
||||
style="fill:#000000;fill-opacity:0.80000001;fill-rule:evenodd"
|
||||
id="path1136"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="6"
|
||||
sodipodi:cy="6"
|
||||
sodipodi:r1="16.552944"
|
||||
sodipodi:r2="8.276473"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="1.5707963"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 20.33527,14.276472 -28.6705402,0 14.3352703,-24.829416 z"
|
||||
transform="matrix(-0.96659542,0,0,-0.96659542,29.799573,4.7995726)"
|
||||
inkscape:transform-center-y="4.000001" /></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
57
resources/icons/mdlight/position.marker.top.svg
Normal file
57
resources/icons/mdlight/position.marker.top.svg
Normal file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 48 48"
|
||||
enable-background="new 0 0 76.00 76.00"
|
||||
xml:space="preserve"
|
||||
id="svg4"
|
||||
sodipodi:docname="position.marker.top.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
|
||||
id="metadata10"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs8" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1381"
|
||||
id="namedview6"
|
||||
showgrid="true"
|
||||
inkscape:zoom="22.627417"
|
||||
inkscape:cx="22.561126"
|
||||
inkscape:cy="24.925514"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid835"
|
||||
originx="0"
|
||||
originy="0" /></sodipodi:namedview>
|
||||
|
||||
<path
|
||||
style="fill:#000000;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
d="M 0,0 24,48 48,0 Z"
|
||||
id="path298" /></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
Reference in New Issue
Block a user