diff options
Diffstat (limited to 'ui/base')
-rw-r--r-- | ui/base/text/text_elider.cc | 34 | ||||
-rw-r--r-- | ui/base/text/text_elider.h | 14 | ||||
-rw-r--r-- | ui/base/text/text_elider_unittest.cc | 90 |
3 files changed, 115 insertions, 23 deletions
diff --git a/ui/base/text/text_elider.cc b/ui/base/text/text_elider.cc index 4b18619..e6aaa26 100644 --- a/ui/base/text/text_elider.cc +++ b/ui/base/text/text_elider.cc @@ -507,11 +507,13 @@ namespace { // can be broken into smaller methods sharing this state. class RectangleString { public: - RectangleString(size_t max_rows, size_t max_cols, string16 *output) + RectangleString(size_t max_rows, size_t max_cols, + bool strict, string16 *output) : max_rows_(max_rows), max_cols_(max_cols), current_row_(0), current_col_(0), + strict_(strict), suppressed_(false), output_(output) {} @@ -542,10 +544,11 @@ class RectangleString { // have not been exceeded, advancing the current position. void Append(const string16& string); - // Add a newline to the output string if the rectangular boundaries - // have not been exceeded, resetting the current position to the - // beginning of the next line. - void NewLine(); + // Set the current position to the beginning of the next line. If + // |output| is true, add a newline to the output string if the rectangular + // boundaries have not been exceeded. If |output| is false, we assume + // some other mechanism will (likely) do similar breaking after the fact. + void NewLine(bool output); // Maximum number of rows allowed in the output string. size_t max_rows_; @@ -564,6 +567,9 @@ class RectangleString { // Current character position, should never exceed max_cols_. size_t current_col_; + // True when we do whitespace to newline conversions ourselves. + bool strict_; + // True when some of the input has been truncated. bool suppressed_; @@ -610,7 +616,7 @@ void RectangleString::AddWord(const string16& word) { if (word.length() < max_cols_) { // Word can be made to fit, no need to fragment it. if (current_col_ + word.length() >= max_cols_) - NewLine(); + NewLine(strict_); Append(word); } else { // Word is so big that it must be fragmented. @@ -621,7 +627,7 @@ void RectangleString::AddWord(const string16& word) { // When boundary is hit, add as much as will fit on this line. if (current_col_ + (chars.char_pos() - char_start) >= max_cols_) { Append(word.substr(array_start, chars.array_pos() - array_start)); - NewLine(); + NewLine(true); array_start = chars.array_pos(); char_start = chars.char_pos(); } @@ -641,11 +647,13 @@ void RectangleString::Append(const string16& string) { current_col_ += string.length(); } -void RectangleString::NewLine() { - if (current_row_ < max_rows_) - output_->append(ASCIIToUTF16("\n")); - else +void RectangleString::NewLine(bool output) { + if (current_row_ < max_rows_) { + if (output) + output_->append(ASCIIToUTF16("\n")); + } else { suppressed_ = true; + } ++current_row_; current_col_ = 0; } @@ -655,8 +663,8 @@ void RectangleString::NewLine() { namespace ui { bool ElideRectangleString(const string16& input, size_t max_rows, - size_t max_cols, string16* output) { - RectangleString rect(max_rows, max_cols, output); + size_t max_cols, bool strict, string16* output) { + RectangleString rect(max_rows, max_cols, strict, output); rect.Init(); rect.AddString(input); return rect.Finalize(); diff --git a/ui/base/text/text_elider.h b/ui/base/text/text_elider.h index f010712..5dd3dc5 100644 --- a/ui/base/text/text_elider.h +++ b/ui/base/text/text_elider.h @@ -106,13 +106,15 @@ bool ElideString(const string16& input, int max_len, string16* output); // Reformat |input| into |output| so that it fits into a |max_rows| by // |max_cols| rectangle of characters. Input newlines are respected, but -// lines that are too long are broken into pieces, first at naturally -// occuring whitespace boundaries, and then intra-word (respecting UTF-16 -// surrogate pairs) as necssary. Truncation (indicated by an added 3 dots) -// occurs if the result is still too long. Returns true if the input had -// to be truncated (and not just reformatted). +// lines that are too long are broken into pieces. If |strict| is true, +// we break first at naturally occuring whitespace boundaries, otherwise +// we assume some other mechanism will do this in approximately the same +// spot after the fact. If the word itself is too long, we always break +// intra-word (respecting UTF-16 surrogate pairs) as necssary. Truncation +// (indicated by an added 3 dots) occurs if the result is still too long. +// Returns true if the input had to be truncated (and not just reformatted). bool ElideRectangleString(const string16& input, size_t max_rows, - size_t max_cols, string16* output); + size_t max_cols, bool strict, string16* output); } // namespace ui diff --git a/ui/base/text/text_elider_unittest.cc b/ui/base/text/text_elider_unittest.cc index 083d9f2..69cf0c1 100644 --- a/ui/base/text/text_elider_unittest.cc +++ b/ui/base/text/text_elider_unittest.cc @@ -401,7 +401,89 @@ TEST(TextEliderTest, ElideRectangleString) { EXPECT_EQ(cases[i].result, ui::ElideRectangleString(UTF8ToUTF16(cases[i].input), cases[i].max_rows, cases[i].max_cols, - &output)); + true, &output)); + EXPECT_EQ(cases[i].output, UTF16ToUTF8(output)); + } +} + +TEST(TextEliderTest, ElideRectangleStringNotStrict) { + struct TestData { + const char* input; + int max_rows; + int max_cols; + bool result; + const char* output; + } cases[] = { + { "", 0, 0, false, "" }, + { "", 1, 1, false, "" }, + { "Hi, my name_is\nDick", 0, 0, true, "..." }, + { "Hi, my name_is\nDick", 1, 0, true, "\n..." }, + { "Hi, my name_is\nDick", 0, 1, true, "..." }, + { "Hi, my name_is\nDick", 1, 1, true, "H\n..." }, + { "Hi, my name_is\nDick", 2, 1, true, "H\ni\n..." }, + { "Hi, my name_is\nDick", 3, 1, true, "H\ni\n,\n..." }, + { "Hi, my name_is\nDick", 4, 1, true, "H\ni\n,\n \n..." }, + { "Hi, my name_is\nDick", 5, 1, true, "H\ni\n,\n \nm\n..." }, + { "Hi, my name_is\nDick", 0, 2, true, "..." }, + { "Hi, my name_is\nDick", 1, 2, true, "Hi\n..." }, + { "Hi, my name_is\nDick", 2, 2, true, "Hi\n, \n..." }, + { "Hi, my name_is\nDick", 3, 2, true, "Hi\n, \nmy\n..." }, + { "Hi, my name_is\nDick", 4, 2, true, "Hi\n, \nmy\n n\n..." }, + { "Hi, my name_is\nDick", 5, 2, true, "Hi\n, \nmy\n n\nam\n..." }, + { "Hi, my name_is\nDick", 0, 3, true, "..." }, + { "Hi, my name_is\nDick", 1, 3, true, "Hi,\n..." }, + { "Hi, my name_is\nDick", 2, 3, true, "Hi,\n my\n..." }, + { "Hi, my name_is\nDick", 3, 3, true, "Hi,\n my\n na\n..." }, + { "Hi, my name_is\nDick", 4, 3, true, "Hi,\n my\n na\nme_\n..." }, + { "Hi, my name_is\nDick", 5, 3, true, "Hi,\n my\n na\nme_\nis\n..." }, + { "Hi, my name_is\nDick", 1, 4, true, "Hi, ..." }, + { "Hi, my name_is\nDick", 2, 4, true, "Hi, my n\n..." }, + { "Hi, my name_is\nDick", 3, 4, true, "Hi, my n\name_\n..." }, + { "Hi, my name_is\nDick", 4, 4, true, "Hi, my n\name_\nis\n..." }, + { "Hi, my name_is\nDick", 5, 4, false, "Hi, my n\name_\nis\nDick" }, + { "Hi, my name_is\nDick", 1, 5, true, "Hi, ..." }, + { "Hi, my name_is\nDick", 2, 5, true, "Hi, my na\n..." }, + { "Hi, my name_is\nDick", 3, 5, true, "Hi, my na\nme_is\n..." }, + { "Hi, my name_is\nDick", 4, 5, true, "Hi, my na\nme_is\n\n..." }, + { "Hi, my name_is\nDick", 5, 5, false, "Hi, my na\nme_is\n\nDick" }, + { "Hi, my name_is\nDick", 1, 6, true, "Hi, ..." }, + { "Hi, my name_is\nDick", 2, 6, true, "Hi, my nam\n..." }, + { "Hi, my name_is\nDick", 3, 6, true, "Hi, my nam\ne_is\n..." }, + { "Hi, my name_is\nDick", 4, 6, false, "Hi, my nam\ne_is\nDick" }, + { "Hi, my name_is\nDick", 5, 6, false, "Hi, my nam\ne_is\nDick" }, + { "Hi, my name_is\nDick", 1, 7, true, "Hi, ..." }, + { "Hi, my name_is\nDick", 2, 7, true, "Hi, my name\n..." }, + { "Hi, my name_is\nDick", 3, 7, true, "Hi, my name\n_is\n..." }, + { "Hi, my name_is\nDick", 4, 7, false, "Hi, my name\n_is\nDick" }, + { "Hi, my name_is\nDick", 5, 7, false, "Hi, my name\n_is\nDick" }, + { "Hi, my name_is\nDick", 1, 8, true, "Hi, my n\n..." }, + { "Hi, my name_is\nDick", 2, 8, true, "Hi, my n\name_is\n..." }, + { "Hi, my name_is\nDick", 3, 8, false, "Hi, my n\name_is\nDick" }, + { "Hi, my name_is\nDick", 1, 9, true, "Hi, my ..." }, + { "Hi, my name_is\nDick", 2, 9, true, "Hi, my name_is\n..." }, + { "Hi, my name_is\nDick", 3, 9, false, "Hi, my name_is\nDick" }, + { "Hi, my name_is\nDick", 1, 10, true, "Hi, my ..." }, + { "Hi, my name_is\nDick", 2, 10, true, "Hi, my name_is\n..." }, + { "Hi, my name_is\nDick", 3, 10, false, "Hi, my name_is\nDick" }, + { "Hi, my name_is\nDick", 1, 11, true, "Hi, my ..." }, + { "Hi, my name_is\nDick", 2, 11, true, "Hi, my name_is\n..." }, + { "Hi, my name_is\nDick", 3, 11, false, "Hi, my name_is\nDick" }, + { "Hi, my name_is\nDick", 1, 12, true, "Hi, my ..." }, + { "Hi, my name_is\nDick", 2, 12, true, "Hi, my name_is\n..." }, + { "Hi, my name_is\nDick", 3, 12, false, "Hi, my name_is\nDick" }, + { "Hi, my name_is\nDick", 1, 13, true, "Hi, my ..." }, + { "Hi, my name_is\nDick", 2, 13, true, "Hi, my name_is\n..." }, + { "Hi, my name_is\nDick", 3, 13, false, "Hi, my name_is\nDick" }, + { "Hi, my name_is\nDick", 1, 20, true, "Hi, my name_is\n..." }, + { "Hi, my name_is\nDick", 2, 20, false, "Hi, my name_is\nDick" }, + { "Hi, my name_is Dick", 1, 40, false, "Hi, my name_is Dick" }, + }; + string16 output; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { + EXPECT_EQ(cases[i].result, + ui::ElideRectangleString(UTF8ToUTF16(cases[i].input), + cases[i].max_rows, cases[i].max_cols, + false, &output)); EXPECT_EQ(cases[i].output, UTF16ToUTF8(output)); } } @@ -419,9 +501,9 @@ TEST(TextEliderTest, ElideRectangleWide16) { L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9\x03bf\x03c2\x0020\n" L"\x0399\x03c3\x03c4\x03cc\x03c2")); string16 output; - EXPECT_TRUE(ui::ElideRectangleString(str, 2, 4, &output)); + EXPECT_TRUE(ui::ElideRectangleString(str, 2, 4, true, &output)); EXPECT_EQ(out1, output); - EXPECT_FALSE(ui::ElideRectangleString(str, 2, 12, &output)); + EXPECT_FALSE(ui::ElideRectangleString(str, 2, 12, true, &output)); EXPECT_EQ(out2, output); } @@ -434,7 +516,7 @@ TEST(TextEliderTest, ElideRectangleWide32) { "\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\n" "\xF0\x9D\x92\x9C \naaa\n...")); string16 output; - EXPECT_TRUE(ui::ElideRectangleString(str, 3, 3, &output)); + EXPECT_TRUE(ui::ElideRectangleString(str, 3, 3, true, &output)); EXPECT_EQ(out, output); } |