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

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

Powered by Google App Engine
This is Rietveld 408576698