15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/label_button.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/animation/throb_animation.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/sys_color_change_listener.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/label_button_border.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/focus_border.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/window/dialog_delegate.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme_win.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The spacing between the icon and text. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSpacing = 5; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The length of the hover fade animation. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kHoverAnimationDurationMs = 170; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Default text and shadow colors for STYLE_BUTTON. 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst SkColor kStyleButtonTextColor = SK_ColorBLACK; 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst SkColor kStyleButtonShadowColor = SK_ColorWHITE; 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char LabelButton::kViewClassName[] = "LabelButton"; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LabelButton::LabelButton(ButtonListener* listener, const string16& text) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : CustomButton(listener), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_(new ImageView()), 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) label_(new Label()), 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button_state_images_(), 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button_state_colors_(), 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicitly_set_colors_(), 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_default_(false), 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) style_(STYLE_TEXTBUTTON) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetAnimationDuration(kHoverAnimationDurationMs); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetText(text); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(image_); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_->set_interactive(false); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(label_); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetAutoColorReadabilityEnabled(false); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Initialize the colors, border, and layout. 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetStyle(style_); 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetAccessibleName(text); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LabelButton::~LabelButton() {} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::ImageSkia& LabelButton::GetImage(ButtonState for_state) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (for_state != STATE_NORMAL && button_state_images_[for_state].isNull()) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return button_state_images_[STATE_NORMAL]; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return button_state_images_[for_state]; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_state_images_[for_state] = image; 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UpdateImage(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const string16& LabelButton::GetText() const { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return label_->text(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::SetText(const string16& text) { 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetAccessibleName(text); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetText(text); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::SetTextColor(ButtonState for_state, SkColor color) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_state_colors_[for_state] = color; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (for_state == STATE_DISABLED) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetDisabledColor(color); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (for_state == state()) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetEnabledColor(color); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicitly_set_colors_[for_state] = true; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LabelButton::GetTextMultiLine() const { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return label_->is_multi_line(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::SetTextMultiLine(bool text_multi_line) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetMultiLine(text_multi_line); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::Font& LabelButton::GetFont() const { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return label_->font(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::SetFont(const gfx::Font& font) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetFont(font); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::HorizontalAlignment LabelButton::GetHorizontalAlignment() const { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return label_->horizontal_alignment(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetHorizontalAlignment(alignment); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InvalidateLayout(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LabelButton::SetIsDefault(bool is_default) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_default == is_default_) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_default_ = is_default; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::Accelerator accel(ui::VKEY_RETURN, ui::EF_NONE); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_default_ ? AddAccelerator(accel) : RemoveAccelerator(accel); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // STYLE_BUTTON uses bold text to indicate default buttons. 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (style_ == STYLE_BUTTON) { 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int style = label_->font().GetStyle(); 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) style = is_default ? style | gfx::Font::BOLD : style & !gfx::Font::BOLD; 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) label_->SetFont(label_->font().DeriveFont(0, style)); 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LabelButton::SetStyle(ButtonStyle style) { 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Use the new button style instead of the native button style. 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(msw): Officialy deprecate and remove STYLE_NATIVE_TEXTBUTTON. 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (DialogDelegate::UseNewStyle() && style == STYLE_NATIVE_TEXTBUTTON) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) style = STYLE_BUTTON; 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) style_ = style; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_border(new LabelButtonBorder(style)); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Inset the button focus rect from the actual border; roughly match Windows. 145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) set_focus_border(style == STYLE_BUTTON ? 146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NULL : FocusBorder::CreateDashedFocusBorder(3, 3, 3, 3)); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (style == STYLE_BUTTON || style == STYLE_NATIVE_TEXTBUTTON) { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) set_focusable(true); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (style == STYLE_BUTTON) 1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) set_min_size(gfx::Size(70, 33)); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalidate the layout to pickup the new insets from the border. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InvalidateLayout(); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResetColorsFromNativeTheme(); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Size LabelButton::GetPreferredSize() { 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Use a temporary label copy for sizing to avoid calculation side-effects. 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch gfx::Font font = GetFont(); 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Label label(GetText(), font); 162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) label.SetMultiLine(GetTextMultiLine()); 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (style() == STYLE_BUTTON) { 1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Some text appears wider when rendered normally than when rendered bold. 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Accommodate the widest, as buttons may show bold and shouldn't resize. 1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const int current_width = label.GetPreferredSize().width(); 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch label.SetFont(font.DeriveFont(0, font.GetStyle() ^ gfx::Font::BOLD)); 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (label.GetPreferredSize().width() < current_width) 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch label.SetFont(font); 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Resize multi-line labels given the current limited available width. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size image_size(image_->GetPreferredSize()); 175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const int image_width = image_size.width(); 176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (GetTextMultiLine() && (width() > image_width + kSpacing)) 177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) label.SizeToFit(width() - image_width - (image_width > 0 ? kSpacing : 0)); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Calculate the required size. 180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) gfx::Size size(label.GetPreferredSize()); 181a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (image_width > 0 && size.width() > 0) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size.Enlarge(kSpacing, 0); 183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size.SetToMax(gfx::Size(0, image_size.height())); 184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const gfx::Insets insets(GetInsets()); 185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size.Enlarge(image_size.width() + insets.width(), insets.height()); 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Increase the minimum size monotonically with the preferred size. 188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size.SetToMax(min_size_); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) min_size_ = size; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Return the largest known size clamped to the maximum size (if valid). 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (max_size_.width() > 0) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size.set_width(std::min(max_size_.width(), size.width())); 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (max_size_.height() > 0) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size.set_height(std::min(max_size_.height(), size.height())); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::Layout() { 20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::HorizontalAlignment adjusted_alignment = GetHorizontalAlignment(); 20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (base::i18n::IsRTL() && adjusted_alignment != gfx::ALIGN_CENTER) 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) adjusted_alignment = (adjusted_alignment == gfx::ALIGN_LEFT) ? 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT; 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect child_area(GetLocalBounds()); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_area.Inset(GetInsets()); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size image_size(image_->GetPreferredSize()); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_size.set_width(std::min(image_size.width(), child_area.width())); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_size.set_height(std::min(image_size.height(), child_area.height())); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The label takes any remaining width after sizing the image, unless both 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views are centered. In that case, using the tighter preferred label width 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avoids wasted space within the label that would look like awkward padding. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size label_size(child_area.size()); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_size.IsEmpty() && !label_size.IsEmpty()) { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) label_size.set_width( 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::max(child_area.width() - image_size.width() - kSpacing, 0)); 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (adjusted_alignment == gfx::ALIGN_CENTER) { 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ensure multi-line labels paired with images use their available width. 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (GetTextMultiLine()) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) label_->SizeToFit(label_size.width()); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) label_size.set_width( 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::min(label_size.width(), label_->GetPreferredSize().width())); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point image_origin(child_area.origin()); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_origin.Offset(0, (child_area.height() - image_size.height()) / 2); 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (adjusted_alignment == gfx::ALIGN_CENTER) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int total_width = image_size.width() + label_size.width() + 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((image_size.width() > 0 && label_size.width() > 0) ? kSpacing : 0); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_origin.Offset((child_area.width() - total_width) / 2, 0); 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else if (adjusted_alignment == gfx::ALIGN_RIGHT) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_origin.Offset(child_area.width() - image_size.width(), 0); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point label_origin(child_area.origin()); 23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!image_size.IsEmpty() &&adjusted_alignment != gfx::ALIGN_RIGHT) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_origin.set_x(image_origin.x() + image_size.width() + kSpacing); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_->SetBoundsRect(gfx::Rect(image_origin, image_size)); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_->SetBoundsRect(gfx::Rect(label_origin, label_size)); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char* LabelButton::GetClassName() const { 24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return kViewClassName; 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LabelButton::GetExtraParams(ui::NativeTheme::ExtraParams* params) const { 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params->button.checked = false; 25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params->button.indeterminate = false; 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params->button.is_default = is_default_; 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params->button.is_focused = HasFocus() && IsAccessibilityFocusable(); 25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params->button.has_border = style() == STYLE_NATIVE_TEXTBUTTON; 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params->button.classic_state = 0; 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch params->button.background_color = label()->background_color(); 25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LabelButton::UpdateImage() { 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) image_->SetImage(GetImage(state())); 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LabelButton::ResetColorsFromNativeTheme() { 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ui::NativeTheme* theme = GetNativeTheme(); 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkColor colors[STATE_COUNT] = { 26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) theme->GetSystemColor(ui::NativeTheme::kColorId_ButtonEnabledColor), 26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) theme->GetSystemColor(ui::NativeTheme::kColorId_ButtonHoverColor), 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) theme->GetSystemColor(ui::NativeTheme::kColorId_ButtonHoverColor), 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) theme->GetSystemColor(ui::NativeTheme::kColorId_ButtonDisabledColor), 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) }; 27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Certain styles do not change text color when hovered or pressed. 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool constant_text_color = false; 27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN) 27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) constant_text_color |= (style() == STYLE_NATIVE_TEXTBUTTON && 27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) theme == ui::NativeThemeWin::instance()); 27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label_->SetBackgroundColor(theme->GetSystemColor( 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui::NativeTheme::kColorId_ButtonBackgroundColor)); 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Use hardcoded colors for inverted color scheme support and STYLE_BUTTON. 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (gfx::IsInvertedColorScheme()) { 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch constant_text_color = true; 286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch colors[STATE_NORMAL] = SK_ColorWHITE; 287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label_->SetBackgroundColor(SK_ColorBLACK); 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label_->SetAutoColorReadabilityEnabled(true); 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label_->ClearEmbellishing(); 290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (style() == STYLE_BUTTON) { 291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch constant_text_color = true; 292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch colors[STATE_NORMAL] = kStyleButtonTextColor; 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label_->SetAutoColorReadabilityEnabled(false); 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label_->SetShadowColors(kStyleButtonShadowColor, kStyleButtonShadowColor); 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label_->SetShadowOffset(0, 1); 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (constant_text_color) 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) colors[STATE_HOVERED] = colors[STATE_PRESSED] = colors[STATE_NORMAL]; 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t state = STATE_NORMAL; state < STATE_COUNT; ++state) { 30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!explicitly_set_colors_[state]) { 30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetTextColor(static_cast<ButtonState>(state), colors[state]); 30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) explicitly_set_colors_[state] = false; 30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LabelButton::StateChanged() { 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const gfx::Size previous_image_size(image_->GetPreferredSize()); 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UpdateImage(); 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const SkColor color = button_state_colors_[state()]; 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (state() != STATE_DISABLED && label_->enabled_color() != color) 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) label_->SetEnabledColor(color); 31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) label_->SetEnabled(state() != STATE_DISABLED); 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (image_->GetPreferredSize() != previous_image_size) 31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Layout(); 31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::ChildPreferredSizeChanged(View* child) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreferredSizeChanged(); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LabelButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResetColorsFromNativeTheme(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::Part LabelButton::GetThemePart() const { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::NativeTheme::kPushButton; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect LabelButton::GetThemePaintRect() const { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetLocalBounds(); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::State LabelButton::GetThemeState( 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::NativeTheme::ExtraParams* params) const { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetExtraParams(params); 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (state()) { 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_NORMAL: return ui::NativeTheme::kNormal; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_HOVERED: return ui::NativeTheme::kHovered; 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_PRESSED: return ui::NativeTheme::kPressed; 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_DISABLED: return ui::NativeTheme::kDisabled; 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_COUNT: NOTREACHED() << "Unknown state: " << state(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::NativeTheme::kNormal; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ui::Animation* LabelButton::GetThemeAnimation() const { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (style() == STYLE_NATIVE_TEXTBUTTON && 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetNativeTheme() == ui::NativeThemeWin::instance()) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::NativeThemeWin::instance()->IsThemingActive() ? 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hover_animation_.get() : NULL; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hover_animation_.get(); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::State LabelButton::GetBackgroundThemeState( 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::NativeTheme::ExtraParams* params) const { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetExtraParams(params); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::NativeTheme::kNormal; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::State LabelButton::GetForegroundThemeState( 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::NativeTheme::ExtraParams* params) const { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetExtraParams(params); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::NativeTheme::kHovered; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 373