xref: /haiku/src/kits/interface/ColorControl.cpp (revision 23d36867f63af34f65b35f1eb42a269bf36a0555)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		BColorControl.h
23 //	Author:			Marc Flerackers (mflerackers@androme.be)
24 //	Description:	BColorControl displays a palette of selectable colors.
25 //------------------------------------------------------------------------------
26 
27 // Standard Includes -----------------------------------------------------------
28 #include <stdio.h>
29 
30 // System Includes -------------------------------------------------------------
31 #include "ColorControl.h"
32 #include "TextControl.h"
33 #include <Support/Errors.h>
34 
35 // Project Includes ------------------------------------------------------------
36 
37 // Local Includes --------------------------------------------------------------
38 
39 // Local Defines ---------------------------------------------------------------
40 
41 // Globals ---------------------------------------------------------------------
42 
43 const uint32 U_COLOR_CONTROL_RED_CHANGED_MSG = 'CCRC';
44 const uint32 U_COLOR_CONTROL_GREEN_CHANGED_MSG = 'CCGC';
45 const uint32 U_COLOR_CONTROL_BLUE_CHANGED_MSG = 'CCBC';
46 
47 //------------------------------------------------------------------------------
48 BColorControl::BColorControl(BPoint leftTop, color_control_layout matrix,
49 							 float cellSize, const char *name,
50 							 BMessage *message, bool bufferedDrawing)
51 	:	BControl(BRect(leftTop, leftTop), name, NULL, message,
52 			B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE)
53 {
54 	switch (matrix)
55 	{
56 		case B_CELLS_4x64:
57 			fColumns = 4;
58 			fRows = 64;
59 			break;
60 		case B_CELLS_8x32:
61 			fColumns = 8;
62 			fRows = 32;
63 			break;
64 		case B_CELLS_16x16:
65 			fColumns = 16;
66 			fRows = 16;
67 			break;
68 		case B_CELLS_32x8:
69 			fColumns = 32;
70 			fRows = 8;
71 			break;
72 		case B_CELLS_64x4:
73 			fColumns = 64;
74 			fRows = 4;
75 			break;
76 	}
77 
78 	fCellSize = cellSize;
79 
80 	BRect rect(0.0f, 0.0f, 196, 52);
81 
82 	ResizeTo(rect.Width() + 70, rect.Height());
83 
84 	fRedText = new BTextControl(BRect(rect.right + 1, 0.0f,
85 		rect.right + 70, 15.0f), "_red", "Red:", NULL,
86 		new BMessage(U_COLOR_CONTROL_RED_CHANGED_MSG));
87 	AddChild(fRedText);
88 
89 	fGreenText = new BTextControl(BRect(rect.right + 1, 16.0f,
90 		rect.right + 70, 30.0f), "_green", "Green:", NULL,
91 		new BMessage(U_COLOR_CONTROL_GREEN_CHANGED_MSG));
92 	AddChild(fGreenText);
93 
94 	fBlueText = new BTextControl(BRect(rect.right + 1, 31.0f,
95 		rect.right + 70, 45), "_blue", "Blue:", NULL,
96 		new BMessage(U_COLOR_CONTROL_BLUE_CHANGED_MSG));
97 	AddChild(fBlueText);
98 
99 	fFocusedComponent = 0;
100 }
101 //------------------------------------------------------------------------------
102 BColorControl::BColorControl(BMessage *archive)
103 	:	BControl(archive)
104 {
105 	int32 layout;
106 	bool use_offscreen;
107 
108 	archive->FindInt32("_layout", &layout);
109 	SetLayout((color_control_layout)layout);
110 
111 	archive->FindFloat("_csize", &fCellSize);
112 
113 	archive->FindBool("_use_off", &use_offscreen);
114 }
115 //------------------------------------------------------------------------------
116 BColorControl::~BColorControl()
117 {
118 }
119 //------------------------------------------------------------------------------
120 BArchivable *BColorControl::Instantiate(BMessage *archive)
121 {
122 	if ( validate_instantiation(archive, "BColorControl"))
123 		return new BColorControl(archive);
124 	else
125 		return NULL;
126 }
127 //------------------------------------------------------------------------------
128 status_t BColorControl::Archive(BMessage *archive, bool deep) const
129 {
130 	BControl::Archive(archive, deep);
131 
132 	archive->AddInt32("_layout", Layout());
133 	archive->AddFloat("_csize", fCellSize);
134 	archive->AddBool("_use_off", fOffscreenView != NULL);
135 
136 	return B_OK;
137 }
138 //------------------------------------------------------------------------------
139 void BColorControl::SetValue(int32 color)
140 {
141 	BControl::SetValue(color);
142 
143 	rgb_color c = ValueAsColor();
144 	char string[4];
145 
146 	sprintf(string, "%d", c.red);
147 	fRedText->SetText( string);
148 	sprintf(string, "%d", c.green);
149 	fGreenText->SetText( string);
150 	sprintf(string, "%d", c.blue);
151 	fBlueText->SetText(string);
152 
153 	Invoke();
154 }
155 //------------------------------------------------------------------------------
156 rgb_color BColorControl::ValueAsColor()
157 {
158 	int32 value = Value();
159 	rgb_color color;
160 
161 	color.red = (value & 0xFF000000) >> 24;
162 	color.green = (value & 0x00FF0000) >> 16;
163 	color.blue = (value & 0x0000FF00) >> 8;
164 	color.alpha = 255;
165 
166 	return color;
167 }
168 //------------------------------------------------------------------------------
169 void BColorControl::SetEnabled(bool enabled)
170 {
171 	BControl::SetEnabled(enabled);
172 
173 	fRedText->SetEnabled(enabled);
174 	fGreenText->SetEnabled(enabled);
175 	fBlueText->SetEnabled(enabled);
176 }
177 //------------------------------------------------------------------------------
178 void BColorControl::AttachedToWindow()
179 {
180 	if (Parent())
181       SetViewColor(Parent()->ViewColor());
182 
183 	BControl::AttachedToWindow();
184 
185 	fRedText->SetTarget(this);
186 	fGreenText->SetTarget(this);
187 	fBlueText->SetTarget(this);
188 }
189 //------------------------------------------------------------------------------
190 void BColorControl::MessageReceived(BMessage *message)
191 {
192 	switch (message->what)
193 	{
194 		case U_COLOR_CONTROL_RED_CHANGED_MSG:
195 		{
196 			unsigned char shade;
197 			rgb_color color = ValueAsColor();
198 
199 			sscanf(fRedText->Text(), "%d", &shade);
200 
201 			color.red = max_c(0, min_c(shade, 255));
202 
203 			SetValue(color);
204 
205 			break;
206 		}
207 		case U_COLOR_CONTROL_GREEN_CHANGED_MSG:
208 		{
209 			unsigned char shade;
210 			rgb_color color = ValueAsColor();
211 
212 			sscanf(fGreenText->Text(), "%d", &shade);
213 
214 			color.green = max_c(0, min_c(shade, 255));
215 
216 			SetValue(color);
217 
218 			break;
219 		}
220 		case U_COLOR_CONTROL_BLUE_CHANGED_MSG:
221 		{
222 			unsigned char shade;
223 			rgb_color color = ValueAsColor();
224 
225 			sscanf(fBlueText->Text(), "%d", &shade);
226 
227 			color.blue = max_c(0, min_c(shade, 255));
228 
229 			SetValue(color);
230 
231 			break;
232 		}
233 		default:
234 			BControl::MessageReceived(message);
235 	}
236 }
237 //------------------------------------------------------------------------------
238 void BColorControl::Draw(BRect updateRect)
239 {
240 	BRect rect(0.0f, 0.0f, 196, 52);
241 
242 	rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR),
243 	lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT),
244 	darken1 = tint_color(no_tint, B_DARKEN_1_TINT),
245 	darken4 = tint_color(no_tint, B_DARKEN_4_TINT);
246 
247 	// First bevel
248 	SetHighColor(darken1);
249 	StrokeLine(rect.LeftBottom(), rect.LeftTop());
250 	StrokeLine(rect.LeftTop(), rect.RightTop());
251 	SetHighColor(lightenmax);
252 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom());
253 	StrokeLine(rect.RightBottom(), BPoint(rect.right, rect.top + 1.0f));
254 
255 	rect.InsetBy(1.0f, 1.0f);
256 
257 	// Second bevel
258 	SetHighColor(darken4);
259 	StrokeLine(rect.LeftBottom(), rect.LeftTop());
260 	StrokeLine(rect.LeftTop(), rect.RightTop());
261 	SetHighColor(no_tint);
262 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom());
263 	StrokeLine(rect.RightBottom(), BPoint(rect.right, rect.top + 1.0f));
264 
265 	// Ramps
266 	rgb_color white = {255, 255, 255, 255};
267 	rgb_color red = {255, 0, 0, 255};
268 	rgb_color green = {0, 255, 0, 255};
269 	rgb_color blue = {0, 0, 255, 255};
270 
271 	rect.InsetBy(1.0f, 1.0f);
272 
273 	ColorRamp(BRect(), BRect(rect.left, rect.top,
274 		rect.right, rect.top + 12.0f), this, white, 0, false);
275 
276 	ColorRamp(BRect(), BRect(rect.left, rect.top + 13.0f,
277 		rect.right, rect.top + 24.0f), this, red, 0, false);
278 
279 	ColorRamp(BRect(), BRect(rect.left, rect.top + 25.0f,
280 		rect.right, rect.top + 36.0f), this, green, 0, false);
281 
282 	ColorRamp(BRect(), BRect(rect.left, rect.top + 37.0f,
283 		rect.right, rect.top + 48.0f), this, blue, 0, false);
284 
285 	// Selectors
286 	rgb_color color = ValueAsColor();
287 	float x, y = rect.top + 16.0f;
288 
289 	SetPenSize(2.0f);
290 
291 	x = rect.left + color.red * (rect.Width() - 7) / 255;
292 	SetHighColor(255, 255, 255);
293 	StrokeEllipse(BRect(x, y, x + 4.0f, y + 4.0f));
294 
295 	y += 11;
296 
297 	x = rect.left + color.green * (rect.Width() - 7) / 255;
298 	SetHighColor(255, 255, 255);
299 	StrokeEllipse(BRect(x, y, x + 4.0f, y + 4.0f));
300 
301 	y += 11;
302 
303 	x = rect.left + color.blue * (rect.Width() - 7) / 255;
304 	SetHighColor(255, 255, 255);
305 	StrokeEllipse(BRect ( x, y, x + 4.0f, y + 4.0f));
306 
307 	SetPenSize(1.0f);
308 }
309 //------------------------------------------------------------------------------
310 void BColorControl::MouseDown(BPoint point)
311 {
312 	rgb_color color = ValueAsColor();
313 
314 	BRect rect(0.0f, 0.0f, 196, 52);
315 
316 	uint8 shade = (unsigned char)max_c(0,
317 		min_c((point.x - 2) * 255 / (rect.Width() - 4.0f), 255));
318 
319 	if (point.y - 2 < 12)
320 	{
321 		color.red = color.green = color.blue = shade;
322 		fFocusedComponent = 1;
323 	}
324 	else if (point.y - 2 < 24)
325 	{
326 		color.red = shade;
327 		fFocusedComponent = 2;
328 	}
329 	else if (point.y - 2 < 36)
330 	{
331 		color.green = shade;
332 		fFocusedComponent = 3;
333 	}
334 	else if (point.y - 2 < 48)
335 	{
336 		color.blue = shade;
337 		fFocusedComponent = 4;
338 	}
339 
340 	SetValue(color);
341 
342 	MakeFocus();
343 	SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
344 }
345 //------------------------------------------------------------------------------
346 void BColorControl::KeyDown(const char *bytes, int32 numBytes)
347 {
348 }
349 //------------------------------------------------------------------------------
350 void BColorControl::SetCellSize(float cellSide)
351 {
352 	fCellSize = cellSide;
353 }
354 //------------------------------------------------------------------------------
355 float BColorControl::CellSize() const
356 {
357 	return fCellSize;
358 }
359 //------------------------------------------------------------------------------
360 void BColorControl::SetLayout(color_control_layout layout)
361 {
362 	switch (layout)
363 	{
364 		case B_CELLS_4x64:
365 			fColumns = 4;
366 			fRows = 64;
367 			break;
368 		case B_CELLS_8x32:
369 			fColumns = 8;
370 			fRows = 32;
371 			break;
372 		case B_CELLS_16x16:
373 			fColumns = 16;
374 			fRows = 16;
375 			break;
376 		case B_CELLS_32x8:
377 			fColumns = 32;
378 			fRows = 8;
379 			break;
380 		case B_CELLS_64x4:
381 			fColumns = 64;
382 			fRows = 4;
383 			break;
384 	}
385 }
386 //------------------------------------------------------------------------------
387 color_control_layout BColorControl::Layout() const
388 {
389 	if (fColumns == 4 &&fRows == 64)
390 		return B_CELLS_4x64;
391 	if (fColumns == 8 &&fRows == 32)
392 		return B_CELLS_8x32;
393 	if (fColumns == 16 &&fRows == 16)
394 		return B_CELLS_16x16;
395 	if (fColumns == 32 &&fRows == 8)
396 		return B_CELLS_32x8;
397 	if (fColumns == 64 &&fRows == 4)
398 		return B_CELLS_64x4;
399 
400 	return B_CELLS_32x8;
401 }
402 //------------------------------------------------------------------------------
403 void BColorControl::WindowActivated(bool state)
404 {
405 	BControl::WindowActivated(state);
406 }
407 //------------------------------------------------------------------------------
408 void BColorControl::MouseUp(BPoint point)
409 {
410 	fFocusedComponent = 0;
411 }
412 //------------------------------------------------------------------------------
413 void BColorControl::MouseMoved(BPoint point, uint32 transit,
414 							   const BMessage *message)
415 {
416 	if (fFocusedComponent != 0)
417 	{
418 		rgb_color color = ValueAsColor();
419 
420 		BRect rect(0.0f, 0.0f, 196, 52);
421 
422 		uint8 shade = (unsigned char)max_c(0,
423 		min_c((point.x - 2) * 255 / (rect.Width() - 4.0f), 255));
424 
425 		switch (fFocusedComponent)
426 		{
427 			case 1:
428 				color.red = color.green = color.blue = shade;
429 				break;
430 			case 2:
431 				color.red = shade;
432 				break;
433 			case 3:
434 				color.green = shade;
435 				break;
436 			case 4:
437 				color.blue = shade;
438 				break;
439 		}
440 
441 		SetValue(color);
442 	}
443 }
444 //------------------------------------------------------------------------------
445 void BColorControl::DetachedFromWindow()
446 {
447 	BControl::DetachedFromWindow();
448 }
449 //------------------------------------------------------------------------------
450 void BColorControl::GetPreferredSize(float *width, float *height)
451 {
452 	*width = fColumns * fCellSize + 4.0f + 88.0f;
453 	*height = fRows * fCellSize + 4.0f;
454 }
455 //------------------------------------------------------------------------------
456 void BColorControl::ResizeToPreferred()
457 {
458 	BControl::ResizeToPreferred();
459 }
460 //------------------------------------------------------------------------------
461 status_t BColorControl::Invoke(BMessage *msg)
462 {
463 	return BControl::Invoke(msg);
464 }
465 //------------------------------------------------------------------------------
466 void BColorControl::FrameMoved(BPoint new_position)
467 {
468 	BControl::FrameMoved(new_position);
469 }
470 //------------------------------------------------------------------------------
471 void BColorControl::FrameResized(float new_width, float new_height)
472 {
473 	BControl::FrameResized(new_width, new_height);
474 }
475 //------------------------------------------------------------------------------
476 BHandler *BColorControl::ResolveSpecifier(BMessage *msg, int32 index,
477 										  BMessage *specifier, int32 form,
478 										  const char *property)
479 {
480 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
481 }
482 //------------------------------------------------------------------------------
483 status_t BColorControl::GetSupportedSuites(BMessage *data)
484 {
485 	return BControl::GetSupportedSuites(data);
486 }
487 //------------------------------------------------------------------------------
488 void BColorControl::MakeFocus(bool state)
489 {
490 	BControl::MakeFocus(state);
491 }
492 //------------------------------------------------------------------------------
493 void BColorControl::AllAttached()
494 {
495 	BControl::AllAttached();
496 }
497 //------------------------------------------------------------------------------
498 void BColorControl::AllDetached()
499 {
500 	BControl::AllDetached();
501 }
502 //------------------------------------------------------------------------------
503 status_t BColorControl::Perform(perform_code d, void *arg)
504 {
505 	return B_ERROR;
506 }
507 //------------------------------------------------------------------------------
508 void BColorControl::_ReservedColorControl1() {}
509 void BColorControl::_ReservedColorControl2() {}
510 void BColorControl::_ReservedColorControl3() {}
511 void BColorControl::_ReservedColorControl4() {}
512 //------------------------------------------------------------------------------
513 BColorControl &BColorControl::operator=(const BColorControl &)
514 {
515 	return *this;
516 }
517 //------------------------------------------------------------------------------
518 void BColorControl::LayoutView(bool calc_frame)
519 {
520 }
521 //------------------------------------------------------------------------------
522 void BColorControl::UpdateOffscreen()
523 {
524 }
525 //------------------------------------------------------------------------------
526 void BColorControl::UpdateOffscreen(BRect update)
527 {
528 }
529 //------------------------------------------------------------------------------
530 void BColorControl::DrawColorArea(BView *target, BRect update)
531 {
532 }
533 //------------------------------------------------------------------------------
534 void BColorControl::ColorRamp(BRect r, BRect where, BView *target, rgb_color c,
535 							  int16 flag, bool focused)
536 {
537 	rgb_color color = {255, 255, 255, 255};
538 	float width = where.Width();
539 
540 	for (float i = 0; i <= width; i++)
541 	{
542 		color.red = (uint8)(i * c.red / width);
543 		color.green = (uint8)(i * c.green / width);
544 		color.blue = (uint8)(i * c.blue / width);
545 
546 		target->SetHighColor(color);
547 		target->StrokeLine(BPoint(where.left + i, where.top),
548 			BPoint(where.left + i, where.bottom));
549 	}
550 }
551 //------------------------------------------------------------------------------
552 void BColorControl::KbAdjustColor(uint32 key)
553 {
554 }
555 //------------------------------------------------------------------------------
556 bool BColorControl::key_down32(uint32 key)
557 {
558 	return false;
559 }
560 //------------------------------------------------------------------------------
561 bool BColorControl::key_down8(uint32 key)
562 {
563 	return false;
564 }
565 //------------------------------------------------------------------------------
566 BRect BColorControl::CalcFrame(BPoint start, color_control_layout layout,
567 							   int32 size)
568 {
569 	BRect rect;
570 
571 	switch (layout)
572 	{
573 		case B_CELLS_4x64:
574 			rect.Set(0.0f, 0.0f, 4 * size + 4.0f,
575 				64 * size + 4.0f);
576 			break;
577 		case B_CELLS_8x32:
578 			rect.Set(0.0f, 0.0f, 8 * size + 4.0f,
579 				32 * size + 4.0f);
580 			break;
581 		case B_CELLS_16x16:
582 			rect.Set(0.0f, 0.0f, 16 * size + 4.0f,
583 				16 * size + 4.0f);
584 			break;
585 		case B_CELLS_32x8:
586 			rect.Set(0.0f, 0.0f, 32 * size + 4.0f,
587 				8 * size + 4.0f);
588 			break;
589 		case B_CELLS_64x4:
590 			rect.Set(0.0f, 0.0f, 64 * size + 4.0f,
591 				4 * size + 4.0f);
592 			break;
593 	}
594 
595 	return rect;
596 }
597 //------------------------------------------------------------------------------
598 void BColorControl::InitData(color_control_layout layout, float size,
599 							 bool use_offscreen, BMessage *data)
600 {
601 }
602 //------------------------------------------------------------------------------
603 void BColorControl::DoMouseMoved(BPoint pt)
604 {
605 }
606 //------------------------------------------------------------------------------
607 void BColorControl::DoMouseUp(BPoint pt)
608 {
609 }
610 //------------------------------------------------------------------------------
611