From 668e84290e2a1c248bf6ef81ce11546eab0d6ef5 Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 28 Jul 2013 16:05:51 +0800 Subject: [PATCH 1/3] fix fractional pix returned by scaleByDPI --- frontend/ui/screen.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/ui/screen.lua b/frontend/ui/screen.lua index b3cf969d3..96b9af09f 100644 --- a/frontend/ui/screen.lua +++ b/frontend/ui/screen.lua @@ -131,7 +131,7 @@ function Screen:getDPI() end function Screen:scaleByDPI(px) - return (px * self:getDPI()/167) + return math.floor(px * self:getDPI()/167) end -- make a shortcut to Screen:scaleByDPI From 872ffa576787144569517168aef7c2ecbc9bee12 Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 28 Jul 2013 16:06:45 +0800 Subject: [PATCH 2/3] add vertically scrollable text widget --- frontend/ui/widget/text.lua | 218 ++++++++++++++++++++++++++++++++---- 1 file changed, 199 insertions(+), 19 deletions(-) diff --git a/frontend/ui/widget/text.lua b/frontend/ui/widget/text.lua index c455ea455..e78269491 100644 --- a/frontend/ui/widget/text.lua +++ b/frontend/ui/widget/text.lua @@ -1,6 +1,6 @@ -require "ui/widget/base" require "ui/rendertext" - +require "ui/widget/base" +require "ui/widget/scrollbar" --[[ A TextWidget puts a string on a single line @@ -65,12 +65,25 @@ TextBoxWidget = Widget:new{ bgcolor = 0.0, -- [0.0, 1.0] fgcolor = 1.0, -- [0.0, 1.0] width = 400, -- in pixels + height = nil, + first_line = 1, + virtual_line = 1, -- used by scroll bar line_height = 0.3, -- in em v_list = nil, _bb = nil, _length = 0, } +function TextBoxWidget:init() + local v_list = nil + if self.height then + v_list = self:_getCurrentVerticalList() + else + v_list = self:_getVerticalList() + end + self:_render(v_list) +end + function TextBoxWidget:_wrapGreedyAlg(h_list) local cur_line_width = 0 local space_w = sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x @@ -98,10 +111,13 @@ function TextBoxWidget:_wrapGreedyAlg(h_list) end function TextBoxWidget:_getVerticalList(alg) + if self.vertical_list then + return self.vertical_list + end -- build horizontal list - h_list = {} + local h_list = {} for w in self.text:gmatch("[\33-\127\192-\255]+[\128-\191]*") do - word_box = {} + local word_box = {} word_box.word = w word_box.width = sizeUtf8Text(0, Screen:getWidth(), self.face, w, true).x table.insert(h_list, word_box) @@ -109,12 +125,84 @@ function TextBoxWidget:_getVerticalList(alg) -- @TODO check alg here 25.04 2012 (houqp) -- @TODO replace greedy algorithm with K&P algorithm 25.04 2012 (houqp) - return self:_wrapGreedyAlg(h_list) + self.vertical_list = self:_wrapGreedyAlg(h_list) + return self.vertical_list end -function TextBoxWidget:_render() - self.v_list = self:_getVerticalList() - local v_list = self.v_list +function TextBoxWidget:_getCurrentVerticalList() + local line_height = (1 + self.line_height) * self.face.size + local v_list = self:_getVerticalList() + local current_v_list = {} + local height = 0 + for i = self.first_line, #v_list do + if height < self.height - line_height then + table.insert(current_v_list, v_list[i]) + height = height + line_height + else + break + end + end + return current_v_list +end + +function TextBoxWidget:_getPreviousVerticalList() + local line_height = (1 + self.line_height) * self.face.size + local v_list = self:_getVerticalList() + local previous_v_list = {} + local height = 0 + if self.first_line == 1 then + return self:_getCurrentVerticalList() + end + self.virtual_line = self.first_line + for i = self.first_line - 1, 1, -1 do + if height < self.height - line_height then + table.insert(previous_v_list, 1, v_list[i]) + height = height + line_height + self.virtual_line = self.virtual_line - 1 + else + break + end + end + for i = self.first_line, #v_list do + if height < self.height - line_height then + table.insert(previous_v_list, v_list[i]) + height = height + line_height + else + break + end + end + if self.first_line > #previous_v_list then + self.first_line = self.first_line - #previous_v_list + else + self.first_line = 1 + end + return previous_v_list +end + +function TextBoxWidget:_getNextVerticalList() + local line_height = (1 + self.line_height) * self.face.size + local v_list = self:_getVerticalList() + local current_v_list = self:_getCurrentVerticalList() + local next_v_list = {} + local height = 0 + if self.first_line + #current_v_list > #v_list then + return current_v_list + end + self.virtual_line = self.first_line + for i = self.first_line + #current_v_list, #v_list do + if height < self.height - line_height then + table.insert(next_v_list, v_list[i]) + height = height + line_height + self.virtual_line = self.virtual_line + 1 + else + break + end + end + self.first_line = self.first_line + #current_v_list + return next_v_list +end + +function TextBoxWidget:_render(v_list) local font_height = self.face.size local line_height_px = self.line_height * font_height local space_w = sizeUtf8Text(0, Screen:getWidth(), self.face, " ", true).x @@ -134,23 +222,47 @@ function TextBoxWidget:_render() end y = y + line_height_px + font_height end - -- if text is shorter than one line, shrink to text's width - if #v_list == 1 then - self.width = pen_x - end +-- -- if text is shorter than one line, shrink to text's width +-- if #v_list == 1 then +-- self.width = pen_x +-- end +end + +function TextBoxWidget:getVirtualLineNum() + return self.virtual_line +end + +function TextBoxWidget:getAllLineCount() + local v_list = self:_getVerticalList() + return #v_list +end + +function TextBoxWidget:getVisLineCount() + local line_height = (1 + self.line_height) * self.face.size + return math.floor(self.height / line_height) +end + +function TextBoxWidget:scrollDown() + local next_v_list = self:_getNextVerticalList() + self:free() + self:_render(next_v_list) +end + +function TextBoxWidget:scrollUp() + local previous_v_list = self:_getPreviousVerticalList() + self:free() + self:_render(previous_v_list) end function TextBoxWidget:getSize() - if not self._bb then - self:_render() + if self.width and self.height then + return Geom:new{ w = self.width, h = self.height} + else + return Geom:new{ w = self.width, h = self._bb:getHeight()} end - return { w = self.width, h = self._bb:getHeight() } end function TextBoxWidget:paintTo(bb, x, y) - if not self._bb then - self:_render() - end bb:blitFrom(self._bb, x, y, 0, 0, self.width, self._bb:getHeight()) end @@ -161,7 +273,6 @@ function TextBoxWidget:free() end end - --[[ FixedTextWidget --]] @@ -183,3 +294,72 @@ function FixedTextWidget:paintTo(bb, x, y) renderUtf8Text(bb, x, y+self._height, self.face, self.text, true, self.bgcolor, self.fgcolor) end + +--[[ +Text widget with vertical scroll bar +--]] +ScrollTextWidget = InputContainer:new{ + text = nil, + font_face = nil, + width = 400, + height = 300, + scroll_bar_width = scaleByDPI(6), + text_scroll_span = scaleByDPI(6), + dialog = nil, +} + +function ScrollTextWidget:init() + self.text_widget = TextBoxWidget:new{ + text = self.text, + face = self.font_face, + width = self.width - self.scroll_bar_width - self.text_scroll_span, + height = self.height + } + local visible_line_count = self.text_widget:getVisLineCount() + local total_line_count = self.text_widget:getAllLineCount() + self.v_scroll_bar = VerticalScrollBar:new{ + enable = visible_line_count < total_line_count, + low = 0, + high = visible_line_count/total_line_count, + width = scaleByDPI(6), + height = self.height, + } + local horizontal_group = HorizontalGroup:new{} + table.insert(horizontal_group, self.text_widget) + table.insert(horizontal_group, HorizontalSpan:new{width = scaleByDPI(6)}) + table.insert(horizontal_group, self.v_scroll_bar) + self[1] = horizontal_group + self.dimen = Geom:new(self[1]:getSize()) + if Device:isTouchDevice() then + self.ges_events = { + Swipe = { + GestureRange:new{ + ges = "swipe", + range = self.dimen, + }, + }, + } + end +end + +function ScrollTextWidget:updateScrollBar(text) + local virtual_line_num = text:getVirtualLineNum() + local visible_line_count = text:getVisLineCount() + local all_line_count = text:getAllLineCount() + self.v_scroll_bar:set( + (virtual_line_num - 1) / all_line_count, + (virtual_line_num - 1 + visible_line_count) / all_line_count + ) +end + +function ScrollTextWidget:onSwipe(arg, ges) + if ges.direction == "north" then + self.text_widget:scrollDown() + self:updateScrollBar(self.text_widget) + elseif ges.direction == "south" then + self.text_widget:scrollUp() + self:updateScrollBar(self.text_widget) + end + UIManager:setDirty(self.dialog, "partial") + return true +end From 6c7641cd0b4650f9089681d9f1bdcd5e0fdec580 Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 28 Jul 2013 16:07:51 +0800 Subject: [PATCH 3/3] fix long definition not shown properly in dictionary window --- frontend/ui/reader/readerdictionary.lua | 1 + frontend/ui/widget/dict.lua | 66 ++++++++++++++++--------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/frontend/ui/reader/readerdictionary.lua b/frontend/ui/reader/readerdictionary.lua index 391e71995..17e3f7769 100644 --- a/frontend/ui/reader/readerdictionary.lua +++ b/frontend/ui/reader/readerdictionary.lua @@ -39,6 +39,7 @@ function ReaderDictionary:showDict(results) results = results, dictionary = self.default_dictionary, width = Screen:getWidth() - scaleByDPI(120), + height = Screen:getHeight()*0.43, }) end end diff --git a/frontend/ui/widget/dict.lua b/frontend/ui/widget/dict.lua index c0cce51a4..482352e34 100644 --- a/frontend/ui/widget/dict.lua +++ b/frontend/ui/widget/dict.lua @@ -14,35 +14,43 @@ DictQuickLookup = InputContainer:new{ word_face = Font:getFace("tfont", 20), content_face = Font:getFace("cfont", 20), width = nil, + height = nil, title_padding = scaleByDPI(5), title_margin = scaleByDPI(2), - word_padding = scaleByDPI(5), + word_padding = scaleByDPI(2), word_margin = scaleByDPI(2), - definition_padding = scaleByDPI(5), + definition_padding = scaleByDPI(2), definition_margin = scaleByDPI(2), button_padding = scaleByDPI(14), } function DictQuickLookup:init() - if Device:hasKeyboard() then - key_events = { - AnyKeyPressed = { { Input.group.Any }, - seqtext = "any key", doc = _("close dialog") } - } - else - self.ges_events.TapCloseDict = { - GestureRange:new{ - ges = "tap", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight(), - } - } + self:changeToDefaultDict() + if Device:isTouchDevice() then + self.ges_events = { + TapCloseDict = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight(), + } + }, + }, + Swipe = { + GestureRange:new{ + ges = "swipe", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight(), + } + }, + }, } end - self:changeToDefaultDict() end function DictQuickLookup:update() @@ -73,10 +81,12 @@ function DictQuickLookup:update() padding = self.definition_padding, margin = self.definition_margin, bordersize = 0, - TextBoxWidget:new{ + ScrollTextWidget:new{ text = self.definition, - face = self.content_face, + font_face = self.content_face, width = self.width, + height = self.height*0.8, + dialog = self, }, } local button_table = ButtonTable:new{ @@ -138,9 +148,21 @@ function DictQuickLookup:update() self.dict_title, title_bar, -- word - lookup_word, + CenterContainer:new{ + dimen = Geom:new{ + w = title_bar:getSize().w, + h = lookup_word:getSize().h, + }, + lookup_word, + }, -- definition - definition, + CenterContainer:new{ + dimen = Geom:new{ + w = title_bar:getSize().w, + h = definition:getSize().h, + }, + definition, + }, -- buttons CenterContainer:new{ dimen = Geom:new{