From fa5b0c98748c17f69bf16867c0dc87317805af58 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Sun, 26 Feb 2012 09:47:54 +0800 Subject: [PATCH] mod: toc and jumpstack refactored --- pdfreader.lua | 104 +++++++++++++++---------- selectmenu.lua | 25 ++++--- tocmenu.lua | 200 ------------------------------------------------- 3 files changed, 80 insertions(+), 249 deletions(-) delete mode 100644 tocmenu.lua diff --git a/pdfreader.lua b/pdfreader.lua index 9570e651f..f22da6c98 100644 --- a/pdfreader.lua +++ b/pdfreader.lua @@ -1,6 +1,6 @@ require "keys" require "settings" -require "tocmenu" +--require "tocmenu" require "selectmenu" PDFReader = { @@ -243,6 +243,7 @@ function PDFReader:goto(no) local jump_item = nil -- add current page to jump_stack if no in for _t,_v in ipairs(self.jump_stack) do + --print(_v) if _v.page == self.pageno then jump_item = _v table.remove(self.jump_stack, _t) @@ -308,6 +309,51 @@ function PDFReader:setrotate(rotate) self:goto(self.pageno) end +function PDFReader:showTOC() + toc = self.doc:getTOC() + local menu_items = {} + -- build menu items + for _k,_v in ipairs(toc) do + table.insert(menu_items, + (" "):rep(_v.depth-1).._v.title) + end + toc_menu = SelectMenu:new{ + menu_title = "Table of Contents", + item_array = menu_items, + no_item_msg = + "This document does not have a Table of Contents.", + } + item_no = toc_menu:choose(0, fb.bb:getHeight()) + if item_no then + self:goto(toc[item_no].page) + else + self:goto(self.pageno) + end +end + +function PDFReader:showJumpStack() + local menu_items = {} + for _k,_v in ipairs(self.jump_stack) do + --print(_v.datetime.." -> Page ".._v.page) + table.insert(menu_items, + _v.datetime.." -> Page ".._v.page) + end + jump_menu = SelectMenu:new{ + menu_title = + "Jump Keeper, Current page: "..self.pageno, + item_array = menu_items, + no_item_msg = "No jump history.", + } + item_no = jump_menu:choose(0, fb.bb:getHeight()) + if item_no then + local jump_item = self.jump_stack[item_no] + self:goto(jump_item.page) + else + self:goto(self.pageno) + end +end + + -- wait for input and handle it function PDFReader:inputloop() while 1 do @@ -335,16 +381,24 @@ function PDFReader:inputloop() self:goto(self.pageno - 1) end elseif ev.code == KEY_BACK then - self:clearcache() - if self.doc ~= nil then - self.doc:close() - end - if self.settings ~= nil then - self.settings:savesetting("last_page", self.pageno) - self.settings:savesetting("gamma", self.globalgamma) - self.settings:close() + if self.altmode then + -- in altmode, back to last jump + if #self.jump_stack ~= 0 then + self:goto(self.jump_stack[1].page) + end + else + -- not altmode, exit pdfreader + self:clearcache() + if self.doc ~= nil then + self.doc:close() + end + if self.settings ~= nil then + self.settings:savesetting("last_page", self.pageno) + self.settings:savesetting("gamma", self.globalgamma) + self.settings:close() + end + return end - return elseif ev.code == KEY_VPLUS then self:modify_gamma( 1.25 ) elseif ev.code == KEY_VMINUS then @@ -367,38 +421,12 @@ function PDFReader:inputloop() else self:setglobalzoommode(self.ZOOM_FIT_TO_PAGE_HEIGHT) end - elseif ev.code == KEY_T then if self.altmode then - -- show jump_stack - local menu_items = {} - for _k,_v in ipairs(self.jump_stack) do - table.insert(menu_items, - _v.datetime.." -> Page ".._v.page) - end - jump_menu = SelectMenu:new( - "Jump Keeper, Current page: "..self.pageno, menu_items) - jump_re = jump_menu:choose(0, fb.bb:getHeight()) - jump_menu = nil - if jump_re then - local jump_item = self.jump_stack[jump_re] - self:goto(jump_item.page) - else - self:goto(self.pageno) - end + self:showJumpStack() else - -- show table of content menu - toc = self.doc:getTOC() - toc_menu = TOCMenu:new(toc) - --toc_menu:dump() - no = toc_menu:choose(0, fb.bb:getHeight()) - if no then - self:goto(no) - else - self:goto(self.pageno) - end + self:showTOC() end - elseif ev.code == KEY_J then self:setrotate( self.globalrotate + 10 ) elseif ev.code == KEY_K then diff --git a/selectmenu.lua b/selectmenu.lua index 7d6daf5d6..8c6219f60 100644 --- a/selectmenu.lua +++ b/selectmenu.lua @@ -24,23 +24,26 @@ SelectMenu = { -- foot height foot_H = 27, - -- state buffer - menu_title = "None Title", + menu_title = "None Titled", + no_item_msg = "No items found.", item_array = {}, items = 14, + + -- state buffer page = 1, current = 1, oldcurrent = 0, } -function SelectMenu:new(menu_title, item_array) - instance = self - instance.item_array = item_array - instance.menu_title = menu_title - instance.items = #item_array - instance.current = 1 - instance.oldcurrent = 0 - return instance +function SelectMenu:new(o) + o = o or {} + setmetatable(o, self) + self.__index = self + o.items = #o.item_array + o.page = 1 + o.current = 1 + o.oldcurrent = 0 + return o end function SelectMenu:updateFont() @@ -119,7 +122,7 @@ function SelectMenu:choose(ypos, height) "Oops... Bad news for you:", true) y = y + self.spacing renderUtf8Text(fb.bb, 30, y, self.face, self.fhash, - "No items found.", true) + self.no_item_msg, true) markerdirty = false else local c diff --git a/tocmenu.lua b/tocmenu.lua deleted file mode 100644 index ee2d70d51..000000000 --- a/tocmenu.lua +++ /dev/null @@ -1,200 +0,0 @@ -require "rendertext" -require "keys" -require "graphics" -require "fontchooser" - -TOCMenu = { - -- font for displaying toc item names - fsize = 22, - face = nil, - fhash = nil, - -- font for page title - tfsize = 25, - tface = nil, - tfhash = nil, - -- font for paging display - ffsize = 16, - fface = nil, - ffhash = nil, - - -- title height - title_H = 40, - -- spacing between lines - spacing = 36, - -- foot height - foot_H = 27, - - -- state buffer - toc = {}, - items = 14, - page = 1, - current = 1, - oldcurrent = 0, -} - -function TOCMenu:new(toc) - instance = self - instance.toc = toc - instance.items = #toc - return instance -end - -function TOCMenu:dump() - for k,v in pairs(self.toc) do - print("TOC item: "..k) - for key,value in pairs(v) do - print(" "..key..": "..value) - end - end -end - -function TOCMenu:updateFont() - if self.fhash ~= FontChooser.cfont..self.fsize then - self.face = freetype.newBuiltinFace(FontChooser.cfont, self.fsize) - self.fhash = FontChooser.cfont..self.fsize - end - - if self.tfhash ~= FontChooser.tfont..self.tfsize then - self.tface = freetype.newBuiltinFace(FontChooser.tfont, self.tfsize) - self.tfhash = FontChooser.tfont..self.tfsize - end - - if self.ffhash ~= FontChooser.ffont..self.ffsize then - self.fface = freetype.newBuiltinFace(FontChooser.ffont, self.ffsize) - self.ffhash = FontChooser.ffont..self.ffsize - end -end - -function TOCMenu:choose(ypos, height) - local perpage = math.floor(height / self.spacing) - 2 - local pagedirty = true - local markerdirty = false - self:updateFont() - - local prevItem = function () - if self.current == 1 then - if self.page > 1 then - self.current = perpage - self.page = self.page - 1 - pagedirty = true - end - else - self.current = self.current - 1 - markerdirty = true - end - end - - local nextItem = function () - if self.current == perpage then - if self.page < (self.items / perpage) then - self.current = 1 - self.page = self.page + 1 - pagedirty = true - end - else - if self.page ~= math.floor(self.items / perpage) + 1 - or self.current + (self.page-1)*perpage < self.items then - self.current = self.current + 1 - markerdirty = true - end - end - end - - - while true do - if pagedirty then - markerdirty = true - -- draw menu title - fb.bb:paintRect(0, ypos, fb.bb:getWidth(), self.title_H + 10, 0) - fb.bb:paintRect(30, ypos + 10, fb.bb:getWidth() - 60, self.title_H, 5) - x = fb.bb:getWidth() - 260 -- move text to the right - y = ypos + self.title_H - renderUtf8Text(fb.bb, x, y, self.tface, self.tfhash, - "Table of Contents", true) - - -- draw toc items - fb.bb:paintRect(0, ypos + self.title_H + 10, fb.bb:getWidth(), height - self.title_H, 0) - if self.items == 0 then - y = ypos + self.title_H + (self.spacing * 2) - renderUtf8Text(fb.bb, 30, y, self.face, self.fhash, - "Oops... Bad news for you:", true) - y = y + self.spacing - renderUtf8Text(fb.bb, 30, y, self.face, self.fhash, - "This document doesn't have a TOC.", true) - markerdirty = false - else - local c - for c = 1, perpage do - local i = (self.page - 1) * perpage + c - if i <= self.items then - y = ypos + self.title_H + (self.spacing * c) - renderUtf8Text(fb.bb, 30, y, self.face, self.fhash, - (" "):rep(self.toc[i]["depth"]-1)..self.toc[i]["title"], true) - end - end - end - - -- draw footer - y = ypos + self.title_H + (self.spacing * perpage) + self.foot_H + 5 - x = (fb.bb:getWidth() / 2) - 50 - renderUtf8Text(fb.bb, x, y, self.fface, self.ffhash, - "Page "..self.page.." of "..(math.floor(self.items / perpage)+1), true) - end - - if markerdirty then - if not pagedirty then - if self.oldcurrent > 0 then - y = ypos + self.title_H + (self.spacing * self.oldcurrent) + 8 - fb.bb:paintRect(30, y, fb.bb:getWidth() - 60, 3, 0) - fb:refresh(1, 30, y, fb.bb:getWidth() - 60, 3) - end - end - -- draw new marker line - y = ypos + self.title_H + (self.spacing * self.current) + 8 - fb.bb:paintRect(30, y, fb.bb:getWidth() - 60, 3, 15) - if not pagedirty then - fb:refresh(1, 30, y, fb.bb:getWidth() - 60, 3) - end - self.oldcurrent = self.current - markerdirty = false - end - - if pagedirty then - fb:refresh(0, 0, ypos, fb.bb:getWidth(), height) - pagedirty = false - end - - local ev = input.waitForEvent() - if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then - ev.code = adjustFWKey(ev.code) - if ev.code == KEY_FW_UP then - prevItem() - elseif ev.code == KEY_FW_DOWN then - nextItem() - elseif ev.code == KEY_PGFWD then - if self.page < (self.items / perpage) then - if self.current + self.page*perpage > self.items then - self.current = self.items - self.page*perpage - end - self.page = self.page + 1 - pagedirty = true - else - self.current = self.items - (self.page-1)*perpage - markerdirty = true - end - elseif ev.code == KEY_PGBCK then - if self.page > 1 then - self.page = self.page - 1 - pagedirty = true - else - self.current = 1 - markerdirty = true - end - elseif ev.code == KEY_ENTER or ev.code == KEY_FW_PRESS then - return self.toc[perpage*(self.page-1)+self.current]["page"] - elseif ev.code == KEY_BACK then - return nil - end - end - end -end