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