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

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, 5 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
« no previous file with comments | « ui/views/color_chooser/color_chooser_view.h ('k') | ui/views/views.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 kSaturationValueIndicatorSize = 3;
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() - 1);
83 SkScalar hue_max = SkIntToScalar(360);
84 int level = SkScalarDiv(SkScalarMul(hue_max - hue, height), hue_max);
85 if (level_ != level) {
86 level_ = level;
87 SchedulePaint();
88 }
89 }
90
91 gfx::Size ColorChooserView::HueView::GetPreferredSize() {
92 // We put indicators on the both sides of the hue bar.
93 return gfx::Size(kHueBarWidth + kHueIndicatorSize * 2, kSaturationValueSize);
94 }
95
96 void ColorChooserView::HueView::OnPaint(gfx::Canvas* canvas) {
97 SkScalar hsv[3];
98 // In the hue bar, saturation and value for the color should be always 100%.
99 hsv[1] = SK_Scalar1;
100 hsv[2] = SK_Scalar1;
101
102 for (int y = 0; y < height(); ++y) {
103 hsv[0] = SkScalarDiv(SkScalarMul(SkIntToScalar(360),
104 SkIntToScalar(height() - 1 - y)),
105 SkIntToScalar(height() - 1));
106 canvas->DrawLine(gfx::Point(kHueIndicatorSize, y),
107 gfx::Point(width() - kHueIndicatorSize, y),
108 SkHSVToColor(hsv));
109 }
110
111 // Put the triangular indicators besides.
112 SkPath left_indicator_path;
113 SkPath right_indicator_path;
114 left_indicator_path.moveTo(
115 SK_ScalarHalf, SkIntToScalar(level_ - kHueIndicatorSize));
116 left_indicator_path.lineTo(
117 kHueIndicatorSize, SkIntToScalar(level_));
118 left_indicator_path.lineTo(
119 SK_ScalarHalf, SkIntToScalar(level_ + kHueIndicatorSize));
120 left_indicator_path.lineTo(
121 SK_ScalarHalf, SkIntToScalar(level_ - kHueIndicatorSize));
122 right_indicator_path.moveTo(
123 SkIntToScalar(width()) - SK_ScalarHalf,
124 SkIntToScalar(level_ - kHueIndicatorSize));
125 right_indicator_path.lineTo(
126 SkIntToScalar(width() - kHueIndicatorSize) - SK_ScalarHalf,
127 SkIntToScalar(level_));
128 right_indicator_path.lineTo(
129 SkIntToScalar(width()) - SK_ScalarHalf,
130 SkIntToScalar(level_ + kHueIndicatorSize));
131 right_indicator_path.lineTo(
132 SkIntToScalar(width()) - SK_ScalarHalf,
133 SkIntToScalar(level_ - kHueIndicatorSize));
134
135 SkPaint indicator_paint;
136 indicator_paint.setColor(SK_ColorBLACK);
137 indicator_paint.setStyle(SkPaint::kStroke_Style);
138 canvas->DrawPath(left_indicator_path, indicator_paint);
139 canvas->DrawPath(right_indicator_path, indicator_paint);
140 }
141
142 bool ColorChooserView::HueView::OnMousePressed(const MouseEvent& event) {
143 level_ = std::max(0, std::min(height() - 1, event.y()));
144 chooser_view_->OnHueChosen(SkScalarDiv(
145 SkScalarMul(SkIntToScalar(360), SkIntToScalar(height() - 1 - level_)),
146 SkIntToScalar(height() - 1)));
147 return true;
148 }
149
150 bool ColorChooserView::HueView::OnMouseDragged(const MouseEvent& event) {
151 return OnMousePressed(event);
152 }
153
154 // The class to choose the saturation and the value of the color. It draws
155 // a square area and the indicator for the currently selected saturation and
156 // value.
157 class ColorChooserView::SaturationValueView : public View {
158 public:
159 explicit SaturationValueView(ColorChooserView* chooser_view);
160
161 void OnHueChanged(SkScalar hue);
162 void OnSaturationValueChanged(SkScalar saturation, SkScalar value);
163
164 private:
165 // View overrides:
166 virtual gfx::Size GetPreferredSize() OVERRIDE;
167 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
168 virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE;
169 virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE;
170
171 ColorChooserView* chooser_view_;
172 SkScalar hue_;
173 gfx::Point marker_position_;
174
175 DISALLOW_COPY_AND_ASSIGN(SaturationValueView);
176 };
177
178 ColorChooserView::SaturationValueView::SaturationValueView(
179 ColorChooserView* chooser_view)
180 : chooser_view_(chooser_view), hue_(0) {
181 set_focusable(false);
182 }
183
184 void ColorChooserView::SaturationValueView::OnHueChanged(SkScalar hue) {
185 if (hue_ != hue) {
186 hue_ = hue;
187 SchedulePaint();
188 }
189 }
190
191 void ColorChooserView::SaturationValueView::OnSaturationValueChanged(
192 SkScalar saturation,
193 SkScalar value) {
194 SkScalar scalar_size = SkIntToScalar(kSaturationValueSize - 1);
195 int x = SkScalarFloorToInt(SkScalarMul(saturation, scalar_size));
196 int y = SkScalarFloorToInt(SkScalarMul(SK_Scalar1 - value, scalar_size));
197 if (gfx::Point(x, y) == marker_position_)
198 return;
199
200 marker_position_.set_x(x);
201 marker_position_.set_y(y);
202 SchedulePaint();
203 chooser_view_->OnSaturationValueChosen(saturation, value);
204 }
205
206 gfx::Size ColorChooserView::SaturationValueView::GetPreferredSize() {
207 return gfx::Size(kSaturationValueSize, kSaturationValueSize);
208 }
209
210 void ColorChooserView::SaturationValueView::OnPaint(gfx::Canvas* canvas) {
211 SkScalar hsv[3];
212 hsv[0] = hue_;
213 SkScalar scalar_size = SkIntToScalar(kSaturationValueSize - 1);
214 for (int x = 0; x < width(); ++x) {
215 hsv[1] = SkScalarDiv(SkIntToScalar(x), scalar_size);
216 for (int y = 0; y < height(); ++y) {
217 hsv[2] = SK_Scalar1 - SkScalarDiv(SkIntToScalar(y), scalar_size);
218 SkPaint paint;
219 paint.setColor(SkHSVToColor(255, hsv));
220 canvas->DrawPoint(gfx::Point(x, y), paint);
221 }
222 }
223
224 // The background is very dark at the bottom of the view. Use a white
225 // marker in that case.
226 SkColor indicator_color =
227 (marker_position_.y() > width() * 3 / 4) ? SK_ColorWHITE : SK_ColorBLACK;
228 // Draw a crosshair indicator but do not draw its center to see the selected
229 // saturation/value. Note that the DrawLine() doesn't draw the right-bottom
230 // pixel.
231 canvas->DrawLine(
232 gfx::Point(marker_position_.x(),
233 marker_position_.y() - kSaturationValueIndicatorSize),
234 gfx::Point(marker_position_.x(),
235 marker_position_.y()),
236 indicator_color);
237 canvas->DrawLine(
238 gfx::Point(marker_position_.x(),
239 marker_position_.y() + kSaturationValueIndicatorSize + 1),
240 gfx::Point(marker_position_.x(),
241 marker_position_.y() + 1),
242 indicator_color);
243 canvas->DrawLine(
244 gfx::Point(marker_position_.x() - kSaturationValueIndicatorSize,
245 marker_position_.y()),
246 gfx::Point(marker_position_.x(),
247 marker_position_.y()),
248 indicator_color);
249 canvas->DrawLine(
250 gfx::Point(marker_position_.x() + kSaturationValueIndicatorSize + 1,
251 marker_position_.y()),
252 gfx::Point(marker_position_.x() + 1,
253 marker_position_.y()),
254 indicator_color);
255 }
256
257 bool ColorChooserView::SaturationValueView::OnMousePressed(
258 const MouseEvent& event) {
259 SkScalar scalar_size = SkIntToScalar(kSaturationValueSize);
260 SkScalar saturation = SkScalarDiv(SkIntToScalar(event.x()), scalar_size);
261 SkScalar value = SK_Scalar1 - SkScalarDiv(
262 SkIntToScalar(event.y()), scalar_size);
263 saturation = SkScalarPin(saturation, 0, SK_Scalar1);
264 value = SkScalarPin(value, 0, SK_Scalar1);
265 OnSaturationValueChanged(saturation, value);
266 return true;
267 }
268
269 bool ColorChooserView::SaturationValueView::OnMouseDragged(
270 const MouseEvent& event) {
271 return OnMousePressed(event);
272 }
273
274
275 ColorChooserView::ColorChooserView(ColorChooserListener* listener,
276 SkColor initial_color)
277 : listener_(listener) {
278 DCHECK(listener_);
279
280 set_focusable(false);
281 set_background(Background::CreateSolidBackground(SK_ColorLTGRAY));
282 SetLayoutManager(new BoxLayout(BoxLayout::kVertical, kMarginWidth,
283 kMarginWidth, kMarginWidth));
284
285 View* container = new View();
286 container->SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, 0, 0,
287 kMarginWidth));
288 saturation_value_ = new SaturationValueView(this);
289 container->AddChildView(saturation_value_);
290 hue_ = new HueView(this);
291 container->AddChildView(hue_);
292 AddChildView(container);
293
294 textfield_ = new Textfield();
295 textfield_->SetController(this);
296 AddChildView(textfield_);
297
298 OnColorChanged(initial_color);
299 MessageLoopForUI::current()->PostTask(FROM_HERE,
300 base::Bind(&View::RequestFocus, base::Unretained(textfield_)));
Ben Goodger (Google) 2012/06/25 15:56:44 instead of doing this, override GetInitiallyFocuse
Jun Mukai 2012/06/25 16:57:26 Done.
301 }
302
303 ColorChooserView::~ColorChooserView() {
304 }
305
306 void ColorChooserView::OnColorChanged(SkColor color) {
307 SkColorToHSV(color, hsv_);
308 hue_->OnHueChanged(hsv_[0]);
309 saturation_value_->OnHueChanged(hsv_[0]);
310 saturation_value_->OnSaturationValueChanged(hsv_[1], hsv_[2]);
311 textfield_->SetText(GetColorText(color));
312 }
313
314 void ColorChooserView::OnHueChosen(SkScalar hue) {
315 hsv_[0] = hue;
316 SkColor color = SkHSVToColor(255, hsv_);
317 listener_->OnColorChosen(color);
318 saturation_value_->OnHueChanged(hue);
319 textfield_->SetText(GetColorText(color));
320 }
321
322 void ColorChooserView::OnSaturationValueChosen(SkScalar saturation,
323 SkScalar value) {
324 hsv_[1] = saturation;
325 hsv_[2] = value;
326 SkColor color = SkHSVToColor(255, hsv_);
327 listener_->OnColorChosen(color);
328 textfield_->SetText(GetColorText(color));
329 }
330
331 ui::ModalType ColorChooserView::GetModalType() const {
332 return ui::MODAL_TYPE_WINDOW;
333 }
334
335 void ColorChooserView::WindowClosing() {
336 if (listener_)
337 listener_->OnColorChooserDialogClosed();
338 }
339
340 View* ColorChooserView::GetContentsView() {
341 return this;
342 }
343
344 void ColorChooserView::ContentsChanged(Textfield* sender,
345 const string16& new_contents) {
346 SkColor color = SK_ColorBLACK;
347 if (GetColorFromText(new_contents, &color)) {
348 SkColorToHSV(color, hsv_);
349 listener_->OnColorChosen(color);
350 hue_->OnHueChanged(hsv_[0]);
351 saturation_value_->OnHueChanged(hsv_[0]);
352 saturation_value_->OnSaturationValueChanged(hsv_[1], hsv_[2]);
353 }
354 }
355
356 bool ColorChooserView::HandleKeyEvent(Textfield* sender,
357 const KeyEvent& key_event) {
358 if (key_event.key_code() != ui::VKEY_RETURN &&
359 key_event.key_code() != ui::VKEY_ESCAPE)
360 return false;
361
362 GetWidget()->Close();
363 return true;
364 }
365
366 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/color_chooser/color_chooser_view.h ('k') | ui/views/views.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698