1 /* 2 * Copyright 2006-2011, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * Axel Dörfler, axeld@pinc-software.de. 8 */ 9 10 11 #include "IconButton.h" 12 13 #include <new> 14 #include <stdio.h> 15 16 #include <Application.h> 17 #include <Bitmap.h> 18 #include <Control.h> 19 #include <ControlLook.h> 20 #include <Entry.h> 21 #include <IconUtils.h> 22 #include <Looper.h> 23 #include <Message.h> 24 #include <Mime.h> 25 #include <Path.h> 26 #include <Region.h> 27 #include <Resources.h> 28 #include <Roster.h> 29 #include <TranslationUtils.h> 30 #include <Window.h> 31 32 33 namespace BPrivate { 34 35 36 enum { 37 STATE_NONE = 0x0000, 38 STATE_PRESSED = 0x0002, 39 STATE_INSIDE = 0x0008, 40 STATE_FORCE_PRESSED = 0x0010, 41 }; 42 43 44 45 BIconButton::BIconButton(const char* name, const char* label, 46 BMessage* message, BHandler* target) 47 : 48 BControl(name, label, message, B_WILL_DRAW), 49 fButtonState(0), 50 fNormalBitmap(NULL), 51 fDisabledBitmap(NULL), 52 fClickedBitmap(NULL), 53 fDisabledClickedBitmap(NULL), 54 fTargetCache(target) 55 { 56 SetTarget(target); 57 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 58 SetViewColor(B_TRANSPARENT_32_BIT); 59 } 60 61 62 BIconButton::~BIconButton() 63 { 64 _DeleteBitmaps(); 65 } 66 67 68 void 69 BIconButton::MessageReceived(BMessage* message) 70 { 71 switch (message->what) { 72 default: 73 BView::MessageReceived(message); 74 break; 75 } 76 } 77 78 79 void 80 BIconButton::AttachedToWindow() 81 { 82 AdoptParentColors(); 83 84 if (ViewUIColor() != B_NO_COLOR) 85 SetLowUIColor(ViewUIColor()); 86 87 SetTarget(fTargetCache); 88 if (!Target()) 89 SetTarget(Window()); 90 } 91 92 93 void 94 BIconButton::Draw(BRect updateRect) 95 { 96 rgb_color background = LowColor(); 97 98 BRect r(Bounds()); 99 100 uint32 flags = 0; 101 BBitmap* bitmap = fNormalBitmap; 102 if (!IsEnabled()) { 103 flags |= BControlLook::B_DISABLED; 104 bitmap = fDisabledBitmap; 105 } 106 if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) 107 flags |= BControlLook::B_ACTIVATED; 108 109 if (ShouldDrawBorder()) { 110 DrawBorder(r, updateRect, background, flags); 111 DrawBackground(r, updateRect, background, flags); 112 } else { 113 SetHighColor(background); 114 FillRect(r); 115 } 116 117 if (bitmap && bitmap->IsValid()) { 118 if (bitmap->ColorSpace() == B_RGBA32 119 || bitmap->ColorSpace() == B_RGBA32_BIG) { 120 SetDrawingMode(B_OP_ALPHA); 121 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 122 } 123 float x = r.left + floorf((r.Width() 124 - bitmap->Bounds().Width()) / 2.0 + 0.5); 125 float y = r.top + floorf((r.Height() 126 - bitmap->Bounds().Height()) / 2.0 + 0.5); 127 DrawBitmap(bitmap, BPoint(x, y)); 128 } 129 } 130 131 132 bool 133 BIconButton::ShouldDrawBorder() const 134 { 135 return (IsEnabled() && (IsInside() || IsTracking())) 136 || _HasFlags(STATE_FORCE_PRESSED); 137 } 138 139 140 void 141 BIconButton::DrawBorder(BRect& frame, const BRect& updateRect, 142 const rgb_color& backgroundColor, uint32 flags) 143 { 144 be_control_look->DrawButtonFrame(this, frame, updateRect, backgroundColor, 145 backgroundColor, flags); 146 } 147 148 149 void 150 BIconButton::DrawBackground(BRect& frame, const BRect& updateRect, 151 const rgb_color& backgroundColor, uint32 flags) 152 { 153 be_control_look->DrawButtonBackground(this, frame, updateRect, 154 backgroundColor, flags); 155 } 156 157 158 void 159 BIconButton::MouseDown(BPoint where) 160 { 161 if (!IsValid()) 162 return; 163 164 if (IsEnabled()) { 165 if (Bounds().Contains(where)) { 166 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); 167 _SetFlags(STATE_PRESSED, true); 168 _SetTracking(true); 169 } else { 170 _SetFlags(STATE_PRESSED, false); 171 _SetTracking(false); 172 } 173 } 174 } 175 176 177 void 178 BIconButton::MouseUp(BPoint where) 179 { 180 if (!IsValid()) 181 return; 182 183 if (IsEnabled() && _HasFlags(STATE_PRESSED) 184 && Bounds().Contains(where)) { 185 Invoke(); 186 } else if (Bounds().Contains(where)) 187 SetInside(true); 188 189 _SetFlags(STATE_PRESSED, false); 190 _SetTracking(false); 191 } 192 193 194 void 195 BIconButton::MouseMoved(BPoint where, uint32 transit, const BMessage* message) 196 { 197 if (!IsValid()) 198 return; 199 200 uint32 buttons = 0; 201 Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); 202 // catch a mouse up event that we might have missed 203 if (!buttons && _HasFlags(STATE_PRESSED)) { 204 MouseUp(where); 205 return; 206 } 207 if (buttons != 0 && !IsTracking()) 208 return; 209 210 SetInside((transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW) 211 && IsEnabled()); 212 if (IsTracking()) 213 _SetFlags(STATE_PRESSED, Bounds().Contains(where)); 214 } 215 216 217 void 218 BIconButton::GetPreferredSize(float* width, float* height) 219 { 220 float minWidth = 0.0f; 221 float minHeight = 0.0f; 222 if (IsValid()) { 223 minWidth += fNormalBitmap->Bounds().IntegerWidth() + 1.0f; 224 minHeight += fNormalBitmap->Bounds().IntegerHeight() + 1.0f; 225 } 226 227 const float kMinSpace = 15.0f; 228 if (minWidth < kMinSpace) 229 minWidth = kMinSpace; 230 if (minHeight < kMinSpace) 231 minHeight = kMinSpace; 232 233 float hPadding = max_c(6.0f, ceilf(minHeight / 4.0f)); 234 float vPadding = max_c(6.0f, ceilf(minWidth / 4.0f)); 235 236 if (Label() != NULL && Label()[0] != '\0') { 237 font_height fh; 238 GetFontHeight(&fh); 239 minHeight += ceilf(fh.ascent + fh.descent) + vPadding; 240 minWidth += StringWidth(Label()) + vPadding; 241 } 242 243 if (width) 244 *width = minWidth + hPadding; 245 if (height) 246 *height = minHeight + vPadding; 247 } 248 249 250 BSize 251 BIconButton::MinSize() 252 { 253 BSize size; 254 GetPreferredSize(&size.width, &size.height); 255 return size; 256 } 257 258 259 BSize 260 BIconButton::MaxSize() 261 { 262 return MinSize(); 263 } 264 265 266 status_t 267 BIconButton::Invoke(BMessage* message) 268 { 269 if (message == NULL) 270 message = Message(); 271 if (message != NULL) { 272 BMessage clone(*message); 273 clone.AddInt64("be:when", system_time()); 274 clone.AddPointer("be:source", (BView*)this); 275 clone.AddInt32("be:value", Value()); 276 return BInvoker::Invoke(&clone); 277 } 278 return BInvoker::Invoke(message); 279 } 280 281 282 void 283 BIconButton::SetPressed(bool pressed) 284 { 285 _SetFlags(STATE_FORCE_PRESSED, pressed); 286 } 287 288 289 bool 290 BIconButton::IsPressed() const 291 { 292 return _HasFlags(STATE_FORCE_PRESSED); 293 } 294 295 296 status_t 297 BIconButton::SetIcon(int32 resourceID) 298 { 299 app_info info; 300 status_t status = be_app->GetAppInfo(&info); 301 if (status != B_OK) 302 return status; 303 304 BResources resources(&info.ref); 305 status = resources.InitCheck(); 306 if (status != B_OK) 307 return status; 308 309 size_t size; 310 const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, resourceID, 311 &size); 312 if (data != NULL) { 313 BBitmap bitmap(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_RGBA32); 314 status = bitmap.InitCheck(); 315 if (status != B_OK) 316 return status; 317 status = BIconUtils::GetVectorIcon(reinterpret_cast<const uint8*>(data), 318 size, &bitmap); 319 if (status != B_OK) 320 return status; 321 return SetIcon(&bitmap); 322 } 323 // const void* data = resources.LoadResource(B_BITMAP_TYPE, resourceID, &size); 324 return B_ERROR; 325 } 326 327 328 status_t 329 BIconButton::SetIcon(const char* pathToBitmap) 330 { 331 if (pathToBitmap == NULL) 332 return B_BAD_VALUE; 333 334 status_t status = B_BAD_VALUE; 335 BBitmap* fileBitmap = NULL; 336 // try to load bitmap from either relative or absolute path 337 BEntry entry(pathToBitmap, true); 338 if (!entry.Exists()) { 339 app_info info; 340 status = be_app->GetAppInfo(&info); 341 if (status == B_OK) { 342 BEntry app_entry(&info.ref, true); 343 BPath path; 344 app_entry.GetPath(&path); 345 status = path.InitCheck(); 346 if (status == B_OK) { 347 status = path.GetParent(&path); 348 if (status == B_OK) { 349 status = path.Append(pathToBitmap, true); 350 if (status == B_OK) 351 fileBitmap = BTranslationUtils::GetBitmap(path.Path()); 352 else { 353 printf("BIconButton::SetIcon() - path.Append() failed: " 354 "%s\n", strerror(status)); 355 } 356 } else { 357 printf("BIconButton::SetIcon() - path.GetParent() failed: " 358 "%s\n", strerror(status)); 359 } 360 } else { 361 printf("BIconButton::SetIcon() - path.InitCheck() failed: " 362 "%s\n", strerror(status)); 363 } 364 } else { 365 printf("BIconButton::SetIcon() - be_app->GetAppInfo() failed: " 366 "%s\n", strerror(status)); 367 } 368 } else 369 fileBitmap = BTranslationUtils::GetBitmap(pathToBitmap); 370 if (fileBitmap) { 371 status = _MakeBitmaps(fileBitmap); 372 delete fileBitmap; 373 } else 374 status = B_ERROR; 375 return status; 376 } 377 378 379 status_t 380 BIconButton::SetIcon(const BBitmap* bitmap, uint32 flags) 381 { 382 if (bitmap && bitmap->ColorSpace() == B_CMAP8) { 383 status_t status = bitmap->InitCheck(); 384 if (status >= B_OK) { 385 if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap)) { 386 status = _MakeBitmaps(rgb32Bitmap); 387 delete rgb32Bitmap; 388 } else 389 status = B_NO_MEMORY; 390 } 391 return status; 392 } else 393 return _MakeBitmaps(bitmap); 394 } 395 396 397 status_t 398 BIconButton::SetIcon(const BMimeType* fileType, bool small) 399 { 400 status_t status = fileType ? fileType->InitCheck() : B_BAD_VALUE; 401 if (status >= B_OK) { 402 BBitmap* mimeBitmap = new(std::nothrow) BBitmap(BRect(0.0, 0.0, 15.0, 403 15.0), B_CMAP8); 404 if (mimeBitmap && mimeBitmap->IsValid()) { 405 status = fileType->GetIcon(mimeBitmap, small ? B_MINI_ICON 406 : B_LARGE_ICON); 407 if (status >= B_OK) { 408 if (BBitmap* bitmap = _ConvertToRGB32(mimeBitmap)) { 409 status = _MakeBitmaps(bitmap); 410 delete bitmap; 411 } else { 412 printf("BIconButton::SetIcon() - B_RGB32 bitmap is not " 413 "valid\n"); 414 } 415 } else { 416 printf("BIconButton::SetIcon() - fileType->GetIcon() failed: " 417 "%s\n", strerror(status)); 418 } 419 } else 420 printf("BIconButton::SetIcon() - B_CMAP8 bitmap is not valid\n"); 421 delete mimeBitmap; 422 } else { 423 printf("BIconButton::SetIcon() - fileType is not valid: %s\n", 424 strerror(status)); 425 } 426 return status; 427 } 428 429 430 status_t 431 BIconButton::SetIcon(const unsigned char* bitsFromQuickRes, 432 uint32 width, uint32 height, color_space format, bool convertToBW) 433 { 434 status_t status = B_BAD_VALUE; 435 if (bitsFromQuickRes && width > 0 && height > 0) { 436 BBitmap* quickResBitmap = new(std::nothrow) BBitmap(BRect(0.0, 0.0, 437 width - 1.0, height - 1.0), format); 438 status = quickResBitmap ? quickResBitmap->InitCheck() : B_ERROR; 439 if (status >= B_OK) { 440 // It doesn't look right to copy BitsLength() bytes, but bitmaps 441 // exported from QuickRes still contain their padding, so it is 442 // all right. 443 memcpy(quickResBitmap->Bits(), bitsFromQuickRes, 444 quickResBitmap->BitsLength()); 445 if (format != B_RGB32 && format != B_RGBA32 446 && format != B_RGB32_BIG && format != B_RGBA32_BIG) { 447 // colorspace needs conversion 448 BBitmap* bitmap = new(std::nothrow) BBitmap( 449 quickResBitmap->Bounds(), B_RGB32, true); 450 if (bitmap && bitmap->IsValid()) { 451 if (bitmap->Lock()) { 452 BView* helper = new BView(bitmap->Bounds(), "helper", 453 B_FOLLOW_NONE, B_WILL_DRAW); 454 bitmap->AddChild(helper); 455 helper->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 456 helper->FillRect(helper->Bounds()); 457 helper->SetDrawingMode(B_OP_OVER); 458 helper->DrawBitmap(quickResBitmap, BPoint(0.0, 0.0)); 459 helper->Sync(); 460 bitmap->Unlock(); 461 } 462 status = _MakeBitmaps(bitmap); 463 } else { 464 printf("BIconButton::SetIcon() - B_RGB32 bitmap is not " 465 "valid\n"); 466 } 467 delete bitmap; 468 } else { 469 // native colorspace (32 bits) 470 if (convertToBW) { 471 // convert to gray scale icon 472 uint8* bits = (uint8*)quickResBitmap->Bits(); 473 uint32 bpr = quickResBitmap->BytesPerRow(); 474 for (uint32 y = 0; y < height; y++) { 475 uint8* handle = bits; 476 uint8 gray; 477 for (uint32 x = 0; x < width; x++) { 478 gray = uint8((116 * handle[0] + 600 * handle[1] 479 + 308 * handle[2]) / 1024); 480 handle[0] = gray; 481 handle[1] = gray; 482 handle[2] = gray; 483 handle += 4; 484 } 485 bits += bpr; 486 } 487 } 488 status = _MakeBitmaps(quickResBitmap); 489 } 490 } else { 491 printf("BIconButton::SetIcon() - error allocating bitmap: " 492 "%s\n", strerror(status)); 493 } 494 delete quickResBitmap; 495 } 496 return status; 497 } 498 499 500 void 501 BIconButton::ClearIcon() 502 { 503 _DeleteBitmaps(); 504 _Update(); 505 } 506 507 508 void 509 BIconButton::TrimIcon(bool keepAspect) 510 { 511 if (fNormalBitmap == NULL) 512 return; 513 514 uint8* bits = (uint8*)fNormalBitmap->Bits(); 515 uint32 bpr = fNormalBitmap->BytesPerRow(); 516 uint32 width = fNormalBitmap->Bounds().IntegerWidth() + 1; 517 uint32 height = fNormalBitmap->Bounds().IntegerHeight() + 1; 518 BRect trimmed(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN); 519 for (uint32 y = 0; y < height; y++) { 520 uint8* b = bits + 3; 521 bool rowHasAlpha = false; 522 for (uint32 x = 0; x < width; x++) { 523 if (*b) { 524 rowHasAlpha = true; 525 if (x < trimmed.left) 526 trimmed.left = x; 527 if (x > trimmed.right) 528 trimmed.right = x; 529 } 530 b += 4; 531 } 532 if (rowHasAlpha) { 533 if (y < trimmed.top) 534 trimmed.top = y; 535 if (y > trimmed.bottom) 536 trimmed.bottom = y; 537 } 538 bits += bpr; 539 } 540 if (!trimmed.IsValid()) 541 return; 542 if (keepAspect) { 543 float minInset = trimmed.left; 544 minInset = min_c(minInset, trimmed.top); 545 minInset = min_c(minInset, fNormalBitmap->Bounds().right 546 - trimmed.right); 547 minInset = min_c(minInset, fNormalBitmap->Bounds().bottom 548 - trimmed.bottom); 549 trimmed = fNormalBitmap->Bounds().InsetByCopy(minInset, minInset); 550 } 551 trimmed = trimmed & fNormalBitmap->Bounds(); 552 BBitmap trimmedBitmap(trimmed.OffsetToCopy(B_ORIGIN), 553 B_BITMAP_NO_SERVER_LINK, B_RGBA32); 554 bits = (uint8*)fNormalBitmap->Bits(); 555 bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top; 556 uint8* dst = (uint8*)trimmedBitmap.Bits(); 557 uint32 trimmedWidth = trimmedBitmap.Bounds().IntegerWidth() + 1; 558 uint32 trimmedHeight = trimmedBitmap.Bounds().IntegerHeight() + 1; 559 uint32 trimmedBPR = trimmedBitmap.BytesPerRow(); 560 for (uint32 y = 0; y < trimmedHeight; y++) { 561 memcpy(dst, bits, trimmedWidth * 4); 562 dst += trimmedBPR; 563 bits += bpr; 564 } 565 SetIcon(&trimmedBitmap); 566 } 567 568 569 bool 570 BIconButton::IsValid() const 571 { 572 return (fNormalBitmap && fDisabledBitmap && fClickedBitmap 573 && fDisabledClickedBitmap 574 && fNormalBitmap->IsValid() 575 && fDisabledBitmap->IsValid() 576 && fClickedBitmap->IsValid() 577 && fDisabledClickedBitmap->IsValid()); 578 } 579 580 581 BBitmap* 582 BIconButton::Bitmap() const 583 { 584 BBitmap* bitmap = NULL; 585 if (fNormalBitmap && fNormalBitmap->IsValid()) { 586 bitmap = new(std::nothrow) BBitmap(fNormalBitmap); 587 if (bitmap != NULL && bitmap->IsValid()) { 588 // TODO: remove this functionality when we use real transparent 589 // bitmaps 590 uint8* bits = (uint8*)bitmap->Bits(); 591 uint32 bpr = bitmap->BytesPerRow(); 592 uint32 width = bitmap->Bounds().IntegerWidth() + 1; 593 uint32 height = bitmap->Bounds().IntegerHeight() + 1; 594 color_space format = bitmap->ColorSpace(); 595 if (format == B_CMAP8) { 596 // replace gray with magic transparent index 597 } else if (format == B_RGB32) { 598 for (uint32 y = 0; y < height; y++) { 599 uint8* bitsHandle = bits; 600 for (uint32 x = 0; x < width; x++) { 601 if (bitsHandle[0] == 216 602 && bitsHandle[1] == 216 603 && bitsHandle[2] == 216) { 604 // make this pixel completely transparent 605 bitsHandle[3] = 0; 606 } 607 bitsHandle += 4; 608 } 609 bits += bpr; 610 } 611 } 612 } else { 613 delete bitmap; 614 bitmap = NULL; 615 } 616 } 617 return bitmap; 618 } 619 620 621 void 622 BIconButton::SetValue(int32 value) 623 { 624 BControl::SetValue(value); 625 _SetFlags(STATE_PRESSED, value != 0); 626 } 627 628 629 void 630 BIconButton::SetEnabled(bool enabled) 631 { 632 BControl::SetEnabled(enabled); 633 if (!enabled) { 634 SetInside(false); 635 _SetTracking(false); 636 } 637 } 638 639 640 // #pragma mark - protected 641 642 643 bool 644 BIconButton::IsInside() const 645 { 646 return _HasFlags(STATE_INSIDE); 647 } 648 649 650 void 651 BIconButton::SetInside(bool inside) 652 { 653 _SetFlags(STATE_INSIDE, inside); 654 } 655 656 657 // #pragma mark - private 658 659 660 BBitmap* 661 BIconButton::_ConvertToRGB32(const BBitmap* bitmap) const 662 { 663 BBitmap* convertedBitmap = new(std::nothrow) BBitmap(bitmap->Bounds(), 664 B_BITMAP_ACCEPTS_VIEWS, B_RGBA32); 665 if (convertedBitmap && convertedBitmap->IsValid()) { 666 memset(convertedBitmap->Bits(), 0, convertedBitmap->BitsLength()); 667 if (convertedBitmap->Lock()) { 668 BView* helper = new BView(bitmap->Bounds(), "helper", 669 B_FOLLOW_NONE, B_WILL_DRAW); 670 convertedBitmap->AddChild(helper); 671 helper->SetDrawingMode(B_OP_OVER); 672 helper->DrawBitmap(bitmap, BPoint(0.0, 0.0)); 673 helper->Sync(); 674 convertedBitmap->Unlock(); 675 } 676 } else { 677 delete convertedBitmap; 678 convertedBitmap = NULL; 679 } 680 return convertedBitmap; 681 } 682 683 684 status_t 685 BIconButton::_MakeBitmaps(const BBitmap* bitmap) 686 { 687 status_t status = bitmap ? bitmap->InitCheck() : B_BAD_VALUE; 688 if (status == B_OK) { 689 // make our own versions of the bitmap 690 BRect b(bitmap->Bounds()); 691 _DeleteBitmaps(); 692 color_space format = bitmap->ColorSpace(); 693 fNormalBitmap = new(std::nothrow) BBitmap(b, format); 694 fDisabledBitmap = new(std::nothrow) BBitmap(b, format); 695 fClickedBitmap = new(std::nothrow) BBitmap(b, format); 696 fDisabledClickedBitmap = new(std::nothrow) BBitmap(b, format); 697 if (IsValid()) { 698 // copy bitmaps from file bitmap 699 uint8* nBits = (uint8*)fNormalBitmap->Bits(); 700 uint8* dBits = (uint8*)fDisabledBitmap->Bits(); 701 uint8* cBits = (uint8*)fClickedBitmap->Bits(); 702 uint8* dcBits = (uint8*)fDisabledClickedBitmap->Bits(); 703 uint8* fBits = (uint8*)bitmap->Bits(); 704 int32 nbpr = fNormalBitmap->BytesPerRow(); 705 int32 fbpr = bitmap->BytesPerRow(); 706 int32 pixels = b.IntegerWidth() + 1; 707 int32 lines = b.IntegerHeight() + 1; 708 // nontransparent version: 709 if (format == B_RGB32 || format == B_RGB32_BIG) { 710 // iterate over color components 711 for (int32 y = 0; y < lines; y++) { 712 for (int32 x = 0; x < pixels; x++) { 713 int32 nOffset = 4 * x; 714 int32 fOffset = 4 * x; 715 nBits[nOffset + 0] = fBits[fOffset + 0]; 716 nBits[nOffset + 1] = fBits[fOffset + 1]; 717 nBits[nOffset + 2] = fBits[fOffset + 2]; 718 nBits[nOffset + 3] = 255; 719 // clicked bits are darker (lame method...) 720 cBits[nOffset + 0] = (uint8)((float)nBits[nOffset + 0] 721 * 0.8); 722 cBits[nOffset + 1] = (uint8)((float)nBits[nOffset + 1] 723 * 0.8); 724 cBits[nOffset + 2] = (uint8)((float)nBits[nOffset + 2] 725 * 0.8); 726 cBits[nOffset + 3] = 255; 727 // disabled bits have less contrast (lame method...) 728 uint8 grey = 216; 729 float dist = (nBits[nOffset + 0] - grey) * 0.4; 730 dBits[nOffset + 0] = (uint8)(grey + dist); 731 dist = (nBits[nOffset + 1] - grey) * 0.4; 732 dBits[nOffset + 1] = (uint8)(grey + dist); 733 dist = (nBits[nOffset + 2] - grey) * 0.4; 734 dBits[nOffset + 2] = (uint8)(grey + dist); 735 dBits[nOffset + 3] = 255; 736 // disabled bits have less contrast (lame method...) 737 grey = 188; 738 dist = (nBits[nOffset + 0] - grey) * 0.4; 739 dcBits[nOffset + 0] = (uint8)(grey + dist); 740 dist = (nBits[nOffset + 1] - grey) * 0.4; 741 dcBits[nOffset + 1] = (uint8)(grey + dist); 742 dist = (nBits[nOffset + 2] - grey) * 0.4; 743 dcBits[nOffset + 2] = (uint8)(grey + dist); 744 dcBits[nOffset + 3] = 255; 745 } 746 nBits += nbpr; 747 dBits += nbpr; 748 cBits += nbpr; 749 dcBits += nbpr; 750 fBits += fbpr; 751 } 752 // transparent version: 753 } else if (format == B_RGBA32 || format == B_RGBA32_BIG) { 754 // iterate over color components 755 for (int32 y = 0; y < lines; y++) { 756 for (int32 x = 0; x < pixels; x++) { 757 int32 nOffset = 4 * x; 758 int32 fOffset = 4 * x; 759 nBits[nOffset + 0] = fBits[fOffset + 0]; 760 nBits[nOffset + 1] = fBits[fOffset + 1]; 761 nBits[nOffset + 2] = fBits[fOffset + 2]; 762 nBits[nOffset + 3] = fBits[fOffset + 3]; 763 // clicked bits are darker (lame method...) 764 cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8); 765 cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); 766 cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); 767 cBits[nOffset + 3] = fBits[fOffset + 3]; 768 // disabled bits have less opacity 769 770 uint8 grey = ((uint16)nBits[nOffset + 0] * 10 771 + nBits[nOffset + 1] * 60 772 + nBits[nOffset + 2] * 30) / 100; 773 float dist = (nBits[nOffset + 0] - grey) * 0.3; 774 dBits[nOffset + 0] = (uint8)(grey + dist); 775 dist = (nBits[nOffset + 1] - grey) * 0.3; 776 dBits[nOffset + 1] = (uint8)(grey + dist); 777 dist = (nBits[nOffset + 2] - grey) * 0.3; 778 dBits[nOffset + 2] = (uint8)(grey + dist); 779 dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); 780 // disabled bits have less contrast (lame method...) 781 dcBits[nOffset + 0] = (uint8)(dBits[nOffset + 0] * 0.8); 782 dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8); 783 dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8); 784 dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); 785 } 786 nBits += nbpr; 787 dBits += nbpr; 788 cBits += nbpr; 789 dcBits += nbpr; 790 fBits += fbpr; 791 } 792 // unsupported format 793 } else { 794 printf("BIconButton::_MakeBitmaps() - bitmap has unsupported " 795 "colorspace\n"); 796 status = B_MISMATCHED_VALUES; 797 _DeleteBitmaps(); 798 } 799 } else { 800 printf("BIconButton::_MakeBitmaps() - error allocating local " 801 "bitmaps\n"); 802 status = B_NO_MEMORY; 803 _DeleteBitmaps(); 804 } 805 } else 806 printf("BIconButton::_MakeBitmaps() - bitmap is not valid\n"); 807 return status; 808 } 809 810 811 void 812 BIconButton::_DeleteBitmaps() 813 { 814 delete fNormalBitmap; 815 fNormalBitmap = NULL; 816 delete fDisabledBitmap; 817 fDisabledBitmap = NULL; 818 delete fClickedBitmap; 819 fClickedBitmap = NULL; 820 delete fDisabledClickedBitmap; 821 fDisabledClickedBitmap = NULL; 822 } 823 824 825 void 826 BIconButton::_Update() 827 { 828 if (LockLooper()) { 829 Invalidate(); 830 UnlockLooper(); 831 } 832 } 833 834 835 void 836 BIconButton::_SetFlags(uint32 flags, bool set) 837 { 838 if (_HasFlags(flags) != set) { 839 if (set) 840 fButtonState |= flags; 841 else 842 fButtonState &= ~flags; 843 844 if ((flags & STATE_PRESSED) != 0) 845 SetValueNoUpdate(set ? B_CONTROL_ON : B_CONTROL_OFF); 846 _Update(); 847 } 848 } 849 850 851 bool 852 BIconButton::_HasFlags(uint32 flags) const 853 { 854 return (fButtonState & flags) != 0; 855 } 856 857 858 //! This one calls _Update() if needed; BControl::SetTracking() isn't virtual. 859 void 860 BIconButton::_SetTracking(bool tracking) 861 { 862 if (IsTracking() == tracking) 863 return; 864 865 SetTracking(tracking); 866 _Update(); 867 } 868 869 870 } // namespace BPrivate 871