ui(kvpage) truncate title/key/value if it's too long

This commit is contained in:
Qingping Hou
2016-02-15 17:56:13 -08:00
parent e410ce14df
commit 3bec9cea89
2 changed files with 90 additions and 30 deletions

View File

@@ -9,7 +9,7 @@ local BlitBuffer = require("ffi/blitbuffer")
local DEBUG = require("dbg")
--[[
TODO: all these functions should probably be methods on Face objects
@TODO: all these functions should probably be methods on Face objects
]]--
local RenderText = {}
@@ -99,9 +99,18 @@ function RenderText:getGlyph(face, charcode, bold)
return rendered_glyph
end
--- Return a substring of a given text that meets the maximum width (in pixels)
-- restriction.
--
-- @string text text to truncate
-- @tparam ui.font.FontFaceObj face font face for the text
-- @int width maximum width in pixels
-- @bool[opt=false] kerning whether the text should be measured with kerning
-- @bool[opt=false] bold whether the text should be measured as bold
-- @treturn string
function RenderText:getSubTextByWidth(text, face, width, kerning, bold)
local pen_x = 0
local prevcharcode = 0
local prevcharcode
local char_list = {}
for _, charcode, uchar in utf8Chars(text) do
if pen_x < width then
@@ -127,13 +136,13 @@ end
-- Note this function does not render the text into a bitmap. Use it if you
-- only care about the size for the rendered result.
--
---- @int x start position for a given text (within maxium width)
---- @int width maxium rendering width (think of it as size of the bitmap)
---- @tparam ui.font.FontFaceObj face font face that will be used for rendering
---- @string text text to measure
---- @bool[opt=false] kerning whether the text should be measured with kerning
---- @bool[opt=false] bold whether the text should be measured as bold
---- @treturn RenderTextSize
-- @int x start position for a given text (within maximum width)
-- @int width maximum rendering width in pixels (think of it as size of the bitmap)
-- @tparam ui.font.FontFaceObj face font face that will be used for rendering
-- @string text text to measure
-- @bool[opt=false] kerning whether the text should be measured with kerning
-- @bool[opt=false] bold whether the text should be measured as bold
-- @treturn RenderTextSize
function RenderText:sizeUtf8Text(x, width, face, text, kerning, bold)
if not text then
DEBUG("sizeUtf8Text called without text");

View File

@@ -32,25 +32,56 @@ local CloseButton = require("ui/widget/closebutton")
local UIManager = require("ui/uimanager")
local TextWidget = require("ui/widget/textwidget")
local GestureRange = require("ui/gesturerange")
local RenderText = require("ui/rendertext")
local Geom = require("ui/geometry")
local Font = require("ui/font")
local Device = require("device")
local Screen = Device.screen
local ellipsis, space = "...", " "
local ellipsis_width, space_width
function truncateTextByWidth(text, face, max_width, prepend_space)
if not ellipsis_width then
ellipsis_width = RenderText:sizeUtf8Text(0, max_width, face, ellipsis).x
end
if not space_width then
space_width = RenderText:sizeUtf8Text(0, max_width, face, space).x
end
local new_txt_width = max_width - ellipsis_width - space_width
local sub_txt = RenderText:getSubTextByWidth(text, face, new_txt_width)
if prepend_space then
return space.. sub_txt .. ellipsis
else
return sub_txt .. ellipsis .. space
end
end
local KeyValueTitle = VerticalGroup:new{
kv_page = nil,
title = "",
tface = Font:getFace("tfont"),
align = "left",
}
function KeyValueTitle:init()
self.close_button = CloseButton:new{ window = self }
local btn_width = self.close_button:getSize().w
local title_txt_width = RenderText:sizeUtf8Text(
0, self.width, self.tface, self.title).x
local show_title_txt
if self.width < (title_txt_width + btn_width) then
show_title_txt = truncateTextByWidth(
self.title, self.tface, self.width-btn_width)
else
show_title_txt = self.title
end
table.insert(self, OverlapGroup:new{
dimen = { w = self.width },
TextWidget:new{
text = self.title,
face = Font:getFace("tfont", 26),
text = show_title_txt,
face = self.tface,
},
self.close_button,
})
@@ -100,7 +131,7 @@ end
local KeyValueItem = InputContainer:new{
key = nil,
value = nil,
cface = Font:getFace("cfont", 24),
cface = Font:getFace("cfont"),
width = nil,
height = nil,
}
@@ -117,20 +148,40 @@ function KeyValueItem:init()
}
end
self[1] = OverlapGroup:new{
dimen = self.dimen:copy(),
LeftContainer:new{
local key_w = RenderText:sizeUtf8Text(0, self.width, self.cface, self.key).x
local value_w = RenderText:sizeUtf8Text(0, self.width, self.cface, self.value).x
if key_w + value_w > self.width then
-- truncate key or value so they fits in one row
if key_w >= value_w then
self.show_key = truncateTextByWidth(self.key, self.cface, self.width-value_w)
self.show_value = self.value
else
self.show_value = truncateTextByWidth(self.value, self.cface, self.width-key_w, true)
self.show_key = self.key
end
else
self.show_key = self.key
self.show_value = self.value
end
self[1] = FrameContainer:new{
padding = 0,
bordersize = 0,
OverlapGroup:new{
dimen = self.dimen:copy(),
TextWidget:new{
text = self.key,
face = self.cface,
}
},
RightContainer:new{
dimen = self.dimen:copy(),
TextWidget:new{
text = self.value,
face = self.cface,
LeftContainer:new{
dimen = self.dimen:copy(),
TextWidget:new{
text = self.show_key,
face = self.cface,
}
},
RightContainer:new{
dimen = self.dimen:copy(),
TextWidget:new{
text = self.show_value,
face = self.cface,
}
}
}
}
@@ -176,8 +227,8 @@ function KeyValuePage:init()
kv_page = self,
}
-- setup main content
self.item_padding = self.item_height / 4
local line_height = self.item_height + 2 * self.item_padding
self.item_margin = self.item_height / 4
local line_height = self.item_height + 2 * self.item_margin
local content_height = self.dimen.h - self.title_bar:getSize().h
self.items_per_page = math.floor(content_height / line_height)
self.pages = math.ceil(#self.kv_pairs / self.items_per_page)
@@ -212,7 +263,7 @@ function KeyValuePage:prevPage()
end
end
-- make sure self.item_padding and self.item_height are set before calling this
-- make sure self.item_margin and self.item_height are set before calling this
function KeyValuePage:_populateItems()
self.main_content:clear()
local idx_offset = (self.show_page - 1) * self.items_per_page
@@ -221,7 +272,7 @@ function KeyValuePage:_populateItems()
if entry == nil then break end
table.insert(self.main_content,
VerticalSpan:new{ width = self.item_padding })
VerticalSpan:new{ width = self.item_margin })
if type(entry) == "table" then
table.insert(
self.main_content,
@@ -247,7 +298,7 @@ function KeyValuePage:_populateItems()
end
end
table.insert(self.main_content,
VerticalSpan:new{ width = self.item_padding })
VerticalSpan:new{ width = self.item_margin })
end
self.title_bar:setPageCount(self.show_page, self.pages)
UIManager:setDirty(self, function()