From 8399effc451a76250a97ece61b15e8e30f09dc7d Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 13 Jun 2015 17:59:47 -0400 Subject: [PATCH 1/4] Table-driven construction of Prefs dialog. A factory for each kind of panel... ... and maybe a future plug-in protocol to break compilation dependency on all of the PrefsPanel subclasses. --- src/prefs/BatchPrefs.cpp | 5 + src/prefs/BatchPrefs.h | 5 + src/prefs/DevicePrefs.cpp | 5 + src/prefs/DevicePrefs.h | 6 ++ src/prefs/DirectoriesPrefs.cpp | 5 + src/prefs/DirectoriesPrefs.h | 5 + src/prefs/EffectsPrefs.cpp | 5 + src/prefs/EffectsPrefs.h | 5 + src/prefs/ExtImportPrefs.cpp | 5 + src/prefs/ExtImportPrefs.h | 6 ++ src/prefs/GUIPrefs.cpp | 5 + src/prefs/GUIPrefs.h | 5 + src/prefs/ImportExportPrefs.cpp | 5 + src/prefs/ImportExportPrefs.h | 5 + src/prefs/KeyConfigPrefs.cpp | 5 + src/prefs/KeyConfigPrefs.h | 8 +- src/prefs/LibraryPrefs.cpp | 5 + src/prefs/LibraryPrefs.h | 5 + src/prefs/MidiIOPrefs.cpp | 5 + src/prefs/MidiIOPrefs.h | 5 + src/prefs/ModulePrefs.cpp | 4 + src/prefs/ModulePrefs.h | 5 + src/prefs/MousePrefs.cpp | 5 + src/prefs/MousePrefs.h | 5 + src/prefs/PlaybackPrefs.cpp | 5 + src/prefs/PlaybackPrefs.h | 6 ++ src/prefs/PrefsDialog.cpp | 156 +++++++++++++++++++++++++------- src/prefs/PrefsDialog.h | 27 +++++- src/prefs/PrefsPanel.h | 6 ++ src/prefs/ProjectsPrefs.cpp | 5 + src/prefs/ProjectsPrefs.h | 5 + src/prefs/QualityPrefs.cpp | 5 + src/prefs/QualityPrefs.h | 5 + src/prefs/RecordingPrefs.cpp | 5 + src/prefs/RecordingPrefs.h | 5 + src/prefs/SpectrumPrefs.cpp | 5 + src/prefs/SpectrumPrefs.h | 6 ++ src/prefs/ThemePrefs.cpp | 5 + src/prefs/ThemePrefs.h | 5 + src/prefs/TracksPrefs.cpp | 5 + src/prefs/TracksPrefs.h | 5 + src/prefs/WarningsPrefs.cpp | 5 + src/prefs/WarningsPrefs.h | 5 + 43 files changed, 359 insertions(+), 36 deletions(-) diff --git a/src/prefs/BatchPrefs.cpp b/src/prefs/BatchPrefs.cpp index 8f7664d2c..94ce27880 100644 --- a/src/prefs/BatchPrefs.cpp +++ b/src/prefs/BatchPrefs.cpp @@ -82,3 +82,8 @@ bool BatchPrefs::Apply() BatchPrefs::~BatchPrefs() { } + +PrefsPanel *BatchPrefsFactory::Create(wxWindow *parent) +{ + return new BatchPrefs(parent); +} diff --git a/src/prefs/BatchPrefs.h b/src/prefs/BatchPrefs.h index 427e7233c..98210b973 100644 --- a/src/prefs/BatchPrefs.h +++ b/src/prefs/BatchPrefs.h @@ -34,4 +34,9 @@ private: DECLARE_EVENT_TABLE(); }; +class BatchPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/DevicePrefs.cpp b/src/prefs/DevicePrefs.cpp index 24e5fa502..c0663c84c 100644 --- a/src/prefs/DevicePrefs.cpp +++ b/src/prefs/DevicePrefs.cpp @@ -373,3 +373,8 @@ bool DevicePrefs::Apply() return true; } + +PrefsPanel *DevicePrefsFactory::Create(wxWindow *parent) +{ + return new DevicePrefs(parent); +} diff --git a/src/prefs/DevicePrefs.h b/src/prefs/DevicePrefs.h index 67d3bef24..bb3bc7b65 100644 --- a/src/prefs/DevicePrefs.h +++ b/src/prefs/DevicePrefs.h @@ -54,4 +54,10 @@ class DevicePrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class DevicePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; + #endif diff --git a/src/prefs/DirectoriesPrefs.cpp b/src/prefs/DirectoriesPrefs.cpp index 606e3891b..1a48313ff 100644 --- a/src/prefs/DirectoriesPrefs.cpp +++ b/src/prefs/DirectoriesPrefs.cpp @@ -242,3 +242,8 @@ bool DirectoriesPrefs::Apply() return true; } + +PrefsPanel *DirectoriesPrefsFactory::Create(wxWindow *parent) +{ + return new DirectoriesPrefs(parent); +} diff --git a/src/prefs/DirectoriesPrefs.h b/src/prefs/DirectoriesPrefs.h index 404071857..423fd005d 100644 --- a/src/prefs/DirectoriesPrefs.h +++ b/src/prefs/DirectoriesPrefs.h @@ -38,4 +38,9 @@ class DirectoriesPrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class DirectoriesPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/EffectsPrefs.cpp b/src/prefs/EffectsPrefs.cpp index cf5ae326e..e8a36f1f8 100644 --- a/src/prefs/EffectsPrefs.cpp +++ b/src/prefs/EffectsPrefs.cpp @@ -165,3 +165,8 @@ bool EffectsPrefs::Apply() return true; } + +PrefsPanel *EffectsPrefsFactory::Create(wxWindow *parent) +{ + return new EffectsPrefs(parent); +} diff --git a/src/prefs/EffectsPrefs.h b/src/prefs/EffectsPrefs.h index 0d096c042..484913352 100644 --- a/src/prefs/EffectsPrefs.h +++ b/src/prefs/EffectsPrefs.h @@ -34,4 +34,9 @@ class EffectsPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class EffectsPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/ExtImportPrefs.cpp b/src/prefs/ExtImportPrefs.cpp index 9e6550cb7..26c1b6593 100644 --- a/src/prefs/ExtImportPrefs.cpp +++ b/src/prefs/ExtImportPrefs.cpp @@ -780,3 +780,8 @@ void ExtImportPrefsDropTarget::SetDataObject(wxDataObject* data) { this->m_dataObject = data; } + +PrefsPanel *ExtImportPrefsFactory::Create(wxWindow *parent) +{ + return new ExtImportPrefs(parent); +} diff --git a/src/prefs/ExtImportPrefs.h b/src/prefs/ExtImportPrefs.h index d97f29b69..38670d8e3 100644 --- a/src/prefs/ExtImportPrefs.h +++ b/src/prefs/ExtImportPrefs.h @@ -107,4 +107,10 @@ class ExtImportPrefs:public PrefsPanel DECLARE_EVENT_TABLE() }; + +class ExtImportPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/GUIPrefs.cpp b/src/prefs/GUIPrefs.cpp index c6fc5aa04..61e54f1f1 100644 --- a/src/prefs/GUIPrefs.cpp +++ b/src/prefs/GUIPrefs.cpp @@ -158,3 +158,8 @@ bool GUIPrefs::Apply() return true; } + +PrefsPanel *GUIPrefsFactory::Create(wxWindow *parent) +{ + return new GUIPrefs(parent); +} diff --git a/src/prefs/GUIPrefs.h b/src/prefs/GUIPrefs.h index e3af2b7f3..7f114f53a 100644 --- a/src/prefs/GUIPrefs.h +++ b/src/prefs/GUIPrefs.h @@ -43,4 +43,9 @@ class GUIPrefs :public PrefsPanel wxArrayString mRangeChoices; }; +class GUIPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/ImportExportPrefs.cpp b/src/prefs/ImportExportPrefs.cpp index f6e9538f2..609689cc9 100644 --- a/src/prefs/ImportExportPrefs.cpp +++ b/src/prefs/ImportExportPrefs.cpp @@ -109,3 +109,8 @@ bool ImportExportPrefs::Apply() return true; } + +PrefsPanel *ImportExportPrefsFactory::Create(wxWindow *parent) +{ + return new ImportExportPrefs(parent); +} diff --git a/src/prefs/ImportExportPrefs.h b/src/prefs/ImportExportPrefs.h index 9ba891ea7..9ffe03541 100644 --- a/src/prefs/ImportExportPrefs.h +++ b/src/prefs/ImportExportPrefs.h @@ -33,4 +33,9 @@ class ImportExportPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class ImportExportPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/KeyConfigPrefs.cpp b/src/prefs/KeyConfigPrefs.cpp index dbd71e275..07e088512 100644 --- a/src/prefs/KeyConfigPrefs.cpp +++ b/src/prefs/KeyConfigPrefs.cpp @@ -1211,3 +1211,8 @@ void KeyConfigPrefs::Cancel() } #endif + +PrefsPanel *KeyConfigPrefsFactory::Create(wxWindow *parent) +{ + return new KeyConfigPrefs(parent); +} diff --git a/src/prefs/KeyConfigPrefs.h b/src/prefs/KeyConfigPrefs.h index 36f869ec4..e6b2e942a 100644 --- a/src/prefs/KeyConfigPrefs.h +++ b/src/prefs/KeyConfigPrefs.h @@ -141,6 +141,12 @@ class KeyConfigPrefs:public PrefsPanel DECLARE_EVENT_TABLE(); }; -#endif #endif + +class KeyConfigPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; +#endif diff --git a/src/prefs/LibraryPrefs.cpp b/src/prefs/LibraryPrefs.cpp index b1b42ec33..d3632c582 100644 --- a/src/prefs/LibraryPrefs.cpp +++ b/src/prefs/LibraryPrefs.cpp @@ -235,3 +235,8 @@ bool LibraryPrefs::Apply() return true; } + +PrefsPanel *LibraryPrefsFactory::Create(wxWindow *parent) +{ + return new LibraryPrefs(parent); +} diff --git a/src/prefs/LibraryPrefs.h b/src/prefs/LibraryPrefs.h index 15e54a98f..f3a35417d 100644 --- a/src/prefs/LibraryPrefs.h +++ b/src/prefs/LibraryPrefs.h @@ -46,4 +46,9 @@ class LibraryPrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class LibraryPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/MidiIOPrefs.cpp b/src/prefs/MidiIOPrefs.cpp index d541e6ec3..382876e1b 100644 --- a/src/prefs/MidiIOPrefs.cpp +++ b/src/prefs/MidiIOPrefs.cpp @@ -284,4 +284,9 @@ bool MidiIOPrefs::Validate() return true; } +PrefsPanel *MidiIOPrefsFactory::Create(wxWindow *parent) +{ + return new MidiIOPrefs(parent); +} + #endif diff --git a/src/prefs/MidiIOPrefs.h b/src/prefs/MidiIOPrefs.h index 81da992c3..1970b7061 100644 --- a/src/prefs/MidiIOPrefs.h +++ b/src/prefs/MidiIOPrefs.h @@ -62,6 +62,11 @@ class MidiIOPrefs:public PrefsPanel DECLARE_EVENT_TABLE(); }; +class MidiIOPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif #endif diff --git a/src/prefs/ModulePrefs.cpp b/src/prefs/ModulePrefs.cpp index a9a2d9c30..01544b50b 100644 --- a/src/prefs/ModulePrefs.cpp +++ b/src/prefs/ModulePrefs.cpp @@ -161,5 +161,9 @@ void ModulePrefs::SetModuleStatus( wxString fname, int iStatus ){ gPrefs->Flush(); } +PrefsPanel *ModulePrefsFactory::Create(wxWindow *parent) +{ + return new ModulePrefs(parent); +} diff --git a/src/prefs/ModulePrefs.h b/src/prefs/ModulePrefs.h index 9014e96a5..09d80a1d2 100644 --- a/src/prefs/ModulePrefs.h +++ b/src/prefs/ModulePrefs.h @@ -50,4 +50,9 @@ class ModulePrefs:public PrefsPanel wxArrayString mPaths; }; +class ModulePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/MousePrefs.cpp b/src/prefs/MousePrefs.cpp index 4618ddf39..42d99f78c 100644 --- a/src/prefs/MousePrefs.cpp +++ b/src/prefs/MousePrefs.cpp @@ -196,3 +196,8 @@ bool MousePrefs::Apply() // PopulateOrExchange(S); return true; } + +PrefsPanel *MousePrefsFactory::Create(wxWindow *parent) +{ + return new MousePrefs(parent); +} diff --git a/src/prefs/MousePrefs.h b/src/prefs/MousePrefs.h index 33f5254ea..df8803732 100644 --- a/src/prefs/MousePrefs.h +++ b/src/prefs/MousePrefs.h @@ -38,4 +38,9 @@ class MousePrefs :public PrefsPanel wxListCtrl * mList; }; +class MousePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/PlaybackPrefs.cpp b/src/prefs/PlaybackPrefs.cpp index 997d9be13..d3c56e5c3 100644 --- a/src/prefs/PlaybackPrefs.cpp +++ b/src/prefs/PlaybackPrefs.cpp @@ -122,3 +122,8 @@ bool PlaybackPrefs::Apply() return true; } + +PrefsPanel *PlaybackPrefsFactory::Create(wxWindow *parent) +{ + return new PlaybackPrefs(parent); +} diff --git a/src/prefs/PlaybackPrefs.h b/src/prefs/PlaybackPrefs.h index 8384fb584..057b51d84 100644 --- a/src/prefs/PlaybackPrefs.h +++ b/src/prefs/PlaybackPrefs.h @@ -32,4 +32,10 @@ class PlaybackPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class PlaybackPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; + #endif diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index 91f18bc65..dc94a705c 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -15,6 +15,7 @@ *//*******************************************************************/ #include "../Audacity.h" +#include "PrefsDialog.h" #include #include @@ -41,7 +42,6 @@ #include "../Prefs.h" #include "../ShuttleGui.h" -#include "PrefsDialog.h" #include "PrefsPanel.h" #include "BatchPrefs.h" @@ -108,11 +108,82 @@ int wxTreebookExt::SetSelection(size_t n) -PrefsDialog::PrefsDialog(wxWindow * parent) +PrefsDialog::Factories +&PrefsDialog::DefaultFactories() +{ + // To do, perhaps: create this table by registration, without including each PrefsPanel + // class... and thus allowing a plug-in protocol + static DevicePrefsFactory devicePrefsFactory; + static PlaybackPrefsFactory playbackPrefsFactory; + static RecordingPrefsFactory recordingPrefsFactory; +#ifdef EXPERIMENTAL_MIDI_OUT + static MidiIOPrefsFactory midiIOPrefsFactory; +#endif + static QualityPrefsFactory qualityPrefsFactory; + static GUIPrefsFactory guiPrefsFactory; + static TracksPrefsFactory tracksPrefsFactory; + static ImportExportPrefsFactory importExportPrefsFactory; + static ExtImportPrefsFactory extImportPrefsFactory; + static ProjectsPrefsFactory projectsPrefsFactory; +#if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) + static LibraryPrefsFactory libraryPrefsFactory; +#endif + static SpectrumPrefsFactory spectrumPrefsFactory; + static DirectoriesPrefsFactory directoriesPrefsFactory; + static WarningsPrefsFactory warningsPrefsFactory; + static EffectsPrefsFactory effectsPrefsFactory; +#ifdef EXPERIMENTAL_THEME_PREFS + static ThemePrefsFactory themePrefsFactory; +#endif + // static BatchPrefsFactory batchPrefsFactory; + static KeyConfigPrefsFactory keyConfigPrefsFactory; + static MousePrefsFactory mousePrefsFactory; +#ifdef EXPERIMENTAL_MODULE_PREFS + static ModulePrefsFactory modulePrefsFactory; +#endif + + static PrefsNode nodes[] = { + &devicePrefsFactory, + &playbackPrefsFactory, + &recordingPrefsFactory, +#ifdef EXPERIMENTAL_MIDI_OUT + &midiIOPrefsFactory, +#endif + &qualityPrefsFactory, + &guiPrefsFactory, + &tracksPrefsFactory, + &importExportPrefsFactory, + &extImportPrefsFactory, + &projectsPrefsFactory, +#if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) + &libraryPrefsFactory, +#endif + &spectrumPrefsFactory, + &directoriesPrefsFactory, + &warningsPrefsFactory, + &effectsPrefsFactory, +#ifdef EXPERIMENTAL_THEME_PREFS + &themePrefsFactory, +#endif + // &batchPrefsFactory, + &keyConfigPrefsFactory, + &mousePrefsFactory, +#ifdef EXPERIMENTAL_MODULE_PREFS + &modulePrefsFactory, +#endif + }; + + static Factories factories(nodes, nodes + sizeof(nodes) / sizeof(nodes[0])); + return factories; +} + + +PrefsDialog::PrefsDialog(wxWindow * parent, Factories &factories) : wxDialog(parent, wxID_ANY, wxString(_("Audacity Preferences")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +, mFactories(factories) { ShuttleGui S(this, eIsCreating); @@ -124,38 +195,32 @@ PrefsDialog::PrefsDialog(wxWindow * parent) S.Prop(1); S.AddWindow(mCategories, wxEXPAND); - wxWindow *w; - // Parameters are: AddPage(page, name, IsSelected, imageId). - w = new DevicePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new PlaybackPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new RecordingPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#ifdef EXPERIMENTAL_MIDI_OUT - w = new MidiIOPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif - w = new QualityPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new GUIPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new TracksPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new ImportExportPrefs(mCategories);mCategories->AddPage(w, w->GetName(), false, 0); - w = new ExtImportPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new ProjectsPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) - w = new LibraryPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif - w = new SpectrumPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new DirectoriesPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new WarningsPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new EffectsPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - -#ifdef EXPERIMENTAL_THEME_PREFS - w = new ThemePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif - -// w = new BatchPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new KeyConfigPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new MousePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#ifdef EXPERIMENTAL_MODULE_PREFS - w = new ModulePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif + { + typedef std::pair IntPair; + std::vector stack; + int iPage = 0; + for (Factories::const_iterator it = factories.begin(), end = factories.end(); + it != end; ++it, ++iPage) + { + const PrefsNode &node = *it; + PrefsPanelFactory &factory = *node.pFactory; + wxWindow *const w = factory.Create(mCategories); + if (stack.empty()) + // Parameters are: AddPage(page, name, IsSelected, imageId). + mCategories->AddPage(w, w->GetName(), false, 0); + else { + IntPair &top = *stack.rbegin(); + mCategories->InsertSubPage(top.first, w, w->GetName(), false, 0); + if (--top.second == 0) { + // Expand all nodes before the layout calculation + mCategories->ExpandNode(top.first, true); + stack.pop_back(); + } + } + if (node.nChildren > 0) + stack.push_back(IntPair(iPage, node.nChildren)); + } + } } S.EndHorizontalLay(); } @@ -189,6 +254,14 @@ PrefsDialog::PrefsDialog(wxWindow * parent) Fit(); wxSize sz = GetSize(); + // Collapse nodes only after layout so the tree is wide enough + { + int iPage = 0; + for (Factories::const_iterator it = factories.begin(), end = factories.end(); + it != end; ++it, ++iPage) + mCategories->ExpandNode(iPage, it->expanded); + } + // This ASSERT used to limit us to 800 x 600. // However, we think screens have got bigger now, and that was a bit too restrictive. // The impetus for increasing the limit (before we ASSERT) was that this ASSERT @@ -221,6 +294,8 @@ PrefsDialog::~PrefsDialog() void PrefsDialog::OnCancel(wxCommandEvent & WXUNUSED(event)) { + RecordExpansionState(); + for (size_t i = 0; i < mCategories->GetPageCount(); i++) { ((PrefsPanel *) mCategories->GetPage(i))->Cancel(); } @@ -238,6 +313,8 @@ void PrefsDialog::OnTreeKeyDown(wxTreeEvent & event) void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event)) { + RecordExpansionState(); + // Validate all pages first for (size_t i = 0; i < mCategories->GetPageCount(); i++) { PrefsPanel *panel = (PrefsPanel *) mCategories->GetPage(i); @@ -311,3 +388,14 @@ void PrefsDialog::ShowTempDirPage() { SelectPageByName(_("Directories")); } + +void PrefsDialog::RecordExpansionState() +{ + // Remember expansion state of the tree control + { + int iPage = 0; + for (Factories::iterator it = mFactories.begin(), end = mFactories.end(); + it != end; ++it, ++iPage) + it->expanded = mCategories->IsNodeExpanded(iPage); + } +} diff --git a/src/prefs/PrefsDialog.h b/src/prefs/PrefsDialog.h index 13f3d3e0c..294826815 100644 --- a/src/prefs/PrefsDialog.h +++ b/src/prefs/PrefsDialog.h @@ -12,6 +12,7 @@ #ifndef __AUDACITY_PREFS_DIALOG__ #define __AUDACITY_PREFS_DIALOG__ +#include #include #include #include @@ -19,10 +20,31 @@ #include #include +class PrefsPanelFactory; + +#ifdef __GNUC__ +#define CONST +#else +#define CONST const +#endif + class PrefsDialog:public wxDialog { public: - PrefsDialog(wxWindow * parent); + // An array of PrefsNode specifies the tree of pages in pre-order traversal. + struct PrefsNode { + PrefsPanelFactory * CONST pFactory; + CONST int nChildren; + bool expanded; + + PrefsNode(PrefsPanelFactory *pFactory_, int nChildren_ = 0) + : pFactory(pFactory_), nChildren(nChildren_), expanded(false) + {} + }; + typedef std::vector Factories; + static Factories &DefaultFactories(); + + PrefsDialog(wxWindow * parent, Factories &factories = DefaultFactories()); virtual ~PrefsDialog(); void OnCategoryChange(wxCommandEvent & e); @@ -34,7 +56,10 @@ class PrefsDialog:public wxDialog void ShowTempDirPage(); private: + void RecordExpansionState(); + wxTreebook *mCategories; + Factories &mFactories; DECLARE_EVENT_TABLE() }; diff --git a/src/prefs/PrefsPanel.h b/src/prefs/PrefsPanel.h index e35eacf44..2af21079a 100644 --- a/src/prefs/PrefsPanel.h +++ b/src/prefs/PrefsPanel.h @@ -61,4 +61,10 @@ class PrefsPanel:public wxPanel } }; +class PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent) = 0; +}; + #endif diff --git a/src/prefs/ProjectsPrefs.cpp b/src/prefs/ProjectsPrefs.cpp index 56f22f8c8..fc1e07630 100644 --- a/src/prefs/ProjectsPrefs.cpp +++ b/src/prefs/ProjectsPrefs.cpp @@ -79,3 +79,8 @@ bool ProjectsPrefs::Apply() return true; } + +PrefsPanel *ProjectsPrefsFactory::Create(wxWindow *parent) +{ + return new ProjectsPrefs(parent); +} diff --git a/src/prefs/ProjectsPrefs.h b/src/prefs/ProjectsPrefs.h index 3f1a00791..480a49f71 100644 --- a/src/prefs/ProjectsPrefs.h +++ b/src/prefs/ProjectsPrefs.h @@ -33,4 +33,9 @@ class ProjectsPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class ProjectsPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/QualityPrefs.cpp b/src/prefs/QualityPrefs.cpp index 10c5fb1b0..243d0c419 100644 --- a/src/prefs/QualityPrefs.cpp +++ b/src/prefs/QualityPrefs.cpp @@ -228,3 +228,8 @@ bool QualityPrefs::Apply() return true; } + +PrefsPanel *QualityPrefsFactory::Create(wxWindow *parent) +{ + return new QualityPrefs(parent); +} diff --git a/src/prefs/QualityPrefs.h b/src/prefs/QualityPrefs.h index 726da2490..778417a2c 100644 --- a/src/prefs/QualityPrefs.h +++ b/src/prefs/QualityPrefs.h @@ -53,4 +53,9 @@ class QualityPrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class QualityPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/RecordingPrefs.cpp b/src/prefs/RecordingPrefs.cpp index 01e3db2a4..393f2f113 100644 --- a/src/prefs/RecordingPrefs.cpp +++ b/src/prefs/RecordingPrefs.cpp @@ -202,3 +202,8 @@ bool RecordingPrefs::Apply() #endif return gPrefs->Flush(); } + +PrefsPanel *RecordingPrefsFactory::Create(wxWindow *parent) +{ + return new RecordingPrefs(parent); +} diff --git a/src/prefs/RecordingPrefs.h b/src/prefs/RecordingPrefs.h index d4f1dd122..f3f8b9ee1 100644 --- a/src/prefs/RecordingPrefs.h +++ b/src/prefs/RecordingPrefs.h @@ -32,4 +32,9 @@ class RecordingPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class RecordingPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index 118df5a38..79f2fe238 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -342,6 +342,11 @@ BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) EVT_CHOICE(ID_WINDOW_SIZE, SpectrumPrefs::OnWindowSize) END_EVENT_TABLE() +PrefsPanel *SpectrumPrefsFactory::Create(wxWindow *parent) +{ + return new SpectrumPrefs(parent); +} + SpectrogramSettings::SpectrogramSettings() : hFFT(0) , window(0) diff --git a/src/prefs/SpectrumPrefs.h b/src/prefs/SpectrumPrefs.h index 20a1e7385..a2be08dda 100644 --- a/src/prefs/SpectrumPrefs.h +++ b/src/prefs/SpectrumPrefs.h @@ -124,4 +124,10 @@ public: #endif }; +class SpectrumPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; + #endif diff --git a/src/prefs/ThemePrefs.cpp b/src/prefs/ThemePrefs.cpp index 2cbfd7ba3..f6d947b3e 100644 --- a/src/prefs/ThemePrefs.cpp +++ b/src/prefs/ThemePrefs.cpp @@ -205,3 +205,8 @@ bool ThemePrefs::Apply() return true; } + +PrefsPanel *ThemePrefsFactory::Create(wxWindow *parent) +{ + return new ThemePrefs(parent); +} diff --git a/src/prefs/ThemePrefs.h b/src/prefs/ThemePrefs.h index 40d080c8c..7668289d0 100644 --- a/src/prefs/ThemePrefs.h +++ b/src/prefs/ThemePrefs.h @@ -41,4 +41,9 @@ class ThemePrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class ThemePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/TracksPrefs.cpp b/src/prefs/TracksPrefs.cpp index 925c20888..7bed5d735 100644 --- a/src/prefs/TracksPrefs.cpp +++ b/src/prefs/TracksPrefs.cpp @@ -165,3 +165,8 @@ bool TracksPrefs::Apply() return true; } + +PrefsPanel *TracksPrefsFactory::Create(wxWindow *parent) +{ + return new TracksPrefs(parent); +} diff --git a/src/prefs/TracksPrefs.h b/src/prefs/TracksPrefs.h index aa0f54272..be1baeaa0 100644 --- a/src/prefs/TracksPrefs.h +++ b/src/prefs/TracksPrefs.h @@ -39,4 +39,9 @@ class TracksPrefs :public PrefsPanel wxArrayString mViewChoices; }; +class TracksPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/WarningsPrefs.cpp b/src/prefs/WarningsPrefs.cpp index 68d344593..c0cb5b47b 100644 --- a/src/prefs/WarningsPrefs.cpp +++ b/src/prefs/WarningsPrefs.cpp @@ -83,3 +83,8 @@ bool WarningsPrefs::Apply() return true; } + +PrefsPanel *WarningsPrefsFactory::Create(wxWindow *parent) +{ + return new WarningsPrefs(parent); +} diff --git a/src/prefs/WarningsPrefs.h b/src/prefs/WarningsPrefs.h index 8f789e163..97e9605b6 100644 --- a/src/prefs/WarningsPrefs.h +++ b/src/prefs/WarningsPrefs.h @@ -33,4 +33,9 @@ class WarningsPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class WarningsPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif From 2361758316cbf2c849cfe533dd9220d9650a12f3 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 13 Jun 2015 18:33:01 -0400 Subject: [PATCH 2/4] PrefsDialog can vary the title prefix string --- src/prefs/PrefsDialog.cpp | 13 +++++++++---- src/prefs/PrefsDialog.h | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index dc94a705c..9852d2f95 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -81,11 +81,14 @@ class wxTreebookExt : public wxTreebook { public: wxTreebookExt( wxWindow *parent, - wxWindowID id) : wxTreebook( parent, id ) + wxWindowID id, const wxString &titlePrefix) + : wxTreebook( parent, id ) + , mTitlePrefix(titlePrefix) {;}; ~wxTreebookExt(){;}; virtual int ChangeSelection(size_t n); virtual int SetSelection(size_t n); + const wxString mTitlePrefix; }; @@ -100,7 +103,7 @@ int wxTreebookExt::ChangeSelection(size_t n) { int wxTreebookExt::SetSelection(size_t n) { int i = wxTreebook::SetSelection(n); - wxString Temp = wxString(_("Preferences: ")) + GetPageText( n ); + wxString Temp = wxString(mTitlePrefix) + GetPageText( n ); ((wxDialog*)GetParent())->SetTitle( Temp ); ((wxDialog*)GetParent())->SetName( Temp ); return i; @@ -178,12 +181,14 @@ PrefsDialog::Factories } -PrefsDialog::PrefsDialog(wxWindow * parent, Factories &factories) +PrefsDialog::PrefsDialog + (wxWindow * parent, const wxString &titlePrefix, Factories &factories) : wxDialog(parent, wxID_ANY, wxString(_("Audacity Preferences")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) , mFactories(factories) +, mTitlePrefix(titlePrefix) { ShuttleGui S(this, eIsCreating); @@ -191,7 +196,7 @@ PrefsDialog::PrefsDialog(wxWindow * parent, Factories &factories) { S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND, true); { - mCategories = new wxTreebookExt(this, wxID_ANY); + mCategories = new wxTreebookExt(this, wxID_ANY, mTitlePrefix); S.Prop(1); S.AddWindow(mCategories, wxEXPAND); diff --git a/src/prefs/PrefsDialog.h b/src/prefs/PrefsDialog.h index 294826815..190207030 100644 --- a/src/prefs/PrefsDialog.h +++ b/src/prefs/PrefsDialog.h @@ -44,7 +44,9 @@ class PrefsDialog:public wxDialog typedef std::vector Factories; static Factories &DefaultFactories(); - PrefsDialog(wxWindow * parent, Factories &factories = DefaultFactories()); + PrefsDialog(wxWindow * parent, + const wxString &titlePrefix = _("Preferences: "), + Factories &factories = DefaultFactories()); virtual ~PrefsDialog(); void OnCategoryChange(wxCommandEvent & e); @@ -60,6 +62,7 @@ class PrefsDialog:public wxDialog wxTreebook *mCategories; Factories &mFactories; + const wxString mTitlePrefix; DECLARE_EVENT_TABLE() }; From 7b01339e510f53f5427f774103891e3fac366889 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 17 Jun 2015 15:52:29 -0400 Subject: [PATCH 3/4] Future subclasses of PrefsDialog may choose the preferred page by other means. --- src/AudacityApp.cpp | 4 +-- src/DirManager.cpp | 1 - src/Menus.cpp | 2 +- src/prefs/PrefsDialog.cpp | 61 +++++++++++++++++++++++++++------------ src/prefs/PrefsDialog.h | 28 ++++++++++++++++-- 5 files changed, 71 insertions(+), 25 deletions(-) diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 7f7df24dd..90ea7c794 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -1605,7 +1605,7 @@ bool AudacityApp::InitTempDir() // Failed wxMessageBox(_("Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog.")); - PrefsDialog dialog(NULL); + GlobalPrefsDialog dialog(NULL); dialog.ShowTempDirPage(); dialog.ShowModal(); @@ -2132,7 +2132,7 @@ void AudacityApp::OnMenuPreferences(wxCommandEvent & event) // all platforms. if(gAudacityProjects.GetCount() == 0) { - PrefsDialog dialog(NULL /* parent */ ); + GlobalPrefsDialog dialog(NULL /* parent */ ); dialog.ShowModal(); } else diff --git a/src/DirManager.cpp b/src/DirManager.cpp index 8104f56b1..691915c5a 100644 --- a/src/DirManager.cpp +++ b/src/DirManager.cpp @@ -101,7 +101,6 @@ #include "widgets/Warning.h" #include "widgets/MultiDialog.h" -#include "prefs/PrefsDialog.h" #include "ondemand/ODManager.h" #if defined(__WXMAC__) diff --git a/src/Menus.cpp b/src/Menus.cpp index 5ecfcce68..92c00da52 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -3586,7 +3586,7 @@ void AudacityProject::OnExportMultiple() void AudacityProject::OnPreferences() { - PrefsDialog dialog(this /* parent */ ); + GlobalPrefsDialog dialog(this /* parent */ ); if (!dialog.ShowModal()) { // Canceled diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index 9852d2f95..32da41f8f 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -233,23 +233,6 @@ PrefsDialog::PrefsDialog S.AddStandardButtons(eOkButton | eCancelButton); - /* long is signed, size_t is unsigned. On some platforms they are different - * lengths as well. So we must check that the stored category is both > 0 - * and within the possible range of categories, making the first check on the - * _signed_ value to avoid issues when converting an unsigned one. - */ - size_t selected; - long prefscat = gPrefs->Read(wxT("/Prefs/PrefsCategory"), 0L); - if (prefscat > 0L ) - selected = prefscat; // only assign if number will fit - else - selected = 0; // use 0 if value can't be assigned - - if (selected >= mCategories->GetPageCount()) - selected = 0; // clamp to available range of tabs - - mCategories->SetSelection(selected); - #if defined(__WXGTK__) mCategories->GetTreeCtrl()->EnsureVisible(mCategories->GetTreeCtrl()->GetRootItem()); #endif @@ -297,6 +280,21 @@ PrefsDialog::~PrefsDialog() { } +int PrefsDialog::ShowModal() +{ + /* long is signed, size_t is unsigned. On some platforms they are different + * lengths as well. So we must check that the stored category is both > 0 + * and within the possible range of categories, making the first check on the + * _signed_ value to avoid issues when converting an unsigned one. + */ + long selected = GetPreferredPage(); + if (selected < 0 || size_t(selected) >= mCategories->GetPageCount()) + selected = 0; // clamp to available range of tabs + mCategories->SetSelection(selected); + + return wxDialog::ShowModal(); +} + void PrefsDialog::OnCancel(wxCommandEvent & WXUNUSED(event)) { RecordExpansionState(); @@ -338,8 +336,7 @@ void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event)) panel->Apply(); } - gPrefs->Write(wxT("/Prefs/PrefsCategory"), (long)mCategories->GetSelection()); - gPrefs->Flush(); + SavePreferredPage(); #if USE_PORTMIXER if (gAudioIO) { @@ -394,6 +391,32 @@ void PrefsDialog::ShowTempDirPage() SelectPageByName(_("Directories")); } +int PrefsDialog::GetSelectedPage() const +{ + return mCategories->GetSelection(); +} + +GlobalPrefsDialog::GlobalPrefsDialog(wxWindow * parent) + : PrefsDialog(parent, _("Preferences: "), DefaultFactories()) +{ +} + +GlobalPrefsDialog::~GlobalPrefsDialog() +{ +} + +long GlobalPrefsDialog::GetPreferredPage() +{ + long prefscat = gPrefs->Read(wxT("/Prefs/PrefsCategory"), 0L); + return prefscat; +} + +void GlobalPrefsDialog::SavePreferredPage() +{ + gPrefs->Write(wxT("/Prefs/PrefsCategory"), (long)GetSelectedPage()); + gPrefs->Flush(); +} + void PrefsDialog::RecordExpansionState() { // Remember expansion state of the tree control diff --git a/src/prefs/PrefsDialog.h b/src/prefs/PrefsDialog.h index 190207030..239eb4d8a 100644 --- a/src/prefs/PrefsDialog.h +++ b/src/prefs/PrefsDialog.h @@ -49,6 +49,9 @@ class PrefsDialog:public wxDialog Factories &factories = DefaultFactories()); virtual ~PrefsDialog(); + // Defined this so a protected virtual can be invoked after the constructor + virtual int ShowModal(); + void OnCategoryChange(wxCommandEvent & e); void OnOK(wxCommandEvent & e); void OnCancel(wxCommandEvent & e); @@ -57,9 +60,19 @@ class PrefsDialog:public wxDialog void SelectPageByName(wxString pageName); void ShowTempDirPage(); - private: - void RecordExpansionState(); + // Accessor to help implementations of SavePreferredPage(), + // such as by saving a preference after DoModal() returns + int GetSelectedPage() const; + protected: + // Decide which page to open first; return -1 for undecided + virtual long GetPreferredPage() = 0; + + // Called after OK is clicked and all pages validate + virtual void SavePreferredPage() = 0; + +private: + void RecordExpansionState(); wxTreebook *mCategories; Factories &mFactories; const wxString mTitlePrefix; @@ -67,4 +80,15 @@ class PrefsDialog:public wxDialog DECLARE_EVENT_TABLE() }; +// This adds code appropriate only to the original use of PrefsDialog for +// global settings -- not its reuses elsewhere as in View Settings +class GlobalPrefsDialog : public PrefsDialog +{ +public: + GlobalPrefsDialog(wxWindow * parent); + virtual ~GlobalPrefsDialog(); + virtual long GetPreferredPage(); + virtual void SavePreferredPage(); +}; + #endif From b924c8ad62367cb1af203b4221d53158a588ccf1 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 17 Jun 2015 16:01:44 -0400 Subject: [PATCH 4/4] Fix crash initializing GlobalPrefsDialog for special case of undefined temp... ... directory at startup time. --- src/AudacityApp.cpp | 8 ++++++-- src/prefs/PrefsDialog.cpp | 9 ++------- src/prefs/PrefsDialog.h | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 90ea7c794..4a9e63021 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -92,6 +92,7 @@ It handles initialization and termination by subclassing wxApp. #include "ondemand/ODManager.h" #include "commands/Keyboard.h" #include "widgets/ErrorDialog.h" +#include "prefs/DirectoriesPrefs.h" //temporarilly commented out till it is added to all projects //#include "Profiler.h" @@ -1605,8 +1606,11 @@ bool AudacityApp::InitTempDir() // Failed wxMessageBox(_("Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog.")); - GlobalPrefsDialog dialog(NULL); - dialog.ShowTempDirPage(); + // Only want one page of the preferences + DirectoriesPrefsFactory directoriesPrefsFactory; + PrefsDialog::Factories factories; + factories.push_back(&directoriesPrefsFactory); + GlobalPrefsDialog dialog(NULL, factories); dialog.ShowModal(); wxMessageBox(_("Audacity is now going to exit. Please launch Audacity again to use the new temporary directory.")); diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index 32da41f8f..71a63fe5b 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -386,18 +386,13 @@ void PrefsDialog::SelectPageByName(wxString pageName) } } -void PrefsDialog::ShowTempDirPage() -{ - SelectPageByName(_("Directories")); -} - int PrefsDialog::GetSelectedPage() const { return mCategories->GetSelection(); } -GlobalPrefsDialog::GlobalPrefsDialog(wxWindow * parent) - : PrefsDialog(parent, _("Preferences: "), DefaultFactories()) +GlobalPrefsDialog::GlobalPrefsDialog(wxWindow * parent, Factories &factories) + : PrefsDialog(parent, _("Preferences: "), factories) { } diff --git a/src/prefs/PrefsDialog.h b/src/prefs/PrefsDialog.h index 239eb4d8a..a4b468921 100644 --- a/src/prefs/PrefsDialog.h +++ b/src/prefs/PrefsDialog.h @@ -58,7 +58,6 @@ class PrefsDialog:public wxDialog void OnTreeKeyDown(wxTreeEvent & e); // Used to dismiss the dialog when enter is pressed with focus on tree void SelectPageByName(wxString pageName); - void ShowTempDirPage(); // Accessor to help implementations of SavePreferredPage(), // such as by saving a preference after DoModal() returns @@ -85,7 +84,7 @@ private: class GlobalPrefsDialog : public PrefsDialog { public: - GlobalPrefsDialog(wxWindow * parent); + GlobalPrefsDialog(wxWindow * parent, Factories &factories = DefaultFactories()); virtual ~GlobalPrefsDialog(); virtual long GetPreferredPage(); virtual void SavePreferredPage();