28#include <wx/radiobut.h>
29#include <wx/stattext.h>
30#include <wx/statbox.h>
31#include <wx/textctrl.h>
37#include "../ProjectWindows.h"
45#include "../widgets/BasicMenu.h"
46#include "../widgets/KeyView.h"
50#if wxUSE_ACCESSIBILITY
57#define AssignDefaultsButtonID 17001
58#define CurrentComboID 17002
59#define SetButtonID 17003
60#define ClearButtonID 17004
61#define CommandsListID 17005
62#define ExportButtonID 17006
63#define ImportButtonID 17007
65#define ViewByTreeID 17009
66#define ViewByNameID 17010
67#define ViewByKeyID 17011
68#define FilterTimerID 17012
71#define EMPTY_SHORTCUT ("")
73#define NO_SHORTCUT (wxString)((wxChar)7)
97 , mProject{ pProject }
101 auto index = mView->GetIndexByName(
name);
102 mView->SelectNode(index);
117 return XO(
"Preferences for KeyConfig");
122 return "Keyboard_Preferences";
130 S.StartVerticalLay(
true);
132 S.StartStatic( {},
true);
134 S.AddTitle(
XO(
"Keyboard preferences currently unavailable."));
135 S.AddTitle(
XO(
"Open a new project to modify keyboard shortcuts."));
177 {
wxT(
"tree"),
XXO(
"&Tree") },
178 {
wxT(
"name"),
XXO(
"&Name") },
179 {
wxT(
"key"),
XXO(
"&Key") },
186 S.StartStatic(
XO(
"Key Bindings"), 1);
188 S.StartHorizontalLay(wxEXPAND, 0);
190 S.Position(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL).AddTitle(
XO(
"View by:"));
196 S.StartHorizontalLay();
201 .Name(
XO(
"View by tree"))
204 .Name(
XO(
"View by name"))
207 .Name(
XO(
"View by key"))
209#if !defined(__WXMAC__) && wxUSE_ACCESSIBILITY
216 S.EndRadioButtonGroup();
218 S.EndHorizontalLay();
222 S.AddSpace(wxDefaultCoord, wxDefaultCoord, 1);
224 S.StartHorizontalLay(wxALIGN_CENTER_VERTICAL, 0);
226 mFilterLabel =
S.Position(wxALIGN_CENTER_VERTICAL).AddVariableText(
XO(
"Searc&h:"));
233#
if defined(__WXMAC__)
241 S.Position(wxALIGN_NOT | wxALIGN_LEFT)
242 .ConnectRoot(wxEVT_KEY_DOWN,
244 .ConnectRoot(wxEVT_CHAR,
248 S.EndHorizontalLay();
250 S.EndHorizontalLay();
252 S.AddSpace(wxDefaultCoord, 2);
254 S.StartHorizontalLay(wxEXPAND, 1);
258 mView->SetName(
_(
"Bindings"));
264 S.EndHorizontalLay();
266 S.StartThreeColumn();
273#
if defined(__WXMAC__)
279#if !defined(__WXMAC__) && wxUSE_ACCESSIBILITY
283 mKey->SetName(
_(
"Short cut"));
286 .ConnectRoot(wxEVT_KEY_DOWN,
288 .ConnectRoot(wxEVT_CHAR,
290 .ConnectRoot(wxEVT_KILL_FOCUS,
292 .ConnectRoot(wxEVT_CONTEXT_MENU,
303#if defined(__WXMAC__)
304 S.AddFixedText(
XO(
"Note: Pressing Cmd+Q will quit. All other keys are valid."));
307 S.StartThreeColumn();
372 for (
const auto & command :
mNames)
384 using IndexesArray = std::vector<int>;
385 std::unordered_map<NormalizedKeyString, IndexesArray> seen;
387 for (
size_t i{ 0 }; i <
mKeys.size(); i++)
392 if (seen.count(
mKeys[i]) == 0)
393 seen.insert({
mKeys[i], {(int)i} });
396 IndexesArray checkMe{ seen.at(
mKeys[i]) };
397 for (
int index : checkMe)
407 seen.at(
mKeys[i]).push_back(index);
422 const std::vector<NormalizedKeyString> &toAdd)
426 auto searchAddInKeys = [&](
size_t index)
428 for (
size_t k{ 0 }; k < toAdd.size(); k++)
431 else if (toAdd[index] ==
mKeys[k] &&
441 for (
size_t i{ 0 }; i < toAdd.size(); i++)
449 int sRes{ searchAddInKeys(i) };
459"\n * \"%s\" (because the shortcut \'%s\' is used by \"%s\")\n")
470 return disabledShortcuts;
481 if (event.IsShown() &&
mView !=
nullptr)
489 wxString file =
wxT(
"Audacity-keys.xml");
492 XO(
"Select an XML file containing Audacity keyboard shortcuts..."),
509 const std::vector<NormalizedKeyString> oldKeys{
mKeys };
519 XO(
"Error Importing Keyboard Shortcuts"),
534 for (
size_t k{ 0 }; k <
mNames.size(); k++)
541"The file with the shortcuts contains illegal shortcut duplicates for \"%s\" and \"%s\".\nNothing is imported.")
542 .
Format( fMatching, sMatching ),
543 XO(
"Error Importing Keyboard Shortcuts"),
544 wxICON_ERROR | wxCENTRE,
this);
558 if (disabledShortcuts.Translation() != (
""))
559 message +=
XO(
"\nThe following commands are not mentioned in the imported file, "
560 "but have their shortcuts removed because of the conflict with other new shortcuts:\n") +
568 wxString file =
wxT(
"Audacity-keys.xml");
570 file =
SelectFile(FileNames::Operation::Export,
571 XO(
"Export Keyboard Shortcuts As:"),
576 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
584 XMLFileWriter prefFile{ file,
XO(
"Error Exporting Keyboard Shortcuts") };
597 Menu.Append( 1,
_(
"Standard") );
598 Menu.Append( 2,
_(
"Full") );
608 for (
size_t i = 0; i < arr.size(); i++) {
609 if( std::binary_search(MaxListOnly.begin(), MaxListOnly.end(), arr[i]) )
620 if( event.GetId() == 1 )
623 for (
size_t i = 0; i <
mNewKeys.size(); i++) {
632 wxTextCtrl *t = (wxTextCtrl *)e.GetEventObject();
642 if (e.GetKeyCode() == WXK_TAB) {
643 t->Navigate(e.ShiftDown()
644 ? wxNavigationKeyEvent::IsBackward
645 : wxNavigationKeyEvent::IsForward);
683 wxTextCtrl *t = (wxTextCtrl *)e.GetEventObject();
684 int keycode = e.GetKeyCode();
689 if (keycode == WXK_TAB) {
690 wxNavigationKeyEvent nevent;
691 nevent.SetWindowChange(e.ControlDown());
692 nevent.SetDirection(!e.ShiftDown());
693 nevent.SetEventObject(t);
694 nevent.SetCurrentFocus(t);
695 t->GetParent()->GetEventHandler()->ProcessEvent(nevent);
710 if (keycode == WXK_RETURN) {
747 XO(
"You may not assign a key to this entry"),
749 wxICON_ERROR | wxCENTRE,
764 XO(
"You must select a binding before assigning a shortcut"),
766 wxICON_WARNING | wxCENTRE,
778 for (
size_t i{ 0 }; i <
mNames.size(); i++)
783 if (
mNames[i] == newCommand)
789 oldCommands.push_back(
mNames[i]);
795 if (!oldCommands.empty()) {
805 for (
size_t i{ 1 }; i < oldCommands.size(); i++)
806 oldlabel +=
XO(
"\n\n\t and\n\n\t") +
813"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.")
820 wxOK | wxCANCEL | wxICON_STOP | wxCENTRE,
826 for (
const auto & command : oldCommands)
857 mKey->Enable(canset);
858 mSet->Enable(canset);
902 for (
size_t i = 0; i <
mNames.size(); i++) {
929 for (
size_t i = 0; i <
mNames.size(); i++) {
939 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)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
XXO("&Cut/Copy/Paste Toolbar")
std::vector< CommandID > CommandIDs
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
PrefsPanel::Factory KeyConfigPrefsFactory(const CommandID &name)
#define AssignDefaultsButtonID
#define KEY_CONFIG_PREFS_PLUGIN_SYMBOL
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
TranslatableString GetCategoryFromName(const CommandID &name) const
NormalizedKeyString GetDefaultKeyFromName(const CommandID &name) const
static CommandManager & Get(AudacityProject &project)
static const std::vector< NormalizedKeyString > & ExcludedList()
void GetAllCommandData(CommandIDs &names, std::vector< NormalizedKeyString > &keys, std::vector< NormalizedKeyString > &default_keys, TranslatableStrings &labels, TranslatableStrings &categories, TranslatableStrings &prefixes, bool includeMultis)
void SetKeyFromName(const CommandID &name, const NormalizedKeyString &key)
NormalizedKeyString GetKeyFromName(const CommandID &name) const
TranslatableString GetPrefixedLabelFromName(const CommandID &name) const
void SetKeyFromIndex(int i, const NormalizedKeyString &key)
int GetNumberOfKeysRead() const
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