tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / ColorControl.cpp
blob1da6e90657bd354a26fda8ea42d5329ea5ef62a3
1 /*
2 * Copyright 2001-2013 Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Alexandre Deckner, alex@zappotek.com
7 * Axel Dörfler, axeld@pinc-software.de
8 * Jérôme Duval
9 * Marc Flerackers, mflerackers@androme.be
10 * John Scipione, jscipione@gmail.com
13 /** BColorControl displays a palette of selectable colors. */
15 #include <ColorControl.h>
17 #include <algorithm>
19 #include <stdio.h>
20 #include <stdlib.h>
22 #include <iostream>
24 #include <ControlLook.h>
25 #include <Bitmap.h>
26 #include <TextControl.h>
27 #include <Region.h>
28 #include <Screen.h>
29 #include <SystemCatalog.h>
30 #include <Window.h>
32 using BPrivate::gSystemCatalog;
34 #include <binary_compatibility/Interface.h>
37 #undef B_TRANSLATION_CONTEXT
38 #define B_TRANSLATION_CONTEXT "ColorControl"
40 static const uint32 kMsgColorEntered = 'ccol';
41 static const float kMinCellSize = 6.0f;
42 static const float kSelectorPenSize = 2.0f;
43 static const float kSelectorSize = 4.0f;
44 static const float kSelectorHSpacing = 2.0f;
45 static const float kTextFieldsHSpacing = 6.0f;
46 static const float kDefaultFontSize = 12.0f;
47 static const float kBevelSpacing = 2.0f;
48 static const uint32 kRampCount = 4;
51 BColorControl::BColorControl(BPoint leftTop, color_control_layout layout,
52 float cellSize, const char* name, BMessage* message, bool bufferedDrawing)
54 BControl(BRect(leftTop, leftTop), name, NULL, message,
55 B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE)
57 _InitData(layout, cellSize, bufferedDrawing, NULL);
61 BColorControl::BColorControl(BMessage* data)
63 BControl(data)
65 int32 layout;
66 float cellSize;
67 bool useOffscreen;
69 data->FindInt32("_layout", &layout);
70 data->FindFloat("_csize", &cellSize);
71 data->FindBool("_use_off", &useOffscreen);
73 _InitData((color_control_layout)layout, cellSize, useOffscreen, data);
77 BColorControl::~BColorControl()
79 delete fBitmap;
83 void
84 BColorControl::_InitData(color_control_layout layout, float size,
85 bool useOffscreen, BMessage* data)
87 fPaletteMode = BScreen(B_MAIN_SCREEN_ID).ColorSpace() == B_CMAP8;
88 //TODO: we don't support workspace and colorspace changing for now
89 // so we take the main_screen colorspace at startup
90 fColumns = layout;
91 fRows = 256 / fColumns;
93 _SetCellSize(size);
95 fSelectedPaletteColorIndex = -1;
96 fPreviousSelectedPaletteColorIndex = -1;
97 fFocusedRamp = !fPaletteMode && IsFocus() ? 1 : -1;
98 fClickedRamp = -1;
100 const char* red = B_TRANSLATE_MARK("Red:");
101 const char* green = B_TRANSLATE_MARK("Green:");
102 const char* blue = B_TRANSLATE_MARK("Blue:");
103 red = gSystemCatalog.GetString(red, "ColorControl");
104 green = gSystemCatalog.GetString(green, "ColorControl");
105 blue = gSystemCatalog.GetString(blue, "ColorControl");
107 if (data != NULL) {
108 fRedText = (BTextControl*)FindView("_red");
109 fGreenText = (BTextControl*)FindView("_green");
110 fBlueText = (BTextControl*)FindView("_blue");
112 int32 value = 0;
113 data->FindInt32("_val", &value);
115 SetValue(value);
116 } else {
117 BRect textRect(0.0f, 0.0f, 0.0f, 0.0f);
118 float labelWidth = std::max(StringWidth(red),
119 std::max(StringWidth(green), StringWidth(blue)))
120 + kTextFieldsHSpacing;
121 textRect.right = labelWidth + StringWidth("999999");
122 // enough room for 3 digits plus 3 digits of padding
123 font_height fontHeight;
124 GetFontHeight(&fontHeight);
125 float labelHeight = fontHeight.ascent + fontHeight.descent;
126 textRect.bottom = labelHeight;
128 // red
130 fRedText = new BTextControl(textRect, "_red", red, "0",
131 new BMessage(kMsgColorEntered), B_FOLLOW_LEFT | B_FOLLOW_TOP,
132 B_WILL_DRAW | B_NAVIGABLE);
133 fRedText->SetDivider(labelWidth);
135 for (int32 i = 0; i < 256; i++)
136 fRedText->TextView()->DisallowChar(i);
137 for (int32 i = '0'; i <= '9'; i++)
138 fRedText->TextView()->AllowChar(i);
139 fRedText->TextView()->SetMaxBytes(3);
141 // green
143 textRect.OffsetBy(0, _TextRectOffset());
144 fGreenText = new BTextControl(textRect, "_green", green, "0",
145 new BMessage(kMsgColorEntered), B_FOLLOW_LEFT | B_FOLLOW_TOP,
146 B_WILL_DRAW | B_NAVIGABLE);
147 fGreenText->SetDivider(labelWidth);
149 for (int32 i = 0; i < 256; i++)
150 fGreenText->TextView()->DisallowChar(i);
151 for (int32 i = '0'; i <= '9'; i++)
152 fGreenText->TextView()->AllowChar(i);
153 fGreenText->TextView()->SetMaxBytes(3);
155 // blue
157 textRect.OffsetBy(0, _TextRectOffset());
158 fBlueText = new BTextControl(textRect, "_blue", blue, "0",
159 new BMessage(kMsgColorEntered), B_FOLLOW_LEFT | B_FOLLOW_TOP,
160 B_WILL_DRAW | B_NAVIGABLE);
161 fBlueText->SetDivider(labelWidth);
163 for (int32 i = 0; i < 256; i++)
164 fBlueText->TextView()->DisallowChar(i);
165 for (int32 i = '0'; i <= '9'; i++)
166 fBlueText->TextView()->AllowChar(i);
167 fBlueText->TextView()->SetMaxBytes(3);
169 AddChild(fRedText);
170 AddChild(fGreenText);
171 AddChild(fBlueText);
174 ResizeToPreferred();
176 if (useOffscreen) {
177 BRect bounds = _PaletteFrame();
178 fBitmap = new BBitmap(bounds, B_RGB32, true, false);
179 fOffscreenView = new BView(bounds, "off_view", 0, 0);
181 fBitmap->Lock();
182 fBitmap->AddChild(fOffscreenView);
183 fBitmap->Unlock();
184 } else {
185 fBitmap = NULL;
186 fOffscreenView = NULL;
191 void
192 BColorControl::_LayoutView()
194 fPaletteFrame.Set(0, 0, fColumns * fCellSize, fRows * fCellSize);
195 fPaletteFrame.OffsetBy(kBevelSpacing, kBevelSpacing);
196 if (!fPaletteMode) {
197 // Reduce the inner space by 1 pixel so that the frame
198 // is exactly rows * cellsize pixels in height
199 fPaletteFrame.bottom -= 1;
202 float rampHeight = (float)(fRows * fCellSize / kRampCount);
203 float offset = _TextRectOffset();
204 float y = 0;
205 if (rampHeight > fRedText->Frame().Height()) {
206 // there is enough room to fit kRampCount labels,
207 // shift text controls down by one ramp
208 offset = rampHeight;
209 y = floorf(offset + (offset - fRedText->Frame().Height()) / 2);
212 BRect rect = _PaletteFrame();
213 fRedText->MoveTo(rect.right + kTextFieldsHSpacing, y);
215 y += offset;
216 fGreenText->MoveTo(rect.right + kTextFieldsHSpacing, y);
218 y += offset;
219 fBlueText->MoveTo(rect.right + kTextFieldsHSpacing, y);
223 BArchivable*
224 BColorControl::Instantiate(BMessage* data)
226 if (validate_instantiation(data, "BColorControl"))
227 return new BColorControl(data);
229 return NULL;
233 status_t
234 BColorControl::Archive(BMessage* data, bool deep) const
236 status_t status = BControl::Archive(data, deep);
238 if (status == B_OK)
239 status = data->AddInt32("_layout", Layout());
241 if (status == B_OK)
242 status = data->AddFloat("_csize", fCellSize);
244 if (status == B_OK)
245 status = data->AddBool("_use_off", fOffscreenView != NULL);
247 return status;
251 void
252 BColorControl::SetLayout(BLayout* layout)
254 // We need to implement this method, since we have another SetLayout()
255 // method and C++ has this special method hiding "feature".
256 BControl::SetLayout(layout);
260 void
261 BColorControl::SetValue(int32 value)
263 rgb_color c1 = ValueAsColor();
264 rgb_color c2;
265 c2.red = (value & 0xFF000000) >> 24;
266 c2.green = (value & 0x00FF0000) >> 16;
267 c2.blue = (value & 0x0000FF00) >> 8;
268 c2.alpha = 255;
270 if (fPaletteMode) {
271 //workaround when two indexes have the same color
272 rgb_color c = BScreen(Window()).ColorForIndex(fSelectedPaletteColorIndex);
273 c.alpha = 255;
274 if (fSelectedPaletteColorIndex == -1 || c != c2) {
275 //here SetValue hasn't been called by mouse tracking
276 fSelectedPaletteColorIndex = BScreen(Window()).IndexForColor(c2);
279 c2 = BScreen(Window()).ColorForIndex(fSelectedPaletteColorIndex);
281 Invalidate(_PaletteSelectorFrame(fPreviousSelectedPaletteColorIndex));
282 Invalidate(_PaletteSelectorFrame(fSelectedPaletteColorIndex));
284 fPreviousSelectedPaletteColorIndex = fSelectedPaletteColorIndex;
285 } else if (c1 != c2)
286 Invalidate();
288 // Set the value here, since BTextControl will trigger
289 // Window()->UpdateIfNeeded() which will cause us to draw the indicators
290 // at the old offset.
291 if (Value() != value)
292 BControl::SetValueNoUpdate(value);
294 // the textcontrols have to be updated even when the color
295 // hasn't changed since the value is clamped upstream
296 // and the textcontrols would still show the unclamped value
297 char string[4];
298 sprintf(string, "%d", c2.red);
299 fRedText->SetText(string);
300 sprintf(string, "%d", c2.green);
301 fGreenText->SetText(string);
302 sprintf(string, "%d", c2.blue);
303 fBlueText->SetText(string);
307 rgb_color
308 BColorControl::ValueAsColor()
310 int32 value = Value();
311 rgb_color color;
313 color.red = (value & 0xFF000000) >> 24;
314 color.green = (value & 0x00FF0000) >> 16;
315 color.blue = (value & 0x0000FF00) >> 8;
316 color.alpha = 255;
318 return color;
322 void
323 BColorControl::SetEnabled(bool enabled)
325 BControl::SetEnabled(enabled);
327 fRedText->SetEnabled(enabled);
328 fGreenText->SetEnabled(enabled);
329 fBlueText->SetEnabled(enabled);
333 void
334 BColorControl::AttachedToWindow()
336 if (Parent())
337 SetViewColor(Parent()->ViewColor());
338 else
339 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
341 BControl::AttachedToWindow();
343 fRedText->SetTarget(this);
344 fGreenText->SetTarget(this);
345 fBlueText->SetTarget(this);
347 if (fBitmap)
348 _InitOffscreen();
352 void
353 BColorControl::MessageReceived(BMessage* message)
355 switch (message->what) {
356 case kMsgColorEntered:
358 rgb_color color;
359 color.red = min_c(strtol(fRedText->Text(), NULL, 10), 255);
360 color.green = min_c(strtol(fGreenText->Text(), NULL, 10), 255);
361 color.blue = min_c(strtol(fBlueText->Text(), NULL, 10), 255);
362 color.alpha = 255;
364 SetValue(color);
365 Invoke();
366 break;
368 default:
369 BControl::MessageReceived(message);
374 void
375 BColorControl::Draw(BRect updateRect)
377 if (fBitmap != NULL)
378 DrawBitmap(fBitmap, B_ORIGIN);
379 else
380 _DrawColorArea(this, updateRect);
382 _DrawSelectors(this);
386 void
387 BColorControl::_DrawColorArea(BView* target, BRect updateRect)
389 BRect rect = _PaletteFrame();
390 bool enabled = IsEnabled();
392 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
393 rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT);
395 if (be_control_look != NULL) {
396 uint32 flags = be_control_look->Flags(this);
397 be_control_look->DrawTextControlBorder(target, rect, updateRect,
398 base, flags);
399 } else {
400 // first bevel
401 rgb_color lighten1 = tint_color(base, B_LIGHTEN_1_TINT);
402 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
403 target->SetHighColor(enabled ? darken1 : base);
405 target->StrokeLine(rect.LeftBottom(), rect.LeftTop());
406 target->StrokeLine(rect.LeftTop(), rect.RightTop());
407 target->SetHighColor(enabled ? lightenmax : lighten1);
409 target->StrokeLine(BPoint(rect.left + 1.0f, rect.bottom),
410 rect.RightBottom());
411 target->StrokeLine(rect.RightBottom(),
412 BPoint(rect.right, rect.top + 1.0f));
414 rect.InsetBy(1.0f, 1.0f);
416 // second bevel
417 rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT);
418 rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT);
419 target->SetHighColor(enabled ? darken4 : darken2);
421 target->StrokeLine(rect.LeftBottom(), rect.LeftTop());
422 target->StrokeLine(rect.LeftTop(), rect.RightTop());
423 target->SetHighColor(base);
424 target->StrokeLine(BPoint(rect.left + 1.0f, rect.bottom),
425 rect.RightBottom());
426 target->StrokeLine(rect.RightBottom(),
427 BPoint(rect.right, rect.top + 1.0f));
430 if (fPaletteMode) {
431 int colBegin = max_c(0, -1 + int(updateRect.left) / int(fCellSize));
432 int colEnd = min_c(fColumns,
433 2 + int(updateRect.right) / int(fCellSize));
434 int rowBegin = max_c(0, -1 + int(updateRect.top) / int(fCellSize));
435 int rowEnd = min_c(fRows, 2 + int(updateRect.bottom)
436 / int(fCellSize));
438 // grid
439 target->SetHighColor(enabled ? darken1 : base);
441 for (int xi = 0; xi < fColumns + 1; xi++) {
442 float x = fPaletteFrame.left + float(xi) * fCellSize;
443 target->StrokeLine(BPoint(x, fPaletteFrame.top),
444 BPoint(x, fPaletteFrame.bottom));
446 for (int yi = 0; yi < fRows + 1; yi++) {
447 float y = fPaletteFrame.top + float(yi) * fCellSize;
448 target->StrokeLine(BPoint(fPaletteFrame.left, y),
449 BPoint(fPaletteFrame.right, y));
452 // colors
453 for (int col = colBegin; col < colEnd; col++) {
454 for (int row = rowBegin; row < rowEnd; row++) {
455 uint8 colorIndex = row * fColumns + col;
456 float x = fPaletteFrame.left + col * fCellSize;
457 float y = fPaletteFrame.top + row * fCellSize;
459 target->SetHighColor(system_colors()->color_list[colorIndex]);
460 target->FillRect(BRect(x + 1, y + 1,
461 x + fCellSize - 1, y + fCellSize - 1));
464 } else {
465 rgb_color white = { 255, 255, 255, 255 };
466 rgb_color red = { 255, 0, 0, 255 };
467 rgb_color green = { 0, 255, 0, 255 };
468 rgb_color blue = { 0, 0, 255, 255 };
470 rgb_color compColor = { 0, 0, 0, 255 };
471 if (!enabled) {
472 compColor.red = compColor.green = compColor.blue = 156;
473 red.red = green.green = blue.blue = 70;
474 white.red = white.green = white.blue = 70;
476 _DrawColorRamp(_RampFrame(0), target, white, compColor, 0, false,
477 updateRect);
478 _DrawColorRamp(_RampFrame(1), target, red, compColor, 0, false,
479 updateRect);
480 _DrawColorRamp(_RampFrame(2), target, green, compColor, 0, false,
481 updateRect);
482 _DrawColorRamp(_RampFrame(3), target, blue, compColor, 0, false,
483 updateRect);
488 void
489 BColorControl::_DrawSelectors(BView* target)
491 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
492 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
494 if (fPaletteMode) {
495 if (fSelectedPaletteColorIndex != -1) {
496 target->SetHighColor(lightenmax);
497 target->StrokeRect(_PaletteSelectorFrame(fSelectedPaletteColorIndex));
499 } else {
500 rgb_color color = ValueAsColor();
501 target->SetHighColor(255, 255, 255);
502 target->SetLowColor(0, 0, 0);
504 int components[4] = { color.alpha, color.red, color.green, color.blue };
506 for (int i = 1; i < 4; i++) {
507 BPoint center = _SelectorPosition(_RampFrame(i), components[i]);
509 target->SetPenSize(kSelectorPenSize);
510 target->StrokeEllipse(center, kSelectorSize / 2, kSelectorSize / 2);
511 target->SetPenSize(kSelectorPenSize / 2);
512 target->StrokeEllipse(center, kSelectorSize, kSelectorSize,
513 B_SOLID_LOW);
514 if (i == fFocusedRamp) {
515 target->StrokeEllipse(center,
516 kSelectorSize / 2, kSelectorSize / 2, B_SOLID_LOW);
520 target->SetPenSize(1.0f);
525 void
526 BColorControl::_DrawColorRamp(BRect rect, BView* target,
527 rgb_color baseColor, rgb_color compColor, int16 flag, bool focused,
528 BRect updateRect)
530 float width = rect.Width() + 1;
531 rgb_color color = ValueAsColor();
532 color.alpha = 255;
534 updateRect = updateRect & rect;
536 if (updateRect.IsValid() && updateRect.Width() >= 0) {
537 target->BeginLineArray((int32)updateRect.Width() + 1);
539 for (float i = (updateRect.left - rect.left);
540 i <= (updateRect.right - rect.left) + 1; i++) {
541 if (baseColor.red == 255)
542 color.red = (uint8)(i * 255 / width) + compColor.red;
543 if (baseColor.green == 255)
544 color.green = (uint8)(i * 255 / width) + compColor.green;
545 if (baseColor.blue == 255)
546 color.blue = (uint8)(i * 255 / width) + compColor.blue;
548 target->AddLine(BPoint(rect.left + i, rect.top),
549 BPoint(rect.left + i, rect.bottom - 1), color);
552 target->EndLineArray();
557 BPoint
558 BColorControl::_SelectorPosition(const BRect& rampRect, uint8 shade) const
560 float radius = kSelectorSize / 2 + kSelectorPenSize / 2;
562 return BPoint(rampRect.left + kSelectorHSpacing + radius +
563 shade * (rampRect.Width() - 2 * (kSelectorHSpacing + radius)) / 255,
564 rampRect.top + rampRect.Height() / 2);
568 BRect
569 BColorControl::_PaletteFrame() const
571 return fPaletteFrame.InsetByCopy(-kBevelSpacing, -kBevelSpacing);
575 BRect
576 BColorControl::_RampFrame(uint8 rampIndex) const
578 float rampHeight = (float)(fRows * fCellSize / kRampCount);
580 return BRect(fPaletteFrame.left,
581 fPaletteFrame.top + float(rampIndex) * rampHeight,
582 fPaletteFrame.right,
583 fPaletteFrame.top + float(rampIndex + 1) * rampHeight);
587 void
588 BColorControl::_SetCellSize(float size)
590 BFont font;
591 GetFont(&font);
592 fCellSize = std::max(kMinCellSize,
593 ceilf(size * font.Size() / kDefaultFontSize));
597 float
598 BColorControl::_TextRectOffset()
600 return std::max(fRedText->Bounds().Height(),
601 ceilf(_PaletteFrame().Height() / 3));
605 BRect
606 BColorControl::_PaletteSelectorFrame(uint8 colorIndex) const
608 uint32 row = colorIndex / fColumns;
609 uint32 column = colorIndex % fColumns;
610 float x = fPaletteFrame.left + column * fCellSize;
611 float y = fPaletteFrame.top + row * fCellSize;
612 return BRect(x, y, x + fCellSize, y + fCellSize);
616 void
617 BColorControl::_InitOffscreen()
619 if (fBitmap->Lock()) {
620 _DrawColorArea(fOffscreenView, _PaletteFrame());
621 fOffscreenView->Sync();
622 fBitmap->Unlock();
627 void
628 BColorControl::_InvalidateSelector(int16 ramp, rgb_color color, bool focused)
630 if (fPaletteMode)
631 return;
633 if (ramp < 1 || ramp > 3)
634 return;
636 float invalidateRadius = focused
637 ? kSelectorSize + kSelectorPenSize / 2
638 : kSelectorSize / 2 + kSelectorPenSize;
640 uint8 colorValue = ramp == 1 ? color.red : ramp == 2 ? color.green
641 : color.blue;
643 BPoint pos = _SelectorPosition(_RampFrame(ramp), colorValue);
644 Invalidate(BRect(pos.x - invalidateRadius, pos.y - invalidateRadius,
645 pos.x + invalidateRadius, pos.y + invalidateRadius));
649 void
650 BColorControl::SetCellSize(float size)
652 _SetCellSize(size);
653 ResizeToPreferred();
657 float
658 BColorControl::CellSize() const
660 return fCellSize;
664 void
665 BColorControl::SetLayout(color_control_layout layout)
667 switch (layout) {
668 case B_CELLS_4x64:
669 fColumns = 4;
670 fRows = 64;
671 break;
672 case B_CELLS_8x32:
673 fColumns = 8;
674 fRows = 32;
675 break;
676 case B_CELLS_16x16:
677 fColumns = 16;
678 fRows = 16;
679 break;
680 case B_CELLS_32x8:
681 fColumns = 32;
682 fRows = 8;
683 break;
684 case B_CELLS_64x4:
685 fColumns = 64;
686 fRows = 4;
687 break;
690 ResizeToPreferred();
691 Invalidate();
695 color_control_layout
696 BColorControl::Layout() const
698 if (fColumns == 4 && fRows == 64)
699 return B_CELLS_4x64;
700 if (fColumns == 8 && fRows == 32)
701 return B_CELLS_8x32;
702 if (fColumns == 16 && fRows == 16)
703 return B_CELLS_16x16;
704 if (fColumns == 32 && fRows == 8)
705 return B_CELLS_32x8;
706 if (fColumns == 64 && fRows == 4)
707 return B_CELLS_64x4;
709 return B_CELLS_32x8;
713 void
714 BColorControl::WindowActivated(bool state)
716 BControl::WindowActivated(state);
720 void
721 BColorControl::KeyDown(const char* bytes, int32 numBytes)
723 if (IsFocus() && !fPaletteMode && numBytes == 1) {
724 rgb_color color = ValueAsColor();
726 switch (bytes[0]) {
727 case B_UP_ARROW:
729 int16 oldFocus = fFocusedRamp;
730 fFocusedRamp--;
731 if (fFocusedRamp < 1)
732 fFocusedRamp = 3;
734 _InvalidateSelector(oldFocus, color, true);
735 _InvalidateSelector(fFocusedRamp, color, true);
736 break;
739 case B_DOWN_ARROW:
741 int16 oldFocus = fFocusedRamp;
742 fFocusedRamp++;
743 if (fFocusedRamp > 3)
744 fFocusedRamp = 1;
746 _InvalidateSelector(oldFocus, color, true);
747 _InvalidateSelector(fFocusedRamp, color, true);
748 break;
751 case B_LEFT_ARROW:
753 bool goFaster = false;
754 if (Window() != NULL) {
755 BMessage* message = Window()->CurrentMessage();
756 if (message != NULL && message->what == B_KEY_DOWN) {
757 int32 repeats = 0;
758 if (message->FindInt32("be:key_repeat", &repeats)
759 == B_OK && repeats > 4) {
760 goFaster = true;
765 if (fFocusedRamp == 1) {
766 if (goFaster && color.red >= 5)
767 color.red -= 5;
768 else if (color.red > 0)
769 color.red--;
770 } else if (fFocusedRamp == 2) {
771 if (goFaster && color.green >= 5)
772 color.green -= 5;
773 else if (color.green > 0)
774 color.green--;
775 } else if (fFocusedRamp == 3) {
776 if (goFaster && color.blue >= 5)
777 color.blue -= 5;
778 else if (color.blue > 0)
779 color.blue--;
782 SetValue(color);
783 Invoke();
784 break;
787 case B_RIGHT_ARROW:
789 bool goFaster = false;
790 if (Window() != NULL) {
791 BMessage* message = Window()->CurrentMessage();
792 if (message != NULL && message->what == B_KEY_DOWN) {
793 int32 repeats = 0;
794 if (message->FindInt32("be:key_repeat", &repeats)
795 == B_OK && repeats > 4) {
796 goFaster = true;
801 if (fFocusedRamp == 1) {
802 if (goFaster && color.red <= 250)
803 color.red += 5;
804 else if (color.red < 255)
805 color.red++;
806 } else if (fFocusedRamp == 2) {
807 if (goFaster && color.green <= 250)
808 color.green += 5;
809 else if (color.green < 255)
810 color.green++;
811 } else if (fFocusedRamp == 3) {
812 if (goFaster && color.blue <= 250)
813 color.blue += 5;
814 else if (color.blue < 255)
815 color.blue++;
818 SetValue(color);
819 Invoke();
820 break;
825 BControl::KeyDown(bytes, numBytes);
829 void
830 BColorControl::MouseUp(BPoint point)
832 fClickedRamp = -1;
833 SetTracking(false);
837 void
838 BColorControl::MouseDown(BPoint point)
840 if (!IsEnabled())
841 return;
842 if (!fPaletteFrame.Contains(point))
843 return;
845 if (fPaletteMode) {
846 int col = (int)((point.x - fPaletteFrame.left) / fCellSize);
847 int row = (int)((point.y - fPaletteFrame.top) / fCellSize);
848 int colorIndex = row * fColumns + col;
849 if (colorIndex >= 0 && colorIndex < 256) {
850 fSelectedPaletteColorIndex = colorIndex;
851 SetValue(system_colors()->color_list[colorIndex]);
853 } else {
854 rgb_color color = ValueAsColor();
856 uint8 shade = (unsigned char)max_c(0,
857 min_c((point.x - _RampFrame(0).left) * 255
858 / _RampFrame(0).Width(), 255));
860 if (_RampFrame(0).Contains(point)) {
861 color.red = color.green = color.blue = shade;
862 fClickedRamp = 0;
863 } else if (_RampFrame(1).Contains(point)) {
864 color.red = shade;
865 fClickedRamp = 1;
866 } else if (_RampFrame(2).Contains(point)) {
867 color.green = shade;
868 fClickedRamp = 2;
869 } else if (_RampFrame(3).Contains(point)) {
870 color.blue = shade;
871 fClickedRamp = 3;
874 SetValue(color);
877 Invoke();
879 SetTracking(true);
880 SetMouseEventMask(B_POINTER_EVENTS,
881 B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
885 void
886 BColorControl::MouseMoved(BPoint point, uint32 transit,
887 const BMessage* message)
889 if (!IsTracking())
890 return;
892 if (fPaletteMode && fPaletteFrame.Contains(point)) {
893 int col = (int)((point.x - fPaletteFrame.left) / fCellSize);
894 int row = (int)((point.y - fPaletteFrame.top) / fCellSize);
895 int colorIndex = row * fColumns + col;
896 if (colorIndex >= 0 && colorIndex < 256) {
897 fSelectedPaletteColorIndex = colorIndex;
898 SetValue(system_colors()->color_list[colorIndex]);
900 } else {
901 if (fClickedRamp < 0 || fClickedRamp > 3)
902 return;
904 rgb_color color = ValueAsColor();
906 uint8 shade = (unsigned char)max_c(0,
907 min_c((point.x - _RampFrame(0).left) * 255
908 / _RampFrame(0).Width(), 255));
910 if (fClickedRamp == 0)
911 color.red = color.green = color.blue = shade;
912 else if (fClickedRamp == 1)
913 color.red = shade;
914 else if (fClickedRamp == 2)
915 color.green = shade;
916 else if (fClickedRamp == 3)
917 color.blue = shade;
919 SetValue(color);
922 Invoke();
926 void
927 BColorControl::DetachedFromWindow()
929 BControl::DetachedFromWindow();
933 void
934 BColorControl::GetPreferredSize(float* _width, float* _height)
936 BRect rect = _PaletteFrame();
938 if (rect.Height() < fBlueText->Frame().bottom) {
939 // adjust the height to fit
940 rect.bottom = fBlueText->Frame().bottom;
943 if (_width) {
944 *_width = rect.Width() + kTextFieldsHSpacing
945 + fRedText->Bounds().Width();
948 if (_height)
949 *_height = rect.Height();
953 void
954 BColorControl::ResizeToPreferred()
956 _LayoutView();
957 BControl::ResizeToPreferred();
961 status_t
962 BColorControl::Invoke(BMessage* message)
964 return BControl::Invoke(message);
968 void
969 BColorControl::FrameMoved(BPoint newPosition)
971 BControl::FrameMoved(newPosition);
975 void
976 BColorControl::FrameResized(float newWidth, float newHeight)
978 BControl::FrameResized(newWidth, newHeight);
982 BHandler*
983 BColorControl::ResolveSpecifier(BMessage* message, int32 index,
984 BMessage* specifier, int32 form, const char* property)
986 return BControl::ResolveSpecifier(message, index, specifier, form,
987 property);
991 status_t
992 BColorControl::GetSupportedSuites(BMessage* data)
994 return BControl::GetSupportedSuites(data);
998 void
999 BColorControl::MakeFocus(bool focused)
1001 fFocusedRamp = !fPaletteMode && focused ? 1 : -1;
1002 BControl::MakeFocus(focused);
1006 void
1007 BColorControl::AllAttached()
1009 BControl::AllAttached();
1013 void
1014 BColorControl::AllDetached()
1016 BControl::AllDetached();
1020 status_t
1021 BColorControl::SetIcon(const BBitmap* icon, uint32 flags)
1023 return BControl::SetIcon(icon, flags);
1027 status_t
1028 BColorControl::Perform(perform_code code, void* _data)
1030 switch (code) {
1031 case PERFORM_CODE_MIN_SIZE:
1032 ((perform_data_min_size*)_data)->return_value
1033 = BColorControl::MinSize();
1034 return B_OK;
1035 case PERFORM_CODE_MAX_SIZE:
1036 ((perform_data_max_size*)_data)->return_value
1037 = BColorControl::MaxSize();
1038 return B_OK;
1039 case PERFORM_CODE_PREFERRED_SIZE:
1040 ((perform_data_preferred_size*)_data)->return_value
1041 = BColorControl::PreferredSize();
1042 return B_OK;
1043 case PERFORM_CODE_LAYOUT_ALIGNMENT:
1044 ((perform_data_layout_alignment*)_data)->return_value
1045 = BColorControl::LayoutAlignment();
1046 return B_OK;
1047 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
1048 ((perform_data_has_height_for_width*)_data)->return_value
1049 = BColorControl::HasHeightForWidth();
1050 return B_OK;
1051 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
1053 perform_data_get_height_for_width* data
1054 = (perform_data_get_height_for_width*)_data;
1055 BColorControl::GetHeightForWidth(data->width, &data->min,
1056 &data->max, &data->preferred);
1057 return B_OK;
1059 case PERFORM_CODE_SET_LAYOUT:
1061 perform_data_set_layout* data = (perform_data_set_layout*)_data;
1062 BColorControl::SetLayout(data->layout);
1063 return B_OK;
1065 case PERFORM_CODE_LAYOUT_INVALIDATED:
1067 perform_data_layout_invalidated* data
1068 = (perform_data_layout_invalidated*)_data;
1069 BColorControl::LayoutInvalidated(data->descendants);
1070 return B_OK;
1072 case PERFORM_CODE_DO_LAYOUT:
1074 BColorControl::DoLayout();
1075 return B_OK;
1077 case PERFORM_CODE_SET_ICON:
1079 perform_data_set_icon* data = (perform_data_set_icon*)_data;
1080 return BColorControl::SetIcon(data->icon, data->flags);
1084 return BControl::Perform(code, _data);
1088 void BColorControl::_ReservedColorControl1() {}
1089 void BColorControl::_ReservedColorControl2() {}
1090 void BColorControl::_ReservedColorControl3() {}
1091 void BColorControl::_ReservedColorControl4() {}
1094 BColorControl &
1095 BColorControl::operator=(const BColorControl &)
1097 return *this;