summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authortsepez@chromium.org <tsepez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-29 16:28:57 +0000
committertsepez@chromium.org <tsepez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-29 16:28:57 +0000
commit416126c592ee845356e41b5540ac341fe8108a93 (patch)
treed7dcc7f790d4302d107ef4769fabc3d508ef615c /ui
parente12b30268ea0dffc301a9bb06f25db6a924d6e00 (diff)
downloadchromium_src-416126c592ee845356e41b5540ac341fe8108a93.zip
chromium_src-416126c592ee845356e41b5540ac341fe8108a93.tar.gz
chromium_src-416126c592ee845356e41b5540ac341fe8108a93.tar.bz2
Lengthy alerts have line breaks in them on all platforms. Only do this
where we can't trust the window system to behave properly. Even so, only break long words, assuming that spaces are properly triggering breaks. BUG=77231 TEST=Goto URL javascript:alert(""It looks like you're in the middle of composing another message. Are you sure you want to continue? This may affect any unsaved drafts."); and ensure no break between "unsaved" and "drafts". Review URL: http://codereview.chromium.org/6696074 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79692 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/base/text/text_elider.cc34
-rw-r--r--ui/base/text/text_elider.h14
-rw-r--r--ui/base/text/text_elider_unittest.cc90
3 files changed, 115 insertions, 23 deletions
diff --git a/ui/base/text/text_elider.cc b/ui/base/text/text_elider.cc
index 4b18619..e6aaa26 100644
--- a/ui/base/text/text_elider.cc
+++ b/ui/base/text/text_elider.cc
@@ -507,11 +507,13 @@ namespace {
// can be broken into smaller methods sharing this state.
class RectangleString {
public:
- RectangleString(size_t max_rows, size_t max_cols, string16 *output)
+ RectangleString(size_t max_rows, size_t max_cols,
+ bool strict, string16 *output)
: max_rows_(max_rows),
max_cols_(max_cols),
current_row_(0),
current_col_(0),
+ strict_(strict),
suppressed_(false),
output_(output) {}
@@ -542,10 +544,11 @@ class RectangleString {
// have not been exceeded, advancing the current position.
void Append(const string16& string);
- // Add a newline to the output string if the rectangular boundaries
- // have not been exceeded, resetting the current position to the
- // beginning of the next line.
- void NewLine();
+ // Set the current position to the beginning of the next line. If
+ // |output| is true, add a newline to the output string if the rectangular
+ // boundaries have not been exceeded. If |output| is false, we assume
+ // some other mechanism will (likely) do similar breaking after the fact.
+ void NewLine(bool output);
// Maximum number of rows allowed in the output string.
size_t max_rows_;
@@ -564,6 +567,9 @@ class RectangleString {
// Current character position, should never exceed max_cols_.
size_t current_col_;
+ // True when we do whitespace to newline conversions ourselves.
+ bool strict_;
+
// True when some of the input has been truncated.
bool suppressed_;
@@ -610,7 +616,7 @@ void RectangleString::AddWord(const string16& word) {
if (word.length() < max_cols_) {
// Word can be made to fit, no need to fragment it.
if (current_col_ + word.length() >= max_cols_)
- NewLine();
+ NewLine(strict_);
Append(word);
} else {
// Word is so big that it must be fragmented.
@@ -621,7 +627,7 @@ void RectangleString::AddWord(const string16& word) {
// When boundary is hit, add as much as will fit on this line.
if (current_col_ + (chars.char_pos() - char_start) >= max_cols_) {
Append(word.substr(array_start, chars.array_pos() - array_start));
- NewLine();
+ NewLine(true);
array_start = chars.array_pos();
char_start = chars.char_pos();
}
@@ -641,11 +647,13 @@ void RectangleString::Append(const string16& string) {
current_col_ += string.length();
}
-void RectangleString::NewLine() {
- if (current_row_ < max_rows_)
- output_->append(ASCIIToUTF16("\n"));
- else
+void RectangleString::NewLine(bool output) {
+ if (current_row_ < max_rows_) {
+ if (output)
+ output_->append(ASCIIToUTF16("\n"));
+ } else {
suppressed_ = true;
+ }
++current_row_;
current_col_ = 0;
}
@@ -655,8 +663,8 @@ void RectangleString::NewLine() {
namespace ui {
bool ElideRectangleString(const string16& input, size_t max_rows,
- size_t max_cols, string16* output) {
- RectangleString rect(max_rows, max_cols, output);
+ size_t max_cols, bool strict, string16* output) {
+ RectangleString rect(max_rows, max_cols, strict, output);
rect.Init();
rect.AddString(input);
return rect.Finalize();
diff --git a/ui/base/text/text_elider.h b/ui/base/text/text_elider.h
index f010712..5dd3dc5 100644
--- a/ui/base/text/text_elider.h
+++ b/ui/base/text/text_elider.h
@@ -106,13 +106,15 @@ bool ElideString(const string16& input, int max_len, string16* output);
// Reformat |input| into |output| so that it fits into a |max_rows| by
// |max_cols| rectangle of characters. Input newlines are respected, but
-// lines that are too long are broken into pieces, first at naturally
-// occuring whitespace boundaries, and then intra-word (respecting UTF-16
-// surrogate pairs) as necssary. Truncation (indicated by an added 3 dots)
-// occurs if the result is still too long. Returns true if the input had
-// to be truncated (and not just reformatted).
+// lines that are too long are broken into pieces. If |strict| is true,
+// we break first at naturally occuring whitespace boundaries, otherwise
+// we assume some other mechanism will do this in approximately the same
+// spot after the fact. If the word itself is too long, we always break
+// intra-word (respecting UTF-16 surrogate pairs) as necssary. Truncation
+// (indicated by an added 3 dots) occurs if the result is still too long.
+// Returns true if the input had to be truncated (and not just reformatted).
bool ElideRectangleString(const string16& input, size_t max_rows,
- size_t max_cols, string16* output);
+ size_t max_cols, bool strict, string16* output);
} // namespace ui
diff --git a/ui/base/text/text_elider_unittest.cc b/ui/base/text/text_elider_unittest.cc
index 083d9f2..69cf0c1 100644
--- a/ui/base/text/text_elider_unittest.cc
+++ b/ui/base/text/text_elider_unittest.cc
@@ -401,7 +401,89 @@ TEST(TextEliderTest, ElideRectangleString) {
EXPECT_EQ(cases[i].result,
ui::ElideRectangleString(UTF8ToUTF16(cases[i].input),
cases[i].max_rows, cases[i].max_cols,
- &output));
+ true, &output));
+ EXPECT_EQ(cases[i].output, UTF16ToUTF8(output));
+ }
+}
+
+TEST(TextEliderTest, ElideRectangleStringNotStrict) {
+ struct TestData {
+ const char* input;
+ int max_rows;
+ int max_cols;
+ bool result;
+ const char* output;
+ } cases[] = {
+ { "", 0, 0, false, "" },
+ { "", 1, 1, false, "" },
+ { "Hi, my name_is\nDick", 0, 0, true, "..." },
+ { "Hi, my name_is\nDick", 1, 0, true, "\n..." },
+ { "Hi, my name_is\nDick", 0, 1, true, "..." },
+ { "Hi, my name_is\nDick", 1, 1, true, "H\n..." },
+ { "Hi, my name_is\nDick", 2, 1, true, "H\ni\n..." },
+ { "Hi, my name_is\nDick", 3, 1, true, "H\ni\n,\n..." },
+ { "Hi, my name_is\nDick", 4, 1, true, "H\ni\n,\n \n..." },
+ { "Hi, my name_is\nDick", 5, 1, true, "H\ni\n,\n \nm\n..." },
+ { "Hi, my name_is\nDick", 0, 2, true, "..." },
+ { "Hi, my name_is\nDick", 1, 2, true, "Hi\n..." },
+ { "Hi, my name_is\nDick", 2, 2, true, "Hi\n, \n..." },
+ { "Hi, my name_is\nDick", 3, 2, true, "Hi\n, \nmy\n..." },
+ { "Hi, my name_is\nDick", 4, 2, true, "Hi\n, \nmy\n n\n..." },
+ { "Hi, my name_is\nDick", 5, 2, true, "Hi\n, \nmy\n n\nam\n..." },
+ { "Hi, my name_is\nDick", 0, 3, true, "..." },
+ { "Hi, my name_is\nDick", 1, 3, true, "Hi,\n..." },
+ { "Hi, my name_is\nDick", 2, 3, true, "Hi,\n my\n..." },
+ { "Hi, my name_is\nDick", 3, 3, true, "Hi,\n my\n na\n..." },
+ { "Hi, my name_is\nDick", 4, 3, true, "Hi,\n my\n na\nme_\n..." },
+ { "Hi, my name_is\nDick", 5, 3, true, "Hi,\n my\n na\nme_\nis\n..." },
+ { "Hi, my name_is\nDick", 1, 4, true, "Hi, ..." },
+ { "Hi, my name_is\nDick", 2, 4, true, "Hi, my n\n..." },
+ { "Hi, my name_is\nDick", 3, 4, true, "Hi, my n\name_\n..." },
+ { "Hi, my name_is\nDick", 4, 4, true, "Hi, my n\name_\nis\n..." },
+ { "Hi, my name_is\nDick", 5, 4, false, "Hi, my n\name_\nis\nDick" },
+ { "Hi, my name_is\nDick", 1, 5, true, "Hi, ..." },
+ { "Hi, my name_is\nDick", 2, 5, true, "Hi, my na\n..." },
+ { "Hi, my name_is\nDick", 3, 5, true, "Hi, my na\nme_is\n..." },
+ { "Hi, my name_is\nDick", 4, 5, true, "Hi, my na\nme_is\n\n..." },
+ { "Hi, my name_is\nDick", 5, 5, false, "Hi, my na\nme_is\n\nDick" },
+ { "Hi, my name_is\nDick", 1, 6, true, "Hi, ..." },
+ { "Hi, my name_is\nDick", 2, 6, true, "Hi, my nam\n..." },
+ { "Hi, my name_is\nDick", 3, 6, true, "Hi, my nam\ne_is\n..." },
+ { "Hi, my name_is\nDick", 4, 6, false, "Hi, my nam\ne_is\nDick" },
+ { "Hi, my name_is\nDick", 5, 6, false, "Hi, my nam\ne_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 7, true, "Hi, ..." },
+ { "Hi, my name_is\nDick", 2, 7, true, "Hi, my name\n..." },
+ { "Hi, my name_is\nDick", 3, 7, true, "Hi, my name\n_is\n..." },
+ { "Hi, my name_is\nDick", 4, 7, false, "Hi, my name\n_is\nDick" },
+ { "Hi, my name_is\nDick", 5, 7, false, "Hi, my name\n_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 8, true, "Hi, my n\n..." },
+ { "Hi, my name_is\nDick", 2, 8, true, "Hi, my n\name_is\n..." },
+ { "Hi, my name_is\nDick", 3, 8, false, "Hi, my n\name_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 9, true, "Hi, my ..." },
+ { "Hi, my name_is\nDick", 2, 9, true, "Hi, my name_is\n..." },
+ { "Hi, my name_is\nDick", 3, 9, false, "Hi, my name_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 10, true, "Hi, my ..." },
+ { "Hi, my name_is\nDick", 2, 10, true, "Hi, my name_is\n..." },
+ { "Hi, my name_is\nDick", 3, 10, false, "Hi, my name_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 11, true, "Hi, my ..." },
+ { "Hi, my name_is\nDick", 2, 11, true, "Hi, my name_is\n..." },
+ { "Hi, my name_is\nDick", 3, 11, false, "Hi, my name_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 12, true, "Hi, my ..." },
+ { "Hi, my name_is\nDick", 2, 12, true, "Hi, my name_is\n..." },
+ { "Hi, my name_is\nDick", 3, 12, false, "Hi, my name_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 13, true, "Hi, my ..." },
+ { "Hi, my name_is\nDick", 2, 13, true, "Hi, my name_is\n..." },
+ { "Hi, my name_is\nDick", 3, 13, false, "Hi, my name_is\nDick" },
+ { "Hi, my name_is\nDick", 1, 20, true, "Hi, my name_is\n..." },
+ { "Hi, my name_is\nDick", 2, 20, false, "Hi, my name_is\nDick" },
+ { "Hi, my name_is Dick", 1, 40, false, "Hi, my name_is Dick" },
+ };
+ string16 output;
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ EXPECT_EQ(cases[i].result,
+ ui::ElideRectangleString(UTF8ToUTF16(cases[i].input),
+ cases[i].max_rows, cases[i].max_cols,
+ false, &output));
EXPECT_EQ(cases[i].output, UTF16ToUTF8(output));
}
}
@@ -419,9 +501,9 @@ TEST(TextEliderTest, ElideRectangleWide16) {
L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9\x03bf\x03c2\x0020\n"
L"\x0399\x03c3\x03c4\x03cc\x03c2"));
string16 output;
- EXPECT_TRUE(ui::ElideRectangleString(str, 2, 4, &output));
+ EXPECT_TRUE(ui::ElideRectangleString(str, 2, 4, true, &output));
EXPECT_EQ(out1, output);
- EXPECT_FALSE(ui::ElideRectangleString(str, 2, 12, &output));
+ EXPECT_FALSE(ui::ElideRectangleString(str, 2, 12, true, &output));
EXPECT_EQ(out2, output);
}
@@ -434,7 +516,7 @@ TEST(TextEliderTest, ElideRectangleWide32) {
"\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\n"
"\xF0\x9D\x92\x9C \naaa\n..."));
string16 output;
- EXPECT_TRUE(ui::ElideRectangleString(str, 3, 3, &output));
+ EXPECT_TRUE(ui::ElideRectangleString(str, 3, 3, true, &output));
EXPECT_EQ(out, output);
}