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 #include "ui/views/controls/label.h" | 5 #include "ui/views/controls/label.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <limits> | 9 #include <limits> |
10 #include <vector> | 10 #include <vector> |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 | 143 |
144 void Label::SetObscured(bool obscured) { | 144 void Label::SetObscured(bool obscured) { |
145 if (this->obscured() == obscured) | 145 if (this->obscured() == obscured) |
146 return; | 146 return; |
147 is_first_paint_text_ = true; | 147 is_first_paint_text_ = true; |
148 render_text_->SetObscured(obscured); | 148 render_text_->SetObscured(obscured); |
149 ResetLayout(); | 149 ResetLayout(); |
150 } | 150 } |
151 | 151 |
152 void Label::SetAllowCharacterBreak(bool allow_character_break) { | 152 void Label::SetAllowCharacterBreak(bool allow_character_break) { |
153 if (allow_character_break_ == allow_character_break) | 153 const gfx::WordWrapBehavior behavior = |
154 allow_character_break ? gfx::WRAP_LONG_WORDS : gfx::TRUNCATE_LONG_WORDS; | |
155 if (render_text_->word_wrap_behavior() == behavior) | |
154 return; | 156 return; |
155 is_first_paint_text_ = true; | 157 is_first_paint_text_ = true; |
156 allow_character_break_ = allow_character_break; | 158 render_text_->SetWordWrapBehavior(behavior); |
157 ResetLayout(); | 159 ResetLayout(); |
msw
2015/03/26 19:36:30
nit: perhaps the layout shouldn't be reset (nor sh
Jun Mukai
2015/03/26 22:47:39
Done.
| |
158 } | 160 } |
159 | 161 |
160 void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) { | 162 void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) { |
161 DCHECK(!multi_line() || (elide_behavior_ == gfx::ELIDE_TAIL || | 163 DCHECK(!multi_line() || (elide_behavior_ == gfx::ELIDE_TAIL || |
162 elide_behavior_ == gfx::NO_ELIDE)); | 164 elide_behavior_ == gfx::NO_ELIDE)); |
163 if (elide_behavior_ == elide_behavior) | 165 if (elide_behavior_ == elide_behavior) |
164 return; | 166 return; |
165 is_first_paint_text_ = true; | 167 is_first_paint_text_ = true; |
166 elide_behavior_ = elide_behavior; | 168 elide_behavior_ = elide_behavior; |
167 ResetLayout(); | 169 ResetLayout(); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 | 253 |
252 int Label::GetHeightForWidth(int w) const { | 254 int Label::GetHeightForWidth(int w) const { |
253 if (!visible() && collapse_when_hidden_) | 255 if (!visible() && collapse_when_hidden_) |
254 return 0; | 256 return 0; |
255 | 257 |
256 w -= GetInsets().width(); | 258 w -= GetInsets().width(); |
257 if (!multi_line() || text().empty() || w <= 0) | 259 if (!multi_line() || text().empty() || w <= 0) |
258 return std::max(line_height(), font_list().GetHeight()); | 260 return std::max(line_height(), font_list().GetHeight()); |
259 | 261 |
260 int height = 0; | 262 int height = 0; |
261 // RenderText doesn't support character breaks. | 263 if (render_text_->MultilineSupported()) { |
262 // TODO(mukai): remove this restriction. | |
263 if (render_text_->MultilineSupported() && !allow_character_break_) { | |
264 // SetDisplayRect() has a side effect for later calls of GetStringSize(). | 264 // SetDisplayRect() has a side effect for later calls of GetStringSize(). |
265 // Be careful to invoke |render_text_->SetDisplayRect(gfx::Rect())| to | 265 // Be careful to invoke |render_text_->SetDisplayRect(gfx::Rect())| to |
266 // cancel this effect before the next time GetStringSize() is called. | 266 // cancel this effect before the next time GetStringSize() is called. |
267 // It would be beneficial not to cancel here, considering that some layout | 267 // It would be beneficial not to cancel here, considering that some layout |
268 // managers invoke GetHeightForWidth() for the same width multiple times | 268 // managers invoke GetHeightForWidth() for the same width multiple times |
269 // and |render_text_| can cache the height. | 269 // and |render_text_| can cache the height. |
270 render_text_->SetDisplayRect(gfx::Rect(0, 0, w, 0)); | 270 render_text_->SetDisplayRect(gfx::Rect(0, 0, w, 0)); |
271 height = render_text_->GetStringSize().height(); | 271 height = render_text_->GetStringSize().height(); |
272 } else { | 272 } else { |
273 std::vector<base::string16> lines = GetLinesForWidth(w); | 273 std::vector<base::string16> lines = GetLinesForWidth(w); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 | 377 |
378 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { | 378 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { |
379 render_text_.reset(gfx::RenderText::CreateInstance()); | 379 render_text_.reset(gfx::RenderText::CreateInstance()); |
380 render_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER); | 380 render_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER); |
381 render_text_->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT); | 381 render_text_->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT); |
382 // NOTE: |render_text_| should not be elided at all. This is used to keep some | 382 // NOTE: |render_text_| should not be elided at all. This is used to keep some |
383 // properties and to compute the size of the string. | 383 // properties and to compute the size of the string. |
384 render_text_->SetElideBehavior(gfx::NO_ELIDE); | 384 render_text_->SetElideBehavior(gfx::NO_ELIDE); |
385 render_text_->SetFontList(font_list); | 385 render_text_->SetFontList(font_list); |
386 render_text_->SetCursorEnabled(false); | 386 render_text_->SetCursorEnabled(false); |
387 render_text_->SetWordWrapBehavior(gfx::TRUNCATE_LONG_WORDS); | |
387 | 388 |
388 elide_behavior_ = gfx::ELIDE_TAIL; | 389 elide_behavior_ = gfx::ELIDE_TAIL; |
389 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; | 390 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; |
390 subpixel_rendering_enabled_ = true; | 391 subpixel_rendering_enabled_ = true; |
391 auto_color_readability_ = true; | 392 auto_color_readability_ = true; |
392 multi_line_ = false; | 393 multi_line_ = false; |
393 UpdateColorsFromTheme(ui::NativeTheme::instance()); | 394 UpdateColorsFromTheme(ui::NativeTheme::instance()); |
394 handles_tooltips_ = true; | 395 handles_tooltips_ = true; |
395 collapse_when_hidden_ = false; | 396 collapse_when_hidden_ = false; |
396 allow_character_break_ = false; | |
397 max_width_ = 0; | 397 max_width_ = 0; |
398 is_first_paint_text_ = true; | 398 is_first_paint_text_ = true; |
399 SetText(text); | 399 SetText(text); |
400 } | 400 } |
401 | 401 |
402 void Label::ResetLayout() { | 402 void Label::ResetLayout() { |
403 InvalidateLayout(); | 403 InvalidateLayout(); |
404 PreferredSizeChanged(); | 404 PreferredSizeChanged(); |
405 SchedulePaint(); | 405 SchedulePaint(); |
406 lines_.clear(); | 406 lines_.clear(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 if (alignment == gfx::ALIGN_TO_HEAD) | 444 if (alignment == gfx::ALIGN_TO_HEAD) |
445 alignment = rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT; | 445 alignment = rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT; |
446 directionality = | 446 directionality = |
447 rtl ? gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR; | 447 rtl ? gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR; |
448 } | 448 } |
449 | 449 |
450 // Text eliding is not supported for multi-lined Labels. | 450 // Text eliding is not supported for multi-lined Labels. |
451 // TODO(mukai): Add multi-lined elided text support. | 451 // TODO(mukai): Add multi-lined elided text support. |
452 gfx::ElideBehavior elide_behavior = | 452 gfx::ElideBehavior elide_behavior = |
453 multi_line() ? gfx::NO_ELIDE : elide_behavior_; | 453 multi_line() ? gfx::NO_ELIDE : elide_behavior_; |
454 if (!multi_line() || | 454 if (!multi_line() || render_text_->MultilineSupported()) { |
455 (render_text_->MultilineSupported() && !allow_character_break_)) { | |
456 scoped_ptr<gfx::RenderText> render_text = | 455 scoped_ptr<gfx::RenderText> render_text = |
457 CreateRenderText(text(), alignment, directionality, elide_behavior); | 456 CreateRenderText(text(), alignment, directionality, elide_behavior); |
458 render_text->SetDisplayRect(rect); | 457 render_text->SetDisplayRect(rect); |
459 render_text->SetMultiline(multi_line()); | 458 render_text->SetMultiline(multi_line()); |
459 render_text->SetWordWrapBehavior(render_text_->word_wrap_behavior()); | |
460 lines_.push_back(render_text.release()); | 460 lines_.push_back(render_text.release()); |
461 } else { | 461 } else { |
462 std::vector<base::string16> lines = GetLinesForWidth(rect.width()); | 462 std::vector<base::string16> lines = GetLinesForWidth(rect.width()); |
463 if (lines.size() > 1) | 463 if (lines.size() > 1) |
464 rect.set_height(std::max(line_height(), font_list().GetHeight())); | 464 rect.set_height(std::max(line_height(), font_list().GetHeight())); |
465 | 465 |
466 const int bottom = GetContentsBounds().bottom(); | 466 const int bottom = GetContentsBounds().bottom(); |
467 for (size_t i = 0; i < lines.size() && rect.y() <= bottom; ++i) { | 467 for (size_t i = 0; i < lines.size() && rect.y() <= bottom; ++i) { |
468 scoped_ptr<gfx::RenderText> line = | 468 scoped_ptr<gfx::RenderText> line = |
469 CreateRenderText(lines[i], alignment, directionality, elide_behavior); | 469 CreateRenderText(lines[i], alignment, directionality, elide_behavior); |
(...skipping 27 matching lines...) Expand all Loading... | |
497 return focus_bounds; | 497 return focus_bounds; |
498 } | 498 } |
499 | 499 |
500 std::vector<base::string16> Label::GetLinesForWidth(int width) const { | 500 std::vector<base::string16> Label::GetLinesForWidth(int width) const { |
501 std::vector<base::string16> lines; | 501 std::vector<base::string16> lines; |
502 // |width| can be 0 when getting the default text size, in that case | 502 // |width| can be 0 when getting the default text size, in that case |
503 // the ideal lines (i.e. broken at newline characters) are wanted. | 503 // the ideal lines (i.e. broken at newline characters) are wanted. |
504 if (width <= 0) { | 504 if (width <= 0) { |
505 base::SplitString(render_text_->GetDisplayText(), '\n', &lines); | 505 base::SplitString(render_text_->GetDisplayText(), '\n', &lines); |
506 } else { | 506 } else { |
507 const gfx::WordWrapBehavior wrap = allow_character_break_ | |
508 ? gfx::WRAP_LONG_WORDS | |
509 : gfx::TRUNCATE_LONG_WORDS; | |
510 gfx::ElideRectangleText(render_text_->GetDisplayText(), font_list(), width, | 507 gfx::ElideRectangleText(render_text_->GetDisplayText(), font_list(), width, |
511 std::numeric_limits<int>::max(), wrap, &lines); | 508 std::numeric_limits<int>::max(), |
509 render_text_->word_wrap_behavior(), &lines); | |
512 } | 510 } |
513 return lines; | 511 return lines; |
514 } | 512 } |
515 | 513 |
516 gfx::Size Label::GetTextSize() const { | 514 gfx::Size Label::GetTextSize() const { |
517 gfx::Size size; | 515 gfx::Size size; |
518 if (text().empty()) { | 516 if (text().empty()) { |
519 size = gfx::Size(0, std::max(line_height(), font_list().GetHeight())); | 517 size = gfx::Size(0, std::max(line_height(), font_list().GetHeight())); |
520 } else if (!multi_line() || | 518 } else if (!multi_line() || render_text_->MultilineSupported()) { |
521 (render_text_->MultilineSupported() && !allow_character_break_)) { | |
522 // Cancel the display rect of |render_text_|. The display rect may be | 519 // Cancel the display rect of |render_text_|. The display rect may be |
523 // specified in GetHeightForWidth(), and specifying empty Rect cancels | 520 // specified in GetHeightForWidth(), and specifying empty Rect cancels |
524 // its effect. See also the comment in GetHeightForWidth(). | 521 // its effect. See also the comment in GetHeightForWidth(). |
525 // TODO(mukai): use gfx::Rect() to compute the ideal size rather than | 522 // TODO(mukai): use gfx::Rect() to compute the ideal size rather than |
526 // the current width(). See crbug.com/468494, crbug.com/467526, and | 523 // the current width(). See crbug.com/468494, crbug.com/467526, and |
527 // the comment for MultilinePreferredSizeTest in label_unittest.cc. | 524 // the comment for MultilinePreferredSizeTest in label_unittest.cc. |
528 render_text_->SetDisplayRect(gfx::Rect(0, 0, width(), 0)); | 525 render_text_->SetDisplayRect(gfx::Rect(0, 0, width(), 0)); |
529 size = render_text_->GetStringSize(); | 526 size = render_text_->GetStringSize(); |
530 } else { | 527 } else { |
531 // Get the natural text size, unelided and only wrapped on newlines. | 528 // Get the natural text size, unelided and only wrapped on newlines. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
581 } | 578 } |
582 | 579 |
583 bool Label::ShouldShowDefaultTooltip() const { | 580 bool Label::ShouldShowDefaultTooltip() const { |
584 const gfx::Size text_size = GetTextSize(); | 581 const gfx::Size text_size = GetTextSize(); |
585 const gfx::Size size = GetContentsBounds().size(); | 582 const gfx::Size size = GetContentsBounds().size(); |
586 return !obscured() && (text_size.width() > size.width() || | 583 return !obscured() && (text_size.width() > size.width() || |
587 (multi_line() && text_size.height() > size.height())); | 584 (multi_line() && text_size.height() > size.height())); |
588 } | 585 } |
589 | 586 |
590 } // namespace views | 587 } // namespace views |
OLD | NEW |