fix indent sytle

pull/2028/head
union2find 8 years ago
parent 3d89b27e59
commit f8943efdbf

@ -18,7 +18,7 @@ local InputText = InputContainer:new{
charpos = nil, -- position to insert a new char, or the position of the cursor charpos = nil, -- position to insert a new char, or the position of the cursor
input_type = nil, input_type = nil,
text_type = nil, text_type = nil,
text_widget = nil, -- Text Widget for cursor movement text_widget = nil, -- Text Widget for cursor movement
width = nil, width = nil,
height = nil, height = nil,
@ -50,15 +50,15 @@ if Device.isTouchDevice() then
function InputText:onTapTextBox(arg, ges) function InputText:onTapTextBox(arg, ges)
if self.parent.onSwitchFocus then if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self) self.parent:onSwitchFocus(self)
else else
local x = ges.pos.x - self.dimen.x - self.bordersize - self.padding local x = ges.pos.x - self.dimen.x - self.bordersize - self.padding
local y = ges.pos.y - self.dimen.y - self.bordersize - self.padding local y = ges.pos.y - self.dimen.y - self.bordersize - self.padding
if x > 0 and y > 0 then if x > 0 and y > 0 then
self.charpos = self.text_widget:moveCursor(x, y) self.charpos = self.text_widget:moveCursor(x, y)
UIManager:setDirty(self.parent, function() UIManager:setDirty(self.parent, function()
return "ui", self[1].dimen return "ui", self[1].dimen
end) end)
end end
end end
end end
else else
@ -74,10 +74,10 @@ end
function InputText:initTextBox(text) function InputText:initTextBox(text)
self.text = text self.text = text
util.splitToChars(text, self.charlist) util.splitToChars(text, self.charlist)
if self.charpos == nil then if self.charpos == nil then
self.charpos = #self.charlist + 1 self.charpos = #self.charlist + 1
end end
local fgcolor = Blitbuffer.gray(self.text == "" and 0.5 or 1.0) local fgcolor = Blitbuffer.gray(self.text == "" and 0.5 or 1.0)
local show_text = self.text local show_text = self.text
@ -88,9 +88,9 @@ function InputText:initTextBox(text)
if self.scroll then if self.scroll then
self.text_widget = ScrollTextWidget:new{ self.text_widget = ScrollTextWidget:new{
text = show_text, text = show_text,
charlist = self.charlist, charlist = self.charlist,
charpos = self.charpos, charpos = self.charpos,
editable = true, editable = true,
face = self.face, face = self.face,
fgcolor = fgcolor, fgcolor = fgcolor,
width = self.width, width = self.width,
@ -99,9 +99,9 @@ function InputText:initTextBox(text)
else else
self.text_widget = TextBoxWidget:new{ self.text_widget = TextBoxWidget:new{
text = show_text, text = show_text,
charlist = self.charlist, charlist = self.charlist,
charpos = self.charpos, charpos = self.charpos,
editable = true, editable = true,
face = self.face, face = self.face,
fgcolor = fgcolor, fgcolor = fgcolor,
width = self.width, width = self.width,

@ -16,9 +16,9 @@ Text widget with vertical scroll bar
--]] --]]
local ScrollTextWidget = InputContainer:new{ local ScrollTextWidget = InputContainer:new{
text = nil, text = nil,
charlist = nil, charlist = nil,
charpos = nil, charpos = nil,
editable = false, editable = false,
face = nil, face = nil,
fgcolor = Blitbuffer.COLOR_BLACK, fgcolor = Blitbuffer.COLOR_BLACK,
width = 400, width = 400,
@ -31,9 +31,9 @@ local ScrollTextWidget = InputContainer:new{
function ScrollTextWidget:init() function ScrollTextWidget:init()
self.text_widget = TextBoxWidget:new{ self.text_widget = TextBoxWidget:new{
text = self.text, text = self.text,
charlist = self.charlist, charlist = self.charlist,
charpos = self.charpos, charpos = self.charpos,
editable = self.editable, editable = self.editable,
face = self.face, face = self.face,
fgcolor = self.fgcolor, fgcolor = self.fgcolor,
width = self.width - self.scroll_bar_width - self.text_scroll_span, width = self.width - self.scroll_bar_width - self.text_scroll_span,
@ -76,10 +76,10 @@ function ScrollTextWidget:scrollText(direction)
if direction == 0 then return end if direction == 0 then return end
if direction > 0 then if direction > 0 then
low, high = self.text_widget:scrollDown() low, high = self.text_widget:scrollDown()
self.v_scroll_bar:set(low, high) self.v_scroll_bar:set(low, high)
else else
low, high = self.text_widget:scrollUp() low, high = self.text_widget:scrollUp()
self.v_scroll_bar:set(low, high) self.v_scroll_bar:set(low, high)
end end
UIManager:setDirty(self.dialog, function() UIManager:setDirty(self.dialog, function()
return "partial", self.dimen return "partial", self.dimen

@ -12,12 +12,12 @@ A TextWidget that handles long text wrapping
--]] --]]
local TextBoxWidget = Widget:new{ local TextBoxWidget = Widget:new{
text = nil, text = nil,
charlist = nil, charlist = nil,
charpos = nil, charpos = nil,
char_width_list = nil, -- list of widths of the chars in `charlist`. char_width_list = nil, -- list of widths of the chars in `charlist`.
vertical_string_list = nil, vertical_string_list = nil,
editable = false, -- Editable flag for whether drawing the cursor or not. editable = false, -- Editable flag for whether drawing the cursor or not.
cursor_line = nil, -- LineWidget to draw the vertical cursor. cursor_line = nil, -- LineWidget to draw the vertical cursor.
face = nil, face = nil,
bold = nil, bold = nil,
line_height = 0.3, -- in em line_height = 0.3, -- in em
@ -29,127 +29,127 @@ local TextBoxWidget = Widget:new{
} }
function TextBoxWidget:init() function TextBoxWidget:init()
local line_height = (1 + self.line_height) * self.face.size local line_height = (1 + self.line_height) * self.face.size
local font_height = self.face.size local font_height = self.face.size
self.cursor_line = LineWidget:new{ self.cursor_line = LineWidget:new{
dimen = Geom:new{ dimen = Geom:new{
w = Screen:scaleBySize(1), w = Screen:scaleBySize(1),
h = line_height, h = line_height,
} }
} }
self:_evalCharWidthList() self:_evalCharWidthList()
self:_splitCharWidthList() self:_splitCharWidthList()
if self.height == nil then if self.height == nil then
self:_renderText(1, #self.vertical_string_list) self:_renderText(1, #self.vertical_string_list)
else else
self:_renderText(1, self:getVisLineCount()) self:_renderText(1, self:getVisLineCount())
end end
if self.editable then if self.editable then
x, y = self:_findCharPos() x, y = self:_findCharPos()
self.cursor_line:paintTo(self._bb, x, y) self.cursor_line:paintTo(self._bb, x, y)
end end
self.dimen = Geom:new(self:getSize()) self.dimen = Geom:new(self:getSize())
end end
-- Return whether the text widget is editable. -- Return whether the text widget is editable.
function TextBoxWidget:isEditable() function TextBoxWidget:isEditable()
return self.editable return self.editable
end end
-- Evaluate the width of each char in `self.charlist`. -- Evaluate the width of each char in `self.charlist`.
function TextBoxWidget:_evalCharWidthList() function TextBoxWidget:_evalCharWidthList()
if self.charlist == nil then if self.charlist == nil then
self.charlist = {} self.charlist = {}
util.splitToChars(self.text, self.charlist) util.splitToChars(self.text, self.charlist)
self.charpos = #self.charlist + 1 self.charpos = #self.charlist + 1
end end
self.char_width_list = {} self.char_width_list = {}
for _, v in ipairs(self.charlist) do for _, v in ipairs(self.charlist) do
w = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, v, true, self.bold).x w = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, v, true, self.bold).x
table.insert(self.char_width_list, {char = v, width = w}) table.insert(self.char_width_list, {char = v, width = w})
end end
end end
-- Split the text into logical lines to fit into the text box. -- Split the text into logical lines to fit into the text box.
function TextBoxWidget:_splitCharWidthList() function TextBoxWidget:_splitCharWidthList()
self.vertical_string_list = {} self.vertical_string_list = {}
self.vertical_string_list[1] = {text = "Demo hint", offset = 1, width = 0} -- hint for empty string self.vertical_string_list[1] = {text = "Demo hint", offset = 1, width = 0} -- hint for empty string
local idx = 1 local idx = 1
local offset = 1 local offset = 1
local cur_line_width = 0 local cur_line_width = 0
local cur_line_text = nil local cur_line_text = nil
local size = #self.char_width_list local size = #self.char_width_list
local ln = 1 local ln = 1
while idx <= size do while idx <= size do
offset = idx offset = idx
-- Appending chars until the accumulated width exceeds `self.width`, -- Appending chars until the accumulated width exceeds `self.width`,
-- or a newline occurs, or no more chars to consume. -- or a newline occurs, or no more chars to consume.
cur_line_width = 0 cur_line_width = 0
local hard_newline = false local hard_newline = false
cur_line_text = nil cur_line_text = nil
while idx <= size do while idx <= size do
if self.char_width_list[idx].char == "\n" then if self.char_width_list[idx].char == "\n" then
hard_newline = true hard_newline = true
break break
end end
cur_line_width = cur_line_width + self.char_width_list[idx].width cur_line_width = cur_line_width + self.char_width_list[idx].width
if cur_line_width > self.width then break else idx = idx + 1 end if cur_line_width > self.width then break else idx = idx + 1 end
end end
if cur_line_width <= self.width then -- a hard newline or end of string if cur_line_width <= self.width then -- a hard newline or end of string
cur_line_text = table.concat(self.charlist, "", offset, idx - 1) cur_line_text = table.concat(self.charlist, "", offset, idx - 1)
else else
-- Backtrack the string until the length fit into one line. -- Backtrack the string until the length fit into one line.
local c = self.char_width_list[idx].char local c = self.char_width_list[idx].char
if util.isSplitable(c) then if util.isSplitable(c) then
cur_line_text = table.concat(self.charlist, "", offset, idx - 1) cur_line_text = table.concat(self.charlist, "", offset, idx - 1)
cur_line_width = cur_line_width - self.char_width_list[idx].width cur_line_width = cur_line_width - self.char_width_list[idx].width
else else
local adjusted_idx = idx local adjusted_idx = idx
local adjusted_width = cur_line_width local adjusted_width = cur_line_width
repeat repeat
adjusted_width = adjusted_width - self.char_width_list[adjusted_idx].width adjusted_width = adjusted_width - self.char_width_list[adjusted_idx].width
adjusted_idx = adjusted_idx - 1 adjusted_idx = adjusted_idx - 1
c = self.char_width_list[adjusted_idx].char c = self.char_width_list[adjusted_idx].char
until adjusted_idx > offset and util.isSplitable(c) until adjusted_idx > offset and util.isSplitable(c)
if adjusted_idx == offset then -- a very long english word ocuppying more than one line if adjusted_idx == offset then -- a very long english word ocuppying more than one line
cur_line_text = table.concat(self.charlist, "", offset, idx - 1) cur_line_text = table.concat(self.charlist, "", offset, idx - 1)
cur_line_width = cur_line_width - self.char_width_list[idx].width cur_line_width = cur_line_width - self.char_width_list[idx].width
else else
cur_line_text = table.concat(self.charlist, "", offset, adjusted_idx) cur_line_text = table.concat(self.charlist, "", offset, adjusted_idx)
cur_line_width = adjusted_line_width cur_line_width = adjusted_line_width
idx = adjusted_idx + 1 idx = adjusted_idx + 1
end end
end -- endif util.isSplitable(c) end -- endif util.isSplitable(c)
end -- endif cur_line_width > self.width end -- endif cur_line_width > self.width
self.vertical_string_list[ln] = {text = cur_line_text, offset = offset, width = cur_line_width} self.vertical_string_list[ln] = {text = cur_line_text, offset = offset, width = cur_line_width}
if hard_newline then if hard_newline then
idx = idx + 1 idx = idx + 1
self.vertical_string_list[ln + 1] = {text = "", offset = idx, width = 0} self.vertical_string_list[ln + 1] = {text = "", offset = idx, width = 0}
end end
ln = ln + 1 ln = ln + 1
-- Make sure `idx` point to the next char to be processed in the next loop. -- Make sure `idx` point to the next char to be processed in the next loop.
end end
end end
function TextBoxWidget:_renderText(start_row_idx, end_row_idx) function TextBoxWidget:_renderText(start_row_idx, end_row_idx)
local font_height = self.face.size local font_height = self.face.size
local line_height = (1 + self.line_height) * font_height local line_height = (1 + self.line_height) * font_height
if start_row_idx < 1 then start_row_idx = 1 end if start_row_idx < 1 then start_row_idx = 1 end
if end_row_idx > #self.vertical_string_list then end_row_idx = #self.vertical_string_list end if end_row_idx > #self.vertical_string_list then end_row_idx = #self.vertical_string_list end
local row_count = end_row_idx == 0 and 1 or end_row_idx - start_row_idx + 1 local row_count = end_row_idx == 0 and 1 or end_row_idx - start_row_idx + 1
local h = line_height * row_count local h = line_height * row_count
self._bb = Blitbuffer.new(self.width, h) self._bb = Blitbuffer.new(self.width, h)
self._bb:fill(Blitbuffer.COLOR_WHITE) self._bb:fill(Blitbuffer.COLOR_WHITE)
local y = font_height local y = font_height
for i = start_row_idx, end_row_idx do for i = start_row_idx, end_row_idx do
local line = self.vertical_string_list[i] local line = self.vertical_string_list[i]
local pen_x = self.alignment == "center" and (self.width - line.width)/2 or 0 local pen_x = self.alignment == "center" and (self.width - line.width)/2 or 0
--@TODO Don't use kerning for monospaced fonts. (houqp) --@TODO Don't use kerning for monospaced fonts. (houqp)
-- refert to cb25029dddc42693cc7aaefbe47e9bd3b7e1a750 in master tree -- refert to cb25029dddc42693cc7aaefbe47e9bd3b7e1a750 in master tree
RenderText:renderUtf8Text(self._bb, pen_x, y, self.face, line.text, true, self.bold, self.fgcolor) RenderText:renderUtf8Text(self._bb, pen_x, y, self.face, line.text, true, self.bold, self.fgcolor)
y = y + line_height y = y + line_height
end end
-- -- if text is shorter than one line, shrink to text's width -- -- if text is shorter than one line, shrink to text's width
-- if #v_list == 1 then -- if #v_list == 1 then
-- self.width = pen_x -- self.width = pen_x
@ -159,50 +159,50 @@ end
-- Return the position of the cursor corresponding to `self.charpos`, -- Return the position of the cursor corresponding to `self.charpos`,
-- Be aware of virtual line number of the scorllTextWidget. -- Be aware of virtual line number of the scorllTextWidget.
function TextBoxWidget:_findCharPos() function TextBoxWidget:_findCharPos()
-- Find the line number. -- Find the line number.
local ln = self.height == nil and 1 or self.virtual_line_num local ln = self.height == nil and 1 or self.virtual_line_num
while ln + 1 <= #self.vertical_string_list do while ln + 1 <= #self.vertical_string_list do
if self.vertical_string_list[ln + 1].offset > self.charpos then break else ln = ln + 1 end if self.vertical_string_list[ln + 1].offset > self.charpos then break else ln = ln + 1 end
end end
-- Find the offset at the current line. -- Find the offset at the current line.
local x = 0 local x = 0
local offset = self.vertical_string_list[ln].offset local offset = self.vertical_string_list[ln].offset
while offset < self.charpos do while offset < self.charpos do
x = x + self.char_width_list[offset].width x = x + self.char_width_list[offset].width
offset = offset + 1 offset = offset + 1
end end
local line_height = (1 + self.line_height) * self.face.size local line_height = (1 + self.line_height) * self.face.size
return x + 1, (ln - 1) * line_height -- offset `x` by 1 to avoid overlap return x + 1, (ln - 1) * line_height -- offset `x` by 1 to avoid overlap
end end
-- Click event: Move the cursor to a new location with (x, y), in pixels. -- Click event: Move the cursor to a new location with (x, y), in pixels.
-- Be aware of virtual line number of the scorllTextWidget. -- Be aware of virtual line number of the scorllTextWidget.
function TextBoxWidget:moveCursor(x, y) function TextBoxWidget:moveCursor(x, y)
local w = 0 local w = 0
local h = 0 local h = 0
local line_height = (1 + self.line_height) * self.face.size local line_height = (1 + self.line_height) * self.face.size
local ln = self.height == nil and 1 or self.virtual_line_num local ln = self.height == nil and 1 or self.virtual_line_num
ln = ln + math.ceil(y / line_height) - 1 ln = ln + math.ceil(y / line_height) - 1
if ln > #self.vertical_string_list then if ln > #self.vertical_string_list then
ln = #self.vertical_string_list ln = #self.vertical_string_list
x = self.width x = self.width
end end
local offset = self.vertical_string_list[ln].offset local offset = self.vertical_string_list[ln].offset
local idx = ln == #self.vertical_string_list and #self.char_width_list or self.vertical_string_list[ln + 1].offset - 1 local idx = ln == #self.vertical_string_list and #self.char_width_list or self.vertical_string_list[ln + 1].offset - 1
while offset <= idx do while offset <= idx do
w = w + self.char_width_list[offset].width w = w + self.char_width_list[offset].width
if w > x then break else offset = offset + 1 end if w > x then break else offset = offset + 1 end
end end
if w > x then if w > x then
local w_prev = w - self.char_width_list[offset].width local w_prev = w - self.char_width_list[offset].width
if x - w_prev < w - x then -- the previous one is more closer if x - w_prev < w - x then -- the previous one is more closer
w = w_prev w = w_prev
end end
end end
self:free() self:free()
self:_renderText(1, #self.vertical_string_list) self:_renderText(1, #self.vertical_string_list)
self.cursor_line:paintTo(self._bb, w + 1, (ln - self.virtual_line_num) * line_height) self.cursor_line:paintTo(self._bb, w + 1, (ln - self.virtual_line_num) * line_height)
return offset return offset
end end
function TextBoxWidget:getVisLineCount() function TextBoxWidget:getVisLineCount()
@ -211,34 +211,34 @@ function TextBoxWidget:getVisLineCount()
end end
function TextBoxWidget:getAllLineCount() function TextBoxWidget:getAllLineCount()
return #self.vertical_string_list return #self.vertical_string_list
end end
-- TODO: modify `charpos` so that it can render the cursor -- TODO: modify `charpos` so that it can render the cursor
function TextBoxWidget:scrollDown() function TextBoxWidget:scrollDown()
local visible_line_count = self:getVisLineCount() local visible_line_count = self:getVisLineCount()
if self.virtual_line_num + visible_line_count <= #self.vertical_string_list then if self.virtual_line_num + visible_line_count <= #self.vertical_string_list then
self:free() self:free()
self.virtual_line_num = self.virtual_line_num + visible_line_count self.virtual_line_num = self.virtual_line_num + visible_line_count
self:_renderText(self.virtual_line_num, self.virtual_line_num + visible_line_count - 1) self:_renderText(self.virtual_line_num, self.virtual_line_num + visible_line_count - 1)
end end
return (self.virtual_line_num - 1) / #self.vertical_string_list, (self.virtual_line_num - 1 + visible_line_count) / #self.vertical_string_list return (self.virtual_line_num - 1) / #self.vertical_string_list, (self.virtual_line_num - 1 + visible_line_count) / #self.vertical_string_list
end end
-- TODO: modify `charpos` so that it can render the cursor -- TODO: modify `charpos` so that it can render the cursor
function TextBoxWidget:scrollUp() function TextBoxWidget:scrollUp()
local visible_line_count = self:getVisLineCount() local visible_line_count = self:getVisLineCount()
if self.virtual_line_num > 1 then if self.virtual_line_num > 1 then
self:free() self:free()
if self.virtual_line_num <= visible_line_count then if self.virtual_line_num <= visible_line_count then
self.virtual_line_num = 1 self.virtual_line_num = 1
else else
self.virtual_line_num = self.virtual_line_num - visible_line_count self.virtual_line_num = self.virtual_line_num - visible_line_count
end end
self:_renderText(self.virtual_line_num, self.virtual_line_num + visible_line_count - 1) self:_renderText(self.virtual_line_num, self.virtual_line_num + visible_line_count - 1)
end end
return (self.virtual_line_num - 1) / #self.vertical_string_list, (self.virtual_line_num - 1 + visible_line_count) / #self.vertical_string_list return (self.virtual_line_num - 1) / #self.vertical_string_list, (self.virtual_line_num - 1 + visible_line_count) / #self.vertical_string_list
end end
function TextBoxWidget:getSize() function TextBoxWidget:getSize()

@ -101,11 +101,11 @@ end
-- @text: the string to be splitted. -- @text: the string to be splitted.
-- @tab: the table to store the chars sequentially, must not be nil. -- @tab: the table to store the chars sequentially, must not be nil.
function util.splitToChars(text, tab) function util.splitToChars(text, tab)
if text == nil then return end if text == nil then return end
-- clear -- clear
for k, v in pairs(tab) do for k, v in pairs(tab) do
tab[k] = nil tab[k] = nil
end end
local prevcharcode, charcode = 0 local prevcharcode, charcode = 0
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
charcode = BaseUtil.utf8charcode(uchar) charcode = BaseUtil.utf8charcode(uchar)
@ -118,7 +118,7 @@ end
-- Test whether a string could be separated by a char for multi-line rendering -- Test whether a string could be separated by a char for multi-line rendering
function util.isSplitable(c) function util.isSplitable(c)
return #c > 1 or c == " " or string.match(c, "%p") ~= nil return #c > 1 or c == " " or string.match(c, "%p") ~= nil
end end
return util return util

Loading…
Cancel
Save