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