1 /* 2 * Copyright 2011 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * John Scipione, jscipione@gmail.com 7 */ 8 9 10 #include "ModifierKeysWindow.h" 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 #include <Catalog.h> 17 #include <FindDirectory.h> 18 #include <GroupLayout.h> 19 #include <GridLayoutBuilder.h> 20 #include <GroupLayoutBuilder.h> 21 #include <IconUtils.h> 22 #include <Locale.h> 23 #include <LayoutBuilder.h> 24 #include <MenuItem.h> 25 #include <Message.h> 26 #include <Path.h> 27 #include <Resources.h> 28 #include <Size.h> 29 30 #include "KeymapApplication.h" 31 32 33 #ifdef DEBUG_ALERT 34 # define FTRACE(x) fprintf(x) 35 #else 36 # define FTRACE(x) /* nothing */ 37 #endif 38 39 40 const rgb_color disabledColor = (rgb_color){128, 128, 128, 255}; 41 const rgb_color normalColor = (rgb_color){0, 0, 0, 255}; 42 43 enum { 44 SHIFT_KEY = 0x00000001, 45 CONTROL_KEY = 0x00000002, 46 OPTION_KEY = 0x00000004, 47 COMMAND_KEY = 0x00000008 48 }; 49 50 enum { 51 MENU_ITEM_SHIFT = 0, 52 MENU_ITEM_CONTROL, 53 MENU_ITEM_OPTION, 54 MENU_ITEM_COMMAND, 55 MENU_ITEM_SEPERATOR, 56 MENU_ITEM_DISABLED 57 }; 58 59 static const uint32 kMsgUpdateModifier = 'upmd'; 60 static const uint32 kMsgApplyModifiers = 'apmd'; 61 static const uint32 kMsgRevertModifiers = 'rvmd'; 62 63 64 #undef B_TRANSLATION_CONTEXT 65 #define B_TRANSLATION_CONTEXT "Modifier keys window" 66 67 68 ModifierKeysWindow::ModifierKeysWindow() 69 : 70 BWindow(BRect(0, 0, 360, 220), B_TRANSLATE("Modifier keys"), 71 B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE 72 | B_AUTO_UPDATE_SIZE_LIMITS) 73 { 74 get_key_map(&fCurrentMap, &fCurrentBuffer); 75 get_key_map(&fSavedMap, &fSavedBuffer); 76 77 BStringView* keyRole = new BStringView("key role", 78 B_TRANSLATE_COMMENT("Role", "As in the role of a modifier key")); 79 keyRole->SetAlignment(B_ALIGN_RIGHT); 80 keyRole->SetFont(be_bold_font); 81 82 BStringView* keyLabel = new BStringView("key label", 83 B_TRANSLATE_COMMENT("Key", "As in a computer keyboard key")); 84 keyLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 85 keyLabel->SetFont(be_bold_font); 86 87 fShiftStringView = new BStringView("shift", 88 B_TRANSLATE_COMMENT("Shift:", "Shift key role name")); 89 fShiftStringView->SetAlignment(B_ALIGN_RIGHT); 90 91 fControlStringView = new BStringView("control", 92 B_TRANSLATE_COMMENT("Control:", "Control key role name")); 93 fControlStringView->SetAlignment(B_ALIGN_RIGHT); 94 95 fOptionStringView = new BStringView("option", 96 B_TRANSLATE_COMMENT("Option:", "Option key role name")); 97 fOptionStringView->SetAlignment(B_ALIGN_RIGHT); 98 99 fCommandStringView = new BStringView("command", 100 B_TRANSLATE_COMMENT("Command:", "Command key role name")); 101 fCommandStringView->SetAlignment(B_ALIGN_RIGHT); 102 103 fShiftConflictView = new ConflictView("shift warning view"); 104 fShiftConflictView->SetExplicitMaxSize(BSize(15, 15)); 105 106 fControlConflictView = new ConflictView("control warning view"); 107 fControlConflictView->SetExplicitMaxSize(BSize(15, 15)); 108 109 fOptionConflictView = new ConflictView("option warning view"); 110 fOptionConflictView->SetExplicitMaxSize(BSize(15, 15)); 111 112 fCommandConflictView = new ConflictView("command warning view"); 113 fCommandConflictView->SetExplicitMaxSize(BSize(15, 15)); 114 115 fCancelButton = new BButton("cancelButton", B_TRANSLATE("Cancel"), 116 new BMessage(B_QUIT_REQUESTED)); 117 118 fRevertButton = new BButton("revertButton", B_TRANSLATE("Revert"), 119 new BMessage(kMsgRevertModifiers)); 120 fRevertButton->SetEnabled(false); 121 122 fOkButton = new BButton("okButton", B_TRANSLATE("Set modifier keys"), 123 new BMessage(kMsgApplyModifiers)); 124 fOkButton->MakeDefault(true); 125 126 // Build the layout 127 SetLayout(new BGroupLayout(B_VERTICAL)); 128 129 AddChild(BGroupLayoutBuilder(B_VERTICAL, 10) 130 .Add(BGridLayoutBuilder(10, 10) 131 .Add(keyRole, 0, 0) 132 .Add(keyLabel, 1, 0) 133 134 .Add(fShiftStringView, 0, 1) 135 .Add(_CreateShiftMenuField(), 1, 1) 136 .Add(fShiftConflictView, 2, 1) 137 138 .Add(fControlStringView, 0, 2) 139 .Add(_CreateControlMenuField(), 1, 2) 140 .Add(fControlConflictView, 2, 2) 141 142 .Add(fOptionStringView, 0, 3) 143 .Add(_CreateOptionMenuField(), 1, 3) 144 .Add(fOptionConflictView, 2, 3) 145 146 .Add(fCommandStringView, 0, 4) 147 .Add(_CreateCommandMenuField(), 1, 4) 148 .Add(fCommandConflictView, 2, 4) 149 ) 150 .AddGlue() 151 .AddGroup(B_HORIZONTAL, 10) 152 .Add(fCancelButton) 153 .AddGlue() 154 .Add(fRevertButton) 155 .Add(fOkButton) 156 .End() 157 .SetInsets(10, 10, 10, 10) 158 ); 159 160 _MarkMenuItems(); 161 _ValidateDuplicateKeys(); 162 163 CenterOnScreen(); 164 } 165 166 167 ModifierKeysWindow::~ModifierKeysWindow() 168 { 169 be_app->PostMessage(kMsgCloseModifierKeysWindow); 170 } 171 172 173 void 174 ModifierKeysWindow::MessageReceived(BMessage* message) 175 { 176 switch (message->what) { 177 case kMsgUpdateModifier: 178 { 179 int32 menuitem = MENU_ITEM_SHIFT; 180 int32 key = -1; 181 182 for (; menuitem <= MENU_ITEM_COMMAND; menuitem++) { 183 if (message->FindInt32(_KeyToString(menuitem), &key) == B_OK) 184 break; 185 } 186 187 if (key == -1) 188 return; 189 190 // menuitem contains the item we want to set 191 // key contains the item we want to set it to. 192 193 switch (menuitem) { 194 case MENU_ITEM_SHIFT: 195 fCurrentMap->left_shift_key = _KeyToKeyCode(key); 196 fCurrentMap->right_shift_key = _KeyToKeyCode(key, true); 197 break; 198 199 case MENU_ITEM_CONTROL: 200 fCurrentMap->left_control_key = _KeyToKeyCode(key); 201 fCurrentMap->right_control_key = _KeyToKeyCode(key, true); 202 break; 203 204 case MENU_ITEM_OPTION: 205 fCurrentMap->left_option_key = _KeyToKeyCode(key); 206 fCurrentMap->right_option_key = _KeyToKeyCode(key, true); 207 break; 208 209 case MENU_ITEM_COMMAND: 210 fCurrentMap->left_command_key = _KeyToKeyCode(key); 211 fCurrentMap->right_command_key = _KeyToKeyCode(key, true); 212 break; 213 } 214 215 _MarkMenuItems(); 216 _ValidateDuplicateKeys(); 217 218 // enable/disable revert button 219 fRevertButton->SetEnabled( 220 memcmp(fCurrentMap, fSavedMap, sizeof(key_map))); 221 break; 222 } 223 224 // OK button 225 case kMsgApplyModifiers: 226 { 227 // if duplicate modifiers are found, don't update 228 if (_DuplicateKeys() != 0) 229 break; 230 231 BMessage* updateModifiers = new BMessage(kMsgUpdateModifierKeys); 232 233 if (fCurrentMap->left_shift_key != fSavedMap->left_shift_key) { 234 updateModifiers->AddUInt32("left_shift_key", 235 fCurrentMap->left_shift_key); 236 } 237 238 if (fCurrentMap->right_shift_key != fSavedMap->right_shift_key) { 239 updateModifiers->AddUInt32("right_shift_key", 240 fCurrentMap->right_shift_key); 241 } 242 243 if (fCurrentMap->left_control_key != fSavedMap->left_control_key) { 244 updateModifiers->AddUInt32("left_control_key", 245 fCurrentMap->left_control_key); 246 } 247 248 if (fCurrentMap->right_control_key 249 != fSavedMap->right_control_key) { 250 updateModifiers->AddUInt32("right_control_key", 251 fCurrentMap->right_control_key); 252 } 253 254 if (fCurrentMap->left_option_key != fSavedMap->left_option_key) { 255 updateModifiers->AddUInt32("left_option_key", 256 fCurrentMap->left_option_key); 257 } 258 259 if (fCurrentMap->right_option_key != fSavedMap->right_option_key) { 260 updateModifiers->AddUInt32("right_option_key", 261 fCurrentMap->right_option_key); 262 } 263 264 if (fCurrentMap->left_command_key != fSavedMap->left_command_key) { 265 updateModifiers->AddUInt32("left_command_key", 266 fCurrentMap->left_command_key); 267 } 268 269 if (fCurrentMap->right_command_key 270 != fSavedMap->right_command_key) { 271 updateModifiers->AddUInt32("right_command_key", 272 fCurrentMap->right_command_key); 273 } 274 275 // KeymapWindow updates the modifiers 276 be_app->PostMessage(updateModifiers); 277 278 // we are done here, close the window 279 this->PostMessage(B_QUIT_REQUESTED); 280 break; 281 } 282 283 // Revert button 284 case kMsgRevertModifiers: 285 memcpy(fCurrentMap, fSavedMap, sizeof(key_map)); 286 287 _MarkMenuItems(); 288 _ValidateDuplicateKeys(); 289 290 fRevertButton->SetEnabled(false); 291 break; 292 293 default: 294 BWindow::MessageReceived(message); 295 } 296 } 297 298 299 // #pragma mark - 300 301 302 BMenuField* 303 ModifierKeysWindow::_CreateShiftMenuField() 304 { 305 fShiftMenu = new BPopUpMenu( 306 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_SHIFT)), true, true); 307 308 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) { 309 if (key == MENU_ITEM_SEPERATOR) { 310 // add separator item 311 BSeparatorItem* separator = new BSeparatorItem; 312 fShiftMenu->AddItem(separator, MENU_ITEM_SEPERATOR); 313 continue; 314 } 315 316 BMessage* message = new BMessage(kMsgUpdateModifier); 317 message->AddInt32(_KeyToString(MENU_ITEM_SHIFT), key); 318 BMenuItem* item = new BMenuItem( 319 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message); 320 321 fShiftMenu->AddItem(item, key); 322 } 323 fShiftMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, 324 B_ALIGN_VERTICAL_UNSET)); 325 326 return new BMenuField(NULL, fShiftMenu); 327 } 328 329 330 BMenuField* 331 ModifierKeysWindow::_CreateControlMenuField() 332 { 333 fControlMenu = new BPopUpMenu( 334 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_CONTROL)), true, true); 335 336 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) { 337 if (key == MENU_ITEM_SEPERATOR) { 338 // add separator item 339 BSeparatorItem* separator = new BSeparatorItem; 340 fControlMenu->AddItem(separator, MENU_ITEM_SEPERATOR); 341 continue; 342 } 343 344 BMessage* message = new BMessage(kMsgUpdateModifier); 345 message->AddInt32(_KeyToString(MENU_ITEM_CONTROL), key); 346 BMenuItem* item = new BMenuItem( 347 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message); 348 349 fControlMenu->AddItem(item, key); 350 } 351 fControlMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, 352 B_ALIGN_VERTICAL_UNSET)); 353 354 return new BMenuField(NULL, fControlMenu); 355 } 356 357 358 BMenuField* 359 ModifierKeysWindow::_CreateOptionMenuField() 360 { 361 fOptionMenu = new BPopUpMenu( 362 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_OPTION)), true, true); 363 364 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) { 365 if (key == MENU_ITEM_SEPERATOR) { 366 // add separator item 367 BSeparatorItem* separator = new BSeparatorItem; 368 fOptionMenu->AddItem(separator, MENU_ITEM_SEPERATOR); 369 continue; 370 } 371 372 BMessage* message = new BMessage(kMsgUpdateModifier); 373 message->AddInt32(_KeyToString(MENU_ITEM_OPTION), key); 374 BMenuItem* item = new BMenuItem( 375 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message); 376 377 fOptionMenu->AddItem(item, key); 378 } 379 fOptionMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, 380 B_ALIGN_VERTICAL_UNSET)); 381 382 return new BMenuField(NULL, fOptionMenu); 383 } 384 385 386 BMenuField* 387 ModifierKeysWindow::_CreateCommandMenuField() 388 { 389 fCommandMenu = new BPopUpMenu( 390 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_COMMAND)), true, true); 391 392 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) { 393 if (key == MENU_ITEM_SEPERATOR) { 394 // add separator item 395 BSeparatorItem* separator = new BSeparatorItem; 396 fCommandMenu->AddItem(separator, MENU_ITEM_SEPERATOR); 397 continue; 398 } 399 400 BMessage* message = new BMessage(kMsgUpdateModifier); 401 message->AddInt32(_KeyToString(MENU_ITEM_COMMAND), key); 402 BMenuItem* item = new BMenuItem( 403 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message); 404 fCommandMenu->AddItem(item, key); 405 } 406 fCommandMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, 407 B_ALIGN_VERTICAL_UNSET)); 408 409 return new BMenuField(NULL, fCommandMenu); 410 } 411 412 413 void 414 ModifierKeysWindow::_MarkMenuItems() 415 { 416 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) { 417 if (key == MENU_ITEM_SEPERATOR) 418 continue; 419 420 if (fCurrentMap->left_shift_key == _KeyToKeyCode(key) 421 && fCurrentMap->right_shift_key == _KeyToKeyCode(key, true)) { 422 fShiftMenu->ItemAt(key)->SetMarked(true); 423 424 if (key == MENU_ITEM_DISABLED) 425 fShiftStringView->SetHighColor(disabledColor); 426 else 427 fShiftStringView->SetHighColor(normalColor); 428 429 fShiftStringView->Invalidate(); 430 } 431 432 if (fCurrentMap->left_control_key == _KeyToKeyCode(key) 433 && fCurrentMap->right_control_key == _KeyToKeyCode(key, true)) { 434 fControlMenu->ItemAt(key)->SetMarked(true); 435 436 if (key == MENU_ITEM_DISABLED) 437 fControlStringView->SetHighColor(disabledColor); 438 else 439 fControlStringView->SetHighColor(normalColor); 440 441 fControlStringView->Invalidate(); 442 } 443 444 if (fCurrentMap->left_option_key == _KeyToKeyCode(key) 445 && fCurrentMap->right_option_key == _KeyToKeyCode(key, true)) { 446 fOptionMenu->ItemAt(key)->SetMarked(true); 447 448 if (key == MENU_ITEM_DISABLED) 449 fOptionStringView->SetHighColor(disabledColor); 450 else 451 fOptionStringView->SetHighColor(normalColor); 452 453 fOptionStringView->Invalidate(); 454 } 455 456 if (fCurrentMap->left_command_key == _KeyToKeyCode(key) 457 && fCurrentMap->right_command_key == _KeyToKeyCode(key, true)) { 458 fCommandMenu->ItemAt(key)->SetMarked(true); 459 460 if (key == MENU_ITEM_DISABLED) 461 fCommandStringView->SetHighColor(disabledColor); 462 else 463 fCommandStringView->SetHighColor(normalColor); 464 465 fCommandStringView->Invalidate(); 466 } 467 } 468 } 469 470 471 // get the string for a modifier key 472 const char* 473 ModifierKeysWindow::_KeyToString(int32 key) 474 { 475 switch (key) { 476 case MENU_ITEM_SHIFT: 477 return B_TRANSLATE_COMMENT("Shift key", 478 "Label of key above Ctrl, usually Shift"); 479 480 case MENU_ITEM_CONTROL: 481 return B_TRANSLATE_COMMENT("Ctrl key", 482 "Label of key farthest from the spacebar, usually Ctrl" 483 "e.g. Strg for German keyboard"); 484 485 case MENU_ITEM_OPTION: 486 return B_TRANSLATE_COMMENT("Win/Cmd key", 487 "Label of the \"Windows\" key (PC)/Command key (Mac)"); 488 489 case MENU_ITEM_COMMAND: 490 return B_TRANSLATE_COMMENT("Alt/Opt key", 491 "Label of Alt key (PC)/Option key (Mac)"); 492 493 case MENU_ITEM_DISABLED: 494 return B_TRANSLATE_COMMENT("Disabled", "Do nothing"); 495 } 496 497 return ""; 498 } 499 500 501 // get the keycode for a modifier key 502 uint32 503 ModifierKeysWindow::_KeyToKeyCode(int32 key, bool right) 504 { 505 switch (key) { 506 case MENU_ITEM_SHIFT: 507 if (right) 508 return 0x56; 509 return 0x4b; 510 511 case MENU_ITEM_CONTROL: 512 if (right) 513 return 0x60; 514 return 0x5c; 515 516 case MENU_ITEM_OPTION: 517 if (right) 518 return 0x67; 519 return 0x66; 520 521 case MENU_ITEM_COMMAND: 522 if (right) 523 return 0x5f; 524 return 0x5d; 525 526 case MENU_ITEM_DISABLED: 527 return 0; 528 } 529 530 return 0; 531 } 532 533 534 // validate duplicate keys 535 void 536 ModifierKeysWindow::_ValidateDuplicateKeys() 537 { 538 uint32 dupMask = _DuplicateKeys(); 539 540 BBitmap* shiftIcon = fShiftConflictView->Icon(); 541 BBitmap* controlIcon = fControlConflictView->Icon(); 542 BBitmap* optionIcon = fOptionConflictView->Icon(); 543 BBitmap* commandIcon = fCommandConflictView->Icon(); 544 545 if (dupMask != 0) { 546 fShiftConflictView->ShowIcon((dupMask & SHIFT_KEY) != 0); 547 fControlConflictView->ShowIcon((dupMask & CONTROL_KEY) != 0); 548 fOptionConflictView->ShowIcon((dupMask & OPTION_KEY) != 0); 549 fCommandConflictView->ShowIcon((dupMask & COMMAND_KEY) != 0); 550 551 fOkButton->SetEnabled(false); 552 } else { 553 fShiftConflictView->ShowIcon(false); 554 fControlConflictView->ShowIcon(false); 555 fOptionConflictView->ShowIcon(false); 556 fCommandConflictView->ShowIcon(false); 557 558 fOkButton->SetEnabled(true); 559 } 560 561 // if there was a change invalidate the view 562 if (shiftIcon != fShiftConflictView->Icon()) 563 fShiftConflictView->Invalidate(); 564 565 if (controlIcon != fControlConflictView->Icon()) 566 fControlConflictView->Invalidate(); 567 568 if (optionIcon != fOptionConflictView->Icon()) 569 fOptionConflictView->Invalidate(); 570 571 if (commandIcon != fCommandConflictView->Icon()) 572 fCommandConflictView->Invalidate(); 573 } 574 575 576 // return a mask marking which keys are duplicates of each other for 577 // validation. Control = 1, Option = 2, Command = 3 578 uint32 579 ModifierKeysWindow::_DuplicateKeys() 580 { 581 uint32 duplicateMask = 0; 582 583 for (int32 testKey = MENU_ITEM_SHIFT; testKey <= MENU_ITEM_COMMAND; 584 testKey++) { 585 uint32 testLeft = 0; 586 uint32 testRight = 0; 587 588 switch (testKey) { 589 case MENU_ITEM_SHIFT: 590 testLeft = fCurrentMap->left_shift_key; 591 testRight = fCurrentMap->right_shift_key; 592 break; 593 594 case MENU_ITEM_CONTROL: 595 testLeft = fCurrentMap->left_control_key; 596 testRight = fCurrentMap->right_control_key; 597 break; 598 599 case MENU_ITEM_OPTION: 600 testLeft = fCurrentMap->left_option_key; 601 testRight = fCurrentMap->right_option_key; 602 break; 603 604 case MENU_ITEM_COMMAND: 605 testLeft = fCurrentMap->left_command_key; 606 testRight = fCurrentMap->right_command_key; 607 break; 608 } 609 610 if (testLeft == 0 && testRight == 0) 611 continue; 612 613 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_COMMAND; key++) { 614 if (key == testKey) { 615 // skip over yourself 616 continue; 617 } 618 619 uint32 left = 0; 620 uint32 right = 0; 621 622 switch(key) { 623 case MENU_ITEM_SHIFT: 624 left = fCurrentMap->left_shift_key; 625 right = fCurrentMap->right_shift_key; 626 break; 627 628 case MENU_ITEM_CONTROL: 629 left = fCurrentMap->left_control_key; 630 right = fCurrentMap->right_control_key; 631 break; 632 633 case MENU_ITEM_OPTION: 634 left = fCurrentMap->left_option_key; 635 right = fCurrentMap->right_option_key; 636 break; 637 638 case MENU_ITEM_COMMAND: 639 left = fCurrentMap->left_command_key; 640 right = fCurrentMap->right_command_key; 641 break; 642 } 643 644 if (left == 0 && right == 0) 645 continue; 646 647 if (left == testLeft && right == testRight) { 648 duplicateMask |= 1 << testKey; 649 duplicateMask |= 1 << key; 650 } 651 } 652 } 653 654 return duplicateMask; 655 } 656 657 658 // #pragma mark - ConflictView 659 660 661 ConflictView::ConflictView(const char* name) 662 : 663 BView(BRect(0, 0, 15, 15), name, B_FOLLOW_NONE, B_WILL_DRAW), 664 fIcon(NULL), 665 fSavedIcon(NULL) 666 { 667 _FillSavedIcon(); 668 } 669 670 671 ConflictView::~ConflictView() 672 { 673 delete fSavedIcon; 674 } 675 676 677 void 678 ConflictView::Draw(BRect updateRect) 679 { 680 // Draw background 681 682 if (Parent()) 683 SetLowColor(Parent()->ViewColor()); 684 else 685 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 686 687 FillRect(updateRect, B_SOLID_LOW); 688 689 // Draw icon 690 if (fIcon == NULL) 691 return; 692 693 SetDrawingMode(B_OP_ALPHA); 694 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 695 DrawBitmapAsync(fIcon, BPoint(0, 0)); 696 } 697 698 699 // get the icon 700 BBitmap* 701 ConflictView::Icon() 702 { 703 return fIcon; 704 } 705 706 707 // show or hide the icon 708 void 709 ConflictView::ShowIcon(bool show) 710 { 711 if (show) 712 fIcon = fSavedIcon; 713 else 714 fIcon = NULL; 715 } 716 717 718 // #pragma mark - 719 720 721 // fill out the icon with the stop symbol from app_server 722 void 723 ConflictView::_FillSavedIcon() 724 { 725 // return if the fSavedIcon has already been filled out 726 if (fSavedIcon != NULL && fSavedIcon->InitCheck() == B_OK) 727 return; 728 729 BPath path; 730 status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path); 731 if (status < B_OK) { 732 FTRACE((stderr, 733 "_FillWarningIcon() - find_directory failed: %s\n", 734 strerror(status))); 735 delete fSavedIcon; 736 fSavedIcon = NULL; 737 return; 738 } 739 740 path.Append("app_server"); 741 BFile file; 742 status = file.SetTo(path.Path(), B_READ_ONLY); 743 if (status < B_OK) { 744 FTRACE((stderr, 745 "_FillWarningIcon() - BFile init failed: %s\n", 746 strerror(status))); 747 delete fSavedIcon; 748 fSavedIcon = NULL; 749 return; 750 } 751 752 BResources resources; 753 status = resources.SetTo(&file); 754 if (status < B_OK) { 755 FTRACE((stderr, 756 "_WarningIcon() - BResources init failed: %s\n", 757 strerror(status))); 758 delete fSavedIcon; 759 fSavedIcon = NULL; 760 return; 761 } 762 763 // Allocate the fSavedIcon bitmap 764 fSavedIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), 0, B_RGBA32); 765 if (fSavedIcon->InitCheck() < B_OK) { 766 FTRACE((stderr, "_WarningIcon() - No memory for warning bitmap\n")); 767 delete fSavedIcon; 768 fSavedIcon = NULL; 769 return; 770 } 771 772 // Load the raw stop icon data 773 size_t size = 0; 774 const uint8* rawIcon; 775 rawIcon = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, 776 "stop", &size); 777 778 // load vector warning icon into fSavedIcon 779 if (rawIcon == NULL 780 || BIconUtils::GetVectorIcon(rawIcon, size, fSavedIcon) < B_OK) { 781 delete fSavedIcon; 782 fSavedIcon = NULL; 783 } 784 } 785