| 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 the anonymous namespace. | 8 // in this file using helper classes in the anonymous namespace. |
| 9 | 9 |
| 10 #include "ui/base/text/text_elider.h" | 10 #include "ui/base/text/text_elider.h" |
| (...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 int available_pixel_height, | 786 int available_pixel_height, |
| 787 ui::WordWrapBehavior wrap_behavior, | 787 ui::WordWrapBehavior wrap_behavior, |
| 788 std::vector<string16>* lines) | 788 std::vector<string16>* lines) |
| 789 : font_(font), | 789 : font_(font), |
| 790 line_height_(font.GetHeight()), | 790 line_height_(font.GetHeight()), |
| 791 available_pixel_width_(available_pixel_width), | 791 available_pixel_width_(available_pixel_width), |
| 792 available_pixel_height_(available_pixel_height), | 792 available_pixel_height_(available_pixel_height), |
| 793 wrap_behavior_(wrap_behavior), | 793 wrap_behavior_(wrap_behavior), |
| 794 current_width_(0), | 794 current_width_(0), |
| 795 current_height_(0), | 795 current_height_(0), |
| 796 last_line_ended_in_lf_(false), |
| 796 lines_(lines), | 797 lines_(lines), |
| 797 full_(false) {} | 798 full_(false) {} |
| 798 | 799 |
| 799 // Perform deferred initializions following creation. Must be called | 800 // Perform deferred initializions following creation. Must be called |
| 800 // before any input can be added via AddString(). | 801 // before any input can be added via AddString(). |
| 801 void Init() { lines_->clear(); } | 802 void Init() { lines_->clear(); } |
| 802 | 803 |
| 803 // Add an input string, reformatting to fit the desired dimensions. | 804 // Add an input string, reformatting to fit the desired dimensions. |
| 804 // AddString() may be called multiple times to concatenate together | 805 // AddString() may be called multiple times to concatenate together |
| 805 // multiple strings into the region (the current caller doesn't do | 806 // multiple strings into the region (the current caller doesn't do |
| 806 // this, however). | 807 // this, however). |
| 807 void AddString(const string16& input); | 808 void AddString(const string16& input); |
| 808 | 809 |
| 809 // Perform any deferred output processing. Must be called after the last | 810 // Perform any deferred output processing. Must be called after the last |
| 810 // AddString() call has occured. Returns |true| if the text had to be | 811 // AddString() call has occured. Returns |true| if the text had to be |
| 811 // truncated to fit the available height. | 812 // truncated to fit the available height. |
| 812 bool Finalize(); | 813 bool Finalize(); |
| 813 | 814 |
| 814 private: | 815 private: |
| 815 // Returns |true| if |text| is entirely composed of whitespace. | |
| 816 bool IsWhitespaceString(const string16& text) const; | |
| 817 | |
| 818 // Add a line to the rectangular region at the current position, | 816 // Add a line to the rectangular region at the current position, |
| 819 // either by itself or by breaking it into words. | 817 // either by itself or by breaking it into words. |
| 820 void AddLine(const string16& line); | 818 void AddLine(const string16& line); |
| 821 | 819 |
| 822 // Wrap the specified word across multiple lines. | 820 // Wrap the specified word across multiple lines. |
| 823 int WrapWord(const string16& word); | 821 int WrapWord(const string16& word); |
| 824 | 822 |
| 825 // Add a long word - wrapping, eliding or truncating per the wrap behavior. | 823 // Add a long word - wrapping, eliding or truncating per the wrap behavior. |
| 826 int AddWordOverflow(const string16& word); | 824 int AddWordOverflow(const string16& word); |
| 827 | 825 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 856 | 854 |
| 857 // The current running width. | 855 // The current running width. |
| 858 int current_width_; | 856 int current_width_; |
| 859 | 857 |
| 860 // The current running height. | 858 // The current running height. |
| 861 int current_height_; | 859 int current_height_; |
| 862 | 860 |
| 863 // The current line of text. | 861 // The current line of text. |
| 864 string16 current_line_; | 862 string16 current_line_; |
| 865 | 863 |
| 864 // Indicates whether the last line ended with \n. |
| 865 bool last_line_ended_in_lf_; |
| 866 |
| 866 // The output vector of lines. | 867 // The output vector of lines. |
| 867 std::vector<string16>* lines_; | 868 std::vector<string16>* lines_; |
| 868 | 869 |
| 869 // Indicates whether there were too many lines for the available height. | 870 // Indicates whether there were too many lines for the available height. |
| 870 bool full_; | 871 bool full_; |
| 871 | 872 |
| 872 DISALLOW_COPY_AND_ASSIGN(RectangleText); | 873 DISALLOW_COPY_AND_ASSIGN(RectangleText); |
| 873 }; | 874 }; |
| 874 | 875 |
| 875 void RectangleText::AddString(const string16& input) { | 876 void RectangleText::AddString(const string16& input) { |
| 876 base::i18n::BreakIterator lines(input, | 877 base::i18n::BreakIterator lines(input, |
| 877 base::i18n::BreakIterator::BREAK_NEWLINE); | 878 base::i18n::BreakIterator::BREAK_NEWLINE); |
| 878 if (lines.Init()) { | 879 if (lines.Init()) { |
| 879 while (!full_ && lines.Advance()) { | 880 while (!full_ && lines.Advance()) { |
| 880 string16 line = lines.GetString(); | 881 string16 line = lines.GetString(); |
| 881 // The BREAK_NEWLINE iterator will keep the trailing newline character, | 882 // The BREAK_NEWLINE iterator will keep the trailing newline character, |
| 882 // except in the case of the last line, which may not have one. Remove | 883 // except in the case of the last line, which may not have one. Remove |
| 883 // the newline character, if it exists. | 884 // the newline character, if it exists. |
| 884 if (!line.empty() && line[line.length() - 1] == '\n') | 885 last_line_ended_in_lf_ = !line.empty() && line[line.length() - 1] == '\n'; |
| 886 if (last_line_ended_in_lf_) |
| 885 line.resize(line.length() - 1); | 887 line.resize(line.length() - 1); |
| 886 AddLine(line); | 888 AddLine(line); |
| 887 } | 889 } |
| 888 } else { | 890 } else { |
| 889 NOTREACHED() << "BreakIterator (lines) init failed"; | 891 NOTREACHED() << "BreakIterator (lines) init failed"; |
| 890 } | 892 } |
| 891 } | 893 } |
| 892 | 894 |
| 893 bool RectangleText::Finalize() { | 895 bool RectangleText::Finalize() { |
| 894 // Remove trailing whitespace from the last line or remove the last line | 896 // Remove trailing whitespace from the last line or remove the last line |
| 895 // completely, if it's just whitespace. | 897 // completely, if it's just whitespace. |
| 896 if (!full_ && !lines_->empty()) { | 898 if (!full_ && !lines_->empty()) { |
| 897 TrimWhitespace(lines_->back(), TRIM_TRAILING, &lines_->back()); | 899 TrimWhitespace(lines_->back(), TRIM_TRAILING, &lines_->back()); |
| 898 if (lines_->back().empty()) | 900 if (lines_->back().empty() && !last_line_ended_in_lf_) |
| 899 lines_->pop_back(); | 901 lines_->pop_back(); |
| 900 } | 902 } |
| 903 if (last_line_ended_in_lf_) |
| 904 lines_->push_back(string16()); |
| 901 return full_; | 905 return full_; |
| 902 } | 906 } |
| 903 | 907 |
| 904 bool RectangleText::IsWhitespaceString(const string16& text) const { | |
| 905 return text.find_first_not_of(kWhitespaceUTF16) == string16::npos; | |
| 906 } | |
| 907 | |
| 908 void RectangleText::AddLine(const string16& line) { | 908 void RectangleText::AddLine(const string16& line) { |
| 909 const int line_width = font_.GetStringWidth(line); | 909 const int line_width = font_.GetStringWidth(line); |
| 910 if (line_width < available_pixel_width_) { | 910 if (line_width < available_pixel_width_) { |
| 911 AddToCurrentLineWithWidth(line, line_width); | 911 AddToCurrentLineWithWidth(line, line_width); |
| 912 } else { | 912 } else { |
| 913 // Iterate over positions that are valid to break the line at. In general, | 913 // Iterate over positions that are valid to break the line at. In general, |
| 914 // these are word boundaries but after any punctuation following the word. | 914 // these are word boundaries but after any punctuation following the word. |
| 915 base::i18n::BreakIterator words(line, | 915 base::i18n::BreakIterator words(line, |
| 916 base::i18n::BreakIterator::BREAK_LINE); | 916 base::i18n::BreakIterator::BREAK_LINE); |
| 917 if (words.Init()) { | 917 if (words.Init()) { |
| 918 while (words.Advance()) { | 918 while (words.Advance()) { |
| 919 const bool truncate = !current_line_.empty(); | 919 const bool truncate = !current_line_.empty(); |
| 920 const string16& word = words.GetString(); | 920 const string16& word = words.GetString(); |
| 921 const int lines_added = AddWord(word); | 921 const int lines_added = AddWord(word); |
| 922 if (lines_added) { | 922 if (lines_added) { |
| 923 if (truncate) { | 923 if (truncate) { |
| 924 // Trim trailing whitespace from the line that was added. | 924 // Trim trailing whitespace from the line that was added. |
| 925 const int line = lines_->size() - lines_added; | 925 const int line = lines_->size() - lines_added; |
| 926 TrimWhitespace(lines_->at(line), TRIM_TRAILING, &lines_->at(line)); | 926 TrimWhitespace(lines_->at(line), TRIM_TRAILING, &lines_->at(line)); |
| 927 } | 927 } |
| 928 if (IsWhitespaceString(word)) { | 928 if (ContainsOnlyWhitespace(word)) { |
| 929 // Skip the first space if the previous line was carried over. | 929 // Skip the first space if the previous line was carried over. |
| 930 current_width_ = 0; | 930 current_width_ = 0; |
| 931 current_line_.clear(); | 931 current_line_.clear(); |
| 932 } | 932 } |
| 933 } | 933 } |
| 934 } | 934 } |
| 935 } else { | 935 } else { |
| 936 NOTREACHED() << "BreakIterator (words) init failed"; | 936 NOTREACHED() << "BreakIterator (words) init failed"; |
| 937 } | 937 } |
| 938 } | 938 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 string16 trimmed; | 989 string16 trimmed; |
| 990 TrimWhitespace(word, TRIM_TRAILING, &trimmed); | 990 TrimWhitespace(word, TRIM_TRAILING, &trimmed); |
| 991 const int trimmed_width = font_.GetStringWidth(trimmed); | 991 const int trimmed_width = font_.GetStringWidth(trimmed); |
| 992 if (trimmed_width <= available_pixel_width_) { | 992 if (trimmed_width <= available_pixel_width_) { |
| 993 // Word can be made to fit, no need to fragment it. | 993 // Word can be made to fit, no need to fragment it. |
| 994 if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine()) | 994 if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine()) |
| 995 lines_added++; | 995 lines_added++; |
| 996 // Append the non-trimmed word, in case more words are added after. | 996 // Append the non-trimmed word, in case more words are added after. |
| 997 AddToCurrentLine(word); | 997 AddToCurrentLine(word); |
| 998 } else { | 998 } else { |
| 999 lines_added = AddWordOverflow(word); | 999 lines_added = AddWordOverflow(wrap_behavior_ == ui::IGNORE_LONG_WORDS ? |
| 1000 trimmed : word); |
| 1000 } | 1001 } |
| 1001 return lines_added; | 1002 return lines_added; |
| 1002 } | 1003 } |
| 1003 | 1004 |
| 1004 void RectangleText::AddToCurrentLine(const string16& text) { | 1005 void RectangleText::AddToCurrentLine(const string16& text) { |
| 1005 AddToCurrentLineWithWidth(text, font_.GetStringWidth(text)); | 1006 AddToCurrentLineWithWidth(text, font_.GetStringWidth(text)); |
| 1006 } | 1007 } |
| 1007 | 1008 |
| 1008 void RectangleText::AddToCurrentLineWithWidth(const string16& text, | 1009 void RectangleText::AddToCurrentLineWithWidth(const string16& text, |
| 1009 int text_width) { | 1010 int text_width) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 index = char_iterator.getIndex(); | 1114 index = char_iterator.getIndex(); |
| 1114 } else { | 1115 } else { |
| 1115 // String has leading whitespace, return the elide string. | 1116 // String has leading whitespace, return the elide string. |
| 1116 return kElideString; | 1117 return kElideString; |
| 1117 } | 1118 } |
| 1118 } | 1119 } |
| 1119 return string.substr(0, index) + kElideString; | 1120 return string.substr(0, index) + kElideString; |
| 1120 } | 1121 } |
| 1121 | 1122 |
| 1122 } // namespace ui | 1123 } // namespace ui |
| OLD | NEW |