diff options
author | bartfab@chromium.org <bartfab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-14 20:11:00 +0000 |
---|---|---|
committer | bartfab@chromium.org <bartfab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-14 20:11:00 +0000 |
commit | a2ac2864d48491b47068d5c30922329dfd135d0c (patch) | |
tree | 4b379492310e34b9c1e0b1a59caa4928ad4b6598 /ui/base | |
parent | 14efc6d257c73271ae0b70d2e71571b335827570 (diff) | |
download | chromium_src-a2ac2864d48491b47068d5c30922329dfd135d0c.zip chromium_src-a2ac2864d48491b47068d5c30922329dfd135d0c.tar.gz chromium_src-a2ac2864d48491b47068d5c30922329dfd135d0c.tar.bz2 |
Make ElideRectangleText() report horizontal truncation as well
This CL modifies ElideRectangleText() so that instead of a single bool,
it returns a combination of flags indicating whether the text had to be
truncated horizontally and/or vertically.
BUG=None
Review URL: https://chromiumcodereview.appspot.com/11361259
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167720 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r-- | ui/base/text/text_elider.cc | 34 | ||||
-rw-r--r-- | ui/base/text/text_elider.h | 24 | ||||
-rw-r--r-- | ui/base/text/text_elider_unittest.cc | 78 |
3 files changed, 78 insertions, 58 deletions
diff --git a/ui/base/text/text_elider.cc b/ui/base/text/text_elider.cc index 5f1593e..4388c07 100644 --- a/ui/base/text/text_elider.cc +++ b/ui/base/text/text_elider.cc @@ -795,7 +795,8 @@ class RectangleText { current_height_(0), last_line_ended_in_lf_(false), lines_(lines), - full_(false) {} + insufficient_width_(false), + insufficient_height_(false) {} // Perform deferred initializions following creation. Must be called // before any input can be added via AddString(). @@ -808,9 +809,10 @@ class RectangleText { void AddString(const string16& input); // Perform any deferred output processing. Must be called after the last - // AddString() call has occured. Returns |true| if the text had to be - // truncated to fit the available height. - bool Finalize(); + // AddString() call has occured. Returns a combination of + // |ReformattingResultFlags| indicating whether the given width or height was + // insufficient, leading to elision or truncation. + int Finalize(); private: // Add a line to the rectangular region at the current position, @@ -867,8 +869,12 @@ class RectangleText { // The output vector of lines. std::vector<string16>* lines_; + // Indicates whether a word was so long that it had to be truncated or elided + // to fit the available width. + bool insufficient_width_; + // Indicates whether there were too many lines for the available height. - bool full_; + bool insufficient_height_; DISALLOW_COPY_AND_ASSIGN(RectangleText); }; @@ -877,7 +883,7 @@ void RectangleText::AddString(const string16& input) { base::i18n::BreakIterator lines(input, base::i18n::BreakIterator::BREAK_NEWLINE); if (lines.Init()) { - while (!full_ && lines.Advance()) { + while (!insufficient_height_ && lines.Advance()) { string16 line = lines.GetString(); // The BREAK_NEWLINE iterator will keep the trailing newline character, // except in the case of the last line, which may not have one. Remove @@ -892,17 +898,18 @@ void RectangleText::AddString(const string16& input) { } } -bool RectangleText::Finalize() { +int RectangleText::Finalize() { // Remove trailing whitespace from the last line or remove the last line // completely, if it's just whitespace. - if (!full_ && !lines_->empty()) { + if (!insufficient_height_ && !lines_->empty()) { TrimWhitespace(lines_->back(), TRIM_TRAILING, &lines_->back()); if (lines_->back().empty() && !last_line_ended_in_lf_) lines_->pop_back(); } if (last_line_ended_in_lf_) lines_->push_back(string16()); - return full_; + return (insufficient_width_ ? ui::INSUFFICIENT_SPACE_HORIZONTAL : 0) | + (insufficient_height_ ? ui::INSUFFICIENT_SPACE_VERTICAL : 0); } void RectangleText::AddLine(const string16& line) { @@ -945,7 +952,7 @@ int RectangleText::WrapWord(const string16& word) { string16 text = word; int lines_added = 0; bool first_fragment = true; - while (!full_ && !text.empty()) { + while (!insufficient_height_ && !text.empty()) { const string16 fragment = ui::ElideText(text, font_, available_pixel_width_, ui::TRUNCATE_AT_END); if (!first_fragment && NewLine()) @@ -979,6 +986,7 @@ int RectangleText::AddWordOverflow(const string16& word) { const string16 elided_word = ui::ElideText(word, font_, available_pixel_width_, elide_behavior); AddToCurrentLine(elided_word); + insufficient_width_ = true; } return lines_added; @@ -1009,7 +1017,7 @@ void RectangleText::AddToCurrentLine(const string16& text) { void RectangleText::AddToCurrentLineWithWidth(const string16& text, int text_width) { if (current_height_ >= available_pixel_height_) { - full_ = true; + insufficient_height_ = true; return; } current_line_.append(text); @@ -1023,7 +1031,7 @@ bool RectangleText::NewLine() { current_line_.clear(); line_added = true; } else { - full_ = true; + insufficient_height_ = true; } current_height_ += line_height_; current_width_ = 0; @@ -1042,7 +1050,7 @@ bool ElideRectangleString(const string16& input, size_t max_rows, return rect.Finalize(); } -bool ElideRectangleText(const string16& input, +int ElideRectangleText(const string16& input, const gfx::Font& font, int available_pixel_width, int available_pixel_height, diff --git a/ui/base/text/text_elider.h b/ui/base/text/text_elider.h index 20e202d..39249ad 100644 --- a/ui/base/text/text_elider.h +++ b/ui/base/text/text_elider.h @@ -167,18 +167,28 @@ enum WordWrapBehavior { WRAP_LONG_WORDS, }; +// Indicates whether the |available_pixel_width| by |available_pixel_height| +// rectangle passed to |ElideRectangleText()| had insufficient space to +// accommodate the given |text|, leading to elision or truncation. +enum ReformattingResultFlags { + INSUFFICIENT_SPACE_HORIZONTAL = 1 << 0, + INSUFFICIENT_SPACE_VERTICAL = 1 << 1, +}; + // Reformats |text| into output vector |lines| so that the resulting text fits // into an |available_pixel_width| by |available_pixel_height| rectangle with // the specified |font|. Input newlines are respected, but lines that are too // long are broken into pieces. For words that are too wide to fit on a single // line, the wrapping behavior can be specified with the |wrap_behavior| param. -// Returns |true| if the input had to be truncated (and not just reformatted). -UI_EXPORT bool ElideRectangleText(const string16& text, - const gfx::Font& font, - int available_pixel_width, - int available_pixel_height, - WordWrapBehavior wrap_behavior, - std::vector<string16>* lines); +// Returns a combination of |ReformattingResultFlags| that indicate whether the +// given rectangle had insufficient space to accommodate |texŧ|, leading to +// elision or truncation (and not just reformatting). +UI_EXPORT int ElideRectangleText(const string16& text, + const gfx::Font& font, + int available_pixel_width, + int available_pixel_height, + WordWrapBehavior wrap_behavior, + std::vector<string16>* lines); // Truncates the string to length characters. This breaks the string at // the first word break before length, adding the horizontal ellipsis diff --git a/ui/base/text/text_elider_unittest.cc b/ui/base/text/text_elider_unittest.cc index e21b33c..8f9aa9c 100644 --- a/ui/base/text/text_elider_unittest.cc +++ b/ui/base/text/text_elider_unittest.cc @@ -524,7 +524,7 @@ TEST(TextEliderTest, ElideRectangleText) { const char* input; int available_pixel_width; int available_pixel_height; - bool truncated; + bool truncated_y; const char* output; } cases[] = { { "", 0, 0, false, NULL }, @@ -556,7 +556,7 @@ TEST(TextEliderTest, ElideRectangleText) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { std::vector<string16> lines; - EXPECT_EQ(cases[i].truncated, + EXPECT_EQ(cases[i].truncated_y ? INSUFFICIENT_SPACE_VERTICAL : 0, ElideRectangleText(UTF8ToUTF16(cases[i].input), font, cases[i].available_pixel_width, @@ -583,12 +583,12 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) { int available_pixel_width; int available_pixel_height; bool wrap_words; - bool truncated; + bool truncated_x; const char* output; } cases[] = { { "Test T.", test_t_width, line_height * 2, false, false, "Test|T." }, { "Test T ?", test_t_width, line_height * 2, false, false, "Test|T ?" }, - { "Test. Test", test_width, line_height * 3, false, false, "Test|Test" }, + { "Test. Test", test_width, line_height * 3, false, true, "Test|Test" }, { "Test. Test", test_width, line_height * 3, true, false, "Test|.|Test" }, }; @@ -596,7 +596,7 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) { std::vector<string16> lines; const WordWrapBehavior wrap_behavior = (cases[i].wrap_words ? WRAP_LONG_WORDS : TRUNCATE_LONG_WORDS); - EXPECT_EQ(cases[i].truncated, + EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0, ElideRectangleText(UTF8ToUTF16(cases[i].input), font, cases[i].available_pixel_width, @@ -623,45 +623,47 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) { const char* input; int available_pixel_width; WordWrapBehavior wrap_behavior; + bool truncated_x; const char* output; } cases[] = { - { "Testing", test_width, IGNORE_LONG_WORDS, "Testing" }, - { "X Testing", test_width, IGNORE_LONG_WORDS, "X|Testing" }, - { "Test Testing", test_width, IGNORE_LONG_WORDS, "Test|Testing" }, - { "Test\nTesting", test_width, IGNORE_LONG_WORDS, "Test|Testing" }, - { "Test Tests ", test_width, IGNORE_LONG_WORDS, "Test|Tests" }, - { "Test Tests T", test_width, IGNORE_LONG_WORDS, "Test|Tests|T" }, - - { "Testing", elided_width, ELIDE_LONG_WORDS, "Tes..." }, - { "X Testing", elided_width, ELIDE_LONG_WORDS, "X|Tes..." }, - { "Test Testing", elided_width, ELIDE_LONG_WORDS, "Test|Tes..." }, - { "Test\nTesting", elided_width, ELIDE_LONG_WORDS, "Test|Tes..." }, - - { "Testing", test_width, TRUNCATE_LONG_WORDS, "Test" }, - { "X Testing", test_width, TRUNCATE_LONG_WORDS, "X|Test" }, - { "Test Testing", test_width, TRUNCATE_LONG_WORDS, "Test|Test" }, - { "Test\nTesting", test_width, TRUNCATE_LONG_WORDS, "Test|Test" }, - { "Test Tests ", test_width, TRUNCATE_LONG_WORDS, "Test|Test" }, - { "Test Tests T", test_width, TRUNCATE_LONG_WORDS, "Test|Test|T" }, - - { "Testing", test_width, WRAP_LONG_WORDS, "Test|ing" }, - { "X Testing", test_width, WRAP_LONG_WORDS, "X|Test|ing" }, - { "Test Testing", test_width, WRAP_LONG_WORDS, "Test|Test|ing" }, - { "Test\nTesting", test_width, WRAP_LONG_WORDS, "Test|Test|ing" }, - { "Test Tests ", test_width, WRAP_LONG_WORDS, "Test|Test|s" }, - { "Test Tests T", test_width, WRAP_LONG_WORDS, "Test|Test|s T" }, - { "TestTestTest", test_width, WRAP_LONG_WORDS, "Test|Test|Test" }, - { "TestTestTestT", test_width, WRAP_LONG_WORDS, "Test|Test|Test|T" }, + { "Testing", test_width, IGNORE_LONG_WORDS, false, "Testing" }, + { "X Testing", test_width, IGNORE_LONG_WORDS, false, "X|Testing" }, + { "Test Testing", test_width, IGNORE_LONG_WORDS, false, "Test|Testing" }, + { "Test\nTesting", test_width, IGNORE_LONG_WORDS, false, "Test|Testing" }, + { "Test Tests ", test_width, IGNORE_LONG_WORDS, false, "Test|Tests" }, + { "Test Tests T", test_width, IGNORE_LONG_WORDS, false, "Test|Tests|T" }, + + { "Testing", elided_width, ELIDE_LONG_WORDS, true, "Tes..." }, + { "X Testing", elided_width, ELIDE_LONG_WORDS, true, "X|Tes..." }, + { "Test Testing", elided_width, ELIDE_LONG_WORDS, true, "Test|Tes..." }, + { "Test\nTesting", elided_width, ELIDE_LONG_WORDS, true, "Test|Tes..." }, + + { "Testing", test_width, TRUNCATE_LONG_WORDS, true, "Test" }, + { "X Testing", test_width, TRUNCATE_LONG_WORDS, true, "X|Test" }, + { "Test Testing", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test" }, + { "Test\nTesting", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test" }, + { "Test Tests ", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test" }, + { "Test Tests T", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test|T" }, + + { "Testing", test_width, WRAP_LONG_WORDS, false, "Test|ing" }, + { "X Testing", test_width, WRAP_LONG_WORDS, false, "X|Test|ing" }, + { "Test Testing", test_width, WRAP_LONG_WORDS, false, "Test|Test|ing" }, + { "Test\nTesting", test_width, WRAP_LONG_WORDS, false, "Test|Test|ing" }, + { "Test Tests ", test_width, WRAP_LONG_WORDS, false, "Test|Test|s" }, + { "Test Tests T", test_width, WRAP_LONG_WORDS, false, "Test|Test|s T" }, + { "TestTestTest", test_width, WRAP_LONG_WORDS, false, "Test|Test|Test" }, + { "TestTestTestT", test_width, WRAP_LONG_WORDS, false, "Test|Test|Test|T" }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { std::vector<string16> lines; - ElideRectangleText(UTF8ToUTF16(cases[i].input), - font, - cases[i].available_pixel_width, - kAvailableHeight, - cases[i].wrap_behavior, - &lines); + EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0, + ElideRectangleText(UTF8ToUTF16(cases[i].input), + font, + cases[i].available_pixel_width, + kAvailableHeight, + cases[i].wrap_behavior, + &lines)); std::string expected_output(cases[i].output); ReplaceSubstringsAfterOffset(&expected_output, 0, "...", kEllipsis); const std::string result = UTF16ToUTF8(JoinString(lines, '|')); |