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