From 1036db89b65ff0777920ec4f677f3d1631436eb5 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Wed, 25 Apr 2012 12:39:02 +0800 Subject: [PATCH] add TextBoxWidget that handles line wrapping --- widget.lua | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/widget.lua b/widget.lua index 8d74abe8e..b7046ae7b 100644 --- a/widget.lua +++ b/widget.lua @@ -193,6 +193,101 @@ function TextWidget:free() end end +--[[ +A TextWidget that handles long text wrapping +]] +TextBoxWidget = Widget:new{ + text = nil, + face = nil, + color = 15, + width = 400, -- in pixels + line_height = 0.3, -- in em + v_list = nil, + _bb = nil, + _length = 0, +} + +function TextBoxWidget:_wrapGreedyAlg(h_list) + local cur_line_width = 0 + local space_w = sizeUtf8Text(0, G_width, self.face, " ", true).x + local cur_line = {} + local v_list = {} + + for k,w in ipairs(h_list) do + cur_line_width = cur_line_width + w.width + if cur_line_width <= self.width then + cur_line_width = cur_line_width + space_w + table.insert(cur_line, w) + else + -- wrap to next line + table.insert(v_list, cur_line) + cur_line = {} + cur_line_width = w.width + space_w + table.insert(cur_line, w) + end + end + -- handle last line + table.insert(v_list, cur_line) + + return v_list +end + +function TextBoxWidget:_getVerticalList(alg) + -- build horizontal list + h_list = {} + 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 + table.insert(h_list, word_box) + end + + -- @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) +end + +function TextBoxWidget:_render() + self.v_list = self:_getVerticalList() + 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 h = (font_height + line_height_px) * #v_list - line_height_px + self._bb = Blitbuffer.new(self.width, h) + local y = font_height + + for _,l in ipairs(v_list) do + local pen_x = 0 + for _,w in ipairs(l) do + renderUtf8Text(self._bb, pen_x, y, self.face, w.word, true) + pen_x = pen_x + w.width + space_w + end + y = y + line_height_px + font_height + end +end + +function TextBoxWidget:getSize() + if not self._bb then + self:_render() + 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 + +function TextBoxWidget:free() + if self._bb then + self._bb:free() + self._bb = nil + end +end + --[[ ImageWidget shows an image from a file ]]