summaryrefslogtreecommitdiffstats
path: root/ui/views/controls/button/image_button.h
blob: 46ab52ed99cfcafc5a473dbc3e08b520dcd8c030 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_
#define UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_

#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "ui/base/layout.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/button/custom_button.h"

namespace views {

class Painter;

// An image button.

// Note that this type of button is not focusable by default and will not be
// part of the focus chain.  Call SetFocusable(true) to make it part of the
// focus chain.

class VIEWS_EXPORT ImageButton : public CustomButton {
 public:
  static const char kViewClassName[];

  enum HorizontalAlignment {
    ALIGN_LEFT = 0,
    ALIGN_CENTER,
    ALIGN_RIGHT
  };

  enum VerticalAlignment {
    ALIGN_TOP = 0,
    ALIGN_MIDDLE,
    ALIGN_BOTTOM
  };

  explicit ImageButton(ButtonListener* listener);
  virtual ~ImageButton();

  // Returns the image for a given |state|.
  virtual const gfx::ImageSkia& GetImage(ButtonState state) const;

  // Set the image the button should use for the provided state.
  virtual void SetImage(ButtonState state, const gfx::ImageSkia* image);

  // Set the background details.
  void SetBackground(SkColor color,
                     const gfx::ImageSkia* image,
                     const gfx::ImageSkia* mask);

  // Set an |image| to draw on top of the normal / hot / pushed image.
  // Pass NULL for no image.
  void SetOverlayImage(const gfx::ImageSkia* image);

  // Sets how the image is laid out within the button's bounds.
  void SetImageAlignment(HorizontalAlignment h_align,
                         VerticalAlignment v_align);

  void SetFocusPainter(scoped_ptr<Painter> focus_painter);

  // Sets preferred size, so it could be correctly positioned in layout even if
  // it is NULL.
  void SetPreferredSize(const gfx::Size& preferred_size) {
    preferred_size_ = preferred_size;
  }

  // Whether we should draw our images resources horizontally flipped.
  void SetDrawImageMirrored(bool mirrored) {
    draw_image_mirrored_ = mirrored;
  }

  // Overridden from View:
  virtual gfx::Size GetPreferredSize() OVERRIDE;
  virtual const char* GetClassName() const OVERRIDE;
  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;

 protected:
  // Overridden from View:
  virtual void OnFocus() OVERRIDE;
  virtual void OnBlur() OVERRIDE;

  // Returns the image to paint. This is invoked from paint and returns a value
  // from images.
  virtual gfx::ImageSkia GetImageToPaint();

  // Updates button background for |scale_factor|.
  void UpdateButtonBackground(ui::ScaleFactor scale_factor);

  Painter* focus_painter() { return focus_painter_.get(); }

  // The images used to render the different states of this button.
  gfx::ImageSkia images_[STATE_COUNT];

  gfx::ImageSkia background_image_;

  // Image to draw on top of normal / hot / pushed image.  Usually empty.
  gfx::ImageSkia overlay_image_;

 private:
  FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, Basics);
  FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, ImagePositionWithBorder);
  FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, LeftAlignedMirrored);
  FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, RightAlignedMirrored);

  // Returns the correct position of the image for painting.
  gfx::Point ComputeImagePaintPosition(const gfx::ImageSkia& image);

  // Image alignment.
  HorizontalAlignment h_alignment_;
  VerticalAlignment v_alignment_;
  gfx::Size preferred_size_;

  // Whether we draw our resources horizontally flipped. This can happen in the
  // linux titlebar, where image resources were designed to be flipped so a
  // small curved corner in the close button designed to fit into the frame
  // resources.
  bool draw_image_mirrored_;

  scoped_ptr<Painter> focus_painter_;

  DISALLOW_COPY_AND_ASSIGN(ImageButton);
};

////////////////////////////////////////////////////////////////////////////////
//
// ToggleImageButton
//
// A toggle-able ImageButton.  It swaps out its graphics when toggled.
//
////////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT ToggleImageButton : public ImageButton {
 public:
  explicit ToggleImageButton(ButtonListener* listener);
  virtual ~ToggleImageButton();

  // Change the toggled state.
  void SetToggled(bool toggled);

  // Like ImageButton::SetImage(), but to set the graphics used for the
  // "has been toggled" state.  Must be called for each button state
  // before the button is toggled.
  void SetToggledImage(ButtonState state, const gfx::ImageSkia* image);

  // Set the tooltip text displayed when the button is toggled.
  void SetToggledTooltipText(const base::string16& tooltip);

  // Overridden from ImageButton:
  virtual const gfx::ImageSkia& GetImage(ButtonState state) const OVERRIDE;
  virtual void SetImage(ButtonState state,
                        const gfx::ImageSkia* image) OVERRIDE;

  // Overridden from View:
  virtual bool GetTooltipText(const gfx::Point& p,
                              base::string16* tooltip) const OVERRIDE;
  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;

 private:
  // The parent class's images_ member is used for the current images,
  // and this array is used to hold the alternative images.
  // We swap between the two when toggling.
  gfx::ImageSkia alternate_images_[STATE_COUNT];

  // True if the button is currently toggled.
  bool toggled_;

  // The parent class's tooltip_text_ is displayed when not toggled, and
  // this one is shown when toggled.
  base::string16 toggled_tooltip_text_;

  DISALLOW_COPY_AND_ASSIGN(ToggleImageButton);
};

}  // namespace views

#endif  // UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_