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