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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 | 284 |
285 for (size_t i = 0; i < cached_heights_.size(); ++i) { | 285 for (size_t i = 0; i < cached_heights_.size(); ++i) { |
286 const gfx::Size& s = cached_heights_[i]; | 286 const gfx::Size& s = cached_heights_[i]; |
287 if (s.width() == w) | 287 if (s.width() == w) |
288 return s.height() + GetInsets().height(); | 288 return s.height() + GetInsets().height(); |
289 } | 289 } |
290 | 290 |
291 int cache_width = w; | 291 int cache_width = w; |
292 | 292 |
293 int h = font_list_.GetHeight(); | 293 int h = font_list_.GetHeight(); |
294 const int flags = ComputeDrawStringFlags(); | 294 const int flags = ComputeDrawStringFlags(); |
sky
2015/01/08 22:54:57
It seems like there is still a number of places ca
ckocagil
2015/01/09 15:05:14
There are 2 calls to ComputeDrawStringFlags() othe
sky
2015/01/09 17:07:09
Fair enough. Please add comments to these places a
| |
295 gfx::Canvas::SizeStringInt( | 295 gfx::Canvas::SizeStringInt( |
296 layout_text_, font_list_, &w, &h, line_height_, flags); | 296 layout_text_, font_list_, &w, &h, line_height_, flags); |
297 cached_heights_[cached_heights_cursor_] = gfx::Size(cache_width, h); | 297 cached_heights_[cached_heights_cursor_] = gfx::Size(cache_width, h); |
298 cached_heights_cursor_ = (cached_heights_cursor_ + 1) % kCachedSizeLimit; | 298 cached_heights_cursor_ = (cached_heights_cursor_ + 1) % kCachedSizeLimit; |
299 return h + GetInsets().height(); | 299 return h + GetInsets().height(); |
300 } | 300 } |
301 | 301 |
302 const char* Label::GetClassName() const { | 302 const char* Label::GetClassName() const { |
303 return kViewClassName; | 303 return kViewClassName; |
304 } | 304 } |
(...skipping 84 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_.text.clear(); | |
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); |
408 if (layout_text_.empty()) | |
409 return; | |
407 | 410 |
408 base::string16 paint_text; | 411 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_) { | 412 if (is_first_paint_text_) { |
413 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. | 413 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. |
414 tracked_objects::ScopedTracker tracking_profile( | 414 tracked_objects::ScopedTracker tracking_profile( |
415 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText first")); | 415 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText first")); |
416 | 416 |
417 is_first_paint_text_ = false; | 417 is_first_paint_text_ = false; |
418 PaintText(canvas, paint_text, text_bounds, flags); | 418 PaintText(canvas, params->text, params->bounds, params->flags); |
419 } else { | 419 } else { |
420 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. | 420 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed. |
421 tracked_objects::ScopedTracker tracking_profile( | 421 tracked_objects::ScopedTracker tracking_profile( |
422 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText not first")); | 422 FROM_HERE_WITH_EXPLICIT_FUNCTION("431326 Label::PaintText not first")); |
423 | 423 |
424 PaintText(canvas, paint_text, text_bounds, flags); | 424 PaintText(canvas, params->text, params->bounds, params->flags); |
425 } | 425 } |
426 } | 426 } |
427 | 427 |
428 void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) { | 428 void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) { |
429 UpdateColorsFromTheme(theme); | 429 UpdateColorsFromTheme(theme); |
430 } | 430 } |
431 | 431 |
432 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { | 432 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { |
433 font_list_ = font_list; | 433 font_list_ = font_list; |
434 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; | 434 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; |
435 subpixel_rendering_enabled_ = true; | 435 subpixel_rendering_enabled_ = true; |
436 auto_color_readability_ = true; | 436 auto_color_readability_ = true; |
437 UpdateColorsFromTheme(ui::NativeTheme::instance()); | 437 UpdateColorsFromTheme(ui::NativeTheme::instance()); |
438 horizontal_alignment_ = gfx::ALIGN_CENTER; | 438 horizontal_alignment_ = gfx::ALIGN_CENTER; |
439 line_height_ = 0; | 439 line_height_ = 0; |
440 multi_line_ = false; | 440 multi_line_ = false; |
441 obscured_ = false; | 441 obscured_ = false; |
442 allow_character_break_ = false; | 442 allow_character_break_ = false; |
443 elide_behavior_ = gfx::ELIDE_TAIL; | 443 elide_behavior_ = gfx::ELIDE_TAIL; |
444 handles_tooltips_ = true; | 444 handles_tooltips_ = true; |
445 collapse_when_hidden_ = false; | 445 collapse_when_hidden_ = false; |
446 cached_heights_.resize(kCachedSizeLimit); | 446 cached_heights_.resize(kCachedSizeLimit); |
447 ResetCachedSize(); | 447 ResetLayoutCache(); |
448 is_first_paint_text_ = true; | 448 is_first_paint_text_ = true; |
449 | 449 |
450 SetText(text); | 450 SetText(text); |
451 } | 451 } |
452 | 452 |
453 void Label::RecalculateColors() { | 453 void Label::RecalculateColors() { |
454 actual_enabled_color_ = auto_color_readability_ ? | 454 actual_enabled_color_ = auto_color_readability_ ? |
455 color_utils::GetReadableColor(requested_enabled_color_, | 455 color_utils::GetReadableColor(requested_enabled_color_, |
456 background_color_) : | 456 background_color_) : |
457 requested_enabled_color_; | 457 requested_enabled_color_; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
534 | 534 |
535 return flags; | 535 return flags; |
536 } | 536 } |
537 | 537 |
538 gfx::Rect Label::GetAvailableRect() const { | 538 gfx::Rect Label::GetAvailableRect() const { |
539 gfx::Rect bounds(size()); | 539 gfx::Rect bounds(size()); |
540 bounds.Inset(GetInsets()); | 540 bounds.Inset(GetInsets()); |
541 return bounds; | 541 return bounds; |
542 } | 542 } |
543 | 543 |
544 void Label::CalculateDrawStringParams(base::string16* paint_text, | 544 const Label::DrawStringParams* Label::CalculateDrawStringParams() const { |
545 gfx::Rect* text_bounds, | 545 if (cached_draw_params_.text.empty()) { |
546 int* flags) const { | 546 const bool forbid_ellipsis = elide_behavior_ == gfx::NO_ELIDE || |
547 DCHECK(paint_text && text_bounds && flags); | 547 elide_behavior_ == gfx::FADE_TAIL; |
548 if (multi_line_ || forbid_ellipsis) { | |
549 cached_draw_params_.text = layout_text_; | |
550 } else { | |
551 cached_draw_params_.text = gfx::ElideText(layout_text_, font_list_, | |
552 GetAvailableRect().width(), elide_behavior_); | |
553 } | |
548 | 554 |
549 const bool forbid_ellipsis = elide_behavior_ == gfx::NO_ELIDE || | 555 cached_draw_params_.bounds = GetTextBounds(); |
550 elide_behavior_ == gfx::FADE_TAIL; | 556 cached_draw_params_.flags = ComputeDrawStringFlags(); |
551 if (multi_line_ || forbid_ellipsis) { | 557 // TODO(msw): Elide multi-line text with ElideRectangleText instead. |
552 *paint_text = layout_text_; | 558 if (!multi_line_ || forbid_ellipsis) |
553 } else { | 559 cached_draw_params_.flags |= gfx::Canvas::NO_ELLIPSIS; |
554 *paint_text = gfx::ElideText(layout_text_, font_list_, | |
555 GetAvailableRect().width(), elide_behavior_); | |
556 } | 560 } |
557 | 561 |
558 *text_bounds = GetTextBounds(); | 562 return &cached_draw_params_; |
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 } | 563 } |
564 | 564 |
565 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) { | 565 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) { |
566 if (!enabled_color_set_) { | 566 if (!enabled_color_set_) { |
567 requested_enabled_color_ = theme->GetSystemColor( | 567 requested_enabled_color_ = theme->GetSystemColor( |
568 ui::NativeTheme::kColorId_LabelEnabledColor); | 568 ui::NativeTheme::kColorId_LabelEnabledColor); |
569 } | 569 } |
570 if (!disabled_color_set_) { | 570 if (!disabled_color_set_) { |
571 requested_disabled_color_ = theme->GetSystemColor( | 571 requested_disabled_color_ = theme->GetSystemColor( |
572 ui::NativeTheme::kColorId_LabelDisabledColor); | 572 ui::NativeTheme::kColorId_LabelDisabledColor); |
573 } | 573 } |
574 if (!background_color_set_) { | 574 if (!background_color_set_) { |
575 background_color_ = theme->GetSystemColor( | 575 background_color_ = theme->GetSystemColor( |
576 ui::NativeTheme::kColorId_LabelBackgroundColor); | 576 ui::NativeTheme::kColorId_LabelBackgroundColor); |
577 } | 577 } |
578 RecalculateColors(); | 578 RecalculateColors(); |
579 } | 579 } |
580 | 580 |
581 void Label::ResetCachedSize() { | 581 void Label::ResetLayoutCache() { |
582 cached_draw_params_.text.clear(); | |
582 text_size_valid_ = false; | 583 text_size_valid_ = false; |
583 cached_heights_cursor_ = 0; | 584 cached_heights_cursor_ = 0; |
584 for (int i = 0; i < kCachedSizeLimit; ++i) | 585 for (int i = 0; i < kCachedSizeLimit; ++i) |
585 cached_heights_[i] = gfx::Size(); | 586 cached_heights_[i] = gfx::Size(); |
586 } | 587 } |
587 | 588 |
588 bool Label::ShouldShowDefaultTooltip() const { | 589 bool Label::ShouldShowDefaultTooltip() const { |
589 const gfx::Size text_size = GetTextSize(); | 590 const gfx::Size text_size = GetTextSize(); |
590 const gfx::Size size = GetContentsBounds().size(); | 591 const gfx::Size size = GetContentsBounds().size(); |
591 return !obscured() && (text_size.width() > size.width() || | 592 return !obscured() && (text_size.width() > size.width() || |
592 (multi_line_ && text_size.height() > size.height())); | 593 (multi_line_ && text_size.height() > size.height())); |
593 } | 594 } |
594 | 595 |
595 } // namespace views | 596 } // namespace views |
OLD | NEW |