diff --git a/filechooser.lua b/filechooser.lua index 42ffe90ba..a0bd1ff4c 100644 --- a/filechooser.lua +++ b/filechooser.lua @@ -3,15 +3,32 @@ require "keys" require "graphics" FileChooser = { + -- Class vars: + + -- font for displaying file/dir names + face = freetype.newBuiltinFace("sans", 25), + fhash = "s25", + -- font for paging display + sface = freetype.newBuiltinFace("sans", 16), + sfhash = "s16", + -- spacing between lines + spacing = 40, + + -- state buffer dirs = nil, - files = nil + files = nil, + items = 0, + path = "", + page = 1, + current = 1, + oldcurrent = 0, } -function FileChooser:readdir(path) +function FileChooser:readdir() self.dirs = {} self.files = {} - for f in lfs.dir(path) do - if lfs.attributes(path.."/"..f, "mode") == "directory" and f ~= "." and not string.match(f, "^%.[^.]") then + for f in lfs.dir(self.path) do + if lfs.attributes(self.path.."/"..f, "mode") == "directory" and f ~= "." and not string.match(f, "^%.[^.]") then table.insert(self.dirs, f) elseif string.match(f, ".+%.[pP][dD][fF]$") then table.insert(self.files, f) @@ -21,120 +38,116 @@ function FileChooser:readdir(path) table.sort(self.files) end -function FileChooser:choose(startpath, ypos, height) - local face = freetype.newBuiltinFace("sans", 25) - local fhash = "s25" - local sface = freetype.newBuiltinFace("sans", 16) - local sfhash = "s16" - local path = startpath - local spacing = 40 - local perpage = math.floor(height / spacing) - 1 - local pathdirty = true - local pagedirty = false - local framebufferdirty = false - local markerdirty = true - local oldcurrent = 0 - local page - local current - local items +function FileChooser:setPath(newPath) + self.path = newPath + self:readdir() + self.items = #self.dirs + #self.files + if self.items == 0 then + return nil + end + self.page = 1 + self.current = 1 + return true +end + +function FileChooser:choose(ypos, height) + local perpage = math.floor(height / self.spacing) - 1 + local pagedirty = true + local markerdirty = false while true do - if pathdirty then - print("showing file chooser in <"..path..">") - self:readdir(path) - items = #self.dirs + #self.files - if items == 0 then - return nil - end - page = 1 - current = 1 - pathdirty = false - pagedirty = true - end if pagedirty then fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0) local c for c = 1, perpage do - local i = (page - 1) * perpage + c + local i = (self.page - 1) * perpage + c if i <= #self.dirs then - renderUtf8Text(fb.bb, 39, ypos + spacing*c, face, fhash, "/", true) - renderUtf8Text(fb.bb, 50, ypos + spacing*c, face, fhash, self.dirs[i], true) - elseif i <= items then - renderUtf8Text(fb.bb, 50, ypos + spacing*c, face, fhash, self.files[i-#self.dirs], true) + -- resembles display in midnight commander: adds "/" prefix for directories + renderUtf8Text(fb.bb, 39, ypos + self.spacing*c, self.face, self.fhash, "/", true) + renderUtf8Text(fb.bb, 50, ypos + self.spacing*c, self.face, self.fhash, self.dirs[i], true) + elseif i <= self.items then + renderUtf8Text(fb.bb, 50, ypos + self.spacing*c, self.face, self.fhash, self.files[i-#self.dirs], true) end end - renderUtf8Text(fb.bb, 39, ypos + spacing * perpage + 32, sface, sfhash, - "Page "..page.." of "..(math.floor(items / perpage)+1), true) - framebufferdirty = true + renderUtf8Text(fb.bb, 39, ypos + self.spacing * perpage + 32, self.sface, self.sfhash, + "Page "..self.page.." of "..(math.floor(self.items / perpage)+1), true) markerdirty = true - pagedirty = false end if markerdirty then - if oldcurrent > 0 then - fb.bb:paintRect(30, ypos + spacing*oldcurrent + 10, fb.bb:getWidth() - 60, 3, 0) - fb:refresh(1, ypos + spacing*oldcurrent + 10, fb.bb:getWidth() - 60, 3) + if not pagedirty then + if self.oldcurrent > 0 then + fb.bb:paintRect(30, ypos + self.spacing*self.oldcurrent + 10, fb.bb:getWidth() - 60, 3, 0) + fb:refresh(1, 30, ypos + self.spacing*self.oldcurrent + 10, fb.bb:getWidth() - 60, 3) + end + end + fb.bb:paintRect(30, ypos + self.spacing*self.current + 10, fb.bb:getWidth() - 60, 3, 15) + if not pagedirty then + fb:refresh(1, 30, ypos + self.spacing*self.current + 10, fb.bb:getWidth() - 60, 3) end - fb.bb:paintRect(30, ypos + spacing*current + 10, fb.bb:getWidth() - 60, 3, 15) - fb:refresh(1, ypos + spacing*current + 10, fb.bb:getWidth() - 60, 3) - oldcurrent = current + 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 if ev.code == KEY_FW_UP then - if current == 1 then - if page > 1 then - current = perpage - page = page - 1 + if self.current == 1 then + if self.page > 1 then + self.current = self.perpage + self.page = self.page - 1 pagedirty = true end else - current = current - 1 + self.current = self.current - 1 markerdirty = true end elseif ev.code == KEY_FW_DOWN then - if current == perpage then - if page < (items / perpage) then - current = 1 - page = page + 1 + if self.current == perpage then + if self.page < (self.items / perpage) then + self.current = 1 + self.page = page + 1 pagedirty = true end else - if page ~= math.floor(items / perpage) + 1 - or current + (page-1)*perpage < items then - current = current + 1 + 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 elseif ev.code == KEY_PGFWD then - if page < (items / perpage) then - if current + page*perpage > items then - current = items - page*perpage + if self.page < (self.items / perpage) then + if self.current + self.page*perpage > self.items then + self.current = self.items - self.page*perpage end - page = page + 1 + self.page = self.page + 1 pagedirty = true else - current = items - (page-1)*perpage + self.current = self.items - (self.page-1)*perpage markerdirty = true end elseif ev.code == KEY_PGBCK then - if page > 1 then - page = page - 1 + if self.page > 1 then + self.page = self.page - 1 pagedirty = true else - current = 1 + self.current = 1 markerdirty = true end elseif ev.code == KEY_ENTER or ev.code == KEY_FWPRESS then - local newdir = self.dirs[perpage*(page-1)+current] + local newdir = self.dirs[perpage*(self.page-1)+self.current] if newdir == ".." then - path = string.gsub(path, "(.*)/[^/]+/?$", "%1") - pathdirty = true + local path = string.gsub(self.path, "(.*)/[^/]+/?$", "%1") + self:setPath(path) elseif newdir then - path = path.."/"..newdir - pathdirty = true + local path = self.path.."/"..newdir + self:setPath(path) else - return path.."/"..self.files[perpage*(page-1)+current - #self.dirs] + return self.path.."/"..self.files[perpage*(self.page-1)+self.current - #self.dirs] end + pagedirty = true elseif ev.code == KEY_BACK then return nil end diff --git a/reader.lua b/reader.lua index bc5484496..af5300576 100755 --- a/reader.lua +++ b/reader.lua @@ -74,8 +74,9 @@ width, height = fb:getSize() if lfs.attributes(ARGV[optind], "mode") == "directory" then local running = true + FileChooser:setPath(ARGV[optind]) while running do - local pdffile = FileChooser:choose(ARGV[optind],0,height) + local pdffile = FileChooser:choose(0,height) if pdffile ~= nil then PDFReader:open(pdffile,"") -- TODO: query for password PDFReader:goto(tonumber(PDFReader.settings:readsetting("last_page") or 1))