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 |