Audacity  2.2.2
PrefsDialog.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  PrefsDialog.cpp
6 
7  Joshua Haberman
8  James Crook
9 
10 *******************************************************************//*******************************************************************/
16 
17 #include "../Audacity.h"
18 #include "PrefsDialog.h"
19 
20 #include <wx/defs.h>
21 #include <wx/button.h>
22 #include <wx/dialog.h>
23 #include <wx/event.h>
24 #include <wx/font.h>
25 #include <wx/gdicmn.h>
26 #include <wx/intl.h>
27 #include <wx/listbox.h>
28 #include <wx/sizer.h>
29 
30 #include <wx/listbook.h>
31 
32 #include <wx/treebook.h>
33 
34 #include "../AudioIO.h"
35 #include "../Experimental.h"
36 #include "../Project.h"
37 #include "../Prefs.h"
38 #include "../ShuttleGui.h"
39 
40 #include "PrefsPanel.h"
41 
42 #include "BatchPrefs.h"
43 #include "DevicePrefs.h"
44 #include "DirectoriesPrefs.h"
45 #include "EffectsPrefs.h"
46 #include "GUIPrefs.h"
47 #include "ImportExportPrefs.h"
48 #include "KeyConfigPrefs.h"
49 #include "LibraryPrefs.h"
50 #include "MousePrefs.h"
51 #ifdef EXPERIMENTAL_MODULE_PREFS
52 #include "ModulePrefs.h"
53 #endif
54 #include "PlaybackPrefs.h"
55 #include "ProjectsPrefs.h"
56 #include "QualityPrefs.h"
57 #include "RecordingPrefs.h"
58 #include "SpectrumPrefs.h"
59 #include "ThemePrefs.h"
60 #include "TracksPrefs.h"
61 #include "TracksBehaviorsPrefs.h"
62 #include "WarningsPrefs.h"
63 // #include "WaveformPrefs.h"
64 #include "WaveformSettings.h"
65 #include "ExtImportPrefs.h"
66 
67 #ifdef EXPERIMENTAL_MIDI_OUT
68 #include "MidiIOPrefs.h"
69 #endif
70 
71 #include "../Theme.h"
72 #include "../widgets/HelpSystem.h"
73 
74 BEGIN_EVENT_TABLE(PrefsDialog, wxDialogWrapper)
75  EVT_BUTTON(wxID_OK, PrefsDialog::OnOK)
76  EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
77  EVT_BUTTON(wxID_PREVIEW, PrefsDialog::OnPreview)
78  EVT_BUTTON(wxID_HELP, PrefsDialog::OnHelp)
79  EVT_TREE_KEY_DOWN(wxID_ANY, PrefsDialog::OnTreeKeyDown) // Handles key events when tree has focus
81 
82 
83 class wxTreebookExt final : public wxTreebook
84 {
85 public:
86  wxTreebookExt( wxWindow *parent,
87  wxWindowID id, const wxString &titlePrefix)
88  : wxTreebook( parent, id )
89  , mTitlePrefix(titlePrefix)
90  {;};
92  int ChangeSelection(size_t n) override;
93  int SetSelection(size_t n) override;
94  const wxString mTitlePrefix;
95 };
96 
97 
99  int i = wxTreebook::ChangeSelection(n);
100  wxString Temp = GetPageText( n );
101  static_cast<wxDialog*>(GetParent())->SetTitle( Temp );
102  static_cast<wxDialog*>(GetParent())->SetName( Temp );
103  return i;
104 };
105 
107 {
108  int i = wxTreebook::SetSelection(n);
109  wxString Temp = wxString(mTitlePrefix) + GetPageText( n );
110  static_cast<wxDialog*>(GetParent())->SetTitle( Temp );
111  static_cast<wxDialog*>(GetParent())->SetName( Temp );
112 
113  PrefsPanel *const panel = static_cast<PrefsPanel *>(GetPage(n));
114  const bool showHelp = (panel->HelpPageName() != wxEmptyString);
115  const bool showPreview = panel->ShowsPreviewButton();
116  wxWindow *const helpButton = wxWindow::FindWindowById(wxID_HELP, GetParent());
117  wxWindow *const previewButton = wxWindow::FindWindowById(wxID_PREVIEW, GetParent());
118 
119  if (helpButton) {
120  if (showHelp) {
121  wxAcceleratorEntry entries[1];
122 #if defined(__WXMAC__)
123  // Is there a standard shortcut on Mac?
124 #else
125  entries[0].Set(wxACCEL_NORMAL, (int) WXK_F1, wxID_HELP);
126 #endif
127  wxAcceleratorTable accel(1, entries);
128  this->SetAcceleratorTable(accel);
129  }
130  else {
131  this->SetAcceleratorTable(wxNullAcceleratorTable);
132  }
133 
134  const bool changed = helpButton->Show(showHelp);
135  if (changed)
136  GetParent()->Layout();
137  }
138 
139  if (previewButton) { // might still be NULL during population
140  const bool changed = previewButton->Show(showPreview);
141  if (changed)
142  GetParent()->Layout();
143  }
144 
145  return i;
146 }
147 
148 
149 
152 {
153  // To do, perhaps: create this table by registration, without including each PrefsPanel
154  // class... and thus allowing a plug-in protocol
155  static DevicePrefsFactory devicePrefsFactory;
156  static PlaybackPrefsFactory playbackPrefsFactory;
157  static RecordingPrefsFactory recordingPrefsFactory;
158 #ifdef EXPERIMENTAL_MIDI_OUT
159  static MidiIOPrefsFactory midiIOPrefsFactory;
160 #endif
161  static QualityPrefsFactory qualityPrefsFactory;
162  static GUIPrefsFactory guiPrefsFactory;
163  static TracksPrefsFactory tracksPrefsFactory;
164  static ImportExportPrefsFactory importExportPrefsFactory;
165  static ExtImportPrefsFactory extImportPrefsFactory;
166  static ProjectsPrefsFactory projectsPrefsFactory;
167 #if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME)
168  static LibraryPrefsFactory libraryPrefsFactory;
169 #endif
170  // static WaveformPrefsFactory waveformPrefsFactory;
171  static TracksBehaviorsPrefsFactory tracksBehaviorsPrefsFactory;
172  static SpectrumPrefsFactory spectrumPrefsFactory;
173  static DirectoriesPrefsFactory directoriesPrefsFactory;
174  static WarningsPrefsFactory warningsPrefsFactory;
175  static EffectsPrefsFactory effectsPrefsFactory;
176 #ifdef EXPERIMENTAL_THEME_PREFS
177  static ThemePrefsFactory themePrefsFactory;
178 #endif
179  // static BatchPrefsFactory batchPrefsFactory;
180  static KeyConfigPrefsFactory keyConfigPrefsFactory;
181  static MousePrefsFactory mousePrefsFactory;
182 #ifdef EXPERIMENTAL_MODULE_PREFS
183  static ModulePrefsFactory modulePrefsFactory;
184 #endif
185 
186  static PrefsNode nodes[] = {
187  &devicePrefsFactory,
188  &playbackPrefsFactory,
189  &recordingPrefsFactory,
190 #ifdef EXPERIMENTAL_MIDI_OUT
191  &midiIOPrefsFactory,
192 #endif
193  &qualityPrefsFactory,
194  &guiPrefsFactory,
195 
196  // Group other page(s)
197  PrefsNode(&tracksPrefsFactory, 2),
198  // &waveformPrefsFactory,
199  &tracksBehaviorsPrefsFactory,
200  &spectrumPrefsFactory,
201 
202  // Group one other page
203  PrefsNode(&importExportPrefsFactory, 1),
204  &extImportPrefsFactory,
205 
206  &projectsPrefsFactory,
207 #if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME)
208  &libraryPrefsFactory,
209 #endif
210  &directoriesPrefsFactory,
211  &warningsPrefsFactory,
212  &effectsPrefsFactory,
213 #ifdef EXPERIMENTAL_THEME_PREFS
214  &themePrefsFactory,
215 #endif
216  // &batchPrefsFactory,
217  &keyConfigPrefsFactory,
218  &mousePrefsFactory,
219 #ifdef EXPERIMENTAL_MODULE_PREFS
220  &modulePrefsFactory,
221 #endif
222  };
223 
224  static Factories factories(nodes, nodes + sizeof(nodes) / sizeof(nodes[0]));
225  return factories;
226 }
227 
228 
230  (wxWindow * parent, const wxString &titlePrefix, Factories &factories)
231 : wxDialogWrapper(parent, wxID_ANY, wxString(_("Audacity Preferences")),
232  wxDefaultPosition,
233  wxDefaultSize,
234  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
235 , mFactories(factories)
236 , mTitlePrefix(titlePrefix)
237 {
238  wxASSERT(factories.size() > 0);
239  const bool uniquePage = (factories.size() == 1);
240 
241  ShuttleGui S(this, eIsCreating);
242 
243  S.StartVerticalLay(true);
244  {
245  wxASSERT(factories.size() > 0);
246  if (!uniquePage) {
247  mCategories = safenew wxTreebookExt(this, wxID_ANY, mTitlePrefix);
248  // RJH: Prevent NVDA from reading "treeCtrl"
249  mCategories->GetTreeCtrl()->SetName(_("Category"));
250  S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND, true);
251  {
252  S.Prop(1);
253  S.AddWindow(mCategories, wxEXPAND);
254 
255  {
256  typedef std::pair<int, int> IntPair;
257  std::vector<IntPair> stack;
258  int iPage = 0;
259  for (Factories::const_iterator it = factories.begin(), end = factories.end();
260  it != end; ++it, ++iPage)
261  {
262  const PrefsNode &node = *it;
263  PrefsPanelFactory &factory = *node.pFactory;
264  wxWindow *const w = factory(mCategories, wxID_ANY);
265  if (stack.empty())
266  // Parameters are: AddPage(page, name, IsSelected, imageId).
267  mCategories->AddPage(w, w->GetName(), false, 0);
268  else {
269  IntPair &top = *stack.rbegin();
270  mCategories->InsertSubPage(top.first, w, w->GetName(), false, 0);
271  if (--top.second == 0) {
272  // Expand all nodes before the layout calculation
273  mCategories->ExpandNode(top.first, true);
274  stack.pop_back();
275  }
276  }
277  if (node.nChildren > 0)
278  stack.push_back(IntPair(iPage, node.nChildren));
279  }
280  }
281  }
282  S.EndHorizontalLay();
283  }
284  else {
285  // TODO: Look into getting rid of mUniquePage and instead
286  // adding into mCategories, so there is just one page in mCategories.
287  // And then hiding the treebook.
288 
289  // Unique page, don't show the factory
290  const PrefsNode &node = factories[0];
291  PrefsPanelFactory &factory = *node.pFactory;
292  mUniquePage = factory(this, wxID_ANY);
293  wxWindow * uniquePageWindow = S.Prop(1).AddWindow(mUniquePage, wxEXPAND);
294  // We're not in the wxTreebook, so add the accelerator here
295  wxAcceleratorEntry entries[1];
296 #if defined(__WXMAC__)
297  // Is there a standard shortcut on Mac?
298 #else
299  entries[0].Set(wxACCEL_NORMAL, (int) WXK_F1, wxID_HELP);
300 #endif
301  wxAcceleratorTable accel(1, entries);
302  uniquePageWindow->SetAcceleratorTable(accel);
303  }
304  }
305  S.EndVerticalLay();
306 
308  static_cast<wxButton*>(wxWindow::FindWindowById(wxID_OK, this))->SetDefault();
309 
310  if (mUniquePage && !mUniquePage->ShowsPreviewButton()) {
311  wxWindow *const previewButton =
312  wxWindow::FindWindowById(wxID_PREVIEW, GetParent());
313  previewButton->Show(false);
314  }
315 
316 #if defined(__WXGTK__)
317  if (mCategories)
318  mCategories->GetTreeCtrl()->EnsureVisible(mCategories->GetTreeCtrl()->GetRootItem());
319 #endif
320 
321 // mCategories->SetSizeHints(-1, -1, 790, 600); // 790 = 800 - (border * 2)
322  Layout();
323  Fit();
324  wxSize sz = GetSize();
325 
326  // Collapse nodes only after layout so the tree is wide enough
327  if (mCategories)
328  {
329  int iPage = 0;
330  for (Factories::const_iterator it = factories.begin(), end = factories.end();
331  it != end; ++it, ++iPage)
332  mCategories->ExpandNode(iPage, it->expanded);
333  }
334 
335  // This ASSERT was originally used to limit us to 800 x 600.
336  // However, the range of screen sizes and dpi of modern (2018) displays
337  // makes pixel dimensions an inadequate measure of usability, so
338  // now we only ASSERT that preferences will fit in the client display
339  // rectangle of the developer / tester's monitor.
340  // Use scrollers when necessary to ensure that preference pages will
341  // be fully visible.
342  wxRect screenRect(wxGetClientDisplayRect());
343  wxASSERT_MSG(sz.x <= screenRect.width && sz.y <= screenRect.height, wxT("Preferences dialog exceeds max size"));
344 
345  sz.DecTo(screenRect.GetSize());
346 
347  int prefWidth, prefHeight;
348  gPrefs->Read(wxT("/Prefs/Width"), &prefWidth, sz.x);
349  gPrefs->Read(wxT("/Prefs/Height"), &prefHeight, sz.y);
350 
351  wxSize prefSize = wxSize(prefWidth, prefHeight);
352  prefSize.DecTo(screenRect.GetSize());
353  SetSize(prefSize);
354  SetMinSize(sz);
355 
356  // Center after all that resizing, but make sure it doesn't end up
357  // off-screen
358  CentreOnParent();
359 }
360 
362 {
363 }
364 
366 {
367  if (mCategories) {
368  /* long is signed, size_t is unsigned. On some platforms they are different
369  * lengths as well. So we must check that the stored category is both > 0
370  * and within the possible range of categories, making the first check on the
371  * _signed_ value to avoid issues when converting an unsigned one.
372  */
373  long selected = GetPreferredPage();
374  if (selected < 0 || size_t(selected) >= mCategories->GetPageCount())
375  selected = 0; // clamp to available range of tabs
376  mCategories->SetSelection(selected);
377  }
378  else {
379  wxString Temp = mTitlePrefix + mUniquePage->GetLabel();
380  SetTitle(Temp);
381  SetName(Temp);
382  }
383 
384  return wxDialogWrapper::ShowModal();
385 }
386 
387 void PrefsDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
388 {
390 
391  if (mCategories) {
392  for (size_t i = 0; i < mCategories->GetPageCount(); i++) {
393  ((PrefsPanel *)mCategories->GetPage(i))->Cancel();
394  }
395  }
396  else
397  mUniquePage->Cancel();
398 
399  EndModal(false);
400 }
401 
403 {
404  if( mCategories)
405  return static_cast<PrefsPanel*>(mCategories->GetCurrentPage());
406  else
407  {
408  wxASSERT( mUniquePage );
409  return mUniquePage;
410  }
411 }
412 
413 void PrefsDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
414 {
416 }
417 
418 void PrefsDialog::OnHelp(wxCommandEvent & WXUNUSED(event))
419 {
420  wxString page = GetCurrentPanel()->HelpPageName();
421  // Currently (May2017) Spectrum Settings is the only preferences
422  // we ever display in a dialog on its own without others.
423  // We do so when it is configuring spectrums for a track.
424  // Because this happens, we want to visit a different help page.
425  // So we change the page name in the case of a page on its own.
426  if( !mCategories)
427  page.Replace( "Spectrograms_Preferences", "Spectrogram_Settings" );
428  HelpSystem::ShowHelp(this, page, true);
429 }
430 
431 void PrefsDialog::OnTreeKeyDown(wxTreeEvent & event)
432 {
433  if(event.GetKeyCode() == WXK_RETURN)
434  OnOK(event);
435  else
436  event.Skip(); // Ensure standard behavior when enter is not pressed
437 }
438 
439 void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event))
440 {
442 
443  // Validate all pages first
444  if (mCategories) {
445  for (size_t i = 0; i < mCategories->GetPageCount(); i++) {
446  PrefsPanel *panel = (PrefsPanel *)mCategories->GetPage(i);
447 
448  // The dialog doesn't end until all the input is valid
449  if (!panel->Validate()) {
450  mCategories->SetSelection(i);
451  return;
452  }
453  }
454  }
455  else {
456  if (!mUniquePage->Validate())
457  return;
458  }
459 
460  // flush now so toolbars will know their position.
461  gPrefs->Flush();
462  if (mCategories) {
463  // Now apply the changes
464  for (size_t i = 0; i < mCategories->GetPageCount(); i++) {
465  PrefsPanel *panel = (PrefsPanel *)mCategories->GetPage(i);
466 
467  panel->Preview();
468  panel->Commit();
469  }
470  }
471  else {
472  mUniquePage->Preview();
473  mUniquePage->Commit();
474  }
475 
476  wxSize sz = GetSize();
477  gPrefs->Write(wxT("/Prefs/Width"), sz.x);
478  gPrefs->Write(wxT("/Prefs/Height"), sz.y);
479  gPrefs->Flush();
480 
481  // Reads preference /GUI/Theme
484 
486 
487 #if USE_PORTMIXER
488  if (gAudioIO) {
489  // We cannot have opened this dialog if gAudioIO->IsAudioTokenActive(),
490  // per the setting of AudioIONotBusyFlag and AudioIOBusyFlag in
491  // AudacityProject::GetUpdateFlags().
492  // However, we can have an invalid audio token (so IsAudioTokenActive()
493  // is false), but be monitoring.
494  // If monitoring, have to stop the stream, so HandleDeviceChange() can work.
495  // We could disable the Preferences command while monitoring, i.e.,
496  // set AudioIONotBusyFlag/AudioIOBusyFlag according to monitoring, as well.
497  // Instead allow it because unlike recording, for example, monitoring
498  // is not clearly something that should prohibit opening prefs.
499  // TODO: We *could* be smarter in this method and call HandleDeviceChange()
500  // only when the device choices actually changed. True of lots of prefs!
501  // As is, we always stop monitoring before handling the device change.
502  if (gAudioIO->IsMonitoring())
503  {
504  gAudioIO->StopStream();
505  while (gAudioIO->IsBusy())
506  wxMilliSleep(100);
507  }
509  }
510 #endif
511 
512  // LL: wxMac can't handle recreating the menus when this dialog is still active,
513  // so AudacityProject::UpdatePrefs() or any of the routines it calls must
514  // not cause AudacityProject::RebuildMenuBar() to be executed.
515  for (size_t i = 0; i < gAudacityProjects.size(); i++) {
516  gAudacityProjects[i]->UpdatePrefs();
517  }
518 
520 
521  EndModal(true);
522 }
523 
524 void PrefsDialog::SelectPageByName(const wxString &pageName)
525 {
526  if (mCategories) {
527  size_t n = mCategories->GetPageCount();
528 
529  for (size_t i = 0; i < n; i++) {
530  if (mCategories->GetPageText(i) == pageName) {
531  mCategories->SetSelection(i);
532  return;
533  }
534  }
535  }
536 }
537 
539 {
540  if (mCategories)
541  return mCategories->GetSelection();
542  else
543  return 0;
544 }
545 
546 GlobalPrefsDialog::GlobalPrefsDialog(wxWindow * parent, Factories &factories)
547  : PrefsDialog(parent, _("Preferences: "), factories)
548 {
549 }
550 
552 {
553 }
554 
556 {
557  long prefscat = gPrefs->Read(wxT("/Prefs/PrefsCategory"), 0L);
558  return prefscat;
559 }
560 
562 {
563  gPrefs->Write(wxT("/Prefs/PrefsCategory"), (long)GetSelectedPage());
564  gPrefs->Flush();
565 }
566 
568 {
569  // Remember expansion state of the tree control
570  if (mCategories)
571  {
572  int iPage = 0;
573  for (Factories::iterator it = mFactories.begin(), end = mFactories.end();
574  it != end; ++it, ++iPage)
575  it->expanded = mCategories->IsNodeExpanded(iPage);
576  }
577  else
578  mFactories[0].expanded = true;
579 }
580 
582 {
583 }
584 
586 {
587 }
588 
590 {
591  return false;
592 }
593 
595 {
596  return wxEmptyString;
597 }
~wxTreebookExt()
Definition: PrefsDialog.cpp:91
virtual void SavePreferredPage()=0
void StopStream()
Stop recording, playback or input monitoring.
Definition: AudioIO.cpp:2518
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:209
PrefsPanel * mUniquePage
Definition: PrefsDialog.h:84
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:366
wxWindow * AddWindow(wxWindow *pWindow, int Flags=wxALIGN_CENTRE|wxALL)
Definition: ShuttleGui.cpp:257
void ApplyUpdatedImages() override
Definition: Theme.cpp:250
AProjectArray gAudacityProjects
Definition: Project.cpp:295
void SavePreferredPage() override
virtual ~PrefsPanel()
void OnHelp(wxCommandEvent &e)
void OnTreeKeyDown(wxTreeEvent &e)
virtual ~GlobalPrefsDialog()
void SelectPageByName(const wxString &pageName)
virtual ~PrefsDialog()
Factories & mFactories
Definition: PrefsDialog.h:85
static Factories & DefaultFactories()
Dialog that shows the current PrefsPanel in a tabbed divider.
Definition: PrefsDialog.h:34
void RecordExpansionState()
static WaveformSettings & defaults()
bool IsBusy()
Returns true if audio i/o is busy starting, stopping, playing, or recording.
Definition: AudioIO.cpp:2891
int SetSelection(size_t n) override
wxTreebook * mCategories
Definition: PrefsDialog.h:83
PrefsPanel * GetCurrentPanel()
#define safenew
Definition: Audacity.h:223
virtual long GetPreferredPage()=0
void EndHorizontalLay()
Definition: ShuttleGui.cpp:975
const wxString mTitlePrefix
Definition: PrefsDialog.cpp:94
void EndVerticalLay()
Definition: ShuttleGui.cpp:991
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
PrefsDialog(wxWindow *parent, const wxString &titlePrefix=_("Preferences: "), Factories &factories=DefaultFactories())
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:966
virtual bool Commit()=0
const wxString mTitlePrefix
Definition: PrefsDialog.h:86
std::vector< PrefsNode > Factories
Definition: PrefsDialog.h:49
void OnCancel(wxCommandEvent &e)
void HandleDeviceChange()
update state after changing what audio devices are selected
Definition: AudioIO.cpp:1423
long GetPreferredPage() override
static void ShowHelp(wxWindow *parent, const wxString &localFileName, const wxString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:201
virtual bool ShowsPreviewButton()
A wxTreebook is a class like wxNotebook, but not yet supported by wxWidgets 2.6.3.
EVT_TREE_KEY_DOWN(wxID_ANY, PrefsDialog::OnTreeKeyDown) class wxTreebookExt final
Definition: PrefsDialog.cpp:79
void OnPreview(wxCommandEvent &e)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
GlobalPrefsDialog(wxWindow *parent, Factories &factories=DefaultFactories())
Used within the PrefsDialog, classes derived from this class include AudioIOPrefs, BatchPrefs, DirectoriesPrefs, FileFormatPrefs, GUIPrefs, KeyConfigPrefs, MousePrefs, QualityPrefs, SpectrumPrefs and ThemePrefs.
Definition: PrefsPanel.h:43
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
PrefsPanelFactory *CONST pFactory
Definition: PrefsDialog.h:39
void OnOK(wxCommandEvent &e)
AudioIO * gAudioIO
Definition: AudioIO.cpp:481
int ShowModal() override
virtual wxString HelpPageName()
bool IsMonitoring()
Returns true if we're monitoring input (but not recording or playing actual audio) ...
Definition: AudioIO.cpp:2923
int GetSelectedPage() const
int ChangeSelection(size_t n) override
Definition: PrefsDialog.cpp:98
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:374
static bool LoadPreferredTheme()
Definition: Theme.cpp:237
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxButton *extra=NULL)
virtual void Preview()
Definition: PrefsPanel.h:56
END_EVENT_TABLE()
virtual void Cancel()
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:982