875 lines
21 KiB
C++
875 lines
21 KiB
C++
/*
|
|
* Copyright 2011-2014 Haiku, Inc. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* John Scipione, [email protected]
|
|
*/
|
|
|
|
|
|
#include "ModifierKeysWindow.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <Bitmap.h>
|
|
#include <Button.h>
|
|
#include <Catalog.h>
|
|
#include <CheckBox.h>
|
|
#include <ControlLook.h>
|
|
#include <FindDirectory.h>
|
|
#include <IconUtils.h>
|
|
#include <InterfaceDefs.h>
|
|
#include <LayoutBuilder.h>
|
|
#include <Locale.h>
|
|
#include <MenuField.h>
|
|
#include <MenuItem.h>
|
|
#include <Message.h>
|
|
#include <Path.h>
|
|
#include <PopUpMenu.h>
|
|
#include <Resources.h>
|
|
#include <SeparatorView.h>
|
|
#include <Size.h>
|
|
#include <StringView.h>
|
|
|
|
#include "KeymapApplication.h"
|
|
|
|
|
|
#ifdef DEBUG_ALERT
|
|
# define FTRACE(x) fprintf(x)
|
|
#else
|
|
# define FTRACE(x) /* nothing */
|
|
#endif
|
|
|
|
|
|
enum {
|
|
SHIFT_KEY = 0x00000001,
|
|
CONTROL_KEY = 0x00000002,
|
|
OPTION_KEY = 0x00000004,
|
|
COMMAND_KEY = 0x00000008
|
|
};
|
|
|
|
enum {
|
|
MENU_ITEM_SHIFT = 0,
|
|
MENU_ITEM_CONTROL,
|
|
MENU_ITEM_OPTION,
|
|
MENU_ITEM_COMMAND,
|
|
MENU_ITEM_SEPERATOR,
|
|
MENU_ITEM_DISABLED
|
|
};
|
|
|
|
|
|
static const uint32 kMsgHideShowIcons = 'icon';
|
|
static const uint32 kMsgUpdateModifier = 'upmd';
|
|
static const uint32 kMsgApplyModifiers = 'apmd';
|
|
static const uint32 kMsgRevertModifiers = 'rvmd';
|
|
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
#define B_TRANSLATION_CONTEXT "Modifier keys window"
|
|
|
|
|
|
// #pragma mark - ConflictView
|
|
|
|
|
|
ConflictView::ConflictView(const char* name)
|
|
:
|
|
BView(BRect(BPoint(0, 0), be_control_look->ComposeIconSize(B_MINI_ICON)),
|
|
name, B_FOLLOW_NONE, B_WILL_DRAW),
|
|
fIcon(NULL),
|
|
fStopIcon(NULL),
|
|
fWarnIcon(NULL)
|
|
{
|
|
_FillIcons();
|
|
}
|
|
|
|
|
|
ConflictView::~ConflictView()
|
|
{
|
|
delete fStopIcon;
|
|
delete fWarnIcon;
|
|
}
|
|
|
|
|
|
void
|
|
ConflictView::Draw(BRect updateRect)
|
|
{
|
|
// Draw background
|
|
if (Parent())
|
|
SetLowColor(Parent()->ViewColor());
|
|
else
|
|
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
|
|
FillRect(updateRect, B_SOLID_LOW);
|
|
|
|
if (fIcon == NULL)
|
|
return;
|
|
|
|
// Draw icon
|
|
SetDrawingMode(B_OP_ALPHA);
|
|
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
|
DrawBitmapAsync(fIcon, BPoint(0, 0));
|
|
}
|
|
|
|
|
|
// get the icon
|
|
BBitmap*
|
|
ConflictView::Icon()
|
|
{
|
|
return fIcon;
|
|
}
|
|
|
|
|
|
// show or hide the stop icon
|
|
void
|
|
ConflictView::SetStopIcon(bool show)
|
|
{
|
|
fIcon = show ? fStopIcon : NULL;
|
|
const char* tip = show ? B_TRANSLATE("Error: duplicate keys")
|
|
: NULL;
|
|
SetToolTip(tip);
|
|
}
|
|
|
|
|
|
// show or hide the warn icon
|
|
void
|
|
ConflictView::SetWarnIcon(bool show)
|
|
{
|
|
fIcon = show ? fWarnIcon : NULL;
|
|
const char* tip = show
|
|
? B_TRANSLATE("Warning: left and right key roles do not match")
|
|
: NULL;
|
|
SetToolTip(tip);
|
|
}
|
|
|
|
|
|
// #pragma mark - ConflictView private methods
|
|
|
|
|
|
// fill out the icons with the stop and warn symbols from app_server
|
|
void
|
|
ConflictView::_FillIcons()
|
|
{
|
|
// return if the icons have already been filled out
|
|
if (fStopIcon != NULL && fStopIcon->InitCheck() == B_OK
|
|
&& fWarnIcon != NULL && fWarnIcon->InitCheck() == B_OK) {
|
|
return;
|
|
}
|
|
|
|
BPath path;
|
|
status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
|
|
if (status < B_OK) {
|
|
FTRACE((stderr,
|
|
"_FillIcons() - find_directory failed: %s\n",
|
|
strerror(status)));
|
|
return;
|
|
}
|
|
|
|
path.Append("app_server");
|
|
BFile file;
|
|
status = file.SetTo(path.Path(), B_READ_ONLY);
|
|
if (status < B_OK) {
|
|
FTRACE((stderr,
|
|
"_FillIcons() - BFile init failed: %s\n",
|
|
strerror(status)));
|
|
return;
|
|
}
|
|
|
|
BResources resources;
|
|
status = resources.SetTo(&file);
|
|
if (status < B_OK) {
|
|
FTRACE((stderr,
|
|
"_FillIcons() - BResources init failed: %s\n",
|
|
strerror(status)));
|
|
return;
|
|
}
|
|
|
|
size_t size = 0;
|
|
|
|
if (fStopIcon == NULL) {
|
|
// Allocate the fStopIcon bitmap
|
|
fStopIcon = new (std::nothrow) BBitmap(Bounds(), 0,
|
|
B_RGBA32);
|
|
if (fStopIcon->InitCheck() != B_OK) {
|
|
FTRACE((stderr, "_FillIcons() - No memory for stop bitmap\n"));
|
|
delete fStopIcon;
|
|
fStopIcon = NULL;
|
|
return;
|
|
}
|
|
|
|
// load stop icon bitmap from app_server
|
|
const uint8* stopVector
|
|
= (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, "stop",
|
|
&size);
|
|
if (stopVector == NULL
|
|
|| BIconUtils::GetVectorIcon(stopVector, size, fStopIcon)
|
|
!= B_OK) {
|
|
delete fStopIcon;
|
|
fStopIcon = NULL;
|
|
}
|
|
}
|
|
|
|
if (fWarnIcon == NULL) {
|
|
// Allocate the fWarnIcon bitmap
|
|
fWarnIcon = new (std::nothrow) BBitmap(Bounds(), 0,
|
|
B_RGBA32);
|
|
if (fWarnIcon->InitCheck() != B_OK) {
|
|
FTRACE((stderr, "_FillIcons() - No memory for warn bitmap\n"));
|
|
delete fWarnIcon;
|
|
fWarnIcon = NULL;
|
|
return;
|
|
}
|
|
|
|
// load warn icon bitmap from app_server
|
|
const uint8* warnVector
|
|
= (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, "warn",
|
|
&size);
|
|
if (warnVector == NULL
|
|
|| BIconUtils::GetVectorIcon(warnVector, size, fWarnIcon)
|
|
!= B_OK) {
|
|
delete fWarnIcon;
|
|
fWarnIcon = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// #pragma mark - ModifierKeysWindow
|
|
|
|
|
|
ModifierKeysWindow::ModifierKeysWindow()
|
|
:
|
|
BWindow(BRect(0, 0, 360, 220), B_TRANSLATE("Modifier keys"),
|
|
B_FLOATING_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE
|
|
| B_AUTO_UPDATE_SIZE_LIMITS)
|
|
{
|
|
get_key_map(&fCurrentMap, &fCurrentBuffer);
|
|
get_key_map(&fSavedMap, &fSavedBuffer);
|
|
|
|
BStringView* keyRole = new BStringView("key role",
|
|
B_TRANSLATE_COMMENT("Role", "As in the role of a modifier key"));
|
|
keyRole->SetAlignment(B_ALIGN_RIGHT);
|
|
keyRole->SetFont(be_bold_font);
|
|
|
|
BStringView* keyLabel = new BStringView("key label",
|
|
B_TRANSLATE_COMMENT("Key", "As in a computer keyboard key"));
|
|
keyLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
|
|
keyLabel->SetFont(be_bold_font);
|
|
|
|
BMenuField* shiftMenuField = _CreateShiftMenuField();
|
|
shiftMenuField->SetAlignment(B_ALIGN_RIGHT);
|
|
|
|
BMenuField* controlMenuField = _CreateControlMenuField();
|
|
controlMenuField->SetAlignment(B_ALIGN_RIGHT);
|
|
|
|
BMenuField* optionMenuField = _CreateOptionMenuField();
|
|
optionMenuField->SetAlignment(B_ALIGN_RIGHT);
|
|
|
|
BMenuField* commandMenuField = _CreateCommandMenuField();
|
|
commandMenuField->SetAlignment(B_ALIGN_RIGHT);
|
|
|
|
fShiftConflictView = new ConflictView("shift warning view");
|
|
fShiftConflictView->SetExplicitMaxSize(fShiftConflictView->Bounds().Size());
|
|
|
|
fControlConflictView = new ConflictView("control warning view");
|
|
fControlConflictView->SetExplicitMaxSize(fControlConflictView->Bounds().Size());
|
|
|
|
fOptionConflictView = new ConflictView("option warning view");
|
|
fOptionConflictView->SetExplicitMaxSize(fOptionConflictView->Bounds().Size());
|
|
|
|
fCommandConflictView = new ConflictView("command warning view");
|
|
fCommandConflictView->SetExplicitMaxSize(fCommandConflictView->Bounds().Size());
|
|
|
|
fCancelButton = new BButton("cancelButton", B_TRANSLATE("Cancel"),
|
|
new BMessage(B_QUIT_REQUESTED));
|
|
|
|
fRevertButton = new BButton("revertButton", B_TRANSLATE("Revert"),
|
|
new BMessage(kMsgRevertModifiers));
|
|
fRevertButton->SetEnabled(false);
|
|
|
|
fOkButton = new BButton("okButton", B_TRANSLATE("Set modifier keys"),
|
|
new BMessage(kMsgApplyModifiers));
|
|
fOkButton->MakeDefault(true);
|
|
|
|
BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING)
|
|
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
|
|
.Add(keyRole, 0, 0)
|
|
.Add(keyLabel, 1, 0)
|
|
|
|
.Add(shiftMenuField->CreateLabelLayoutItem(), 0, 1)
|
|
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 1)
|
|
.Add(shiftMenuField->CreateMenuBarLayoutItem())
|
|
.Add(fShiftConflictView)
|
|
.End()
|
|
|
|
.Add(controlMenuField->CreateLabelLayoutItem(), 0, 2)
|
|
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 2)
|
|
.Add(controlMenuField->CreateMenuBarLayoutItem())
|
|
.Add(fControlConflictView)
|
|
.End()
|
|
|
|
.Add(optionMenuField->CreateLabelLayoutItem(), 0, 3)
|
|
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 3)
|
|
.Add(optionMenuField->CreateMenuBarLayoutItem())
|
|
.Add(fOptionConflictView)
|
|
.End()
|
|
|
|
.Add(commandMenuField->CreateLabelLayoutItem(), 0, 4)
|
|
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 4)
|
|
.Add(commandMenuField->CreateMenuBarLayoutItem())
|
|
.Add(fCommandConflictView)
|
|
.End()
|
|
.End()
|
|
.AddGlue()
|
|
.AddGroup(B_HORIZONTAL)
|
|
.Add(fCancelButton)
|
|
.AddGlue()
|
|
.Add(fRevertButton)
|
|
.Add(fOkButton)
|
|
.End()
|
|
.SetInsets(B_USE_WINDOW_SPACING)
|
|
.End();
|
|
|
|
_MarkMenuItems();
|
|
_ValidateDuplicateKeys();
|
|
|
|
PostMessage(kMsgHideShowIcons);
|
|
}
|
|
|
|
|
|
ModifierKeysWindow::~ModifierKeysWindow()
|
|
{
|
|
be_app->PostMessage(kMsgCloseModifierKeysWindow);
|
|
}
|
|
|
|
|
|
void
|
|
ModifierKeysWindow::MessageReceived(BMessage* message)
|
|
{
|
|
switch (message->what) {
|
|
case kMsgHideShowIcons:
|
|
_HideShowIcons();
|
|
break;
|
|
|
|
case kMsgUpdateModifier:
|
|
{
|
|
int32 menuitem = MENU_ITEM_SHIFT;
|
|
int32 key = -1;
|
|
|
|
for (; menuitem <= MENU_ITEM_COMMAND; menuitem++) {
|
|
if (message->FindInt32(_KeyToString(menuitem), &key) == B_OK)
|
|
break;
|
|
}
|
|
|
|
if (key == -1)
|
|
return;
|
|
|
|
// menuitem contains the item we want to set
|
|
// key contains the item we want to set it to.
|
|
|
|
switch (menuitem) {
|
|
case MENU_ITEM_SHIFT:
|
|
fCurrentMap->left_shift_key = _KeyToKeyCode(key);
|
|
fCurrentMap->right_shift_key = _KeyToKeyCode(key, true);
|
|
break;
|
|
|
|
case MENU_ITEM_CONTROL:
|
|
fCurrentMap->left_control_key = _KeyToKeyCode(key);
|
|
fCurrentMap->right_control_key = _KeyToKeyCode(key, true);
|
|
break;
|
|
|
|
case MENU_ITEM_OPTION:
|
|
fCurrentMap->left_option_key = _KeyToKeyCode(key);
|
|
fCurrentMap->right_option_key = _KeyToKeyCode(key, true);
|
|
break;
|
|
|
|
case MENU_ITEM_COMMAND:
|
|
fCurrentMap->left_command_key = _KeyToKeyCode(key);
|
|
fCurrentMap->right_command_key = _KeyToKeyCode(key, true);
|
|
break;
|
|
}
|
|
|
|
_MarkMenuItems();
|
|
_ValidateDuplicateKeys();
|
|
_HideShowIcons();
|
|
|
|
// enable/disable revert button
|
|
fRevertButton->SetEnabled(
|
|
memcmp(fCurrentMap, fSavedMap, sizeof(key_map)));
|
|
break;
|
|
}
|
|
|
|
// OK button
|
|
case kMsgApplyModifiers:
|
|
{
|
|
// if duplicate modifiers are found, don't update
|
|
if (_DuplicateKeys() != 0)
|
|
break;
|
|
|
|
BMessage* updateModifiers = new BMessage(kMsgUpdateModifierKeys);
|
|
|
|
if (fCurrentMap->left_shift_key != fSavedMap->left_shift_key) {
|
|
updateModifiers->AddUInt32("left_shift_key",
|
|
fCurrentMap->left_shift_key);
|
|
}
|
|
|
|
if (fCurrentMap->right_shift_key != fSavedMap->right_shift_key) {
|
|
updateModifiers->AddUInt32("right_shift_key",
|
|
fCurrentMap->right_shift_key);
|
|
}
|
|
|
|
if (fCurrentMap->left_control_key != fSavedMap->left_control_key) {
|
|
updateModifiers->AddUInt32("left_control_key",
|
|
fCurrentMap->left_control_key);
|
|
}
|
|
|
|
if (fCurrentMap->right_control_key
|
|
!= fSavedMap->right_control_key) {
|
|
updateModifiers->AddUInt32("right_control_key",
|
|
fCurrentMap->right_control_key);
|
|
}
|
|
|
|
if (fCurrentMap->left_option_key != fSavedMap->left_option_key) {
|
|
updateModifiers->AddUInt32("left_option_key",
|
|
fCurrentMap->left_option_key);
|
|
}
|
|
|
|
if (fCurrentMap->right_option_key != fSavedMap->right_option_key) {
|
|
updateModifiers->AddUInt32("right_option_key",
|
|
fCurrentMap->right_option_key);
|
|
}
|
|
|
|
if (fCurrentMap->left_command_key != fSavedMap->left_command_key) {
|
|
updateModifiers->AddUInt32("left_command_key",
|
|
fCurrentMap->left_command_key);
|
|
}
|
|
|
|
if (fCurrentMap->right_command_key
|
|
!= fSavedMap->right_command_key) {
|
|
updateModifiers->AddUInt32("right_command_key",
|
|
fCurrentMap->right_command_key);
|
|
}
|
|
|
|
// KeymapWindow updates the modifiers
|
|
be_app->PostMessage(updateModifiers);
|
|
|
|
// we are done here, close the window
|
|
this->PostMessage(B_QUIT_REQUESTED);
|
|
break;
|
|
}
|
|
|
|
// Revert button
|
|
case kMsgRevertModifiers:
|
|
memcpy(fCurrentMap, fSavedMap, sizeof(key_map));
|
|
|
|
_MarkMenuItems();
|
|
_ValidateDuplicateKeys();
|
|
_HideShowIcons();
|
|
|
|
fRevertButton->SetEnabled(false);
|
|
break;
|
|
|
|
default:
|
|
BWindow::MessageReceived(message);
|
|
}
|
|
}
|
|
|
|
|
|
// #pragma mark - ModifierKeysWindow private methods
|
|
|
|
|
|
BMenuField*
|
|
ModifierKeysWindow::_CreateShiftMenuField()
|
|
{
|
|
fShiftMenu = new BPopUpMenu(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_SHIFT)), true, true);
|
|
|
|
for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
|
|
if (key == MENU_ITEM_SEPERATOR) {
|
|
// add separator item
|
|
BSeparatorItem* separator = new BSeparatorItem;
|
|
fShiftMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
|
|
continue;
|
|
}
|
|
|
|
BMessage* message = new BMessage(kMsgUpdateModifier);
|
|
message->AddInt32(_KeyToString(MENU_ITEM_SHIFT), key);
|
|
BMenuItem* item = new BMenuItem(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
|
|
|
|
fShiftMenu->AddItem(item, key);
|
|
}
|
|
|
|
fShiftMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
|
|
B_ALIGN_VERTICAL_UNSET));
|
|
|
|
return new BMenuField(B_TRANSLATE_COMMENT("Shift:", "Shift key role name"),
|
|
fShiftMenu);
|
|
}
|
|
|
|
|
|
BMenuField*
|
|
ModifierKeysWindow::_CreateControlMenuField()
|
|
{
|
|
fControlMenu = new BPopUpMenu(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_CONTROL)), true, true);
|
|
|
|
for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
|
|
if (key == MENU_ITEM_SEPERATOR) {
|
|
// add separator item
|
|
BSeparatorItem* separator = new BSeparatorItem;
|
|
fControlMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
|
|
continue;
|
|
}
|
|
|
|
BMessage* message = new BMessage(kMsgUpdateModifier);
|
|
message->AddInt32(_KeyToString(MENU_ITEM_CONTROL), key);
|
|
BMenuItem* item = new BMenuItem(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
|
|
|
|
fControlMenu->AddItem(item, key);
|
|
}
|
|
|
|
fControlMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
|
|
B_ALIGN_VERTICAL_UNSET));
|
|
|
|
return new BMenuField(B_TRANSLATE_COMMENT("Control:",
|
|
"Control key role name"), fControlMenu);
|
|
}
|
|
|
|
|
|
BMenuField*
|
|
ModifierKeysWindow::_CreateOptionMenuField()
|
|
{
|
|
fOptionMenu = new BPopUpMenu(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_OPTION)), true, true);
|
|
|
|
for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
|
|
if (key == MENU_ITEM_SEPERATOR) {
|
|
// add separator item
|
|
BSeparatorItem* separator = new BSeparatorItem;
|
|
fOptionMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
|
|
continue;
|
|
}
|
|
|
|
BMessage* message = new BMessage(kMsgUpdateModifier);
|
|
message->AddInt32(_KeyToString(MENU_ITEM_OPTION), key);
|
|
BMenuItem* item = new BMenuItem(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
|
|
|
|
fOptionMenu->AddItem(item, key);
|
|
}
|
|
|
|
fOptionMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
|
|
B_ALIGN_VERTICAL_UNSET));
|
|
|
|
return new BMenuField(B_TRANSLATE_COMMENT("Option:",
|
|
"Option key role name"), fOptionMenu);
|
|
}
|
|
|
|
|
|
BMenuField*
|
|
ModifierKeysWindow::_CreateCommandMenuField()
|
|
{
|
|
fCommandMenu = new BPopUpMenu(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_COMMAND)), true, true);
|
|
|
|
for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
|
|
if (key == MENU_ITEM_SEPERATOR) {
|
|
// add separator item
|
|
BSeparatorItem* separator = new BSeparatorItem;
|
|
fCommandMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
|
|
continue;
|
|
}
|
|
|
|
BMessage* message = new BMessage(kMsgUpdateModifier);
|
|
message->AddInt32(_KeyToString(MENU_ITEM_COMMAND), key);
|
|
BMenuItem* item = new BMenuItem(
|
|
B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
|
|
fCommandMenu->AddItem(item, key);
|
|
}
|
|
|
|
fCommandMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
|
|
B_ALIGN_VERTICAL_UNSET));
|
|
|
|
return new BMenuField(B_TRANSLATE_COMMENT("Command:",
|
|
"Command key role name"), fCommandMenu);
|
|
}
|
|
|
|
|
|
void
|
|
ModifierKeysWindow::_MarkMenuItems()
|
|
{
|
|
for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
|
|
if (key == MENU_ITEM_SEPERATOR)
|
|
continue;
|
|
|
|
if (fCurrentMap->left_shift_key == _KeyToKeyCode(key)
|
|
&& fCurrentMap->right_shift_key == _KeyToKeyCode(key, true)) {
|
|
fShiftMenu->ItemAt(key)->SetMarked(true);
|
|
}
|
|
|
|
if (fCurrentMap->left_control_key == _KeyToKeyCode(key)
|
|
&& fCurrentMap->right_control_key == _KeyToKeyCode(key, true)) {
|
|
fControlMenu->ItemAt(key)->SetMarked(true);
|
|
}
|
|
|
|
if (fCurrentMap->left_option_key == _KeyToKeyCode(key)
|
|
&& fCurrentMap->right_option_key == _KeyToKeyCode(key, true)) {
|
|
fOptionMenu->ItemAt(key)->SetMarked(true);
|
|
}
|
|
|
|
if (fCurrentMap->left_command_key == _KeyToKeyCode(key)
|
|
&& fCurrentMap->right_command_key == _KeyToKeyCode(key, true)) {
|
|
fCommandMenu->ItemAt(key)->SetMarked(true);
|
|
}
|
|
}
|
|
|
|
// Set the warning icon if not marked
|
|
BBitmap* shiftIcon = fShiftConflictView->Icon();
|
|
BBitmap* controlIcon = fControlConflictView->Icon();
|
|
BBitmap* optionIcon = fOptionConflictView->Icon();
|
|
BBitmap* commandIcon = fCommandConflictView->Icon();
|
|
|
|
fShiftConflictView->SetWarnIcon(fShiftMenu->FindMarked() == NULL);
|
|
fControlConflictView->SetWarnIcon(fControlMenu->FindMarked() == NULL);
|
|
fOptionConflictView->SetWarnIcon(fOptionMenu->FindMarked() == NULL);
|
|
fCommandConflictView->SetWarnIcon(fCommandMenu->FindMarked() == NULL);
|
|
|
|
// if there was a change invalidate the view
|
|
if (shiftIcon != fShiftConflictView->Icon())
|
|
fShiftConflictView->Invalidate();
|
|
|
|
if (controlIcon != fControlConflictView->Icon())
|
|
fControlConflictView->Invalidate();
|
|
|
|
if (optionIcon != fOptionConflictView->Icon())
|
|
fOptionConflictView->Invalidate();
|
|
|
|
if (commandIcon != fCommandConflictView->Icon())
|
|
fCommandConflictView->Invalidate();
|
|
}
|
|
|
|
|
|
// get the string for a modifier key
|
|
const char*
|
|
ModifierKeysWindow::_KeyToString(int32 key)
|
|
{
|
|
switch (key) {
|
|
case MENU_ITEM_SHIFT:
|
|
return B_TRANSLATE_COMMENT("Shift key",
|
|
"Label of key above Ctrl, usually Shift");
|
|
|
|
case MENU_ITEM_CONTROL:
|
|
return B_TRANSLATE_COMMENT("Ctrl key",
|
|
"Label of key farthest from the spacebar, usually Ctrl"
|
|
"e.g. Strg for German keyboard");
|
|
|
|
case MENU_ITEM_OPTION:
|
|
return B_TRANSLATE_COMMENT("Win/Cmd key",
|
|
"Label of the \"Windows\" key (PC)/Command key (Mac)");
|
|
|
|
case MENU_ITEM_COMMAND:
|
|
return B_TRANSLATE_COMMENT("Alt/Opt key",
|
|
"Label of Alt key (PC)/Option key (Mac)");
|
|
|
|
case MENU_ITEM_DISABLED:
|
|
return B_TRANSLATE_COMMENT("Disabled", "Do nothing");
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
|
|
// get the keycode for a modifier key
|
|
uint32
|
|
ModifierKeysWindow::_KeyToKeyCode(int32 key, bool right)
|
|
{
|
|
switch (key) {
|
|
case MENU_ITEM_SHIFT:
|
|
if (right)
|
|
return 0x56;
|
|
return 0x4b;
|
|
|
|
case MENU_ITEM_CONTROL:
|
|
if (right)
|
|
return 0x60;
|
|
return 0x5c;
|
|
|
|
case MENU_ITEM_OPTION:
|
|
if (right)
|
|
return 0x67;
|
|
return 0x66;
|
|
|
|
case MENU_ITEM_COMMAND:
|
|
if (right)
|
|
return 0x5f;
|
|
return 0x5d;
|
|
|
|
case MENU_ITEM_DISABLED:
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// validate duplicate keys
|
|
void
|
|
ModifierKeysWindow::_ValidateDuplicateKeys()
|
|
{
|
|
uint32 dupMask = _DuplicateKeys();
|
|
|
|
BBitmap* shiftIcon = fShiftConflictView->Icon();
|
|
BBitmap* controlIcon = fControlConflictView->Icon();
|
|
BBitmap* optionIcon = fOptionConflictView->Icon();
|
|
BBitmap* commandIcon = fCommandConflictView->Icon();
|
|
|
|
if ((dupMask & SHIFT_KEY) != 0)
|
|
fShiftConflictView->SetStopIcon(true);
|
|
|
|
if ((dupMask & CONTROL_KEY) != 0)
|
|
fControlConflictView->SetStopIcon(true);
|
|
|
|
if ((dupMask & OPTION_KEY) != 0)
|
|
fOptionConflictView->SetStopIcon(true);
|
|
|
|
if ((dupMask & COMMAND_KEY) != 0)
|
|
fCommandConflictView->SetStopIcon(true);
|
|
|
|
fOkButton->SetEnabled(dupMask == 0);
|
|
|
|
// if there was a change invalidate the view
|
|
if (shiftIcon != fShiftConflictView->Icon())
|
|
fShiftConflictView->Invalidate();
|
|
|
|
if (controlIcon != fControlConflictView->Icon())
|
|
fControlConflictView->Invalidate();
|
|
|
|
if (optionIcon != fOptionConflictView->Icon())
|
|
fOptionConflictView->Invalidate();
|
|
|
|
if (commandIcon != fCommandConflictView->Icon())
|
|
fCommandConflictView->Invalidate();
|
|
}
|
|
|
|
|
|
// return a mask marking which keys are duplicates of each other for
|
|
// validation. Shift = 0, Control = 1, Option = 2, Command = 3
|
|
uint32
|
|
ModifierKeysWindow::_DuplicateKeys()
|
|
{
|
|
uint32 duplicateMask = 0;
|
|
|
|
for (int32 testKey = MENU_ITEM_SHIFT; testKey <= MENU_ITEM_COMMAND;
|
|
testKey++) {
|
|
uint32 testLeft = 0;
|
|
uint32 testRight = 0;
|
|
|
|
switch (testKey) {
|
|
case MENU_ITEM_SHIFT:
|
|
testLeft = fCurrentMap->left_shift_key;
|
|
testRight = fCurrentMap->right_shift_key;
|
|
break;
|
|
|
|
case MENU_ITEM_CONTROL:
|
|
testLeft = fCurrentMap->left_control_key;
|
|
testRight = fCurrentMap->right_control_key;
|
|
break;
|
|
|
|
case MENU_ITEM_OPTION:
|
|
testLeft = fCurrentMap->left_option_key;
|
|
testRight = fCurrentMap->right_option_key;
|
|
break;
|
|
|
|
case MENU_ITEM_COMMAND:
|
|
testLeft = fCurrentMap->left_command_key;
|
|
testRight = fCurrentMap->right_command_key;
|
|
break;
|
|
}
|
|
|
|
if (testLeft == 0 && testRight == 0)
|
|
continue;
|
|
|
|
for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_COMMAND; key++) {
|
|
if (key == testKey) {
|
|
// skip over yourself
|
|
continue;
|
|
}
|
|
|
|
uint32 left = 0;
|
|
uint32 right = 0;
|
|
|
|
switch (key) {
|
|
case MENU_ITEM_SHIFT:
|
|
left = fCurrentMap->left_shift_key;
|
|
right = fCurrentMap->right_shift_key;
|
|
break;
|
|
|
|
case MENU_ITEM_CONTROL:
|
|
left = fCurrentMap->left_control_key;
|
|
right = fCurrentMap->right_control_key;
|
|
break;
|
|
|
|
case MENU_ITEM_OPTION:
|
|
left = fCurrentMap->left_option_key;
|
|
right = fCurrentMap->right_option_key;
|
|
break;
|
|
|
|
case MENU_ITEM_COMMAND:
|
|
left = fCurrentMap->left_command_key;
|
|
right = fCurrentMap->right_command_key;
|
|
break;
|
|
}
|
|
|
|
if (left == 0 && right == 0)
|
|
continue;
|
|
|
|
if (left == testLeft || right == testRight) {
|
|
duplicateMask |= 1 << testKey;
|
|
duplicateMask |= 1 << key;
|
|
}
|
|
}
|
|
}
|
|
|
|
return duplicateMask;
|
|
}
|
|
|
|
|
|
void
|
|
ModifierKeysWindow::_HideShowIcons()
|
|
{
|
|
if (fShiftConflictView->Icon() == NULL) {
|
|
while (!fShiftConflictView->IsHidden())
|
|
fShiftConflictView->Hide();
|
|
} else {
|
|
while (fShiftConflictView->IsHidden())
|
|
fShiftConflictView->Show();
|
|
}
|
|
|
|
if (fControlConflictView->Icon() == NULL) {
|
|
while (!fControlConflictView->IsHidden())
|
|
fControlConflictView->Hide();
|
|
} else {
|
|
while (fControlConflictView->IsHidden())
|
|
fControlConflictView->Show();
|
|
}
|
|
|
|
if (fOptionConflictView->Icon() == NULL) {
|
|
while (!fOptionConflictView->IsHidden())
|
|
fOptionConflictView->Hide();
|
|
} else {
|
|
while (fOptionConflictView->IsHidden())
|
|
fOptionConflictView->Show();
|
|
}
|
|
|
|
if (fCommandConflictView->Icon() == NULL) {
|
|
while (!fCommandConflictView->IsHidden())
|
|
fCommandConflictView->Hide();
|
|
} else {
|
|
while (fCommandConflictView->IsHidden())
|
|
fCommandConflictView->Show();
|
|
}
|
|
}
|