xref: /haiku/src/apps/icon-o-matic/gui/SwatchGroup.cpp (revision bab64f65bb775dc23060e276f1f1c4498ab7af6c)
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