From 397d88e41e1e0a1c8439f0d2dbf464f04b00598f Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Thu, 10 Jan 2013 15:31:51 -0500 Subject: [PATCH 01/10] Merge branches 'new_ui_code' and 'new_ui_code' of github.com:houqp/kindlepdfviewer into new_ui_code From 9468b504c19afe63857c70f0eaafa32fbd539a3e Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Sun, 3 Feb 2013 01:43:47 +0800 Subject: [PATCH 02/10] add close button toggle for menu widget --- frontend/ui/menu.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/ui/menu.lua b/frontend/ui/menu.lua index 63e6be7f5..3c23623fe 100644 --- a/frontend/ui/menu.lua +++ b/frontend/ui/menu.lua @@ -226,6 +226,8 @@ Menu = FocusManager:new{ -- set this to true to not paint as popup menu is_borderless = false, + -- set this to true to add close button + has_close_button = true, -- close_callback is a function, which is executed when menu is closed -- it is usually set by the widget which creates the menu close_callback = nil @@ -307,10 +309,12 @@ function Menu:init() -- start to set up input event callback -- ------------------------------------------ if Device:isTouchDevice() then - table.insert(self.title_bar, - MenuCloseButton:new{ - menu = self, - }) + if self.has_close_button then + table.insert(self.title_bar, + MenuCloseButton:new{ + menu = self, + }) + end self.ges_events.TapCloseAllMenus = { GestureRange:new{ ges = "tap", From 22c30439598fb96b5ae4a3a01fbabeaa24ff32d0 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Sun, 3 Feb 2013 03:35:25 +0800 Subject: [PATCH 03/10] add calling item.callback() as default onMenuChoice action --- frontend/ui/menu.lua | 8 ++++++-- frontend/ui/reader/readerfont.lua | 5 ----- frontend/ui/reader/readermenu.lua | 5 ----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/frontend/ui/menu.lua b/frontend/ui/menu.lua index 3c23623fe..becf9a51a 100644 --- a/frontend/ui/menu.lua +++ b/frontend/ui/menu.lua @@ -480,9 +480,13 @@ function Menu:onMenuSelect(item) end --[[ -override this function to handle the choice -]]-- + default to call item callback + override this function to handle the choice +--]] function Menu:onMenuChoice(item) + if item.callback then + item.callback() + end return true end diff --git a/frontend/ui/reader/readerfont.lua b/frontend/ui/reader/readerfont.lua index 33c6f5a3d..7443a2bcb 100644 --- a/frontend/ui/reader/readerfont.lua +++ b/frontend/ui/reader/readerfont.lua @@ -99,11 +99,6 @@ function ReaderFont:onShowFontMenu() item_table = self.face_table, width = Screen:getWidth() - 100, } - function main_menu:onMenuChoice(item) - if item.callback then - item.callback() - end - end -- build container local menu_container = CenterContainer:new{ main_menu, diff --git a/frontend/ui/reader/readermenu.lua b/frontend/ui/reader/readermenu.lua index 810fb4b0d..787af9163 100644 --- a/frontend/ui/reader/readermenu.lua +++ b/frontend/ui/reader/readermenu.lua @@ -73,11 +73,6 @@ function ReaderMenu:onShowMenu() item_table = self.item_table, width = Screen:getWidth() - 100, } - function main_menu:onMenuChoice(item) - if item.callback then - item.callback() - end - end local menu_container = CenterContainer:new{ ignore = "height", From 2090dabf22105e2e02172ab459bb06470be07b95 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Sun, 3 Feb 2013 03:41:35 +0800 Subject: [PATCH 04/10] add menu to FileManager --- frontend/ui/reader/readermenu.lua | 2 +- reader.lua | 72 ++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/frontend/ui/reader/readermenu.lua b/frontend/ui/reader/readermenu.lua index 787af9163..48bc18940 100644 --- a/frontend/ui/reader/readermenu.lua +++ b/frontend/ui/reader/readermenu.lua @@ -55,7 +55,7 @@ function ReaderMenu:setUpdateItemTable() end table.insert(self.item_table, { - text = "Return to file browser", + text = "Return to file manager", callback = function() UIManager:close(self.menu_container) self.ui:onClose() diff --git a/reader.lua b/reader.lua index cad1a7d1f..90acbbeac 100755 --- a/reader.lua +++ b/reader.lua @@ -5,8 +5,62 @@ require "ui/ui" require "ui/readerui" require "ui/filechooser" require "ui/infomessage" +require "ui/button" require "document/document" + + +HomeMenu = InputContainer:new{ + item_table = {}, + ges_events = { + TapShowMenu = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = 25, + } + } + }, + }, +} + +function HomeMenu:setUpdateItemTable() + table.insert(self.item_table, { + text = "Exit", + callback = function() + os.exit(0) + end + }) +end + +function HomeMenu:onTapShowMenu() + if #self.item_table == 0 then + self:setUpdateItemTable() + end + + local home_menu = Menu:new{ + title = "Home menu", + item_table = self.item_table, + width = Screen:getWidth() - 100, + } + + local menu_container = CenterContainer:new{ + ignore = "height", + dimen = Screen:getSize(), + home_menu, + } + home_menu.close_callback = function () + UIManager:close(menu_container) + end + + UIManager:show(menu_container) + + return true +end + + function showReader(file, pass) local document = DocumentRegistry:openDocument(file) if not document then @@ -23,11 +77,14 @@ function showReader(file, pass) UIManager:show(reader) end -function showFileManager(path) +function showHomePage(path) local FileManager = FileChooser:new{ + title = "FileManager", path = path, - dimen = Screen:getSize(), + width = Screen:getWidth(), + height = Screen:getHeight(), is_borderless = true, + has_close_button = false, filter = function(filename) if DocumentRegistry:getProvider(filename) then return true @@ -35,17 +92,22 @@ function showFileManager(path) end } + local HomePage = InputContainer:new{ + FileManager, + HomeMenu, + } + function FileManager:onFileSelect(file) showReader(file) return true end function FileManager:onClose() - UIManager:quit() + --UIManager:quit() return true end - UIManager:show(FileManager) + UIManager:show(HomePage) end @@ -106,7 +168,7 @@ Screen.native_rotation_mode = Screen.cur_rotation_mode if ARGV[argidx] then if lfs.attributes(ARGV[argidx], "mode") == "directory" then - showFileManager(ARGV[argidx]) + showHomePage(ARGV[argidx]) elseif lfs.attributes(ARGV[argidx], "mode") == "file" then showReader(ARGV[argidx]) end From a1aa41136c89c4ef416e4c01cb998efb4cc9560c Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 3 Feb 2013 04:42:59 +0800 Subject: [PATCH 05/10] add manual page crop for pdf/djvu documents --- frontend/document/credocument.lua | 2 +- frontend/document/document.lua | 55 +++++-- frontend/document/koptinterface.lua | 15 +- frontend/ui/config.lua | 56 ++++++-- frontend/ui/geometry.lua | 8 +- frontend/ui/reader/readerconfig.lua | 25 +--- frontend/ui/reader/readercropping.lua | 198 ++++++++++++++++++++++++++ frontend/ui/reader/readerview.lua | 2 +- frontend/ui/reader/readerzooming.lua | 5 +- frontend/ui/readerui.lua | 9 ++ 10 files changed, 328 insertions(+), 47 deletions(-) create mode 100644 frontend/ui/reader/readercropping.lua diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index f1d2f469c..f30f333c9 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -26,7 +26,7 @@ CreOptions = { item_align_center = 1.0, spacing = Screen:getWidth()*0.03, item_font_size = {18, 20, 22, 24, 29, 33, 39, 44}, - values = {18, 20, 22, 24, 29, 33, 39, 44}, + args = {18, 20, 22, 24, 29, 33, 39, 44}, default_value = 1, event = "SetFontSize", }, diff --git a/frontend/document/document.lua b/frontend/document/document.lua index a834d74fe..f453bda95 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -47,13 +47,16 @@ Document = { number_of_pages = 0, -- if not pageable, length of the document in pixels doc_height = 0, - + -- other metadata title = "", author = "", date = "" }, - + + -- override bbox from orignal page's getUsedBBox + bbox = {}, + -- flag to show whether the document was opened successfully is_open = false, error_message = nil, @@ -123,20 +126,56 @@ function Document:getPageDimensions(pageno, zoom, rotation) return native_dimen end +function Document:oddEven(number) + if number % 2 == 1 then + return "odd" + else + return "even" + end +end + +function Document:getPageBBox(pageno) + local bbox = self.bbox[pageno] -- exact + local oddEven = self:oddEven(pageno) + if bbox ~= nil then + DEBUG("bbox from", pageno) + else + bbox = self.bbox[oddEven] -- odd/even + end + if bbox ~= nil then -- last used up to this page + DEBUG("bbox from", oddEven) + else + for i = 0,pageno do + bbox = self.bbox[ pageno - i ] + if bbox ~= nil then + DEBUG("bbox from", pageno - i) + break + end + end + end + if bbox == nil then -- fallback bbox + bbox = self:getUsedBBox(pageno) + DEBUG("bbox from ORIGINAL page") + end + DEBUG("final bbox", bbox) + return bbox +end + --[[ This method returns pagesize if bbox is corrupted --]] function Document:getUsedBBoxDimensions(pageno, zoom, rotation) - ubbox = self:getUsedBBox(pageno) - if ubbox.x0 < 0 or ubbox.y0 < 0 or ubbox.x1 < 0 or ubbox.y1 < 0 then + local bbox = self:getPageBBox(pageno) + local ubbox_dimen = nil + if bbox.x0 < 0 or bbox.y0 < 0 or bbox.x1 < 0 or bbox.y1 < 0 then -- if document's bbox info is corrupted, we use the page size ubbox_dimen = self:getPageDimensions(pageno, zoom, rotation) else ubbox_dimen = Geom:new{ - x = ubbox.x0, - y = ubbox.y0, - w = ubbox.x1 - ubbox.x0, - h = ubbox.y1 - ubbox.y0, + x = bbox.x0, + y = bbox.y0, + w = bbox.x1 - bbox.x0, + h = bbox.y1 - bbox.y0, } if zoom ~= 1 then ubbox_dimen:transformByScale(zoom) diff --git a/frontend/document/koptinterface.lua b/frontend/document/koptinterface.lua index a98fb354d..9f12e7530 100644 --- a/frontend/document/koptinterface.lua +++ b/frontend/document/koptinterface.lua @@ -39,8 +39,11 @@ KoptOptions = { name="trim_page", name_text = "Page Crop", toggle = {"auto", "manual"}, + alternate = false, values = {1, 0}, default_value = 1, + event = "PageCrop", + args = {"auto", "manual"}, } } }, @@ -115,7 +118,15 @@ KoptOptions = { toggle = {"On", "Off"}, values = {1, 0}, default_value = 0, - event = "RedrawCurrentPage", + events = { + { + event = "RedrawCurrentPage", + }, + { + event = "SetZoomMode", + args = {"page", nil}, + }, + } }, { name="screen_rotation", @@ -185,7 +196,7 @@ function KoptInterface:getKOPTContext(doc, pageno) kc:setDefectSize(doc.configurable.defect_size) kc:setLineSpacing(doc.configurable.line_spacing) kc:setWordSpacing(doc.configurable.word_spacing) - local bbox = doc:getUsedBBox(pageno) + local bbox = doc:getPageBBox(pageno) kc:setBBox(bbox.x0, bbox.y0, bbox.x1, bbox.y1) return kc end diff --git a/frontend/ui/config.lua b/frontend/ui/config.lua index c8f797dcb..aaae3f12b 100644 --- a/frontend/ui/config.lua +++ b/frontend/ui/config.lua @@ -88,12 +88,22 @@ function OptionTextItem:onTapSelect() self[1].color = 15 local option_value = nil local option_arg = nil - if type(self.values) == "table" then + if self.values then + self.values = self.values or {} option_value = self.values[self.current_item] - self.config:onConfigChoice(self.name, option_value, self.event) - elseif type(self.args) == "table" then + self.config:onConfigChoice(self.name, option_value) + end + if self.event then + self.args = self.args or {} option_arg = self.args[self.current_item] - self.config:onConfigChoice(self.name, option_arg, self.event) + self.config:onConfigEvent(self.event, option_arg) + end + if self.events then + for i=0,#self.events do + self.events[i].args = self.events[i].args or {} + option_arg = self.events[i].args[self.current_item] + self.config:onConfigEvent(self.events[i].event, option_arg) + end end UIManager.repaint_all = true return true @@ -234,7 +244,7 @@ function ToggleSwitch:setPosition(position) end function ToggleSwitch:togglePosition(position) - if self.n_pos == 2 then + if self.n_pos == 2 and self.alternate ~= false then self.position = (self.position+1)%self.n_pos self.position = self.position == 0 and self.n_pos or self.position else @@ -248,12 +258,22 @@ function ToggleSwitch:onTapSelect(position) self:togglePosition(position) local option_value = nil local option_arg = nil - if type(self.values) == "table" then + if self.values then + self.values = self.values or {} option_value = self.values[self.position] - self.config:onConfigChoice(self.name, option_value, self.event) - elseif type(self.args) == "table" then + self.config:onConfigChoice(self.name, option_value) + end + if self.event then + self.args = self.args or {} option_arg = self.args[self.position] - self.config:onConfigChoice(self.name, option_arg, self.event) + self.config:onConfigEvent(self.event, option_arg) + end + if self.events then + for i=1,#self.events do + self.events[i].args = self.events[i].args or {} + option_arg = self.events[i].args[self.position] + self.config:onConfigEvent(self.events[i].event, option_arg) + end end UIManager.repaint_all = true end @@ -319,6 +339,7 @@ function ConfigOption:init() if self.options[c].name then if self.options[c].values then local val = self.config.configurable[self.options[c].name] + DEBUG("val", val) local min_diff = math.abs(val - self.options[c].values[1]) local diff = nil for index, val_ in pairs(self.options[c].values) do @@ -384,9 +405,11 @@ function ConfigOption:init() local switch = ToggleSwitch:new{ name = self.options[c].name, toggle = self.options[c].toggle, + alternate = self.options[c].alternate, values = self.options[c].values, args = self.options[c].args, event = self.options[c].event, + events = self.options[c].events, config = self.config, } local position = current_item @@ -552,7 +575,18 @@ function ConfigDialog:onShowConfigPanel(index) return true end -function ConfigDialog:onCloseMenu() +function ConfigDialog:onConfigChoice(option_name, option_value) + DEBUG("config option value", option_name, option_value) + self.configurable[option_name] = option_value +end + +function ConfigDialog:onConfigEvent(option_event, option_arg) + DEBUG("config option event", option_event, option_arg) + self.ui:handleEvent(Event:new(option_event, option_arg)) +end + +function ConfigDialog:closeDialog() + DEBUG("closing config dialog") UIManager:close(self) if self.close_callback then self.close_callback() @@ -562,7 +596,7 @@ end function ConfigDialog:onTapCloseMenu(arg, ges_ev) if ges_ev.pos:notIntersectWith(self.dialog_dimen) then - self:onCloseMenu() + self:closeDialog() return true end end diff --git a/frontend/ui/geometry.lua b/frontend/ui/geometry.lua index 3eefdbd75..497100c6e 100644 --- a/frontend/ui/geometry.lua +++ b/frontend/ui/geometry.lua @@ -259,8 +259,12 @@ function Geom:offsetWithin(rect_b, dx, dy) end end - - +--[[ +return the Euclidean distance between two geoms +]]-- +function Geom:distance(geom) + return math.sqrt(math.pow(self.x - geom.x, 2) + math.pow(self.y - geom.y, 2)) +end --[[ Simple math helper function diff --git a/frontend/ui/reader/readerconfig.lua b/frontend/ui/reader/readerconfig.lua index 2eed6226f..6d536a60d 100644 --- a/frontend/ui/reader/readerconfig.lua +++ b/frontend/ui/reader/readerconfig.lua @@ -72,31 +72,14 @@ function ReaderConfig:init() end function ReaderConfig:onShowConfigMenu() - local config_dialog = ConfigDialog:new{ + self.config_dialog = ConfigDialog:new{ dimen = self.dimen:copy(), ui = self.ui, configurable = self.configurable, config_options = self.options, } - function config_dialog:onConfigChoice(option_name, option_value, event) - self.configurable[option_name] = option_value - if event then - self.ui:handleEvent(Event:new(event, option_value)) - end - end - - local dialog_container = CenterContainer:new{ - config_dialog, - dimen = self.dimen:copy(), - } - config_dialog.close_callback = function () - UIManager:close(menu_container) - end - - self.dialog_container = dialog_container - - UIManager:show(config_dialog) + UIManager:show(self.config_dialog) return true end @@ -111,6 +94,10 @@ function ReaderConfig:onSetDimensions(dimen) self:init() end +function ReaderConfig:onCloseConfig() + self.config_dialog:closeDialog() +end + function ReaderConfig:onReadSettings(config) self.configurable:loadSettings(config, self.options.prefix..'_') end diff --git a/frontend/ui/reader/readercropping.lua b/frontend/ui/reader/readercropping.lua new file mode 100644 index 000000000..66d49b2f0 --- /dev/null +++ b/frontend/ui/reader/readercropping.lua @@ -0,0 +1,198 @@ +--[[ +BBoxWidget shows a bbox for page cropping +]] +BBoxWidget = InputContainer:new{ + page_bbox = nil, + screen_bbox = nil, + linesize = 2, +} + +function BBoxWidget:getSize() + return Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } +end + +function BBoxWidget:paintTo(bb, x, y) + self.screen_bbox = self.screen_bbox or self:page_to_screen() + local bbox = self.screen_bbox + -- upper_left + bb:invertRect(bbox.x0 + self.linesize, bbox.y0, bbox.x1 - bbox.x0, self.linesize) + bb:invertRect(bbox.x0, bbox.y0, self.linesize, bbox.y1 - bbox.y0 + self.linesize) + -- bottom_right + bb:invertRect(bbox.x0 + self.linesize, bbox.y1, bbox.x1 - bbox.x0 - self.linesize, self.linesize) + bb:invertRect(bbox.x1, bbox.y0 + self.linesize, self.linesize, bbox.y1 - bbox.y0) +end + +-- transform page bbox to screen bbox +function BBoxWidget:page_to_screen() + local bbox = {} + local scale = self.crop.zoom + local screen_offset = self.crop.screen_offset + DEBUG("screen offset in page_to_screen", screen_offset) + bbox.x0 = self.page_bbox.x0 * scale + screen_offset.x + bbox.y0 = self.page_bbox.y0 * scale + screen_offset.y + bbox.x1 = self.page_bbox.x1 * scale + screen_offset.x + bbox.y1 = self.page_bbox.y1 * scale + screen_offset.y + return bbox +end + +-- transform screen bbox to page bbox +function BBoxWidget:screen_to_page() + local bbox = {} + local scale = self.crop.zoom + local screen_offset = self.crop.screen_offset + DEBUG("screen offset in screen_to_page", screen_offset) + bbox.x0 = self.screen_bbox.x0 / scale - screen_offset.x + bbox.y0 = self.screen_bbox.y0 / scale - screen_offset.y + bbox.x1 = self.screen_bbox.x1 / scale - screen_offset.x + bbox.y1 = self.screen_bbox.y1 / scale - screen_offset.y + return bbox +end + +function BBoxWidget:oddEven(number) + if number % 2 == 1 then + return "odd" + else + return "even" + end +end + +function BBoxWidget:init() + if Device:isTouchDevice() then + self.ges_events = { + AdjustCrop = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + ConfirmCrop = { + GestureRange:new{ + ges = "double_tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + CancelCrop = { + GestureRange:new{ + ges = "hold_release", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + } + end +end + +function BBoxWidget:onGesture(ev) + for name, gsseq in pairs(self.ges_events) do + for _, gs_range in ipairs(gsseq) do + --DEBUG("gs_range", gs_range) + if gs_range:match(ev) then + local eventname = gsseq.event or name + return self:handleEvent(Event:new(eventname, ev.pos)) + end + end + end +end + +function BBoxWidget:onAdjustCrop(pos) + DEBUG("adjusting crop bbox with pos", pos) + local bbox = self.screen_bbox + local upper_left = Geom:new{ x = bbox.x0, y = bbox.y0} + local bottom_right = Geom:new{ x = bbox.x1, y = bbox.y1} + if upper_left:distance(pos) < bottom_right:distance(pos) then + upper_left.x = pos.x + upper_left.y = pos.y + else + bottom_right.x = pos.x + bottom_right.y = pos.y + end + self.screen_bbox = { + x0 = upper_left.x, + y0 = upper_left.y, + x1 = bottom_right.x, + y1 = bottom_right.y + } + UIManager.repaint_all = true +end + +function BBoxWidget:onConfirmCrop() + self.page_bbox = self:screen_to_page() + --DEBUG("new bbox", self.page_bbox) + UIManager:close(self) + self.ui:handleEvent(Event:new("BBoxUpdate"), self.page_bbox) + self.document.bbox[self.pageno] = self.page_bbox + self.document.bbox[self:oddEven(self.pageno)] = self.page_bbox + self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode)) + self.document.configurable.text_wrap = self.orig_reflow_mode + UIManager.repaint_all = true +end + +ReaderCropping = InputContainer:new{} + +function ReaderCropping:onPageCrop(mode) + if mode == "auto" then return end + local orig_reflow_mode = self.document.configurable.text_wrap + self.document.configurable.text_wrap = 0 + self.ui:handleEvent(Event:new("CloseConfig")) + self.ui:handleEvent(Event:new("SetZoomMode", "page")) + local ubbox = self.document:getPageBBox(self.current_page) + --DEBUG("used page bbox", ubbox) + self.crop_bbox = BBoxWidget:new{ + page_bbox = ubbox, + ui = self.ui, + crop = self, + document = self.document, + pageno = self.current_page, + orig_zoom_mode = self.orig_zoom_mode, + orig_reflow_mode = orig_reflow_mode, + } + UIManager:show(self.crop_bbox) + return true +end + +function ReaderCropping:onPageUpdate(page_no) + --DEBUG("page updated to", page_no) + self.current_page = page_no +end + +function ReaderCropping:onZoomUpdate(zoom) + --DEBUG("zoom updated to", zoom) + self.zoom = zoom +end + +function ReaderCropping:onScreenOffsetUpdate(screen_offset) + --DEBUG("offset updated to", screen_offset) + self.screen_offset = screen_offset +end + +function ReaderCropping:onSetZoomMode(mode) + if self.orig_zoom_mode == nil then + --DEBUG("backup zoom mode", mode) + self.orig_zoom_mode = mode + end +end + +function ReaderCropping:onReadSettings(config) + local bbox = config:readSetting("bbox") + self.document.bbox = bbox + DEBUG("read document bbox", self.document.bbox) +end + +function ReaderCropping:onCloseDocument() + self.ui.doc_settings:saveSetting("bbox", self.document.bbox) +end diff --git a/frontend/ui/reader/readerview.lua b/frontend/ui/reader/readerview.lua index 82d0e6d30..4e49d2308 100644 --- a/frontend/ui/reader/readerview.lua +++ b/frontend/ui/reader/readerview.lua @@ -38,7 +38,7 @@ function ReaderView:paintTo(bb, x, y) bb:paintRect(x, y, inner_offset.x, self.ui.dimen.h, self.outer_page_color) bb:paintRect(x + self.ui.dimen.w - inner_offset.x - 1, y, inner_offset.x + 1, self.ui.dimen.h, self.outer_page_color) end - + self.ui:handleEvent(Event:new("ScreenOffsetUpdate", inner_offset)) -- draw content if self.ui.document.info.has_pages then self.ui.document:drawPage( diff --git a/frontend/ui/reader/readerzooming.lua b/frontend/ui/reader/readerzooming.lua index ecfb7cf6d..99440a239 100644 --- a/frontend/ui/reader/readerzooming.lua +++ b/frontend/ui/reader/readerzooming.lua @@ -61,7 +61,7 @@ function ReaderZooming:onReadSettings(config) if not zoom_mode then zoom_mode = self.DEFAULT_ZOOM_MODE end - self:onSetZoomMode(zoom_mode) + self.ui:handleEvent(Event:new("SetZoomMode", zoom_mode)) end function ReaderZooming:onCloseDocument() @@ -99,7 +99,6 @@ function ReaderZooming:onSetZoomMode(new_mode) self:setZoom() self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode)) end - return true end function ReaderZooming:onPageUpdate(new_page_no) @@ -148,7 +147,7 @@ function ReaderZooming:setZoom() elseif self.zoom_mode == "contentheight" or self.zoom_mode == "pageheight" then self.zoom = zoom_h end - self.view:onZoomUpdate(self.zoom) + self.ui:handleEvent(Event:new("ZoomUpdate", self.zoom)) end function ReaderZooming:genSetZoomModeCallBack(mode) diff --git a/frontend/ui/readerui.lua b/frontend/ui/readerui.lua index a4331e97b..52177e84e 100644 --- a/frontend/ui/readerui.lua +++ b/frontend/ui/readerui.lua @@ -11,6 +11,7 @@ require "ui/reader/readerfont" require "ui/reader/readertypeset" require "ui/reader/readermenu" require "ui/reader/readerconfig" +require "ui/reader/readercropping" --[[ This is an abstraction for a reader interface @@ -112,6 +113,14 @@ function ReaderUI:init() ui = self } table.insert(self, panner) + -- cropping controller + local cropper = ReaderCropping:new{ + dialog = self.dialog, + view = self[1], + ui = self, + document = self.document, + } + table.insert(self, cropper) else -- make sure we load document first before calling any callback table.insert(self.postInitCallback, function() From 47371ea8b4bb95951adbc0cbbb7fe74bcc345b35 Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 3 Feb 2013 12:29:30 +0800 Subject: [PATCH 06/10] use hold_release event to cancel page crop --- frontend/ui/reader/readercropping.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontend/ui/reader/readercropping.lua b/frontend/ui/reader/readercropping.lua index 66d49b2f0..fb0e530a9 100644 --- a/frontend/ui/reader/readercropping.lua +++ b/frontend/ui/reader/readercropping.lua @@ -142,6 +142,13 @@ function BBoxWidget:onConfirmCrop() UIManager.repaint_all = true end +function BBoxWidget:onCancelCrop() + UIManager:close(self) + self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode)) + self.document.configurable.text_wrap = self.orig_reflow_mode + UIManager.repaint_all = true +end + ReaderCropping = InputContainer:new{} function ReaderCropping:onPageCrop(mode) From ccf9141dd8a722050ec87b7364ad8eff0970c52b Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 3 Feb 2013 16:15:54 +0800 Subject: [PATCH 07/10] move BBoxWidget to bbox.lua in ui directory --- frontend/ui/bbox.lua | 150 +++++++++++++++++++++++++ frontend/ui/reader/readercropping.lua | 151 +------------------------- 2 files changed, 151 insertions(+), 150 deletions(-) create mode 100644 frontend/ui/bbox.lua diff --git a/frontend/ui/bbox.lua b/frontend/ui/bbox.lua new file mode 100644 index 000000000..1743a614f --- /dev/null +++ b/frontend/ui/bbox.lua @@ -0,0 +1,150 @@ +--[[ +BBoxWidget shows a bbox for page cropping +]] +BBoxWidget = InputContainer:new{ + page_bbox = nil, + screen_bbox = nil, + linesize = 2, +} + +function BBoxWidget:getSize() + return Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } +end + +function BBoxWidget:paintTo(bb, x, y) + self.screen_bbox = self.screen_bbox or self:page_to_screen() + local bbox = self.screen_bbox + -- upper_left + bb:invertRect(bbox.x0 + self.linesize, bbox.y0, bbox.x1 - bbox.x0, self.linesize) + bb:invertRect(bbox.x0, bbox.y0, self.linesize, bbox.y1 - bbox.y0 + self.linesize) + -- bottom_right + bb:invertRect(bbox.x0 + self.linesize, bbox.y1, bbox.x1 - bbox.x0 - self.linesize, self.linesize) + bb:invertRect(bbox.x1, bbox.y0 + self.linesize, self.linesize, bbox.y1 - bbox.y0) +end + +-- transform page bbox to screen bbox +function BBoxWidget:page_to_screen() + local bbox = {} + local scale = self.crop.zoom + local screen_offset = self.crop.screen_offset + DEBUG("screen offset in page_to_screen", screen_offset) + bbox.x0 = self.page_bbox.x0 * scale + screen_offset.x + bbox.y0 = self.page_bbox.y0 * scale + screen_offset.y + bbox.x1 = self.page_bbox.x1 * scale + screen_offset.x + bbox.y1 = self.page_bbox.y1 * scale + screen_offset.y + return bbox +end + +-- transform screen bbox to page bbox +function BBoxWidget:screen_to_page() + local bbox = {} + local scale = self.crop.zoom + local screen_offset = self.crop.screen_offset + DEBUG("screen offset in screen_to_page", screen_offset) + bbox.x0 = self.screen_bbox.x0 / scale - screen_offset.x + bbox.y0 = self.screen_bbox.y0 / scale - screen_offset.y + bbox.x1 = self.screen_bbox.x1 / scale - screen_offset.x + bbox.y1 = self.screen_bbox.y1 / scale - screen_offset.y + return bbox +end + +function BBoxWidget:oddEven(number) + if number % 2 == 1 then + return "odd" + else + return "even" + end +end + +function BBoxWidget:init() + if Device:isTouchDevice() then + self.ges_events = { + AdjustCrop = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + ConfirmCrop = { + GestureRange:new{ + ges = "double_tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + CancelCrop = { + GestureRange:new{ + ges = "hold_release", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight() + } + } + }, + } + end +end + +function BBoxWidget:onGesture(ev) + for name, gsseq in pairs(self.ges_events) do + for _, gs_range in ipairs(gsseq) do + --DEBUG("gs_range", gs_range) + if gs_range:match(ev) then + local eventname = gsseq.event or name + return self:handleEvent(Event:new(eventname, ev.pos)) + end + end + end +end + +function BBoxWidget:onAdjustCrop(pos) + DEBUG("adjusting crop bbox with pos", pos) + local bbox = self.screen_bbox + local upper_left = Geom:new{ x = bbox.x0, y = bbox.y0} + local bottom_right = Geom:new{ x = bbox.x1, y = bbox.y1} + if upper_left:distance(pos) < bottom_right:distance(pos) then + upper_left.x = pos.x + upper_left.y = pos.y + else + bottom_right.x = pos.x + bottom_right.y = pos.y + end + self.screen_bbox = { + x0 = upper_left.x, + y0 = upper_left.y, + x1 = bottom_right.x, + y1 = bottom_right.y + } + UIManager.repaint_all = true +end + +function BBoxWidget:onConfirmCrop() + self.page_bbox = self:screen_to_page() + --DEBUG("new bbox", self.page_bbox) + UIManager:close(self) + self.ui:handleEvent(Event:new("BBoxUpdate"), self.page_bbox) + self.document.bbox[self.pageno] = self.page_bbox + self.document.bbox[self:oddEven(self.pageno)] = self.page_bbox + self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode)) + self.document.configurable.text_wrap = self.orig_reflow_mode + UIManager.repaint_all = true +end + +function BBoxWidget:onCancelCrop() + UIManager:close(self) + self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode)) + self.document.configurable.text_wrap = self.orig_reflow_mode + UIManager.repaint_all = true +end diff --git a/frontend/ui/reader/readercropping.lua b/frontend/ui/reader/readercropping.lua index fb0e530a9..2d0b694ba 100644 --- a/frontend/ui/reader/readercropping.lua +++ b/frontend/ui/reader/readercropping.lua @@ -1,153 +1,4 @@ ---[[ -BBoxWidget shows a bbox for page cropping -]] -BBoxWidget = InputContainer:new{ - page_bbox = nil, - screen_bbox = nil, - linesize = 2, -} - -function BBoxWidget:getSize() - return Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight() - } -end - -function BBoxWidget:paintTo(bb, x, y) - self.screen_bbox = self.screen_bbox or self:page_to_screen() - local bbox = self.screen_bbox - -- upper_left - bb:invertRect(bbox.x0 + self.linesize, bbox.y0, bbox.x1 - bbox.x0, self.linesize) - bb:invertRect(bbox.x0, bbox.y0, self.linesize, bbox.y1 - bbox.y0 + self.linesize) - -- bottom_right - bb:invertRect(bbox.x0 + self.linesize, bbox.y1, bbox.x1 - bbox.x0 - self.linesize, self.linesize) - bb:invertRect(bbox.x1, bbox.y0 + self.linesize, self.linesize, bbox.y1 - bbox.y0) -end - --- transform page bbox to screen bbox -function BBoxWidget:page_to_screen() - local bbox = {} - local scale = self.crop.zoom - local screen_offset = self.crop.screen_offset - DEBUG("screen offset in page_to_screen", screen_offset) - bbox.x0 = self.page_bbox.x0 * scale + screen_offset.x - bbox.y0 = self.page_bbox.y0 * scale + screen_offset.y - bbox.x1 = self.page_bbox.x1 * scale + screen_offset.x - bbox.y1 = self.page_bbox.y1 * scale + screen_offset.y - return bbox -end - --- transform screen bbox to page bbox -function BBoxWidget:screen_to_page() - local bbox = {} - local scale = self.crop.zoom - local screen_offset = self.crop.screen_offset - DEBUG("screen offset in screen_to_page", screen_offset) - bbox.x0 = self.screen_bbox.x0 / scale - screen_offset.x - bbox.y0 = self.screen_bbox.y0 / scale - screen_offset.y - bbox.x1 = self.screen_bbox.x1 / scale - screen_offset.x - bbox.y1 = self.screen_bbox.y1 / scale - screen_offset.y - return bbox -end - -function BBoxWidget:oddEven(number) - if number % 2 == 1 then - return "odd" - else - return "even" - end -end - -function BBoxWidget:init() - if Device:isTouchDevice() then - self.ges_events = { - AdjustCrop = { - GestureRange:new{ - ges = "tap", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight() - } - } - }, - ConfirmCrop = { - GestureRange:new{ - ges = "double_tap", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight() - } - } - }, - CancelCrop = { - GestureRange:new{ - ges = "hold_release", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight() - } - } - }, - } - end -end - -function BBoxWidget:onGesture(ev) - for name, gsseq in pairs(self.ges_events) do - for _, gs_range in ipairs(gsseq) do - --DEBUG("gs_range", gs_range) - if gs_range:match(ev) then - local eventname = gsseq.event or name - return self:handleEvent(Event:new(eventname, ev.pos)) - end - end - end -end - -function BBoxWidget:onAdjustCrop(pos) - DEBUG("adjusting crop bbox with pos", pos) - local bbox = self.screen_bbox - local upper_left = Geom:new{ x = bbox.x0, y = bbox.y0} - local bottom_right = Geom:new{ x = bbox.x1, y = bbox.y1} - if upper_left:distance(pos) < bottom_right:distance(pos) then - upper_left.x = pos.x - upper_left.y = pos.y - else - bottom_right.x = pos.x - bottom_right.y = pos.y - end - self.screen_bbox = { - x0 = upper_left.x, - y0 = upper_left.y, - x1 = bottom_right.x, - y1 = bottom_right.y - } - UIManager.repaint_all = true -end - -function BBoxWidget:onConfirmCrop() - self.page_bbox = self:screen_to_page() - --DEBUG("new bbox", self.page_bbox) - UIManager:close(self) - self.ui:handleEvent(Event:new("BBoxUpdate"), self.page_bbox) - self.document.bbox[self.pageno] = self.page_bbox - self.document.bbox[self:oddEven(self.pageno)] = self.page_bbox - self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode)) - self.document.configurable.text_wrap = self.orig_reflow_mode - UIManager.repaint_all = true -end - -function BBoxWidget:onCancelCrop() - UIManager:close(self) - self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode)) - self.document.configurable.text_wrap = self.orig_reflow_mode - UIManager.repaint_all = true -end +require "ui/bbox" ReaderCropping = InputContainer:new{} From 92586a3b95f4eb8398e4a310b922ecd4638fb5a8 Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 3 Feb 2013 17:49:02 +0800 Subject: [PATCH 08/10] cleanup unused debugs --- frontend/ui/config.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend/ui/config.lua b/frontend/ui/config.lua index aaae3f12b..e0dead867 100644 --- a/frontend/ui/config.lua +++ b/frontend/ui/config.lua @@ -339,7 +339,6 @@ function ConfigOption:init() if self.options[c].name then if self.options[c].values then local val = self.config.configurable[self.options[c].name] - DEBUG("val", val) local min_diff = math.abs(val - self.options[c].values[1]) local diff = nil for index, val_ in pairs(self.options[c].values) do @@ -576,17 +575,16 @@ function ConfigDialog:onShowConfigPanel(index) end function ConfigDialog:onConfigChoice(option_name, option_value) - DEBUG("config option value", option_name, option_value) + --DEBUG("config option value", option_name, option_value) self.configurable[option_name] = option_value end function ConfigDialog:onConfigEvent(option_event, option_arg) - DEBUG("config option event", option_event, option_arg) + --DEBUG("config option event", option_event, option_arg) self.ui:handleEvent(Event:new(option_event, option_arg)) end function ConfigDialog:closeDialog() - DEBUG("closing config dialog") UIManager:close(self) if self.close_callback then self.close_callback() From 4675a220d8789dd4fe3bf5fc42fd29270c80e97e Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 3 Feb 2013 21:36:11 +0800 Subject: [PATCH 09/10] add current bbox in page rendering hash So that changing bbox could take effect on current page. --- frontend/document/koptinterface.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/document/koptinterface.lua b/frontend/document/koptinterface.lua index 9f12e7530..0c5abc44c 100644 --- a/frontend/document/koptinterface.lua +++ b/frontend/document/koptinterface.lua @@ -178,7 +178,7 @@ KoptOptions = { KoptInterface = {} -- get reflow context -function KoptInterface:getKOPTContext(doc, pageno) +function KoptInterface:getKOPTContext(doc, pageno, bbox) local kc = KOPTContext.new() kc:setTrim(doc.configurable.trim_page) kc:setWrap(doc.configurable.text_wrap) @@ -196,7 +196,6 @@ function KoptInterface:getKOPTContext(doc, pageno) kc:setDefectSize(doc.configurable.defect_size) kc:setLineSpacing(doc.configurable.line_spacing) kc:setWordSpacing(doc.configurable.word_spacing) - local bbox = doc:getPageBBox(pageno) kc:setBBox(bbox.x0, bbox.y0, bbox.x1, bbox.y1) return kc end @@ -204,10 +203,11 @@ end -- calculates page dimensions function KoptInterface:getPageDimensions(doc, pageno, zoom, rotation) -- check cached page size - local hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash('|') + self.cur_bbox = doc:getPageBBox(pageno) + local hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..tostring(self.cur_bbox) local cached = Cache:check(hash) if not cached then - local kc = self:getKOPTContext(doc, pageno) + local kc = self:getKOPTContext(doc, pageno, self.cur_bbox) local page = doc._document:openPage(pageno) -- reflow page page:reflow(kc, 0) @@ -227,7 +227,8 @@ end function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, render_mode) doc.render_mode = render_mode - local hash = "renderpg|"..doc.file.."|"..pageno.."|"..doc.configurable:hash('|') + self.cur_bbox = doc:getPageBBox(pageno) + local hash = "renderpg|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..tostring(self.cur_bbox) local page_size = self:getPageDimensions(doc, pageno, zoom, rotation) -- this will be the size we actually render local size = page_size @@ -242,7 +243,7 @@ function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, render_mode return end -- only render required part - hash = "renderpg|"..doc.file.."|"..pageno.."|"..doc.configurable:hash('|').."|"..tostring(rect) + hash = "renderpg|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..tostring(rect) size = rect end @@ -258,7 +259,7 @@ function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, render_mode } -- draw to blitbuffer - local kc_hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash('|') + local kc_hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..tostring(self.cur_bbox) local page = doc._document:openPage(pageno) local cached = Cache:check(kc_hash) if cached then From 0ed5d05bc08cd0acf6f8d2fc2c3d5a0157be5870 Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 3 Feb 2013 22:58:30 +0800 Subject: [PATCH 10/10] hash current bbox explicitly --- frontend/document/koptinterface.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/document/koptinterface.lua b/frontend/document/koptinterface.lua index 0c5abc44c..1e8caf4bd 100644 --- a/frontend/document/koptinterface.lua +++ b/frontend/document/koptinterface.lua @@ -204,7 +204,8 @@ end function KoptInterface:getPageDimensions(doc, pageno, zoom, rotation) -- check cached page size self.cur_bbox = doc:getPageBBox(pageno) - local hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..tostring(self.cur_bbox) + local bbox = self.cur_bbox + local hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..bbox.x0.."|"..bbox.y0.."|"..bbox.x1.."|"..bbox.y1 local cached = Cache:check(hash) if not cached then local kc = self:getKOPTContext(doc, pageno, self.cur_bbox) @@ -228,7 +229,8 @@ end function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, render_mode) doc.render_mode = render_mode self.cur_bbox = doc:getPageBBox(pageno) - local hash = "renderpg|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..tostring(self.cur_bbox) + local bbox = self.cur_bbox + local hash = "renderpg|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..bbox.x0.."|"..bbox.y0.."|"..bbox.x1.."|"..bbox.y1 local page_size = self:getPageDimensions(doc, pageno, zoom, rotation) -- this will be the size we actually render local size = page_size @@ -259,7 +261,7 @@ function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, render_mode } -- draw to blitbuffer - local kc_hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..tostring(self.cur_bbox) + local kc_hash = "kctx|"..doc.file.."|"..pageno.."|"..doc.configurable:hash("|").."|"..bbox.x0.."|"..bbox.y0.."|"..bbox.x1.."|"..bbox.y1 local page = doc._document:openPage(pageno) local cached = Cache:check(kc_hash) if cached then