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