diff --git a/frontend/apps/reader/modules/readercropping.lua b/frontend/apps/reader/modules/readercropping.lua
index 29aaee8dc..e2f75e436 100644
--- a/frontend/apps/reader/modules/readercropping.lua
+++ b/frontend/apps/reader/modules/readercropping.lua
@@ -25,9 +25,6 @@ function ReaderCropping:onPageCrop(mode)
end
return
elseif mode == "none" then
- if self.document.configurable.text_wrap ~= 1 then
- self.ui:handleEvent(Event:new("SetZoomMode", "pagewidth", "cropping"))
- end
return
end
-- backup original view dimen
@@ -51,7 +48,7 @@ function ReaderCropping:onPageCrop(mode)
-- mode, just force readerview to recalculate visible_area
self.view:recalculate()
else
- self.ui:handleEvent(Event:new("SetZoomMode", "page", "cropping"))
+ self.ui:handleEvent(Event:new("SetZoomMode", "page"))
end
-- prepare bottom buttons so we know the size available for the page above it
@@ -152,11 +149,11 @@ end
function ReaderCropping:setCropZoomMode(confirmed)
if confirmed then
- -- if original zoom mode is not "content", set zoom mode to "contentwidth"
- self:setZoomMode(
- self.orig_zoom_mode:find("content")
- and self.orig_zoom_mode
- or "contentwidth")
+ -- if original zoom mode is "page???", set zoom mode to "content???"
+ local zoom_mode_type = self.orig_zoom_mode:match("page(.*)")
+ self:setZoomMode(zoom_mode_type
+ and "content"..zoom_mode_type
+ or self.orig_zoom_mode)
self.ui:handleEvent(Event:new("InitScrollPageStates"))
else
self:setZoomMode(self.orig_zoom_mode)
diff --git a/frontend/apps/reader/modules/readerkoptlistener.lua b/frontend/apps/reader/modules/readerkoptlistener.lua
index 3ada332f7..777be3db8 100644
--- a/frontend/apps/reader/modules/readerkoptlistener.lua
+++ b/frontend/apps/reader/modules/readerkoptlistener.lua
@@ -1,5 +1,7 @@
local EventListener = require("ui/widget/eventlistener")
local Event = require("ui/event")
+local ReaderZooming = require("apps/reader/modules/readerzooming")
+local util = require("util")
local ReaderKoptListener = EventListener:new{}
@@ -14,9 +16,13 @@ end
function ReaderKoptListener:onReadSettings(config)
-- normal zoom mode is zoom mode used in non-reflow mode.
- self.normal_zoom_mode = config:readSetting("normal_zoom_mode") or
+ local normal_zoom_mode = config:readSetting("normal_zoom_mode") or
G_reader_settings:readSetting("zoom_mode") or "page"
- self:setZoomMode(self.normal_zoom_mode)
+ normal_zoom_mode = util.arrayContains(ReaderZooming.available_zoom_modes, normal_zoom_mode)
+ and normal_zoom_mode
+ or "page"
+ self.normal_zoom_mode = normal_zoom_mode
+ self:setZoomMode(normal_zoom_mode)
self.document.configurable.contrast = config:readSetting("kopt_contrast") or
G_reader_settings:readSetting("kopt_contrast") or 1.0
self.ui:handleEvent(Event:new("GammaUpdate", 1/self.document.configurable.contrast))
diff --git a/frontend/apps/reader/modules/readerpaging.lua b/frontend/apps/reader/modules/readerpaging.lua
index 9296c1ce0..9b23dd124 100644
--- a/frontend/apps/reader/modules/readerpaging.lua
+++ b/frontend/apps/reader/modules/readerpaging.lua
@@ -6,6 +6,7 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local Math = require("optmath")
local MultiConfirmBox = require("ui/widget/multiconfirmbox")
local Notification = require("ui/widget/notification")
+local ReaderZooming = require("apps/reader/modules/readerzooming")
local UIManager = require("ui/uimanager")
local bit = require("bit")
local logger = require("logger")
@@ -193,6 +194,9 @@ function ReaderPaging:onReadSettings(config)
if self.inverse_reading_order == nil then
self.inverse_reading_order = G_reader_settings:isTrue("inverse_reading_order")
end
+ for _, v in ipairs(ReaderZooming.zoom_pan_settings) do
+ self[v] = config:readSetting(v) or G_reader_settings:readSetting(v) or ReaderZooming[v]
+ end
end
function ReaderPaging:onSaveSettings()
@@ -840,134 +844,115 @@ function ReaderPaging:onGotoPageRel(diff)
logger.dbg("goto relative page:", diff)
local new_va = self.visible_area:copy()
local x_pan_off, y_pan_off = 0, 0
-
- if self.zoom_mode:find("width") then
- y_pan_off = self.visible_area.h * diff
- elseif self.zoom_mode:find("height") then
- -- negative x panning if writing direction is right to left
- local direction = self.ui.document.configurable.writing_direction
- x_pan_off = self.visible_area.w * diff * (direction == 1 and -1 or 1)
- elseif self.zoom_mode:find("column") then
- -- zoom mode for two-column navigation
-
- y_pan_off = self.visible_area.h * diff
- y_pan_off = Math.roundAwayFromZero(y_pan_off)
- new_va.x = Math.roundAwayFromZero(self.visible_area.x)
- new_va.y = Math.roundAwayFromZero(self.visible_area.y+y_pan_off)
- -- intra-column navigation (vertical), this is the default behavior
- -- if we do not reach the end of a column
-
- if new_va:notIntersectWith(self.page_area) then
- -- if we leave the page, we must either switch to the other column
- -- or switch to another page (we are crossing the end of a column)
-
- x_pan_off = self.visible_area.w * diff
- x_pan_off = Math.roundAwayFromZero(x_pan_off)
- new_va.x = Math.roundAwayFromZero(self.visible_area.x+x_pan_off)
- new_va.y = Math.roundAwayFromZero(self.visible_area.y)
- -- inter-column displacement (horizontal)
-
- if new_va:notIntersectWith(self.page_area) then
- -- if we leave the page with horizontal displacement, then we are
- -- already in the border column, we must turn the page
-
- local new_page = self.current_page + diff
- if diff > 0 and new_page == self.number_of_pages + 1 then
- self.ui:handleEvent(Event:new("EndOfBook"))
- else
- self:_gotoPage(new_page)
- end
-
- if y_pan_off < 0 then
- -- if we are going back to previous page, reset view area
- -- to bottom right of previous page, end of second column
- self.view:PanningUpdate(self.page_area.w, self.page_area.h)
- end
-
- else
- -- if we do not leave the page with horizontal displacement,
- -- it means that we can stay on this page and switch column
-
- if diff > 0 then
- -- end of first column, set view area to the top right of
- -- current page, beginning of second column
- self.view:PanningUpdate(self.page_area.w, -self.page_area.h)
- else
- -- move backwards to the first column, set the view area to the
- -- bottom left of the current page
- self.view:PanningUpdate(-self.page_area.w, self.page_area.h)
- end
- end
-
- -- if we are here, the panning has already been updated so return
- return true
+ local right_to_left = (self.ui.document.configurable.writing_direction > 0)
+ local bottom_to_top = self.ui.zooming.zoom_bottom_to_top
+ local h_progress = 1 - self.ui.zooming.zoom_overlap_h / 100
+ local v_progress = 1 - self.ui.zooming.zoom_overlap_v / 100
+ local old_va = self.visible_area
+ local old_page = self.current_page
+ local x, y, w, h = "x", "y", "w", "h"
+ local x_diff = diff
+ local y_diff = diff
+
+ -- Adjust directions according to settings
+ if self.ui.zooming.zoom_direction_vertical then -- invert axes
+ y, x, h, w = x, y, w, h
+ h_progress, v_progress = v_progress, h_progress
+ if right_to_left then
+ x_diff, y_diff = -x_diff, -y_diff
end
+ if bottom_to_top then
+ x_diff = -x_diff
+ end
+ elseif bottom_to_top then
+ y_diff = -y_diff
+ end
+ if right_to_left then
+ x_diff = -x_diff
+ end
+
+ if self.zoom_mode ~= "free" then
+ x_pan_off = Math.roundAwayFromZero(self.visible_area[w] * h_progress * x_diff)
+ y_pan_off = Math.roundAwayFromZero(self.visible_area[h] * v_progress * y_diff)
+ end
- elseif self.zoom_mode ~= "free" then -- do nothing in "free" zoom mode
- -- must be fit content or page zoom mode
- if self.visible_area.w == self.page_area.w then
- y_pan_off = self.visible_area.h * diff
+ -- Auxiliary functions to (as much as possible) keep things clear
+ -- If going backwards (diff < 0) "end" is equivalent to "beginning", "next" to "previous";
+ -- in column mode, "line" is equivalent to "column".
+ local function at_end(axis)
+ -- returns true if we're at the end of line (axis = x) or page (axis = y)
+ local len, _diff
+ if axis == x then
+ len, _diff = w, x_diff
else
- x_pan_off = self.visible_area.w * diff
+ len, _diff = h, y_diff
end
+ return old_va[axis] + old_va[len] + _diff > self.page_area[axis] + self.page_area[len]
+ or old_va[axis] + _diff < self.page_area[axis]
+ end
+ local function goto_end(axis, _diff)
+ -- updates view area to the end of line (axis = x) or page (axis = y)
+ local len = axis == x and w or h
+ _diff = _diff or (axis == x and x_diff or y_diff)
+ new_va[axis] = _diff > 0
+ and old_va[axis] + self.page_area[len] - old_va[len]
+ or self.page_area[axis]
end
- -- adjust offset to help with page turn decision
- -- we dont take overlap into account here yet, otherwise new_va will
- -- always intersect with page_area
- x_pan_off = Math.roundAwayFromZero(x_pan_off)
- y_pan_off = Math.roundAwayFromZero(y_pan_off)
- new_va.x = Math.roundAwayFromZero(self.visible_area.x+x_pan_off)
- new_va.y = Math.roundAwayFromZero(self.visible_area.y+y_pan_off)
-
- if new_va:notIntersectWith(self.page_area) then
- -- view area out of page area, do a page turn
+ local function goto_next_line()
+ new_va[y] = old_va[y] + y_pan_off
+ goto_end(x, -x_diff)
+ end
+ local function goto_next_page()
local new_page = self.current_page + diff
- if diff > 0 and new_page == self.number_of_pages + 1 then
+ if new_page > self.number_of_pages then
self.ui:handleEvent(Event:new("EndOfBook"))
- else
+ goto_end(y)
+ goto_end(x)
+ elseif new_page > 0 then
self:_gotoPage(new_page)
+ goto_end(y, -y_diff)
+ else
+ goto_end(x)
end
- -- if we are going back to previous page, reset
- -- view area to bottom of previous page
- if x_pan_off < 0 then
- self.view:PanningUpdate(self.page_area.w, 0)
- elseif y_pan_off < 0 then
- self.view:PanningUpdate(0, self.page_area.h)
- end
- else
- -- not end of page yet, goto next view
- -- adjust panning step according to overlap
- local overlap = self.overlap
- if x_pan_off > overlap then
- -- moving to next view, move view
- x_pan_off = x_pan_off - overlap
- elseif x_pan_off < -overlap then
- x_pan_off = x_pan_off + overlap
- end
- if y_pan_off > overlap then
- y_pan_off = y_pan_off - overlap
- elseif y_pan_off < -overlap then
- y_pan_off = y_pan_off + overlap
- end
- -- we have to calculate again to count into overlap
- new_va.x = Math.roundAwayFromZero(self.visible_area.x+x_pan_off)
- new_va.y = Math.roundAwayFromZero(self.visible_area.y+y_pan_off)
- -- fit new view area into page area
- new_va:offsetWithin(self.page_area, 0, 0)
- -- calculate panning offsets
- local panned_x = new_va.x - self.visible_area.x
- local panned_y = new_va.y - self.visible_area.y
- -- adjust for crazy floating point overflow...
- if math.abs(panned_x) < 1 then
- panned_x = 0
- end
- if math.abs(panned_y) < 1 then
- panned_y = 0
+ end
+
+ -- Move the view area towerds line end
+ new_va[x] = old_va[x] + x_pan_off
+ new_va[y] = old_va[y]
+
+ -- Handle cases when the view area gets out of page boundaries
+ if not self.page_area:contains(new_va) then
+ if not at_end(x) then
+ goto_end(x)
+ else
+ goto_next_line()
+ if not self.page_area:contains(new_va) then
+ if not at_end(y) then
+ goto_end(y)
+ else
+ goto_next_page()
+ end
+ end
end
- -- singal panning update
- self.view:PanningUpdate(panned_x, panned_y)
- -- update dime area in ReaderView
- if self.show_overlap_enable then
+ end
+
+ -- signal panning update
+ local panned_x, panned_y = (new_va.x - old_va.x), (new_va.y - old_va.y)
+ -- adjust for crazy floating point overflow...
+ if math.abs(panned_x) < 1 then
+ panned_x = 0
+ end
+ if math.abs(panned_y) < 1 then
+ panned_y = 0
+ end
+ self.view:PanningUpdate(panned_x, panned_y)
+
+ -- update dim area in ReaderView
+ if self.show_overlap_enable then
+ if self.current_page ~= old_page then
+ self.view.dim_area.x = 0
+ self.view.dim_area.y = 0
+ else
self.view.dim_area.h = new_va.h - math.abs(panned_y)
self.view.dim_area.w = new_va.w - math.abs(panned_x)
if panned_y < 0 then
@@ -981,8 +966,6 @@ function ReaderPaging:onGotoPageRel(diff)
self.view.dim_area.x = 0
end
end
- -- update self.visible_area
- self.visible_area = new_va
end
return true
diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua
index 2ab578861..b348183d0 100644
--- a/frontend/apps/reader/modules/readerview.lua
+++ b/frontend/apps/reader/modules/readerview.lua
@@ -573,12 +573,17 @@ function ReaderView:recalculate()
self.visible_area.h = self.visible_area.h - self.ui.view.footer:getHeight()
end
if self.ui.document.configurable.writing_direction == 0 then
- -- starts from left top of page_area
+ -- starts from left of page_area
self.visible_area.x = self.page_area.x
- self.visible_area.y = self.page_area.y
else
- -- start from right top of page_area
+ -- start from right of page_area
self.visible_area.x = self.page_area.x + self.page_area.w - self.visible_area.w
+ end
+ if self.ui.zooming.zoom_bottom_to_top then
+ -- starts from bottom of page_area
+ self.visible_area.y = self.page_area.y + self.page_area.h - self.visible_area.h
+ else
+ -- starts from top of page_area
self.visible_area.y = self.page_area.y
end
if not self.page_scroll then
@@ -736,6 +741,9 @@ In combination with zoom to fit page, page height, content height or content, co
end
self.page_scroll = page_scroll
+ if not page_scroll then
+ self.ui.document.configurable.page_scroll = 0
+ end
self:recalculate()
self.ui:handleEvent(Event:new("InitScrollPageStates"))
end
diff --git a/frontend/apps/reader/modules/readerzooming.lua b/frontend/apps/reader/modules/readerzooming.lua
index a2657d242..31c987dbb 100644
--- a/frontend/apps/reader/modules/readerzooming.lua
+++ b/frontend/apps/reader/modules/readerzooming.lua
@@ -6,8 +6,10 @@ local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange")
local InfoMessage = require("ui/widget/infomessage")
local InputContainer = require("ui/widget/container/inputcontainer")
+local SpinWidget = require("ui/widget/spinwidget")
local UIManager = require("ui/uimanager")
local logger = require("logger")
+local util = require("util")
local _ = require("gettext")
local Input = Device.input
local Screen = Device.screen
@@ -15,9 +17,35 @@ local T = require("ffi/util").template
local ReaderZooming = InputContainer:new{
zoom = 1.0,
+ available_zoom_modes = {
+ "page",
+ "pagewidth",
+ "pageheight",
+ "content",
+ "contentwidth",
+ "contentheight",
+ "columns",
+ "rows",
+ "manual",
+ },
-- default to nil so we can trigger ZoomModeUpdate events on start up
zoom_mode = nil,
DEFAULT_ZOOM_MODE = "pagewidth",
+ -- for pan mode: fit to width/zoom_factor,
+ -- with overlap of zoom_overlap_h % (horizontally)
+ -- and zoom_overlap_v % (vertically).
+ zoom_factor = 2,
+ zoom_pan_settings = {
+ "zoom_factor",
+ "zoom_overlap_h",
+ "zoom_overlap_v",
+ "zoom_bottom_to_top",
+ "zoom_direction_vertical",
+ },
+ zoom_overlap_h = 40,
+ zoom_overlap_v = 40,
+ zoom_bottom_to_top = nil, -- true for bottom-to-top
+ zoom_direction_vertical = nil, -- true for column mode
current_page = 1,
rotation = 0,
paged_modes = {
@@ -71,25 +99,35 @@ function ReaderZooming:init()
doc = "zoom to fit content height",
event = "SetZoomMode", args = "contentheight"
},
- ZoomToFitColumn = {
- { "Shift", "C" },
- doc = "zoom to fit column",
- event = "SetZoomMode", args = "colu"
+ ZoomManual = {
+ { "Shift", "M" },
+ doc = "manual zoom mode",
+ event = "SetZoomMode", args = "manual"
},
}
end
- self.ui.menu:registerToMainMenu(self)
end
function ReaderZooming:onReadSettings(config)
- local zoom_mode = config:readSetting("zoom_mode") or
- G_reader_settings:readSetting("zoom_mode") or
- self.DEFAULT_ZOOM_MODE
+ local zoom_mode = config:readSetting("zoom_mode")
+ or G_reader_settings:readSetting("zoom_mode")
+ or self.DEFAULT_ZOOM_MODE
+ zoom_mode = util.arrayContains(self.available_zoom_modes, zoom_mode)
+ and zoom_mode
+ or self.DEFAULT_ZOOM_MODE
self:setZoomMode(zoom_mode, true) -- avoid informative message on load
+ for _, setting in ipairs(self.zoom_pan_settings) do
+ self[setting] = config:readSetting(setting) or
+ G_reader_settings:readSetting(setting) or
+ self[setting]
+ end
end
function ReaderZooming:onSaveSettings()
self.ui.doc_settings:saveSetting("zoom_mode", self.orig_zoom_mode or self.zoom_mode)
+ for _, setting in ipairs(self.zoom_pan_settings) do
+ self.ui.doc_settings:saveSetting(setting, self[setting])
+ end
end
function ReaderZooming:onSpread(arg, ges)
@@ -161,6 +199,108 @@ function ReaderZooming:onZoom(direction)
return true
end
+function ReaderZooming:onDefineZoom(btn)
+ local config = self.ui.document.configurable
+ local settings = ({
+ [7] = {right_to_left = false, zoom_bottom_to_top = false, zoom_direction_vertical = false},
+ [6] = {right_to_left = false, zoom_bottom_to_top = false, zoom_direction_vertical = true },
+ [5] = {right_to_left = false, zoom_bottom_to_top = true, zoom_direction_vertical = false},
+ [4] = {right_to_left = false, zoom_bottom_to_top = true, zoom_direction_vertical = true },
+ [3] = {right_to_left = true, zoom_bottom_to_top = true, zoom_direction_vertical = true },
+ [2] = {right_to_left = true, zoom_bottom_to_top = true, zoom_direction_vertical = false},
+ [1] = {right_to_left = true, zoom_bottom_to_top = false, zoom_direction_vertical = true },
+ [0] = {right_to_left = true, zoom_bottom_to_top = false, zoom_direction_vertical = false},
+ })[config.zoom_direction]
+ local zoom_range_number = config.zoom_range_number
+ local zoom_factor = config.zoom_factor
+ local zoom_mode_genus = ({
+ [4] = "page",
+ [3] = "content",
+ [2] = "columns",
+ [1] = "rows",
+ [0] = "manual",
+ })[config.zoom_mode_genus]
+ local zoom_mode_type = ({
+ [2] = "",
+ [1] = "width",
+ [0] = "height",
+ })[config.zoom_mode_type]
+ settings.zoom_overlap_h = config.zoom_overlap_h
+ settings.zoom_overlap_v = config.zoom_overlap_v
+ if btn == "set_zoom_overlap_h" then
+ self:_zoomPanChange(_("Set horizontal overlap"), "zoom_overlap_h")
+ settings.zoom_overlap_h = self.zoom_overlap_h
+ elseif btn == "set_zoom_overlap_v" then
+ self:_zoomPanChange(_("Set vertical overlap"), "zoom_overlap_v")
+ settings.zoom_overlap_v = self.zoom_overlap_v
+ end
+
+ local zoom_mode
+ if zoom_mode_genus == "page" or zoom_mode_genus == "content" then
+ zoom_mode = zoom_mode_genus..zoom_mode_type
+ else
+ zoom_mode = zoom_mode_genus
+ self.ui:handleEvent(Event:new("SetScrollMode", false))
+ end
+ zoom_mode = util.arrayContains(self.available_zoom_modes, zoom_mode) and zoom_mode or self.DEFAULT_ZOOM_MODE
+ settings.zoom_mode = zoom_mode
+
+ if settings.right_to_left then
+ if settings.zoom_bottom_to_top then
+ config.writing_direction = 2
+ else
+ config.writing_direction = 1
+ end
+ else
+ config.writing_direction = 0
+ end
+ settings.right_to_left = nil
+
+ if zoom_mode == "columns" or zoom_mode == "rows" then
+ if btn ~= "columns" and btn ~= "rows" then
+ self.ui:handleEvent(Event:new("SetZoomPan", settings, true))
+ settings.zoom_factor = self:setNumberOf(
+ zoom_mode,
+ zoom_range_number,
+ zoom_mode == "columns" and settings.zoom_overlap_h or settings.zoom_overlap_v
+ )
+ end
+ elseif zoom_mode == "manual" then
+ if btn == "manual" then
+ config.zoom_factor = self:getNumberOf("columns")
+ else
+ self:setNumberOf("columns", zoom_factor)
+ end
+ self.ui:handleEvent(Event:new("SetZoomPan", settings, true))
+ end
+ self.ui:handleEvent(Event:new("SetZoomMode", zoom_mode))
+ if btn == "columns" or btn == "rows" then
+ config.zoom_range_number = self:getNumberOf(
+ zoom_mode,
+ btn == "columns" and settings.zoom_overlap_h or settings.zoom_overlap_v
+ )
+ end
+ if tonumber(btn) then
+ UIManager:show(InfoMessage:new{
+ timeout = 2,
+ text = T(_([[Zoom set to:
+
+ mode: %1
+ number of columns: %2
+ number of rows: %4
+ horizontal overlap: %3 %
+ vertical overlap: %5 %
+ zoom factor: %6]]),
+ zoom_mode,
+ ("%.2f"):format(self:getNumberOf("columns", settings.zoom_overlap_h)),
+ settings.zoom_overlap_h,
+ ("%.2f"):format(self:getNumberOf("rows", settings.zoom_overlap_v)),
+ settings.zoom_overlap_v,
+ ("%.2f"):format(self:getNumberOf("columns"))),
+ })
+ end
+end
+
function ReaderZooming:onSetZoomMode(new_mode)
self.view.zoom_mode = new_mode
if self.zoom_mode ~= new_mode then
@@ -168,7 +308,11 @@ function ReaderZooming:onSetZoomMode(new_mode)
self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode))
self.zoom_mode = new_mode
self:setZoom()
- self.ui:handleEvent(Event:new("InitScrollPageStates", new_mode))
+ if new_mode == "manual" then
+ self.ui:handleEvent(Event:new("SetScrollMode", false))
+ else
+ self.ui:handleEvent(Event:new("InitScrollPageStates", new_mode))
+ end
end
end
@@ -241,12 +385,9 @@ end
function ReaderZooming:getZoom(pageno)
-- check if we're in bbox mode and work on bbox if that's the case
- local zoom = nil
+ local zoom
local page_size = self.ui.document:getNativePageDimensions(pageno)
- if self.zoom_mode == "content"
- or self.zoom_mode == "contentwidth"
- or self.zoom_mode == "contentheight"
- or self.zoom_mode == "column" then
+ if not (self.zoom_mode and self.zoom_mode:match("^page") or self.ui.document.configurable.trim_page == 3) then
local ubbox_dimen = self.ui.document:getUsedBBoxDimensions(pageno, 1)
-- if bbox is larger than the native page dimension render the full page
-- See discussion in koreader/koreader#970.
@@ -283,12 +424,15 @@ function ReaderZooming:getZoom(pageno)
end
elseif self.zoom_mode == "contentwidth" or self.zoom_mode == "pagewidth" then
zoom = zoom_w
- elseif self.zoom_mode == "column" then
- zoom = zoom_w * 2
elseif self.zoom_mode == "contentheight" or self.zoom_mode == "pageheight" then
zoom = zoom_h
elseif self.zoom_mode == "free" then
zoom = self.zoom
+ else
+ local zoom_factor = self.ui.doc_settings:readSetting("zoom_factor")
+ or G_reader_settings:readSetting("zoom_factor")
+ or self.zoom_factor
+ zoom = zoom_w * zoom_factor
end
if zoom and zoom > 10 and not Cache:willAccept(zoom * (self.dimen.w * self.dimen.h + 64)) then
logger.dbg("zoom too large, adjusting")
@@ -309,7 +453,7 @@ function ReaderZooming:getZoom(pageno)
if zoom < 0 then return 0 end
end
end
- return zoom
+ return zoom, zoom_w, zoom_h
end
function ReaderZooming:getRegionalZoomCenter(pageno, pos)
@@ -345,54 +489,109 @@ function ReaderZooming:genSetZoomModeCallBack(mode)
end
function ReaderZooming:setZoomMode(mode, no_warning)
- if not no_warning and self.ui.view.page_scroll and self.paged_modes[mode] then
- UIManager:show(InfoMessage:new{
- text = T(_([[
+ if not no_warning and self.ui.view.page_scroll then
+ local message
+ if self.paged_modes[mode] then
+ message = T(_([[
%1
-In combination with continuous view (scroll mode), this can cause unexpected vertical shifts when turning pages.]]), self.paged_modes[mode]),
- timeout = 5,
- })
+In combination with continuous view (scroll mode), this can cause unexpected vertical shifts when turning pages.]]),
+ self.paged_modes[mode])
+ elseif self.zoom_mode == "manual" then
+ message = _([[
+"Manual zoom works best with page view."
+
+Please enable page view instead of continuous view (scroll mode).]])
+ end
+ if message then
+ UIManager:show(InfoMessage:new{text = message, timeout = 5})
+ end
end
self.ui:handleEvent(Event:new("SetZoomMode", mode))
self.ui:handleEvent(Event:new("InitScrollPageStates"))
end
-function ReaderZooming:addToMainMenu(menu_items)
- if self.ui.document.info.has_pages then
- local function getZoomModeMenuItem(text, mode, separator)
- return {
- text_func = function()
- local default_zoom_mode = G_reader_settings:readSetting("zoom_mode") or self.DEFAULT_ZOOM_MODE
- return text .. (mode == default_zoom_mode and " ★" or "")
- end,
- checked_func = function()
- return self.zoom_mode == mode
- end,
- callback = self:genSetZoomModeCallBack(mode),
- hold_callback = function(touchmenu_instance)
- self:makeDefault(mode, touchmenu_instance)
- end,
- separator = separator,
- }
+local function _getOverlapFactorForNum(n, overlap)
+ -- Auxiliary function to "distribute" an overlap between tiles
+ overlap = overlap * (n - 1) / n
+ return (100 / (100 - overlap))
+end
+
+function ReaderZooming:getNumberOf(what, overlap)
+ -- Number of columns (if what ~= "rows") or rows (if what == "rows")
+ local zoom, zoom_w, zoom_h = self:getZoom(self.current_page)
+ local zoom_factor = zoom / (what == "rows" and zoom_h or zoom_w)
+ if overlap then
+ overlap = (what == "rows" and self.zoom_overlap_v or self.zoom_overlap_h)
+ zoom_factor = (overlap - 100 * zoom_factor) / (overlap - 100) -- Thanks Xcas for this one...
+ end
+ return zoom_factor
+end
+
+function ReaderZooming:setNumberOf(what, num, overlap)
+ -- Sets number of columns (if what ~= "rows") or rows (if what == "rows")
+ local _, zoom_w, zoom_h = self:getZoom(self.current_page)
+ local overlap_factor = overlap and _getOverlapFactorForNum(num, overlap) or 1
+ local zoom_factor = num / overlap_factor
+ if what == "rows" then
+ zoom_factor = zoom_factor * zoom_h / zoom_w
+ end
+ self.ui:handleEvent(Event:new("SetZoomPan", {zoom_factor = zoom_factor}))
+ self.ui:handleEvent(Event:new("RedrawCurrentPage"))
+end
+
+function ReaderZooming:_zoomFactorChange(title_text, direction, precision)
+ local zoom_factor, overlap = self:getNumberOf(direction)
+ UIManager:show(SpinWidget:new{
+ width = math.floor(Screen:getWidth() * 0.6),
+ value = zoom_factor,
+ value_min = 0.1,
+ value_max = 10,
+ value_step = 0.1,
+ value_hold_step = 1,
+ precision = "%.1f",
+ ok_text = title_text,
+ title_text = title_text,
+ callback = function(spin)
+ zoom_factor = spin.value
+ self:setNumberOf(direction, zoom_factor, overlap)
end
- menu_items.switch_zoom_mode = {
- text = _("Switch zoom mode"),
- enabled_func = function()
- return self.ui.document.configurable.text_wrap ~= 1
- end,
- sub_item_table = {
- getZoomModeMenuItem(_("Zoom to fit content width"), "contentwidth"),
- getZoomModeMenuItem(_("Zoom to fit content height"), "contentheight", true),
- getZoomModeMenuItem(_("Zoom to fit page width"), "pagewidth"),
- getZoomModeMenuItem(_("Zoom to fit page height"), "pageheight", true),
- getZoomModeMenuItem(_("Zoom to fit column"), "column"),
- getZoomModeMenuItem(_("Zoom to fit content"), "content"),
- getZoomModeMenuItem(_("Zoom to fit page"), "page"),
- }
- }
+ })
+end
+
+function ReaderZooming:_zoomPanChange(text, setting)
+ UIManager:show(SpinWidget:new{
+ width = math.floor(Screen:getWidth() * 0.6),
+ value = self[setting],
+ value_min = 0,
+ value_max = 90,
+ value_step = 1,
+ value_hold_step = 10,
+ ok_text = _("Set"),
+ title_text = text,
+ callback = function(spin)
+ self.ui:handleEvent(Event:new("SetZoomPan", {[setting] = spin.value}))
+ end
+ })
+end
+
+function ReaderZooming:onZoomFactorChange()
+ self:_zoomFactorChange(_("Set Zoom factor"), false, "%.1f")
+end
+
+function ReaderZooming:onSetZoomPan(settings, no_redraw)
+ for k, v in pairs(settings) do
+ self[k] = v
+ self.ui.doc_settings:saveSetting(k, v)
end
+ if not no_redraw then
+ self.ui:handleEvent(Event:new("RedrawCurrentPage"))
+ end
+end
+
+function ReaderZooming:onBBoxUpdate()
+ self:onDefineZoom()
end
function ReaderZooming:makeDefault(zoom_mode, touchmenu_instance)
diff --git a/frontend/dispatcher.lua b/frontend/dispatcher.lua
index 475ea89db..884f5145f 100644
--- a/frontend/dispatcher.lua
+++ b/frontend/dispatcher.lua
@@ -28,6 +28,7 @@ Each setting contains:
local CreOptions = require("ui/data/creoptions")
local Device = require("device")
local Event = require("ui/event")
+local ReaderZooming = require("apps/reader/modules/readerzooming")
local Screen = require("device").screen
local UIManager = require("ui/uimanager")
local _ = require("gettext")
@@ -114,7 +115,7 @@ local settingsList = {
book_cover = { category="none", event="ShowBookCover", title=_("Book cover"), rolling=true, paging=true, separator=true,},
show_config_menu = { category="none", event="ShowConfigMenu", title=_("Show bottom menu"), rolling=true, paging=true,},
toggle_bookmark = { category="none", event="ToggleBookmark", title=_("Toggle bookmark"), rolling=true, paging=true,},
- toggle_inverse_reading_order = { category="none", event="ToggleReadingOrder", title=_("Toggle page turn direction"), rolling=true, paging=true,},
+ toggle_inverse_reading_order = { category="none", event="ToggleReadingOrder", title=_("Toggle page turn direction"), rolling=true, paging=true, separator=true},
cycle_highlight_action = { category="none", event="CycleHighlightAction", title=_("Cycle highlight action"), rolling=true, paging=true,},
cycle_highlight_style = { category="none", event="CycleHighlightStyle", title=_("Cycle highlight style"), rolling=true, paging=true,},
page_jmp = { category="absolutenumber", event="GotoViewRel", min=-100, max=100, title=_("Go %1 pages"), rolling=true, paging=true,},
@@ -127,7 +128,8 @@ local settingsList = {
-- paging reader settings
toggle_page_flipping = { category="none", event="TogglePageFlipping", title=_("Toggle page flipping"), paging=true,},
toggle_reflow = { category="none", event="ToggleReflow", title=_("Toggle reflow"), paging=true,},
- zoom = { category="string", event="SetZoomMode", title=_("Zoom to"), args={"contentwidth", "contentheight", "pagewidth", "pageheight", "column", "content", "page"}, toggle={"content width", "content height", "page width", "page height", "column", "content", "page"}, paging=true,},
+ zoom = { category="string", event="SetZoomMode", title=_("Zoom mode"), args=ReaderZooming.available_zoom_modes, toggle=ReaderZooming.available_zoom_modes, paging=true,},
+ zoom_factor_change = {category="none", event="ZoomFactorChange", title=_("Change zoom factor"), paging=true, separator=true},
-- parsed from CreOptions
-- the rest of the table elements are built from their counterparts in CreOptions
@@ -254,6 +256,7 @@ local dispatcher_menu_order = {
"toggle_reflow",
"toggle_inverse_reading_order",
"zoom",
+ "zoom_factor_change",
"cycle_highlight_action",
"cycle_highlight_style",
"panel_zoom_toggle",
diff --git a/frontend/document/document.lua b/frontend/document/document.lua
index 7b5224478..371bf12f3 100644
--- a/frontend/document/document.lua
+++ b/frontend/document/document.lua
@@ -273,10 +273,10 @@ function Document:getUsedBBoxDimensions(pageno, zoom, rotation)
-- clipping page bbox
if bbox.x0 < 0 then bbox.x0 = 0 end
if bbox.y0 < 0 then bbox.y0 = 0 end
- if bbox.x1 < 0 then bbox.x1 = 0 end
- if bbox.y1 < 0 then bbox.y1 = 0 end
+ if bbox.x1 and bbox.x1 < 0 then bbox.x1 = 0 end
+ if bbox.y1 and bbox.y1 < 0 then bbox.y1 = 0 end
local ubbox_dimen
- if (bbox.x0 >= bbox.x1) or (bbox.y0 >= bbox.y1) then
+ if (not bbox.x1 or bbox.x0 >= bbox.x1) or (not bbox.y1 or bbox.y0 >= bbox.y1) then
-- if document's bbox info is corrupted, we use the page size
ubbox_dimen = self:getPageDimensions(pageno, zoom, rotation)
else
diff --git a/frontend/ui/data/koptoptions.lua b/frontend/ui/data/koptoptions.lua
index 969740c37..ec176a864 100644
--- a/frontend/ui/data/koptoptions.lua
+++ b/frontend/ui/data/koptoptions.lua
@@ -76,6 +76,157 @@ In 'semi-auto' and 'manual' modes, you may need to define areas once on an odd p
},
}
},
+ {
+ icon = "resources/icons/appbar.page.fit.png",
+ options = {
+ {
+ name = "zoom_overlap_h",
+ name_text = _("Horizontal overlap"),
+ buttonprogress = true,
+ fine_tune = true,
+ values = {0, 12, 24, 36, 48, 60, 72, 84},
+ default_pos = 4,
+ default_value = 36,
+ show_func = function(config)
+ return config and config.zoom_mode_genus < 3
+ end,
+ event = "DefineZoom",
+ args = {0, 12, 24, 36, 48, 60, 72, 84},
+ labels = {0, 12, 24, 36, 48, 60, 72, 84},
+ name_text_hold_callback = optionsutil.showValues,
+ help_text = _([[Set horizontal zoom overlap (between columns).]]),
+ },
+ {
+ name = "zoom_overlap_v",
+ name_text = _("Vertical overlap"),
+ buttonprogress = true,
+ fine_tune = true,
+ values = {0, 12, 24, 36, 48, 60, 72, 84},
+ default_pos = 4,
+ default_value = 36,
+ show_func = function(config)
+ return config and config.zoom_mode_genus < 3
+ end,
+ event = "DefineZoom",
+ args = {0, 12, 24, 36, 48, 60, 72, 84},
+ labels = {0, 12, 24, 36, 48, 60, 72, 84},
+ name_text_hold_callback = optionsutil.showValues,
+ help_text = _([[Set vertical zoom overlap (between lines).]]),
+ },
+ {
+ name = "zoom_mode_type",
+ name_text = _("Fit"),
+ toggle = {_("full"), _("width"), _("height")},
+ alternate = false,
+ values = {2, 1, 0},
+ default_value = 2,
+ show_func = function(config) return config and config.zoom_mode_genus > 2 end,
+ event = "DefineZoom",
+ args = {"full", "width", "height"},
+ name_text_hold_callback = optionsutil.showValues,
+ help_text = _([[Set what to fit.]]),
+ },
+ {
+ name = "zoom_range_number",
+ name_text_func = function(config)
+ if config then
+ if config.zoom_mode_genus == 1 then return _("Rows")
+ elseif config.zoom_mode_genus == 2 then return _("Columns")
+ end
+ end
+ return _("Number")
+ end,
+ name_text_true_values = true,
+ show_true_value_func = function(str)
+ return string.format("%.1f", str)
+ end,
+ toggle = {_("1"), _("2"), _("3"), _("4"), _("5"), _("6"), _("7"), _("8")},
+ more_options = true,
+ more_options_param = {
+ value_step = 0.1, value_hold_step = 1,
+ value_min = 0.1, value_max = 1000,
+ precision = "%.1f",
+ },
+ values = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
+ default_pos = 2,
+ default_value = 2,
+ show_func = function(config)
+ return config and config.zoom_mode_genus < 3 and config.zoom_mode_genus > 0
+ end,
+ event = "DefineZoom",
+ args = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
+ name_text_hold_callback = optionsutil.showValues,
+ help_text = _([[Set the number of columns or rows into which to split the page.]]),
+ },
+ {
+ name = "zoom_factor",
+ name_text = _("Zoom factor"),
+ name_text_true_values = true,
+ show_true_value_func = function(str)
+ return string.format("%.1f", str)
+ end,
+ toggle = {_("0.7"), _("1"), _("1.5"), _("2"), _("3"), _("5"), _("10"), _("20")},
+ more_options = true,
+ more_options_param = {
+ value_step = 0.1, value_hold_step = 1,
+ value_min = 0.1, value_max = 1000,
+ precision = "%.1f",
+ },
+ values = {0.7, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0, 20.0},
+ default_pos = 3,
+ default_value = 1.5,
+ show_func = function(config)
+ return config and config.zoom_mode_genus < 1
+ end,
+ event = "DefineZoom",
+ args = {0.7, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0, 20.0},
+ name_text_hold_callback = optionsutil.showValues,
+ },
+ {
+ name = "zoom_mode_genus",
+ name_text = _("Zoom to"),
+ -- toggle = {_("page"), _("content"), _("columns"), _("rows"), _("manual")},
+ item_icons = {
+ "resources/icons/zoom.page.png",
+ "resources/icons/zoom.content.png",
+ "resources/icons/zoom.direction.column.png",
+ "resources/icons/zoom.direction.row.png",
+ "resources/icons/zoom.manual.png",
+ },
+ alternate = false,
+ values = {4, 3, 2, 1, 0},
+ default_value = 4,
+ event = "DefineZoom",
+ args = {"page", "content", "columns", "rows", "manual"},
+ name_text_hold_callback = optionsutil.showValues,
+ },
+ {
+ name = "zoom_direction",
+ name_text = _("Direction"),
+ enabled_func = function(config)
+ return config.zoom_mode_genus < 3
+ end,
+ item_icons = {
+ "resources/icons/direction.LRTB.png",
+ "resources/icons/direction.TBLR.png",
+ "resources/icons/direction.LRBT.png",
+ "resources/icons/direction.BTLR.png",
+ "resources/icons/direction.BTRL.png",
+ "resources/icons/direction.RLBT.png",
+ "resources/icons/direction.TBRL.png",
+ "resources/icons/direction.RLTB.png",
+ },
+ alternate = false,
+ values = {7, 6, 5, 4, 3, 2, 1, 0},
+ default_value = 7,
+ event = "DefineZoom",
+ args = {7, 6, 5, 4, 3, 2, 1, 0},
+ name_text_hold_callback = optionsutil.showValues,
+ help_text = _([[Set how paging and swiping forward should move the view on the page:
+left to right or reverse, top to bottom or reverse.]]),
+ },
+ }
+ },
{
icon = "resources/icons/appbar.column.two.large.png",
options = {
@@ -311,12 +462,12 @@ This can also be used to remove some gray background or to convert a grayscale o
{
name = "writing_direction",
name_text = S.WRITING_DIR,
- toggle = {S.LTR, S.RTL, S.TBRTL},
- values = {0, 1, 2},
- default_value = 0,
enabled_func = function(configurable)
return optionsutil.enableIfEquals(configurable, "text_wrap", 1)
end,
+ toggle = {S.LTR, S.RTL, S.TBRTL},
+ values = {0, 1, 2},
+ default_value = 0,
name_text_hold_callback = optionsutil.showValues,
help_text = _([[In reflow mode, sets the original text direction. This needs to be set to RTL to correctly extract and reflow RTL languages like Arabic or Hebrew.]]),
},
diff --git a/frontend/ui/data/optionsutil.lua b/frontend/ui/data/optionsutil.lua
index 7867b639e..76199fa6e 100644
--- a/frontend/ui/data/optionsutil.lua
+++ b/frontend/ui/data/optionsutil.lua
@@ -99,16 +99,19 @@ function optionsutil.showValues(configurable, option, prefix)
help_text = T("\n%1\n", option.help_text)
end
local text
+ local name_text = option.name_text_func
+ and option.name_text_func(configurable)
+ or option.name_text
if option.name_text_true_values and option.toggle and option.values then
if value_default then
- text = T(_("%1\n%2\nCurrent value: %3 (%4)\nDefault value: %5 (%6)"), option.name_text, help_text,
+ text = T(_("%1\n%2\nCurrent value: %3 (%4)\nDefault value: %5 (%6)"), name_text, help_text,
current, value_current, default, value_default)
else
- text = T(_("%1\n%2\nCurrent value: %3 (%4)\nDefault value: %5"), option.name_text, help_text,
+ text = T(_("%1\n%2\nCurrent value: %3 (%4)\nDefault value: %5"), name_text, help_text,
current, value_current, default)
end
else
- text = T(_("%1\n%2\nCurrent value: %3\nDefault value: %4"), option.name_text, help_text, current, default)
+ text = T(_("%1\n%2\nCurrent value: %3\nDefault value: %4"), name_text, help_text, current, default)
end
UIManager:show(InfoMessage:new{ text=text })
end
diff --git a/frontend/ui/widget/configdialog.lua b/frontend/ui/widget/configdialog.lua
index 08af59e58..6bdc2e598 100644
--- a/frontend/ui/widget/configdialog.lua
+++ b/frontend/ui/widget/configdialog.lua
@@ -112,6 +112,7 @@ function OptionIconItem:init()
}
self[1] = FrameContainer:new{
padding = 0,
+ padding_top = self.underline_padding,
padding_left = self.padding_left,
padding_right = self.padding_right,
bordersize = 0,
@@ -198,12 +199,14 @@ function ConfigOption:init()
local show = self.options[c].show
-- Prefer show_func over show if there's one
if self.options[c].show_func then
- show = self.options[c].show_func()
+ show = self.options[c].show_func(self.config.configurable, self.config.document)
end
if show ~= false and show_default then
local name_font_face = self.options[c].name_font_face and self.options[c].name_font_face or "cfont"
local name_font_size = self.options[c].name_font_size and self.options[c].name_font_size or default_name_font_size
- local text = self.options[c].name_text
+ local text = self.options[c].name_text_func
+ and self.options[c].name_text_func(self.config.configurable, self.config.document)
+ or self.options[c].name_text
local face = Font:getFace(name_font_face, name_font_size)
local txt_width = 0
if text ~= nil then
@@ -236,7 +239,7 @@ function ConfigOption:init()
local show = self.options[c].show
-- Prefer show_func over show if there's one
if self.options[c].show_func then
- show = self.options[c].show_func()
+ show = self.options[c].show_func(self.config.configurable, self.config.document)
end
if show ~= false and show_default then
local name_align = self.options[c].name_align_right and self.options[c].name_align_right or default_name_align_right
@@ -262,20 +265,22 @@ function ConfigOption:init()
local horizontal_group = HorizontalGroup:new{}
-- Deal with the name on the left
- if self.options[c].name_text then
+ local name_text = self.options[c].name_text_func
+ and self.options[c].name_text_func(self.config.configurable, self.config.document)
+ or self.options[c].name_text
+ if name_text then
-- the horizontal padding on the left will be ensured by the RightContainer
local name_widget_width = math.floor(name_align * Screen:getWidth())
-- We don't remove default_option_hpadding from name_text_max_width
-- to give more to text and avoid truncation: as it is right aligned,
-- the text can grow on the left, padding_small is enough.
local name_text_max_width = name_widget_width - 2*padding_small
- local text = self.options[c].name_text
local face = Font:getFace(name_font_face, name_font_size)
local option_name_container = RightContainer:new{
dimen = Geom:new{ w = name_widget_width, h = option_height},
}
local option_name = Button:new{
- text = text,
+ text = name_text,
max_width = name_text_max_width,
bordersize = 0,
face = face,
@@ -461,7 +466,7 @@ function ConfigOption:init()
option_items[d] = option_item
option_item.items = option_items
option_item.name = self.options[c].name
- option_item.name_text = self.options[c].name_text
+ option_item.name_text = name_text
option_item.item_text = self.options[c].item_text
option_item.values = self.options[c].values
option_item.args = self.options[c].args
@@ -476,21 +481,25 @@ function ConfigOption:init()
-- Icons (ex: columns, text align, with PDF)
if self.options[c].item_icons then
local items_count = #self.options[c].item_icons
- local first_item = OptionIconItem:new{
- icon = ImageWidget:new{
- file = self.options[c].item_icons[1]
- }
- }
- local max_item_spacing = (option_widget_width -
- first_item:getSize().w * items_count) / items_count
+ local icon_max_height = option_height
+ local icon_max_width = math.floor(option_widget_width / items_count)
+ local icon_size = math.min(icon_max_height, icon_max_width)
+ local max_item_spacing = (option_widget_width - icon_size * items_count) / items_count
local horizontal_half_padding = math.min(max_item_spacing, item_spacing_width) / 2
+ -- Our icons have a bottom padding that makes 10% to 20% of their height (5-9px in our 48px images)
+ -- We don't want the underline to be that far away from the image content,
+ -- so we use some negative padding to eat a bit on their padding.
+ local underline_padding = - math.floor(0.05 * icon_size)
for d = 1, #self.options[c].item_icons do
local option_item = OptionIconItem:new{
icon = ImageWidget:new{
file = self.options[c].item_icons[d],
dim = not enabled,
+ width = icon_size,
+ height = icon_size,
+ scale_factor = 0, -- scale to fit width and height
},
- underline_padding = -padding_button,
+ underline_padding = underline_padding,
padding_left = d > 1 and horizontal_half_padding,
padding_right = d < #self.options[c].item_icons and horizontal_half_padding,
color = d == current_item and (enabled and Blitbuffer.COLOR_BLACK or Blitbuffer.COLOR_DARK_GRAY) or Blitbuffer.COLOR_WHITE,
@@ -499,7 +508,7 @@ function ConfigOption:init()
option_items[d] = option_item
option_item.items = option_items
option_item.name = self.options[c].name
- option_item.name_text = self.options[c].name_text
+ option_item.name_text = name_text
option_item.values = self.options[c].values
option_item.args = self.options[c].args
option_item.event = self.options[c].event
@@ -528,7 +537,7 @@ function ConfigOption:init()
font_face = item_font_face,
font_size = item_font_size,
name = self.options[c].name,
- name_text = self.options[c].name_text,
+ name_text = name_text,
toggle = self.options[c].toggle,
alternate = self.options[c].alternate,
values = self.options[c].values,
@@ -545,7 +554,7 @@ function ConfigOption:init()
self.options[c].more_options_param.show_true_value_func = self.options[c].show_true_value_func
end
self.config:onConfigMoreChoose(self.options[c].values, self.options[c].name,
- self.options[c].event, arg, self.options[c].name_text, self.options[c].delay_repaint, self.options[c].more_options_param)
+ self.options[c].event, arg, name_text, self.options[c].delay_repaint, self.options[c].more_options_param)
end
end
}
@@ -573,10 +582,11 @@ function ConfigOption:init()
callback = function(arg)
if arg == "-" or arg == "+" then
self.config:onConfigFineTuneChoose(self.options[c].values, self.options[c].name,
- self.options[c].event, self.options[c].args, self.options[c].events, arg, self.options[c].delay_repaint)
+ self.options[c].event, self.options[c].args, self.options[c].events, arg, self.options[c].delay_repaint,
+ self.options[c].fine_tune_param)
elseif arg == "⋮" then
self.config:onConfigMoreChoose(self.options[c].values, self.options[c].name,
- self.options[c].event, arg, self.options[c].name_text, self.options[c].delay_repaint, self.options[c].more_options_param)
+ self.options[c].event, arg, name_text, self.options[c].delay_repaint, self.options[c].more_options_param)
else
self.config:onConfigChoose(self.options[c].values, self.options[c].name,
self.options[c].event, self.options[c].args, self.options[c].events, arg, self.options[c].delay_repaint)
@@ -587,16 +597,17 @@ function ConfigOption:init()
end,
hold_callback = function(arg)
if arg == "-" or arg == "+" then
- self.config:onMakeFineTuneDefault(self.options[c].name, self.options[c].name_text, self.options[c].values,
+ self.config:onMakeFineTuneDefault(self.options[c].name, name_text, self.options[c].values,
self.options[c].labels or self.options[c].args, arg)
elseif arg ~= "⋮" then
- self.config:onMakeDefault(self.options[c].name, self.options[c].name_text, self.options[c].values,
+ self.config:onMakeDefault(self.options[c].name, name_text, self.options[c].values,
self.options[c].labels or self.options[c].args, arg)
end
end,
show_parrent = self.config,
enabled = enabled,
fine_tune = self.options[c].fine_tune,
+ fine_tune_param = self.options[c].fine_tune_param,
more_options = self.options[c].more_options,
more_options_param = self.options[c].more_options_param,
}
@@ -963,7 +974,7 @@ function ConfigDialog:onConfigChoose(values, name, event, args, events, position
end
-- Tweaked variant used with the fine_tune variant of buttonprogress (direction can only be "-" or "+")
-function ConfigDialog:onConfigFineTuneChoose(values, name, event, args, events, direction, delay_repaint)
+function ConfigDialog:onConfigFineTuneChoose(values, name, event, args, events, direction, delay_repaint, params)
UIManager:tickAfterNext(function()
-- Repainting may be delayed depending on options
local refresh_dialog_func = function()
@@ -994,6 +1005,7 @@ function ConfigDialog:onConfigFineTuneChoose(values, name, event, args, events,
end
if values then
local value
+ local step = params and params.value_step or 1
if direction == "-" then
value = self.configurable[name] or values[1]
if type(value) == "table" then
@@ -1001,7 +1013,7 @@ function ConfigDialog:onConfigFineTuneChoose(values, name, event, args, events,
-- to one of the original preset values tables
local updated = {}
for i=1, #value do
- local v = value[i] - 1
+ local v = value[i] - step
if v < 0 then
v = 0
end
@@ -1009,7 +1021,7 @@ function ConfigDialog:onConfigFineTuneChoose(values, name, event, args, events,
end
value = updated
else
- value = value - 1
+ value = value - step
if value < 0 then
value = 0
end
@@ -1019,11 +1031,11 @@ function ConfigDialog:onConfigFineTuneChoose(values, name, event, args, events,
if type(value) == "table" then
local updated = {}
for i=1, #value do
- table.insert(updated, value[i] + 1)
+ table.insert(updated, value[i] + step)
end
value = updated
else
- value = value + 1
+ value = value + step
end
end
self:onConfigChoice(name, value)
diff --git a/frontend/ui/widget/numberpickerwidget.lua b/frontend/ui/widget/numberpickerwidget.lua
index 09973cdef..f34eae54f 100644
--- a/frontend/ui/widget/numberpickerwidget.lua
+++ b/frontend/ui/widget/numberpickerwidget.lua
@@ -129,7 +129,7 @@ function NumberPickerWidget:paintWidget()
callback_input = function()
input_dialog = InputDialog:new{
title = _("Enter number"),
- input = self.value,
+ input = value,
input_type = "number",
buttons = {
{
diff --git a/frontend/util.lua b/frontend/util.lua
index 11f148513..6407f3b61 100644
--- a/frontend/util.lua
+++ b/frontend/util.lua
@@ -339,7 +339,7 @@ function util.arrayAppend(t1, t2)
end
end
--- Reverse array elements in-place in table t
+--- Reverse array elements in-place in table t
---- @param t Lua table
function util.arrayReverse(t)
local i, j = 1, #t
@@ -350,6 +350,22 @@ function util.arrayReverse(t)
end
end
+--- Test whether t contains a value equal to v
+--- (or such a value that callback returns true),
+--- and if so, return the index.
+---- @param t Lua table
+---- @param v
+---- @function callback(v1, v2)
+function util.arrayContains(t, v, cb)
+ cb = cb or function(v1, v2) return v1 == v2 end
+ for _k, _v in ipairs(t) do
+ if cb(_v, v) then
+ return _k
+ end
+ end
+ return false
+end
+
-- Merge t2 into t1, overwriting existing elements if they already exist
-- Probably not safe with nested tables (c.f., https://stackoverflow.com/q/1283388)
---- @param t1 Lua table
diff --git a/l10n b/l10n
index 6d0396d8c..718d53ce4 160000
--- a/l10n
+++ b/l10n
@@ -1 +1 @@
-Subproject commit 6d0396d8c100024e6c11c01720daee8443877241
+Subproject commit 718d53ce4270d72b6421d0f7acc25ba3c0d348b0
diff --git a/resources/icons/README.md b/resources/icons/README.md
index 98992e9f6..ae9545937 100644
--- a/resources/icons/README.md
+++ b/resources/icons/README.md
@@ -9,3 +9,15 @@ Start from an RGB copy of the image if you end up with a 256c or sRGB PNG (check
See https://www.mobileread.com/forums/showpost.php?p=3728291&postcount=17 for more details ;).
+
+Zoom direction icons are generated from direction.LRBT.png with:
+
+```bash
+convert direction.LRBT.png -rotate 90 direction.TBLR.png
+convert direction.LRBT.png -rotate 180 direction.RLTB.png
+convert direction.LRBT.png -rotate -90 direction.BTRL.png
+convert direction.BTRL.png -flop direction.BTLR.png
+convert direction.LRBT.png -flop direction.RLBT.png
+convert direction.RLTB.png -flop direction.LRTB.png
+convert direction.TBLR.png -flop direction.TBRL.png
+```
diff --git a/resources/icons/appbar.magnify.zoom.png b/resources/icons/appbar.magnify.zoom.png
new file mode 100644
index 000000000..adb9c2276
Binary files /dev/null and b/resources/icons/appbar.magnify.zoom.png differ
diff --git a/resources/icons/appbar.page.fit.png b/resources/icons/appbar.page.fit.png
new file mode 100644
index 000000000..7928194d4
Binary files /dev/null and b/resources/icons/appbar.page.fit.png differ
diff --git a/resources/icons/direction.BTLR.png b/resources/icons/direction.BTLR.png
new file mode 100644
index 000000000..9c77d3a5a
Binary files /dev/null and b/resources/icons/direction.BTLR.png differ
diff --git a/resources/icons/direction.BTRL.png b/resources/icons/direction.BTRL.png
new file mode 100644
index 000000000..356acec96
Binary files /dev/null and b/resources/icons/direction.BTRL.png differ
diff --git a/resources/icons/direction.LRBT.png b/resources/icons/direction.LRBT.png
new file mode 100644
index 000000000..6d0fca75b
Binary files /dev/null and b/resources/icons/direction.LRBT.png differ
diff --git a/resources/icons/direction.LRTB.png b/resources/icons/direction.LRTB.png
new file mode 100644
index 000000000..a9f6ba59a
Binary files /dev/null and b/resources/icons/direction.LRTB.png differ
diff --git a/resources/icons/direction.RLBT.png b/resources/icons/direction.RLBT.png
new file mode 100644
index 000000000..da9938b3d
Binary files /dev/null and b/resources/icons/direction.RLBT.png differ
diff --git a/resources/icons/direction.RLTB.png b/resources/icons/direction.RLTB.png
new file mode 100644
index 000000000..149a3c09e
Binary files /dev/null and b/resources/icons/direction.RLTB.png differ
diff --git a/resources/icons/direction.TBLR.png b/resources/icons/direction.TBLR.png
new file mode 100644
index 000000000..466f45fb1
Binary files /dev/null and b/resources/icons/direction.TBLR.png differ
diff --git a/resources/icons/direction.TBRL.png b/resources/icons/direction.TBRL.png
new file mode 100644
index 000000000..989851d9b
Binary files /dev/null and b/resources/icons/direction.TBRL.png differ
diff --git a/resources/icons/src/appbar.magnify.zoom.svg b/resources/icons/src/appbar.magnify.zoom.svg
new file mode 100644
index 000000000..5e97b84e2
--- /dev/null
+++ b/resources/icons/src/appbar.magnify.zoom.svg
@@ -0,0 +1,53 @@
+
+
diff --git a/resources/icons/src/appbar.page.fit.svg b/resources/icons/src/appbar.page.fit.svg
new file mode 100644
index 000000000..1fcbf6f95
--- /dev/null
+++ b/resources/icons/src/appbar.page.fit.svg
@@ -0,0 +1,77 @@
+
+
+
\ No newline at end of file
diff --git a/resources/icons/src/direction.LRBT.svg b/resources/icons/src/direction.LRBT.svg
new file mode 100644
index 000000000..519cfcbfa
--- /dev/null
+++ b/resources/icons/src/direction.LRBT.svg
@@ -0,0 +1,84 @@
+
+
+
\ No newline at end of file
diff --git a/resources/icons/src/zoom.content.svg b/resources/icons/src/zoom.content.svg
new file mode 100644
index 000000000..9e0780afd
--- /dev/null
+++ b/resources/icons/src/zoom.content.svg
@@ -0,0 +1,324 @@
+
+
diff --git a/resources/icons/src/zoom.direction.column.svg b/resources/icons/src/zoom.direction.column.svg
new file mode 100644
index 000000000..d6d491fb4
--- /dev/null
+++ b/resources/icons/src/zoom.direction.column.svg
@@ -0,0 +1,266 @@
+
+
diff --git a/resources/icons/src/zoom.direction.row.svg b/resources/icons/src/zoom.direction.row.svg
new file mode 100644
index 000000000..5429b62e5
--- /dev/null
+++ b/resources/icons/src/zoom.direction.row.svg
@@ -0,0 +1,266 @@
+
+
diff --git a/resources/icons/src/zoom.manual.svg b/resources/icons/src/zoom.manual.svg
new file mode 100644
index 000000000..31d8bdd19
--- /dev/null
+++ b/resources/icons/src/zoom.manual.svg
@@ -0,0 +1,178 @@
+
+
diff --git a/resources/icons/src/zoom.page.svg b/resources/icons/src/zoom.page.svg
new file mode 100644
index 000000000..f0f2bda26
--- /dev/null
+++ b/resources/icons/src/zoom.page.svg
@@ -0,0 +1,319 @@
+
+
diff --git a/resources/icons/zoom.content.png b/resources/icons/zoom.content.png
new file mode 100644
index 000000000..4cf2c303b
Binary files /dev/null and b/resources/icons/zoom.content.png differ
diff --git a/resources/icons/zoom.direction.column.png b/resources/icons/zoom.direction.column.png
new file mode 100644
index 000000000..9d9d3eab2
Binary files /dev/null and b/resources/icons/zoom.direction.column.png differ
diff --git a/resources/icons/zoom.direction.row.png b/resources/icons/zoom.direction.row.png
new file mode 100644
index 000000000..3da7263fe
Binary files /dev/null and b/resources/icons/zoom.direction.row.png differ
diff --git a/resources/icons/zoom.manual.png b/resources/icons/zoom.manual.png
new file mode 100644
index 000000000..5a8dd30b6
Binary files /dev/null and b/resources/icons/zoom.manual.png differ
diff --git a/resources/icons/zoom.page.png b/resources/icons/zoom.page.png
new file mode 100644
index 000000000..5b6249348
Binary files /dev/null and b/resources/icons/zoom.page.png differ