| 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/base/text/text_elider.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 class StringSlicer { | 41 class StringSlicer { |
| 42 public: | 42 public: |
| 43 StringSlicer(const string16& text, | 43 StringSlicer(const string16& text, |
| 44 const string16& ellipsis, | 44 const string16& ellipsis, |
| 45 bool elide_in_middle) | 45 bool elide_in_middle) |
| 46 : text_(text), | 46 : text_(text), |
| 47 ellipsis_(ellipsis), | 47 ellipsis_(ellipsis), |
| 48 elide_in_middle_(elide_in_middle) { | 48 elide_in_middle_(elide_in_middle) { |
| 49 } | 49 } |
| 50 | 50 |
| 51 // Cuts |text_| to be |length| characters long. If |cut_in_middle_| is true, | 51 // Cuts |text_| to be |length| characters long. If |elide_in_middle_| is true, |
| 52 // the middle of the string is removed to leave equal-length pieces from the | 52 // the middle of the string is removed to leave equal-length pieces from the |
| 53 // beginning and end of the string; otherwise, the end of the string is | 53 // beginning and end of the string; otherwise, the end of the string is |
| 54 // removed and only the beginning remains. If |insert_ellipsis| is true, | 54 // removed and only the beginning remains. If |insert_ellipsis| is true, |
| 55 // then an ellipsis character will by inserted at the cut point. | 55 // then an ellipsis character will be inserted at the cut point. |
| 56 string16 CutString(size_t length, bool insert_ellipsis) { | 56 string16 CutString(size_t length, bool insert_ellipsis) { |
| 57 const string16 ellipsis_text = insert_ellipsis ? ellipsis_ : string16(); | 57 const string16 ellipsis_text = insert_ellipsis ? ellipsis_ : string16(); |
| 58 | 58 |
| 59 if (!elide_in_middle_) | 59 if (!elide_in_middle_) |
| 60 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text; | 60 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text; |
| 61 | 61 |
| 62 // We put the extra character, if any, before the cut. | 62 // We put the extra character, if any, before the cut. |
| 63 const size_t half_length = length / 2; | 63 const size_t half_length = length / 2; |
| 64 const size_t prefix_length = FindValidBoundaryBefore(length - half_length); | 64 const size_t prefix_length = FindValidBoundaryBefore(length - half_length); |
| 65 const size_t suffix_start_guess = text_.length() - half_length; | 65 const size_t suffix_start_guess = text_.length() - half_length; |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 // (eliding way too much from a ridiculous string is probably still | 471 // (eliding way too much from a ridiculous string is probably still |
| 472 // ridiculous), but we should check other widths for bogus values as well. | 472 // ridiculous), but we should check other widths for bogus values as well. |
| 473 if (current_text_pixel_width <= 0 && !text.empty()) { | 473 if (current_text_pixel_width <= 0 && !text.empty()) { |
| 474 const string16 cut = slicer.CutString(text.length() / 2, false); | 474 const string16 cut = slicer.CutString(text.length() / 2, false); |
| 475 return ElideText(cut, font, available_pixel_width, elide_behavior); | 475 return ElideText(cut, font, available_pixel_width, elide_behavior); |
| 476 } | 476 } |
| 477 | 477 |
| 478 if (current_text_pixel_width <= available_pixel_width) | 478 if (current_text_pixel_width <= available_pixel_width) |
| 479 return text; | 479 return text; |
| 480 | 480 |
| 481 if (font.GetStringWidth(kEllipsisUTF16) > available_pixel_width) | 481 if (insert_ellipsis && |
| 482 font.GetStringWidth(kEllipsisUTF16) > available_pixel_width) |
| 482 return string16(); | 483 return string16(); |
| 483 | 484 |
| 484 // Use binary search to compute the elided text. | 485 // Use binary search to compute the elided text. |
| 485 size_t lo = 0; | 486 size_t lo = 0; |
| 486 size_t hi = text.length() - 1; | 487 size_t hi = text.length() - 1; |
| 487 size_t guess; | 488 size_t guess; |
| 488 for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) { | 489 for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) { |
| 489 // We check the length of the whole desired string at once to ensure we | 490 // We check the length of the whole desired string at once to ensure we |
| 490 // handle kerning/ligatures/etc. correctly. | 491 // handle kerning/ligatures/etc. correctly. |
| 491 const string16 cut = slicer.CutString(guess, insert_ellipsis); | 492 const string16 cut = slicer.CutString(guess, insert_ellipsis); |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 // Account for naturally-occuring newlines. | 947 // Account for naturally-occuring newlines. |
| 947 NewLine(); | 948 NewLine(); |
| 948 } | 949 } |
| 949 | 950 |
| 950 int RectangleText::WrapWord(const string16& word) { | 951 int RectangleText::WrapWord(const string16& word) { |
| 951 // Word is so wide that it must be fragmented. | 952 // Word is so wide that it must be fragmented. |
| 952 string16 text = word; | 953 string16 text = word; |
| 953 int lines_added = 0; | 954 int lines_added = 0; |
| 954 bool first_fragment = true; | 955 bool first_fragment = true; |
| 955 while (!insufficient_height_ && !text.empty()) { | 956 while (!insufficient_height_ && !text.empty()) { |
| 956 const string16 fragment = | 957 string16 fragment = |
| 957 ui::ElideText(text, font_, available_pixel_width_, ui::TRUNCATE_AT_END); | 958 ui::ElideText(text, font_, available_pixel_width_, ui::TRUNCATE_AT_END); |
| 959 // At least one character has to be added at every line, even if the |
| 960 // available space is too small. |
| 961 if(fragment.empty()) |
| 962 fragment = text.substr(0, 1); |
| 958 if (!first_fragment && NewLine()) | 963 if (!first_fragment && NewLine()) |
| 959 lines_added++; | 964 lines_added++; |
| 960 AddToCurrentLine(fragment); | 965 AddToCurrentLine(fragment); |
| 961 text = text.substr(fragment.length()); | 966 text = text.substr(fragment.length()); |
| 962 first_fragment = false; | 967 first_fragment = false; |
| 963 } | 968 } |
| 964 return lines_added; | 969 return lines_added; |
| 965 } | 970 } |
| 966 | 971 |
| 967 int RectangleText::AddWordOverflow(const string16& word) { | 972 int RectangleText::AddWordOverflow(const string16& word) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1122 index = char_iterator.getIndex(); | 1127 index = char_iterator.getIndex(); |
| 1123 } else { | 1128 } else { |
| 1124 // String has leading whitespace, return the elide string. | 1129 // String has leading whitespace, return the elide string. |
| 1125 return kElideString; | 1130 return kElideString; |
| 1126 } | 1131 } |
| 1127 } | 1132 } |
| 1128 return string.substr(0, index) + kElideString; | 1133 return string.substr(0, index) + kElideString; |
| 1129 } | 1134 } |
| 1130 | 1135 |
| 1131 } // namespace ui | 1136 } // namespace ui |
| OLD | NEW |