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