Keymap: Put status icons inside menu fields
Draw warning and stop icons on top of the menu fields instead. Remove conflict views, create a new file to hold StatusMenuField and StatusMenuItem. Set the icon with them instead. Change-Id: If6c00199f24ac4f4fc789f12cc6cdcd7a912418f Reviewed-on: https://review.haiku-os.org/c/haiku/+/7209 Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk> Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
parent
f99596f4e3
commit
4fc18643b9
@ -18,6 +18,7 @@ Preference Keymap :
|
||||
KeymapListItem.cpp
|
||||
KeymapWindow.cpp
|
||||
ModifierKeysWindow.cpp
|
||||
StatusMenuField.cpp
|
||||
|
||||
: be tracker localestub shared [ TargetLibstdc++ ]
|
||||
: Keymap.rdef
|
||||
@ -29,4 +30,5 @@ DoCatalogs Keymap :
|
||||
KeyboardLayoutView.cpp
|
||||
KeymapWindow.cpp
|
||||
ModifierKeysWindow.cpp
|
||||
StatusMenuField.cpp
|
||||
;
|
||||
|
@ -14,14 +14,10 @@
|
||||
#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>
|
||||
@ -35,13 +31,7 @@
|
||||
#include <StringView.h>
|
||||
|
||||
#include "KeymapApplication.h"
|
||||
|
||||
|
||||
#ifdef DEBUG_ALERT
|
||||
# define FTRACE(x) fprintf(x)
|
||||
#else
|
||||
# define FTRACE(x) /* nothing */
|
||||
#endif
|
||||
#include "StatusMenuField.h"
|
||||
|
||||
|
||||
enum {
|
||||
@ -79,125 +69,6 @@ static const int32 kDisabled = -1;
|
||||
#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()
|
||||
{
|
||||
if (fStopIcon == NULL) {
|
||||
// Allocate the fStopIcon bitmap
|
||||
fStopIcon = new (std::nothrow) BBitmap(Bounds(), 0, B_RGBA32);
|
||||
if (fStopIcon == NULL || fStopIcon->InitCheck() != B_OK) {
|
||||
FTRACE((stderr, "_FillIcons() - No memory for stop bitmap\n"));
|
||||
delete fStopIcon;
|
||||
fStopIcon = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// load dialog-error icon bitmap
|
||||
if (BIconUtils::GetSystemIcon("dialog-error", fStopIcon) != B_OK) {
|
||||
delete fStopIcon;
|
||||
fStopIcon = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fWarnIcon == NULL) {
|
||||
// Allocate the fWarnIcon bitmap
|
||||
fWarnIcon = new (std::nothrow) BBitmap(Bounds(), 0, B_RGBA32);
|
||||
if (fWarnIcon == NULL || fWarnIcon->InitCheck() != B_OK) {
|
||||
FTRACE((stderr, "_FillIcons() - No memory for warn bitmap\n"));
|
||||
delete fWarnIcon;
|
||||
fWarnIcon = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// load dialog-warning icon bitmap
|
||||
if (BIconUtils::GetSystemIcon("dialog-warning", fWarnIcon) != B_OK) {
|
||||
delete fWarnIcon;
|
||||
fWarnIcon = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ModifierKeysWindow
|
||||
|
||||
|
||||
ModifierKeysWindow::ModifierKeysWindow()
|
||||
:
|
||||
BWindow(BRect(0, 0, 360, 220), B_TRANSLATE("Modifier keys"),
|
||||
@ -216,41 +87,17 @@ ModifierKeysWindow::ModifierKeysWindow()
|
||||
keyLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
|
||||
keyLabel->SetFont(be_bold_font);
|
||||
|
||||
BMenuField* capsMenuField;
|
||||
_CreateMenuField(&fCapsMenu, &capsMenuField, MENU_ITEM_CAPS,
|
||||
_CreateMenuField(&fCapsMenu, (BMenuField**)&fCapsField, MENU_ITEM_CAPS,
|
||||
B_TRANSLATE_COMMENT("Caps Lock:", "Caps Lock key role name"));
|
||||
|
||||
BMenuField* shiftMenuField;
|
||||
_CreateMenuField(&fShiftMenu, &shiftMenuField, MENU_ITEM_SHIFT,
|
||||
_CreateMenuField(&fShiftMenu, (BMenuField**)&fShiftField, MENU_ITEM_SHIFT,
|
||||
B_TRANSLATE_COMMENT("Shift:", "Shift key role name"));
|
||||
|
||||
BMenuField* controlMenuField;
|
||||
_CreateMenuField(&fControlMenu, &controlMenuField, MENU_ITEM_CONTROL,
|
||||
_CreateMenuField(&fControlMenu, (BMenuField**)&fControlField, MENU_ITEM_CONTROL,
|
||||
B_TRANSLATE_COMMENT("Control:", "Control key role name"));
|
||||
|
||||
BMenuField* optionMenuField;
|
||||
_CreateMenuField(&fOptionMenu, &optionMenuField, MENU_ITEM_OPTION,
|
||||
_CreateMenuField(&fOptionMenu,(BMenuField**) &fOptionField, MENU_ITEM_OPTION,
|
||||
B_TRANSLATE_COMMENT("Option:", "Option key role name"));
|
||||
|
||||
BMenuField* commandMenuField;
|
||||
_CreateMenuField(&fCommandMenu, &commandMenuField, MENU_ITEM_COMMAND,
|
||||
_CreateMenuField(&fCommandMenu, (BMenuField**)&fCommandField, MENU_ITEM_COMMAND,
|
||||
B_TRANSLATE_COMMENT("Command:", "Command key role name"));
|
||||
|
||||
fCapsConflictView = new ConflictView("caps lock warning view");
|
||||
fCapsConflictView->SetExplicitMaxSize(fCapsConflictView->Bounds().Size());
|
||||
|
||||
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));
|
||||
|
||||
@ -267,34 +114,29 @@ ModifierKeysWindow::ModifierKeysWindow()
|
||||
.Add(keyRole, 0, 0)
|
||||
.Add(keyLabel, 1, 0)
|
||||
|
||||
.Add(capsMenuField->CreateLabelLayoutItem(), 0, 1)
|
||||
.Add(fCapsField->CreateLabelLayoutItem(), 0, 1)
|
||||
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 1)
|
||||
.Add(capsMenuField->CreateMenuBarLayoutItem())
|
||||
.Add(fCapsConflictView)
|
||||
.Add(fCapsField->CreateMenuBarLayoutItem())
|
||||
.End()
|
||||
|
||||
.Add(shiftMenuField->CreateLabelLayoutItem(), 0, 2)
|
||||
.Add(fShiftField->CreateLabelLayoutItem(), 0, 2)
|
||||
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 2)
|
||||
.Add(shiftMenuField->CreateMenuBarLayoutItem())
|
||||
.Add(fShiftConflictView)
|
||||
.Add(fShiftField->CreateMenuBarLayoutItem())
|
||||
.End()
|
||||
|
||||
.Add(controlMenuField->CreateLabelLayoutItem(), 0, 3)
|
||||
.Add(fControlField->CreateLabelLayoutItem(), 0, 3)
|
||||
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 3)
|
||||
.Add(controlMenuField->CreateMenuBarLayoutItem())
|
||||
.Add(fControlConflictView)
|
||||
.Add(fControlField->CreateMenuBarLayoutItem())
|
||||
.End()
|
||||
|
||||
.Add(optionMenuField->CreateLabelLayoutItem(), 0, 4)
|
||||
.Add(fOptionField->CreateLabelLayoutItem(), 0, 4)
|
||||
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 4)
|
||||
.Add(optionMenuField->CreateMenuBarLayoutItem())
|
||||
.Add(fOptionConflictView)
|
||||
.Add(fOptionField->CreateMenuBarLayoutItem())
|
||||
.End()
|
||||
|
||||
.Add(commandMenuField->CreateLabelLayoutItem(), 0, 5)
|
||||
.Add(fCommandField->CreateLabelLayoutItem(), 0, 5)
|
||||
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 5)
|
||||
.Add(commandMenuField->CreateMenuBarLayoutItem())
|
||||
.Add(fCommandConflictView)
|
||||
.Add(fCommandField->CreateMenuBarLayoutItem())
|
||||
.End()
|
||||
|
||||
.End()
|
||||
@ -384,6 +226,9 @@ ModifierKeysWindow::MessageReceived(BMessage* message)
|
||||
|
||||
BMessage* updateModifiers = new BMessage(kMsgUpdateModifierKeys);
|
||||
|
||||
if (fCurrentMap->caps_key != fSavedMap->caps_key)
|
||||
updateModifiers->AddUInt32("caps_key", fCurrentMap->caps_key);
|
||||
|
||||
if (fCurrentMap->left_shift_key != fSavedMap->left_shift_key)
|
||||
updateModifiers->AddUInt32("left_shift_key", fCurrentMap->left_shift_key);
|
||||
|
||||
@ -408,9 +253,6 @@ ModifierKeysWindow::MessageReceived(BMessage* message)
|
||||
if (fCurrentMap->right_command_key != fSavedMap->right_command_key)
|
||||
updateModifiers->AddUInt32("right_command_key", fCurrentMap->right_command_key);
|
||||
|
||||
if (fCurrentMap->caps_key != fSavedMap->caps_key)
|
||||
updateModifiers->AddUInt32("caps_key", fCurrentMap->caps_key);
|
||||
|
||||
// KeymapWindow updates the modifiers
|
||||
be_app->PostMessage(updateModifiers);
|
||||
|
||||
@ -461,7 +303,7 @@ ModifierKeysWindow::_CreateMenuField(BPopUpMenu** _menu, BMenuField** _menuField
|
||||
|
||||
menu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_VERTICAL_UNSET));
|
||||
|
||||
BMenuField* menuField = new BMenuField(label, menu);
|
||||
BMenuField* menuField = new StatusMenuField(label, menu);
|
||||
menuField->SetAlignment(B_ALIGN_RIGHT);
|
||||
|
||||
*_menu = menu;
|
||||
@ -472,42 +314,41 @@ ModifierKeysWindow::_CreateMenuField(BPopUpMenu** _menu, BMenuField** _menuField
|
||||
void
|
||||
ModifierKeysWindow::_MarkMenuItems()
|
||||
{
|
||||
_MarkMenuItem(fCapsMenu, fCapsConflictView,
|
||||
fCurrentMap->caps_key, fCurrentMap->caps_key);
|
||||
_MarkMenuItem(fShiftMenu, fShiftConflictView,
|
||||
fCurrentMap->left_shift_key, fCurrentMap->right_shift_key);
|
||||
_MarkMenuItem(fControlMenu, fControlConflictView,
|
||||
fCurrentMap->left_control_key, fCurrentMap->right_control_key);
|
||||
_MarkMenuItem(fOptionMenu, fOptionConflictView,
|
||||
fCurrentMap->left_option_key, fCurrentMap->right_option_key);
|
||||
_MarkMenuItem(fCommandMenu, fCommandConflictView,
|
||||
fCurrentMap->left_command_key, fCurrentMap->right_command_key);
|
||||
_MarkMenuItem("caps lock", fCapsMenu, fCurrentMap->caps_key, fCurrentMap->caps_key);
|
||||
// mark but don't set unmatched for Caps Lock
|
||||
fShiftField->SetUnmatched(_MarkMenuItem("shift", fShiftMenu,
|
||||
fCurrentMap->left_shift_key, fCurrentMap->right_shift_key) == false);
|
||||
fControlField->SetUnmatched(_MarkMenuItem("control", fControlMenu,
|
||||
fCurrentMap->left_control_key, fCurrentMap->right_control_key) == false);
|
||||
fOptionField->SetUnmatched(_MarkMenuItem("option", fOptionMenu,
|
||||
fCurrentMap->left_option_key, fCurrentMap->right_option_key) == false);
|
||||
fCommandField->SetUnmatched(_MarkMenuItem("command", fCommandMenu,
|
||||
fCurrentMap->left_command_key, fCurrentMap->right_command_key) == false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModifierKeysWindow::_MarkMenuItem(BPopUpMenu* menu, ConflictView* conflictView,
|
||||
uint32 leftKey, uint32 rightKey)
|
||||
bool
|
||||
ModifierKeysWindow::_MarkMenuItem(const char* role, BPopUpMenu* menu, uint32 left, uint32 right)
|
||||
{
|
||||
for (int32 key = MENU_ITEM_FIRST; key <= MENU_ITEM_LAST; key++) {
|
||||
if (key == MENU_ITEM_SEPARATOR)
|
||||
continue;
|
||||
|
||||
if (leftKey == _KeyToKeyCode(key) && rightKey == _KeyToKeyCode(key, true))
|
||||
uint32 leftKey = _KeyToKeyCode(key);
|
||||
uint32 rightKey = _KeyToKeyCode(key, true);
|
||||
if (leftKey != rightKey && key == MENU_ITEM_CAPS) {
|
||||
// mark Caps Lock on Caps Lock role if either left or right is caps
|
||||
// otherwise mark Caps Lock if left side is caps
|
||||
uint32 capsKey = _KeyToKeyCode(MENU_ITEM_CAPS);
|
||||
if (strcmp(role, "caps lock") == 0 && (left == capsKey || right == capsKey))
|
||||
menu->ItemAt(key)->SetMarked(true);
|
||||
else if (left == capsKey)
|
||||
menu->ItemAt(key)->SetMarked(true);
|
||||
} else if (left == leftKey && right == rightKey)
|
||||
menu->ItemAt(key)->SetMarked(true);
|
||||
}
|
||||
|
||||
// no conflict
|
||||
if (menu->FindMarked() != NULL)
|
||||
return;
|
||||
|
||||
// set the warning icon
|
||||
BBitmap* icon = conflictView->Icon();
|
||||
conflictView->SetWarnIcon(icon == NULL);
|
||||
|
||||
// if there was a change invalidate the view
|
||||
if (icon != conflictView->Icon())
|
||||
conflictView->Invalidate();
|
||||
return menu->FindMarked() != NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -541,12 +382,12 @@ ModifierKeysWindow::_KeyToString(int32 key)
|
||||
return B_TRANSLATE_COMMENT("Disabled", "Do nothing");
|
||||
}
|
||||
|
||||
return "";
|
||||
return B_EMPTY_STRING;
|
||||
}
|
||||
|
||||
|
||||
// get the keycode for a modifier key
|
||||
uint32
|
||||
int32
|
||||
ModifierKeysWindow::_KeyToKeyCode(int32 key, bool right)
|
||||
{
|
||||
switch (key) {
|
||||
@ -586,23 +427,20 @@ void
|
||||
ModifierKeysWindow::_ValidateDuplicateKeys()
|
||||
{
|
||||
uint32 dupMask = _DuplicateKeys();
|
||||
_ValidateDuplicateKey(fCapsConflictView, CAPS_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fShiftConflictView, SHIFT_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fControlConflictView, CONTROL_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fOptionConflictView, OPTION_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fCommandConflictView, COMMAND_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fCapsField, CAPS_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fShiftField, SHIFT_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fControlField, CONTROL_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fOptionField, OPTION_KEY & dupMask);
|
||||
_ValidateDuplicateKey(fCommandField, COMMAND_KEY & dupMask);
|
||||
fOkButton->SetEnabled(dupMask == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModifierKeysWindow::_ValidateDuplicateKey(ConflictView* view, uint32 mask)
|
||||
ModifierKeysWindow::_ValidateDuplicateKey(StatusMenuField* field, uint32 mask)
|
||||
{
|
||||
BBitmap* icon = view->Icon();
|
||||
view->SetStopIcon(mask != 0);
|
||||
// if there was a change invalidate the view
|
||||
if (icon != view->Icon())
|
||||
view->Invalidate();
|
||||
if (mask != 0) // don't override if false
|
||||
field->SetDuplicate(true);
|
||||
}
|
||||
|
||||
|
||||
@ -687,6 +525,8 @@ ModifierKeysWindow::_DuplicateKeys()
|
||||
if (left == kUnset && (right == kUnset || right == kDisabled))
|
||||
continue;
|
||||
|
||||
// left or right is set
|
||||
|
||||
if (left == testLeft || right == testRight) {
|
||||
duplicateMask |= 1 << testKey;
|
||||
duplicateMask |= 1 << key;
|
||||
@ -698,34 +538,10 @@ ModifierKeysWindow::_DuplicateKeys()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModifierKeysWindow::_HideShowStatusIcons()
|
||||
{
|
||||
_ToggleStatusIcon(fCapsConflictView);
|
||||
_ToggleStatusIcon(fShiftConflictView);
|
||||
_ToggleStatusIcon(fControlConflictView);
|
||||
_ToggleStatusIcon(fOptionConflictView);
|
||||
_ToggleStatusIcon(fCommandConflictView);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModifierKeysWindow::_ToggleStatusIcon(ConflictView* view)
|
||||
{
|
||||
if (view->Icon() == NULL) {
|
||||
if (!view->IsHidden())
|
||||
view->Hide();
|
||||
} else {
|
||||
if (view->IsHidden())
|
||||
view->Show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModifierKeysWindow::_UpdateStatus()
|
||||
{
|
||||
_ValidateDuplicateKeys();
|
||||
// the order is important
|
||||
_MarkMenuItems();
|
||||
_HideShowStatusIcons();
|
||||
_ValidateDuplicateKeys();
|
||||
}
|
||||
|
@ -10,32 +10,13 @@
|
||||
#define MODIFIER_KEYS_WINDOW_H
|
||||
|
||||
|
||||
#include <View.h>
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
class BButton;
|
||||
class BMenuField;
|
||||
class BPopUpMenu;
|
||||
|
||||
|
||||
class ConflictView : public BView {
|
||||
public:
|
||||
ConflictView(const char* name);
|
||||
~ConflictView();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
BBitmap* Icon();
|
||||
void SetStopIcon(bool show);
|
||||
void SetWarnIcon(bool show);
|
||||
|
||||
private:
|
||||
void _FillIcons();
|
||||
|
||||
BBitmap* fIcon;
|
||||
BBitmap* fStopIcon;
|
||||
BBitmap* fWarnIcon;
|
||||
};
|
||||
class StatusMenuField;
|
||||
|
||||
|
||||
class ModifierKeysWindow : public BWindow {
|
||||
@ -49,17 +30,13 @@ private:
|
||||
void _CreateMenuField(BPopUpMenu** _menu, BMenuField** _field,
|
||||
uint32 key, const char* label);
|
||||
void _MarkMenuItems();
|
||||
void _MarkMenuItem(BPopUpMenu* menu, ConflictView* conflictView,
|
||||
uint32 leftKey, uint32 rightKey);
|
||||
bool _MarkMenuItem(const char*, BPopUpMenu*, uint32 l, uint32 r);
|
||||
const char* _KeyToString(int32 key);
|
||||
uint32 _KeyToKeyCode(int32 key,
|
||||
bool right = false);
|
||||
int32 _KeyToKeyCode(int32 key, bool right = false);
|
||||
int32 _LastKey();
|
||||
void _ValidateDuplicateKeys();
|
||||
void _ValidateDuplicateKey(ConflictView* view, uint32 mask);
|
||||
void _ValidateDuplicateKey(StatusMenuField*, uint32);
|
||||
uint32 _DuplicateKeys();
|
||||
void _HideShowStatusIcons();
|
||||
void _ToggleStatusIcon(ConflictView* view);
|
||||
void _UpdateStatus();
|
||||
|
||||
BPopUpMenu* fCapsMenu;
|
||||
@ -68,11 +45,11 @@ private:
|
||||
BPopUpMenu* fOptionMenu;
|
||||
BPopUpMenu* fCommandMenu;
|
||||
|
||||
ConflictView* fCapsConflictView;
|
||||
ConflictView* fShiftConflictView;
|
||||
ConflictView* fControlConflictView;
|
||||
ConflictView* fOptionConflictView;
|
||||
ConflictView* fCommandConflictView;
|
||||
StatusMenuField* fCapsField;
|
||||
StatusMenuField* fShiftField;
|
||||
StatusMenuField* fControlField;
|
||||
StatusMenuField* fOptionField;
|
||||
StatusMenuField* fCommandField;
|
||||
|
||||
BButton* fRevertButton;
|
||||
BButton* fCancelButton;
|
||||
|
283
src/preferences/keymap/StatusMenuField.cpp
Normal file
283
src/preferences/keymap/StatusMenuField.cpp
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright 2023 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* John Scipione, jscipione@gmail.com
|
||||
*/
|
||||
|
||||
|
||||
#include "StatusMenuField.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Catalog.h>
|
||||
#include <ControlLook.h>
|
||||
#include <IconUtils.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <LayoutUtils.h>
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "Modifier keys window"
|
||||
|
||||
|
||||
#ifdef DEBUG_ALERT
|
||||
# define FTRACE(x) fprintf(x)
|
||||
#else
|
||||
# define FTRACE(x) /* nothing */
|
||||
#endif
|
||||
|
||||
|
||||
static const char* kDuplicate = "duplicate";
|
||||
static const char* kUnmatched = "unmatched";
|
||||
|
||||
|
||||
// #pragma mark - StatusMenuItem
|
||||
|
||||
|
||||
StatusMenuItem::StatusMenuItem(const char* name, BMessage* message)
|
||||
:
|
||||
BMenuItem(name, message),
|
||||
fIcon(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
StatusMenuItem::StatusMenuItem(BMessage* archive)
|
||||
:
|
||||
BMenuItem(archive),
|
||||
fIcon(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BArchivable*
|
||||
StatusMenuItem::Instantiate(BMessage* data)
|
||||
{
|
||||
if (validate_instantiation(data, "StatusMenuItem"))
|
||||
return new StatusMenuItem(data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
StatusMenuItem::Archive(BMessage* data, bool deep) const
|
||||
{
|
||||
status_t result = BMenuItem::Archive(data, deep);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuItem::DrawContent()
|
||||
{
|
||||
if (fIcon == NULL)
|
||||
return BMenuItem::DrawContent();
|
||||
|
||||
// blend transparency
|
||||
Menu()->SetDrawingMode(B_OP_ALPHA);
|
||||
Menu()->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
|
||||
|
||||
// draw bitmap
|
||||
Menu()->DrawBitmapAsync(fIcon, IconRect().LeftTop());
|
||||
|
||||
BMenuItem::DrawContent();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuItem::GetContentSize(float* _width, float* _height)
|
||||
{
|
||||
float width;
|
||||
float height;
|
||||
BMenuItem::GetContentSize(&width, &height);
|
||||
|
||||
// prevent label from drawing over icon
|
||||
if (_width != NULL)
|
||||
*_width = Menu()->Bounds().Width() - IconRect().Width() - Spacing() * 4;
|
||||
|
||||
if (_height != NULL)
|
||||
*_height = height;
|
||||
}
|
||||
|
||||
|
||||
BBitmap*
|
||||
StatusMenuItem::Icon()
|
||||
{
|
||||
return fIcon;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuItem::SetIcon(BBitmap* icon)
|
||||
{
|
||||
fIcon = icon;
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
StatusMenuItem::IconRect()
|
||||
{
|
||||
BRect bounds(Menu()->Bounds());
|
||||
bounds.top += roundf(Spacing() / 2); // center inside menu field vertically
|
||||
bounds.right -= Spacing() * 3; // move inside menu field horizontally
|
||||
return BLayoutUtils::AlignInFrame(bounds, IconSize(),
|
||||
BAlignment(B_ALIGN_RIGHT, B_ALIGN_TOP));
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
StatusMenuItem::IconSize()
|
||||
{
|
||||
return be_control_look->ComposeIconSize(B_MINI_ICON);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
StatusMenuItem::Spacing()
|
||||
{
|
||||
return be_control_look->DefaultLabelSpacing();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - StatusMenuField
|
||||
|
||||
|
||||
StatusMenuField::StatusMenuField(const char* label, BMenu* menu)
|
||||
:
|
||||
BMenuField(label, menu),
|
||||
fStatus(B_EMPTY_STRING),
|
||||
fStopIcon(NULL),
|
||||
fWarnIcon(NULL)
|
||||
{
|
||||
_FillIcons();
|
||||
}
|
||||
|
||||
|
||||
StatusMenuField::~StatusMenuField()
|
||||
{
|
||||
delete fStopIcon;
|
||||
delete fWarnIcon;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuField::SetDuplicate(bool on)
|
||||
{
|
||||
ShowStopIcon(on);
|
||||
on ? SetStatus(kDuplicate) : ClearStatus();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuField::SetUnmatched(bool on)
|
||||
{
|
||||
ShowWarnIcon(on);
|
||||
on ? SetStatus(kUnmatched) : ClearStatus();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuField::ShowStopIcon(bool show)
|
||||
{
|
||||
// show or hide the stop icon
|
||||
StatusMenuItem* item = dynamic_cast<StatusMenuItem*>(MenuItem());
|
||||
if (item != NULL)
|
||||
item->SetIcon(show ? fStopIcon : NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuField::ShowWarnIcon(bool show)
|
||||
{
|
||||
// show or hide the warn icon
|
||||
StatusMenuItem* item = dynamic_cast<StatusMenuItem*>(MenuItem());
|
||||
if (item != NULL)
|
||||
item->SetIcon(show ? fWarnIcon : NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuField::ClearStatus()
|
||||
{
|
||||
fStatus = B_EMPTY_STRING;
|
||||
SetToolTip((const char*)NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusMenuField::SetStatus(BString status)
|
||||
{
|
||||
fStatus = status;
|
||||
|
||||
const char* tooltip = B_EMPTY_STRING;
|
||||
if (fStatus == kDuplicate)
|
||||
tooltip = B_TRANSLATE("Error: duplicate keys");
|
||||
else if (fStatus == kUnmatched)
|
||||
tooltip = B_TRANSLATE("Warning: left and right key roles do not match");
|
||||
|
||||
SetToolTip(tooltip);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - StatusMenuField private methods
|
||||
|
||||
|
||||
void
|
||||
StatusMenuField::_FillIcons()
|
||||
{
|
||||
// fill out the icons with the stop and warn icons from app_server
|
||||
// TODO find better icons
|
||||
|
||||
if (fStopIcon == NULL) {
|
||||
// allocate the fStopIcon bitmap
|
||||
fStopIcon = new (std::nothrow) BBitmap(_IconRect(), 0, B_RGBA32);
|
||||
if (fStopIcon == NULL || fStopIcon->InitCheck() != B_OK) {
|
||||
FTRACE((stderr, "MKW::_FillIcons() - No memory for stop bitmap\n"));
|
||||
delete fStopIcon;
|
||||
fStopIcon = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// load dialog-error icon bitmap
|
||||
if (BIconUtils::GetSystemIcon("dialog-error", fStopIcon) != B_OK) {
|
||||
delete fStopIcon;
|
||||
fStopIcon = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fWarnIcon == NULL) {
|
||||
// allocate the fWarnIcon bitmap
|
||||
fWarnIcon = new (std::nothrow) BBitmap(_IconRect(), 0, B_RGBA32);
|
||||
if (fWarnIcon == NULL || fWarnIcon->InitCheck() != B_OK) {
|
||||
FTRACE((stderr, "MKW::_FillIcons() - No memory for warn bitmap\n"));
|
||||
delete fWarnIcon;
|
||||
fWarnIcon = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// load dialog-warning icon bitmap
|
||||
if (BIconUtils::GetSystemIcon("dialog-warning", fWarnIcon) != B_OK) {
|
||||
delete fWarnIcon;
|
||||
fWarnIcon = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
StatusMenuField::_IconRect()
|
||||
{
|
||||
BSize iconSize = be_control_look->ComposeIconSize(B_MINI_ICON);
|
||||
return BRect(0, 0, iconSize.Width() - 1, iconSize.Height() - 1);
|
||||
}
|
72
src/preferences/keymap/StatusMenuField.h
Normal file
72
src/preferences/keymap/StatusMenuField.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2023 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* John Scipione, jscipione@gmail.com
|
||||
*/
|
||||
#ifndef STATUS_MENU_FIELD_H
|
||||
#define STATUS_MENU_FIELD_H
|
||||
|
||||
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class BBitmap;
|
||||
|
||||
|
||||
class StatusMenuItem : public BMenuItem {
|
||||
public:
|
||||
StatusMenuItem(const char* name, BMessage* message = NULL);
|
||||
StatusMenuItem(BMessage* archive);
|
||||
|
||||
static BArchivable* Instantiate(BMessage* archive);
|
||||
virtual status_t Archive(BMessage* archive,
|
||||
bool deep = true) const;
|
||||
|
||||
virtual void DrawContent();
|
||||
virtual void GetContentSize(float* _width, float* _height);
|
||||
|
||||
BBitmap* Icon();
|
||||
virtual void SetIcon(BBitmap* icon);
|
||||
|
||||
BRect IconRect();
|
||||
BSize IconSize();
|
||||
float Spacing();
|
||||
|
||||
private:
|
||||
BBitmap* fIcon;
|
||||
};
|
||||
|
||||
|
||||
class StatusMenuField : public BMenuField {
|
||||
public:
|
||||
StatusMenuField(const char*, BMenu*);
|
||||
~StatusMenuField();
|
||||
|
||||
virtual void SetDuplicate(bool on);
|
||||
virtual void SetUnmatched(bool on);
|
||||
|
||||
BString Status() { return fStatus; };
|
||||
virtual void ClearStatus();
|
||||
virtual void SetStatus(BString status);
|
||||
|
||||
protected:
|
||||
virtual void ShowStopIcon(bool show);
|
||||
virtual void ShowWarnIcon(bool show);
|
||||
|
||||
private:
|
||||
void _FillIcons();
|
||||
BRect _IconRect();
|
||||
|
||||
private:
|
||||
BString fStatus;
|
||||
|
||||
BBitmap* fStopIcon;
|
||||
BBitmap* fWarnIcon;
|
||||
};
|
||||
|
||||
|
||||
#endif // STATUS_MENU_FIELD_H
|
Loading…
x
Reference in New Issue
Block a user