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_IMAGE_BUTTON_H_
6 #define UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_
7
8 #include <memory>
9
10 #include "base/gtest_prod_util.h"
11 #include "base/macros.h"
12 #include "ui/base/layout.h"
13 #include "ui/gfx/image/image_skia.h"
14 #include "ui/views/controls/button/button.h"
15 #include "ui/views/metadata/view_factory.h"
16
17 namespace views {
18
19 class VIEWS_EXPORT ImageButton : public Button {
20 public:
21 METADATA_HEADER(ImageButton);
22
23 // An enum describing the horizontal alignment of images on Buttons.
24 enum HorizontalAlignment { ALIGN_LEFT = 0, ALIGN_CENTER, ALIGN_RIGHT };
25
26 // An enum describing the vertical alignment of images on Buttons.
27 enum VerticalAlignment { ALIGN_TOP = 0, ALIGN_MIDDLE, ALIGN_BOTTOM };
28
29 explicit ImageButton(PressedCallback callback = PressedCallback());
30 ~ImageButton() override;
31
32 // Returns the image for a given |state|.
33 virtual const gfx::ImageSkia& GetImage(ButtonState state) const;
34
35 // Set the image the button should use for the provided state.
36 void SetImage(ButtonState state, const gfx::ImageSkia* image);
37
38 // As above, but takes a const ref. TODO(estade): all callers should be
39 // updated to use this version, and then the implementations can be
40 // consolidated.
41 virtual void SetImage(ButtonState state, const gfx::ImageSkia& image);
42
43 // Set the background details. The background image uses the same alignment
44 // as the image.
45 void SetBackgroundImage(SkColor color,
46 const gfx::ImageSkia* image,
47 const gfx::ImageSkia* mask);
48
49 // How the image is laid out within the button's bounds.
50 HorizontalAlignment GetImageHorizontalAlignment() const;
51 VerticalAlignment GetImageVerticalAlignment() const;
52 void SetImageHorizontalAlignment(HorizontalAlignment h_alignment);
53 void SetImageVerticalAlignment(VerticalAlignment v_alignment);
54
55 // The minimum size of the contents (not including the border). The contents
56 // will be at least this size, but may be larger if the image itself is
57 // larger.
58 gfx::Size GetMinimumImageSize() const;
59 void SetMinimumImageSize(const gfx::Size& size);
60
61 // Whether we should draw our images resources horizontally flipped.
SetDrawImageMirrored(bool mirrored)62 void SetDrawImageMirrored(bool mirrored) { draw_image_mirrored_ = mirrored; }
63
64 // Overridden from View:
65 gfx::Size CalculatePreferredSize() const override;
66 views::PaintInfo::ScaleType GetPaintScaleType() const override;
67
68 protected:
69 // Overridden from Button:
70 void PaintButtonContents(gfx::Canvas* canvas) override;
71
72 // Returns the image to paint. This is invoked from paint and returns a value
73 // from images.
74 virtual gfx::ImageSkia GetImageToPaint();
75
76 // Updates button background for |scale_factor|.
77 void UpdateButtonBackground(ui::ScaleFactor scale_factor);
78
79 // The images used to render the different states of this button.
80 gfx::ImageSkia images_[STATE_COUNT];
81
82 gfx::ImageSkia background_image_;
83
84 private:
85 FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, Basics);
86 FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, ImagePositionWithBorder);
87 FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, LeftAlignedMirrored);
88 FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, RightAlignedMirrored);
89 FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, ImagePositionWithBackground);
90
91 FRIEND_TEST_ALL_PREFIXES(ImageButtonFactoryTest, CreateVectorImageButton);
92
93 // Returns the correct position of the image for painting.
94 const gfx::Point ComputeImagePaintPosition(const gfx::ImageSkia& image) const;
95
96 // Image alignment.
97 HorizontalAlignment h_alignment_ = ALIGN_LEFT;
98 VerticalAlignment v_alignment_ = ALIGN_TOP;
99 gfx::Size minimum_image_size_;
100
101 // Whether we draw our resources horizontally flipped. This can happen in the
102 // linux titlebar, where image resources were designed to be flipped so a
103 // small curved corner in the close button designed to fit into the frame
104 // resources.
105 bool draw_image_mirrored_ = false;
106
107 DISALLOW_COPY_AND_ASSIGN(ImageButton);
108 };
109
BEGIN_VIEW_BUILDER(VIEWS_EXPORT,ImageButton,Button)110 BEGIN_VIEW_BUILDER(VIEWS_EXPORT, ImageButton, Button)
111 VIEW_BUILDER_PROPERTY(bool, DrawImageMirrored)
112 VIEW_BUILDER_PROPERTY(ImageButton::HorizontalAlignment,
113 ImageHorizontalAlignment)
114 VIEW_BUILDER_PROPERTY(ImageButton::VerticalAlignment, ImageVerticalAlignment)
115 VIEW_BUILDER_PROPERTY(gfx::Size, MinimumImageSize)
116 END_VIEW_BUILDER
117
118 ////////////////////////////////////////////////////////////////////////////////
119 //
120 // ToggleImageButton
121 //
122 // A toggle-able ImageButton. It swaps out its graphics when toggled.
123 //
124 ////////////////////////////////////////////////////////////////////////////////
125 class VIEWS_EXPORT ToggleImageButton : public ImageButton {
126 public:
127 METADATA_HEADER(ToggleImageButton);
128
129 explicit ToggleImageButton(PressedCallback callback = PressedCallback());
130 ~ToggleImageButton() override;
131
132 // Change the toggled state.
133 bool GetToggled() const;
134 void SetToggled(bool toggled);
135
136 // Like ImageButton::SetImage(), but to set the graphics used for the
137 // "has been toggled" state. Must be called for each button state
138 // before the button is toggled.
139 void SetToggledImage(ButtonState state, const gfx::ImageSkia* image);
140
141 // Get/Set the tooltip text displayed when the button is toggled.
142 base::string16 GetToggledTooltipText() const;
143 void SetToggledTooltipText(const base::string16& tooltip);
144
145 // Get/Set the accessible text used when the button is toggled.
146 base::string16 GetToggledAccessibleName() const;
147 void SetToggledAccessibleName(const base::string16& name);
148
149 // Overridden from ImageButton:
150 const gfx::ImageSkia& GetImage(ButtonState state) const override;
151 void SetImage(ButtonState state, const gfx::ImageSkia& image) override;
152
153 // Overridden from View:
154 base::string16 GetTooltipText(const gfx::Point& p) const override;
155 void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
156
157 private:
158 // The parent class's images_ member is used for the current images,
159 // and this array is used to hold the alternative images.
160 // We swap between the two when toggling.
161 gfx::ImageSkia alternate_images_[STATE_COUNT];
162
163 // True if the button is currently toggled.
164 bool toggled_ = false;
165
166 // The parent class's tooltip_text_ is displayed when not toggled, and
167 // this one is shown when toggled.
168 base::string16 toggled_tooltip_text_;
169
170 // The parent class's accessibility data is used when not toggled, and this
171 // one is used when toggled.
172 base::string16 toggled_accessible_name_;
173
174 DISALLOW_COPY_AND_ASSIGN(ToggleImageButton);
175 };
176
177 BEGIN_VIEW_BUILDER(VIEWS_EXPORT, ToggleImageButton, ImageButton)
178 VIEW_BUILDER_PROPERTY(bool, Toggled)
179 VIEW_BUILDER_PROPERTY(base::string16, ToggledTooltipText)
180 VIEW_BUILDER_PROPERTY(base::string16, ToggledAccessibleName)
181 END_VIEW_BUILDER
182
183 } // namespace views
184
185 DEFINE_VIEW_BUILDER(VIEWS_EXPORT, ImageButton)
186 DEFINE_VIEW_BUILDER(VIEWS_EXPORT, ToggleImageButton)
187
188 #endif // UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_
189