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/text_button.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/throb_animation.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/button.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/painter.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/skia_utils_win.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/platform_font_win.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme_win.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default space between the icon and text.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultIconTextSpacing = 5;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Preferred padding between text and edge.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPreferredPaddingHorizontal = 6;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPreferredPaddingVertical = 5;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Preferred padding between text and edge for NativeTheme border.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPreferredNativeThemePaddingHorizontal = 12;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPreferredNativeThemePaddingVertical = 5;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// By default the focus rect is drawn at the border of the view.  For a button,
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// we inset the focus rect by 3 pixels so that it doesn't draw on top of the
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// button's border. This roughly matches how the Windows native focus rect for
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// buttons looks. A subclass that draws a button with different padding may need
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// to provide a different focus painter and do something different.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFocusRectInset = 3;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long the hover fade animation should last.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kHoverAnimationDurationMs = 170;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These sizes are from http://msdn.microsoft.com/en-us/library/aa511279.aspx
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinWidthDLUs = 50;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinHeightDLUs = 14;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The default hot and pushed button image IDs; normal has none by default.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kHotImages[] = IMAGE_GRID(IDR_TEXTBUTTON_HOVER);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kPushedImages[] = IMAGE_GRID(IDR_TEXTBUTTON_PRESSED);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char TextButtonBase::kViewClassName[] = "TextButtonBase";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char TextButton::kViewClassName[] = "TextButton";
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// TextButtonBorder -----------------------------------------------------------
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TextButtonBorder::TextButtonBorder() {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextButtonBorder::~TextButtonBorder() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextButtonBorder::Paint(const View& view, gfx::Canvas* canvas) {
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Insets TextButtonBorder::GetInsets() const {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return insets_;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)gfx::Size TextButtonBorder::GetMinimumSize() const {
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return gfx::Size();
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TextButtonBorder::SetInsets(const gfx::Insets& insets) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  insets_ = insets;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// TextButtonDefaultBorder ----------------------------------------------------
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TextButtonDefaultBorder::TextButtonDefaultBorder()
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : vertical_padding_(kPreferredPaddingVertical) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set_hot_painter(Painter::CreateImageGridPainter(kHotImages));
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set_pushed_painter(Painter::CreateImageGridPainter(kPushedImages));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetInsets(gfx::Insets(vertical_padding_, kPreferredPaddingHorizontal,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        vertical_padding_, kPreferredPaddingHorizontal));
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TextButtonDefaultBorder::~TextButtonDefaultBorder() {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TextButtonDefaultBorder::Paint(const View& view, gfx::Canvas* canvas) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TextButton* button = static_cast<const TextButton*>(&view);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int state = button->state();
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool animating = button->GetAnimation()->is_animating();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Painter* painter = normal_painter_.get();
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Use the hot painter when we're hovered. Also use the hot painter when we're
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // STATE_NORMAL and |animating| so that we show throb animations started from
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // CustomButton::StartThrobbing which should start throbbing the button
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // regardless of whether it is hovered.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (button->show_multiple_icon_states() &&
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ((state == TextButton::STATE_HOVERED) ||
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       (state == TextButton::STATE_PRESSED) ||
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       ((state == TextButton::STATE_NORMAL) && animating))) {
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    painter = (state == TextButton::STATE_PRESSED) ?
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pushed_painter_.get() : hot_painter_.get();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (painter) {
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (animating) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(pkasting): Really this should crossfade between states so it could
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // handle the case of having a non-NULL |normal_painter_|.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      canvas->SaveLayerAlpha(static_cast<uint8>(
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          button->GetAnimation()->CurrentValueBetween(0, 255)));
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      painter->Paint(canvas, view.size());
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      canvas->Restore();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      painter->Paint(canvas, view.size());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)gfx::Size TextButtonDefaultBorder::GetMinimumSize() const {
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Size size;
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (normal_painter_)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    size.SetToMax(normal_painter_->GetMinimumSize());
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (hot_painter_)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    size.SetToMax(hot_painter_->GetMinimumSize());
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pushed_painter_)
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    size.SetToMax(pushed_painter_->GetMinimumSize());
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return size;
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// TextButtonNativeThemeBorder ------------------------------------------------
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextButtonNativeThemeBorder::TextButtonNativeThemeBorder(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NativeThemeDelegate* delegate)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(delegate) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetInsets(gfx::Insets(kPreferredNativeThemePaddingVertical,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        kPreferredNativeThemePaddingHorizontal,
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        kPreferredNativeThemePaddingVertical,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        kPreferredNativeThemePaddingHorizontal));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextButtonNativeThemeBorder::~TextButtonNativeThemeBorder() {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonNativeThemeBorder::Paint(const View& view, gfx::Canvas* canvas) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ui::NativeTheme* theme = view.GetNativeTheme();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TextButtonBase* tb = static_cast<const TextButton*>(&view);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::NativeTheme::Part part = delegate_->GetThemePart();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect rect(delegate_->GetThemePaintRect());
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tb->show_multiple_icon_states() &&
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->GetThemeAnimation() != NULL &&
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->GetThemeAnimation()->is_animating()) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Paint background state.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::ExtraParams prev_extra;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::State prev_state =
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->GetBackgroundThemeState(&prev_extra);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    theme->Paint(canvas->sk_canvas(), part, prev_state, rect, prev_extra);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Composite foreground state above it.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::ExtraParams extra;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::State state = delegate_->GetForegroundThemeState(&extra);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int alpha = delegate_->GetThemeAnimation()->CurrentValueBetween(0, 255);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canvas->SaveLayerAlpha(static_cast<uint8>(alpha));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    theme->Paint(canvas->sk_canvas(), part, state, rect, extra);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canvas->Restore();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::ExtraParams extra;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::State state = delegate_->GetThemeState(&extra);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    theme->Paint(canvas->sk_canvas(), part, state, rect, extra);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// TextButtonBase -------------------------------------------------------------
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TextButtonBase::TextButtonBase(ButtonListener* listener,
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const base::string16& text)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : CustomButton(listener),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alignment_(ALIGN_LEFT),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      min_width_(0),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      min_height_(0),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_width_(0),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      show_multiple_icon_states_(true),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_default_(false),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_line_(false),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_enabled_color_from_theme_(true),
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_disabled_color_from_theme_(true),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_highlight_color_from_theme_(true),
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      use_hover_color_from_theme_(true),
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      focus_painter_(Painter::CreateDashedFocusPainter()) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetText(text);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAnimationDuration(kHoverAnimationDurationMs);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextButtonBase::~TextButtonBase() {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::SetIsDefault(bool is_default) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_default == is_default_)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_default_ = is_default;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_default_)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TextButtonBase::SetText(const base::string16& text) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (text == text_)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  text_ = text;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAccessibleName(text);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateTextSize();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TextButtonBase::SetFontList(const gfx::FontList& font_list) {
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  font_list_ = font_list;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateTextSize();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::SetEnabledColor(SkColor color) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color_enabled_ = color;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  use_enabled_color_from_theme_ = false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColor();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::SetDisabledColor(SkColor color) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color_disabled_ = color;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  use_disabled_color_from_theme_ = false;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColor();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::SetHighlightColor(SkColor color) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color_highlight_ = color;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  use_highlight_color_from_theme_ = false;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::SetHoverColor(SkColor color) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color_hover_ = color;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  use_hover_color_from_theme_ = false;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::ClearMaxTextSize() {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  max_text_size_ = text_size_;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::SetShowMultipleIconStates(bool show_multiple_icon_states) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_multiple_icon_states_ = show_multiple_icon_states;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::SetMultiLine(bool multi_line) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (multi_line != multi_line_) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    multi_line_ = multi_line;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_text_size_.SetSize(0, 0);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTextSize();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SchedulePaint();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size TextButtonBase::GetPreferredSize() const {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Insets insets = GetInsets();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the max size to set the button boundaries.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In multiline mode max size can be undefined while
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // width() is 0, so max it out with current text size.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size prefsize(std::max(max_text_size_.width(),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              text_size_.width()) + insets.width(),
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     std::max(max_text_size_.height(),
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              text_size_.height()) + insets.height());
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (max_width_ > 0)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prefsize.set_width(std::min(max_width_, prefsize.width()));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefsize.set_width(std::max(prefsize.width(), min_width_));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefsize.set_height(std::max(prefsize.height(), min_height_));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prefsize;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int TextButtonBase::GetHeightForWidth(int w) const {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!multi_line_)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return View::GetHeightForWidth(w);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (max_width_ > 0)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    w = std::min(max_width_, w);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size text_size;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateTextSize(&text_size, w);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height = text_size.height() + GetInsets().height();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::max(height, min_height_);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::OnPaint(gfx::Canvas* canvas) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PaintButton(canvas, PB_NORMAL);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::OnBoundsChanged(const gfx::Rect& previous_bounds) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (multi_line_)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTextSize();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const gfx::Animation* TextButtonBase::GetAnimation() const {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hover_animation_.get();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::UpdateColor() {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color_ = enabled() ? color_enabled_ : color_disabled_;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::UpdateTextSize() {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int text_width = width();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If width is defined, use GetTextBounds.width() for maximum text width,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as it will take size of checkbox/radiobutton into account.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (text_width != 0) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect text_bounds = GetTextBounds();
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    text_width = text_bounds.width();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateTextSize(&text_size_, text_width);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Before layout width() is 0, and multiline text will be treated as one line.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not store max_text_size in this case. UpdateTextSize will be called
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // again once width() changes.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!multi_line_ || text_width != 0) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_text_size_.SetSize(std::max(max_text_size_.width(), text_size_.width()),
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           std::max(max_text_size_.height(),
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    text_size_.height()));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PreferredSizeChanged();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void TextButtonBase::CalculateTextSize(gfx::Size* text_size,
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       int max_width) const {
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int h = font_list_.GetHeight();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int w = multi_line_ ? max_width : 0;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = ComputeCanvasStringFlags();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!multi_line_)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= gfx::Canvas::NO_ELLIPSIS;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, 0, flags);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  text_size->SetSize(w, h);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void TextButtonBase::OnPaintText(gfx::Canvas* canvas, PaintButtonMode mode) {
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gfx::Rect text_bounds(GetTextBounds());
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (text_bounds.width() > 0) {
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Because the text button can (at times) draw multiple elements on the
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // canvas, we can not mirror the button by simply flipping the canvas as
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // doing this will mirror the text itself. Flipping the canvas will also
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // make the icons look wrong because icons are almost always represented as
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // direction-insensitive images and such images should never be flipped
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // horizontally.
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Due to the above, we must perform the flipping manually for RTL UIs.
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    text_bounds.set_x(GetMirroredXForRect(text_bounds));
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SkColor text_color = (show_multiple_icon_states_ &&
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (state() == STATE_HOVERED || state() == STATE_PRESSED)) ?
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            color_hover_ : color_;
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int draw_string_flags = gfx::Canvas::DefaultCanvasTextAlignment() |
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ComputeCanvasStringFlags();
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (mode == PB_FOR_DRAG) {
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Disable sub-pixel rendering as background is transparent.
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      draw_string_flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      canvas->DrawStringRectWithHalo(text_, font_list_,
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     SK_ColorBLACK, SK_ColorWHITE,
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     text_bounds, draw_string_flags);
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      canvas->DrawStringRectWithFlags(text_, font_list_, text_color,
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      text_bounds, draw_string_flags);
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TextButtonBase::ComputeCanvasStringFlags() const {
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!multi_line_)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int flags = gfx::Canvas::MULTI_LINE;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (alignment_) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ALIGN_LEFT:
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ALIGN_RIGHT:
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ALIGN_CENTER:
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return flags;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TextButtonBase::OnFocus() {
415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  View::OnFocus();
416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (focus_painter_)
417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SchedulePaint();
418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TextButtonBase::OnBlur() {
421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  View::OnBlur();
422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (focus_painter_)
423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SchedulePaint();
424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::GetExtraParams(
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::ExtraParams* params) const {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.checked = false;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.indeterminate = false;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.is_default = false;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.is_focused = false;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.has_border = false;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.classic_state = 0;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.background_color =
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetNativeTheme()->GetSystemColor(
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          ui::NativeTheme::kColorId_ButtonBackgroundColor);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect TextButtonBase::GetContentBounds(int extra_width) const {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Insets insets = GetInsets();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int available_width = width() - insets.width();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int content_width = text_size_.width() + extra_width;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int content_x = 0;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch(alignment_) {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ALIGN_LEFT:
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_x = insets.left();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ALIGN_RIGHT:
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_x = width() - insets.right() - content_width;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (content_x < insets.left())
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content_x = insets.left();
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ALIGN_CENTER:
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_x = insets.left() + std::max(0,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (available_width - content_width) / 2);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_width = std::min(content_width,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           width() - insets.right() - content_x);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int available_height = height() - insets.height();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int content_y = (available_height - text_size_.height()) / 2 + insets.top();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds(content_x, content_y, content_width, text_size_.height());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bounds;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect TextButtonBase::GetTextBounds() const {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetContentBounds(0);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TextButtonBase::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  focus_painter_ = focus_painter.Pass();
473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode == PB_NORMAL) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPaintBackground(canvas);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPaintBorder(canvas);
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  OnPaintText(canvas, mode);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size TextButtonBase::GetMinimumSize() const {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return max_text_size_;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::OnEnabledChanged() {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should always call UpdateColor() since the state of the button might be
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // changed by other functions like CustomButton::SetState().
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColor();
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CustomButton::OnEnabledChanged();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* TextButtonBase::GetClassName() const {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButtonBase::OnNativeThemeChanged(const ui::NativeTheme* theme) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_enabled_color_from_theme_) {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color_enabled_ = theme->GetSystemColor(
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ui::NativeTheme::kColorId_ButtonEnabledColor);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_disabled_color_from_theme_) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color_disabled_ = theme->GetSystemColor(
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ui::NativeTheme::kColorId_ButtonDisabledColor);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_highlight_color_from_theme_) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color_highlight_ = theme->GetSystemColor(
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ui::NativeTheme::kColorId_ButtonHighlightColor);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_hover_color_from_theme_) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color_hover_ = theme->GetSystemColor(
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ui::NativeTheme::kColorId_ButtonHoverColor);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColor();
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect TextButtonBase::GetThemePaintRect() const {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetLocalBounds();
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::State TextButtonBase::GetThemeState(
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::NativeTheme::ExtraParams* params) const {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetExtraParams(params);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch(state()) {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case STATE_DISABLED:
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ui::NativeTheme::kDisabled;
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case STATE_NORMAL:
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ui::NativeTheme::kNormal;
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case STATE_HOVERED:
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ui::NativeTheme::kHovered;
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case STATE_PRESSED:
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ui::NativeTheme::kPressed;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unknown state: " << state();
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ui::NativeTheme::kNormal;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const gfx::Animation* TextButtonBase::GetThemeAnimation() const {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetNativeTheme() == ui::NativeThemeWin::instance()) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ui::NativeThemeWin::instance()->IsThemingActive() ?
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hover_animation_.get() : NULL;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hover_animation_.get();
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::State TextButtonBase::GetBackgroundThemeState(
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::NativeTheme::ExtraParams* params) const {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetExtraParams(params);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::NativeTheme::kNormal;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::State TextButtonBase::GetForegroundThemeState(
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::NativeTheme::ExtraParams* params) const {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetExtraParams(params);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::NativeTheme::kHovered;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// TextButton -----------------------------------------------------------------
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TextButton::TextButton(ButtonListener* listener, const base::string16& text)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : TextButtonBase(listener, text),
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_placement_(ICON_ON_LEFT),
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_hover_icon_(false),
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_pushed_icon_(false),
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_text_spacing_(kDefaultIconTextSpacing),
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ignore_minimum_size_(true),
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      full_justification_(false) {
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBorder(scoped_ptr<Border>(new TextButtonDefaultBorder));
576a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets(
577a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      gfx::Insets(kFocusRectInset, kFocusRectInset,
578a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  kFocusRectInset, kFocusRectInset)));
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextButton::~TextButton() {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButton::SetIcon(const gfx::ImageSkia& icon) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon_ = icon;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButton::SetHoverIcon(const gfx::ImageSkia& icon) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon_hover_ = icon;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_hover_icon_ = true;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButton::SetPushedIcon(const gfx::ImageSkia& icon) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon_pushed_ = icon;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_pushed_icon_ = true;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size TextButton::GetPreferredSize() const {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size prefsize(TextButtonBase::GetPreferredSize());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefsize.Enlarge(icon_.width(), 0);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefsize.set_height(std::max(prefsize.height(), icon_.height()));
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the max size to set the button boundaries.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon_.width() > 0 && !text_.empty())
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prefsize.Enlarge(icon_text_spacing_, 0);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (max_width_ > 0)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prefsize.set_width(std::min(max_width_, prefsize.width()));
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clamp the size returned to at least the minimum size.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ignore_minimum_size_) {
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::PlatformFontWin* platform_font = static_cast<gfx::PlatformFontWin*>(
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        font_list_.GetPrimaryFont().platform_font());
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prefsize.set_width(std::max(
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prefsize.width(),
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        platform_font->horizontal_dlus_to_pixels(kMinWidthDLUs)));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prefsize.set_height(std::max(
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prefsize.height(),
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        platform_font->vertical_dlus_to_pixels(kMinHeightDLUs)));
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefsize.set_width(std::max(prefsize.width(), min_width_));
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefsize.set_height(std::max(prefsize.height(), min_height_));
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prefsize;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButton::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (full_justification_ && icon_placement_ == ICON_ON_LEFT)
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      set_alignment(ALIGN_RIGHT);
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextButtonBase::PaintButton(canvas, mode);
638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  OnPaintIcon(canvas, mode);
639cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void TextButton::OnPaintIcon(gfx::Canvas* canvas, PaintButtonMode mode) {
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkia& icon = GetImageToPaint();
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon.width() > 0) {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect text_bounds = GetTextBounds();
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int icon_x = 0;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int spacing = text_.empty() ? 0 : icon_text_spacing_;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Insets insets = GetInsets();
6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (icon_placement_) {
6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ICON_ON_LEFT:
6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        icon_x = full_justification_ ? insets.left()
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     : text_bounds.x() - icon.width() - spacing;
6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ICON_ON_RIGHT:
6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        icon_x = full_justification_ ? width() - insets.right() - icon.width()
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     : text_bounds.right() + spacing;
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ICON_CENTERED:
6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(text_.empty());
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        icon_x = (width() - insets.width() - icon.width()) / 2 + insets.left();
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      default:
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        NOTREACHED();
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int available_height = height() - insets.height();
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int icon_y = (available_height - icon.height()) / 2 + insets.top();
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Mirroring the icon position if necessary.
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect icon_bounds(icon_x, icon_y, icon.width(), icon.height());
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_bounds.set_x(GetMirroredXForRect(icon_bounds));
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canvas->DrawImageInt(icon, icon_bounds.x(), icon_bounds.y());
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButton::set_ignore_minimum_size(bool ignore_minimum_size) {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ignore_minimum_size_ = ignore_minimum_size;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TextButton::set_full_justification(bool full_justification) {
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  full_justification_ = full_justification;
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* TextButton::GetClassName() const {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::Part TextButton::GetThemePart() const {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::NativeTheme::kPushButton;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextButton::GetExtraParams(ui::NativeTheme::ExtraParams* params) const {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextButtonBase::GetExtraParams(params);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.is_default = is_default_;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect TextButton::GetTextBounds() const {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_width = 0;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkia& icon = GetImageToPaint();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon.width() > 0)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extra_width = icon.width() + (text_.empty() ? 0 : icon_text_spacing_);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds(GetContentBounds(extra_width));
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_width > 0) {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the icon is always fully visible.
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (icon_placement_ == ICON_ON_LEFT) {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds.Inset(extra_width, 0, 0, 0);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (icon_placement_ == ICON_ON_RIGHT) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds.Inset(0, 0, extra_width, 0);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bounds;
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::ImageSkia& TextButton::GetImageToPaint() const {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (show_multiple_icon_states_) {
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (has_hover_icon_ && (state() == STATE_HOVERED))
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return icon_hover_;
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (has_pushed_icon_ && (state() == STATE_PRESSED))
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return icon_pushed_;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return icon_;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
730