mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-22 06:22:58 +02:00
Fixes for bugs 1122 and 1113
Several other issues were also fixed (hopefully ;-)). This is a major change to accelerator handling and keyboard capturing. Menu shortcuts, non-menu commands, label editing, navigation, and basically anything else were you might use the keyboard should be thoroughly tested.
This commit is contained in:
@@ -111,6 +111,8 @@ CommandManager. It holds the callback for one command.
|
||||
#if defined(__WXMAC__)
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <wx/osx/private.h>
|
||||
#elif defined(__WXGTK__)
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
|
||||
// Shared by all projects
|
||||
@@ -122,7 +124,7 @@ public:
|
||||
{
|
||||
#if defined(__WXMAC__)
|
||||
NSEventMask mask = NSKeyDownMask;
|
||||
|
||||
|
||||
mHandler =
|
||||
[
|
||||
NSEvent addLocalMonitorForEventsMatchingMask:mask handler:^NSEvent *(NSEvent *event)
|
||||
@@ -134,6 +136,8 @@ public:
|
||||
wxWidgetImpl::FindFromWXWidget(widget);
|
||||
if (impl)
|
||||
{
|
||||
mEvent = event;
|
||||
|
||||
wxKeyEvent wxevent(wxEVT_KEY_DOWN);
|
||||
impl->SetupKeyEvent(wxevent, event);
|
||||
|
||||
@@ -161,78 +165,84 @@ public:
|
||||
|
||||
int FilterEvent(wxEvent& event)
|
||||
{
|
||||
AudacityProject *project = GetActiveProject();
|
||||
if (!project)
|
||||
{
|
||||
return Event_Skip;
|
||||
}
|
||||
|
||||
wxEvtHandler *handler = project->GetKeyboardCaptureHandler();
|
||||
if (!handler)
|
||||
{
|
||||
return Event_Skip;
|
||||
}
|
||||
|
||||
wxEventType type = event.GetEventType();
|
||||
if (type != wxEVT_CHAR_HOOK)
|
||||
{
|
||||
return Event_Skip;
|
||||
}
|
||||
|
||||
wxKeyEvent temp = (wxKeyEvent &) event;
|
||||
temp.SetEventType(wxEVT_KEY_DOWN);
|
||||
|
||||
wxCommandEvent e(EVT_CAPTURE_KEY);
|
||||
e.SetEventObject(&temp);
|
||||
e.StopPropagation();
|
||||
|
||||
if (!handler->ProcessEvent(e))
|
||||
AudacityProject *project = GetActiveProject();
|
||||
if (!project)
|
||||
{
|
||||
return Event_Skip;
|
||||
}
|
||||
|
||||
|
||||
wxWindow *handler = project->GetKeyboardCaptureHandler();
|
||||
if (handler && HandleCapture(handler, (wxKeyEvent &) event))
|
||||
{
|
||||
return Event_Processed;
|
||||
}
|
||||
|
||||
CommandManager *manager = project->GetCommandManager();
|
||||
if (manager && manager->FilterKeyEvent(project, (wxKeyEvent &) event))
|
||||
{
|
||||
return Event_Processed;
|
||||
}
|
||||
|
||||
return Event_Skip;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Returns true if the event was captured and processed
|
||||
bool HandleCapture(wxWindow *target, wxKeyEvent & event)
|
||||
{
|
||||
if (wxGetTopLevelParent(target) != wxGetTopLevelParent(wxWindow::FindFocus()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
wxEvtHandler *handler = target->GetEventHandler();
|
||||
|
||||
wxKeyEvent temp = (wxKeyEvent &) event;
|
||||
temp.SetEventType(wxEVT_KEY_DOWN);
|
||||
|
||||
#if defined(__WXGTK__)
|
||||
// wxGTK uses the control and alt modifiers to represent ALTGR,
|
||||
// so remove it as it might confuse the capture handlers.
|
||||
if (temp.GetModifiers() == (wxMOD_CONTROL | wxMOD_ALT))
|
||||
{
|
||||
temp.SetControlDown(false);
|
||||
temp.SetAltDown(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
wxCommandEvent e(EVT_CAPTURE_KEY);
|
||||
e.SetEventObject(&temp);
|
||||
e.StopPropagation();
|
||||
|
||||
if (!handler->ProcessEvent(e))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
temp.WasProcessed();
|
||||
temp.StopPropagation();
|
||||
wxEventProcessInHandlerOnly onlyDown(temp, handler);
|
||||
if (!handler->ProcessEvent(temp))
|
||||
{
|
||||
return Event_Skip;
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyCode = temp.GetKeyCode();
|
||||
switch (keyCode)
|
||||
|
||||
wxString chars = GetUnicodeString(temp);
|
||||
for (size_t i = 0, cnt = chars.Length(); i < cnt; i++)
|
||||
{
|
||||
case WXK_SHIFT:
|
||||
case WXK_CONTROL:
|
||||
case WXK_MENU:
|
||||
case WXK_CAPITAL:
|
||||
case WXK_NUMLOCK:
|
||||
case WXK_SCROLL:
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = (wxKeyEvent &) event;
|
||||
temp.SetEventType(wxEVT_CHAR);
|
||||
|
||||
if (!temp.ShiftDown())
|
||||
{
|
||||
if (wxIsascii(temp.m_keyCode))
|
||||
{
|
||||
temp.m_keyCode = wxTolower(temp.m_keyCode);
|
||||
}
|
||||
|
||||
if (temp.m_keyCode < WXK_START)
|
||||
{
|
||||
temp.m_uniChar = wxTolower(temp.m_uniChar);
|
||||
}
|
||||
}
|
||||
|
||||
temp.WasProcessed();
|
||||
temp.StopPropagation();
|
||||
temp.m_uniChar = chars[i];
|
||||
wxEventProcessInHandlerOnly onlyChar(temp, handler);
|
||||
handler->ProcessEvent(temp);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
temp = (wxKeyEvent &) event;
|
||||
@@ -242,13 +252,97 @@ public:
|
||||
wxEventProcessInHandlerOnly onlyUp(temp, handler);
|
||||
handler->ProcessEvent(temp);
|
||||
|
||||
return Event_Processed;
|
||||
return true;
|
||||
}
|
||||
|
||||
wxString GetUnicodeString(const wxKeyEvent & event)
|
||||
{
|
||||
wxString chars;
|
||||
|
||||
#if defined(__WXMSW__)
|
||||
|
||||
BYTE ks[256];
|
||||
GetKeyboardState(ks);
|
||||
WCHAR ucode[256];
|
||||
int res = ToUnicode(event.GetRawKeyCode(), 0, ks, ucode, 256, 0);
|
||||
if (res >= 1)
|
||||
{
|
||||
chars.Append(ucode, res);
|
||||
}
|
||||
|
||||
#elif defined(__WXGTK__)
|
||||
|
||||
chars.Append((wxChar) gdk_keyval_to_unicode(event.GetRawKeyCode()));
|
||||
|
||||
#elif defined(__WXMAC__)
|
||||
|
||||
NSString *c = [mEvent charactersIgnoringModifiers];
|
||||
if ([c length] == 1)
|
||||
{
|
||||
unichar codepoint = [c characterAtIndex:0];
|
||||
if ((codepoint >= 0xF700 && codepoint <= 0xF8FF) || codepoint == 0x7F)
|
||||
{
|
||||
return chars;
|
||||
}
|
||||
}
|
||||
|
||||
c = [mEvent characters];
|
||||
chars = [c UTF8String];
|
||||
|
||||
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
||||
CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
|
||||
CFRelease(currentKeyboard);
|
||||
if (uchr == NULL)
|
||||
{
|
||||
return chars;
|
||||
}
|
||||
|
||||
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
|
||||
if (keyboardLayout == NULL)
|
||||
{
|
||||
return chars;
|
||||
}
|
||||
|
||||
const UniCharCount maxStringLength = 255;
|
||||
UniCharCount actualStringLength = 0;
|
||||
UniChar unicodeString[maxStringLength];
|
||||
UInt32 nsflags = [mEvent modifierFlags];
|
||||
UInt16 modifiers = (nsflags & NSAlphaShiftKeyMask ? alphaLock : 0) |
|
||||
(nsflags & NSShiftKeyMask ? shiftKey : 0) |
|
||||
(nsflags & NSControlKeyMask ? controlKey : 0) |
|
||||
(nsflags & NSAlternateKeyMask ? optionKey : 0) |
|
||||
(nsflags & NSCommandKeyMask ? cmdKey : 0);
|
||||
|
||||
OSStatus status = UCKeyTranslate(keyboardLayout,
|
||||
[mEvent keyCode],
|
||||
kUCKeyActionDown,
|
||||
(modifiers >> 8) & 0xff,
|
||||
LMGetKbdType(),
|
||||
0,
|
||||
&mDeadKeyState,
|
||||
maxStringLength,
|
||||
&actualStringLength,
|
||||
unicodeString);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
return chars;
|
||||
}
|
||||
|
||||
chars = [[NSString stringWithCharacters:unicodeString
|
||||
length:(NSInteger)actualStringLength] UTF8String];
|
||||
|
||||
#endif
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
id mHandler;
|
||||
NSEvent *mEvent;
|
||||
UInt32 mDeadKeyState;
|
||||
#endif
|
||||
|
||||
} monitor;
|
||||
@@ -336,7 +430,7 @@ wxMenuBar *CommandManager::AddMenuBar(wxString sMenu)
|
||||
///
|
||||
/// Retrieves the menubar based on the name given in AddMenuBar(name)
|
||||
///
|
||||
wxMenuBar * CommandManager::GetMenuBar(wxString sMenu)
|
||||
wxMenuBar * CommandManager::GetMenuBar(wxString sMenu) const
|
||||
{
|
||||
for(unsigned int i = 0; i < mMenuBarList.GetCount(); i++)
|
||||
{
|
||||
@@ -351,7 +445,7 @@ wxMenuBar * CommandManager::GetMenuBar(wxString sMenu)
|
||||
///
|
||||
/// Retrieve the 'current' menubar; either NULL or the
|
||||
/// last on in the mMenuBarList.
|
||||
wxMenuBar * CommandManager::CurrentMenuBar()
|
||||
wxMenuBar * CommandManager::CurrentMenuBar() const
|
||||
{
|
||||
if(mMenuBarList.IsEmpty())
|
||||
return NULL;
|
||||
@@ -433,7 +527,7 @@ void CommandManager::EndSubMenu()
|
||||
///
|
||||
/// This returns the 'Current' Submenu, which is the one at the
|
||||
/// end of the mSubMenuList (or NULL, if it doesn't exist).
|
||||
wxMenu * CommandManager::CurrentSubMenu()
|
||||
wxMenu * CommandManager::CurrentSubMenu() const
|
||||
{
|
||||
if(mSubMenuList.IsEmpty())
|
||||
return NULL;
|
||||
@@ -445,7 +539,7 @@ wxMenu * CommandManager::CurrentSubMenu()
|
||||
/// This returns the current menu that we're appending to - note that
|
||||
/// it could be a submenu if BeginSubMenu was called and we haven't
|
||||
/// reached EndSubMenu yet.
|
||||
wxMenu * CommandManager::CurrentMenu()
|
||||
wxMenu * CommandManager::CurrentMenu() const
|
||||
{
|
||||
if(!mCurrentMenu)
|
||||
return NULL;
|
||||
@@ -515,7 +609,9 @@ void CommandManager::InsertItem(wxString name, wxString label_in,
|
||||
}
|
||||
}
|
||||
|
||||
int ID = NewIdentifier(name, label, menu, callback, false, 0, 0);
|
||||
CommandListEntry *entry = NewIdentifier(name, label, menu, callback, false, 0, 0);
|
||||
int ID = entry->id;
|
||||
label = GetLabel(entry);
|
||||
|
||||
if (checkmark >= 0) {
|
||||
menu->InsertCheckItem(pos, ID, label);
|
||||
@@ -528,6 +624,8 @@ void CommandManager::InsertItem(wxString name, wxString label_in,
|
||||
mbSeparatorAllowed = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CommandManager::AddCheck(const wxChar *name,
|
||||
const wxChar *label,
|
||||
CommandFunctor *callback,
|
||||
@@ -563,16 +661,15 @@ void CommandManager::AddItem(const wxChar *name,
|
||||
unsigned int mask,
|
||||
int checkmark)
|
||||
{
|
||||
wxString label(label_in);
|
||||
label += wxT("\t");
|
||||
label += accel ? accel : wxEmptyString;
|
||||
|
||||
int ID = NewIdentifier(name, label, CurrentMenu(), callback, false, 0, 0);
|
||||
CommandListEntry *entry = NewIdentifier(name, label_in, accel, CurrentMenu(), callback, false, 0, 0);
|
||||
int ID = entry->id;
|
||||
wxString label = GetLabel(entry);
|
||||
|
||||
if (flags != NoFlagsSpecifed || mask != NoFlagsSpecifed) {
|
||||
SetCommandFlags(name, flags, mask);
|
||||
}
|
||||
|
||||
|
||||
if (checkmark >= 0) {
|
||||
CurrentMenu()->AppendCheckItem(ID, label);
|
||||
CurrentMenu()->Check(ID, checkmark != 0);
|
||||
@@ -593,17 +690,15 @@ void CommandManager::AddItem(const wxChar *name,
|
||||
void CommandManager::AddItemList(wxString name, wxArrayString labels,
|
||||
CommandFunctor *callback)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
unsigned int effLen = labels.GetCount();
|
||||
|
||||
wxString label;
|
||||
int tmpmax;
|
||||
|
||||
for(i=0; i<effLen; i++) {
|
||||
int ID = NewIdentifier(name, labels[i], CurrentMenu(), callback,
|
||||
true, i, effLen);
|
||||
CurrentMenu()->Append(ID, labels[i]);
|
||||
for (size_t i = 0, cnt = labels.GetCount(); i < cnt; i++) {
|
||||
CommandListEntry *entry = NewIdentifier(name,
|
||||
labels[i],
|
||||
CurrentMenu(),
|
||||
callback,
|
||||
true,
|
||||
i,
|
||||
cnt);
|
||||
CurrentMenu()->Append(entry->id, GetLabel(entry));
|
||||
mbSeparatorAllowed = true;
|
||||
}
|
||||
}
|
||||
@@ -627,11 +722,7 @@ void CommandManager::AddCommand(const wxChar *name,
|
||||
unsigned int flags,
|
||||
unsigned int mask)
|
||||
{
|
||||
wxString label(label_in);
|
||||
label += wxT("\t");
|
||||
label += accel;
|
||||
|
||||
NewIdentifier(name, label, NULL, callback, false, 0, 0);
|
||||
NewIdentifier(name, label_in, accel, NULL, callback, false, 0, 0);
|
||||
|
||||
if (flags != NoFlagsSpecifed || mask != NoFlagsSpecifed) {
|
||||
SetCommandFlags(name, flags, mask);
|
||||
@@ -643,13 +734,8 @@ void CommandManager::AddMetaCommand(const wxChar *name,
|
||||
CommandFunctor *callback,
|
||||
const wxChar *accel)
|
||||
{
|
||||
wxString label(label_in);
|
||||
label += wxT("\t");
|
||||
label += accel;
|
||||
CommandListEntry *entry = NewIdentifier(name, label_in, accel, NULL, callback, false, 0, 0);
|
||||
|
||||
NewIdentifier(name, label, NULL, callback, false, 0, 0);
|
||||
|
||||
CommandListEntry *entry = mCommandNameHash[name];
|
||||
entry->enabled = false;
|
||||
entry->isMeta = true;
|
||||
entry->flags = 0;
|
||||
@@ -679,15 +765,34 @@ int CommandManager::NextIdentifier(int ID)
|
||||
///WARNING: Does this conflict with the identifiers set for controls/windows?
|
||||
///If it does, a workaround may be to keep controls below wxID_LOWEST
|
||||
///and keep menus above wxID_HIGHEST
|
||||
int CommandManager::NewIdentifier(wxString name,
|
||||
wxString label,
|
||||
wxMenu *menu,
|
||||
CommandFunctor *callback,
|
||||
bool multi,
|
||||
int index,
|
||||
int count)
|
||||
CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
|
||||
const wxString & label,
|
||||
wxMenu *menu,
|
||||
CommandFunctor *callback,
|
||||
bool multi,
|
||||
int index,
|
||||
int count)
|
||||
{
|
||||
CommandListEntry *tmpEntry = new CommandListEntry;
|
||||
return NewIdentifier(name,
|
||||
label.BeforeFirst(wxT('\t')),
|
||||
label.AfterFirst(wxT('\t')),
|
||||
menu,
|
||||
callback,
|
||||
multi,
|
||||
index,
|
||||
count);
|
||||
}
|
||||
|
||||
CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
|
||||
const wxString & label,
|
||||
const wxString & accel,
|
||||
wxMenu *menu,
|
||||
CommandFunctor *callback,
|
||||
bool multi,
|
||||
int index,
|
||||
int count)
|
||||
{
|
||||
CommandListEntry *entry = new CommandListEntry;
|
||||
|
||||
wxString labelPrefix;
|
||||
if (!mSubMenuList.IsEmpty()) {
|
||||
@@ -704,86 +809,88 @@ int CommandManager::NewIdentifier(wxString name,
|
||||
// menu (which might be translated).
|
||||
|
||||
mCurrentID = NextIdentifier(mCurrentID);
|
||||
tmpEntry->id = mCurrentID;
|
||||
tmpEntry->key = GetKey(label);
|
||||
entry->id = mCurrentID;
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
if (name == wxT("Preferences"))
|
||||
tmpEntry->id = wxID_PREFERENCES;
|
||||
entry->id = wxID_PREFERENCES;
|
||||
else if (name == wxT("Exit"))
|
||||
tmpEntry->id = wxID_EXIT;
|
||||
entry->id = wxID_EXIT;
|
||||
else if (name == wxT("About"))
|
||||
tmpEntry->id = wxID_ABOUT;
|
||||
entry->id = wxID_ABOUT;
|
||||
#endif
|
||||
|
||||
tmpEntry->defaultKey = tmpEntry->key;
|
||||
entry->defaultKey = entry->key;
|
||||
entry->name = name;
|
||||
entry->label = label;
|
||||
entry->key = KeyStringNormalize(accel.BeforeFirst(wxT('\t')));
|
||||
entry->labelPrefix = labelPrefix;
|
||||
entry->labelTop = wxMenuItem::GetLabelText(mCurrentMenuName);
|
||||
entry->menu = menu;
|
||||
entry->callback = callback;
|
||||
entry->multi = multi;
|
||||
entry->index = index;
|
||||
entry->count = count;
|
||||
entry->flags = mDefaultFlags;
|
||||
entry->mask = mDefaultMask;
|
||||
entry->enabled = true;
|
||||
entry->wantevent = (accel.Find(wxT("\twantevent")) != wxNOT_FOUND);
|
||||
entry->ignoredown = (accel.Find(wxT("\tignoredown")) != wxNOT_FOUND);
|
||||
entry->isMeta = false;
|
||||
|
||||
// For key bindings for commands with a list, such as effects,
|
||||
// the name in prefs is the category name plus the effect name.
|
||||
if( multi )
|
||||
name= wxString::Format( wxT("%s:%s"), name.c_str(), label.c_str() );
|
||||
tmpEntry->name = name;
|
||||
|
||||
tmpEntry->label = label;
|
||||
tmpEntry->labelPrefix = labelPrefix;
|
||||
tmpEntry->labelTop = wxMenuItem::GetLabelText(mCurrentMenuName);
|
||||
tmpEntry->menu = menu;
|
||||
tmpEntry->callback = callback;
|
||||
tmpEntry->multi = multi;
|
||||
tmpEntry->index = index;
|
||||
tmpEntry->count = count;
|
||||
tmpEntry->flags = mDefaultFlags;
|
||||
tmpEntry->mask = mDefaultMask;
|
||||
tmpEntry->enabled = true;
|
||||
tmpEntry->wantevent = (label.Find(wxT("\twantevent")) != wxNOT_FOUND);
|
||||
tmpEntry->ignoredown = (label.Find(wxT("\tignoredown")) != wxNOT_FOUND);
|
||||
tmpEntry->isMeta = false;
|
||||
if (multi) {
|
||||
entry->name = wxString::Format( wxT("%s:%s"), name.c_str(), label.c_str() );
|
||||
}
|
||||
|
||||
// Key from preferences overridse the default key given
|
||||
gPrefs->SetPath(wxT("/NewKeys"));
|
||||
if (gPrefs->HasEntry(name)) {
|
||||
tmpEntry->key = KeyStringNormalize(gPrefs->Read(name, tmpEntry->key));
|
||||
entry->key = KeyStringNormalize(gPrefs->Read(name, entry->key));
|
||||
}
|
||||
gPrefs->SetPath(wxT("/"));
|
||||
|
||||
mCommandList.Add(tmpEntry);
|
||||
mCommandIDHash[tmpEntry->id] = tmpEntry;
|
||||
mCommandList.Add(entry);
|
||||
mCommandIDHash[entry->id] = entry;
|
||||
|
||||
#if defined(__WXDEBUG__)
|
||||
CommandListEntry *prev = mCommandNameHash[name];
|
||||
CommandListEntry *prev = mCommandNameHash[entry->name];
|
||||
if (prev) {
|
||||
// Under Linux it looks as if we may ask for a newID for the same command
|
||||
// more than once. So it's only an error if two different commands
|
||||
// have the exact same name.
|
||||
if( prev->label != tmpEntry->label )
|
||||
if( prev->label != entry->label )
|
||||
{
|
||||
wxLogDebug(wxT("Command '%s' defined by '%s' and '%s'"),
|
||||
name.c_str(),
|
||||
prev->label.BeforeFirst(wxT('\t')).c_str(),
|
||||
tmpEntry->label.BeforeFirst(wxT('\t')).c_str());
|
||||
wxFAIL_MSG( wxString::Format(wxT("Command '%s' defined by '%s' and '%s'"),
|
||||
name.c_str(),
|
||||
prev->label.BeforeFirst(wxT('\t')).c_str(),
|
||||
tmpEntry->label.BeforeFirst(wxT('\t')).c_str()));
|
||||
entry->name.c_str(),
|
||||
prev->label.BeforeFirst(wxT('\t')).c_str(),
|
||||
entry->label.BeforeFirst(wxT('\t')).c_str());
|
||||
wxFAIL_MSG(wxString::Format(wxT("Command '%s' defined by '%s' and '%s'"),
|
||||
entry->name.c_str(),
|
||||
prev->label.BeforeFirst(wxT('\t')).c_str(),
|
||||
entry->label.BeforeFirst(wxT('\t')).c_str()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mCommandNameHash[name] = tmpEntry;
|
||||
mCommandNameHash[name] = entry;
|
||||
|
||||
if (tmpEntry->key != wxT("")) {
|
||||
mCommandKeyHash[tmpEntry->key] = tmpEntry;
|
||||
if (entry->key != wxT("")) {
|
||||
mCommandKeyHash[entry->key] = entry;
|
||||
}
|
||||
|
||||
return tmpEntry->id;
|
||||
return entry;
|
||||
}
|
||||
|
||||
wxString CommandManager::GetKey(wxString label)
|
||||
wxString CommandManager::GetLabel(const CommandListEntry *entry) const
|
||||
{
|
||||
wxString key = label.AfterFirst(wxT('\t')).BeforeFirst(wxT('\t'));
|
||||
if (key.IsEmpty()) {
|
||||
return key;
|
||||
wxString label = entry->label;
|
||||
if (!entry->key.IsEmpty())
|
||||
{
|
||||
label += wxT("\t") + entry->key;
|
||||
}
|
||||
|
||||
return KeyStringNormalize(key);
|
||||
return label;
|
||||
}
|
||||
|
||||
///Enables or disables a menu item based on its name (not the
|
||||
@@ -932,6 +1039,44 @@ void CommandManager::TellUserWhyDisallowed( wxUint32 flagsGot, wxUint32 flagsReq
|
||||
wxMessageBox(reason, _("Disallowed"), wxICON_WARNING | wxOK );
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
bool CommandManager::FilterKeyEvent(AudacityProject *project, wxKeyEvent & evt)
|
||||
{
|
||||
if (HandleMeta(evt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Any other keypresses must be destined for this project window.
|
||||
if (wxGetTopLevelParent(wxWindow::FindFocus()) != project)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wxUint32 flags = project->GetUpdateFlags();
|
||||
|
||||
wxKeyEvent temp = evt;
|
||||
temp.SetEventType(wxEVT_KEY_DOWN);
|
||||
if (HandleKey(temp, flags, 0xFFFFFFFF))
|
||||
{
|
||||
temp.SetEventType(wxEVT_KEY_UP);
|
||||
HandleKey(temp, flags, 0xFFFFFFFF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (project->HandleKeyDown(evt))
|
||||
{
|
||||
wxKeyEvent temp = evt;
|
||||
temp.SetEventType(wxEVT_KEY_UP);
|
||||
project->HandleKeyUp(temp);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// HandleCommandEntry() takes a CommandListEntry and executes it
|
||||
/// returning true iff successful. If you pass any flags,
|
||||
///the command won't be executed unless the flags are compatible
|
||||
@@ -952,7 +1097,6 @@ bool CommandManager::HandleCommandEntry(CommandListEntry * entry, wxUint32 flags
|
||||
|
||||
// NB: The call may have the side effect of changing flags.
|
||||
bool allowed = proj->TryToMakeActionAllowed( flags, entry->flags, combinedMask );
|
||||
|
||||
if (!allowed)
|
||||
{
|
||||
TellUserWhyDisallowed(
|
||||
|
@@ -71,6 +71,8 @@ WX_DEFINE_USER_EXPORTED_ARRAY(CommandListEntry *, CommandList, class AUDACITY_DL
|
||||
WX_DECLARE_STRING_HASH_MAP_WITH_DECL(CommandListEntry *, CommandNameHash, class AUDACITY_DLL_API);
|
||||
WX_DECLARE_HASH_MAP_WITH_DECL(int, CommandListEntry *, wxIntegerHash, wxIntegerEqual, CommandIDHash, class AUDACITY_DLL_API);
|
||||
|
||||
class AudacityProject;
|
||||
|
||||
class AUDACITY_DLL_API CommandManager: public XMLTagHandler
|
||||
{
|
||||
public:
|
||||
@@ -183,6 +185,7 @@ class AUDACITY_DLL_API CommandManager: public XMLTagHandler
|
||||
//
|
||||
// Executing commands
|
||||
//
|
||||
bool FilterKeyEvent(AudacityProject *project, wxKeyEvent & evt);
|
||||
bool HandleCommandEntry(CommandListEntry * entry, wxUint32 flags, wxUint32 mask, const wxEvent * evt = NULL);
|
||||
bool HandleMenuID(int id, wxUint32 flags, wxUint32 mask);
|
||||
bool HandleKey(wxKeyEvent &evt, wxUint32 flags, wxUint32 mask);
|
||||
@@ -228,18 +231,30 @@ class AUDACITY_DLL_API CommandManager: public XMLTagHandler
|
||||
|
||||
protected:
|
||||
|
||||
wxMenuBar * CurrentMenuBar();
|
||||
wxMenuBar * GetMenuBar(wxString sMenu);
|
||||
wxMenu * CurrentSubMenu();
|
||||
wxMenu * CurrentMenu();
|
||||
wxMenuBar * CurrentMenuBar() const;
|
||||
wxMenuBar * GetMenuBar(wxString sMenu) const;
|
||||
wxMenu * CurrentSubMenu() const;
|
||||
wxMenu * CurrentMenu() const;
|
||||
|
||||
int NextIdentifier(int ID);
|
||||
int NewIdentifier(wxString name, wxString label, wxMenu *menu,
|
||||
CommandFunctor *callback,
|
||||
bool multi, int index, int count);
|
||||
CommandListEntry *NewIdentifier(const wxString & name,
|
||||
const wxString & label,
|
||||
wxMenu *menu,
|
||||
CommandFunctor *callback,
|
||||
bool multi,
|
||||
int index,
|
||||
int count);
|
||||
CommandListEntry *NewIdentifier(const wxString & name,
|
||||
const wxString & label,
|
||||
const wxString & accel,
|
||||
wxMenu *menu,
|
||||
CommandFunctor *callback,
|
||||
bool multi,
|
||||
int index,
|
||||
int count);
|
||||
void Enable(CommandListEntry *entry, bool enabled);
|
||||
|
||||
wxString GetKey(wxString label);
|
||||
wxString GetLabel(const CommandListEntry *entry) const;
|
||||
|
||||
private:
|
||||
MenuBarList mMenuBarList;
|
||||
|
@@ -62,11 +62,8 @@ wxString KeyEventToKeyString(const wxKeyEvent & event)
|
||||
long key = event.GetKeyCode();
|
||||
|
||||
if (event.ControlDown())
|
||||
#if defined(__WXMAC__)
|
||||
newStr += wxT("XCtrl+");
|
||||
#else
|
||||
newStr += wxT("Ctrl+");
|
||||
#endif
|
||||
|
||||
if (event.AltDown())
|
||||
newStr += wxT("Alt+");
|
||||
|
||||
@@ -74,11 +71,11 @@ wxString KeyEventToKeyString(const wxKeyEvent & event)
|
||||
newStr += wxT("Shift+");
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
if (event.MetaDown())
|
||||
newStr += wxT("Ctrl+");
|
||||
if (event.RawControlDown())
|
||||
newStr += wxT("XCtrl+");
|
||||
#endif
|
||||
|
||||
if (event.ControlDown() && key >= 1 && key <= 26)
|
||||
if (event.RawControlDown() && key >= 1 && key <= 26)
|
||||
newStr += (wxChar)(64 + key);
|
||||
else if (key >= 33 && key <= 126)
|
||||
newStr += (wxChar)key;
|
||||
|
Reference in New Issue
Block a user