OLD | NEW |
---|---|
(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 | |
OLD | NEW |