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