1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00

Use a type distinction for key strings in normalized form...

... Such are not for display to the user.  They are appended to menu item
names to identify accelerators, and wxWidgets transforms them appropriately
for the operating system.
This commit is contained in:
Paul Licameli 2018-02-08 21:16:13 -05:00
parent 19014f22b7
commit e5052a1973
10 changed files with 256 additions and 236 deletions

View File

@ -440,6 +440,71 @@ CommandManager::~CommandManager()
PurgeData();
}
const std::vector<NormalizedKeyString> &CommandManager::ExcludedList()
{
static const auto list = [] {
// These short cuts are for the max list only....
const char *const strings[] = {
"Ctrl+I",
"Ctrl+Alt+I",
"Ctrl+J",
"Ctrl+Alt+J",
"Ctrl+Alt+V",
"Alt+X",
"Alt+K",
"Shift+Alt+X",
"Shift+Alt+K",
"Alt+L",
"Shift+Alt+C",
"Alt+I",
"Alt+J",
"Shift+Alt+J",
"Ctrl+Shift+A",
"Q",
//"Shift+J",
//"Shift+K",
//"Shift+Home",
//"Shift+End",
"Ctrl+[",
"Ctrl+]",
"1",
"Shift+F5",
"Shift+F6",
"Shift+F7",
"Shift+F8",
"Ctrl+Shift+F5",
"Ctrl+Shift+F7",
"Ctrl+Shift+N",
"Ctrl+Shift+M",
"Ctrl+Home",
"Ctrl+End",
"Shift+C",
"Alt+Shift+Up",
"Alt+Shift+Down",
"Shift+P",
"Alt+Shift+Left",
"Alt+Shift+Right",
"Ctrl+Shift+T",
//"Command+M",
//"Option+Command+M",
"Shift+H",
"Shift+O",
"Shift+I",
"Shift+N",
"D",
"A",
"Alt+Shift+F6",
"Alt+F6",
};
std::vector<NormalizedKeyString> result(
strings, strings + sizeof(strings)/sizeof(*strings) );
std::sort( result.begin(), result.end() );
return result;
}();
return list;
}
// CommandManager needs to know which defaults are standard and which are in the
// full (max) list.
void CommandManager::SetMaxList()
@ -452,68 +517,14 @@ void CommandManager::SetMaxList()
// instead use flags in the menu entrys to indicate whether the default
// shortcut is standard or full.
mMaxListOnly.Clear();
mMaxListOnly.clear();
// if the full list, don't exclude any.
bool bFull = gPrefs->ReadBool(wxT("/GUI/Shortcuts/FullDefaults"),false);
if( bFull )
return;
// These short cuts are for the max list only....
//mMaxListOnly.Add( "Ctrl+I" );
mMaxListOnly.Add( "Ctrl+Alt+I" );
mMaxListOnly.Add( "Ctrl+J" );
mMaxListOnly.Add( "Ctrl+Alt+J" );
mMaxListOnly.Add( "Ctrl+Alt+V" );
mMaxListOnly.Add( "Alt+X" );
mMaxListOnly.Add( "Alt+K" );
mMaxListOnly.Add( "Shift+Alt+X" );
mMaxListOnly.Add( "Shift+Alt+K" );
mMaxListOnly.Add( "Alt+L" );
mMaxListOnly.Add( "Shift+Alt+C" );
mMaxListOnly.Add( "Alt+I" );
mMaxListOnly.Add( "Alt+J" );
mMaxListOnly.Add( "Shift+Alt+J" );
mMaxListOnly.Add( "Ctrl+Shift+A" );
mMaxListOnly.Add( "Q" );
//mMaxListOnly.Add( "Shift+J" );
//mMaxListOnly.Add( "Shift+K" );
//mMaxListOnly.Add( "Shift+Home" );
//mMaxListOnly.Add( "Shift+End" );
mMaxListOnly.Add( "Ctrl+[" );
mMaxListOnly.Add( "Ctrl+]" );
mMaxListOnly.Add( "1" );
mMaxListOnly.Add( "Shift+F5" );
mMaxListOnly.Add( "Shift+F6" );
mMaxListOnly.Add( "Shift+F7" );
mMaxListOnly.Add( "Shift+F8" );
mMaxListOnly.Add( "Ctrl+Shift+F5" );
mMaxListOnly.Add( "Ctrl+Shift+F7" );
mMaxListOnly.Add( "Ctrl+Shift+N" );
mMaxListOnly.Add( "Ctrl+Shift+M" );
mMaxListOnly.Add( "Ctrl+Home" );
mMaxListOnly.Add( "Ctrl+End" );
mMaxListOnly.Add( "Shift+C" );
mMaxListOnly.Add( "Alt+Shift+Up" );
mMaxListOnly.Add( "Alt+Shift+Down" );
mMaxListOnly.Add( "Shift+P" );
mMaxListOnly.Add( "Alt+Shift+Left" );
mMaxListOnly.Add( "Alt+Shift+Right" );
mMaxListOnly.Add( "Ctrl+Shift+T" );
//mMaxListOnly.Add( "Command+M" );
//mMaxListOnly.Add( "Option+Command+M" );
mMaxListOnly.Add( "Shift+H" );
mMaxListOnly.Add( "Shift+O" );
mMaxListOnly.Add( "Shift+I" );
mMaxListOnly.Add( "Shift+N" );
mMaxListOnly.Add( "D" );
mMaxListOnly.Add( "A" );
mMaxListOnly.Add( "Alt+Shift+F6" );
mMaxListOnly.Add( "Alt+F6" );
std::transform( mMaxListOnly.begin(), mMaxListOnly.end(), mMaxListOnly.begin(),
KeyStringNormalize );
mMaxListOnly.Sort();
mMaxListOnly = ExcludedList();
}
@ -1013,7 +1024,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn,
entry->name = name;
entry->label = label;
entry->key = KeyStringNormalize(accel.BeforeFirst(wxT('\t')));
entry->key = NormalizedKeyString{ accel.BeforeFirst(wxT('\t')) };
entry->defaultKey = entry->key;
entry->labelPrefix = labelPrefix;
entry->labelTop = wxMenuItem::GetLabelText(mCurrentMenuName);
@ -1035,13 +1046,15 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn,
// Note that the default is unaffected, intentionally so.
// There are effectively two levels of default, the full (max) list
// and the normal reduced list.
if( mMaxListOnly.Index( entry->key ) !=-1)
entry->key = wxT("");
if( std::binary_search( mMaxListOnly.begin(), mMaxListOnly.end(),
entry->key ) )
entry->key = {};
// Key from preferences overridse the default key given
// Key from preferences overrides the default key given
gPrefs->SetPath(wxT("/NewKeys"));
if (gPrefs->HasEntry(entry->name)) {
entry->key = KeyStringNormalize(gPrefs->Read(entry->name, entry->key));
entry->key =
NormalizedKeyString{ gPrefs->Read(entry->name, entry->key.Raw()) };
}
gPrefs->SetPath(wxT("/"));
@ -1074,7 +1087,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn,
#endif
mCommandNameHash[entry->name] = entry;
if (entry->key != wxT("")) {
if (!entry->key.empty()) {
mCommandKeyHash[entry->key] = entry;
}
@ -1084,9 +1097,9 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn,
wxString CommandManager::GetLabel(const CommandListEntry *entry) const
{
wxString label = entry->label;
if (!entry->key.IsEmpty())
if (!entry->key.empty())
{
label += wxT("\t") + entry->key;
label += wxT("\t") + entry->key.Raw();
}
return label;
@ -1103,7 +1116,7 @@ wxString CommandManager::GetLabelWithDisabledAccel(const CommandListEntry *entry
#if 1
wxString Accel = "";
do{
if (!entry->key.IsEmpty())
if (!entry->key.empty())
{
// Dummy accelerator that looks Ok in menus but is non functional.
// Note the space before the key.
@ -1136,7 +1149,7 @@ wxString CommandManager::GetLabelWithDisabledAccel(const CommandListEntry *entry
#endif
//wxLogDebug("Added Accel:[%s][%s]", entry->label, entry->key );
// Normal accelerator.
Accel = wxString("\t") + entry->key;
Accel = wxString("\t") + entry->key.Raw();
}
} while (false );
label += Accel;
@ -1251,18 +1264,19 @@ void CommandManager::Modify(const wxString &name, const wxString &newLabel)
}
}
void CommandManager::SetKeyFromName(const wxString &name, const wxString &key)
void CommandManager::SetKeyFromName(const wxString &name,
const NormalizedKeyString &key)
{
CommandListEntry *entry = mCommandNameHash[name];
if (entry) {
entry->key = KeyStringNormalize(key);
entry->key = key;
}
}
void CommandManager::SetKeyFromIndex(int i, const wxString &key)
void CommandManager::SetKeyFromIndex(int i, const NormalizedKeyString &key)
{
const auto &entry = mCommandList[i];
entry->key = KeyStringNormalize(key);
entry->key = key;
}
void CommandManager::TellUserWhyDisallowed( const wxString & Name, CommandFlag flagsGot, CommandMask flagsRequired )
@ -1352,7 +1366,7 @@ wxString CommandManager::DescribeCommandsAndShortcuts
if (!name.empty()) {
auto keyStr = GetKeyFromName(name);
if (!keyStr.empty()){
auto keyString = KeyStringDisplay(keyStr, true);
auto keyString = keyStr.Display(true);
auto format = wxT("%s %s(%s)");
#ifdef __WXMAC__
// The unicode controls push and pop left-to-right embedding.
@ -1649,8 +1663,8 @@ void CommandManager::GetAllCommandLabels(wxArrayString &names,
void CommandManager::GetAllCommandData(
wxArrayString &names,
wxArrayString &keys,
wxArrayString &default_keys,
std::vector<NormalizedKeyString> &keys,
std::vector<NormalizedKeyString> &default_keys,
wxArrayString &labels,
wxArrayString &categories,
#if defined(EXPERIMENTAL_KEY_VIEW)
@ -1662,8 +1676,8 @@ void CommandManager::GetAllCommandData(
if (!entry->multi)
{
names.Add(entry->name);
keys.Add(entry->key);
default_keys.Add(entry->defaultKey);
keys.push_back(entry->key);
default_keys.push_back(entry->defaultKey);
labels.Add(entry->label);
categories.Add(entry->labelTop);
#if defined(EXPERIMENTAL_KEY_VIEW)
@ -1673,8 +1687,8 @@ void CommandManager::GetAllCommandData(
else if( includeMultis )
{
names.Add(entry->name);
keys.Add(entry->key);
default_keys.Add(entry->defaultKey);
keys.push_back(entry->key);
default_keys.push_back(entry->defaultKey);
labels.Add(entry->label);
categories.Add(entry->labelTop);
#if defined(EXPERIMENTAL_KEY_VIEW)
@ -1727,22 +1741,22 @@ wxString CommandManager::GetCategoryFromName(const wxString &name)
return entry->labelTop;
}
wxString CommandManager::GetKeyFromName(const wxString &name) const
NormalizedKeyString CommandManager::GetKeyFromName(const wxString &name) const
{
CommandListEntry *entry =
// May create a NULL entry
const_cast<CommandManager*>(this)->mCommandNameHash[name];
if (!entry)
return wxT("");
return {};
return entry->key;
}
wxString CommandManager::GetDefaultKeyFromName(const wxString &name)
NormalizedKeyString CommandManager::GetDefaultKeyFromName(const wxString &name)
{
CommandListEntry *entry = mCommandNameHash[name];
if (!entry)
return wxT("");
return {};
return entry->defaultKey;
}
@ -1755,7 +1769,7 @@ bool CommandManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
if (!wxStrcmp(tag, wxT("command"))) {
wxString name;
wxString key;
NormalizedKeyString key;
while(*attrs) {
const wxChar *attr = *attrs++;
@ -1767,12 +1781,12 @@ bool CommandManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
if (!wxStrcmp(attr, wxT("name")) && XMLValueChecker::IsGoodString(value))
name = value;
if (!wxStrcmp(attr, wxT("key")) && XMLValueChecker::IsGoodString(value))
key = KeyStringNormalize(value);
key = NormalizedKeyString{ value };
}
if (mCommandNameHash[name]) {
if (GetDefaultKeyFromName(name) != key) {
mCommandNameHash[name]->key = KeyStringNormalize(key);
mCommandNameHash[name]->key = key;
mXMLKeysRead++;
}
}
@ -1809,7 +1823,7 @@ void CommandManager::WriteXML(XMLWriter &xmlFile) const
xmlFile.StartTag(wxT("command"));
xmlFile.WriteAttr(wxT("name"), entry->name);
xmlFile.WriteAttr(wxT("label"), label);
xmlFile.WriteAttr(wxT("key"), entry->key);
xmlFile.WriteAttr(wxT("key"), entry->key.Raw());
xmlFile.EndTag(wxT("command"));
}
@ -1865,7 +1879,7 @@ void CommandManager::CheckDups()
{
int cnt = mCommandList.size();
for (size_t j = 0; (int)j < cnt; j++) {
if (mCommandList[j]->key.IsEmpty()) {
if (mCommandList[j]->key.empty()) {
continue;
}
@ -1881,7 +1895,7 @@ void CommandManager::CheckDups()
if (mCommandList[i]->key == mCommandList[j]->key) {
wxString msg;
msg.Printf(wxT("key combo '%s' assigned to '%s' and '%s'"),
mCommandList[i]->key,
mCommandList[i]->key.Raw(),
mCommandList[i]->label.BeforeFirst(wxT('\t')),
mCommandList[j]->label.BeforeFirst(wxT('\t')));
wxASSERT_MSG(mCommandList[i]->key != mCommandList[j]->key, msg);

View File

@ -18,6 +18,7 @@
#include "CommandFlag.h"
#include "../MemoryX.h"
#include "Keyboard.h"
#include <vector>
#include <wx/string.h>
#include <wx/menu.h>
@ -63,8 +64,8 @@ struct CommandListEntry
{
int id;
wxString name;
wxString key;
wxString defaultKey;
NormalizedKeyString key;
NormalizedKeyString defaultKey;
wxString label;
wxString labelPrefix;
wxString labelTop;
@ -93,6 +94,27 @@ using SubMenuList = std::vector < movable_ptr<SubMenuListEntry> >;
// so we don't want the structures to relocate with vector operations.
using CommandList = std::vector<movable_ptr<CommandListEntry>>;
namespace std
{
#ifdef __AUDACITY_OLD_STD__
namespace tr1
{
#endif
template<typename T> struct hash;
template<> struct hash< NormalizedKeyString > {
size_t operator () (const NormalizedKeyString &str) const // noexcept
{
auto &stdstr = str.Raw(); // no allocations, a cheap fetch
using Hasher = hash< wxString >;
return Hasher{}( stdstr );
}
};
#ifdef __AUDACITY_OLD_STD__
}
#endif
}
using CommandKeyHash = std::unordered_map<NormalizedKeyString, CommandListEntry*>;
using CommandNameHash = std::unordered_map<wxString, CommandListEntry*>;
using CommandIDHash = std::unordered_map<int, CommandListEntry*>;
@ -234,8 +256,8 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
// Modifying accelerators
//
void SetKeyFromName(const wxString &name, const wxString &key);
void SetKeyFromIndex(int i, const wxString &key);
void SetKeyFromName(const wxString &name, const NormalizedKeyString &key);
void SetKeyFromIndex(int i, const NormalizedKeyString &key);
//
// Executing commands
@ -255,7 +277,9 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
void GetAllCommandNames(wxArrayString &names, bool includeMultis);
void GetAllCommandLabels(wxArrayString &labels, bool includeMultis);
void GetAllCommandData(
wxArrayString &names, wxArrayString &keys, wxArrayString &default_keys,
wxArrayString &names,
std::vector<NormalizedKeyString> &keys,
std::vector<NormalizedKeyString> &default_keys,
wxArrayString &labels, wxArrayString &categories,
#if defined(EXPERIMENTAL_KEY_VIEW)
wxArrayString &prefixes,
@ -266,8 +290,8 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
wxString GetLabelFromName(const wxString &name);
wxString GetPrefixedLabelFromName(const wxString &name);
wxString GetCategoryFromName(const wxString &name);
wxString GetKeyFromName(const wxString &name) const;
wxString GetDefaultKeyFromName(const wxString &name);
NormalizedKeyString GetKeyFromName(const wxString &name) const;
NormalizedKeyString GetDefaultKeyFromName(const wxString &name);
bool GetEnabled(const wxString &name);
@ -294,6 +318,9 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
// user-visible string.
const LocalizedCommandNameVector &commands) const;
// Sorted list of the shortcut keys to be exluded from the standard defaults
static const std::vector<NormalizedKeyString> &ExcludedList();
protected:
//
@ -352,14 +379,15 @@ protected:
XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
private:
// mMaxList only holds shortcuts that should not be added (by default).
wxSortedArrayString mMaxListOnly;
// mMaxList only holds shortcuts that should not be added (by default)
// and is sorted.
std::vector<NormalizedKeyString> mMaxListOnly;
MenuBarList mMenuBarList;
SubMenuList mSubMenuList;
CommandList mCommandList;
CommandNameHash mCommandNameHash;
CommandNameHash mCommandKeyHash;
CommandKeyHash mCommandKeyHash;
CommandIDHash mCommandIDHash;
int mCurrentID;
int mXMLKeysRead;

View File

@ -13,7 +13,7 @@
#include "Keyboard.h"
wxString KeyStringNormalize(const wxString & key)
NormalizedKeyString::NormalizedKeyString(const wxString & key)
{
#if defined(__WXMAC__)
wxString newkey;
@ -44,16 +44,16 @@ wxString KeyStringNormalize(const wxString & key)
newkey += wxT("Ctrl+");
}
return newkey + temp.AfterLast(wxT('+'));
(wxString&)*this = newkey + temp.AfterLast(wxT('+'));
#else
return key;
(wxString&)*this = key;
#endif
}
wxString KeyStringDisplay(const wxString & key, bool usesSpecialChars)
wxString NormalizedKeyString::Display(bool usesSpecialChars) const
{
(void)usesSpecialChars;//compiler food
wxString newkey = KeyStringNormalize(key);
wxString newkey = *this;
#if defined(__WXMAC__)
if (!usesSpecialChars) {
@ -75,7 +75,7 @@ wxString KeyStringDisplay(const wxString & key, bool usesSpecialChars)
return newkey;
}
wxString KeyEventToKeyString(const wxKeyEvent & event)
NormalizedKeyString KeyEventToKeyString(const wxKeyEvent & event)
{
wxString newStr = wxT("");
@ -332,9 +332,9 @@ wxString KeyEventToKeyString(const wxKeyEvent & event)
newStr += wxT("NUMPAD_DIVIDE");
break;
default:
return wxT(""); // Don't do anything if we don't recognize the key
return {}; // Don't do anything if we don't recognize the key
}
}
return KeyStringNormalize(newStr);
return NormalizedKeyString{ newStr };
}

View File

@ -9,10 +9,41 @@
**********************************************************************/
#ifndef __AUDACITY_KEYBOARD__
#define __AUDACITY_KEYBOARD__
#include <wx/defs.h>
#include <wx/event.h>
#include <wx/string.h>
wxString KeyStringNormalize(const wxString & key);
wxString KeyStringDisplay(const wxString & key, bool useSpecialChars = false);
wxString KeyEventToKeyString(const wxKeyEvent & keyEvent);
struct NormalizedKeyString : private wxString
{
NormalizedKeyString() = default;
explicit NormalizedKeyString( const wxString &str );
wxString Display(bool usesSpecialChars = false) const;
const wxString &Raw() const { return *this; }
bool NoCaseEqual( const NormalizedKeyString &other ) const
{ return 0 == this->Raw() .CmpNoCase( other.Raw() ); }
using wxString::empty;
};
inline bool operator ==
( const NormalizedKeyString &a, const NormalizedKeyString &b)
{ return a.Raw () == b.Raw(); }
inline bool operator !=
( const NormalizedKeyString &a, const NormalizedKeyString &b)
{ return a.Raw () != b.Raw(); }
inline bool operator <
( const NormalizedKeyString &a, const NormalizedKeyString &b)
{ return a.Raw () < b.Raw(); }
NormalizedKeyString KeyEventToKeyString(const wxKeyEvent & keyEvent);
#endif

View File

@ -271,9 +271,9 @@ void KeyConfigPrefs::RefreshBindings(bool bSort)
wxArrayString Prefixes;
mNames.Clear();
mKeys.Clear();
mDefaultKeys.Clear();
mStandardDefaultKeys.Clear();
mKeys.clear();
mDefaultKeys.clear();
mStandardDefaultKeys.clear();
mManager->GetAllCommandData(
mNames,
mKeys,
@ -363,69 +363,14 @@ void KeyConfigPrefs::OnDefaults(wxCommandEvent & WXUNUSED(event))
PopupMenu(&Menu);//, wxPoint(0, 0));
}
void KeyConfigPrefs::FilterKeys( wxArrayString & arr )
void KeyConfigPrefs::FilterKeys( std::vector<NormalizedKeyString> & arr )
{
wxSortedArrayString MaxListOnly;
const auto &MaxListOnly = CommandManager::ExcludedList();
// These short cuts are for the max list only....
//MaxListOnly.Add( "Ctrl+I" );
MaxListOnly.Add( "Ctrl+Alt+I" );
MaxListOnly.Add( "Ctrl+J" );
MaxListOnly.Add( "Ctrl+Alt+J" );
MaxListOnly.Add( "Ctrl+Alt+V" );
MaxListOnly.Add( "Alt+X" );
MaxListOnly.Add( "Alt+K" );
MaxListOnly.Add( "Shift+Alt+X" );
MaxListOnly.Add( "Shift+Alt+K" );
MaxListOnly.Add( "Alt+L" );
MaxListOnly.Add( "Shift+Alt+C" );
MaxListOnly.Add( "Alt+I" );
MaxListOnly.Add( "Alt+J" );
MaxListOnly.Add( "Shift+Alt+J" );
MaxListOnly.Add( "Ctrl+Shift+A" );
MaxListOnly.Add( "Q" );
//MaxListOnly.Add( "Shift+J" );
//MaxListOnly.Add( "Shift+K" );
//MaxListOnly.Add( "Shift+Home" );
//MaxListOnly.Add( "Shift+End" );
MaxListOnly.Add( "Ctrl+[" );
MaxListOnly.Add( "Ctrl+]" );
MaxListOnly.Add( "1" );
MaxListOnly.Add( "Shift+F5" );
MaxListOnly.Add( "Shift+F6" );
MaxListOnly.Add( "Shift+F7" );
MaxListOnly.Add( "Shift+F8" );
MaxListOnly.Add( "Ctrl+Shift+F5" );
MaxListOnly.Add( "Ctrl+Shift+F7" );
MaxListOnly.Add( "Ctrl+Shift+N" );
MaxListOnly.Add( "Ctrl+Shift+M" );
MaxListOnly.Add( "Ctrl+Home" );
MaxListOnly.Add( "Ctrl+End" );
MaxListOnly.Add( "Shift+C" );
MaxListOnly.Add( "Alt+Shift+Up" );
MaxListOnly.Add( "Alt+Shift+Down" );
MaxListOnly.Add( "Shift+P" );
MaxListOnly.Add( "Alt+Shift+Left" );
MaxListOnly.Add( "Alt+Shift+Right" );
MaxListOnly.Add( "Ctrl+Shift+T" );
//MaxListOnly.Add( "Command+M" );
//MaxListOnly.Add( "Option+Command+M" );
MaxListOnly.Add( "Shift+H" );
MaxListOnly.Add( "Shift+O" );
MaxListOnly.Add( "Shift+I" );
MaxListOnly.Add( "Shift+N" );
MaxListOnly.Add( "D" );
MaxListOnly.Add( "A" );
MaxListOnly.Add( "Alt+Shift+F6" );
MaxListOnly.Add( "Alt+F6" );
std::transform( MaxListOnly.begin(), MaxListOnly.end(), MaxListOnly.begin(),
KeyStringNormalize );
MaxListOnly.Sort();
// Remove items that are in MaxList.
for (size_t i = 0; i < arr.GetCount(); i++) {
if( MaxListOnly.Index( arr[i] ) != wxNOT_FOUND )
arr[i]= wxT("");
for (size_t i = 0; i < arr.size(); i++) {
if( std::binary_search(MaxListOnly.begin(), MaxListOnly.end(), arr[i]) )
arr[i] = {};
}
}
@ -438,7 +383,7 @@ void KeyConfigPrefs::OnImportDefaults(wxCommandEvent & event)
if( event.GetId() == 1 )
FilterKeys( mNewKeys );
for (size_t i = 0; i < mNewKeys.GetCount(); i++) {
for (size_t i = 0; i < mNewKeys.size(); i++) {
mManager->SetKeyFromIndex(i, mNewKeys[i]);
}
@ -464,7 +409,7 @@ void KeyConfigPrefs::OnHotkeyKeyDown(wxKeyEvent & e)
return;
}
t->SetValue(KeyStringDisplay(KeyEventToKeyString(e)));
t->SetValue(KeyEventToKeyString(e).Display());
}
void KeyConfigPrefs::OnHotkeyChar(wxKeyEvent & WXUNUSED(e))
@ -475,7 +420,7 @@ void KeyConfigPrefs::OnHotkeyChar(wxKeyEvent & WXUNUSED(e))
void KeyConfigPrefs::OnHotkeyKillFocus(wxFocusEvent & e)
{
if (mKey->GetValue().IsEmpty() && mCommandSelected != wxNOT_FOUND) {
mKey->AppendText(mView->GetKey(mCommandSelected));
mKey->AppendText(mView->GetKey(mCommandSelected).Display());
}
e.Skip();
@ -511,7 +456,7 @@ void KeyConfigPrefs::OnFilterKeyDown(wxKeyEvent & e)
}
if (mViewType == ViewByKey) {
wxString key = KeyStringDisplay(KeyEventToKeyString(e));
wxString key = KeyEventToKeyString(e).Display();
t->SetValue(key);
if (key != wxEmptyString) {
@ -543,14 +488,14 @@ void KeyConfigPrefs::OnFilterChar(wxKeyEvent & e)
// Given a hotkey combination, returns the name (description) of the
// corresponding command, or the empty string if none is found.
wxString KeyConfigPrefs::NameFromKey(const wxString & key)
wxString KeyConfigPrefs::NameFromKey(const NormalizedKeyString & key)
{
return mView->GetNameByKey(key);
}
// Sets the selected command to have this key
// This is not yet a committed change, which will happen on a save.
void KeyConfigPrefs::SetKeyForSelected(const wxString & key)
void KeyConfigPrefs::SetKeyForSelected(const NormalizedKeyString & key)
{
wxString name = mView->GetName(mCommandSelected);
@ -575,7 +520,7 @@ void KeyConfigPrefs::OnSet(wxCommandEvent & WXUNUSED(event))
return;
}
wxString key = mKey->GetValue();
NormalizedKeyString key { mKey->GetValue() };
wxString oldname = mView->GetNameByKey(key);
wxString newname = mView->GetName(mCommandSelected);
@ -595,7 +540,7 @@ void KeyConfigPrefs::OnSet(wxCommandEvent & WXUNUSED(event))
if (AudacityMessageBox(
wxString::Format(
_("The keyboard shortcut '%s' is already assigned to:\n\n\t'%s'\n\nClick OK to assign the shortcut to\n\n\t'%s'\n\ninstead. Otherwise, click Cancel."),
key,
mKey->GetValue(),
oldlabel,
newlabel),
_("Error"), wxOK | wxCANCEL | wxICON_STOP | wxCENTRE, this) == wxCANCEL)
@ -603,9 +548,9 @@ void KeyConfigPrefs::OnSet(wxCommandEvent & WXUNUSED(event))
return;
}
mView->SetKeyByName(oldname, wxEmptyString);
mManager->SetKeyFromName(oldname, wxEmptyString);
mNewKeys[mNames.Index(oldname)].Empty();
mView->SetKeyByName(oldname, {});
mManager->SetKeyFromName(oldname, {});
mNewKeys[mNames.Index(oldname)] = {};
}
@ -617,7 +562,7 @@ void KeyConfigPrefs::OnClear(wxCommandEvent& WXUNUSED(event))
mKey->Clear();
if (mCommandSelected != wxNOT_FOUND) {
SetKeyForSelected(wxEmptyString);
SetKeyForSelected({});
}
}
@ -629,7 +574,7 @@ void KeyConfigPrefs::OnSelected(wxCommandEvent & WXUNUSED(e))
if (mCommandSelected != wxNOT_FOUND) {
bool canset = mView->CanSetKey(mCommandSelected);
if (canset) {
mKey->AppendText(mView->GetKey(mCommandSelected));
mKey->AppendText(mView->GetKey(mCommandSelected).Display());
}
mKey->Enable(canset);
@ -678,13 +623,13 @@ bool KeyConfigPrefs::Commit()
bool bFull = gPrefs->ReadBool(wxT("/GUI/Shortcuts/FullDefaults"), false);
for (size_t i = 0; i < mNames.GetCount(); i++) {
wxString dkey = bFull ? KeyStringNormalize(mDefaultKeys[i]) : KeyStringNormalize(mStandardDefaultKeys[i]);
const auto &dkey = bFull ? mDefaultKeys[i] : mStandardDefaultKeys[i];
wxString name = wxT("/NewKeys/") + mNames[i];
wxString key = KeyStringNormalize(mNewKeys[i]);
const auto &key = mNewKeys[i];
if (gPrefs->HasEntry(name)) {
if (key != KeyStringNormalize(gPrefs->Read(name, key))) {
gPrefs->Write(name, key);
if (key != NormalizedKeyString{ gPrefs->Read(name, key.Raw()) } ) {
gPrefs->Write(name, key.Raw());
}
if (key == dkey) {
gPrefs->DeleteEntry(name);
@ -692,7 +637,7 @@ bool KeyConfigPrefs::Commit()
}
else {
if (key != dkey) {
gPrefs->Write(name, key);
gPrefs->Write(name, key.Raw());
}
}
}

View File

@ -31,6 +31,7 @@ class ShuttleGui;
#include "PrefsPanel.h"
class wxStaticText;
struct NormalizedKeyString;
class KeyConfigPrefs final : public PrefsPanel
{
@ -44,9 +45,9 @@ private:
void Populate();
void PopulateOrExchange(ShuttleGui & S);
void RefreshBindings(bool bSort);
void FilterKeys( wxArrayString & arr );
wxString NameFromKey(const wxString & key);
void SetKeyForSelected(const wxString & key);
void FilterKeys( std::vector<NormalizedKeyString> & arr );
wxString NameFromKey(const NormalizedKeyString & key);
void SetKeyForSelected(const NormalizedKeyString & key);
void OnViewBy(wxCommandEvent & e);
void OnDefaults(wxCommandEvent & e);
@ -84,10 +85,10 @@ private:
int mCommandSelected;
wxArrayString mNames;
wxArrayString mDefaultKeys; // The full set.
wxArrayString mStandardDefaultKeys; // The reduced set.
wxArrayString mKeys;
wxArrayString mNewKeys; // Used for work in progress.
std::vector<NormalizedKeyString> mDefaultKeys; // The full set.
std::vector<NormalizedKeyString> mStandardDefaultKeys; // The reduced set.
std::vector<NormalizedKeyString> mKeys;
std::vector<NormalizedKeyString> mNewKeys; // Used for work in progress.
DECLARE_EVENT_TABLE()
};

View File

@ -913,14 +913,14 @@ HitTestPreview SelectHandle::Preview
if (bMultiToolMode) {
// Look up the current key binding for Preferences.
// (Don't assume it's the default!)
wxString keyStr
(pProject->GetCommandManager()->GetKeyFromName(wxT("Preferences")));
if (keyStr.IsEmpty())
auto keyStr =
pProject->GetCommandManager()->GetKeyFromName(wxT("Preferences"))
.Display( true );
if (keyStr.empty())
// No keyboard preference defined for opening Preferences dialog
/* i18n-hint: These are the names of a menu and a command in that menu */
keyStr = _("Edit, Preferences...");
else
keyStr = KeyStringDisplay(keyStr);
/* i18n-hint: %s is usually replaced by "Ctrl+P" for Windows/Linux, "Command+," for Mac */
tip = wxString::Format(
_("Multi-Tool Mode: %s for Mouse and Keyboard Preferences."),

View File

@ -125,30 +125,31 @@ BEGIN_POPUP_MENU(TrackMenuTable)
POPUP_MENU_ITEM(OnSetNameID, _("&Name..."), OnSetName)
POPUP_MENU_SEPARATOR()
POPUP_MENU_ITEM(
// It is not correct to use KeyStringDisplay here -- wxWidgets will apply
// its equivalent to the key names passed to menu functions.
// It is not correct to use NormalizedKeyString::Display here --
// wxWidgets will apply its equivalent to the key names passed to menu
// functions.
OnMoveUpID,
_("Move Track &Up") + wxT("\t") +
(GetActiveProject()->GetCommandManager()->
GetKeyFromName(wxT("TrackMoveUp"))),
GetKeyFromName(wxT("TrackMoveUp")).Raw()),
OnMoveTrack)
POPUP_MENU_ITEM(
OnMoveDownID,
_("Move Track &Down") + wxT("\t") +
(GetActiveProject()->GetCommandManager()->
GetKeyFromName(wxT("TrackMoveDown"))),
GetKeyFromName(wxT("TrackMoveDown")).Raw()),
OnMoveTrack)
POPUP_MENU_ITEM(
OnMoveTopID,
_("Move Track to &Top") + wxT("\t") +
(GetActiveProject()->GetCommandManager()->
GetKeyFromName(wxT("TrackMoveTop"))),
GetKeyFromName(wxT("TrackMoveTop")).Raw()),
OnMoveTrack)
POPUP_MENU_ITEM(
OnMoveBottomID,
_("Move Track to &Bottom") + wxT("\t") +
(GetActiveProject()->GetCommandManager()->
GetKeyFromName(wxT("TrackMoveBottom"))),
GetKeyFromName(wxT("TrackMoveBottom")).Raw()),
OnMoveTrack)
END_POPUP_MENU()

View File

@ -178,14 +178,14 @@ KeyView::GetName(int index) const
// Returns the command manager index for the given key combination
//
wxString
KeyView::GetNameByKey(const wxString & key) const
KeyView::GetNameByKey(const NormalizedKeyString & key) const
{
int cnt = (int) mNodes.size();
// Search the nodes for the key
for (int i = 0; i < cnt; i++)
{
if (key.CmpNoCase(mNodes[i].key) == 0)
if (key.NoCaseEqual( mNodes[i].key))
{
return mNodes[i].name;
}
@ -198,14 +198,14 @@ KeyView::GetNameByKey(const wxString & key) const
// Returns the index for the given key
//
int
KeyView::GetIndexByKey(const wxString & key) const
KeyView::GetIndexByKey(const NormalizedKeyString & key) const
{
int cnt = (int) mNodes.size();
// Search the nodes for the key
for (int i = 0; i < cnt; i++)
{
if (key.CmpNoCase(mNodes[i].key) == 0)
if (key.NoCaseEqual( mNodes[i].key))
{
return mNodes[i].index;
}
@ -217,14 +217,14 @@ KeyView::GetIndexByKey(const wxString & key) const
//
// Returns the key for the given index
//
wxString
NormalizedKeyString
KeyView::GetKey(int index) const
{
// Make sure index is valid
if (index < 0 || index >= (int) mNodes.size())
{
wxASSERT(false);
return wxEmptyString;
return {};
}
return mNodes[index].key;
@ -251,7 +251,7 @@ KeyView::CanSetKey(int index) const
// Sets the key for the given index
//
bool
KeyView::SetKey(int index, const wxString & key)
KeyView::SetKey(int index, const NormalizedKeyString & key)
{
// Make sure index is valid
if (index < 0 || index >= (int) mNodes.size())
@ -274,7 +274,7 @@ KeyView::SetKey(int index, const wxString & key)
// Check to see if the key column needs to be expanded
int x, y;
GetTextExtent(node.key, &x, &y);
GetTextExtent(node.key.Display(), &x, &y);
if (x > mKeyWidth || y > mLineHeight)
{
// New key is wider than column so recalc extents (will refresh view)
@ -292,7 +292,7 @@ KeyView::SetKey(int index, const wxString & key)
// Sets the key for the given name
//
bool
KeyView::SetKeyByName(const wxString & name, const wxString & key)
KeyView::SetKeyByName(const wxString & name, const NormalizedKeyString & key)
{
int index = GetIndexByName(name);
@ -465,7 +465,7 @@ KeyView::RecalcExtents()
else
{
// Measure the key
GetTextExtent(node.key, &x, &y);
GetTextExtent(node.key.Display(), &x, &y);
mLineHeight = wxMax(mLineHeight, y);
mKeyWidth = wxMax(mKeyWidth, x);
@ -531,7 +531,7 @@ KeyView::RefreshBindings(const wxArrayString & names,
const wxArrayString & categories,
const wxArrayString & prefixes,
const wxArrayString & labels,
const wxArrayString & keys,
const std::vector<NormalizedKeyString> & keys,
bool bSort
)
{
@ -676,7 +676,7 @@ KeyView::RefreshBindings(const wxArrayString & names,
// Fill in remaining info
node.name = name;
node.key = KeyStringDisplay(keys[i]);
node.key = keys[i];
node.index = nodecnt++;
node.depth = depth;
@ -684,7 +684,7 @@ KeyView::RefreshBindings(const wxArrayString & names,
mNodes.push_back(node);
// Measure key
GetTextExtent(node.key, &x, &y);
GetTextExtent(node.key.Display(), &x, &y);
mLineHeight = wxMax(mLineHeight, y);
mKeyWidth = wxMax(mKeyWidth, x);
@ -767,7 +767,7 @@ KeyView::RefreshLines(bool bSort)
case ViewByTree:
searchit = node.label.Lower() +
wxT("\01x") +
node.key.Lower();
node.key.Display().Lower();
break;
case ViewByName:
@ -775,7 +775,7 @@ KeyView::RefreshLines(bool bSort)
break;
case ViewByKey:
searchit = node.key.Lower();
searchit = node.key.Display().Lower();
break;
}
if (searchit.Find(mFilter) == wxNOT_FOUND)
@ -1175,7 +1175,7 @@ KeyView::OnDrawItem(wxDC & dc, const wxRect & rect, size_t line) const
x += KV_LEFT_MARGIN;
// Draw the key and command columns
dc.DrawText(node->key, x , rect.y);
dc.DrawText(node->key.Display(), x , rect.y);
dc.DrawText(label, x + mKeyWidth + KV_COLUMN_SPACER + node->depth * KV_BITMAP_SIZE, rect.y);
}
else
@ -1193,7 +1193,7 @@ KeyView::OnDrawItem(wxDC & dc, const wxRect & rect, size_t line) const
if((mViewType == ViewByName) || (mViewType == ViewByKey))
{
// Draw key columnd and then command column
dc.DrawText(node->key, x, rect.y);
dc.DrawText(node->key.Display(), x, rect.y);
dc.DrawText(label, x + mKeyWidth + KV_COLUMN_SPACER, rect.y);
}
}
@ -1446,7 +1446,7 @@ KeyView::OnKeyDown(wxKeyEvent & event)
}
else if (mViewType == ViewByKey)
{
label = GetKey(LineToIndex(i));
label = GetKey(LineToIndex(i)).Display();
}
// Move selection if they match
@ -1480,7 +1480,7 @@ KeyView::OnKeyDown(wxKeyEvent & event)
}
else if (mViewType == ViewByKey)
{
label = GetKey(LineToIndex(i));
label = GetKey(LineToIndex(i)).Display();
}
// Move selection if they match
@ -1638,8 +1638,8 @@ KeyView::CmpKeyNodeByName(KeyNode *t1, KeyNode *t2)
bool
KeyView::CmpKeyNodeByKey(KeyNode *t1, KeyNode *t2)
{
wxString k1 = t1->key;
wxString k2 = t2->key;
wxString k1 = t1->key.Display();
wxString k2 = t2->key.Display();
// Left node is unassigned, so prefix it
if(k1.IsEmpty())
@ -1748,7 +1748,7 @@ KeyView::GetValue(int line)
{
value = GetFullLabel(index);
}
wxString key = GetKey(index);
wxString key = GetKey(index).Display();
// Add the key if it isn't empty
if (!key.IsEmpty())

View File

@ -41,7 +41,7 @@ public:
wxString category;
wxString prefix;
wxString label;
wxString key;
NormalizedKeyString key;
int index;
int line;
int depth;
@ -83,7 +83,7 @@ public:
const wxArrayString & categories,
const wxArrayString & prefixes,
const wxArrayString & labels,
const wxArrayString & keys,
const std::vector<NormalizedKeyString> & keys,
bool bSort);
int GetSelected() const;
@ -93,13 +93,13 @@ public:
int GetIndexByName(const wxString & name) const;
wxString GetName(int index) const;
wxString GetNameByKey(const wxString & key) const;
wxString GetNameByKey(const NormalizedKeyString & key) const;
int GetIndexByKey(const wxString & key) const;
wxString GetKey(int index) const;
int GetIndexByKey(const NormalizedKeyString & key) const;
NormalizedKeyString GetKey(int index) const;
bool CanSetKey(int index) const;
bool SetKey(int index, const wxString & key);
bool SetKeyByName(const wxString & name, const wxString & key);
bool SetKey(int index, const NormalizedKeyString & key);
bool SetKeyByName(const wxString & name, const NormalizedKeyString & key);
void SetView(ViewByType type);