Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file implements utility functions for eliding and formatting UI text. | 5 // This file implements utility functions for eliding and formatting UI text. |
| 6 // | 6 // |
| 7 // Note that several of the functions declared in text_elider.h are implemented | 7 // Note that several of the functions declared in text_elider.h are implemented |
| 8 // in this file using helper classes in an unnamed namespace. | 8 // in this file using helper classes in an unnamed namespace. |
| 9 | 9 |
| 10 #include "ui/gfx/text_elider.h" | 10 #include "ui/gfx/text_elider.h" |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 745 wrap_behavior, | 745 wrap_behavior, |
| 746 lines); | 746 lines); |
| 747 rect.Init(); | 747 rect.Init(); |
| 748 rect.AddString(input); | 748 rect.AddString(input); |
| 749 return rect.Finalize(); | 749 return rect.Finalize(); |
| 750 } | 750 } |
| 751 | 751 |
| 752 base::string16 TruncateString(const base::string16& string, | 752 base::string16 TruncateString(const base::string16& string, |
| 753 size_t length, | 753 size_t length, |
| 754 BreakType break_type) { | 754 BreakType break_type) { |
| 755 DCHECK(break_type == CHARACTER_BREAK || break_type == WORD_BREAK); | 755 const bool word_break = break_type == WORD_BREAK; |
| 756 DCHECK(word_break || (break_type == CHARACTER_BREAK)); | |
| 756 | 757 |
| 757 if (string.size() <= length) | 758 if (string.size() <= length) |
| 758 // String fits, return it. | 759 // String fits, return it. |
|
msw
2015/09/17 18:42:44
unrelated nit: please move the comment above the i
Peter Kasting
2015/09/19 02:43:25
Fixed by exchanging these for some EOL comments (w
| |
| 759 return string; | 760 return string; |
| 760 | 761 |
| 761 if (length == 0) | 762 if (length == 0) |
| 762 // No room for the elide string, return an empty string. | 763 // No room for the elide string, return an empty string. |
| 763 return base::string16(); | 764 return base::string16(); |
| 764 | 765 |
| 765 size_t max = length - 1; | |
| 766 | |
| 767 // Added to the end of strings that are too big. | 766 // Added to the end of strings that are too big. |
| 768 static const base::char16 kElideString[] = { 0x2026, 0 }; | 767 static const base::char16 kElideString[] = { 0x2026, 0 }; |
| 769 | 768 |
| 770 if (max == 0) | 769 if (length == 1) |
| 771 // Just enough room for the elide string. | 770 // Just enough room for the elide string. |
| 772 return kElideString; | 771 return kElideString; |
| 773 | 772 |
| 774 int32_t index = static_cast<int32_t>(max); | 773 int32_t index = static_cast<int32_t>(length) - (word_break ? 0 : 1); |
|
msw
2015/09/17 18:42:44
I'd be a lot more comfortable with this code using
Peter Kasting
2015/09/17 19:39:03
I tried a couple times yesterday to rewrite the ch
msw
2015/09/17 20:45:10
That seems fine, except lines 804 and 814 seem to
Peter Kasting
2015/09/17 20:58:05
804 is definitely a regression I need to fix. I m
msw
2015/09/17 21:06:26
OK, sgtm
Peter Kasting
2015/09/19 02:43:25
Fixed line 804 by restoring the next() call.
| |
| 775 if (break_type == WORD_BREAK) { | 774 if (word_break) { |
| 776 // Use a line iterator to find the first boundary. | 775 // Use a word iterator to find the first boundary. |
| 777 UErrorCode status = U_ZERO_ERROR; | 776 UErrorCode status = U_ZERO_ERROR; |
| 778 scoped_ptr<icu::BreakIterator> bi( | 777 scoped_ptr<icu::BreakIterator> bi( |
| 779 icu::RuleBasedBreakIterator::createLineInstance( | 778 icu::RuleBasedBreakIterator::createWordInstance( |
| 780 icu::Locale::getDefault(), status)); | 779 icu::Locale::getDefault(), status)); |
| 781 if (U_FAILURE(status)) | 780 if (U_FAILURE(status)) |
| 782 return string.substr(0, max) + kElideString; | 781 return string.substr(0, length - 1) + kElideString; |
|
msw
2015/09/17 18:42:44
It's unrelated (okay for follow-up), but I think t
Peter Kasting
2015/09/19 02:43:25
Yep, will address in the followup.
| |
| 783 bi->setText(string.c_str()); | 782 bi->setText(string.c_str()); |
| 784 index = bi->preceding(index); | 783 index = bi->preceding(index); |
|
msw
2015/09/17 18:42:44
nit: consider using |index = bi->preceding(length)
Peter Kasting
2015/09/19 02:43:25
Done.
| |
| 785 if (index == icu::BreakIterator::DONE || index == 0) { | 784 if (index == icu::BreakIterator::DONE || index == 0) { |
| 786 // We either found no valid line break at all, or one right at the | 785 // We either found no valid word break at all, or one right at the |
| 787 // beginning of the string. Go back to the end; we'll have to break in the | 786 // beginning of the string. Go back to the end; we'll have to break in the |
| 788 // middle of a word. | 787 // middle of a word. |
| 789 index = static_cast<int32_t>(max); | 788 index = static_cast<int32_t>(length - 1); |
| 790 } | 789 } |
| 791 } | 790 } |
| 792 | 791 |
| 793 // Use a character iterator to find the previous non-whitespace character. | 792 // By this point, |index| should point at the character that's a candidate for |
| 793 // replacing with an ellipsis. Use a character iterator to check previous | |
| 794 // characters and stop as soon as we find a previous non-whitespace character. | |
| 794 icu::StringCharacterIterator char_iterator(string.c_str()); | 795 icu::StringCharacterIterator char_iterator(string.c_str()); |
| 795 char_iterator.setIndex(index); | 796 char_iterator.setIndex(index); |
| 796 while (char_iterator.hasPrevious()) { | 797 while (char_iterator.hasPrevious()) { |
| 797 char_iterator.previous(); | 798 char_iterator.previous(); |
| 798 if (!(u_isspace(char_iterator.current()) || | 799 if (!(u_isspace(char_iterator.current()) || |
| 799 u_charType(char_iterator.current()) == U_CONTROL_CHAR || | 800 u_charType(char_iterator.current()) == U_CONTROL_CHAR || |
| 800 u_charType(char_iterator.current()) == U_NON_SPACING_MARK)) { | 801 u_charType(char_iterator.current()) == U_NON_SPACING_MARK)) { |
| 801 // Not a whitespace character. Advance the iterator so that we | 802 // Not a whitespace character. Truncate to everything up to and including |
| 802 // include the current character in the truncated string. | 803 // this character, plus the ellipsis. |
|
msw
2015/09/17 18:42:44
nit: s/plus/and append/
Peter Kasting
2015/09/19 02:43:25
Done.
| |
| 803 char_iterator.next(); | 804 return string.substr(0, char_iterator.getIndex() + 1) + kElideString; |
| 804 break; | |
| 805 } | 805 } |
| 806 } | 806 } |
| 807 if (char_iterator.hasPrevious()) { | |
| 808 // Found a valid break point. | |
| 809 index = char_iterator.getIndex(); | |
| 810 } else { | |
| 811 // String has leading whitespace, return the elide string. | |
| 812 return kElideString; | |
| 813 } | |
| 814 | 807 |
| 815 return string.substr(0, index) + kElideString; | 808 // Couldn't find a previous non-whitespace character. If we were originally |
| 809 // word-breaking, and index != length - 1, then the string is |index| | |
| 810 // whitespace characters followed by a word we're trying to break in the midst | |
| 811 // of, and we can fit at least one character of the word in the elided string. | |
| 812 // Do that rather than just returning an ellipsis. | |
| 813 if (word_break && (index != static_cast<int32_t>(length - 1))) | |
| 814 return string.substr(0, length - 1) + kElideString; | |
|
msw
2015/09/17 18:42:44
This should use a char iterator to avoid chopping
| |
| 815 | |
| 816 // Trying to break after only whitespace, elide all of it. | |
| 817 return kElideString; | |
| 816 } | 818 } |
| 817 | 819 |
| 818 } // namespace gfx | 820 } // namespace gfx |
| OLD | NEW |