1 /* 2 * Copyright 2001-2008, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Axel Dörfler, axeld@pinc-software.de 8 * Alexandre Deckner, alex@zappotek.com 9 */ 10 11 /** BColorControl displays a palette of selectable colors. */ 12 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 17 #include <ColorControl.h> 18 #include <Bitmap.h> 19 #include <TextControl.h> 20 #include <Region.h> 21 #include <Screen.h> 22 #include <Window.h> 23 24 25 static const uint32 kMsgColorEntered = 'ccol'; 26 static const uint32 kMinCellSize = 6; 27 static const float kSelectorPenSize = 2.0f; 28 static const float kSelectorSize = 4.0f; 29 static const float kSelectorHSpacing = 2.0f; 30 static const float kTextFieldsHSpacing = 6.0f; 31 32 BColorControl::BColorControl(BPoint leftTop, color_control_layout layout, 33 float cellSize, const char *name, BMessage *message, 34 bool bufferedDrawing) 35 : BControl(BRect(leftTop, leftTop), name, NULL, message, 36 B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE) 37 { 38 _InitData(layout, cellSize, bufferedDrawing, NULL); 39 } 40 41 42 BColorControl::BColorControl(BMessage* archive) 43 : BControl(archive) 44 { 45 int32 layout; 46 float cellSize; 47 bool useOffscreen; 48 49 archive->FindInt32("_layout", &layout); 50 archive->FindFloat("_csize", &cellSize); 51 archive->FindBool("_use_off", &useOffscreen); 52 53 _InitData((color_control_layout)layout, cellSize, useOffscreen, archive); 54 } 55 56 57 BColorControl::~BColorControl() 58 { 59 delete fBitmap; 60 } 61 62 63 void 64 BColorControl::_InitData(color_control_layout layout, float size, 65 bool useOffscreen, BMessage* archive) 66 { 67 fPaletteMode = BScreen(B_MAIN_SCREEN_ID).ColorSpace() == B_CMAP8; 68 //TODO: we don't support workspace and colorspace changing for now 69 // so we take the main_screen colorspace at startup 70 fColumns = layout; 71 fRows = 256 / fColumns; 72 fCellSize = ceil(max_c(kMinCellSize, size)); 73 74 fSelectedPaletteColorIndex = -1; 75 fPreviousSelectedPaletteColorIndex = -1; 76 fFocusedComponent = 0; 77 78 if (archive) { 79 fRedText = (BTextControl*)FindView("_red"); 80 fGreenText = (BTextControl*)FindView("_green"); 81 fBlueText = (BTextControl*)FindView("_blue"); 82 83 int32 value = 0; 84 archive->FindInt32("_val", &value); 85 86 SetValue(value); 87 } else { 88 BRect rect(0.0f, 0.0f, 70.0f, 15.0f); 89 float labelWidth = StringWidth("Green:") + 5; 90 rect.right = labelWidth + StringWidth("999") + 20; 91 92 // red 93 94 fRedText = new BTextControl(rect, "_red", "Red:", "0", 95 new BMessage(kMsgColorEntered), B_FOLLOW_LEFT | B_FOLLOW_TOP, 96 B_WILL_DRAW | B_NAVIGABLE); 97 fRedText->SetDivider(labelWidth); 98 99 float offset = fRedText->Bounds().Height() + 2; 100 101 for (int32 i = 0; i < 256; i++) 102 fRedText->TextView()->DisallowChar(i); 103 for (int32 i = '0'; i <= '9'; i++) 104 fRedText->TextView()->AllowChar(i); 105 fRedText->TextView()->SetMaxBytes(3); 106 107 // green 108 109 rect.OffsetBy(0.0f, offset); 110 fGreenText = new BTextControl(rect, "_green", "Green:", "0", 111 new BMessage(kMsgColorEntered), B_FOLLOW_LEFT | B_FOLLOW_TOP, 112 B_WILL_DRAW | B_NAVIGABLE); 113 fGreenText->SetDivider(labelWidth); 114 115 for (int32 i = 0; i < 256; i++) 116 fGreenText->TextView()->DisallowChar(i); 117 for (int32 i = '0'; i <= '9'; i++) 118 fGreenText->TextView()->AllowChar(i); 119 fGreenText->TextView()->SetMaxBytes(3); 120 121 // blue 122 123 rect.OffsetBy(0.0f, offset); 124 fBlueText = new BTextControl(rect, "_blue", "Blue:", "0", 125 new BMessage(kMsgColorEntered), B_FOLLOW_LEFT | B_FOLLOW_TOP, 126 B_WILL_DRAW | B_NAVIGABLE); 127 fBlueText->SetDivider(labelWidth); 128 129 for (int32 i = 0; i < 256; i++) 130 fBlueText->TextView()->DisallowChar(i); 131 for (int32 i = '0'; i <= '9'; i++) 132 fBlueText->TextView()->AllowChar(i); 133 fBlueText->TextView()->SetMaxBytes(3); 134 135 AddChild(fRedText); 136 AddChild(fGreenText); 137 AddChild(fBlueText); 138 } 139 140 _LayoutView(); 141 142 if (useOffscreen) { 143 BRect bounds = fPaletteFrame; 144 bounds.InsetBy(-2.0f, -2.0f); 145 146 fBitmap = new BBitmap(bounds, B_RGB32, true, false); 147 fOffscreenView = new BView(bounds, "off_view", 0, 0); 148 149 fBitmap->Lock(); 150 fBitmap->AddChild(fOffscreenView); 151 fBitmap->Unlock(); 152 } else { 153 fBitmap = NULL; 154 fOffscreenView = NULL; 155 } 156 } 157 158 159 void 160 BColorControl::_LayoutView() 161 { 162 if (fPaletteMode){ 163 fPaletteFrame.Set(2.0f, 2.0f, 164 float(fColumns) * fCellSize + 2.0, 165 float(fRows) * fCellSize + 2.0); 166 } else { 167 fPaletteFrame.Set(2.0f, 2.0f, 168 float(fColumns) * fCellSize + 2.0, 169 float(fRows) * fCellSize + 2.0 - 1.0); 170 //1 pixel adjust so that the inner space 171 //has exactly rows*cellsize pixels in height 172 } 173 174 BRect rect = fPaletteFrame.InsetByCopy(-2.0,-2.0); //bevel 175 176 if (rect.Height() < fBlueText->Frame().bottom) { 177 // adjust the height to fit 178 rect.bottom = fBlueText->Frame().bottom; 179 } 180 181 float offset = floor(rect.bottom / 4); 182 float y = offset; 183 if (offset < fRedText->Bounds().Height() + 2) { 184 offset = fRedText->Bounds().Height() + 2; 185 y = 0; 186 } 187 188 fRedText->MoveTo(rect.right + kTextFieldsHSpacing, y); 189 190 y += offset; 191 fGreenText->MoveTo(rect.right + kTextFieldsHSpacing, y); 192 193 y += offset; 194 fBlueText->MoveTo(rect.right + kTextFieldsHSpacing, y); 195 196 ResizeTo(rect.Width() + kTextFieldsHSpacing + fRedText->Bounds().Width(), rect.Height()); 197 198 } 199 200 201 BArchivable * 202 BColorControl::Instantiate(BMessage *archive) 203 { 204 if (validate_instantiation(archive, "BColorControl")) 205 return new BColorControl(archive); 206 207 return NULL; 208 } 209 210 211 status_t 212 BColorControl::Archive(BMessage *archive, bool deep) const 213 { 214 status_t status = BControl::Archive(archive, deep); 215 216 if (status == B_OK) 217 status = archive->AddInt32("_layout", Layout()); 218 if (status == B_OK) 219 status = archive->AddFloat("_csize", fCellSize); 220 if (status == B_OK) 221 status = archive->AddBool("_use_off", fOffscreenView != NULL); 222 223 return status; 224 } 225 226 227 void 228 BColorControl::SetLayout(BLayout* layout) 229 { 230 // We need to implement this method, since we have another SetLayout() 231 // method and C++ has this special method hiding "feature". 232 BControl::SetLayout(layout); 233 } 234 235 236 void 237 BColorControl::SetValue(int32 value) 238 { 239 rgb_color c1 = ValueAsColor(); 240 rgb_color c2; 241 c2.red = (value & 0xFF000000) >> 24; 242 c2.green = (value & 0x00FF0000) >> 16; 243 c2.blue = (value & 0x0000FF00) >> 8; 244 c2.alpha = 255; 245 char string[4]; 246 247 if (fPaletteMode) { 248 //workaround when two indexes have the same color 249 rgb_color c = BScreen(Window()).ColorForIndex(fSelectedPaletteColorIndex); 250 c.alpha = 255; 251 if (fSelectedPaletteColorIndex == -1 || c != c2) { 252 //here SetValue hasn't been called by mouse tracking 253 fSelectedPaletteColorIndex = BScreen(Window()).IndexForColor(c2); 254 } 255 256 c2 = BScreen(Window()).ColorForIndex(fSelectedPaletteColorIndex); 257 258 Invalidate(_PaletteSelectorFrame(fPreviousSelectedPaletteColorIndex)); 259 Invalidate(_PaletteSelectorFrame(fSelectedPaletteColorIndex)); 260 261 fPreviousSelectedPaletteColorIndex = fSelectedPaletteColorIndex; 262 } else { 263 float invalidateRadius = kSelectorSize/2 + kSelectorPenSize; 264 BPoint p; 265 266 if (c1.red != c2.red) { 267 p = _SelectorPosition(_RampFrame(1), c1.red); 268 Invalidate(BRect(p.x - invalidateRadius, p.y - invalidateRadius, 269 p.x + invalidateRadius, p.y + invalidateRadius)); 270 271 p = _SelectorPosition(_RampFrame(1), c2.red); 272 Invalidate(BRect(p.x - invalidateRadius, p.y - invalidateRadius, 273 p.x + invalidateRadius, p.y + invalidateRadius)); 274 } 275 if (c1.green != c2.green) { 276 p = _SelectorPosition(_RampFrame(2), c1.green); 277 Invalidate(BRect(p.x - invalidateRadius, p.y - invalidateRadius, 278 p.x + invalidateRadius, p.y + invalidateRadius)); 279 280 p = _SelectorPosition(_RampFrame(2), c2.green); 281 Invalidate(BRect(p.x - invalidateRadius, p.y - invalidateRadius, 282 p.x + invalidateRadius, p.y + invalidateRadius)); 283 } 284 if (c1.blue != c2.blue) { 285 p = _SelectorPosition(_RampFrame(3), c1.blue); 286 Invalidate(BRect(p.x - invalidateRadius, p.y - invalidateRadius, 287 p.x + invalidateRadius, p.y + invalidateRadius)); 288 289 p = _SelectorPosition(_RampFrame(3), c2.blue); 290 Invalidate(BRect(p.x - invalidateRadius, p.y - invalidateRadius, 291 p.x + invalidateRadius, p.y + invalidateRadius)); 292 } 293 } 294 295 // the textcontrols have to be updated even when the color 296 // hasn't changed since the value is clamped upstream 297 // and the textcontrols would still show the unclamped value 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); 304 305 if (Value() == value) 306 return; 307 308 BControl::SetValueNoUpdate(value); 309 310 if (LockLooper()) { 311 Window()->UpdateIfNeeded(); 312 UnlockLooper(); 313 } 314 } 315 316 317 rgb_color 318 BColorControl::ValueAsColor() 319 { 320 int32 value = Value(); 321 rgb_color color; 322 323 color.red = (value & 0xFF000000) >> 24; 324 color.green = (value & 0x00FF0000) >> 16; 325 color.blue = (value & 0x0000FF00) >> 8; 326 color.alpha = 255; 327 328 return color; 329 } 330 331 332 void 333 BColorControl::SetEnabled(bool enabled) 334 { 335 BControl::SetEnabled(enabled); 336 337 fRedText->SetEnabled(enabled); 338 fGreenText->SetEnabled(enabled); 339 fBlueText->SetEnabled(enabled); 340 } 341 342 343 void 344 BColorControl::AttachedToWindow() 345 { 346 if (Parent()) 347 SetViewColor(Parent()->ViewColor()); 348 else 349 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 350 351 BControl::AttachedToWindow(); 352 353 fRedText->SetTarget(this); 354 fGreenText->SetTarget(this); 355 fBlueText->SetTarget(this); 356 357 if (fBitmap) 358 _InitOffscreen(); 359 } 360 361 362 void 363 BColorControl::MessageReceived(BMessage *message) 364 { 365 switch (message->what) { 366 case kMsgColorEntered: 367 { 368 rgb_color color; 369 color.red = min_c(strtol(fRedText->Text(), NULL, 10), 255); 370 color.green = min_c(strtol(fGreenText->Text(), NULL, 10), 255); 371 color.blue = min_c(strtol(fBlueText->Text(), NULL, 10), 255); 372 color.alpha = 255; 373 374 SetValue(color); 375 Invoke(); 376 break; 377 } 378 default: 379 BControl::MessageReceived(message); 380 } 381 } 382 383 384 void 385 BColorControl::Draw(BRect updateRect) 386 { 387 if (fBitmap) { 388 if (!fBitmap->Lock()) 389 return; 390 391 if (fOffscreenView->Bounds().Intersects(updateRect)) { 392 BRegion region(updateRect); 393 ConstrainClippingRegion(®ion); 394 DrawBitmap(fBitmap, B_ORIGIN); 395 ConstrainClippingRegion(NULL); 396 } 397 398 fBitmap->Unlock(); 399 _DrawSelectors(this); 400 401 } else { 402 _DrawColorArea(this, updateRect); 403 _DrawSelectors(this); 404 } 405 } 406 407 408 void 409 BColorControl::_DrawColorArea(BView* target, BRect update) 410 { 411 BRegion region(update); 412 target->ConstrainClippingRegion(®ion); 413 414 rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR), 415 lightenmax = tint_color(noTint, B_LIGHTEN_MAX_TINT), 416 darken1 = tint_color(noTint, B_DARKEN_1_TINT), 417 darken4 = tint_color(noTint, B_DARKEN_4_TINT); 418 419 BRect bevelRect = fPaletteFrame.InsetByCopy(-2.0,-2.0); //bevel 420 421 // First bevel 422 target->SetHighColor(darken1); 423 target->StrokeLine(bevelRect.LeftBottom(), bevelRect.LeftTop()); 424 target->StrokeLine(bevelRect.LeftTop(), bevelRect.RightTop()); 425 target->SetHighColor(lightenmax); 426 target->StrokeLine(BPoint(bevelRect.left + 1.0f, bevelRect.bottom), bevelRect.RightBottom()); 427 target->StrokeLine(bevelRect.RightBottom(), BPoint(bevelRect.right, bevelRect.top + 1.0f)); 428 429 bevelRect.InsetBy(1.0f, 1.0f); 430 431 // Second bevel 432 target->SetHighColor(darken4); 433 target->StrokeLine(bevelRect.LeftBottom(), bevelRect.LeftTop()); 434 target->StrokeLine(bevelRect.LeftTop(), bevelRect.RightTop()); 435 target->SetHighColor(noTint); 436 target->StrokeLine(BPoint(bevelRect.left + 1.0f, bevelRect.bottom), bevelRect.RightBottom()); 437 target->StrokeLine(bevelRect.RightBottom(), BPoint(bevelRect.right, bevelRect.top + 1.0f)); 438 439 if (fPaletteMode) { 440 int colBegin = max_c(0, -1 + int(update.left) / int(fCellSize)); 441 int colEnd = min_c(fColumns, 2 + int(update.right) / int(fCellSize)); 442 int rowBegin = max_c(0, -1 + int(update.top) / int(fCellSize)); 443 int rowEnd = min_c(fRows, 2 + int(update.bottom) / int(fCellSize)); 444 445 //grid 446 target->SetHighColor(darken1); 447 for (int xi = 0; xi < fColumns+1; xi++){ 448 float x = fPaletteFrame.left + float(xi) * fCellSize; 449 target->StrokeLine(BPoint(x, fPaletteFrame.top), BPoint(x, fPaletteFrame.bottom)); 450 } 451 for (int yi = 0; yi < fRows+1; yi++){ 452 float y = fPaletteFrame.top + float(yi) * fCellSize; 453 target->StrokeLine(BPoint(fPaletteFrame.left, y), BPoint(fPaletteFrame.right, y)); 454 } 455 456 //colors 457 for (int col = colBegin; col < colEnd; col++){ 458 for (int row = rowBegin; row < rowEnd; row++){ 459 uint8 colorIndex = row * fColumns + col; 460 float x = fPaletteFrame.left + col * fCellSize; 461 float y = fPaletteFrame.top + row * fCellSize; 462 463 target->SetHighColor(system_colors()->color_list[colorIndex]); 464 target->FillRect(BRect(x+1, y+1, x + fCellSize - 1, y + fCellSize - 1)); 465 } 466 } 467 } else { 468 rgb_color white = {255, 255, 255, 255}; 469 rgb_color red = {255, 0, 0, 255}; 470 rgb_color green = {0, 255, 0, 255}; 471 rgb_color blue = {0, 0, 255, 255}; 472 473 _ColorRamp(_RampFrame(0), target, white, 0, false, update); 474 _ColorRamp(_RampFrame(1), target, red, 0, false, update); 475 _ColorRamp(_RampFrame(2), target, green, 0, false, update); 476 _ColorRamp(_RampFrame(3), target, blue, 0, false, update); 477 } 478 479 ConstrainClippingRegion(NULL); 480 } 481 482 483 void 484 BColorControl::_DrawSelectors(BView* target) 485 { 486 rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR); 487 rgb_color lightenmax = tint_color(noTint, B_LIGHTEN_MAX_TINT); 488 489 if (fPaletteMode) { 490 if (fSelectedPaletteColorIndex != -1) { 491 target->SetHighColor(lightenmax); 492 target->StrokeRect(_PaletteSelectorFrame(fSelectedPaletteColorIndex)); 493 } 494 } else { 495 rgb_color color = ValueAsColor(); 496 target->SetPenSize(kSelectorPenSize); 497 target->SetHighColor(255, 255, 255); 498 499 target->StrokeEllipse(_SelectorPosition(_RampFrame(1), color.red), 500 kSelectorSize / 2, kSelectorSize / 2); 501 target->StrokeEllipse(_SelectorPosition(_RampFrame(2), color.green), 502 kSelectorSize / 2, kSelectorSize / 2); 503 target->StrokeEllipse(_SelectorPosition(_RampFrame(3), color.blue), 504 kSelectorSize / 2, kSelectorSize / 2); 505 506 target->SetPenSize(1.0f); 507 } 508 } 509 510 511 void 512 BColorControl::_ColorRamp(BRect rect, BView* target, 513 rgb_color baseColor, int16 flag, bool focused, BRect update) 514 { 515 float width = rect.Width() + 1; 516 rgb_color color; 517 color.alpha = 255; 518 519 update = update & rect; 520 521 if (update.IsValid() && update.Width() >= 0){ 522 target->BeginLineArray((int32)update.Width() + 1); 523 524 for (float i = (update.left - rect.left); i <= (update.right - rect.left) + 1; i++) { 525 color.red = (uint8)(i * baseColor.red / width); 526 color.green = (uint8)(i * baseColor.green / width); 527 color.blue = (uint8)(i * baseColor.blue / width); 528 529 target->AddLine(BPoint(rect.left + i, rect.top), 530 BPoint(rect.left + i, rect.bottom - 1), color); 531 } 532 533 target->EndLineArray(); 534 } 535 } 536 537 538 BPoint 539 BColorControl::_SelectorPosition(const BRect& rampRect, uint8 shade) const 540 { 541 float radius = kSelectorSize / 2 + kSelectorPenSize / 2; 542 543 return BPoint(rampRect.left + kSelectorHSpacing + radius + 544 shade * (rampRect.Width() - 2 * (kSelectorHSpacing + radius)) / 255, 545 rampRect.top + rampRect.Height() / 2); 546 } 547 548 549 BRect 550 BColorControl::_RampFrame(uint8 rampIndex) const 551 { 552 float rampHeight = float(fRows) * fCellSize / 4.0f; 553 554 return BRect( fPaletteFrame.left, 555 fPaletteFrame.top + float(rampIndex) * rampHeight, 556 fPaletteFrame.right, 557 fPaletteFrame.top + float(rampIndex + 1) * rampHeight); 558 } 559 560 561 BRect 562 BColorControl::_PaletteSelectorFrame(uint8 colorIndex) const 563 { 564 uint32 row = colorIndex / fColumns; 565 uint32 column = colorIndex % fColumns; 566 float x = fPaletteFrame.left + column * fCellSize; 567 float y = fPaletteFrame.top + row * fCellSize; 568 return BRect(x, y, x + fCellSize, y + fCellSize); 569 } 570 571 572 void 573 BColorControl::_InitOffscreen() 574 { 575 if (fBitmap->Lock()) { 576 _DrawColorArea(fOffscreenView, fPaletteFrame.InsetByCopy(-2.0f,-2.0f)); 577 fOffscreenView->Sync(); 578 fBitmap->Unlock(); 579 } 580 } 581 582 583 void 584 BColorControl::SetCellSize(float cellSide) 585 { 586 fCellSize = ceil(max_c(kMinCellSize, cellSide)); 587 _LayoutView(); 588 ResizeToPreferred(); 589 } 590 591 592 float 593 BColorControl::CellSize() const 594 { 595 return fCellSize; 596 } 597 598 599 void 600 BColorControl::SetLayout(color_control_layout layout) 601 { 602 switch (layout) { 603 case B_CELLS_4x64: 604 fColumns = 4; 605 fRows = 64; 606 break; 607 case B_CELLS_8x32: 608 fColumns = 8; 609 fRows = 32; 610 break; 611 case B_CELLS_16x16: 612 fColumns = 16; 613 fRows = 16; 614 break; 615 case B_CELLS_32x8: 616 fColumns = 32; 617 fRows = 8; 618 break; 619 case B_CELLS_64x4: 620 fColumns = 64; 621 fRows = 4; 622 break; 623 } 624 625 _LayoutView(); 626 627 ResizeToPreferred(); 628 Invalidate(); 629 } 630 631 632 color_control_layout 633 BColorControl::Layout() const 634 { 635 if (fColumns == 4 && fRows == 64) 636 return B_CELLS_4x64; 637 if (fColumns == 8 && fRows == 32) 638 return B_CELLS_8x32; 639 if (fColumns == 16 && fRows == 16) 640 return B_CELLS_16x16; 641 if (fColumns == 32 && fRows == 8) 642 return B_CELLS_32x8; 643 if (fColumns == 64 && fRows == 4) 644 return B_CELLS_64x4; 645 646 return B_CELLS_32x8; 647 } 648 649 650 void 651 BColorControl::WindowActivated(bool state) 652 { 653 BControl::WindowActivated(state); 654 } 655 656 657 void 658 BColorControl::KeyDown(const char* bytes, int32 numBytes) 659 { 660 // TODO: make this keyboard navigable! 661 BControl::KeyDown(bytes, numBytes); 662 } 663 664 665 void 666 BColorControl::MouseUp(BPoint point) 667 { 668 fFocusedComponent = 0; 669 SetTracking(false); 670 } 671 672 673 void 674 BColorControl::MouseDown(BPoint point) 675 { 676 if (!fPaletteFrame.Contains(point)) 677 return; 678 679 if (fPaletteMode) { 680 int column = (int) ( (point.x - fPaletteFrame.left) / fCellSize ); 681 int row = (int) ( (point.y - fPaletteFrame.top) / fCellSize ); 682 int colorIndex = row * fColumns + column; 683 if (colorIndex >= 0 && colorIndex < 256) { 684 fSelectedPaletteColorIndex = colorIndex; 685 SetValue(system_colors()->color_list[colorIndex]); 686 } 687 } else { 688 rgb_color color = ValueAsColor(); 689 690 uint8 shade = (unsigned char)max_c(0, 691 min_c((point.x - _RampFrame(0).left) * 255 / _RampFrame(0).Width(), 255)); 692 693 if (_RampFrame(0).Contains(point)) { 694 color.red = color.green = color.blue = shade; 695 fFocusedComponent = 1; 696 } else if (_RampFrame(1).Contains(point)) { 697 color.red = shade; 698 fFocusedComponent = 2; 699 } else if (_RampFrame(2).Contains(point)) { 700 color.green = shade; 701 fFocusedComponent = 3; 702 } else if (_RampFrame(3).Contains(point)){ 703 color.blue = shade; 704 fFocusedComponent = 4; 705 } 706 707 SetValue(color); 708 709 } 710 711 Invoke(); 712 713 SetTracking(true); 714 MakeFocus(); 715 SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY|B_LOCK_WINDOW_FOCUS); 716 } 717 718 719 void 720 BColorControl::MouseMoved(BPoint point, uint32 transit, 721 const BMessage *message) 722 { 723 if (!IsTracking()) 724 return; 725 726 if (fPaletteMode && fPaletteFrame.Contains(point)) { 727 int column = (int) ( (point.x - fPaletteFrame.left) / fCellSize ); 728 int row = (int) ( (point.y - fPaletteFrame.top) / fCellSize ); 729 int colorIndex = row * fColumns + column; 730 if (colorIndex >= 0 && colorIndex < 256) { 731 fSelectedPaletteColorIndex = colorIndex; 732 SetValue(system_colors()->color_list[colorIndex]); 733 } 734 735 } else { 736 if (fFocusedComponent == 0) 737 return; 738 739 rgb_color color = ValueAsColor(); 740 741 uint8 shade = (unsigned char)max_c(0, 742 min_c((point.x - _RampFrame(0).left) * 255 / _RampFrame(0).Width(), 255)); 743 744 switch (fFocusedComponent) { 745 case 1: 746 color.red = color.green = color.blue = shade; 747 break; 748 case 2: 749 color.red = shade; 750 break; 751 case 3: 752 color.green = shade; 753 break; 754 case 4: 755 color.blue = shade; 756 break; 757 default: 758 break; 759 } 760 761 SetValue(color); 762 } 763 764 Invoke(); 765 } 766 767 768 void 769 BColorControl::DetachedFromWindow() 770 { 771 BControl::DetachedFromWindow(); 772 } 773 774 775 void 776 BColorControl::GetPreferredSize(float *_width, float *_height) 777 { 778 BRect rect = fPaletteFrame.InsetByCopy(-2.0,-2.0); //bevel 779 780 if (rect.Height() < fBlueText->Frame().bottom) { 781 // adjust the height to fit 782 rect.bottom = fBlueText->Frame().bottom; 783 } 784 785 if (_width) 786 *_width = rect.Width() + kTextFieldsHSpacing + fRedText->Bounds().Width(); 787 788 if (_height) 789 *_height = rect.Height(); 790 } 791 792 793 void 794 BColorControl::ResizeToPreferred() 795 { 796 BControl::ResizeToPreferred(); 797 798 _LayoutView(); 799 } 800 801 802 status_t 803 BColorControl::Invoke(BMessage *msg) 804 { 805 return BControl::Invoke(msg); 806 } 807 808 809 void 810 BColorControl::FrameMoved(BPoint new_position) 811 { 812 BControl::FrameMoved(new_position); 813 } 814 815 816 void 817 BColorControl::FrameResized(float new_width, float new_height) 818 { 819 BControl::FrameResized(new_width, new_height); 820 } 821 822 823 BHandler * 824 BColorControl::ResolveSpecifier(BMessage *msg, int32 index, 825 BMessage *specifier, int32 form, const char *property) 826 { 827 return BControl::ResolveSpecifier(msg, index, specifier, form, property); 828 } 829 830 831 status_t 832 BColorControl::GetSupportedSuites(BMessage *data) 833 { 834 return BControl::GetSupportedSuites(data); 835 } 836 837 838 void 839 BColorControl::MakeFocus(bool state) 840 { 841 BControl::MakeFocus(state); 842 } 843 844 845 void 846 BColorControl::AllAttached() 847 { 848 BControl::AllAttached(); 849 } 850 851 852 void 853 BColorControl::AllDetached() 854 { 855 BControl::AllDetached(); 856 } 857 858 859 status_t 860 BColorControl::Perform(perform_code d, void *arg) 861 { 862 return BControl::Perform(d, arg); 863 } 864 865 866 void BColorControl::_ReservedColorControl1() {} 867 void BColorControl::_ReservedColorControl2() {} 868 void BColorControl::_ReservedColorControl3() {} 869 void BColorControl::_ReservedColorControl4() {} 870 871 872 BColorControl & 873 BColorControl::operator=(const BColorControl &) 874 { 875 return *this; 876 } 877