| 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/base/text/text_elider.h" | 10 #include "ui/gfx/text_elider.h" |
| 11 | 11 |
| 12 #include <string> | 12 #include <string> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 16 #include "base/i18n/break_iterator.h" | 16 #include "base/i18n/break_iterator.h" |
| 17 #include "base/i18n/char_iterator.h" | 17 #include "base/i18n/char_iterator.h" |
| 18 #include "base/i18n/rtl.h" | 18 #include "base/i18n/rtl.h" |
| 19 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
| 20 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
| (...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 } | 807 } |
| 808 | 808 |
| 809 // Internal class used to track progress of a rectangular text elide | 809 // Internal class used to track progress of a rectangular text elide |
| 810 // operation. Exists so the top-level ElideRectangleText() function | 810 // operation. Exists so the top-level ElideRectangleText() function |
| 811 // can be broken into smaller methods sharing this state. | 811 // can be broken into smaller methods sharing this state. |
| 812 class RectangleText { | 812 class RectangleText { |
| 813 public: | 813 public: |
| 814 RectangleText(const gfx::FontList& font_list, | 814 RectangleText(const gfx::FontList& font_list, |
| 815 int available_pixel_width, | 815 int available_pixel_width, |
| 816 int available_pixel_height, | 816 int available_pixel_height, |
| 817 ui::WordWrapBehavior wrap_behavior, | 817 gfx::WordWrapBehavior wrap_behavior, |
| 818 std::vector<string16>* lines) | 818 std::vector<string16>* lines) |
| 819 : font_list_(font_list), | 819 : font_list_(font_list), |
| 820 line_height_(font_list.GetHeight()), | 820 line_height_(font_list.GetHeight()), |
| 821 available_pixel_width_(available_pixel_width), | 821 available_pixel_width_(available_pixel_width), |
| 822 available_pixel_height_(available_pixel_height), | 822 available_pixel_height_(available_pixel_height), |
| 823 wrap_behavior_(wrap_behavior), | 823 wrap_behavior_(wrap_behavior), |
| 824 current_width_(0), | 824 current_width_(0), |
| 825 current_height_(0), | 825 current_height_(0), |
| 826 last_line_ended_in_lf_(false), | 826 last_line_ended_in_lf_(false), |
| 827 lines_(lines), | 827 lines_(lines), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 // The height of each line of text. | 875 // The height of each line of text. |
| 876 const int line_height_; | 876 const int line_height_; |
| 877 | 877 |
| 878 // The number of pixels of available width in the rectangle. | 878 // The number of pixels of available width in the rectangle. |
| 879 const int available_pixel_width_; | 879 const int available_pixel_width_; |
| 880 | 880 |
| 881 // The number of pixels of available height in the rectangle. | 881 // The number of pixels of available height in the rectangle. |
| 882 const int available_pixel_height_; | 882 const int available_pixel_height_; |
| 883 | 883 |
| 884 // The wrap behavior for words that are too long to fit on a single line. | 884 // The wrap behavior for words that are too long to fit on a single line. |
| 885 const ui::WordWrapBehavior wrap_behavior_; | 885 const gfx::WordWrapBehavior wrap_behavior_; |
| 886 | 886 |
| 887 // The current running width. | 887 // The current running width. |
| 888 int current_width_; | 888 int current_width_; |
| 889 | 889 |
| 890 // The current running height. | 890 // The current running height. |
| 891 int current_height_; | 891 int current_height_; |
| 892 | 892 |
| 893 // The current line of text. | 893 // The current line of text. |
| 894 string16 current_line_; | 894 string16 current_line_; |
| 895 | 895 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 int RectangleText::Finalize() { | 931 int RectangleText::Finalize() { |
| 932 // Remove trailing whitespace from the last line or remove the last line | 932 // Remove trailing whitespace from the last line or remove the last line |
| 933 // completely, if it's just whitespace. | 933 // completely, if it's just whitespace. |
| 934 if (!insufficient_height_ && !lines_->empty()) { | 934 if (!insufficient_height_ && !lines_->empty()) { |
| 935 TrimWhitespace(lines_->back(), TRIM_TRAILING, &lines_->back()); | 935 TrimWhitespace(lines_->back(), TRIM_TRAILING, &lines_->back()); |
| 936 if (lines_->back().empty() && !last_line_ended_in_lf_) | 936 if (lines_->back().empty() && !last_line_ended_in_lf_) |
| 937 lines_->pop_back(); | 937 lines_->pop_back(); |
| 938 } | 938 } |
| 939 if (last_line_ended_in_lf_) | 939 if (last_line_ended_in_lf_) |
| 940 lines_->push_back(string16()); | 940 lines_->push_back(string16()); |
| 941 return (insufficient_width_ ? ui::INSUFFICIENT_SPACE_HORIZONTAL : 0) | | 941 return (insufficient_width_ ? gfx::INSUFFICIENT_SPACE_HORIZONTAL : 0) | |
| 942 (insufficient_height_ ? ui::INSUFFICIENT_SPACE_VERTICAL : 0); | 942 (insufficient_height_ ? gfx::INSUFFICIENT_SPACE_VERTICAL : 0); |
| 943 } | 943 } |
| 944 | 944 |
| 945 void RectangleText::AddLine(const string16& line) { | 945 void RectangleText::AddLine(const string16& line) { |
| 946 const int line_width = gfx::GetStringWidth(line, font_list_); | 946 const int line_width = gfx::GetStringWidth(line, font_list_); |
| 947 if (line_width <= available_pixel_width_) { | 947 if (line_width <= available_pixel_width_) { |
| 948 AddToCurrentLineWithWidth(line, line_width); | 948 AddToCurrentLineWithWidth(line, line_width); |
| 949 } else { | 949 } else { |
| 950 // Iterate over positions that are valid to break the line at. In general, | 950 // Iterate over positions that are valid to break the line at. In general, |
| 951 // these are word boundaries but after any punctuation following the word. | 951 // these are word boundaries but after any punctuation following the word. |
| 952 base::i18n::BreakIterator words(line, | 952 base::i18n::BreakIterator words(line, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 977 NewLine(); | 977 NewLine(); |
| 978 } | 978 } |
| 979 | 979 |
| 980 int RectangleText::WrapWord(const string16& word) { | 980 int RectangleText::WrapWord(const string16& word) { |
| 981 // Word is so wide that it must be fragmented. | 981 // Word is so wide that it must be fragmented. |
| 982 string16 text = word; | 982 string16 text = word; |
| 983 int lines_added = 0; | 983 int lines_added = 0; |
| 984 bool first_fragment = true; | 984 bool first_fragment = true; |
| 985 while (!insufficient_height_ && !text.empty()) { | 985 while (!insufficient_height_ && !text.empty()) { |
| 986 string16 fragment = | 986 string16 fragment = |
| 987 ui::ElideText(text, font_list_, available_pixel_width_, | 987 gfx::ElideText(text, font_list_, available_pixel_width_, |
| 988 ui::TRUNCATE_AT_END); | 988 gfx::TRUNCATE_AT_END); |
| 989 // At least one character has to be added at every line, even if the | 989 // At least one character has to be added at every line, even if the |
| 990 // available space is too small. | 990 // available space is too small. |
| 991 if(fragment.empty()) | 991 if(fragment.empty()) |
| 992 fragment = text.substr(0, 1); | 992 fragment = text.substr(0, 1); |
| 993 if (!first_fragment && NewLine()) | 993 if (!first_fragment && NewLine()) |
| 994 lines_added++; | 994 lines_added++; |
| 995 AddToCurrentLine(fragment); | 995 AddToCurrentLine(fragment); |
| 996 text = text.substr(fragment.length()); | 996 text = text.substr(fragment.length()); |
| 997 first_fragment = false; | 997 first_fragment = false; |
| 998 } | 998 } |
| 999 return lines_added; | 999 return lines_added; |
| 1000 } | 1000 } |
| 1001 | 1001 |
| 1002 int RectangleText::AddWordOverflow(const string16& word) { | 1002 int RectangleText::AddWordOverflow(const string16& word) { |
| 1003 int lines_added = 0; | 1003 int lines_added = 0; |
| 1004 | 1004 |
| 1005 // Unless this is the very first word, put it on a new line. | 1005 // Unless this is the very first word, put it on a new line. |
| 1006 if (!current_line_.empty()) { | 1006 if (!current_line_.empty()) { |
| 1007 if (!NewLine()) | 1007 if (!NewLine()) |
| 1008 return 0; | 1008 return 0; |
| 1009 lines_added++; | 1009 lines_added++; |
| 1010 } | 1010 } |
| 1011 | 1011 |
| 1012 if (wrap_behavior_ == ui::IGNORE_LONG_WORDS) { | 1012 if (wrap_behavior_ == gfx::IGNORE_LONG_WORDS) { |
| 1013 current_line_ = word; | 1013 current_line_ = word; |
| 1014 current_width_ = available_pixel_width_; | 1014 current_width_ = available_pixel_width_; |
| 1015 } else if (wrap_behavior_ == ui::WRAP_LONG_WORDS) { | 1015 } else if (wrap_behavior_ == gfx::WRAP_LONG_WORDS) { |
| 1016 lines_added += WrapWord(word); | 1016 lines_added += WrapWord(word); |
| 1017 } else { | 1017 } else { |
| 1018 const ui::ElideBehavior elide_behavior = | 1018 const gfx::ElideBehavior elide_behavior = |
| 1019 (wrap_behavior_ == ui::ELIDE_LONG_WORDS ? ui::ELIDE_AT_END : | 1019 (wrap_behavior_ == gfx::ELIDE_LONG_WORDS ? gfx::ELIDE_AT_END : |
| 1020 ui::TRUNCATE_AT_END); | 1020 gfx::TRUNCATE_AT_END); |
| 1021 const string16 elided_word = | 1021 const string16 elided_word = |
| 1022 ui::ElideText(word, font_list_, available_pixel_width_, elide_behavior); | 1022 gfx::ElideText(word, font_list_, available_pixel_width_, elide_behavior)
; |
| 1023 AddToCurrentLine(elided_word); | 1023 AddToCurrentLine(elided_word); |
| 1024 insufficient_width_ = true; | 1024 insufficient_width_ = true; |
| 1025 } | 1025 } |
| 1026 | 1026 |
| 1027 return lines_added; | 1027 return lines_added; |
| 1028 } | 1028 } |
| 1029 | 1029 |
| 1030 int RectangleText::AddWord(const string16& word) { | 1030 int RectangleText::AddWord(const string16& word) { |
| 1031 int lines_added = 0; | 1031 int lines_added = 0; |
| 1032 string16 trimmed; | 1032 string16 trimmed; |
| 1033 TrimWhitespace(word, TRIM_TRAILING, &trimmed); | 1033 TrimWhitespace(word, TRIM_TRAILING, &trimmed); |
| 1034 const int trimmed_width = gfx::GetStringWidth(trimmed, font_list_); | 1034 const int trimmed_width = gfx::GetStringWidth(trimmed, font_list_); |
| 1035 if (trimmed_width <= available_pixel_width_) { | 1035 if (trimmed_width <= available_pixel_width_) { |
| 1036 // Word can be made to fit, no need to fragment it. | 1036 // Word can be made to fit, no need to fragment it. |
| 1037 if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine()) | 1037 if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine()) |
| 1038 lines_added++; | 1038 lines_added++; |
| 1039 // Append the non-trimmed word, in case more words are added after. | 1039 // Append the non-trimmed word, in case more words are added after. |
| 1040 AddToCurrentLine(word); | 1040 AddToCurrentLine(word); |
| 1041 } else { | 1041 } else { |
| 1042 lines_added = AddWordOverflow(wrap_behavior_ == ui::IGNORE_LONG_WORDS ? | 1042 lines_added = AddWordOverflow(wrap_behavior_ == gfx::IGNORE_LONG_WORDS ? |
| 1043 trimmed : word); | 1043 trimmed : word); |
| 1044 } | 1044 } |
| 1045 return lines_added; | 1045 return lines_added; |
| 1046 } | 1046 } |
| 1047 | 1047 |
| 1048 void RectangleText::AddToCurrentLine(const string16& text) { | 1048 void RectangleText::AddToCurrentLine(const string16& text) { |
| 1049 AddToCurrentLineWithWidth(text, gfx::GetStringWidth(text, font_list_)); | 1049 AddToCurrentLineWithWidth(text, gfx::GetStringWidth(text, font_list_)); |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 void RectangleText::AddToCurrentLineWithWidth(const string16& text, | 1052 void RectangleText::AddToCurrentLineWithWidth(const string16& text, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 index = char_iterator.getIndex(); | 1168 index = char_iterator.getIndex(); |
| 1169 } else { | 1169 } else { |
| 1170 // String has leading whitespace, return the elide string. | 1170 // String has leading whitespace, return the elide string. |
| 1171 return kElideString; | 1171 return kElideString; |
| 1172 } | 1172 } |
| 1173 } | 1173 } |
| 1174 return string.substr(0, index) + kElideString; | 1174 return string.substr(0, index) + kElideString; |
| 1175 } | 1175 } |
| 1176 | 1176 |
| 1177 } // namespace ui | 1177 } // namespace ui |
| OLD | NEW |