Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: ui/views/color_chooser/color_chooser_view.cc

Issue 10442020: Initial implementation of ColorChooser for Aura. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/color_chooser/color_chooser_view.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/string_number_conversions.h"
11 #include "base/stringprintf.h"
12 #include "base/utf_string_conversions.h"
13 #include "ui/gfx/canvas.h"
14 #include "ui/base/keycodes/keyboard_codes.h"
15 #include "ui/views/color_chooser/color_chooser_listener.h"
16 #include "ui/views/controls/textfield/textfield.h"
17 #include "ui/views/controls/textfield/textfield_controller.h"
18 #include "ui/views/events/event.h"
19 #include "ui/views/layout/box_layout.h"
20 #include "ui/views/widget/widget.h"
21
22 namespace {
23
24 const int kHueBarWidth = 20;
25 const int kSaturationValueSize = 200;
26 const int kMarginWidth = 5;
27 const int kSaturationValueIndicatorRadius = 3;
Peter Kasting 2012/06/21 18:46:16 The saturation/value square still has an even-pixe
Jun Mukai 2012/06/22 09:39:35 Changed to crosshair.
28 const int kHueIndicatorSize = 3;
29
30 string16 GetColorText(SkColor color) {
31 return ASCIIToUTF16(base::StringPrintf("#%02x%02x%02x",
32 SkColorGetR(color),
33 SkColorGetG(color),
34 SkColorGetB(color)));
35 }
36
37 bool GetColorFromText(const string16& text, SkColor* result) {
38 if (text.size() != 6 && !(text.size() == 7 && text[0] == '#'))
39 return false;
40
41 std::string input = UTF16ToUTF8((text.size() == 6) ? text : text.substr(1));
42 std::vector<uint8> hex;
43 if (!base::HexStringToBytes(input, &hex))
44 return false;
45
46 *result = SkColorSetRGB(hex[0], hex[1], hex[2]);
47 return true;
48 }
49
50 } // namespace
51
52 namespace views {
53
54 // The class to choose the hue of the color. It draws a vertical bar and
55 // the indicator for the currently selected hue.
56 class ColorChooserView::HueView : public View {
57 public:
58 explicit HueView(ColorChooserView* chooser_view);
59
60 void OnHueChanged(SkScalar hue);
61
62 private:
63 // View overrides:
64 virtual gfx::Size GetPreferredSize() OVERRIDE;
65 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
66 virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE;
67 virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE;
68
69 ColorChooserView* chooser_view_;
70 int level_;
71
72 DISALLOW_COPY_AND_ASSIGN(HueView);
73 };
74
75 ColorChooserView::HueView::HueView(ColorChooserView* chooser_view)
76 : chooser_view_(chooser_view),
77 level_(0) {
78 set_focusable(false);
79 }
80
81 void ColorChooserView::HueView::OnHueChanged(SkScalar hue) {
82 SkScalar height = SkIntToScalar(GetPreferredSize().height());
83 int level = SkScalarDiv(SkScalarMul(hue, height), SkIntToScalar(360));
84 if (level_ != level) {
85 level_ = level;
86 SchedulePaint();
87 }
88 }
89
90 gfx::Size ColorChooserView::HueView::GetPreferredSize() {
91 // We put indicators on the both sides of the hue bar.
92 return gfx::Size(kHueBarWidth + kHueIndicatorSize * 2, kSaturationValueSize);
93 }
94
95 void ColorChooserView::HueView::OnPaint(gfx::Canvas* canvas) {
96 SkScalar hsv[3];
97 // In the hue bar, saturation and value for the color should be always 100%.
98 hsv[1] = SK_Scalar1;
99 hsv[2] = SK_Scalar1;
100
101 for (int y = 0; y < height(); ++y) {
102 hsv[0] = SkScalarDiv(SkScalarMul(SkIntToScalar(360), SkIntToScalar(y)),
103 SkIntToScalar(height()));
104 canvas->DrawLine(gfx::Point(kHueIndicatorSize, y),
105 gfx::Point(width() - kHueIndicatorSize, y),
106 SkHSVToColor(hsv));
107 }
108
109 // Put the triangular indicators besides.
110 SkPath left_indicator_path;
111 SkPath right_indicator_path;
112 left_indicator_path.moveTo(
113 SK_ScalarHalf, SkIntToScalar(level_ - kHueIndicatorSize));
114 left_indicator_path.lineTo(
115 kHueIndicatorSize, SkIntToScalar(level_));
116 left_indicator_path.lineTo(
117 SK_ScalarHalf, SkIntToScalar(level_ + kHueIndicatorSize));
118 left_indicator_path.lineTo(
119 SK_ScalarHalf, SkIntToScalar(level_ - kHueIndicatorSize));
120 right_indicator_path.moveTo(
121 SkIntToScalar(width()) - SK_ScalarHalf,
122 SkIntToScalar(level_ - kHueIndicatorSize));
123 right_indicator_path.lineTo(
124 SkIntToScalar(width() - kHueIndicatorSize) - SK_ScalarHalf,
125 SkIntToScalar(level_));
126 right_indicator_path.lineTo(
127 SkIntToScalar(width()) - SK_ScalarHalf,
128 SkIntToScalar(level_ + kHueIndicatorSize));
129 right_indicator_path.lineTo(
130 SkIntToScalar(width()) - SK_ScalarHalf,
131 SkIntToScalar(level_ - kHueIndicatorSize));
132
133 SkPaint indicator_paint;
134 indicator_paint.setColor(SK_ColorBLACK);
135 indicator_paint.setStyle(SkPaint::kStroke_Style);
136 canvas->DrawPath(left_indicator_path, indicator_paint);
137 canvas->DrawPath(right_indicator_path, indicator_paint);
138 }
139
140 bool ColorChooserView::HueView::OnMousePressed(const MouseEvent& event) {
141 level_ = std::max(0, std::min(height(), event.y()));
142 chooser_view_->OnHueChosen(SkScalarDiv(SkScalarMul(SkIntToScalar(360),
143 SkIntToScalar(level_)),
144 SkIntToScalar(height())));
145 return true;
146 }
147
148 bool ColorChooserView::HueView::OnMouseDragged(const MouseEvent& event) {
149 return OnMousePressed(event);
150 }
151
152 // The class to choose the saturation and the value of the color. It draws
153 // a square area and the indicator for the currently selected saturation and
154 // value.
155 class ColorChooserView::SaturationValueView : public View {
156 public:
157 explicit SaturationValueView(ColorChooserView* chooser_view);
158
159 void OnHueChanged(SkScalar hue);
160 void OnSaturationValueChanged(SkScalar saturation, SkScalar value);
161
162 private:
163 // View overrides:
164 virtual gfx::Size GetPreferredSize() OVERRIDE;
165 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
166 virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE;
167 virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE;
168
169 ColorChooserView* chooser_view_;
170 SkScalar hue_;
171 gfx::Point marker_position_;
172
173 DISALLOW_COPY_AND_ASSIGN(SaturationValueView);
174 };
175
176 ColorChooserView::SaturationValueView::SaturationValueView(
177 ColorChooserView* chooser_view)
178 : chooser_view_(chooser_view), hue_(0) {
179 set_focusable(false);
180 }
181
182 void ColorChooserView::SaturationValueView::OnHueChanged(SkScalar hue) {
183 if (hue_ != hue) {
184 hue_ = hue;
185 SchedulePaint();
186 }
187 }
188
189 void ColorChooserView::SaturationValueView::OnSaturationValueChanged(
190 SkScalar saturation,
191 SkScalar value) {
192 SkScalar scalar_size = SkIntToScalar(kSaturationValueSize);
193 int x = SkScalarToInt(SkScalarMul(saturation, scalar_size));
194 int y = SkScalarToInt(SkScalarMul((SK_Scalar1 - value), scalar_size));
195 if (gfx::Point(x, y) == marker_position_)
196 return;
197
198 marker_position_.set_x(x);
199 marker_position_.set_y(y);
200 SchedulePaint();
201 chooser_view_->OnSaturationValueChosen(saturation, value);
202 }
203
204 gfx::Size ColorChooserView::SaturationValueView::GetPreferredSize() {
205 return gfx::Size(kSaturationValueSize, kSaturationValueSize);
206 }
207
208 void ColorChooserView::SaturationValueView::OnPaint(gfx::Canvas* canvas) {
209 SkScalar hsv[3];
210 hsv[0] = hue_;
211 SkScalar scalar_size = SkIntToScalar(kSaturationValueSize);
212 for (int x = 0; x < width(); ++x) {
213 hsv[1] = SkScalarDiv(SkIntToScalar(x), scalar_size);
214 for (int y = 0; y < height(); ++y) {
215 hsv[2] = SkScalarDiv(SK_Scalar1 - SkIntToScalar(y), scalar_size);
216 SkPaint paint;
217 paint.setColor(SkHSVToColor(255, hsv));
218 canvas->DrawPoint(gfx::Point(x, y), paint);
219 }
220 }
221
222 SkPaint circle_paint;
223 // The background is very dark at the bottom of the view. Use a white
224 // marker in that case.
225 circle_paint.setColor(
226 (marker_position_.y() > width() * 3 / 4) ? SK_ColorWHITE : SK_ColorBLACK);
227 circle_paint.setStyle(SkPaint::kStroke_Style);
228 canvas->DrawCircle(marker_position_,
229 kSaturationValueIndicatorRadius, circle_paint);
230 }
231
232 bool ColorChooserView::SaturationValueView::OnMousePressed(
233 const MouseEvent& event) {
234 SkScalar scalar_size = SkIntToScalar(kSaturationValueSize);
235 SkScalar saturation = SkScalarDiv(SkIntToScalar(event.x()), scalar_size);
236 SkScalar value = SkScalarDiv(
Peter Kasting 2012/06/21 18:46:16 Nit: Extra space
Jun Mukai 2012/06/22 09:39:35 Done.
237 SK_Scalar1 - SkIntToScalar(event.y()), scalar_size);
238 saturation = SkScalarPin(saturation, 0, SK_Scalar1);
239 value = SkScalarPin(value, 0, SK_Scalar1);
240 OnSaturationValueChanged(saturation, value);
241 return true;
242 }
243
244 bool ColorChooserView::SaturationValueView::OnMouseDragged(
245 const MouseEvent& event) {
246 return OnMousePressed(event);
247 }
248
249
250 ColorChooserView::ColorChooserView(ColorChooserListener* listener,
251 SkColor initial_color)
252 : listener_(listener) {
253 DCHECK(listener_);
254
255 set_focusable(false);
256 set_background(Background::CreateSolidBackground(SK_ColorLTGRAY));
257 SetLayoutManager(new BoxLayout(BoxLayout::kVertical, kMarginWidth,
258 kMarginWidth, kMarginWidth));
259
260 View* container = new View();
261 container->SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, 0, 0,
262 kMarginWidth));
263 saturation_value_ = new SaturationValueView(this);
264 container->AddChildView(saturation_value_);
265 hue_ = new HueView(this);
266 container->AddChildView(hue_);
267 AddChildView(container);
268
269 textfield_ = new Textfield();
270 textfield_->SetController(this);
271 AddChildView(textfield_);
272
273 OnColorChanged(initial_color);
274 MessageLoopForUI::current()->PostTask(FROM_HERE,
275 base::Bind(&View::RequestFocus, base::Unretained(textfield_)));
276 }
277
278 ColorChooserView::~ColorChooserView() {
279 }
280
281 void ColorChooserView::OnOwningWindowClosed() {
282 listener_ = NULL;
283 Widget* widget = GetWidget();
284 if (widget && widget->IsVisible())
285 widget->Close();
286 }
287
288 void ColorChooserView::OnColorChanged(SkColor color) {
289 SkColorToHSV(color, hsv_);
290 hue_->OnHueChanged(hsv_[0]);
291 saturation_value_->OnHueChanged(hsv_[0]);
292 saturation_value_->OnSaturationValueChanged(hsv_[1], hsv_[2]);
293 textfield_->SetText(GetColorText(color));
294 }
295
296 void ColorChooserView::OnHueChosen(SkScalar hue) {
297 hsv_[0] = hue;
298 SkColor color = SkHSVToColor(255, hsv_);
299 listener_->OnColorChosen(color);
300 saturation_value_->OnHueChanged(hue);
301 textfield_->SetText(GetColorText(color));
302 }
303
304 void ColorChooserView::OnSaturationValueChosen(SkScalar saturation,
305 SkScalar value) {
306 hsv_[1] = saturation;
307 hsv_[2] = value;
308 SkColor color = SkHSVToColor(255, hsv_);
309 listener_->OnColorChosen(color);
310 textfield_->SetText(GetColorText(color));
311 }
312
313 ui::ModalType ColorChooserView::GetModalType() const {
314 return ui::MODAL_TYPE_WINDOW;
315 }
316
317 void ColorChooserView::WindowClosing() {
318 if (listener_)
319 listener_->OnColorChooserDialogClosed();
320 }
321
322 View* ColorChooserView::GetContentsView() {
323 return this;
324 }
325
326 void ColorChooserView::ContentsChanged(Textfield* sender,
327 const string16& new_contents) {
328 SkColor color = SK_ColorBLACK;
329 if (GetColorFromText(new_contents, &color)) {
330 SkColorToHSV(color, hsv_);
331 listener_->OnColorChosen(color);
332 hue_->OnHueChanged(hsv_[0]);
333 saturation_value_->OnHueChanged(hsv_[0]);
334 saturation_value_->OnSaturationValueChanged(hsv_[1], hsv_[2]);
335 }
336 }
337
338 bool ColorChooserView::HandleKeyEvent(Textfield* sender,
339 const KeyEvent& key_event) {
340 if (key_event.key_code() != ui::VKEY_RETURN &&
341 key_event.key_code() != ui::VKEY_ESCAPE)
342 return false;
343
344 GetWidget()->Close();
345 return true;
346 }
347
348 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698