diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 136fe911f..d9cf6a45d 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -110,7 +110,6 @@ class AdornedRulerPanel::QuickPlayRulerOverlay final : public Overlay { public: QuickPlayRulerOverlay(QuickPlayIndicatorOverlay &partner); - virtual ~QuickPlayRulerOverlay(); // Available to this and to partner @@ -149,20 +148,19 @@ private: class AdornedRulerPanel::QuickPlayIndicatorOverlay final : public Overlay { friend QuickPlayRulerOverlay; + friend AdornedRulerPanel; public: QuickPlayIndicatorOverlay(AudacityProject *project); - virtual ~QuickPlayIndicatorOverlay(); - private: std::pair DoGetRectangle(wxSize size) override; void Draw(OverlayPanel &panel, wxDC &dc) override; AudacityProject *mProject; - std::unique_ptr mPartner - { std::make_unique(*this) }; + std::shared_ptr mPartner + { std::make_shared(*this) }; int mOldQPIndicatorPos { -1 }; bool mOldQPIndicatorSnapped {}; @@ -179,14 +177,6 @@ AdornedRulerPanel::QuickPlayRulerOverlay::QuickPlayRulerOverlay( QuickPlayIndicatorOverlay &partner) : mPartner(partner) { - GetRuler()->AddOverlay(this); -} - -AdornedRulerPanel::QuickPlayRulerOverlay::~QuickPlayRulerOverlay() -{ - auto ruler = GetRuler(); - if (ruler) - ruler->RemoveOverlay(this); } AdornedRulerPanel *AdornedRulerPanel::QuickPlayRulerOverlay::GetRuler() const @@ -286,15 +276,6 @@ AdornedRulerPanel::QuickPlayIndicatorOverlay::QuickPlayIndicatorOverlay( AudacityProject *project) : mProject(project) { - auto tp = mProject->GetTrackPanel(); - tp->AddOverlay(this); -} - -AdornedRulerPanel::QuickPlayIndicatorOverlay::~QuickPlayIndicatorOverlay() -{ - auto tp = mProject->GetTrackPanel(); - if (tp) - tp->RemoveOverlay(this); } std::pair @@ -2175,7 +2156,10 @@ bool AdornedRulerPanel::TakesFocus() const void AdornedRulerPanel::CreateOverlays() { - if (!mOverlay) + if (!mOverlay) { mOverlay = - std::make_unique( mProject ); + std::make_shared( mProject ); + mProject->GetTrackPanel()->AddOverlay( mOverlay ); + this->AddOverlay( mOverlay->mPartner ); + } } diff --git a/src/AdornedRulerPanel.h b/src/AdornedRulerPanel.h index 2f3966563..dc9a40757 100644 --- a/src/AdornedRulerPanel.h +++ b/src/AdornedRulerPanel.h @@ -193,7 +193,7 @@ private: // Cooperating objects class QuickPlayIndicatorOverlay; - std::unique_ptr mOverlay; + std::shared_ptr mOverlay; class QuickPlayRulerOverlay; diff --git a/src/Project.cpp b/src/Project.cpp index 863068c17..aa3921b36 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -1178,28 +1178,28 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, mRuler); mTrackPanel->UpdatePrefs(); - mCursorOverlay = std::make_unique(this); + mCursorOverlay = std::make_shared(this); mBackgroundCell = std::make_shared(this); #ifdef EXPERIMENTAL_SCRUBBING_BASIC - mScrubOverlay = std::make_unique(this); + mScrubOverlay = std::make_shared(this); mScrubber = std::make_unique(this); #endif mPlaybackScroller = std::make_unique(this); - mIndicatorOverlay = std::make_unique(this); + mIndicatorOverlay = std::make_shared(this); this->Bind(EVT_TRACK_PANEL_TIMER, &ViewInfo::OnTimer, &mViewInfo); // Add the overlays, in the sequence in which they will be painted - mTrackPanel->AddOverlay(mIndicatorOverlay.get()); - mTrackPanel->AddOverlay(mCursorOverlay.get()); + mTrackPanel->AddOverlay( mIndicatorOverlay ); + mTrackPanel->AddOverlay( mCursorOverlay ); #ifdef EXPERIMENTAL_SCRUBBING_BASIC - mTrackPanel->AddOverlay(mScrubOverlay.get()); + mTrackPanel->AddOverlay( mScrubOverlay ); #endif mMenuManager->CreateMenusAndCommands(*this); @@ -1337,14 +1337,6 @@ AudacityProject::~AudacityProject() // Tool manager gives us capture sometimes if(HasCapture()) ReleaseMouse(); - - if(mTrackPanel) { -#ifdef EXPERIMENTAL_SCRUBBING_BASIC - mTrackPanel->RemoveOverlay(mScrubOverlay.get()); -#endif - mTrackPanel->RemoveOverlay(mCursorOverlay.get()); - mTrackPanel->RemoveOverlay(mIndicatorOverlay.get()); - } } void AudacityProject::ApplyUpdatedTheme() diff --git a/src/Project.h b/src/Project.h index 778e9890e..b6099d8f5 100644 --- a/src/Project.h +++ b/src/Project.h @@ -33,7 +33,7 @@ #include "toolbars/SelectionBarListener.h" #include "toolbars/SpectralSelectionBarListener.h" -#include "MemoryX.h" +#include #include #include #include @@ -774,13 +774,13 @@ private: friend class CommandManager; // TrackPanelOverlay objects - std::unique_ptr + std::shared_ptr mIndicatorOverlay, mCursorOverlay; std::shared_ptr mBackgroundCell; #ifdef EXPERIMENTAL_SCRUBBING_BASIC - std::unique_ptr mScrubOverlay; + std::shared_ptr mScrubOverlay; std::unique_ptr mScrubber; public: Scrubber &GetScrubber() { return *mScrubber; } diff --git a/src/tracks/ui/EditCursorOverlay.cpp b/src/tracks/ui/EditCursorOverlay.cpp index 577de1d38..b2386da7b 100644 --- a/src/tracks/ui/EditCursorOverlay.cpp +++ b/src/tracks/ui/EditCursorOverlay.cpp @@ -37,15 +37,6 @@ EditCursorOverlay::EditCursorOverlay(AudacityProject *project, bool isMaster) { } -EditCursorOverlay::~EditCursorOverlay() -{ - if (mIsMaster && mPartner) { - auto ruler = mProject->GetRulerPanel(); - if (ruler) - ruler->RemoveOverlay(mPartner.get()); - } -} - std::pair EditCursorOverlay::DoGetRectangle(wxSize size) { const SelectedRegion &selection = mProject->GetSelection(); @@ -74,8 +65,8 @@ void EditCursorOverlay::Draw(OverlayPanel &panel, wxDC &dc) if (mIsMaster && !mPartner) { auto ruler = mProject->GetRulerPanel(); if (ruler) { - mPartner = std::make_unique(mProject, false); - ruler->AddOverlay(mPartner.get()); + mPartner = std::make_shared(mProject, false); + ruler->AddOverlay( mPartner ); } } diff --git a/src/tracks/ui/EditCursorOverlay.h b/src/tracks/ui/EditCursorOverlay.h index 65dad676e..8ad634cd9 100644 --- a/src/tracks/ui/EditCursorOverlay.h +++ b/src/tracks/ui/EditCursorOverlay.h @@ -11,7 +11,7 @@ Paul Licameli split from TrackPanel.cpp #ifndef __AUDACITY_EDIT_CURSOR_OVERLAY__ #define __AUDACITY_EDIT_CURSOR_OVERLAY__ -#include "../../MemoryX.h" +#include #include "../../widgets/Overlay.h" class AudacityProject; @@ -20,7 +20,6 @@ class EditCursorOverlay final : public Overlay { public: EditCursorOverlay(AudacityProject *project, bool isMaster = true); - virtual ~EditCursorOverlay(); private: std::pair DoGetRectangle(wxSize size) override; @@ -28,7 +27,7 @@ private: AudacityProject *mProject; bool mIsMaster; - std::unique_ptr mPartner; + std::shared_ptr mPartner; int mLastCursorX; double mCursorTime; diff --git a/src/tracks/ui/PlayIndicatorOverlay.cpp b/src/tracks/ui/PlayIndicatorOverlay.cpp index 5d159ce35..6e69289ef 100644 --- a/src/tracks/ui/PlayIndicatorOverlay.cpp +++ b/src/tracks/ui/PlayIndicatorOverlay.cpp @@ -115,15 +115,6 @@ PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project) this); } -PlayIndicatorOverlay::~PlayIndicatorOverlay() -{ - if (mPartner) { - auto ruler = mProject->GetRulerPanel(); - if(ruler) - ruler->RemoveOverlay(mPartner.get()); - } -} - void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event) { // Let other listeners get the notification @@ -133,8 +124,8 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event) if (!mPartner) { auto ruler = mProject->GetRulerPanel(); if (ruler) { - mPartner = std::make_unique(mProject, false); - ruler->AddOverlay(mPartner.get()); + mPartner = std::make_shared(mProject, false); + ruler->AddOverlay( mPartner ); } } diff --git a/src/tracks/ui/PlayIndicatorOverlay.h b/src/tracks/ui/PlayIndicatorOverlay.h index da4214d2c..37ffd183d 100644 --- a/src/tracks/ui/PlayIndicatorOverlay.h +++ b/src/tracks/ui/PlayIndicatorOverlay.h @@ -46,12 +46,11 @@ class PlayIndicatorOverlay final : public PlayIndicatorOverlayBase { public: PlayIndicatorOverlay(AudacityProject *project); - virtual ~PlayIndicatorOverlay(); private: void OnTimer(wxCommandEvent &event); - std::unique_ptr mPartner; + std::shared_ptr mPartner; }; #endif diff --git a/src/widgets/OverlayPanel.cpp b/src/widgets/OverlayPanel.cpp index 94865130b..9201321a6 100644 --- a/src/widgets/OverlayPanel.cpp +++ b/src/widgets/OverlayPanel.cpp @@ -20,18 +20,11 @@ OverlayPanel::OverlayPanel(wxWindow * parent, wxWindowID id, : BackedPanel(parent, id, pos, size, style) {} -void OverlayPanel::AddOverlay(Overlay *pOverlay) +void OverlayPanel::AddOverlay( const std::weak_ptr &pOverlay) { mOverlays.push_back(pOverlay); } -bool OverlayPanel::RemoveOverlay(Overlay *pOverlay) -{ - const size_t oldSize = mOverlays.size(); - mOverlays.erase(std::remove(mOverlays.begin(), mOverlays.end(), pOverlay), mOverlays.end()); - return oldSize != mOverlays.size(); -} - void OverlayPanel::ClearOverlays() { mOverlays.clear(); @@ -45,10 +38,14 @@ void OverlayPanel::DrawOverlays(bool repaint_all, wxDC *pDC) std::vector< Pair > pairs; pairs.reserve(n_pairs); + // First... + Compress(); + // ... then assume pointers are not expired + // Find out the rectangles and outdatedness for each overlay wxSize size(GetBackingDC().GetSize()); for (const auto pOverlay : mOverlays) - pairs.push_back(pOverlay->GetRectangle(size)); + pairs.push_back( pOverlay.lock()->GetRectangle(size) ); // See what requires redrawing. If repainting, all. // If not, then whatever is outdated, and whatever will be damaged by @@ -96,7 +93,7 @@ void OverlayPanel::DrawOverlays(bool repaint_all, wxDC *pDC) auto it2 = pairs.begin(); for (auto pOverlay : mOverlays) { if (repaint_all || it2->second) - pOverlay->Erase(dc, GetBackingDC()); + pOverlay.lock()->Erase(dc, GetBackingDC()); ++it2; } @@ -107,11 +104,23 @@ void OverlayPanel::DrawOverlays(bool repaint_all, wxDC *pDC) // Guarantee a clean state of the dc each pass: ADCChanger changer{ &dc }; - pOverlay->Draw(*this, dc); + pOverlay.lock()->Draw(*this, dc); } ++it2; } } +void OverlayPanel::Compress() +{ + // remove any expired pointers + auto begin = mOverlays.begin(); + auto end = mOverlays.end(); + auto newEnd = std::remove_if( begin, end, + []( const std::weak_ptr &pOverlay ){ + return pOverlay.expired(); } ); + if ( end != newEnd ) + mOverlays.resize( newEnd - begin ); +} + BEGIN_EVENT_TABLE(OverlayPanel, BackedPanel) END_EVENT_TABLE() diff --git a/src/widgets/OverlayPanel.h b/src/widgets/OverlayPanel.h index 98cc922d4..a9196937d 100644 --- a/src/widgets/OverlayPanel.h +++ b/src/widgets/OverlayPanel.h @@ -9,6 +9,7 @@ #ifndef __AUDACITY_OVERLAY_PANEL__ #define __AUDACITY_OVERLAY_PANEL__ +#include #include #include "BackedPanel.h" @@ -22,13 +23,11 @@ public: // default as for wxPanel: long style = wxTAB_TRAVERSAL | wxNO_BORDER); - // Registers and unregisters overlay objects. + // Registers overlay objects. // The sequence in which they were registered is the sequence in // which they are painted. // OverlayPanel is not responsible for their memory management. - void AddOverlay(Overlay *pOverlay); - // Returns true if the overlay was found - bool RemoveOverlay(Overlay *pOverlay); + void AddOverlay( const std::weak_ptr &pOverlay ); void ClearOverlays(); // Erases and redraws to the client area the overlays that have @@ -41,7 +40,8 @@ public: void DrawOverlays(bool repaint_all, wxDC *pDC = nullptr); private: - std::vector mOverlays; + void Compress(); + std::vector< std::weak_ptr > mOverlays; DECLARE_EVENT_TABLE()