diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 29c98ae3d..b4581a024 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -75,7 +75,6 @@ It handles initialization and termination by subclassing wxApp. #include "DirManager.h" #include "commands/CommandHandler.h" #include "commands/AppCommandEvent.h" -#include "effects/Contrast.h" #include "widgets/ASlider.h" #include "FFmpeg.h" #include "LangChoice.h" diff --git a/src/AudacityHeaders.h b/src/AudacityHeaders.h index 74d9d846f..dc75e0c17 100644 --- a/src/AudacityHeaders.h +++ b/src/AudacityHeaders.h @@ -51,7 +51,6 @@ #include "Envelope.h" #include "FFT.h" #include "FileFormats.h" -#include "FreqWindow.h" #include "ImageManipulation.h" #include "LabelTrack.h" #include "Mix.h" diff --git a/src/Project.cpp b/src/Project.cpp index 42c9bdd55..60c3af571 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -98,22 +98,17 @@ scroll information. It also has some status flags. #include "AdornedRulerPanel.h" #include "Clipboard.h" #include "widgets/FileHistory.h" -#include "FreqWindow.h" -#include "effects/Contrast.h" #include "AutoRecovery.h" #include "AColor.h" #include "AudioIO.h" -#include "BatchProcessDialog.h" #include "Dependencies.h" #include "Diags.h" -#include "HistoryWindow.h" +#include "export/Export.h" #include "InconsistencyException.h" -#include "MixerBoard.h" #include "import/Import.h" #include "KeyboardCapture.h" #include "LabelTrack.h" #include "Legacy.h" -#include "LyricsWindow.h" #include "Menus.h" #include "MissingAliasFileDialog.h" #include "Mix.h" @@ -1352,6 +1347,8 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, #endif AttachedObjects::BuildAll(); + // But not for the attached windows. They get built only on demand, such as + // from menu items. } AudacityProject::~AudacityProject() @@ -2479,14 +2476,6 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) return; } - // TODO: consider postponing these steps until after the possible veto - // below: closing the two analysis dialogs, and stopping audio streams. - // Streams can be for play, recording, or monitoring. But maybe it still - // makes sense to stop any recording before putting up the dialog. - - mFreqWindow.reset(); - mContrastDialog.reset(); - // Check to see if we were playing or recording // audio, and if so, make sure Audio I/O is completely finished. // The main point of this is to properly push the state @@ -2590,16 +2579,6 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) projectFileIO.CloseLock(); - // Get rid of the history window - // LL: Destroy it before the TrackPanel and ToolBars since they - // may/will get additional wxEVT_PAINT events since window - // destruction may be queued. This seems to only be a problem - // on the Mac. - if (mHistoryWindow) { - mHistoryWindow->Destroy(); - mHistoryWindow = NULL; - } - // Some of the AdornedRulerPanel functions refer to the TrackPanel, so destroy this // before the TrackPanel is destroyed. This change was needed to stop Audacity // crashing when running with Jaws on Windows 10 1703. @@ -5507,64 +5486,6 @@ void AudacityProject::PlaybackScroller::OnTimer(wxCommandEvent &event) } } -LyricsWindow* AudacityProject::GetLyricsWindow(bool create) -{ - if (create && !mLyricsWindow) - mLyricsWindow = safenew LyricsWindow{ this }; - return mLyricsWindow; -} - -MixerBoardFrame* AudacityProject::GetMixerBoardFrame(bool create) -{ - if (create && !mMixerBoardFrame) - mMixerBoardFrame = safenew MixerBoardFrame{ this }; - return mMixerBoardFrame; -} - -HistoryWindow *AudacityProject::GetHistoryWindow(bool create) -{ - auto &project = *this; - auto &undoManager = UndoManager::Get( project ); - if (create && !mHistoryWindow) - mHistoryWindow = safenew HistoryWindow{ this, &undoManager }; - return mHistoryWindow; -} - -MacrosWindow *AudacityProject::GetMacrosWindow(bool bExpanded, bool create) -{ - if (create && !mMacrosWindow) - mMacrosWindow = safenew MacrosWindow{ this, bExpanded }; - - if (mMacrosWindow) { - mMacrosWindow->Show(); - mMacrosWindow->Raise(); - mMacrosWindow->UpdateDisplay( bExpanded ); - } - return mMacrosWindow; -} - -FreqWindow *AudacityProject::GetFreqWindow(bool create) -{ - if (create && !mFreqWindow) - mFreqWindow.reset( safenew FreqWindow{ - this, -1, _("Frequency Analysis"), - wxPoint{ 150, 150 } - } ); - return mFreqWindow.get(); -} - -ContrastDialog *AudacityProject::GetContrastDialog(bool create) -{ - // All of this goes away when the Contrast Dialog is converted to a module - if(create && !mContrastDialog) - mContrastDialog.reset( safenew ContrastDialog{ - this, -1, _("Contrast Analysis (WCAG 2 compliance)"), - wxPoint{ 150, 150 } - } ); - - return mContrastDialog.get(); -} - void AudacityProject::ZoomInByFactor( double ZoomFactor ) { auto &project = *this; diff --git a/src/Project.h b/src/Project.h index 364d890e3..73925ff16 100644 --- a/src/Project.h +++ b/src/Project.h @@ -61,7 +61,6 @@ class TrackList; class TrackPanel; class FreqWindow; -class ContrastDialog; class MeterPanel; // toolbar classes @@ -76,11 +75,7 @@ class TranscriptionToolBar; // windows and frames class AdornedRulerPanel; -class HistoryWindow; -class MacrosWindow; class LyricsWindow; -class MixerBoard; -class MixerBoardFrame; struct AudioIOStartStreamOptions; struct UndoState; @@ -166,9 +161,17 @@ class WaveTrack; class MenuManager; +// Container of various objects associated with the project, which is +// responsible for destroying them using AttachedObjects = ClientData::Site< AudacityProject, ClientData::Base, ClientData::SkipCopying, std::shared_ptr >; +// Container of pointers to various windows associated with the project, which +// is not responsible for destroying them -- wxWidgets handles that instead +using AttachedWindows = ClientData::Site< + AudacityProject, wxWindow, ClientData::SkipCopying, wxWeakRef +>; + class AUDACITY_DLL_API AudacityProject final : public wxFrame, public TrackPanelListener, public SelectionBarListener, @@ -177,9 +180,11 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame, public AudioIOListener, private PrefsListener , public AttachedObjects + , public AttachedWindows { public: using AttachedObjects = ::AttachedObjects; + using AttachedWindows = ::AttachedWindows; AudacityProject(wxWindow * parent, wxWindowID id, const wxPoint & pos, const wxSize & size); @@ -435,13 +440,6 @@ public: MeterPanel *GetCaptureMeter(); void SetCaptureMeter(MeterPanel *capture); - LyricsWindow* GetLyricsWindow(bool create = false); - MixerBoardFrame* GetMixerBoardFrame(bool create = false); - HistoryWindow *GetHistoryWindow(bool create = false); - MacrosWindow *GetMacrosWindow(bool bExpanded, bool create = false); - FreqWindow *GetFreqWindow(bool create = false); - ContrastDialog *GetContrastDialog(bool create = false); - private: bool SnapSelection(); @@ -562,14 +560,6 @@ private: bool mActive{ true }; bool mIconized; - MacrosWindow *mMacrosWindow{}; - HistoryWindow *mHistoryWindow{}; - LyricsWindow* mLyricsWindow{}; - MixerBoardFrame* mMixerBoardFrame{}; - - Destroy_ptr mFreqWindow; - Destroy_ptr mContrastDialog; - bool mShownOnce{ false }; // Project owned meters diff --git a/src/menus/PluginMenus.cpp b/src/menus/PluginMenus.cpp index e53866fce..fc7fb6c5b 100644 --- a/src/menus/PluginMenus.cpp +++ b/src/menus/PluginMenus.cpp @@ -23,6 +23,32 @@ // private helper classes and functions namespace { +AudacityProject::AttachedWindows::RegisteredFactory sContrastDialogKey{ + []( AudacityProject &parent ) -> wxWeakRef< wxWindow > { + return safenew ContrastDialog( + &parent, -1, _("Contrast Analysis (WCAG 2 compliance)"), + wxPoint{ 150, 150 } + ); + } +}; + +AudacityProject::AttachedWindows::RegisteredFactory sFrequencyWindowKey{ + []( AudacityProject &parent ) -> wxWeakRef< wxWindow > { + return safenew FreqWindow( + &parent, -1, _("Frequency Analysis"), + wxPoint{ 150, 150 } + ); + } +}; + +AudacityProject::AttachedWindows::RegisteredFactory sMacrosWindowKey{ + []( AudacityProject &parent ) -> wxWeakRef< wxWindow > { + return safenew MacrosWindow( + &parent, true + ); + } +}; + void DoManagePluginsMenu (AudacityProject &project, EffectType type) { @@ -591,8 +617,8 @@ void OnManageAnalyzers(const CommandContext &context) void OnContrast(const CommandContext &context) { auto &project = context.project; - auto contrastDialog = project.GetContrastDialog(true); - + auto contrastDialog = + &project.AttachedWindows::Get< ContrastDialog >( sContrastDialogKey ); contrastDialog->CentreOnParent(); if( ScreenshotCommand::MayCapture( contrastDialog ) ) @@ -603,8 +629,8 @@ void OnContrast(const CommandContext &context) void OnPlotSpectrum(const CommandContext &context) { auto &project = context.project; - auto freqWindow = project.GetFreqWindow(true); - + auto freqWindow = + &project.AttachedWindows::Get< FreqWindow >( sFrequencyWindowKey ); if( ScreenshotCommand::MayCapture( freqWindow ) ) return; @@ -622,13 +648,25 @@ void OnManageTools(const CommandContext &context ) void OnManageMacros(const CommandContext &context ) { auto &project = context.project; - project.GetMacrosWindow( true, true ); + auto macrosWindow = + &project.AttachedWindows::Get< MacrosWindow >( sMacrosWindowKey ); + if (macrosWindow) { + macrosWindow->Show(); + macrosWindow->Raise(); + macrosWindow->UpdateDisplay( true ); + } } void OnApplyMacrosPalette(const CommandContext &context ) { auto &project = context.project; - project.GetMacrosWindow( false, true ); + auto macrosWindow = + &project.AttachedWindows::Get< MacrosWindow >( sMacrosWindowKey ); + if (macrosWindow) { + macrosWindow->Show(); + macrosWindow->Raise(); + macrosWindow->UpdateDisplay( false ); + } } void OnScreenshot(const CommandContext &WXUNUSED(context) ) diff --git a/src/menus/ViewMenus.cpp b/src/menus/ViewMenus.cpp index 237629619..76acacc7d 100644 --- a/src/menus/ViewMenus.cpp +++ b/src/menus/ViewMenus.cpp @@ -8,6 +8,7 @@ #include "../Prefs.h" #include "../Project.h" #include "../TrackPanel.h" +#include "../UndoManager.h" #include "../ViewInfo.h" #include "../commands/CommandContext.h" #include "../commands/CommandManager.h" @@ -23,6 +24,25 @@ // private helper classes and functions namespace { +AudacityProject::AttachedWindows::RegisteredFactory sMixerBoardKey{ + []( AudacityProject &parent ) -> wxWeakRef< wxWindow > { + return safenew MixerBoardFrame( &parent ); + } +}; + +AudacityProject::AttachedWindows::RegisteredFactory sHistoryWindowKey{ + []( AudacityProject &parent ) -> wxWeakRef< wxWindow > { + auto &undoManager = UndoManager::Get( parent ); + return safenew HistoryWindow( &parent, &undoManager ); + } +}; + +AudacityProject::AttachedWindows::RegisteredFactory sLyricsWindowKey{ + []( AudacityProject &parent ) -> wxWeakRef< wxWindow > { + return safenew LyricsWindow( &parent ); + } +}; + double GetZoomOfSelection( const AudacityProject &project ) { auto &viewInfo = ViewInfo::Get( project ); @@ -323,7 +343,7 @@ void OnHistory(const CommandContext &context) { auto &project = context.project; - auto historyWindow = project.GetHistoryWindow(true); + auto historyWindow = &project.AttachedWindows::Get( sHistoryWindowKey ); historyWindow->Show(); historyWindow->Raise(); } @@ -332,7 +352,7 @@ void OnKaraoke(const CommandContext &context) { auto &project = context.project; - auto lyricsWindow = project.GetLyricsWindow(true); + auto lyricsWindow = &project.AttachedWindows::Get( sLyricsWindowKey ); lyricsWindow->Show(); lyricsWindow->Raise(); } @@ -341,7 +361,7 @@ void OnMixerBoard(const CommandContext &context) { auto &project = context.project; - auto mixerBoardFrame = project.GetMixerBoardFrame(true); + auto mixerBoardFrame = &project.AttachedWindows::Get( sMixerBoardKey ); mixerBoardFrame->Show(); mixerBoardFrame->Raise(); mixerBoardFrame->SetFocus();