Home | History | Annotate | Download | only in button
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef UI_VIEWS_CONTROLS_BUTTON_TEXT_BUTTON_H_
      6 #define UI_VIEWS_CONTROLS_BUTTON_TEXT_BUTTON_H_
      7 
      8 #include <string>
      9 
     10 #include "base/compiler_specific.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/strings/string16.h"
     13 #include "third_party/skia/include/core/SkColor.h"
     14 #include "ui/gfx/font.h"
     15 #include "ui/gfx/image/image_skia.h"
     16 #include "ui/views/border.h"
     17 #include "ui/views/controls/button/custom_button.h"
     18 #include "ui/views/native_theme_delegate.h"
     19 #include "ui/views/painter.h"
     20 
     21 namespace views {
     22 
     23 ////////////////////////////////////////////////////////////////////////////////
     24 //
     25 // TextButtonBorder
     26 //
     27 //  An abstract Border subclass for TextButtons that allows configurable insets
     28 //  for the button.
     29 //
     30 ////////////////////////////////////////////////////////////////////////////////
     31 class VIEWS_EXPORT TextButtonBorder : public Border {
     32  public:
     33   TextButtonBorder();
     34   virtual ~TextButtonBorder();
     35 
     36   void SetInsets(const gfx::Insets& insets);
     37 
     38   // Border:
     39   virtual gfx::Insets GetInsets() const OVERRIDE;
     40 
     41 private:
     42   // Border:
     43   virtual TextButtonBorder* AsTextButtonBorder() OVERRIDE;
     44   virtual const TextButtonBorder* AsTextButtonBorder() const OVERRIDE;
     45 
     46   gfx::Insets insets_;
     47 
     48   DISALLOW_COPY_AND_ASSIGN(TextButtonBorder);
     49 };
     50 
     51 ////////////////////////////////////////////////////////////////////////////////
     52 //
     53 // TextButtonDefaultBorder
     54 //
     55 //  A Border subclass that paints a TextButton's background layer -
     56 //  basically the button frame in the hot/pushed states.
     57 //
     58 // Note that this type of button is not focusable by default and will not be
     59 // part of the focus chain.  Call set_focusable(true) to make it part of the
     60 // focus chain.
     61 //
     62 ////////////////////////////////////////////////////////////////////////////////
     63 class VIEWS_EXPORT TextButtonDefaultBorder : public TextButtonBorder {
     64  public:
     65   TextButtonDefaultBorder();
     66   virtual ~TextButtonDefaultBorder();
     67 
     68  protected:
     69   // TextButtonDefaultBorder takes and retains ownership of these |painter|s.
     70   void set_normal_painter(Painter* painter) { normal_painter_.reset(painter); }
     71   void set_hot_painter(Painter* painter) { hot_painter_.reset(painter); }
     72   void set_pushed_painter(Painter* painter) { pushed_painter_.reset(painter); }
     73 
     74  private:
     75   // Implementation of Border:
     76   virtual void Paint(const View& view, gfx::Canvas* canvas) OVERRIDE;
     77 
     78   scoped_ptr<Painter> normal_painter_;
     79   scoped_ptr<Painter> hot_painter_;
     80   scoped_ptr<Painter> pushed_painter_;
     81 
     82   int vertical_padding_;
     83 
     84   DISALLOW_COPY_AND_ASSIGN(TextButtonDefaultBorder);
     85 };
     86 
     87 
     88 ////////////////////////////////////////////////////////////////////////////////
     89 //
     90 // TextButtonNativeThemeBorder
     91 //
     92 //  A Border subclass that paints a TextButton's background layer using the
     93 //  platform's native theme look.  This handles normal/disabled/hot/pressed
     94 //  states, with possible animation between states.
     95 //
     96 ////////////////////////////////////////////////////////////////////////////////
     97 class VIEWS_EXPORT TextButtonNativeThemeBorder : public TextButtonBorder {
     98  public:
     99   explicit TextButtonNativeThemeBorder(NativeThemeDelegate* delegate);
    100   virtual ~TextButtonNativeThemeBorder();
    101 
    102   // Implementation of Border:
    103   virtual void Paint(const View& view, gfx::Canvas* canvas) OVERRIDE;
    104 
    105  private:
    106   // The delegate the controls the appearance of this border.
    107   NativeThemeDelegate* delegate_;
    108 
    109   DISALLOW_COPY_AND_ASSIGN(TextButtonNativeThemeBorder);
    110 };
    111 
    112 
    113 ////////////////////////////////////////////////////////////////////////////////
    114 //
    115 // TextButtonBase
    116 //
    117 //  A base class for different types of buttons, like push buttons, radio
    118 //  buttons, and checkboxes, that do not depend on native components for
    119 //  look and feel. TextButton reserves space for the largest string
    120 //  passed to SetText. To reset the cached max size invoke ClearMaxTextSize.
    121 //
    122 ////////////////////////////////////////////////////////////////////////////////
    123 class VIEWS_EXPORT TextButtonBase : public CustomButton,
    124                                     public NativeThemeDelegate {
    125  public:
    126   // The menu button's class name.
    127   static const char kViewClassName[];
    128 
    129   virtual ~TextButtonBase();
    130 
    131   // Call SetText once per string in your set of possible values at button
    132   // creation time, so that it can contain the largest of them and avoid
    133   // resizing the button when the text changes.
    134   virtual void SetText(const string16& text);
    135   const string16& text() const { return text_; }
    136 
    137   enum TextAlignment {
    138     ALIGN_LEFT,
    139     ALIGN_CENTER,
    140     ALIGN_RIGHT
    141   };
    142 
    143   void set_alignment(TextAlignment alignment) { alignment_ = alignment; }
    144 
    145   const ui::Animation* GetAnimation() const;
    146 
    147   void SetIsDefault(bool is_default);
    148   bool is_default() const { return is_default_; }
    149 
    150   // Set whether the button text can wrap on multiple lines.
    151   // Default is false.
    152   void SetMultiLine(bool multi_line);
    153 
    154   // Return whether the button text can wrap on multiple lines.
    155   bool multi_line() const { return multi_line_; }
    156 
    157   // TextButton remembers the maximum display size of the text passed to
    158   // SetText. This method resets the cached maximum display size to the
    159   // current size.
    160   void ClearMaxTextSize();
    161 
    162   void set_min_width(int min_width) { min_width_ = min_width; }
    163   void set_min_height(int min_height) { min_height_ = min_height; }
    164   void set_max_width(int max_width) { max_width_ = max_width; }
    165   void SetFont(const gfx::Font& font);
    166   // Return the font used by this button.
    167   gfx::Font font() const { return font_; }
    168 
    169   void SetEnabledColor(SkColor color);
    170   void SetDisabledColor(SkColor color);
    171   void SetHighlightColor(SkColor color);
    172   void SetHoverColor(SkColor color);
    173 
    174   // Enables a drop shadow underneath the text.
    175   void SetTextShadowColors(SkColor active_color, SkColor inactive_color);
    176 
    177   // Sets the drop shadow's offset from the text.
    178   void SetTextShadowOffset(int x, int y);
    179 
    180   // Disables shadows.
    181   void ClearEmbellishing();
    182 
    183   // Sets whether or not to show the hot and pushed states for the button icon
    184   // (if present) in addition to the normal state.  Defaults to true.
    185   bool show_multiple_icon_states() const { return show_multiple_icon_states_; }
    186   void SetShowMultipleIconStates(bool show_multiple_icon_states);
    187 
    188   // Paint the button into the specified canvas. If |mode| is |PB_FOR_DRAG|, the
    189   // function paints a drag image representation into the canvas.
    190   enum PaintButtonMode { PB_NORMAL, PB_FOR_DRAG };
    191   virtual void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode);
    192 
    193   // Overridden from View:
    194   virtual gfx::Size GetPreferredSize() OVERRIDE;
    195   virtual gfx::Size GetMinimumSize() OVERRIDE;
    196   virtual int GetHeightForWidth(int w) OVERRIDE;
    197   virtual void OnEnabledChanged() OVERRIDE;
    198   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
    199   virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
    200   virtual const char* GetClassName() const OVERRIDE;
    201   virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
    202 
    203  protected:
    204   TextButtonBase(ButtonListener* listener, const string16& text);
    205 
    206   // Called when enabled or disabled state changes, or the colors for those
    207   // states change.
    208   virtual void UpdateColor();
    209 
    210   // Updates text_size_ and max_text_size_ from the current text/font. This is
    211   // invoked when the font or text changes.
    212   void UpdateTextSize();
    213 
    214   // Calculate the size of the text size without setting any of the members.
    215   void CalculateTextSize(gfx::Size* text_size, int max_width);
    216 
    217   void set_color_enabled(SkColor color) { color_enabled_ = color; }
    218   void set_color_disabled(SkColor color) { color_disabled_ = color; }
    219   void set_color_hover(SkColor color) { color_hover_ = color; }
    220 
    221   bool use_enabled_color_from_theme() const {
    222     return use_enabled_color_from_theme_;
    223   }
    224 
    225   bool use_disabled_color_from_theme() const {
    226     return use_disabled_color_from_theme_;
    227   }
    228 
    229   bool use_hover_color_from_theme() const {
    230     return use_hover_color_from_theme_;
    231   }
    232 
    233   // Overridden from NativeThemeDelegate:
    234   virtual gfx::Rect GetThemePaintRect() const OVERRIDE;
    235   virtual ui::NativeTheme::State GetThemeState(
    236       ui::NativeTheme::ExtraParams* params) const OVERRIDE;
    237   virtual const ui::Animation* GetThemeAnimation() const OVERRIDE;
    238   virtual ui::NativeTheme::State GetBackgroundThemeState(
    239       ui::NativeTheme::ExtraParams* params) const OVERRIDE;
    240   virtual ui::NativeTheme::State GetForegroundThemeState(
    241       ui::NativeTheme::ExtraParams* params) const OVERRIDE;
    242 
    243   virtual void GetExtraParams(ui::NativeTheme::ExtraParams* params) const;
    244 
    245   virtual gfx::Rect GetTextBounds() const;
    246 
    247   int ComputeCanvasStringFlags() const;
    248 
    249   // Calculate the bounds of the content of this button, including any extra
    250   // width needed on top of the text width.
    251   gfx::Rect GetContentBounds(int extra_width) const;
    252 
    253   // The text string that is displayed in the button.
    254   string16 text_;
    255 
    256   // The size of the text string.
    257   gfx::Size text_size_;
    258 
    259   // Track the size of the largest text string seen so far, so that
    260   // changing text_ will not resize the button boundary.
    261   gfx::Size max_text_size_;
    262 
    263   // The alignment of the text string within the button.
    264   TextAlignment alignment_;
    265 
    266   // The font used to paint the text.
    267   gfx::Font font_;
    268 
    269   // Flag indicating if a shadow should be drawn behind the text.
    270   bool has_text_shadow_;
    271   // Optional shadow text colors for active and inactive widget states.
    272   SkColor active_text_shadow_color_;
    273   SkColor inactive_text_shadow_color_;
    274   // Space between the text and its shadow. Defaults to (1,1).
    275   gfx::Point text_shadow_offset_;
    276 
    277   // The dimensions of the button will be at least these values.
    278   int min_width_;
    279   int min_height_;
    280 
    281   // The width of the button will never be larger than this value. A value <= 0
    282   // indicates the width is not constrained.
    283   int max_width_;
    284 
    285   // Whether or not to show the hot and pushed icon states.
    286   bool show_multiple_icon_states_;
    287 
    288   // Whether or not the button appears and behaves as the default button in its
    289   // current context.
    290   bool is_default_;
    291 
    292   // Whether the text button should handle its text string as multi-line.
    293   bool multi_line_;
    294 
    295  private:
    296   // Text color.
    297   SkColor color_;
    298 
    299   // State colors.
    300   SkColor color_enabled_;
    301   SkColor color_disabled_;
    302   SkColor color_highlight_;
    303   SkColor color_hover_;
    304 
    305   // True if the specified color should be used from the theme.
    306   bool use_enabled_color_from_theme_;
    307   bool use_disabled_color_from_theme_;
    308   bool use_highlight_color_from_theme_;
    309   bool use_hover_color_from_theme_;
    310 
    311   DISALLOW_COPY_AND_ASSIGN(TextButtonBase);
    312 };
    313 
    314 ////////////////////////////////////////////////////////////////////////////////
    315 //
    316 // TextButton
    317 //
    318 //  A button which displays text and/or and icon that can be changed in
    319 //  response to actions. TextButton reserves space for the largest string
    320 //  passed to SetText. To reset the cached max size invoke ClearMaxTextSize.
    321 //
    322 ////////////////////////////////////////////////////////////////////////////////
    323 class VIEWS_EXPORT TextButton : public TextButtonBase {
    324  public:
    325   // The button's class name.
    326   static const char kViewClassName[];
    327 
    328   TextButton(ButtonListener* listener, const string16& text);
    329   virtual ~TextButton();
    330 
    331   void set_icon_text_spacing(int icon_text_spacing) {
    332     icon_text_spacing_ = icon_text_spacing;
    333   }
    334 
    335   // Sets the icon.
    336   virtual void SetIcon(const gfx::ImageSkia& icon);
    337   virtual void SetHoverIcon(const gfx::ImageSkia& icon);
    338   virtual void SetPushedIcon(const gfx::ImageSkia& icon);
    339 
    340   bool HasIcon() const { return !icon_.isNull(); }
    341 
    342   // Meanings are reversed for right-to-left layouts.
    343   enum IconPlacement {
    344     ICON_ON_LEFT,
    345     ICON_ON_RIGHT,
    346     ICON_CENTERED  // Centered is valid only when text is empty.
    347   };
    348 
    349   IconPlacement icon_placement() { return icon_placement_; }
    350   void set_icon_placement(IconPlacement icon_placement) {
    351     // ICON_CENTERED works only when |text_| is empty.
    352     DCHECK((icon_placement != ICON_CENTERED) || text_.empty());
    353     icon_placement_ = icon_placement;
    354   }
    355 
    356   void set_ignore_minimum_size(bool ignore_minimum_size);
    357 
    358   // Overridden from View:
    359   virtual gfx::Size GetPreferredSize() OVERRIDE;
    360   virtual const char* GetClassName() const OVERRIDE;
    361 
    362   // Overridden from TextButtonBase:
    363   virtual void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) OVERRIDE;
    364 
    365  protected:
    366   gfx::ImageSkia icon() const { return icon_; }
    367 
    368   virtual const gfx::ImageSkia& GetImageToPaint() const;
    369 
    370   // Overridden from NativeThemeDelegate:
    371   virtual ui::NativeTheme::Part GetThemePart() const OVERRIDE;
    372 
    373   // Overridden from TextButtonBase:
    374   virtual void GetExtraParams(
    375       ui::NativeTheme::ExtraParams* params) const OVERRIDE;
    376   virtual gfx::Rect GetTextBounds() const OVERRIDE;
    377 
    378  private:
    379   // The position of the icon.
    380   IconPlacement icon_placement_;
    381 
    382   // An icon displayed with the text.
    383   gfx::ImageSkia icon_;
    384 
    385   // An optional different version of the icon for hover state.
    386   gfx::ImageSkia icon_hover_;
    387   bool has_hover_icon_;
    388 
    389   // An optional different version of the icon for pushed state.
    390   gfx::ImageSkia icon_pushed_;
    391   bool has_pushed_icon_;
    392 
    393   // Space between icon and text.
    394   int icon_text_spacing_;
    395 
    396   // True if the button should ignore the minimum size for the platform. Default
    397   // is true. Set to false to prevent narrower buttons.
    398   bool ignore_minimum_size_;
    399 
    400   DISALLOW_COPY_AND_ASSIGN(TextButton);
    401 };
    402 
    403 }  // namespace views
    404 
    405 #endif  // UI_VIEWS_CONTROLS_BUTTON_TEXT_BUTTON_H_
    406