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 33namespace BPrivate { 34 35 36enum { 37 STATE_NONE = 0x0000, 38 STATE_PRESSED = 0x0002, 39 STATE_INSIDE = 0x0008, 40 STATE_FORCE_PRESSED = 0x0010, 41}; 42 43 44 45BIconButton::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 62BIconButton::~BIconButton() 63{ 64 _DeleteBitmaps(); 65} 66 67 68void 69BIconButton::MessageReceived(BMessage* message) 70{ 71 switch (message->what) { 72 default: 73 BView::MessageReceived(message); 74 break; 75 } 76} 77 78 79void 80BIconButton::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 93void 94BIconButton::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 132bool 133BIconButton::ShouldDrawBorder() const 134{ 135 return (IsEnabled() && (IsInside() || IsTracking())) 136 || _HasFlags(STATE_FORCE_PRESSED); 137} 138 139 140void 141BIconButton::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 149void 150BIconButton::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 158void 159BIconButton::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 177void 178BIconButton::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 194void 195BIconButton::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 217void 218BIconButton::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 250BSize 251BIconButton::MinSize() 252{ 253 BSize size; 254 GetPreferredSize(&size.width, &size.height); 255 return size; 256} 257 258 259BSize 260BIconButton::MaxSize() 261{ 262 return MinSize(); 263} 264 265 266status_t 267BIconButton::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 282void 283BIconButton::SetPressed(bool pressed) 284{ 285 _SetFlags(STATE_FORCE_PRESSED, pressed); 286} 287 288 289bool 290BIconButton::IsPressed() const 291{ 292 return _HasFlags(STATE_FORCE_PRESSED); 293} 294 295 296status_t 297BIconButton::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 const BRect bitmapRect(BPoint(0, 0), be_control_look->ComposeIconSize(32)); 314 BBitmap bitmap(bitmapRect, B_BITMAP_NO_SERVER_LINK, B_RGBA32); 315 status = bitmap.InitCheck(); 316 if (status != B_OK) 317 return status; 318 status = BIconUtils::GetVectorIcon(reinterpret_cast<const uint8*>(data), 319 size, &bitmap); 320 if (status != B_OK) 321 return status; 322 return SetIcon(&bitmap); 323 } 324// const void* data = resources.LoadResource(B_BITMAP_TYPE, resourceID, &size); 325 return B_ERROR; 326} 327 328 329status_t 330BIconButton::SetIcon(const char* pathToBitmap) 331{ 332 if (pathToBitmap == NULL) 333 return B_BAD_VALUE; 334 335 status_t status = B_BAD_VALUE; 336 BBitmap* fileBitmap = NULL; 337 // try to load bitmap from either relative or absolute path 338 BEntry entry(pathToBitmap, true); 339 if (!entry.Exists()) { 340 app_info info; 341 status = be_app->GetAppInfo(&info); 342 if (status == B_OK) { 343 BEntry app_entry(&info.ref, true); 344 BPath path; 345 app_entry.GetPath(&path); 346 status = path.InitCheck(); 347 if (status == B_OK) { 348 status = path.GetParent(&path); 349 if (status == B_OK) { 350 status = path.Append(pathToBitmap, true); 351 if (status == B_OK) 352 fileBitmap = BTranslationUtils::GetBitmap(path.Path()); 353 else { 354 printf("BIconButton::SetIcon() - path.Append() failed: " 355 "%s\n", strerror(status)); 356 } 357 } else { 358 printf("BIconButton::SetIcon() - path.GetParent() failed: " 359 "%s\n", strerror(status)); 360 } 361 } else { 362 printf("BIconButton::SetIcon() - path.InitCheck() failed: " 363 "%s\n", strerror(status)); 364 } 365 } else { 366 printf("BIconButton::SetIcon() - be_app->GetAppInfo() failed: " 367 "%s\n", strerror(status)); 368 } 369 } else 370 fileBitmap = BTranslationUtils::GetBitmap(pathToBitmap); 371 if (fileBitmap) { 372 status = _MakeBitmaps(fileBitmap); 373 delete fileBitmap; 374 } else 375 status = B_ERROR; 376 return status; 377} 378 379 380status_t 381BIconButton::SetIcon(const BBitmap* bitmap, uint32 flags) 382{ 383 if (bitmap && bitmap->ColorSpace() == B_CMAP8) { 384 status_t status = bitmap->InitCheck(); 385 if (status >= B_OK) { 386 if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap)) { 387 status = _MakeBitmaps(rgb32Bitmap); 388 delete rgb32Bitmap; 389 } else 390 status = B_NO_MEMORY; 391 } 392 return status; 393 } else 394 return _MakeBitmaps(bitmap); 395} 396 397 398status_t 399BIconButton::SetIcon(const BMimeType* fileType, bool small) 400{ 401 status_t status = fileType ? fileType->InitCheck() : B_BAD_VALUE; 402 if (status >= B_OK) { 403 BBitmap* mimeBitmap = new(std::nothrow) BBitmap(BRect(0.0, 0.0, 15.0, 404 15.0), B_CMAP8); 405 if (mimeBitmap && mimeBitmap->IsValid()) { 406 status = fileType->GetIcon(mimeBitmap, small ? B_MINI_ICON 407 : B_LARGE_ICON); 408 if (status >= B_OK) { 409 if (BBitmap* bitmap = _ConvertToRGB32(mimeBitmap)) { 410 status = _MakeBitmaps(bitmap); 411 delete bitmap; 412 } else { 413 printf("BIconButton::SetIcon() - B_RGB32 bitmap is not " 414 "valid\n"); 415 } 416 } else { 417 printf("BIconButton::SetIcon() - fileType->GetIcon() failed: " 418 "%s\n", strerror(status)); 419 } 420 } else 421 printf("BIconButton::SetIcon() - B_CMAP8 bitmap is not valid\n"); 422 delete mimeBitmap; 423 } else { 424 printf("BIconButton::SetIcon() - fileType is not valid: %s\n", 425 strerror(status)); 426 } 427 return status; 428} 429 430 431status_t 432BIconButton::SetIcon(const unsigned char* bitsFromQuickRes, 433 uint32 width, uint32 height, color_space format, bool convertToBW) 434{ 435 status_t status = B_BAD_VALUE; 436 if (bitsFromQuickRes && width > 0 && height > 0) { 437 BBitmap* quickResBitmap = new(std::nothrow) BBitmap(BRect(0.0, 0.0, 438 width - 1.0, height - 1.0), format); 439 status = quickResBitmap ? quickResBitmap->InitCheck() : B_ERROR; 440 if (status >= B_OK) { 441 // It doesn't look right to copy BitsLength() bytes, but bitmaps 442 // exported from QuickRes still contain their padding, so it is 443 // all right. 444 memcpy(quickResBitmap->Bits(), bitsFromQuickRes, 445 quickResBitmap->BitsLength()); 446 if (format != B_RGB32 && format != B_RGBA32 447 && format != B_RGB32_BIG && format != B_RGBA32_BIG) { 448 // colorspace needs conversion 449 BBitmap* bitmap = new(std::nothrow) BBitmap( 450 quickResBitmap->Bounds(), B_RGB32, true); 451 if (bitmap && bitmap->IsValid()) { 452 if (bitmap->Lock()) { 453 BView* helper = new BView(bitmap->Bounds(), "helper", 454 B_FOLLOW_NONE, B_WILL_DRAW); 455 bitmap->AddChild(helper); 456 helper->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 457 helper->FillRect(helper->Bounds()); 458 helper->SetDrawingMode(B_OP_OVER); 459 helper->DrawBitmap(quickResBitmap, BPoint(0.0, 0.0)); 460 helper->Sync(); 461 bitmap->Unlock(); 462 } 463 status = _MakeBitmaps(bitmap); 464 } else { 465 printf("BIconButton::SetIcon() - B_RGB32 bitmap is not " 466 "valid\n"); 467 } 468 delete bitmap; 469 } else { 470 // native colorspace (32 bits) 471 if (convertToBW) { 472 // convert to gray scale icon 473 uint8* bits = (uint8*)quickResBitmap->Bits(); 474 uint32 bpr = quickResBitmap->BytesPerRow(); 475 for (uint32 y = 0; y < height; y++) { 476 uint8* handle = bits; 477 uint8 gray; 478 for (uint32 x = 0; x < width; x++) { 479 gray = uint8((116 * handle[0] + 600 * handle[1] 480 + 308 * handle[2]) / 1024); 481 handle[0] = gray; 482 handle[1] = gray; 483 handle[2] = gray; 484 handle += 4; 485 } 486 bits += bpr; 487 } 488 } 489 status = _MakeBitmaps(quickResBitmap); 490 } 491 } else { 492 printf("BIconButton::SetIcon() - error allocating bitmap: " 493 "%s\n", strerror(status)); 494 } 495 delete quickResBitmap; 496 } 497 return status; 498} 499 500 501void 502BIconButton::ClearIcon() 503{ 504 _DeleteBitmaps(); 505 _Update(); 506} 507 508 509void 510BIconButton::TrimIcon(bool keepAspect) 511{ 512 if (fNormalBitmap == NULL) 513 return; 514 515 uint8* bits = (uint8*)fNormalBitmap->Bits(); 516 uint32 bpr = fNormalBitmap->BytesPerRow(); 517 uint32 width = fNormalBitmap->Bounds().IntegerWidth() + 1; 518 uint32 height = fNormalBitmap->Bounds().IntegerHeight() + 1; 519 BRect trimmed(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN); 520 for (uint32 y = 0; y < height; y++) { 521 uint8* b = bits + 3; 522 bool rowHasAlpha = false; 523 for (uint32 x = 0; x < width; x++) { 524 if (*b) { 525 rowHasAlpha = true; 526 if (x < trimmed.left) 527 trimmed.left = x; 528 if (x > trimmed.right) 529 trimmed.right = x; 530 } 531 b += 4; 532 } 533 if (rowHasAlpha) { 534 if (y < trimmed.top) 535 trimmed.top = y; 536 if (y > trimmed.bottom) 537 trimmed.bottom = y; 538 } 539 bits += bpr; 540 } 541 if (!trimmed.IsValid()) 542 return; 543 if (keepAspect) { 544 float minInset = trimmed.left; 545 minInset = min_c(minInset, trimmed.top); 546 minInset = min_c(minInset, fNormalBitmap->Bounds().right 547 - trimmed.right); 548 minInset = min_c(minInset, fNormalBitmap->Bounds().bottom 549 - trimmed.bottom); 550 trimmed = fNormalBitmap->Bounds().InsetByCopy(minInset, minInset); 551 } 552 trimmed = trimmed & fNormalBitmap->Bounds(); 553 BBitmap trimmedBitmap(trimmed.OffsetToCopy(B_ORIGIN), 554 B_BITMAP_NO_SERVER_LINK, B_RGBA32); 555 bits = (uint8*)fNormalBitmap->Bits(); 556 bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top; 557 uint8* dst = (uint8*)trimmedBitmap.Bits(); 558 uint32 trimmedWidth = trimmedBitmap.Bounds().IntegerWidth() + 1; 559 uint32 trimmedHeight = trimmedBitmap.Bounds().IntegerHeight() + 1; 560 uint32 trimmedBPR = trimmedBitmap.BytesPerRow(); 561 for (uint32 y = 0; y < trimmedHeight; y++) { 562 memcpy(dst, bits, trimmedWidth * 4); 563 dst += trimmedBPR; 564 bits += bpr; 565 } 566 SetIcon(&trimmedBitmap); 567} 568 569 570bool 571BIconButton::IsValid() const 572{ 573 return (fNormalBitmap && fDisabledBitmap && fClickedBitmap 574 && fDisabledClickedBitmap 575 && fNormalBitmap->IsValid() 576 && fDisabledBitmap->IsValid() 577 && fClickedBitmap->IsValid() 578 && fDisabledClickedBitmap->IsValid()); 579} 580 581 582BBitmap* 583BIconButton::Bitmap() const 584{ 585 BBitmap* bitmap = NULL; 586 if (fNormalBitmap && fNormalBitmap->IsValid()) { 587 bitmap = new(std::nothrow) BBitmap(fNormalBitmap); 588 if (bitmap != NULL && bitmap->IsValid()) { 589 // TODO: remove this functionality when we use real transparent 590 // bitmaps 591 uint8* bits = (uint8*)bitmap->Bits(); 592 uint32 bpr = bitmap->BytesPerRow(); 593 uint32 width = bitmap->Bounds().IntegerWidth() + 1; 594 uint32 height = bitmap->Bounds().IntegerHeight() + 1; 595 color_space format = bitmap->ColorSpace(); 596 if (format == B_CMAP8) { 597 // replace gray with magic transparent index 598 } else if (format == B_RGB32) { 599 for (uint32 y = 0; y < height; y++) { 600 uint8* bitsHandle = bits; 601 for (uint32 x = 0; x < width; x++) { 602 if (bitsHandle[0] == 216 603 && bitsHandle[1] == 216 604 && bitsHandle[2] == 216) { 605 // make this pixel completely transparent 606 bitsHandle[3] = 0; 607 } 608 bitsHandle += 4; 609 } 610 bits += bpr; 611 } 612 } 613 } else { 614 delete bitmap; 615 bitmap = NULL; 616 } 617 } 618 return bitmap; 619} 620 621 622void 623BIconButton::SetValue(int32 value) 624{ 625 BControl::SetValue(value); 626 _SetFlags(STATE_PRESSED, value != 0); 627} 628 629 630void 631BIconButton::SetEnabled(bool enabled) 632{ 633 BControl::SetEnabled(enabled); 634 if (!enabled) { 635 SetInside(false); 636 _SetTracking(false); 637 } 638} 639 640 641// #pragma mark - protected 642 643 644bool 645BIconButton::IsInside() const 646{ 647 return _HasFlags(STATE_INSIDE); 648} 649 650 651void 652BIconButton::SetInside(bool inside) 653{ 654 _SetFlags(STATE_INSIDE, inside); 655} 656 657 658// #pragma mark - private 659 660 661BBitmap* 662BIconButton::_ConvertToRGB32(const BBitmap* bitmap) const 663{ 664 BBitmap* convertedBitmap = new(std::nothrow) BBitmap(bitmap->Bounds(), 665 B_BITMAP_ACCEPTS_VIEWS, B_RGBA32); 666 if (convertedBitmap && convertedBitmap->IsValid()) { 667 memset(convertedBitmap->Bits(), 0, convertedBitmap->BitsLength()); 668 if (convertedBitmap->Lock()) { 669 BView* helper = new BView(bitmap->Bounds(), "helper", 670 B_FOLLOW_NONE, B_WILL_DRAW); 671 convertedBitmap->AddChild(helper); 672 helper->SetDrawingMode(B_OP_OVER); 673 helper->DrawBitmap(bitmap, BPoint(0.0, 0.0)); 674 helper->Sync(); 675 convertedBitmap->Unlock(); 676 } 677 } else { 678 delete convertedBitmap; 679 convertedBitmap = NULL; 680 } 681 return convertedBitmap; 682} 683 684 685status_t 686BIconButton::_MakeBitmaps(const BBitmap* bitmap) 687{ 688 status_t status = bitmap ? bitmap->InitCheck() : B_BAD_VALUE; 689 if (status == B_OK) { 690 // make our own versions of the bitmap 691 BRect b(bitmap->Bounds()); 692 _DeleteBitmaps(); 693 color_space format = bitmap->ColorSpace(); 694 fNormalBitmap = new(std::nothrow) BBitmap(b, format); 695 fDisabledBitmap = new(std::nothrow) BBitmap(b, format); 696 fClickedBitmap = new(std::nothrow) BBitmap(b, format); 697 fDisabledClickedBitmap = new(std::nothrow) BBitmap(b, format); 698 if (IsValid()) { 699 // copy bitmaps from file bitmap 700 uint8* nBits = (uint8*)fNormalBitmap->Bits(); 701 uint8* dBits = (uint8*)fDisabledBitmap->Bits(); 702 uint8* cBits = (uint8*)fClickedBitmap->Bits(); 703 uint8* dcBits = (uint8*)fDisabledClickedBitmap->Bits(); 704 uint8* fBits = (uint8*)bitmap->Bits(); 705 int32 nbpr = fNormalBitmap->BytesPerRow(); 706 int32 fbpr = bitmap->BytesPerRow(); 707 int32 pixels = b.IntegerWidth() + 1; 708 int32 lines = b.IntegerHeight() + 1; 709 // nontransparent version: 710 if (format == B_RGB32 || format == B_RGB32_BIG) { 711 // iterate over color components 712 for (int32 y = 0; y < lines; y++) { 713 for (int32 x = 0; x < pixels; x++) { 714 int32 nOffset = 4 * x; 715 int32 fOffset = 4 * x; 716 nBits[nOffset + 0] = fBits[fOffset + 0]; 717 nBits[nOffset + 1] = fBits[fOffset + 1]; 718 nBits[nOffset + 2] = fBits[fOffset + 2]; 719 nBits[nOffset + 3] = 255; 720 // clicked bits are darker (lame method...) 721 cBits[nOffset + 0] = (uint8)((float)nBits[nOffset + 0] 722 * 0.8); 723 cBits[nOffset + 1] = (uint8)((float)nBits[nOffset + 1] 724 * 0.8); 725 cBits[nOffset + 2] = (uint8)((float)nBits[nOffset + 2] 726 * 0.8); 727 cBits[nOffset + 3] = 255; 728 // disabled bits have less contrast (lame method...) 729 uint8 grey = 216; 730 float dist = (nBits[nOffset + 0] - grey) * 0.4; 731 dBits[nOffset + 0] = (uint8)(grey + dist); 732 dist = (nBits[nOffset + 1] - grey) * 0.4; 733 dBits[nOffset + 1] = (uint8)(grey + dist); 734 dist = (nBits[nOffset + 2] - grey) * 0.4; 735 dBits[nOffset + 2] = (uint8)(grey + dist); 736 dBits[nOffset + 3] = 255; 737 // disabled bits have less contrast (lame method...) 738 grey = 188; 739 dist = (nBits[nOffset + 0] - grey) * 0.4; 740 dcBits[nOffset + 0] = (uint8)(grey + dist); 741 dist = (nBits[nOffset + 1] - grey) * 0.4; 742 dcBits[nOffset + 1] = (uint8)(grey + dist); 743 dist = (nBits[nOffset + 2] - grey) * 0.4; 744 dcBits[nOffset + 2] = (uint8)(grey + dist); 745 dcBits[nOffset + 3] = 255; 746 } 747 nBits += nbpr; 748 dBits += nbpr; 749 cBits += nbpr; 750 dcBits += nbpr; 751 fBits += fbpr; 752 } 753 // transparent version: 754 } else if (format == B_RGBA32 || format == B_RGBA32_BIG) { 755 // iterate over color components 756 for (int32 y = 0; y < lines; y++) { 757 for (int32 x = 0; x < pixels; x++) { 758 int32 nOffset = 4 * x; 759 int32 fOffset = 4 * x; 760 nBits[nOffset + 0] = fBits[fOffset + 0]; 761 nBits[nOffset + 1] = fBits[fOffset + 1]; 762 nBits[nOffset + 2] = fBits[fOffset + 2]; 763 nBits[nOffset + 3] = fBits[fOffset + 3]; 764 // clicked bits are darker (lame method...) 765 cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8); 766 cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); 767 cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); 768 cBits[nOffset + 3] = fBits[fOffset + 3]; 769 // disabled bits have less opacity 770 771 uint8 grey = ((uint16)nBits[nOffset + 0] * 10 772 + nBits[nOffset + 1] * 60 773 + nBits[nOffset + 2] * 30) / 100; 774 float dist = (nBits[nOffset + 0] - grey) * 0.3; 775 dBits[nOffset + 0] = (uint8)(grey + dist); 776 dist = (nBits[nOffset + 1] - grey) * 0.3; 777 dBits[nOffset + 1] = (uint8)(grey + dist); 778 dist = (nBits[nOffset + 2] - grey) * 0.3; 779 dBits[nOffset + 2] = (uint8)(grey + dist); 780 dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); 781 // disabled bits have less contrast (lame method...) 782 dcBits[nOffset + 0] = (uint8)(dBits[nOffset + 0] * 0.8); 783 dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8); 784 dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8); 785 dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); 786 } 787 nBits += nbpr; 788 dBits += nbpr; 789 cBits += nbpr; 790 dcBits += nbpr; 791 fBits += fbpr; 792 } 793 // unsupported format 794 } else { 795 printf("BIconButton::_MakeBitmaps() - bitmap has unsupported " 796 "colorspace\n"); 797 status = B_MISMATCHED_VALUES; 798 _DeleteBitmaps(); 799 } 800 } else { 801 printf("BIconButton::_MakeBitmaps() - error allocating local " 802 "bitmaps\n"); 803 status = B_NO_MEMORY; 804 _DeleteBitmaps(); 805 } 806 } else 807 printf("BIconButton::_MakeBitmaps() - bitmap is not valid\n"); 808 return status; 809} 810 811 812void 813BIconButton::_DeleteBitmaps() 814{ 815 delete fNormalBitmap; 816 fNormalBitmap = NULL; 817 delete fDisabledBitmap; 818 fDisabledBitmap = NULL; 819 delete fClickedBitmap; 820 fClickedBitmap = NULL; 821 delete fDisabledClickedBitmap; 822 fDisabledClickedBitmap = NULL; 823} 824 825 826void 827BIconButton::_Update() 828{ 829 if (LockLooper()) { 830 Invalidate(); 831 UnlockLooper(); 832 } 833} 834 835 836void 837BIconButton::_SetFlags(uint32 flags, bool set) 838{ 839 if (_HasFlags(flags) != set) { 840 if (set) 841 fButtonState |= flags; 842 else 843 fButtonState &= ~flags; 844 845 if ((flags & STATE_PRESSED) != 0) 846 SetValueNoUpdate(set ? B_CONTROL_ON : B_CONTROL_OFF); 847 _Update(); 848 } 849} 850 851 852bool 853BIconButton::_HasFlags(uint32 flags) const 854{ 855 return (fButtonState & flags) != 0; 856} 857 858 859//! This one calls _Update() if needed; BControl::SetTracking() isn't virtual. 860void 861BIconButton::_SetTracking(bool tracking) 862{ 863 if (IsTracking() == tracking) 864 return; 865 866 SetTracking(tracking); 867 _Update(); 868} 869 870 871} // namespace BPrivate 872