From ce5614ef6f5020fd87b16a3c76384e5afa470890 Mon Sep 17 00:00:00 2001 From: HW Date: Sun, 10 Jun 2012 17:36:19 +0200 Subject: [PATCH] cleanup, also removal of G_* constants a bit of cleanup, switched width/height combo over to use Geom() objects, moved framebuffer handling to Screen object, callback syntax sanitizing, lots of small changes --- frontend/document/credocument.lua | 2 +- frontend/document/document.lua | 2 +- frontend/ui/dialog.lua | 151 ++++++++++++++++++------------ frontend/ui/filechooser.lua | 15 +-- frontend/ui/geometry.lua | 31 ++++-- frontend/ui/reader/readertoc.lua | 13 ++- frontend/ui/reader/readerview.lua | 2 +- frontend/ui/screen.lua | 33 +++++-- frontend/ui/ui.lua | 11 +-- frontend/ui/widget.lua | 16 ++-- wtest.lua | 20 ++-- 11 files changed, 178 insertions(+), 118 deletions(-) diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index def02e21f..7cf24ae3d 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -55,7 +55,7 @@ function CreDocument:init() local style_sheet = "./data/"..file_type..".css" ok, self._document = pcall(cre.openDocument, self.file, style_sheet, - G_width, G_height) + Screen:getWidth(), Screen:getHeight()) if not ok then self.error_message = self.doc -- will contain error message return diff --git a/frontend/document/document.lua b/frontend/document/document.lua index 3ec9d55aa..80c5c6c99 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -105,7 +105,7 @@ end -- calculates page dimensions function Document:getPageDimensions(pageno, zoom, rotation) - local native_dimen = Geom:copy(self:getNativePageDimensions(pageno)) + local native_dimen = self:getNativePageDimensions(pageno):copy() if rotation == 90 or rotation == 270 then -- switch orientation native_dimen.w, native_dimen.h = native_dimen.h, native_dimen.w diff --git a/frontend/ui/dialog.lua b/frontend/ui/dialog.lua index da6543347..21079e14c 100644 --- a/frontend/ui/dialog.lua +++ b/frontend/ui/dialog.lua @@ -49,6 +49,9 @@ function FocusManager:onFocusMove(args) return true end + if not self.layout or not self.layout[self.selected.y] or not self.layout[self.selected.y][self.selected.x] then + return true + end local current_item = self.layout[self.selected.y][self.selected.x] while true do if self.selected.x + dx > #self.layout[self.selected.y] @@ -140,7 +143,7 @@ ConfirmBox = FocusManager:new{ function ConfirmBox:init() -- calculate box width on the fly if not given if not self.width then - self.width = G_width - 200 + self.width = Screen:getWidth() - 200 end -- build bottons self.key_events.Close = { {{"Home","Back"}}, doc = "cancel" } @@ -158,7 +161,7 @@ function ConfirmBox:init() self.selected.x = 2 -- Cancel is default self[1] = CenterContainer:new{ - dimen = { w = G_width, h = G_height }, + dimen = Screen:getSize(), FrameContainer:new{ margin = 2, background = 0, @@ -222,7 +225,7 @@ InfoMessage = InputContainer:new{ function InfoMessage:init() -- we construct the actual content here because self.text is only available now self[1] = CenterContainer:new{ - dimen = { w = G_width, h = G_height }, + dimen = Screen:getSize(), FrameContainer:new{ margin = 2, background = 0, @@ -260,8 +263,7 @@ end Widget that displays a shortcut icon for menu item ]] ItemShortCutIcon = WidgetContainer:new{ - width = 22, - height = 22, + dimen = Geom:new{ w = 22, h = 22 }, key = nil, bordersize = 2, radius = 0, @@ -293,15 +295,9 @@ function ItemShortCutIcon:init() bordersize = self.bordersize, radius = radius, background = background, - dimen = { - w = self.width, - h = self.height, - }, + dimen = self.dimen, CenterContainer:new{ - dimen = { - w = self.width, - h = self.height, - }, + dimen = self.dimen, TextWidget:new{ text = self.key, face = sc_face, @@ -319,43 +315,41 @@ MenuItem = InputContainer:new{ text = nil, detail = nil, face = Font:getFace("cfont", 22), - width = nil, - height = nil, + dimen = nil, shortcut = nil, shortcut_style = "square", _underline_container = nil, } function MenuItem:init() - local shortcut_icon_w = 0 - local shortcut_icon_h = 0 + local shortcut_icon_dimen = Geom:new() if self.shortcut then - shortcut_icon_w = math.floor(self.height*4/5) - shortcut_icon_h = shortcut_icon_w + shortcut_icon_dimen.w = math.floor(self.dimen.h*4/5) + shortcut_icon_dimen.h = shortcut_icon_dimen.w end self.detail = self.text -- 15 for HorizontalSpan, - self.content_width = self.width - shortcut_icon_w - 15 + self.content_width = self.dimen.w - shortcut_icon_dimen.w - 15 -- we need this table per-instance, so we declare it here self.active_key_events = { Select = { {"Press"}, doc = "chose selected item" }, } - w = sizeUtf8Text(0, self.width, self.face, self.text, true).x + w = sizeUtf8Text(0, self.dimen.w, self.face, self.text, true).x if w >= self.content_width then self.active_key_events.ShowItemDetail = { {"Right"}, doc = "show item detail" } indicator = " >>" - indicator_w = sizeUtf8Text(0, self.width, self.face, indicator, true).x + indicator_w = sizeUtf8Text(0, self.dimen.w, self.face, indicator, true).x self.text = getSubTextByWidth(self.text, self.face, self.content_width - indicator_w, true) .. indicator end self._underline_container = UnderlineContainer:new{ - dimen = { + dimen = Geom:new{ w = self.content_width, - h = self.height + h = self.dimen.h }, HorizontalGroup:new { align = "center", @@ -369,8 +363,7 @@ function MenuItem:init() self[1] = HorizontalGroup:new{ HorizontalSpan:new{ width = 5 }, ItemShortCutIcon:new{ - width = shortcut_icon_w, - height = shortcut_icon_h, + dimen = shortcut_icon_dimen, key = self.shortcut, radius = shortcut_icon_r, style = self.shortcut_style, @@ -414,8 +407,7 @@ Menu = FocusManager:new{ sface = Font:getFace("scfont", 20), title = "No Title", - height = 500, - width = 500, + dimen = Geom:new{ w = 500, h = 500 }, item_table = {}, item_shortcuts = { "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", @@ -424,17 +416,23 @@ Menu = FocusManager:new{ }, is_enable_shortcut = true, - item_height = 36, + item_dimen = nil, page = 1, - on_select_callback = function() end, - item_group = nil, page_info = nil, + + -- set this to true to not paint as popup menu + is_borderless = false, } function Menu:init() - self.perpage = math.floor(self.height / self.item_height) - 2 + self.item_dimen = Geom:new{ + w = self.dimen.w, + h = 36, -- hardcoded for now + } + + self.perpage = math.floor(self.dimen.h / self.item_dimen.h) - 2 self.page = 1 self.page_num = math.ceil(#self.item_table / self.perpage) @@ -459,21 +457,36 @@ function Menu:init() face = self.fface, } - self[1] = CenterContainer:new{ - FrameContainer:new{ + local content = VerticalGroup:new{ + TextWidget:new{ + text = self.title, + face = self.tface, + }, + self.item_group, + self.page_info, + } -- VerticalGroup + + if not self.is_borderless then + self[1] = CenterContainer:new{ + FrameContainer:new{ + background = 0, + radius = math.floor(self.dimen.w/20), + content + }, + dimen = Screen:getSize(), + } + -- we need to substract border, margin and padding + self.item_dimen.w = self.item_dimen.w - 14 + else + self[1] = FrameContainer:new{ background = 0, - radius = math.floor(self.width/20), - VerticalGroup:new{ - TextWidget:new{ - text = self.title, - face = self.tface, - }, - self.item_group, - self.page_info, - }, -- VerticalGroup - }, -- FrameContainer - dimen = {w = G_width, h = G_height}, - } -- CenterContainer + bordersize = 0, + padding = 0, + margin = 0, + dimen = Screen:getSize(), + content + } + end if #self.item_table > 0 then -- if the table is not yet initialized, this call @@ -503,11 +516,10 @@ function Menu:updateItems() item_shortcut = "Ent" end end - item_tmp = MenuItem:new{ + local item_tmp = MenuItem:new{ text = self.item_table[i].text, face = self.cface, - width = self.width - 14, - height = self.item_height, + dimen = self.item_dimen, shortcut = item_shortcut, shortcut_style = shortcut_style, } @@ -517,11 +529,15 @@ function Menu:updateItems() end -- if i <= self.items end -- for c=1, self.perpage -- set focus to first menu item - self.item_group[1]:onFocus() - -- reset focus manager accordingly - self.selected = { x = 1, y = 1 } - -- update page information - self.page_info.text = "page "..self.page.."/"..self.page_num + if self.item_group[1] then + self.item_group[1]:onFocus() + -- reset focus manager accordingly + self.selected = { x = 1, y = 1 } + -- update page information + self.page_info.text = "page "..self.page.."/"..self.page_num + else + self.page_info.text = "no choices available" + end UIManager:setDirty(self) end @@ -531,16 +547,31 @@ function Menu:onSelectByShortCut(_, keyevent) if k > self.perpage then break elseif v == keyevent.key then - local item = self.item_table[(self.page-1)*self.perpage+k] - self.item_table = nil - UIManager:close(self) - self.on_select_callback(item) + if self.item_table[(self.page-1)*self.perpage + k] then + self:onMenuSelect(self.item_table[(self.page-1)*self.perpage + k]) + end break end end return true end +--[[ +override this function to process the item selected in a different manner +]]-- +function Menu:onMenuSelect(item) + UIManager:close(self) + self:onMenuChoice(item) + return true +end + +--[[ +override this function to handle the choice +]]-- +function Menu:onMenuChoice(item) + return true +end + function Menu:onNextPage() if self.page < self.page_num then self.page = self.page + 1 @@ -558,8 +589,7 @@ function Menu:onPrevPage() end function Menu:onSelect() - UIManager:close(self) - self.on_select_callback(self.item_table[(self.page-1)*self.perpage+self.selected.y]) + self:onMenuSelect(self.item_table[(self.page-1)*self.perpage+self.selected.y]) return true end @@ -567,3 +597,4 @@ function Menu:onClose() UIManager:close(self) return true end + diff --git a/frontend/ui/filechooser.lua b/frontend/ui/filechooser.lua index 62702a288..515f3f8b8 100644 --- a/frontend/ui/filechooser.lua +++ b/frontend/ui/filechooser.lua @@ -43,15 +43,18 @@ function FileChooser:changeToPath(path) Menu.init(self) -- call parent's init() end -function FileChooser:onSelect() - local selected = self.item_table[(self.page-1)*self.perpage+self.selected.y] - if lfs.attributes(selected.path, "mode") == "directory" then +function FileChooser:onMenuSelect(item) + if lfs.attributes(item.path, "mode") == "directory" then UIManager:close(self) - self:changeToPath(selected.path) + self:changeToPath(item.path) UIManager:show(self) else - UIManager:close(self) - self.on_select_callback(self.item_table[self.selected.y]) + self:onFileSelect(item.path) end return true end + +function FileChooser:onFileSelect(file) + UIManager:close(self) + return true +end diff --git a/frontend/ui/geometry.lua b/frontend/ui/geometry.lua index 0fab4dcdc..847569aaa 100644 --- a/frontend/ui/geometry.lua +++ b/frontend/ui/geometry.lua @@ -23,12 +23,12 @@ function Geom:new(o) return o end -function Geom:copy(o) - local n = self:new() - n.x = o.x - n.y = o.y - n.w = o.w - n.h = o.h +function Geom:copy() + local n = Geom:new() + n.x = self.x + n.y = self.y + n.w = self.w + n.h = self.h return n end @@ -42,6 +42,7 @@ offset rectangle or point by relative values function Geom:offsetBy(dx, dy) self.x = self.x + dx self.y = self.y + dy + return self end --[[ @@ -50,6 +51,7 @@ offset rectangle or point to certain coordinates function Geom:offsetTo(x, y) self.x = x self.y = y + return self end --[[ @@ -60,6 +62,18 @@ if a single factor is given, it is applied to both width and height function Geom:scaleBy(zx, zy) self.w = self.w * zx self.h = self.h * (zy or zx) + return self +end + +--[[ +enlarges or shrinks dimensions or rectangles + +note that for rectangles the offset stays the same +]]-- +function Geom:changeSizeBy(dw, dh) + self.w = self.w + dw + self.h = self.h + dh + return self end --[[ @@ -118,12 +132,9 @@ end set size of dimension or rectangle to size of given dimension/rectangle ]]-- function Geom:setSizeTo(rect_b) - if self.w == rect_b.w and self.h == rect_b.h then - return false - end self.w = rect_b.w self.h = rect_b.h - return true + return self end --[[ diff --git a/frontend/ui/reader/readertoc.lua b/frontend/ui/reader/readertoc.lua index 3f3d8a98b..2722870ab 100644 --- a/frontend/ui/reader/readertoc.lua +++ b/frontend/ui/reader/readertoc.lua @@ -2,7 +2,7 @@ ReaderToc = InputContainer:new{ key_events = { ShowToc = { {"T"}, doc = "show Table of Content menu"}, }, - dimen = Geom:new{ w = G_width-20, h = G_height-20}, + dimen = Geom:new{ w = Screen:getWidth()-20, h = Screen:getHeight()-20}, current_page = 0, current_pos = 0, } @@ -51,22 +51,21 @@ function ReaderToc:getTocTitleOfCurrentPage() end function ReaderToc:onShowToc() - function callback(item) - self.ui:handleEvent(Event:new("PageUpdate", item.page)) - end - local items = self.ui.document:getToc() -- build menu items for _,v in ipairs(items) do v.text = (" "):rep(v.depth-1)..self:cleanUpTocTitle(v.title) end - toc_menu = Menu:new{ + local toc_menu = Menu:new{ title = "Table of Contents", item_table = items, width = self.dimen.w, height = self.dimen.h, - on_select_callback = callback, + ui = self.ui } + function toc_menu:onMenuChoice(item) + self.ui:handleEvent(Event:new("PageUpdate", item.page)) + end UIManager:show(toc_menu) end diff --git a/frontend/ui/reader/readerview.lua b/frontend/ui/reader/readerview.lua index 8d6067d57..20c23a202 100644 --- a/frontend/ui/reader/readerview.lua +++ b/frontend/ui/reader/readerview.lua @@ -76,7 +76,7 @@ end function ReaderView:PanningUpdate(dx, dy) DEBUG("pan by", dx, dy) - local old = Geom:copy(self.visible_area) + local old = self.visible_area:copy() self.visible_area:offsetWithin(self.page_area, dx, dy) if self.visible_area ~= old then -- flag a repaint diff --git a/frontend/ui/screen.lua b/frontend/ui/screen.lua index 67312cf3b..9b4b78887 100644 --- a/frontend/ui/screen.lua +++ b/frontend/ui/screen.lua @@ -46,6 +46,8 @@ Screen = { kpv_rotation_mode = nil, saved_bb = nil, + + fb = einkfb.open("/dev/fb0") } -- @orien: 1 for clockwise rotate, -1 for anti-clockwise @@ -61,13 +63,28 @@ function Screen:screenRotate(orien) self.cur_rotation_mode = (self.cur_rotation_mode + orien) % 4 -- you have to reopen framebuffer after rotate - fb:setOrientation(self.cur_rotation_mode) - fb:close() - fb = einkfb.open("/dev/fb0") + self.fb:setOrientation(self.cur_rotation_mode) + self.fb:close() + self.fb = einkfb.open("/dev/fb0") +end + +function Screen:getSize() + local w, h = self.fb:getSize() + return Geom:new{w = w, h = h} +end + +function Screen:getWidth() + local w, _ = self.fb:getSize() + return w +end + +function Screen:getHeight() + local _, h = self.fb:getSize() + return h end function Screen:updateRotationMode() - if KEY_FW_DOWN == 116 then -- in EMU mode always set to 0 + if util.isEmulated() then -- in EMU mode always set to 0 self.cur_rotation_mode = 0 else orie_fd = assert(io.open("/sys/module/eink_fb_hal_broads/parameters/bs_orientation", "r")) @@ -77,7 +94,7 @@ function Screen:updateRotationMode() end function Screen:saveCurrentBB() - local width, height = G_width, G_height + local width, height = self:getWidth(), self.getHeight() if not self.saved_bb then self.saved_bb = Blitbuffer.new(width, height) @@ -94,14 +111,14 @@ function Screen:restoreFromSavedBB() end function Screen:getCurrentScreenBB() - local bb = Blitbuffer.new(G_width, G_height) - bb:blitFullFrom(fb.bb) + local bb = Blitbuffer.new(self:getWidth(), self:getHeight()) + bb:blitFullFrom(self.fb.bb) return bb end function Screen:restoreFromBB(bb) if bb then - fb.bb:blitFullFrom(bb) + self.fb.bb:blitFullFrom(bb) else DEBUG("Got nil bb in restoreFromSavedBB!") end diff --git a/frontend/ui/ui.lua b/frontend/ui/ui.lua index 5c55bedd5..233163ad1 100644 --- a/frontend/ui/ui.lua +++ b/frontend/ui/ui.lua @@ -6,12 +6,7 @@ require "ui/dialog" require "settings" -- for DEBUG(), TODO: put DEBUG() somewhere else --- we also initialize the framebuffer - -fb = einkfb.open("/dev/fb0") -G_width, G_height = fb:getSize() - --- and the input handling +-- initialize the input handling Input:init() @@ -151,7 +146,7 @@ function UIManager:run() local dirty = false for _, widget in ipairs(self._window_stack) do if self._dirty[widget.widget] then - widget.widget:paintTo(fb.bb, widget.x, widget.y) + widget.widget:paintTo(Screen.fb.bb, widget.x, widget.y) -- and remove from list after painting self._dirty[widget.widget] = nil -- trigger repaint @@ -161,7 +156,7 @@ function UIManager:run() if dirty then -- refresh FB - fb:refresh(self.refresh_type) -- TODO: refresh explicitly only repainted area + Screen.fb:refresh(self.refresh_type) -- TODO: refresh explicitly only repainted area -- reset refresh_type self.refresh_type = 0 end diff --git a/frontend/ui/widget.lua b/frontend/ui/widget.lua index 415d577fe..c4ce3713e 100644 --- a/frontend/ui/widget.lua +++ b/frontend/ui/widget.lua @@ -1,3 +1,4 @@ +require "ui/screen" require "ui/rendertext" require "ui/graphics" require "ui/image" @@ -186,10 +187,13 @@ function TextWidget:getSize() --self:_render() --end --return { w = self._length, h = self._bb:getHeight() } - - self._length = sizeUtf8Text(0, G_width, self.face, self.text, true).x + local tsize = sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true) + if not tsize then + return Geom:new{} + end + self._length = tsize.x self._height = self.face.size * 1.5 - return { + return Geom:new{ w = self._length, h = self._height, } @@ -226,7 +230,7 @@ TextBoxWidget = Widget:new{ function TextBoxWidget:_wrapGreedyAlg(h_list) local cur_line_width = 0 - local space_w = sizeUtf8Text(0, G_width, self.face, " ", true).x + local space_w = sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x local cur_line = {} local v_list = {} @@ -255,7 +259,7 @@ function TextBoxWidget:_getVerticalList(alg) for w in self.text:gmatch("%S+") do word_box = {} word_box.word = w - word_box.width = sizeUtf8Text(0, G_width, self.face, w, true).x + word_box.width = sizeUtf8Text(0, Screen:getWidth(), self.face, w, true).x table.insert(h_list, word_box) end @@ -269,7 +273,7 @@ function TextBoxWidget:_render() local v_list = self.v_list local font_height = self.face.size local line_height_px = self.line_height * font_height - local space_w = sizeUtf8Text(0, G_width, self.face, " ", true).x + local space_w = sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x local h = (font_height + line_height_px) * #v_list - line_height_px self._bb = Blitbuffer.new(self.width, h) local y = font_height diff --git a/wtest.lua b/wtest.lua index 0aa7ea31b..b6e9dd065 100644 --- a/wtest.lua +++ b/wtest.lua @@ -6,18 +6,18 @@ require "document/document" TestGrid = Widget:new{} -function TestGrid:paintTo() - v_line = math.floor(G_width / 50) - h_line = math.floor(G_height / 50) +function TestGrid:paintTo(bb) + v_line = math.floor(bb:getWidth() / 50) + h_line = math.floor(bb:getHeight() / 50) for i=1,h_line do y_num = i*50 - renderUtf8Text(fb.bb, 0, y_num+10, Font:getFace("ffont", 12), y_num, true) - fb.bb:paintRect(0, y_num, G_width, 1, 10) + renderUtf8Text(bb, 0, y_num+10, Font:getFace("ffont", 12), y_num, true) + bb:paintRect(0, y_num, bb:getWidth(), 1, 10) end for i=1,v_line do x_num = i*50 - renderUtf8Text(fb.bb, x_num, 10, Font:getFace("ffont", 12), x_num, true) - fb.bb:paintRect(x_num, 0, 1, G_height, 10) + renderUtf8Text(bb, x_num, 10, Font:getFace("ffont", 12), x_num, true) + bb:paintRect(x_num, 0, 1, bb:getHeight(), 10) end end @@ -33,7 +33,7 @@ Background = InputContainer:new{ FrameContainer:new{ background = 3, bordersize = 0, - dimen = { w = G_width, h = G_height } + dimen = Screen:getSize() } } @@ -133,14 +133,14 @@ M = Menu:new{ readerwindow = CenterContainer:new{ - dimen = Geom:new{ w = G_width, h = G_height }, + dimen = Screen:getSize(), FrameContainer:new{ background = 0 } } reader = ReaderUI:new{ dialog = readerwindow, - dimen = Geom:new{ w = G_width - 100, h = G_height - 100 }, + dimen = Geom:new{ w = Screen:getWidth() - 100, h = Screen:getHeight() - 100 }, document = DocumentRegistry:getProvider("test/2col.pdf") --document = DocumentRegistry:getProvider("test/djvu3spec.djvu") --document = DocumentRegistry:getProvider("./README.TXT")