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