Skip to content

Commit

Permalink
Add option to truncate down to nearest full word (#46)
Browse files Browse the repository at this point in the history
* Add option to truncate down to nearest full word
  • Loading branch information
britzl authored Sep 8, 2019
1 parent c7de1f5 commit e6ca0db
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 24 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,17 @@ Get all words with a specific tag.
* `words` (table) - A table with all the words that matches the tag.


### richtext.truncate(words, length)
Truncate a text such that only a specific number of characters and images are visible. The function will disable nodes that shouldn't be seen at all and updates the text in nodes that should be partially visible. The text metrics of a truncated word will be updated.
### richtext.truncate(words, length, [options])
Truncate a text down to a specific length. This function has two modes of operation: 1) It can truncate the text on a per word basis or 2) on a per character/image basis. The function will disable nodes that shouldn't be visible and in the case of truncating on a per character basis also update the text in nodes that should be partially visible. The text metrics of a truncated word will be updated.

**PARAMETERS**
* `words` (table) - The words to truncate, as received by a call to `richtext.create()`.
* `length` (number) - Maximum number of characters or images to show.
* `length` (number) - Maximum number of words or characters and images to show.
* `options` (table) - Optional table with options when truncating.

Available options in the `option` table are:

* `words` (boolean) - True if the function should truncate down to the nearest full word instead of truncating to a partial word.

**RETURNS**
* `word` (table) - The last visible word.
Expand Down
19 changes: 16 additions & 3 deletions example/example.gui_script
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,24 @@ local function create_truncate_example()
local settings = { position = vmath.vector3(0, 240, 0) }
local words, metrics = richtext.create("This text should be shown one <img=smileys:cyclops/> at a time...", "Roboto-Regular", settings)
local length = 0
richtext.truncate(words, length)
local max_length = #words
local options = { words = true }
richtext.truncate(words, length, options)
timer.delay(0.1, true, function()
length = (length + 1) % (metrics.char_count + 1)
length = length + 1
if length > max_length then
-- alternate between truncating full words and per character
if options.words then
options.words = false
max_length = metrics.char_count
else
options.words = true
max_length = #words
end
length = 0
end

local last_word = richtext.truncate(words, length)
local last_word = richtext.truncate(words, length, options)
local pos = vmath.vector3(settings.position)
if last_word then
pos = gui.get_position(last_word.node)
Expand Down
52 changes: 34 additions & 18 deletions richtext/richtext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -490,29 +490,45 @@ end
-- and images are visible
-- @param words List of words to truncate
-- @param length Maximum number of characters to show
function M.truncate(words, length)
-- @param options Optional table with truncate options. Available options are: words
-- @return Last visible word
function M.truncate(words, length, options)
assert(words)
assert(length)
local count = 0
local last_visible_word = nil
for i=1, #words do
local word = words[i]
local is_text_node = not word.image and not word.spine
local word_length = is_text_node and utf8.len(word.text) or 1
local visible = count < length
last_visible_word = visible and word or last_visible_word
gui.set_enabled(word.node, visible)
if count < length and is_text_node then
local text = word.text
-- partial word?
if count + word_length > length then
local overflow = (count + word_length) - length
text = utf8.sub(word.text, 1, word_length - overflow)
if options and options.words then
for i=1, #words do
local word = words[i]
local visible = i <= length
if visible then
last_visible_word = word
end
gui.set_enabled(word.node, visible)
end
else
local count = 0
for i=1, #words do
local word = words[i]
local is_text_node = not word.image and not word.spine
local word_length = is_text_node and utf8.len(word.text) or 1
local visible = count < length
if visible then
last_visible_word = word
end
gui.set_enabled(word.node, visible)
if count < length and is_text_node then
local text = word.text
-- partial word?
if count + word_length > length then
-- remove overflowing characters from word
local overflow = (count + word_length) - length
text = utf8.sub(word.text, 1, word_length - overflow)
end
gui.set_text(word.node, text)
word.metrics = get_text_metrics(word, word.font, text)
end
gui.set_text(word.node, text)
word.metrics = get_text_metrics(word, word.font, text)
count = count + word_length
end
count = count + word_length
end
return last_visible_word
end
Expand Down

0 comments on commit e6ca0db

Please sign in to comment.