Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / views / controls / button / image_button.cc
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 #include "ui/views/controls/button/image_button.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "ui/base/accessibility/accessible_view_state.h"
9 #include "ui/gfx/animation/throb_animation.h"
10 #include "ui/gfx/canvas.h"
11 #include "ui/gfx/image/image_skia_operations.h"
12 #include "ui/gfx/scoped_canvas.h"
13 #include "ui/views/painter.h"
14 #include "ui/views/widget/widget.h"
15
16 namespace views {
17
18 static const int kDefaultWidth = 16;   // Default button width if no theme.
19 static const int kDefaultHeight = 14;  // Default button height if no theme.
20
21 const char ImageButton::kViewClassName[] = "ImageButton";
22
23 ////////////////////////////////////////////////////////////////////////////////
24 // ImageButton, public:
25
26 ImageButton::ImageButton(ButtonListener* listener)
27     : CustomButton(listener),
28       h_alignment_(ALIGN_LEFT),
29       v_alignment_(ALIGN_TOP),
30       preferred_size_(kDefaultWidth, kDefaultHeight),
31       draw_image_mirrored_(false),
32       focus_painter_(Painter::CreateDashedFocusPainter()) {
33   // By default, we request that the gfx::Canvas passed to our View::OnPaint()
34   // implementation is flipped horizontally so that the button's images are
35   // mirrored when the UI directionality is right-to-left.
36   EnableCanvasFlippingForRTLUI(true);
37 }
38
39 ImageButton::~ImageButton() {
40 }
41
42 const gfx::ImageSkia& ImageButton::GetImage(ButtonState state) const {
43   return images_[state];
44 }
45
46 void ImageButton::SetImage(ButtonState state, const gfx::ImageSkia* image) {
47   images_[state] = image ? *image : gfx::ImageSkia();
48   PreferredSizeChanged();
49 }
50
51 void ImageButton::SetBackground(SkColor color,
52                                 const gfx::ImageSkia* image,
53                                 const gfx::ImageSkia* mask) {
54   if (image == NULL || mask == NULL) {
55     background_image_ = gfx::ImageSkia();
56     return;
57   }
58
59   background_image_ = gfx::ImageSkiaOperations::CreateButtonBackground(color,
60      *image, *mask);
61 }
62
63 void ImageButton::SetImageAlignment(HorizontalAlignment h_align,
64                                     VerticalAlignment v_align) {
65   h_alignment_ = h_align;
66   v_alignment_ = v_align;
67   SchedulePaint();
68 }
69
70 void ImageButton::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
71   focus_painter_ = focus_painter.Pass();
72 }
73
74 ////////////////////////////////////////////////////////////////////////////////
75 // ImageButton, View overrides:
76
77 gfx::Size ImageButton::GetPreferredSize() {
78   gfx::Size size = preferred_size_;
79   if (!images_[STATE_NORMAL].isNull()) {
80     size = gfx::Size(images_[STATE_NORMAL].width(),
81                      images_[STATE_NORMAL].height());
82   }
83
84   gfx::Insets insets = GetInsets();
85   size.Enlarge(insets.width(), insets.height());
86   return size;
87 }
88
89 const char* ImageButton::GetClassName() const {
90   return kViewClassName;
91 }
92
93 void ImageButton::OnPaint(gfx::Canvas* canvas) {
94   // Call the base class first to paint any background/borders.
95   View::OnPaint(canvas);
96
97   gfx::ImageSkia img = GetImageToPaint();
98
99   if (!img.isNull()) {
100     gfx::ScopedCanvas scoped(canvas);
101     if (draw_image_mirrored_) {
102       canvas->Translate(gfx::Vector2d(width(), 0));
103       canvas->Scale(-1, 1);
104     }
105
106     gfx::Point position = ComputeImagePaintPosition(img);
107     if (!background_image_.isNull())
108       canvas->DrawImageInt(background_image_, position.x(), position.y());
109
110     canvas->DrawImageInt(img, position.x(), position.y());
111   }
112
113   Painter::PaintFocusPainter(this, canvas, focus_painter());
114 }
115
116 ////////////////////////////////////////////////////////////////////////////////
117 // ImageButton, protected:
118
119 void ImageButton::OnFocus() {
120   View::OnFocus();
121   if (focus_painter_.get())
122     SchedulePaint();
123 }
124
125 void ImageButton::OnBlur() {
126   View::OnBlur();
127   if (focus_painter_.get())
128     SchedulePaint();
129 }
130
131 gfx::ImageSkia ImageButton::GetImageToPaint() {
132   gfx::ImageSkia img;
133
134   if (!images_[STATE_HOVERED].isNull() && hover_animation_->is_animating()) {
135     img = gfx::ImageSkiaOperations::CreateBlendedImage(images_[STATE_NORMAL],
136         images_[STATE_HOVERED], hover_animation_->GetCurrentValue());
137   } else {
138     img = images_[state_];
139   }
140
141   return !img.isNull() ? img : images_[STATE_NORMAL];
142 }
143
144 ////////////////////////////////////////////////////////////////////////////////
145 // ImageButton, private:
146
147 gfx::Point ImageButton::ComputeImagePaintPosition(const gfx::ImageSkia& image) {
148   int x = 0, y = 0;
149   gfx::Rect rect = GetContentsBounds();
150
151   HorizontalAlignment h_alignment = h_alignment_;
152   if (draw_image_mirrored_) {
153     if (h_alignment == ALIGN_RIGHT)
154       h_alignment = ALIGN_LEFT;
155     else if (h_alignment == ALIGN_LEFT)
156       h_alignment = ALIGN_RIGHT;
157   }
158
159   if (h_alignment == ALIGN_CENTER)
160     x = (rect.width() - image.width()) / 2;
161   else if (h_alignment == ALIGN_RIGHT)
162     x = rect.width() - image.width();
163
164   if (v_alignment_ == ALIGN_MIDDLE)
165     y = (rect.height() - image.height()) / 2;
166   else if (v_alignment_ == ALIGN_BOTTOM)
167     y = rect.height() - image.height();
168
169   x += rect.x();
170   y += rect.y();
171
172   return gfx::Point(x, y);
173 }
174
175 ////////////////////////////////////////////////////////////////////////////////
176 // ToggleImageButton, public:
177
178 ToggleImageButton::ToggleImageButton(ButtonListener* listener)
179     : ImageButton(listener),
180       toggled_(false) {
181 }
182
183 ToggleImageButton::~ToggleImageButton() {
184 }
185
186 void ToggleImageButton::SetToggled(bool toggled) {
187   if (toggled == toggled_)
188     return;
189
190   for (int i = 0; i < STATE_COUNT; ++i) {
191     gfx::ImageSkia temp = images_[i];
192     images_[i] = alternate_images_[i];
193     alternate_images_[i] = temp;
194   }
195   toggled_ = toggled;
196   SchedulePaint();
197
198   NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, true);
199 }
200
201 void ToggleImageButton::SetToggledImage(ButtonState state,
202                                         const gfx::ImageSkia* image) {
203   if (toggled_) {
204     images_[state] = image ? *image : gfx::ImageSkia();
205     if (state_ == state)
206       SchedulePaint();
207   } else {
208     alternate_images_[state] = image ? *image : gfx::ImageSkia();
209   }
210 }
211
212 void ToggleImageButton::SetToggledTooltipText(const base::string16& tooltip) {
213   toggled_tooltip_text_ = tooltip;
214 }
215
216 ////////////////////////////////////////////////////////////////////////////////
217 // ToggleImageButton, ImageButton overrides:
218
219 const gfx::ImageSkia& ToggleImageButton::GetImage(ButtonState state) const {
220   if (toggled_)
221     return alternate_images_[state];
222   return images_[state];
223 }
224
225 void ToggleImageButton::SetImage(ButtonState state,
226                                  const gfx::ImageSkia* image) {
227   if (toggled_) {
228     alternate_images_[state] = image ? *image : gfx::ImageSkia();
229   } else {
230     images_[state] = image ? *image : gfx::ImageSkia();
231     if (state_ == state)
232       SchedulePaint();
233   }
234   PreferredSizeChanged();
235 }
236
237 ////////////////////////////////////////////////////////////////////////////////
238 // ToggleImageButton, View overrides:
239
240 bool ToggleImageButton::GetTooltipText(const gfx::Point& p,
241                                        base::string16* tooltip) const {
242   if (!toggled_ || toggled_tooltip_text_.empty())
243     return Button::GetTooltipText(p, tooltip);
244
245   *tooltip = toggled_tooltip_text_;
246   return true;
247 }
248
249 void ToggleImageButton::GetAccessibleState(ui::AccessibleViewState* state) {
250   ImageButton::GetAccessibleState(state);
251   GetTooltipText(gfx::Point(), &state->name);
252 }
253
254 }  // namespace views