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

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: rebase 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 const int kHueBarWidth = 20;
Peter Kasting 2012/06/18 21:24:03 Nit Blank line above
Jun Mukai 2012/06/19 08:40:00 Done.
24 const int kSaturationValueSize = 200;
25 const int kMarginWidth = 5;
26 const int kSaturationValueIndicatorSize = 3;
27 const int kHueIndicatorSize = 2;
28
29 string16 GetColorText(SkColor color) {
30 return UTF8ToUTF16(base::StringPrintf("#%02x%02x%02x",
Peter Kasting 2012/06/18 21:24:03 Nit: ASCIIToUTF16()
Jun Mukai 2012/06/19 08:40:01 Done.
31 SkColorGetR(color),
32 SkColorGetG(color),
33 SkColorGetB(color)));
34 }
35
36 bool GetColorFromText(const string16& text, SkColor* result) {
37 if (text.size() != 6 && !(text.size() == 7 && text[0] == '#'))
38 return false;
39
40 std::string input = UTF16ToUTF8((text.size() == 6) ? text : text.substr(1));
41 std::vector<uint8> hex;
42 if (!base::HexStringToBytes(input, &hex))
43 return false;
44
45 *result = SkColorSetRGB(hex[0], hex[1], hex[2]);
46 return true;
47 }
48
49 } // namespace
50
51 namespace views {
52
53 class ColorChooserView::HueView : public View {
54 public:
55 explicit HueView(ColorChooserView* chooser_view);
56
57 void OnHueChanged(float hue);
58
59 private:
60 // View overrides:
61 virtual gfx::Size GetPreferredSize() OVERRIDE;
62 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
63 virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE;
64 virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE;
65
66 ColorChooserView* chooser_view_;
67 int level_;
68
69 DISALLOW_COPY_AND_ASSIGN(HueView);
70 };
71
72 ColorChooserView::HueView::HueView(ColorChooserView* chooser_view)
73 : chooser_view_(chooser_view), level_(0) {
Peter Kasting 2012/06/18 21:24:03 Nit: One initializer per line (2 places)
Jun Mukai 2012/06/19 08:40:01 Done.
74 set_focusable(false);
75 }
76
77 void ColorChooserView::HueView::OnHueChanged(float hue) {
78 int level = hue * GetPreferredSize().height() / 360.0f;
79 if (level_ != level) {
80 level_ = level;
81 SchedulePaint();
82 }
83 }
84
85 gfx::Size ColorChooserView::HueView::GetPreferredSize() {
86 return gfx::Size(kHueBarWidth + kHueIndicatorSize * 4, kSaturationValueSize);
Peter Kasting 2012/06/18 21:24:03 Nit: This * 4 is magic, what does it mean? (I thi
Jun Mukai 2012/06/19 08:40:01 Changed as: - use -Radius rather than Size, for th
87 }
88
89 void ColorChooserView::HueView::OnPaint(gfx::Canvas* canvas) {
90 SkScalar hsv[3];
91 // bightness/value are 100%
Peter Kasting 2012/06/18 21:24:03 Nit: Comments should be complete sentences (initia
Jun Mukai 2012/06/19 08:40:01 Done.
92 hsv[1] = 1.0;
Peter Kasting 2012/06/18 21:24:03 Nit: Use SK_Scalar1 (2 places)
Jun Mukai 2012/06/19 08:40:01 Done.
93 hsv[2] = 1.0;
94
95 for (int y = 0; y < height(); ++y) {
96 SkPaint paint;
97 if (y == level_) {
98 paint.setColor(SK_ColorBLACK);
99 } else {
100 hsv[0] = 360 * static_cast<float>(y) / height();
Peter Kasting 2012/06/18 21:24:03 Nit: 360.0f * y / height()
Jun Mukai 2012/06/19 08:40:01 Done.
101 paint.setColor(SkHSVToColor(hsv));
102 }
103 canvas->DrawLine(gfx::Point(kHueIndicatorSize * 2, y),
104 gfx::Point(width() - kHueIndicatorSize * 2, y),
105 paint);
106 }
107
108 SkPaint circle_paint;
109 circle_paint.setColor(SK_ColorBLACK);
110 circle_paint.setStyle(SkPaint::kStroke_Style);
111 canvas->DrawCircle(gfx::Point(kHueIndicatorSize, level_),
112 kHueIndicatorSize,
113 circle_paint);
114 canvas->DrawCircle(gfx::Point(width() - kHueIndicatorSize, level_),
115 kHueIndicatorSize,
116 circle_paint);
117 }
118
119 bool ColorChooserView::HueView::OnMousePressed(const MouseEvent& event) {
120 level_ = std::max(0, std::min(height(), event.y()));
121 chooser_view_->OnHueChosen(360 * static_cast<float>(level_) / height());
Peter Kasting 2012/06/18 21:24:03 Nit: 360.0f * level_ / height()
Jun Mukai 2012/06/19 08:40:01 Done.
122 return true;
123 }
124
125 bool ColorChooserView::HueView::OnMouseDragged(const MouseEvent& event) {
126 return OnMousePressed(event);
127 }
128
129 class ColorChooserView::SaturationValueView : public View {
130 public:
131 explicit SaturationValueView(ColorChooserView* chooser_view);
132
133 void OnHueChanged(float hue);
134 void OnSaturationValueChanged(float saturation, float value);
135
136 private:
137 // View overrides:
138 virtual gfx::Size GetPreferredSize() OVERRIDE;
139 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
140 virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE;
141 virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE;
142
143 ColorChooserView* chooser_view_;
144 float hue_;
145 gfx::Point marker_position_;
146
147 DISALLOW_COPY_AND_ASSIGN(SaturationValueView);
148 };
149
150 ColorChooserView::SaturationValueView::SaturationValueView(
151 ColorChooserView* chooser_view)
152 : chooser_view_(chooser_view), hue_(0) {
153 set_focusable(false);
154 }
155
156 void ColorChooserView::SaturationValueView::OnHueChanged(float hue) {
157 if (hue_ == hue)
Peter Kasting 2012/06/18 21:24:03 Tiny nit: Early return or using {} are both fine,
Jun Mukai 2012/06/19 08:40:01 Using if {} here.
158 return;
159
160 hue_ = hue;
161 SchedulePaint();
162 }
163
164 void ColorChooserView::SaturationValueView::OnSaturationValueChanged(
165 float saturation,
166 float value) {
167 gfx::Size size = GetPreferredSize();
Peter Kasting 2012/06/18 21:24:03 Nit: const& ? Or just use kSaturationValueSize di
Jun Mukai 2012/06/19 08:40:01 Used kSaturationValueSize
168 int x = saturation * size.width();
169 int y = (1.0 - value) * size.height();
170 if (gfx::Point(x, y) == marker_position_)
171 return;
172
173 marker_position_.set_x(x);
174 marker_position_.set_y(y);
175 SchedulePaint();
176 chooser_view_->OnSaturationValueChosen(saturation, value);
177 }
178
179 gfx::Size ColorChooserView::SaturationValueView::GetPreferredSize() {
180 return gfx::Size(kSaturationValueSize, kSaturationValueSize);
181 }
182
183 void ColorChooserView::SaturationValueView::OnPaint(gfx::Canvas* canvas) {
184 SkScalar hsv[3];
185 hsv[0] = hue_;
186 for (int x = 0; x < width(); ++x) {
187 hsv[1] = static_cast<float>(x) / width();
188 for (int y = 0; y < height(); ++y) {
189 hsv[2] = 1.0 - static_cast<float>(y) / height();
190 SkPaint paint;
191 paint.setColor(SkHSVToColor(255, hsv));
192 canvas->DrawPoint(gfx::Point(x, y), paint);
193 }
194 }
195
196 SkPaint circle_paint;
197 // The background is very dark at the bottom of the view. Use white
Peter Kasting 2012/06/18 21:24:03 Nit: "Use a white"
Jun Mukai 2012/06/19 08:40:01 Done.
198 // marker in that case.
199 circle_paint.setColor(
200 (marker_position_.y() > width() * 3 / 4) ? SK_ColorWHITE : SK_ColorBLACK);
201 circle_paint.setStyle(SkPaint::kStroke_Style);
202 canvas->DrawCircle(
Peter Kasting 2012/06/18 21:24:03 Nit: Preferred linebreaking: canvas->DrawCircle
Jun Mukai 2012/06/19 08:40:01 Done.
203 marker_position_, kSaturationValueIndicatorSize, circle_paint);
204 }
205
206 bool ColorChooserView::SaturationValueView::OnMousePressed(
207 const MouseEvent& event) {
208 float saturation = static_cast<float>(event.x()) / width();
209 float value = 1.0 - static_cast<float>(event.y()) / height();
210 saturation = std::max(0.0f, std::min(1.0f, saturation));
211 value = std::max(0.0f, std::min(1.0f, value));
212 OnSaturationValueChanged(saturation, value);
213 return true;
214 }
215
216 bool ColorChooserView::SaturationValueView::OnMouseDragged(
217 const MouseEvent& event) {
218 return OnMousePressed(event);
219 }
220
221
222 ColorChooserView::ColorChooserView(ColorChooserListener* listener,
223 SkColor initial_color)
224 : listener_(listener) {
225 DCHECK(listener_);
226
227 set_focusable(false);
228 set_background(Background::CreateSolidBackground(SK_ColorLTGRAY));
229 SetLayoutManager(new BoxLayout(
230 BoxLayout::kVertical, kMarginWidth, kMarginWidth, kMarginWidth));
231
232 View* container = new View();
233 container->SetLayoutManager(
234 new BoxLayout(BoxLayout::kHorizontal, 0, 0, kMarginWidth));
Peter Kasting 2012/06/18 21:24:03 Nit: See preferred linebreaking above
Jun Mukai 2012/06/19 08:40:01 Done.
235 saturation_value_ = new SaturationValueView(this);
236 container->AddChildView(saturation_value_);
237 hue_ = new HueView(this);
238 container->AddChildView(hue_);
239 AddChildView(container);
240
241 textfield_ = new Textfield();
242 textfield_->SetController(this);
243 AddChildView(textfield_);
244
245 OnColorChanged(initial_color);
246 MessageLoopForUI::current()->PostTask(
247 FROM_HERE,
Peter Kasting 2012/06/18 21:24:03 Nit: Can go on prior line
Jun Mukai 2012/06/19 08:40:01 Done.
248 base::Bind(&View::RequestFocus, base::Unretained(textfield_)));
249 }
250
251 ColorChooserView::~ColorChooserView() {
252 }
253
254 void ColorChooserView::OnOwningWindowClosed() {
255 listener_ = NULL;
Ben Goodger (Google) 2012/06/18 17:00:46 is it valid for this window to still exist with th
Jun Mukai 2012/06/19 08:40:01 When the owning window is closed, the color choose
256 }
257
258 void ColorChooserView::OnColorChanged(SkColor color) {
259 SkColorToHSV(color, hsv_);
260 hue_->OnHueChanged(hsv_[0]);
261 saturation_value_->OnHueChanged(hsv_[0]);
262 saturation_value_->OnSaturationValueChanged(hsv_[1], hsv_[2]);
263 textfield_->SetText(GetColorText(color));
264 }
265
266 void ColorChooserView::OnHueChosen(float hue) {
267 hsv_[0] = hue;
268 SkColor color = SkHSVToColor(255, hsv_);
269 listener_->OnColorChosen(color);
270 saturation_value_->OnHueChanged(hue);
271 textfield_->SetText(GetColorText(color));
272 }
273
274 void ColorChooserView::OnSaturationValueChosen(float saturation, float value) {
275 hsv_[1] = saturation;
276 hsv_[2] = value;
277 SkColor color = SkHSVToColor(255, hsv_);
278 listener_->OnColorChosen(color);
279 textfield_->SetText(GetColorText(color));
280 }
281
282 ui::ModalType ColorChooserView::GetModalType() const {
283 return ui::MODAL_TYPE_WINDOW;
284 }
285
286 void ColorChooserView::WindowClosing() {
287 if (listener_)
288 listener_->OnColorChooserDialogClosed();
289 }
290
291 View* ColorChooserView::GetContentsView() {
292 return this;
293 }
294
295 void ColorChooserView::ContentsChanged(Textfield* sender,
296 const string16& new_contents) {
297 SkColor color;
298 if (GetColorFromText(new_contents, &color)) {
299 SkColorToHSV(color, hsv_);
300 listener_->OnColorChosen(color);
301 hue_->OnHueChanged(hsv_[0]);
302 saturation_value_->OnHueChanged(hsv_[0]);
303 saturation_value_->OnSaturationValueChanged(hsv_[1], hsv_[2]);
304 }
305 }
306
307 bool ColorChooserView::HandleKeyEvent(Textfield* sender,
308 const KeyEvent& key_event) {
309 if (key_event.key_code() == ui::VKEY_RETURN ||
310 key_event.key_code() == ui::VKEY_ESCAPE) {
Peter Kasting 2012/06/18 21:24:03 Nit: Can avoid {} if you reverse conditional and e
Jun Mukai 2012/06/19 08:40:01 Done.
311 GetWidget()->Close();
312 return true;
313 }
314
315 return false;
316 }
317
318 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698