| 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 Label::Label(const base::string16& text, const gfx::FontList& font_list) { | 49 Label::Label(const base::string16& text, const gfx::FontList& font_list) { |
| 50 Init(text, font_list); | 50 Init(text, font_list); |
| 51 } | 51 } |
| 52 | 52 |
| 53 Label::~Label() { | 53 Label::~Label() { |
| 54 } | 54 } |
| 55 | 55 |
| 56 void Label::SetFontList(const gfx::FontList& font_list) { | 56 void Label::SetFontList(const gfx::FontList& font_list) { |
| 57 is_first_paint_text_ = true; | 57 is_first_paint_text_ = true; |
| 58 font_list_ = font_list; | 58 font_list_ = font_list; |
| 59 ResetCachedSize(); | 59 ResetLayoutCache(); |
| 60 PreferredSizeChanged(); | 60 PreferredSizeChanged(); |
| 61 SchedulePaint(); | 61 SchedulePaint(); |
| 62 } | 62 } |
| 63 | 63 |
| 64 void Label::SetText(const base::string16& text) { | 64 void Label::SetText(const base::string16& text) { |
| 65 if (text != text_) | 65 if (text != text_) |
| 66 SetTextInternal(text); | 66 SetTextInternal(text); |
| 67 } | 67 } |
| 68 | 68 |
| 69 void Label::SetTextInternal(const base::string16& text) { | 69 void Label::SetTextInternal(const base::string16& text) { |
| 70 is_first_paint_text_ = true; | 70 is_first_paint_text_ = true; |
| 71 text_ = text; | 71 text_ = text; |
| 72 | 72 |
| 73 if (obscured_) { | 73 if (obscured_) { |
| 74 size_t obscured_text_length = | 74 size_t obscured_text_length = |
| 75 static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, text_.length())); | 75 static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, text_.length())); |
| 76 layout_text_.assign(obscured_text_length, kPasswordReplacementChar); | 76 layout_text_.assign(obscured_text_length, kPasswordReplacementChar); |
| 77 } else { | 77 } else { |
| 78 layout_text_ = text_; | 78 layout_text_ = text_; |
| 79 } | 79 } |
| 80 | 80 |
| 81 ResetCachedSize(); | 81 ResetLayoutCache(); |
| 82 PreferredSizeChanged(); | 82 PreferredSizeChanged(); |
| 83 SchedulePaint(); | 83 SchedulePaint(); |
| 84 } | 84 } |
| 85 | 85 |
| 86 void Label::SetAutoColorReadabilityEnabled(bool enabled) { | 86 void Label::SetAutoColorReadabilityEnabled(bool enabled) { |
| 87 is_first_paint_text_ = true; | 87 is_first_paint_text_ = true; |
| 88 auto_color_readability_ = enabled; | 88 auto_color_readability_ = enabled; |
| 89 RecalculateColors(); | 89 RecalculateColors(); |
| 90 } | 90 } |
| 91 | 91 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 106 void Label::SetBackgroundColor(SkColor color) { | 106 void Label::SetBackgroundColor(SkColor color) { |
| 107 is_first_paint_text_ = true; | 107 is_first_paint_text_ = true; |
| 108 background_color_ = color; | 108 background_color_ = color; |
| 109 background_color_set_ = true; | 109 background_color_set_ = true; |
| 110 RecalculateColors(); | 110 RecalculateColors(); |
| 111 } | 111 } |
| 112 | 112 |
| 113 void Label::SetShadows(const gfx::ShadowValues& shadows) { | 113 void Label::SetShadows(const gfx::ShadowValues& shadows) { |
| 114 is_first_paint_text_ = true; | 114 is_first_paint_text_ = true; |
| 115 shadows_ = shadows; | 115 shadows_ = shadows; |
| 116 text_size_valid_ = false; | 116 ResetLayoutCache(); |
| 117 } | 117 } |
| 118 | 118 |
| 119 void Label::SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled) { | 119 void Label::SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled) { |
| 120 is_first_paint_text_ = true; | 120 is_first_paint_text_ = true; |
| 121 subpixel_rendering_enabled_ = subpixel_rendering_enabled; | 121 subpixel_rendering_enabled_ = subpixel_rendering_enabled; |
| 122 } | 122 } |
| 123 | 123 |
| 124 void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) { | 124 void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) { |
| 125 is_first_paint_text_ = true; | 125 is_first_paint_text_ = true; |
| 126 // If the UI layout is right-to-left, flip the alignment direction. | 126 // If the UI layout is right-to-left, flip the alignment direction. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 141 | 141 |
| 142 const base::i18n::TextDirection dir = | 142 const base::i18n::TextDirection dir = |
| 143 base::i18n::GetFirstStrongCharacterDirection(layout_text_); | 143 base::i18n::GetFirstStrongCharacterDirection(layout_text_); |
| 144 return dir == base::i18n::RIGHT_TO_LEFT ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT; | 144 return dir == base::i18n::RIGHT_TO_LEFT ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT; |
| 145 } | 145 } |
| 146 | 146 |
| 147 void Label::SetLineHeight(int height) { | 147 void Label::SetLineHeight(int height) { |
| 148 is_first_paint_text_ = true; | 148 is_first_paint_text_ = true; |
| 149 if (height != line_height_) { | 149 if (height != line_height_) { |
| 150 line_height_ = height; | 150 line_height_ = height; |
| 151 ResetCachedSize(); | 151 ResetLayoutCache(); |
| 152 PreferredSizeChanged(); | 152 PreferredSizeChanged(); |
| 153 SchedulePaint(); | 153 SchedulePaint(); |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 | 156 |
| 157 void Label::SetMultiLine(bool multi_line) { | 157 void Label::SetMultiLine(bool multi_line) { |
| 158 is_first_paint_text_ = true; | 158 is_first_paint_text_ = true; |
| 159 DCHECK(!multi_line || (elide_behavior_ == gfx::ELIDE_TAIL || | 159 DCHECK(!multi_line || (elide_behavior_ == gfx::ELIDE_TAIL || |
| 160 elide_behavior_ == gfx::NO_ELIDE)); | 160 elide_behavior_ == gfx::NO_ELIDE)); |
| 161 if (multi_line != multi_line_) { | 161 if (multi_line != multi_line_) { |
| 162 multi_line_ = multi_line; | 162 multi_line_ = multi_line; |
| 163 ResetCachedSize(); | 163 ResetLayoutCache(); |
| 164 PreferredSizeChanged(); | 164 PreferredSizeChanged(); |
| 165 SchedulePaint(); | 165 SchedulePaint(); |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 | 168 |
| 169 void Label::SetObscured(bool obscured) { | 169 void Label::SetObscured(bool obscured) { |
| 170 is_first_paint_text_ = true; | 170 is_first_paint_text_ = true; |
| 171 if (obscured != obscured_) { | 171 if (obscured != obscured_) { |
| 172 obscured_ = obscured; | 172 obscured_ = obscured; |
| 173 SetTextInternal(text_); | 173 SetTextInternal(text_); |
| 174 } | 174 } |
| 175 } | 175 } |
| 176 | 176 |
| 177 void Label::SetAllowCharacterBreak(bool allow_character_break) { | 177 void Label::SetAllowCharacterBreak(bool allow_character_break) { |
| 178 is_first_paint_text_ = true; | 178 is_first_paint_text_ = true; |
| 179 if (allow_character_break != allow_character_break_) { | 179 if (allow_character_break != allow_character_break_) { |
| 180 allow_character_break_ = allow_character_break; | 180 allow_character_break_ = allow_character_break; |
| 181 ResetCachedSize(); | 181 ResetLayoutCache(); |
| 182 PreferredSizeChanged(); | 182 PreferredSizeChanged(); |
| 183 SchedulePaint(); | 183 SchedulePaint(); |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) { | 187 void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) { |
| 188 is_first_paint_text_ = true; | 188 is_first_paint_text_ = true; |
| 189 DCHECK(!multi_line_ || (elide_behavior_ == gfx::ELIDE_TAIL || | 189 DCHECK(!multi_line_ || (elide_behavior_ == gfx::ELIDE_TAIL || |
| 190 elide_behavior_ == gfx::NO_ELIDE)); | 190 elide_behavior_ == gfx::NO_ELIDE)); |
| 191 if (elide_behavior != elide_behavior_) { | 191 if (elide_behavior != elide_behavior_) { |
| 192 elide_behavior_ = elide_behavior; | 192 elide_behavior_ = elide_behavior; |
| 193 ResetCachedSize(); | 193 ResetLayoutCache(); |
| 194 PreferredSizeChanged(); | 194 PreferredSizeChanged(); |
| 195 SchedulePaint(); | 195 SchedulePaint(); |
| 196 } | 196 } |
| 197 } | 197 } |
| 198 | 198 |
| 199 void Label::SetTooltipText(const base::string16& tooltip_text) { | 199 void Label::SetTooltipText(const base::string16& tooltip_text) { |
| 200 DCHECK(handles_tooltips_); | 200 DCHECK(handles_tooltips_); |
| 201 tooltip_text_ = tooltip_text; | 201 tooltip_text_ = tooltip_text; |
| 202 } | 202 } |
| 203 | 203 |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 const gfx::Insets shadow_margin = -gfx::ShadowValue::GetMargin(shadows_); | 389 const gfx::Insets shadow_margin = -gfx::ShadowValue::GetMargin(shadows_); |
| 390 text_size_.Enlarge(shadow_margin.width(), shadow_margin.height()); | 390 text_size_.Enlarge(shadow_margin.width(), shadow_margin.height()); |
| 391 text_size_valid_ = true; | 391 text_size_valid_ = true; |
| 392 } | 392 } |
| 393 | 393 |
| 394 return text_size_; | 394 return text_size_; |
| 395 } | 395 } |
| 396 | 396 |
| 397 void Label::OnBoundsChanged(const gfx::Rect& previous_bounds) { | 397 void Label::OnBoundsChanged(const gfx::Rect& previous_bounds) { |
| 398 text_size_valid_ &= !multi_line_; | 398 text_size_valid_ &= !multi_line_; |
| 399 cached_draw_params_.reset(); |
| 399 } | 400 } |
| 400 | 401 |
| 401 void Label::OnPaint(gfx::Canvas* canvas) { | 402 void Label::OnPaint(gfx::Canvas* canvas) { |
| 402 OnPaintBackground(canvas); | 403 OnPaintBackground(canvas); |
| 403 // We skip painting the focus border because it is being handled seperately by | 404 // We skip painting the focus border because it is being handled seperately by |
| 404 // some subclasses of Label. We do not want View's focus border painting to | 405 // some subclasses of Label. We do not want View's focus border painting to |
| 405 // interfere with that. | 406 // interfere with that. |
| 406 OnPaintBorder(canvas); | 407 OnPaintBorder(canvas); |
| 407 | 408 |
| 408 base::string16 paint_text; | 409 const DrawStringParams* params = CalculateDrawStringParams(); |
| 409 gfx::Rect text_bounds; | |
| 410 int flags = 0; | |
| 411 CalculateDrawStringParams(&paint_text, &text_bounds, &flags); | |
| 412 if (is_first_paint_text_) { | 410 if (is_first_paint_text_) { |
| 413 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. | 411 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. |
| 414 tracked_objects::ScopedTracker tracking_profile( | 412 tracked_objects::ScopedTracker tracking_profile( |
| 415 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText first")); | 413 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText first")); |
| 416 | 414 |
| 417 is_first_paint_text_ = false; | 415 is_first_paint_text_ = false; |
| 418 PaintText(canvas, paint_text, text_bounds, flags); | 416 PaintText(canvas, params->text, params->bounds, params->flags); |
| 419 } else { | 417 } else { |
| 420 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. | 418 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. |
| 421 tracked_objects::ScopedTracker tracking_profile( | 419 tracked_objects::ScopedTracker tracking_profile( |
| 422 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText not first")); | 420 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText not first")); |
| 423 | 421 |
| 424 PaintText(canvas, paint_text, text_bounds, flags); | 422 PaintText(canvas, params->text, params->bounds, params->flags); |
| 425 } | 423 } |
| 426 } | 424 } |
| 427 | 425 |
| 428 void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) { | 426 void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) { |
| 429 UpdateColorsFromTheme(theme); | 427 UpdateColorsFromTheme(theme); |
| 430 } | 428 } |
| 431 | 429 |
| 432 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { | 430 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { |
| 433 font_list_ = font_list; | 431 font_list_ = font_list; |
| 434 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; | 432 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; |
| 435 subpixel_rendering_enabled_ = true; | 433 subpixel_rendering_enabled_ = true; |
| 436 auto_color_readability_ = true; | 434 auto_color_readability_ = true; |
| 437 UpdateColorsFromTheme(ui::NativeTheme::instance()); | 435 UpdateColorsFromTheme(ui::NativeTheme::instance()); |
| 438 horizontal_alignment_ = gfx::ALIGN_CENTER; | 436 horizontal_alignment_ = gfx::ALIGN_CENTER; |
| 439 line_height_ = 0; | 437 line_height_ = 0; |
| 440 multi_line_ = false; | 438 multi_line_ = false; |
| 441 obscured_ = false; | 439 obscured_ = false; |
| 442 allow_character_break_ = false; | 440 allow_character_break_ = false; |
| 443 elide_behavior_ = gfx::ELIDE_TAIL; | 441 elide_behavior_ = gfx::ELIDE_TAIL; |
| 444 handles_tooltips_ = true; | 442 handles_tooltips_ = true; |
| 445 collapse_when_hidden_ = false; | 443 collapse_when_hidden_ = false; |
| 446 cached_heights_.resize(kCachedSizeLimit); | 444 cached_heights_.resize(kCachedSizeLimit); |
| 447 ResetCachedSize(); | 445 ResetLayoutCache(); |
| 448 is_first_paint_text_ = true; | 446 is_first_paint_text_ = true; |
| 449 | 447 |
| 450 SetText(text); | 448 SetText(text); |
| 451 } | 449 } |
| 452 | 450 |
| 453 void Label::RecalculateColors() { | 451 void Label::RecalculateColors() { |
| 454 actual_enabled_color_ = auto_color_readability_ ? | 452 actual_enabled_color_ = auto_color_readability_ ? |
| 455 color_utils::GetReadableColor(requested_enabled_color_, | 453 color_utils::GetReadableColor(requested_enabled_color_, |
| 456 background_color_) : | 454 background_color_) : |
| 457 requested_enabled_color_; | 455 requested_enabled_color_; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 | 532 |
| 535 return flags; | 533 return flags; |
| 536 } | 534 } |
| 537 | 535 |
| 538 gfx::Rect Label::GetAvailableRect() const { | 536 gfx::Rect Label::GetAvailableRect() const { |
| 539 gfx::Rect bounds(size()); | 537 gfx::Rect bounds(size()); |
| 540 bounds.Inset(GetInsets()); | 538 bounds.Inset(GetInsets()); |
| 541 return bounds; | 539 return bounds; |
| 542 } | 540 } |
| 543 | 541 |
| 544 void Label::CalculateDrawStringParams(base::string16* paint_text, | 542 const Label::DrawStringParams* Label::CalculateDrawStringParams() const { |
| 545 gfx::Rect* text_bounds, | 543 if (!cached_draw_params_) { |
| 546 int* flags) const { | 544 DrawStringParams* params = new DrawStringParams(); |
| 547 DCHECK(paint_text && text_bounds && flags); | |
| 548 | 545 |
| 549 const bool forbid_ellipsis = elide_behavior_ == gfx::NO_ELIDE || | 546 const bool forbid_ellipsis = elide_behavior_ == gfx::NO_ELIDE || |
| 550 elide_behavior_ == gfx::FADE_TAIL; | 547 elide_behavior_ == gfx::FADE_TAIL; |
| 551 if (multi_line_ || forbid_ellipsis) { | 548 if (multi_line_ || forbid_ellipsis) { |
| 552 *paint_text = layout_text_; | 549 params->text = layout_text_; |
| 553 } else { | 550 } else { |
| 554 *paint_text = gfx::ElideText(layout_text_, font_list_, | 551 params->text = gfx::ElideText(layout_text_, font_list_, |
| 555 GetAvailableRect().width(), elide_behavior_); | 552 GetAvailableRect().width(), elide_behavior_); |
| 553 } |
| 554 |
| 555 params->bounds = GetTextBounds(); |
| 556 params->flags = ComputeDrawStringFlags(); |
| 557 // TODO(msw): Elide multi-line text with ElideRectangleText instead. |
| 558 if (!multi_line_ || forbid_ellipsis) |
| 559 params->flags |= gfx::Canvas::NO_ELLIPSIS; |
| 560 |
| 561 cached_draw_params_.reset(params); |
| 556 } | 562 } |
| 557 | 563 |
| 558 *text_bounds = GetTextBounds(); | 564 return cached_draw_params_.get(); |
| 559 *flags = ComputeDrawStringFlags(); | |
| 560 // TODO(msw): Elide multi-line text with ElideRectangleText instead. | |
| 561 if (!multi_line_ || forbid_ellipsis) | |
| 562 *flags |= gfx::Canvas::NO_ELLIPSIS; | |
| 563 } | 565 } |
| 564 | 566 |
| 565 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) { | 567 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) { |
| 566 if (!enabled_color_set_) { | 568 if (!enabled_color_set_) { |
| 567 requested_enabled_color_ = theme->GetSystemColor( | 569 requested_enabled_color_ = theme->GetSystemColor( |
| 568 ui::NativeTheme::kColorId_LabelEnabledColor); | 570 ui::NativeTheme::kColorId_LabelEnabledColor); |
| 569 } | 571 } |
| 570 if (!disabled_color_set_) { | 572 if (!disabled_color_set_) { |
| 571 requested_disabled_color_ = theme->GetSystemColor( | 573 requested_disabled_color_ = theme->GetSystemColor( |
| 572 ui::NativeTheme::kColorId_LabelDisabledColor); | 574 ui::NativeTheme::kColorId_LabelDisabledColor); |
| 573 } | 575 } |
| 574 if (!background_color_set_) { | 576 if (!background_color_set_) { |
| 575 background_color_ = theme->GetSystemColor( | 577 background_color_ = theme->GetSystemColor( |
| 576 ui::NativeTheme::kColorId_LabelBackgroundColor); | 578 ui::NativeTheme::kColorId_LabelBackgroundColor); |
| 577 } | 579 } |
| 578 RecalculateColors(); | 580 RecalculateColors(); |
| 579 } | 581 } |
| 580 | 582 |
| 581 void Label::ResetCachedSize() { | 583 void Label::ResetLayoutCache() { |
| 584 cached_draw_params_.reset(); |
| 582 text_size_valid_ = false; | 585 text_size_valid_ = false; |
| 583 cached_heights_cursor_ = 0; | 586 cached_heights_cursor_ = 0; |
| 584 for (int i = 0; i < kCachedSizeLimit; ++i) | 587 for (int i = 0; i < kCachedSizeLimit; ++i) |
| 585 cached_heights_[i] = gfx::Size(); | 588 cached_heights_[i] = gfx::Size(); |
| 586 } | 589 } |
| 587 | 590 |
| 588 bool Label::ShouldShowDefaultTooltip() const { | 591 bool Label::ShouldShowDefaultTooltip() const { |
| 589 const gfx::Size text_size = GetTextSize(); | 592 const gfx::Size text_size = GetTextSize(); |
| 590 const gfx::Size size = GetContentsBounds().size(); | 593 const gfx::Size size = GetContentsBounds().size(); |
| 591 return !obscured() && (text_size.width() > size.width() || | 594 return !obscured() && (text_size.width() > size.width() || |
| 592 (multi_line_ && text_size.height() > size.height())); | 595 (multi_line_ && text_size.height() > size.height())); |
| 593 } | 596 } |
| 594 | 597 |
| 595 } // namespace views | 598 } // namespace views |
| OLD | NEW |