From ae1c489a0fb94317bef1fa5a60b4d320af4f8ea6 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Mon, 3 Dec 2012 13:48:41 +0800 Subject: [PATCH] implement full pageturn by viewport for all modes * add notIntersectWith method for Geom * add math.roundAwayFromZero in geometry.lua * Readerview:recalculate now signals ViewRecalculate event. For now, this event is only usefull for ReaderPaging --- frontend/ui/geometry.lua | 30 +++++++++++++++ frontend/ui/reader/readerpaging.lua | 57 +++++++++++++++++++++++++++- frontend/ui/reader/readerview.lua | 3 +- frontend/ui/reader/readerzooming.lua | 33 ++++++++++------ 4 files changed, 108 insertions(+), 15 deletions(-) diff --git a/frontend/ui/geometry.lua b/frontend/ui/geometry.lua index dfbace15d..b50a07d85 100644 --- a/frontend/ui/geometry.lua +++ b/frontend/ui/geometry.lua @@ -137,6 +137,19 @@ function Geom:intersect(rect_b) return intersected end +--[[ +return true if self does not share any area with rect_b +]]-- +function Geom:notIntersectWith(rect_b) + if (self.x >= (rect_b.x + rect_b.w)) + or (self.y >= (rect_b.y + rect_b.h)) + or (rect_b.x >= (self.x + self.w)) + or (rect_b.y >= (self.y + self.h)) then + return true + end + return false +end + --[[ set size of dimension or rectangle to size of given dimension/rectangle ]]-- @@ -245,3 +258,20 @@ function Geom:offsetWithin(rect_b, dx, dy) self.y = rect_b.y + rect_b.h - self.h end end + + + + +--[[ +Simple math helper function +]]-- + +function math.roundAwayFromZero(num) + if num > 0 then + return math.ceil(num) + else + return math.floor(num) + end +end + + diff --git a/frontend/ui/reader/readerpaging.lua b/frontend/ui/reader/readerpaging.lua index c41481314..828ab6be1 100644 --- a/frontend/ui/reader/readerpaging.lua +++ b/frontend/ui/reader/readerpaging.lua @@ -1,6 +1,8 @@ ReaderPaging = InputContainer:new{ current_page = 0, - number_of_pages = 0 + number_of_pages = 0, + visible_area = nil, + page_area = nil, } function ReaderPaging:init() @@ -85,10 +87,21 @@ function ReaderPaging:onReadSettings(config) self:gotoPage(config:readSetting("last_page") or 1) end +function ReaderPaging:onZoomModeUpdate(new_mode) + -- we need to remember zoom mode to handle page turn event + self.zoom_mode = new_mode +end + function ReaderPaging:onPageUpdate(new_page_no) self.current_page = new_page_no end +function ReaderPaging:onViewRecalculate(visible_area, page_area) + -- we need to remember areas to handle page turn event + self.visible_area = visible_area + self.page_area = page_area +end + function ReaderPaging:onGotoPercent(percent) DEBUG("goto document offset in percent:", percent) local dest = math.floor(self.number_of_pages * percent / 100) @@ -102,7 +115,47 @@ end function ReaderPaging:onGotoPageRel(diff) DEBUG("goto relative page:", diff) - self:gotoPage(self.current_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 + x_pan_off = self.visible_area.w * diff + else + -- 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 + else + x_pan_off = self.visible_area.w * diff + end + end + + -- adjust offset to help with page turn decision + 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 + self:gotoPage(self.current_page + diff) + -- if we are going back to previous page, reset + -- view 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 + -- fit new view area into page area + new_va:offsetWithin(self.page_area, 0, 0) + self.view:PanningUpdate( + new_va.x - self.visible_area.x, + new_va.y - self.visible_area.y) + -- update self.visible_area + self.visible_area = new_va + end + return true end diff --git a/frontend/ui/reader/readerview.lua b/frontend/ui/reader/readerview.lua index 4e8a01eba..e0662c471 100644 --- a/frontend/ui/reader/readerview.lua +++ b/frontend/ui/reader/readerview.lua @@ -46,7 +46,6 @@ function ReaderView:paintTo(bb, x, y) self.state.zoom, self.state.rotation, self.render_mode) - self:recalculate() else self.ui.document:drawCurrentView( bb, @@ -81,6 +80,8 @@ function ReaderView:recalculate() else self.visible_area:setSizeTo(self.dimen) end + self.ui:handleEvent( + Event:new("ViewRecalculate", self.visible_area, self.page_area)) -- flag a repaint so self:paintTo will be called UIManager:setDirty(self.dialog) end diff --git a/frontend/ui/reader/readerzooming.lua b/frontend/ui/reader/readerzooming.lua index b2a42f1a7..f2324d175 100644 --- a/frontend/ui/reader/readerzooming.lua +++ b/frontend/ui/reader/readerzooming.lua @@ -2,35 +2,43 @@ ReaderZooming = InputContainer:new{ key_events = { ZoomIn = { { "Shift", Input.group.PgFwd }, - doc = "zoom in", event = "Zoom", args = "in" + doc = "zoom in", + event = "Zoom", args = "in" }, ZoomOut = { { "Shift", Input.group.PgBack }, - doc = "zoom out", event = "Zoom", args = "out" + doc = "zoom out", + event = "Zoom", args = "out" }, ZoomToFitPage = { { "A" }, - doc = "zoom to fit page", event = "SetZoomMode", args = "page" + doc = "zoom to fit page", + event = "SetZoomMode", args = "page" }, ZoomToFitContent = { { "Shift", "A" }, - doc = "zoom to fit content", event = "SetZoomMode", args = "content" + doc = "zoom to fit content", + event = "SetZoomMode", args = "content" }, ZoomToFitPageWidth = { { "S" }, - doc = "zoom to fit page width", event = "SetZoomMode", args = "pagewidth" + doc = "zoom to fit page width", + event = "SetZoomMode", args = "pagewidth" }, ZoomToFitContentWidth = { { "Shift", "S" }, - doc = "zoom to fit content width", event = "SetZoomMode", args = "contentwidth" + doc = "zoom to fit content width", + event = "SetZoomMode", args = "contentwidth" }, ZoomToFitPageHeight = { { "D" }, - doc = "zoom to fit page height", event = "SetZoomMode", args = "pageheight" + doc = "zoom to fit page height", + event = "SetZoomMode", args = "pageheight" }, ZoomToFitContentHeight = { { "Shift", "D" }, - doc = "zoom to fit content height", event = "SetZoomMode", args = "contentheight" + doc = "zoom to fit content height", + event = "SetZoomMode", args = "contentheight" }, }, zoom = 1.0, @@ -103,11 +111,12 @@ function ReaderZooming:onZoom(direction) return true end -function ReaderZooming:onSetZoomMode(what) - if self.zoom_mode ~= what then - DEBUG("setting zoom mode to", what) - self.zoom_mode = what +function ReaderZooming:onSetZoomMode(new_mode) + if self.zoom_mode ~= new_mode then + DEBUG("setting zoom mode to", new_mode) + self.zoom_mode = new_mode self:setZoom() + self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode)) end return true end