31#include <wx/radiobut.h>
32#include <wx/stattext.h>
33#include <wx/statbox.h>
34#include <wx/textctrl.h>
39#include "../ProjectWindows.h"
40#include "../commands/CommandManager.h"
48#include "../widgets/BasicMenu.h"
49#include "../widgets/KeyView.h"
53#if wxUSE_ACCESSIBILITY
60#define AssignDefaultsButtonID 17001
61#define CurrentComboID 17002
62#define SetButtonID 17003
63#define ClearButtonID 17004
64#define CommandsListID 17005
65#define ExportButtonID 17006
66#define ImportButtonID 17007
68#define ViewByTreeID 17009
69#define ViewByNameID 17010
70#define ViewByKeyID 17011
71#define FilterTimerID 17012
74#define EMPTY_SHORTCUT ("")
76#define NO_SHORTCUT (wxString)((wxChar)7)
100 , mProject{ pProject }
104 auto index = mView->GetIndexByName(
name);
105 mView->SelectNode(index);
120 return XO(
"Preferences for KeyConfig");
125 return "Keyboard_Preferences";
133 S.StartVerticalLay(
true);
135 S.StartStatic( {},
true);
137 S.AddTitle(
XO(
"Keyboard preferences currently unavailable."));
138 S.AddTitle(
XO(
"Open a new project to modify keyboard shortcuts."));
180 {
wxT(
"tree"),
XXO(
"&Tree") },
181 {
wxT(
"name"),
XXO(
"&Name") },
182 {
wxT(
"key"),
XXO(
"&Key") },
189 S.StartStatic(
XO(
"Key Bindings"), 1);
191 S.StartHorizontalLay(wxEXPAND, 0);
193 S.Position(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL).AddTitle(
XO(
"View by:"));
199 S.StartHorizontalLay();
204 .Name(
XO(
"View by tree"))
207 .Name(
XO(
"View by name"))
210 .Name(
XO(
"View by key"))
212#if !defined(__WXMAC__) && wxUSE_ACCESSIBILITY
219 S.EndRadioButtonGroup();
221 S.EndHorizontalLay();
225 S.AddSpace(wxDefaultCoord, wxDefaultCoord, 1);
227 S.StartHorizontalLay(wxALIGN_CENTER_VERTICAL, 0);
229 mFilterLabel =
S.Position(wxALIGN_CENTER_VERTICAL).AddVariableText(
XO(
"Searc&h:"));
236#
if defined(__WXMAC__)
244 S.Position(wxALIGN_NOT | wxALIGN_LEFT)
245 .ConnectRoot(wxEVT_KEY_DOWN,
247 .ConnectRoot(wxEVT_CHAR,
251 S.EndHorizontalLay();
253 S.EndHorizontalLay();
255 S.AddSpace(wxDefaultCoord, 2);
257 S.StartHorizontalLay(wxEXPAND, 1);
261 mView->SetName(
_(
"Bindings"));
267 S.EndHorizontalLay();
269 S.StartThreeColumn();
276#
if defined(__WXMAC__)
282#if !defined(__WXMAC__) && wxUSE_ACCESSIBILITY
286 mKey->SetName(
_(
"Short cut"));
289 .ConnectRoot(wxEVT_KEY_DOWN,
291 .ConnectRoot(wxEVT_CHAR,
293 .ConnectRoot(wxEVT_KILL_FOCUS,
295 .ConnectRoot(wxEVT_CONTEXT_MENU,
306#if defined(__WXMAC__)
307 S.AddFixedText(
XO(
"Note: Pressing Cmd+Q will quit. All other keys are valid."));
310 S.StartThreeColumn();
375 for (
const auto & command :
mNames)
387 using IndexesArray = std::vector<int>;
388 std::unordered_map<NormalizedKeyString, IndexesArray> seen;
390 for (
size_t i{ 0 }; i <
mKeys.size(); i++)
395 if (seen.count(
mKeys[i]) == 0)
396 seen.insert({
mKeys[i], {(int)i} });
399 IndexesArray checkMe{ seen.at(
mKeys[i]) };
400 for (
int index : checkMe)
410 seen.at(
mKeys[i]).push_back(index);
425 const std::vector<NormalizedKeyString> &toAdd)
429 auto searchAddInKeys = [&](
size_t index)
431 for (
size_t k{ 0 }; k < toAdd.size(); k++)
434 else if (toAdd[index] ==
mKeys[k] &&
444 for (
size_t i{ 0 }; i < toAdd.size(); i++)
452 int sRes{ searchAddInKeys(i) };
462"\n * \"%s\" (because the shortcut \'%s\' is used by \"%s\")\n")
473 return disabledShortcuts;
484 if (event.IsShown() &&
mView !=
nullptr)
492 wxString file =
wxT(
"Audacity-keys.xml");
495 XO(
"Select an XML file containing Audacity keyboard shortcuts..."),
512 const std::vector<NormalizedKeyString> oldKeys{
mKeys };
522 XO(
"Error Importing Keyboard Shortcuts"),
537 for (
size_t k{ 0 }; k <
mNames.size(); k++)
544"The file with the shortcuts contains illegal shortcut duplicates for \"%s\" and \"%s\".\nNothing is imported.")
545 .
Format( fMatching, sMatching ),
546 XO(
"Error Importing Keyboard Shortcuts"),
547 wxICON_ERROR | wxCENTRE,
this);
561 if (disabledShortcuts.Translation() != (
""))
562 message +=
XO(
"\nThe following commands are not mentioned in the imported file, "
563 "but have their shortcuts removed because of the conflict with other new shortcuts:\n") +
571 wxString file =
wxT(
"Audacity-keys.xml");
573 file =
SelectFile(FileNames::Operation::Export,
574 XO(
"Export Keyboard Shortcuts As:"),
579 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
587 XMLFileWriter prefFile{ file,
XO(
"Error Exporting Keyboard Shortcuts") };
600 Menu.Append( 1,
_(
"Standard") );
601 Menu.Append( 2,
_(
"Full") );
611 for (
size_t i = 0; i < arr.size(); i++) {
612 if( std::binary_search(MaxListOnly.begin(), MaxListOnly.end(), arr[i]) )
623 if( event.GetId() == 1 )
626 for (
size_t i = 0; i <
mNewKeys.size(); i++) {
635 wxTextCtrl *t = (wxTextCtrl *)e.GetEventObject();
645 if (e.GetKeyCode() == WXK_TAB) {
646 t->Navigate(e.ShiftDown()
647 ? wxNavigationKeyEvent::IsBackward
648 : wxNavigationKeyEvent::IsForward);
686 wxTextCtrl *t = (wxTextCtrl *)e.GetEventObject();
687 int keycode = e.GetKeyCode();
692 if (keycode == WXK_TAB) {
693 wxNavigationKeyEvent nevent;
694 nevent.SetWindowChange(e.ControlDown());
695 nevent.SetDirection(!e.ShiftDown());
696 nevent.SetEventObject(t);
697 nevent.SetCurrentFocus(t);
698 t->GetParent()->GetEventHandler()->ProcessEvent(nevent);
713 if (keycode == WXK_RETURN) {
750 XO(
"You may not assign a key to this entry"),
752 wxICON_ERROR | wxCENTRE,
767 XO(
"You must select a binding before assigning a shortcut"),
769 wxICON_WARNING | wxCENTRE,
781 for (
size_t i{ 0 }; i <
mNames.size(); i++)
786 if (
mNames[i] == newCommand)
792 oldCommands.push_back(
mNames[i]);
798 if (!oldCommands.empty()) {
808 for (
size_t i{ 1 }; i < oldCommands.size(); i++)
809 oldlabel +=
XO(
"\n\n\t and\n\n\t") +
816"The keyboard shortcut '%s' is already assigned to:\n\n\t%s\n\n\nClick OK to assign the shortcut to\n\n\t%s\n\ninstead. Otherwise, click Cancel.")
823 wxOK | wxCANCEL | wxICON_STOP | wxCENTRE,
829 for (
const auto & command : oldCommands)
860 mKey->Enable(canset);
861 mSet->Enable(canset);
905 for (
size_t i = 0; i <
mNames.size(); i++) {
932 for (
size_t i = 0; i <
mNames.size(); i++) {
942 return [=](wxWindow *parent, wxWindowID winid,
AudacityProject *pProject)
Handle changing of active project and keep global project pointer.
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), F3 delayedHandler=DefaultDelayedHandlerAction) noexcept(noexcept(handler(std::declval< AudacityException * >())) &&noexcept(handler(nullptr)) &&noexcept(std::function< void(AudacityException *)>{std::move(delayedHandler)}))
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
static const AudacityProject::AttachedObjects::RegisteredFactory key
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
XXO("&Cut/Copy/Paste Toolbar")
std::vector< CommandID > CommandIDs
PrefsPanel::Factory KeyConfigPrefsFactory(const CommandID &name)
#define AssignDefaultsButtonID
#define KEY_CONFIG_PREFS_PLUGIN_SYMBOL
NormalizedKeyString KeyEventToKeyString(const wxKeyEvent &event)
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
audacity::BasicSettings * gPrefs
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::vector< TranslatableString > TranslatableStrings
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
void Popup(const BasicUI::WindowPlacement &window, const Point &pos={})
Display the menu at pos, invoke at most one action, then hide it.
void WriteXML(XMLWriter &xmlFile) const
static CommandManager & Get(AudacityProject &project)
TranslatableString GetCategoryFromName(const CommandID &name)
void GetAllCommandData(CommandIDs &names, std::vector< NormalizedKeyString > &keys, std::vector< NormalizedKeyString > &default_keys, TranslatableStrings &labels, TranslatableStrings &categories, bool includeMultis)
static const std::vector< NormalizedKeyString > & ExcludedList()
void SetKeyFromName(const CommandID &name, const NormalizedKeyString &key)
NormalizedKeyString GetKeyFromName(const CommandID &name) const
NormalizedKeyString GetDefaultKeyFromName(const CommandID &name)
void SetKeyFromIndex(int i, const NormalizedKeyString &key)
int GetNumberOfKeysRead() const
TranslatableString GetPrefixedLabelFromName(const CommandID &name)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
FILES_API const FileType XMLFiles
FILES_API const FileType AllFiles
const wxString & GET() const
Explicit conversion to wxString, meant to be ugly-looking and demanding of a comment why it's correct...
A PrefsPanel for keybindings.
void OnFilterKeyDown(wxKeyEvent &e)
void OnImport(wxCommandEvent &e)
void OnHotkeyChar(wxEvent &e)
void OnImportDefaults(wxCommandEvent &e)
TranslatableString MergeWithExistingKeys(const std::vector< NormalizedKeyString > &toAdd)
void OnHotkeyKillFocus(wxEvent &e)
wxStaticText * mFilterLabel
TranslatableString GetDescription() const override
CommandManager * mManager
void PopulateOrExchange(ShuttleGui &S) override
std::vector< NormalizedKeyString > mDefaultKeys
AudacityProject * mProject
ComponentInterfaceSymbol GetSymbol() const override
void FilterKeys(std::vector< NormalizedKeyString > &arr)
void OnSet(wxCommandEvent &e)
bool ContainsIllegalDups(TranslatableString &fMatching, TranslatableString &sMatching) const
void OnHotkeyContext(wxEvent &e)
void OnFilterChar(wxEvent &e)
ManualPageID HelpPageName() override
If not empty string, the Help button is added below the panel.
void OnFilterTimer(wxTimerEvent &e)
CommandID NameFromKey(const NormalizedKeyString &key)
std::vector< NormalizedKeyString > mStandardDefaultKeys
std::vector< NormalizedKeyString > mNewKeys
std::vector< NormalizedKeyString > mKeys
void OnClear(wxCommandEvent &e)
wxRadioButton * mViewByKey
wxRadioButton * mViewByTree
void OnExport(wxCommandEvent &e)
void OnSelected(wxCommandEvent &e)
wxRadioButton * mViewByName
void OnViewBy(wxCommandEvent &e)
void OnDefaults(wxCommandEvent &e)
void RefreshBindings(bool bSort)
void OnShow(wxShowEvent &e)
void OnHotkeyKeyDown(wxKeyEvent &e)
void SetKeyForSelected(const NormalizedKeyString &key)
Provides multiple views of keyboard shortcuts.
bool CanSetKey(int index) const
bool SetKey(int index, const NormalizedKeyString &key)
void SetView(ViewByType type)
void SetFilter(const wxString &filter)
NormalizedKeyString GetKey(int index) const
void RefreshBindings(const CommandIDs &names, const TranslatableStrings &categories, const TranslatableStrings &prefixes, const TranslatableStrings &labels, const std::vector< NormalizedKeyString > &keys, bool bSort)
bool SetKeyByName(const CommandID &name, const NormalizedKeyString &key)
wxString GetName() const override
CommandID GetNameByKey(const NormalizedKeyString &key) const
Base class for a panel in the PrefsDialog. Classes derived from this class include BatchPrefs,...
std::function< PrefsPanel *(wxWindow *parent, wxWindowID winid, AudacityProject *) > Factory
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Holds a msgid for the translation catalog; may also bind format arguments.
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
Reads a file and passes the results through an XMLTagHandler.
const TranslatableString & GetErrorStr() const
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Wrapper to output XML data to files.
T ReadObject(const wxString &key, const T &defaultValue) const
virtual bool Flush() noexcept=0
virtual bool HasEntry(const wxString &key) const =0
Checks whether specified key exists within the current group.
virtual bool Write(const wxString &key, bool value)=0
bool ReadBool(const wxString &key, bool defaultValue) const
bool DeleteEntry(const wxString &key)
Deletes specified entry if exists.
PrefsPanel::Registration sAttachment
wxString Display(bool usesSpecialChars=false) const