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