1 /*
2 * Copyright 2006-2012, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Stephan Aßmus <superstippi@gmx.de>
7 */
8
9 #include "SwatchGroup.h"
10
11 #include <stdio.h>
12
13 #include "support_ui.h"
14 #include "ui_defines.h"
15 #include "rgb_hsv.h"
16
17 #include "AlphaSlider.h"
18 #include "ColorField.h"
19 #include "ColorPickerPanel.h"
20 #include "ColorSlider.h"
21 #include "CurrentColor.h"
22 #include "Group.h"
23 #include "SwatchView.h"
24
25
26 enum {
27 MSG_SET_COLOR = 'stcl',
28 MSG_COLOR_PICKER = 'clpk',
29 MSG_ALPHA_SLIDER = 'alps',
30 };
31
32
33 #define SWATCH_VIEW_WIDTH 20
34 #define SWATCH_VIEW_HEIGHT 15
35
36
SwatchGroup(BRect frame)37 SwatchGroup::SwatchGroup(BRect frame)
38 :
39 BView(frame, "style view", B_FOLLOW_NONE, 0),
40
41 fCurrentColor(NULL),
42 fIgnoreNotifications(false),
43
44 fColorPickerPanel(NULL),
45 fColorPickerMode(H_SELECTED),
46 fColorPickerFrame(100.0, 100.0, 200.0, 200.0)
47 {
48 frame = BRect(0, 0, 100, 15);
49 fTopSwatchViews = new Group(frame, "top swatch group");
50 fBottomSwatchViews = new Group(frame, "bottom swatch group");
51
52 // create swatch views with rainbow default palette
53 float h = 0;
54 float s = 1.0;
55 float v = 1.0;
56 rgb_color color;
57 color.alpha = 255;
58 float r = 0.0f;
59 float g = 0.0f;
60 float b = 0.0f;
61 for (int32 i = 0; i < 20; i++) {
62 if (i < 10) {
63 h = ((float)i / 9.0) * 6.0;
64 } else {
65 h = ((float)(i - 9) / 10.0) * 6.0;
66 v = 0.5;
67 }
68
69 HSV_to_RGB(h, s, v, r, g, b);
70 color.red = (uint8)(255.0 * r);
71 color.green = (uint8)(255.0 * g);
72 color.blue = (uint8)(255.0 * b);
73 fSwatchViews[i] = new SwatchView("swatch", new BMessage(MSG_SET_COLOR),
74 this, color, SWATCH_VIEW_WIDTH, SWATCH_VIEW_HEIGHT);
75
76 fSwatchViews[i]->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP);
77
78 if (i < 10)
79 fTopSwatchViews->AddChild(fSwatchViews[i]);
80 else
81 fBottomSwatchViews->AddChild(fSwatchViews[i]);
82 }
83
84 // create current color swatch view
85 fCurrentColorSV = new SwatchView("current swatch",
86 new BMessage(MSG_COLOR_PICKER), this, color, 28.0, 28.0);
87
88 // When the color of this swatch changes via drag&drop, we want to
89 // adopt it as current color.
90 fCurrentColorSV->SetDroppedMessage(new BMessage(MSG_SET_COLOR));
91
92 // create color field and slider
93 fColorField = new ColorField(BPoint(0.0, 0.0), H_SELECTED,
94 1.0, B_HORIZONTAL);
95 fColorSlider = new ColorSlider(BPoint(0.0, 0.0), H_SELECTED,
96 1.0, 1.0, B_HORIZONTAL);
97 fAlphaSlider = new AlphaSlider(B_HORIZONTAL,
98 new BMessage(MSG_ALPHA_SLIDER));
99
100 // layout gui
101 fTopSwatchViews->SetSpacing(0, 0);
102 fTopSwatchViews->ResizeToPreferred();
103 fTopSwatchViews->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
104 fBottomSwatchViews->SetSpacing(0, 0);
105 fBottomSwatchViews->ResizeToPreferred();
106 fBottomSwatchViews->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
107
108 float paletteHeight = fBottomSwatchViews->Frame().Height()
109 + fTopSwatchViews->Frame().Height() + 1;
110
111 fTopSwatchViews->MoveTo(paletteHeight + 2, 4);
112 fBottomSwatchViews->MoveTo(paletteHeight + 2,
113 fTopSwatchViews->Frame().bottom + 1);
114
115 fCurrentColorSV->MoveTo(0, fTopSwatchViews->Frame().top);
116 fCurrentColorSV->ResizeTo(paletteHeight, paletteHeight);
117 fCurrentColorSV->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP);
118
119 float width = fTopSwatchViews->Frame().right
120 - fCurrentColorSV->Frame().left;
121
122 fColorField->ResizeTo(width, 40);
123 fColorField->FrameResized(width, 40);
124 fColorSlider->ResizeTo(width, 11);
125 fColorSlider->FrameResized(width, 11);
126 fAlphaSlider->ResizeTo(width, 11);
127 fAlphaSlider->FrameResized(width, 11);
128
129 fColorField->MoveTo(0, fBottomSwatchViews->Frame().bottom + 3);
130 fColorSlider->MoveTo(0, fColorField->Frame().bottom + 1);
131 fAlphaSlider->MoveTo(0, fColorSlider->Frame().bottom + 1);
132 fAlphaSlider->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
133
134 // configure self
135 ResizeTo(width, fAlphaSlider->Frame().bottom + 4);
136 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
137
138 // add views
139 AddChild(fCurrentColorSV);
140 AddChild(fTopSwatchViews);
141 AddChild(fBottomSwatchViews);
142 AddChild(fColorField);
143 AddChild(fColorSlider);
144 AddChild(fAlphaSlider);
145 }
146
147
~SwatchGroup()148 SwatchGroup::~SwatchGroup()
149 {
150 SetCurrentColor(NULL);
151 }
152
153
154 void
ObjectChanged(const Observable * object)155 SwatchGroup::ObjectChanged(const Observable* object)
156 {
157 if (object != fCurrentColor || fIgnoreNotifications)
158 return;
159
160 rgb_color color = fCurrentColor->Color();
161
162 float h, s, v;
163 RGB_to_HSV(color.red / 255.0, color.green / 255.0, color.blue / 255.0,
164 h, s, v);
165
166 _SetColor(h, s, v, color.alpha);
167 }
168
169
170 // #pragma mark -
171
172
173 void
AttachedToWindow()174 SwatchGroup::AttachedToWindow()
175 {
176 fColorField->SetTarget(this);
177 fColorSlider->SetTarget(this);
178 fAlphaSlider->SetTarget(this);
179 }
180
181
182 void
MessageReceived(BMessage * message)183 SwatchGroup::MessageReceived(BMessage* message)
184 {
185 switch (message->what) {
186 case MSG_SET_COLOR:
187 {
188 rgb_color color;
189 if (restore_color_from_message(message, color) == B_OK) {
190 // TODO: fix color picker panel to respect alpha
191 if (message->HasRect("panel frame"))
192 color.alpha = fAlphaSlider->Value();
193 //
194 if (fCurrentColor != NULL)
195 fCurrentColor->SetColor(color);
196 }
197 // if message contains these fields,
198 // then it comes from the color picker panel.
199 // it also means the panel has died.
200 BRect frame;
201 SelectedColorMode mode;
202 if (message->FindRect("panel frame", &frame) == B_OK
203 && message->FindInt32("panel mode", (int32*)&mode) == B_OK) {
204 // message came from the color picker panel
205 // we remember the settings of the panel for later
206 fColorPickerFrame = frame;
207 fColorPickerMode = mode;
208 // color picker panel has quit
209 fColorPickerPanel = NULL;
210 }
211 break;
212 }
213
214 case MSG_COLOR_FIELD:
215 {
216 // get h from color slider
217 float h = ((255 - fColorSlider->Value()) / 255.0) * 6.0;
218 float s, v;
219 // s and v are comming from the message
220 if (message->FindFloat("value", &s) == B_OK
221 && message->FindFloat("value", 1, &v) == B_OK) {
222 _SetColor(h, s, v, fAlphaSlider->Value());
223 }
224 break;
225 }
226
227 case MSG_COLOR_SLIDER:
228 {
229 float h;
230 float s, v;
231 fColorSlider->GetOtherValues(&s, &v);
232 // h is comming from the message
233 if (message->FindFloat("value", &h) == B_OK)
234 _SetColor(h, s, v, fAlphaSlider->Value());
235 break;
236 }
237
238 case MSG_ALPHA_SLIDER:
239 {
240 float h = (1.0 - (float)fColorSlider->Value() / 255.0) * 6;
241 float s, v;
242 fColorSlider->GetOtherValues(&s, &v);
243 _SetColor(h, s, v, fAlphaSlider->Value());
244 break;
245 }
246
247 case MSG_COLOR_PICKER:
248 {
249 rgb_color color;
250 if (restore_color_from_message(message, color) < B_OK)
251 break;
252
253 if (fColorPickerPanel == NULL) {
254 fColorPickerPanel = new ColorPickerPanel(fColorPickerFrame,
255 color, fColorPickerMode, Window(),
256 new BMessage(MSG_SET_COLOR), this);
257 fColorPickerPanel->Show();
258 } else {
259 if (fColorPickerPanel->Lock()) {
260 fColorPickerPanel->SetColor(color);
261 fColorPickerPanel->Activate();
262 fColorPickerPanel->Unlock();
263 }
264 }
265 break;
266 }
267
268 default:
269 BView::MessageReceived(message);
270 break;
271 }
272 }
273
274
275 // #pragma mark -
276
277
278 void
SetCurrentColor(CurrentColor * color)279 SwatchGroup::SetCurrentColor(CurrentColor* color)
280 {
281 if (fCurrentColor == color)
282 return;
283
284 if (fCurrentColor != NULL)
285 fCurrentColor->RemoveObserver(this);
286
287 fCurrentColor = color;
288
289 if (fCurrentColor != NULL) {
290 fCurrentColor->AddObserver(this);
291
292 ObjectChanged(fCurrentColor);
293 }
294 }
295
296
297 // #pragma mark -
298
299
300 void
_SetColor(rgb_color color)301 SwatchGroup::_SetColor(rgb_color color)
302 {
303 fCurrentColorSV->SetColor(color);
304 }
305
306
307 void
_SetColor(float h,float s,float v,uint8 a)308 SwatchGroup::_SetColor(float h, float s, float v, uint8 a)
309 {
310 float r = 0.0f;
311 float g = 0.0f;
312 float b = 0.0f;
313 HSV_to_RGB(h, s, v, r, g, b);
314
315 rgb_color color;
316 color.red = (uint8)(r * 255.0);
317 color.green = (uint8)(g * 255.0);
318 color.blue = (uint8)(b * 255.0);
319 color.alpha = a;
320
321 if (!fColorField->IsTracking()) {
322 fColorField->SetFixedValue(h);
323 fColorField->SetMarkerToColor(color);
324 }
325 if (!fColorSlider->IsTracking()) {
326 fColorSlider->SetOtherValues(s, v);
327 fColorSlider->SetValue(255 - (int32)((h / 6.0) * 255.0 + 0.5));
328 }
329 if (!fAlphaSlider->IsTracking()) {
330 fAlphaSlider->SetColor(color);
331 fAlphaSlider->SetValue(a);
332 }
333
334 fIgnoreNotifications = true;
335
336 if (fCurrentColor)
337 fCurrentColor->SetColor(color);
338 _SetColor(color);
339
340 fIgnoreNotifications = false;
341 }
342