Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: ui/views/controls/button/label_button.cc

Issue 371633002: LabelButton: cache the last computed preferred size (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/button/label_button.h" 5 #include "ui/views/controls/button/label_button.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "grit/ui_resources.h" 8 #include "grit/ui_resources.h"
9 #include "ui/base/resource/resource_bundle.h" 9 #include "ui/base/resource/resource_bundle.h"
10 #include "ui/gfx/animation/throb_animation.h" 10 #include "ui/gfx/animation/throb_animation.h"
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 UpdateImage(); 82 UpdateImage();
83 } 83 }
84 84
85 const base::string16& LabelButton::GetText() const { 85 const base::string16& LabelButton::GetText() const {
86 return label_->text(); 86 return label_->text();
87 } 87 }
88 88
89 void LabelButton::SetText(const base::string16& text) { 89 void LabelButton::SetText(const base::string16& text) {
90 SetAccessibleName(text); 90 SetAccessibleName(text);
91 label_->SetText(text); 91 label_->SetText(text);
92 ResetCachedSize();
msw 2014/07/23 19:20:16 Ideally, changing child Label view's text should t
noms (inactive) 2014/07/24 14:20:25 I removed it from here and from all the other plac
92 } 93 }
93 94
94 void LabelButton::SetTextColor(ButtonState for_state, SkColor color) { 95 void LabelButton::SetTextColor(ButtonState for_state, SkColor color) {
95 button_state_colors_[for_state] = color; 96 button_state_colors_[for_state] = color;
96 if (for_state == STATE_DISABLED) 97 if (for_state == STATE_DISABLED)
97 label_->SetDisabledColor(color); 98 label_->SetDisabledColor(color);
98 else if (for_state == state()) 99 else if (for_state == state())
99 label_->SetEnabledColor(color); 100 label_->SetEnabledColor(color);
100 explicitly_set_colors_[for_state] = true; 101 explicitly_set_colors_[for_state] = true;
101 } 102 }
102 103
103 void LabelButton::SetTextShadows(const gfx::ShadowValues& shadows) { 104 void LabelButton::SetTextShadows(const gfx::ShadowValues& shadows) {
104 label_->SetShadows(shadows); 105 label_->SetShadows(shadows);
105 } 106 }
106 107
107 void LabelButton::SetTextSubpixelRenderingEnabled(bool enabled) { 108 void LabelButton::SetTextSubpixelRenderingEnabled(bool enabled) {
108 label_->SetSubpixelRenderingEnabled(enabled); 109 label_->SetSubpixelRenderingEnabled(enabled);
109 } 110 }
110 111
111 bool LabelButton::GetTextMultiLine() const { 112 bool LabelButton::GetTextMultiLine() const {
112 return label_->multi_line(); 113 return label_->multi_line();
113 } 114 }
114 115
115 void LabelButton::SetTextMultiLine(bool text_multi_line) { 116 void LabelButton::SetTextMultiLine(bool text_multi_line) {
116 label_->SetMultiLine(text_multi_line); 117 label_->SetMultiLine(text_multi_line);
118 ResetCachedSize();
117 } 119 }
118 120
119 const gfx::FontList& LabelButton::GetFontList() const { 121 const gfx::FontList& LabelButton::GetFontList() const {
120 return label_->font_list(); 122 return label_->font_list();
121 } 123 }
122 124
123 void LabelButton::SetFontList(const gfx::FontList& font_list) { 125 void LabelButton::SetFontList(const gfx::FontList& font_list) {
124 cached_normal_font_list_ = font_list; 126 cached_normal_font_list_ = font_list;
125 cached_bold_font_list_ = font_list.DeriveWithStyle( 127 cached_bold_font_list_ = font_list.DeriveWithStyle(
126 font_list.GetFontStyle() | gfx::Font::BOLD); 128 font_list.GetFontStyle() | gfx::Font::BOLD);
127 129
128 // STYLE_BUTTON uses bold text to indicate default buttons. 130 // STYLE_BUTTON uses bold text to indicate default buttons.
129 label_->SetFontList( 131 label_->SetFontList(
130 style_ == STYLE_BUTTON && is_default_ ? 132 style_ == STYLE_BUTTON && is_default_ ?
131 cached_bold_font_list_ : cached_normal_font_list_); 133 cached_bold_font_list_ : cached_normal_font_list_);
134 ResetCachedSize();
132 } 135 }
133 136
134 void LabelButton::SetElideBehavior(gfx::ElideBehavior elide_behavior) { 137 void LabelButton::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
135 label_->SetElideBehavior(elide_behavior); 138 label_->SetElideBehavior(elide_behavior);
139 ResetCachedSize();
136 } 140 }
137 141
138 gfx::HorizontalAlignment LabelButton::GetHorizontalAlignment() const { 142 gfx::HorizontalAlignment LabelButton::GetHorizontalAlignment() const {
139 return label_->GetHorizontalAlignment(); 143 return label_->GetHorizontalAlignment();
140 } 144 }
141 145
142 void LabelButton::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) { 146 void LabelButton::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
143 label_->SetHorizontalAlignment(alignment); 147 label_->SetHorizontalAlignment(alignment);
148 ResetCachedSize();
144 InvalidateLayout(); 149 InvalidateLayout();
145 } 150 }
146 151
152 void LabelButton::SetMinSize(const gfx::Size& min_size) {
153 min_size_ = min_size;
154 ResetCachedSize();
155 }
156
157 void LabelButton::SetMaxSize(const gfx::Size& max_size) {
158 max_size_ = max_size;
159 ResetCachedSize();
160 }
161
147 void LabelButton::SetIsDefault(bool is_default) { 162 void LabelButton::SetIsDefault(bool is_default) {
148 if (is_default == is_default_) 163 if (is_default == is_default_)
149 return; 164 return;
150 is_default_ = is_default; 165 is_default_ = is_default;
151 ui::Accelerator accel(ui::VKEY_RETURN, ui::EF_NONE); 166 ui::Accelerator accel(ui::VKEY_RETURN, ui::EF_NONE);
152 is_default_ ? AddAccelerator(accel) : RemoveAccelerator(accel); 167 is_default_ ? AddAccelerator(accel) : RemoveAccelerator(accel);
153 168
154 // STYLE_BUTTON uses bold text to indicate default buttons. 169 // STYLE_BUTTON uses bold text to indicate default buttons.
155 if (style_ == STYLE_BUTTON) { 170 if (style_ == STYLE_BUTTON) {
156 label_->SetFontList( 171 label_->SetFontList(
157 is_default ? cached_bold_font_list_ : cached_normal_font_list_); 172 is_default ? cached_bold_font_list_ : cached_normal_font_list_);
158 } 173 }
159 } 174 }
160 175
161 void LabelButton::SetStyle(ButtonStyle style) { 176 void LabelButton::SetStyle(ButtonStyle style) {
162 style_ = style; 177 style_ = style;
163 // Inset the button focus rect from the actual border; roughly match Windows. 178 // Inset the button focus rect from the actual border; roughly match Windows.
164 if (style == STYLE_BUTTON) { 179 if (style == STYLE_BUTTON) {
165 SetFocusPainter(scoped_ptr<Painter>()); 180 SetFocusPainter(scoped_ptr<Painter>());
166 } else { 181 } else {
167 SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets( 182 SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets(
168 gfx::Insets(3, 3, 3, 3))); 183 gfx::Insets(3, 3, 3, 3)));
169 } 184 }
170 if (style == STYLE_BUTTON) { 185 if (style == STYLE_BUTTON) {
171 label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); 186 label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
172 SetFocusable(true); 187 SetFocusable(true);
173 } 188 }
174 if (style == STYLE_BUTTON) 189 if (style == STYLE_BUTTON)
175 set_min_size(gfx::Size(70, 33)); 190 SetMinSize(gfx::Size(70, 33));
176
177 OnNativeThemeChanged(GetNativeTheme()); 191 OnNativeThemeChanged(GetNativeTheme());
192 ResetCachedSize();
178 } 193 }
179 194
180 void LabelButton::SetFocusPainter(scoped_ptr<Painter> focus_painter) { 195 void LabelButton::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
181 focus_painter_ = focus_painter.Pass(); 196 focus_painter_ = focus_painter.Pass();
182 } 197 }
183 198
184 gfx::Size LabelButton::GetPreferredSize() const { 199 gfx::Size LabelButton::GetPreferredSize() const {
200 if (button_size_valid_)
201 return button_size_;
202
185 // Use a temporary label copy for sizing to avoid calculation side-effects. 203 // Use a temporary label copy for sizing to avoid calculation side-effects.
186 Label label(GetText(), cached_normal_font_list_); 204 Label label(GetText(), cached_normal_font_list_);
187 label.SetShadows(label_->shadows()); 205 label.SetShadows(label_->shadows());
188 label.SetMultiLine(GetTextMultiLine()); 206 label.SetMultiLine(GetTextMultiLine());
189 207
190 if (style() == STYLE_BUTTON) { 208 if (style() == STYLE_BUTTON) {
191 // Some text appears wider when rendered normally than when rendered bold. 209 // Some text appears wider when rendered normally than when rendered bold.
192 // Accommodate the widest, as buttons may show bold and shouldn't resize. 210 // Accommodate the widest, as buttons may show bold and shouldn't resize.
193 const int current_width = label.GetPreferredSize().width(); 211 const int current_width = label.GetPreferredSize().width();
194 label.SetFontList(cached_bold_font_list_); 212 label.SetFontList(cached_bold_font_list_);
(...skipping 15 matching lines...) Expand all
210 228
211 // Increase the minimum size monotonically with the preferred size. 229 // Increase the minimum size monotonically with the preferred size.
212 size.SetToMax(min_size_); 230 size.SetToMax(min_size_);
213 min_size_ = size; 231 min_size_ = size;
214 232
215 // Return the largest known size clamped to the maximum size (if valid). 233 // Return the largest known size clamped to the maximum size (if valid).
216 if (max_size_.width() > 0) 234 if (max_size_.width() > 0)
217 size.set_width(std::min(max_size_.width(), size.width())); 235 size.set_width(std::min(max_size_.width(), size.width()));
218 if (max_size_.height() > 0) 236 if (max_size_.height() > 0)
219 size.set_height(std::min(max_size_.height(), size.height())); 237 size.set_height(std::min(max_size_.height(), size.height()));
220 return size; 238
239 // Cache this computed size, as recomputing it is an expensive operation.
240 button_size_valid_ = true;
241 button_size_ = size;
242 return button_size_;
221 } 243 }
222 244
223 int LabelButton::GetHeightForWidth(int w) const { 245 int LabelButton::GetHeightForWidth(int w) const {
msw 2014/07/23 19:20:16 I wonder if we should similarly cache the preferre
noms (inactive) 2014/07/24 14:20:25 Oh, that's a neat idea. I could help with that :)
224 w -= GetInsets().width(); 246 w -= GetInsets().width();
225 const gfx::Size image_size(image_->GetPreferredSize()); 247 const gfx::Size image_size(image_->GetPreferredSize());
226 w -= image_size.width(); 248 w -= image_size.width();
227 if (image_size.width() > 0 && !GetText().empty()) 249 if (image_size.width() > 0 && !GetText().empty())
228 w -= kSpacing; 250 w -= kSpacing;
229 251
230 int height = std::max(image_size.height(), label_->GetHeightForWidth(w)); 252 int height = std::max(image_size.height(), label_->GetHeightForWidth(w));
231 if (border()) 253 if (border())
232 height = std::max(height, border()->GetMinimumSize().height()); 254 height = std::max(height, border()->GetMinimumSize().height());
233 255
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 return kViewClassName; 307 return kViewClassName;
286 } 308 }
287 309
288 scoped_ptr<LabelButtonBorder> LabelButton::CreateDefaultBorder() const { 310 scoped_ptr<LabelButtonBorder> LabelButton::CreateDefaultBorder() const {
289 return scoped_ptr<LabelButtonBorder>(new LabelButtonBorder(style_)); 311 return scoped_ptr<LabelButtonBorder>(new LabelButtonBorder(style_));
290 } 312 }
291 313
292 void LabelButton::SetBorder(scoped_ptr<Border> border) { 314 void LabelButton::SetBorder(scoped_ptr<Border> border) {
293 border_is_themed_border_ = false; 315 border_is_themed_border_ = false;
294 View::SetBorder(border.Pass()); 316 View::SetBorder(border.Pass());
317 ResetCachedSize();
295 } 318 }
296 319
297 gfx::Rect LabelButton::GetChildAreaBounds() { 320 gfx::Rect LabelButton::GetChildAreaBounds() {
298 return GetLocalBounds(); 321 return GetLocalBounds();
299 } 322 }
300 323
301 void LabelButton::OnPaint(gfx::Canvas* canvas) { 324 void LabelButton::OnPaint(gfx::Canvas* canvas) {
302 View::OnPaint(canvas); 325 View::OnPaint(canvas);
303 Painter::PaintFocusPainter(this, canvas, focus_painter_.get()); 326 Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
304 } 327 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 for (size_t state = STATE_NORMAL; state < STATE_COUNT; ++state) { 392 for (size_t state = STATE_NORMAL; state < STATE_COUNT; ++state) {
370 if (!explicitly_set_colors_[state]) { 393 if (!explicitly_set_colors_[state]) {
371 SetTextColor(static_cast<ButtonState>(state), colors[state]); 394 SetTextColor(static_cast<ButtonState>(state), colors[state]);
372 explicitly_set_colors_[state] = false; 395 explicitly_set_colors_[state] = false;
373 } 396 }
374 } 397 }
375 } 398 }
376 399
377 void LabelButton::UpdateImage() { 400 void LabelButton::UpdateImage() {
378 image_->SetImage(GetImage(state())); 401 image_->SetImage(GetImage(state()));
402 ResetCachedSize();
379 } 403 }
380 404
381 void LabelButton::UpdateThemedBorder() { 405 void LabelButton::UpdateThemedBorder() {
382 // Don't override borders set by others. 406 // Don't override borders set by others.
383 if (!border_is_themed_border_) 407 if (!border_is_themed_border_)
384 return; 408 return;
385 409
386 scoped_ptr<LabelButtonBorder> label_button_border = CreateDefaultBorder(); 410 scoped_ptr<LabelButtonBorder> label_button_border = CreateDefaultBorder();
387 411
388 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 412 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
(...skipping 15 matching lines...) Expand all
404 UpdateImage(); 428 UpdateImage();
405 const SkColor color = button_state_colors_[state()]; 429 const SkColor color = button_state_colors_[state()];
406 if (state() != STATE_DISABLED && label_->enabled_color() != color) 430 if (state() != STATE_DISABLED && label_->enabled_color() != color)
407 label_->SetEnabledColor(color); 431 label_->SetEnabledColor(color);
408 label_->SetEnabled(state() != STATE_DISABLED); 432 label_->SetEnabled(state() != STATE_DISABLED);
409 if (image_->GetPreferredSize() != previous_image_size) 433 if (image_->GetPreferredSize() != previous_image_size)
410 Layout(); 434 Layout();
411 } 435 }
412 436
413 void LabelButton::ChildPreferredSizeChanged(View* child) { 437 void LabelButton::ChildPreferredSizeChanged(View* child) {
438 ResetCachedSize();
414 PreferredSizeChanged(); 439 PreferredSizeChanged();
415 } 440 }
416 441
417 void LabelButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { 442 void LabelButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
418 ResetColorsFromNativeTheme(); 443 ResetColorsFromNativeTheme();
419 UpdateThemedBorder(); 444 UpdateThemedBorder();
420 // Invalidate the layout to pickup the new insets from the border. 445 // Invalidate the layout to pickup the new insets from the border.
421 InvalidateLayout(); 446 InvalidateLayout();
422 } 447 }
423 448
(...skipping 27 matching lines...) Expand all
451 GetExtraParams(params); 476 GetExtraParams(params);
452 return ui::NativeTheme::kNormal; 477 return ui::NativeTheme::kNormal;
453 } 478 }
454 479
455 ui::NativeTheme::State LabelButton::GetForegroundThemeState( 480 ui::NativeTheme::State LabelButton::GetForegroundThemeState(
456 ui::NativeTheme::ExtraParams* params) const { 481 ui::NativeTheme::ExtraParams* params) const {
457 GetExtraParams(params); 482 GetExtraParams(params);
458 return ui::NativeTheme::kHovered; 483 return ui::NativeTheme::kHovered;
459 } 484 }
460 485
486 void LabelButton::ResetCachedSize() {
msw 2014/07/23 19:20:16 I wonder if this should call PreferredSizeChanged(
noms (inactive) 2014/07/24 14:20:25 Acknowledged.
487 button_size_valid_ = false;
488 button_size_= gfx::Size();
489 }
490
461 } // namespace views 491 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698