1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-02 17:09:26 +02:00

OverlayPanel uses weak_ptr to Overlay, which simplifies other dtors

This commit is contained in:
Paul Licameli 2019-01-23 20:53:37 -05:00
parent ac2fecf151
commit f7162d3326
10 changed files with 50 additions and 85 deletions

View File

@ -110,7 +110,6 @@ class AdornedRulerPanel::QuickPlayRulerOverlay final : public Overlay
{ {
public: public:
QuickPlayRulerOverlay(QuickPlayIndicatorOverlay &partner); QuickPlayRulerOverlay(QuickPlayIndicatorOverlay &partner);
virtual ~QuickPlayRulerOverlay();
// Available to this and to partner // Available to this and to partner
@ -149,20 +148,19 @@ private:
class AdornedRulerPanel::QuickPlayIndicatorOverlay final : public Overlay class AdornedRulerPanel::QuickPlayIndicatorOverlay final : public Overlay
{ {
friend QuickPlayRulerOverlay; friend QuickPlayRulerOverlay;
friend AdornedRulerPanel;
public: public:
QuickPlayIndicatorOverlay(AudacityProject *project); QuickPlayIndicatorOverlay(AudacityProject *project);
virtual ~QuickPlayIndicatorOverlay();
private: private:
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override; std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw(OverlayPanel &panel, wxDC &dc) override; void Draw(OverlayPanel &panel, wxDC &dc) override;
AudacityProject *mProject; AudacityProject *mProject;
std::unique_ptr<QuickPlayRulerOverlay> mPartner std::shared_ptr<QuickPlayRulerOverlay> mPartner
{ std::make_unique<QuickPlayRulerOverlay>(*this) }; { std::make_shared<QuickPlayRulerOverlay>(*this) };
int mOldQPIndicatorPos { -1 }; int mOldQPIndicatorPos { -1 };
bool mOldQPIndicatorSnapped {}; bool mOldQPIndicatorSnapped {};
@ -179,14 +177,6 @@ AdornedRulerPanel::QuickPlayRulerOverlay::QuickPlayRulerOverlay(
QuickPlayIndicatorOverlay &partner) QuickPlayIndicatorOverlay &partner)
: mPartner(partner) : mPartner(partner)
{ {
GetRuler()->AddOverlay(this);
}
AdornedRulerPanel::QuickPlayRulerOverlay::~QuickPlayRulerOverlay()
{
auto ruler = GetRuler();
if (ruler)
ruler->RemoveOverlay(this);
} }
AdornedRulerPanel *AdornedRulerPanel::QuickPlayRulerOverlay::GetRuler() const AdornedRulerPanel *AdornedRulerPanel::QuickPlayRulerOverlay::GetRuler() const
@ -286,15 +276,6 @@ AdornedRulerPanel::QuickPlayIndicatorOverlay::QuickPlayIndicatorOverlay(
AudacityProject *project) AudacityProject *project)
: mProject(project) : mProject(project)
{ {
auto tp = mProject->GetTrackPanel();
tp->AddOverlay(this);
}
AdornedRulerPanel::QuickPlayIndicatorOverlay::~QuickPlayIndicatorOverlay()
{
auto tp = mProject->GetTrackPanel();
if (tp)
tp->RemoveOverlay(this);
} }
std::pair<wxRect, bool> std::pair<wxRect, bool>
@ -2175,7 +2156,10 @@ bool AdornedRulerPanel::TakesFocus() const
void AdornedRulerPanel::CreateOverlays() void AdornedRulerPanel::CreateOverlays()
{ {
if (!mOverlay) if (!mOverlay) {
mOverlay = mOverlay =
std::make_unique<QuickPlayIndicatorOverlay>( mProject ); std::make_shared<QuickPlayIndicatorOverlay>( mProject );
mProject->GetTrackPanel()->AddOverlay( mOverlay );
this->AddOverlay( mOverlay->mPartner );
}
} }

View File

@ -193,7 +193,7 @@ private:
// Cooperating objects // Cooperating objects
class QuickPlayIndicatorOverlay; class QuickPlayIndicatorOverlay;
std::unique_ptr<QuickPlayIndicatorOverlay> mOverlay; std::shared_ptr<QuickPlayIndicatorOverlay> mOverlay;
class QuickPlayRulerOverlay; class QuickPlayRulerOverlay;

View File

@ -1178,28 +1178,28 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
mRuler); mRuler);
mTrackPanel->UpdatePrefs(); mTrackPanel->UpdatePrefs();
mCursorOverlay = std::make_unique<EditCursorOverlay>(this); mCursorOverlay = std::make_shared<EditCursorOverlay>(this);
mBackgroundCell = std::make_shared<BackgroundCell>(this); mBackgroundCell = std::make_shared<BackgroundCell>(this);
#ifdef EXPERIMENTAL_SCRUBBING_BASIC #ifdef EXPERIMENTAL_SCRUBBING_BASIC
mScrubOverlay = std::make_unique<ScrubbingOverlay>(this); mScrubOverlay = std::make_shared<ScrubbingOverlay>(this);
mScrubber = std::make_unique<Scrubber>(this); mScrubber = std::make_unique<Scrubber>(this);
#endif #endif
mPlaybackScroller = std::make_unique<PlaybackScroller>(this); mPlaybackScroller = std::make_unique<PlaybackScroller>(this);
mIndicatorOverlay = std::make_unique<PlayIndicatorOverlay>(this); mIndicatorOverlay = std::make_shared<PlayIndicatorOverlay>(this);
this->Bind(EVT_TRACK_PANEL_TIMER, this->Bind(EVT_TRACK_PANEL_TIMER,
&ViewInfo::OnTimer, &ViewInfo::OnTimer,
&mViewInfo); &mViewInfo);
// Add the overlays, in the sequence in which they will be painted // Add the overlays, in the sequence in which they will be painted
mTrackPanel->AddOverlay(mIndicatorOverlay.get()); mTrackPanel->AddOverlay( mIndicatorOverlay );
mTrackPanel->AddOverlay(mCursorOverlay.get()); mTrackPanel->AddOverlay( mCursorOverlay );
#ifdef EXPERIMENTAL_SCRUBBING_BASIC #ifdef EXPERIMENTAL_SCRUBBING_BASIC
mTrackPanel->AddOverlay(mScrubOverlay.get()); mTrackPanel->AddOverlay( mScrubOverlay );
#endif #endif
mMenuManager->CreateMenusAndCommands(*this); mMenuManager->CreateMenusAndCommands(*this);
@ -1337,14 +1337,6 @@ AudacityProject::~AudacityProject()
// Tool manager gives us capture sometimes // Tool manager gives us capture sometimes
if(HasCapture()) if(HasCapture())
ReleaseMouse(); ReleaseMouse();
if(mTrackPanel) {
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
mTrackPanel->RemoveOverlay(mScrubOverlay.get());
#endif
mTrackPanel->RemoveOverlay(mCursorOverlay.get());
mTrackPanel->RemoveOverlay(mIndicatorOverlay.get());
}
} }
void AudacityProject::ApplyUpdatedTheme() void AudacityProject::ApplyUpdatedTheme()

View File

@ -33,7 +33,7 @@
#include "toolbars/SelectionBarListener.h" #include "toolbars/SelectionBarListener.h"
#include "toolbars/SpectralSelectionBarListener.h" #include "toolbars/SpectralSelectionBarListener.h"
#include "MemoryX.h" #include <memory>
#include <wx/defs.h> #include <wx/defs.h>
#include <wx/event.h> #include <wx/event.h>
#include <wx/log.h> #include <wx/log.h>
@ -774,13 +774,13 @@ private:
friend class CommandManager; friend class CommandManager;
// TrackPanelOverlay objects // TrackPanelOverlay objects
std::unique_ptr<Overlay> std::shared_ptr<Overlay>
mIndicatorOverlay, mCursorOverlay; mIndicatorOverlay, mCursorOverlay;
std::shared_ptr<BackgroundCell> mBackgroundCell; std::shared_ptr<BackgroundCell> mBackgroundCell;
#ifdef EXPERIMENTAL_SCRUBBING_BASIC #ifdef EXPERIMENTAL_SCRUBBING_BASIC
std::unique_ptr<Overlay> mScrubOverlay; std::shared_ptr<Overlay> mScrubOverlay;
std::unique_ptr<Scrubber> mScrubber; std::unique_ptr<Scrubber> mScrubber;
public: public:
Scrubber &GetScrubber() { return *mScrubber; } Scrubber &GetScrubber() { return *mScrubber; }

View File

@ -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<wxRect, bool> EditCursorOverlay::DoGetRectangle(wxSize size) std::pair<wxRect, bool> EditCursorOverlay::DoGetRectangle(wxSize size)
{ {
const SelectedRegion &selection = mProject->GetSelection(); const SelectedRegion &selection = mProject->GetSelection();
@ -74,8 +65,8 @@ void EditCursorOverlay::Draw(OverlayPanel &panel, wxDC &dc)
if (mIsMaster && !mPartner) { if (mIsMaster && !mPartner) {
auto ruler = mProject->GetRulerPanel(); auto ruler = mProject->GetRulerPanel();
if (ruler) { if (ruler) {
mPartner = std::make_unique<EditCursorOverlay>(mProject, false); mPartner = std::make_shared<EditCursorOverlay>(mProject, false);
ruler->AddOverlay(mPartner.get()); ruler->AddOverlay( mPartner );
} }
} }

View File

@ -11,7 +11,7 @@ Paul Licameli split from TrackPanel.cpp
#ifndef __AUDACITY_EDIT_CURSOR_OVERLAY__ #ifndef __AUDACITY_EDIT_CURSOR_OVERLAY__
#define __AUDACITY_EDIT_CURSOR_OVERLAY__ #define __AUDACITY_EDIT_CURSOR_OVERLAY__
#include "../../MemoryX.h" #include <memory>
#include "../../widgets/Overlay.h" #include "../../widgets/Overlay.h"
class AudacityProject; class AudacityProject;
@ -20,7 +20,6 @@ class EditCursorOverlay final : public Overlay
{ {
public: public:
EditCursorOverlay(AudacityProject *project, bool isMaster = true); EditCursorOverlay(AudacityProject *project, bool isMaster = true);
virtual ~EditCursorOverlay();
private: private:
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override; std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
@ -28,7 +27,7 @@ private:
AudacityProject *mProject; AudacityProject *mProject;
bool mIsMaster; bool mIsMaster;
std::unique_ptr<EditCursorOverlay> mPartner; std::shared_ptr<EditCursorOverlay> mPartner;
int mLastCursorX; int mLastCursorX;
double mCursorTime; double mCursorTime;

View File

@ -115,15 +115,6 @@ PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
this); this);
} }
PlayIndicatorOverlay::~PlayIndicatorOverlay()
{
if (mPartner) {
auto ruler = mProject->GetRulerPanel();
if(ruler)
ruler->RemoveOverlay(mPartner.get());
}
}
void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event) void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
{ {
// Let other listeners get the notification // Let other listeners get the notification
@ -133,8 +124,8 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
if (!mPartner) { if (!mPartner) {
auto ruler = mProject->GetRulerPanel(); auto ruler = mProject->GetRulerPanel();
if (ruler) { if (ruler) {
mPartner = std::make_unique<PlayIndicatorOverlayBase>(mProject, false); mPartner = std::make_shared<PlayIndicatorOverlayBase>(mProject, false);
ruler->AddOverlay(mPartner.get()); ruler->AddOverlay( mPartner );
} }
} }

View File

@ -46,12 +46,11 @@ class PlayIndicatorOverlay final : public PlayIndicatorOverlayBase
{ {
public: public:
PlayIndicatorOverlay(AudacityProject *project); PlayIndicatorOverlay(AudacityProject *project);
virtual ~PlayIndicatorOverlay();
private: private:
void OnTimer(wxCommandEvent &event); void OnTimer(wxCommandEvent &event);
std::unique_ptr<PlayIndicatorOverlayBase> mPartner; std::shared_ptr<PlayIndicatorOverlayBase> mPartner;
}; };
#endif #endif

View File

@ -20,18 +20,11 @@ OverlayPanel::OverlayPanel(wxWindow * parent, wxWindowID id,
: BackedPanel(parent, id, pos, size, style) : BackedPanel(parent, id, pos, size, style)
{} {}
void OverlayPanel::AddOverlay(Overlay *pOverlay) void OverlayPanel::AddOverlay( const std::weak_ptr<Overlay> &pOverlay)
{ {
mOverlays.push_back(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() void OverlayPanel::ClearOverlays()
{ {
mOverlays.clear(); mOverlays.clear();
@ -45,10 +38,14 @@ void OverlayPanel::DrawOverlays(bool repaint_all, wxDC *pDC)
std::vector< Pair > pairs; std::vector< Pair > pairs;
pairs.reserve(n_pairs); pairs.reserve(n_pairs);
// First...
Compress();
// ... then assume pointers are not expired
// Find out the rectangles and outdatedness for each overlay // Find out the rectangles and outdatedness for each overlay
wxSize size(GetBackingDC().GetSize()); wxSize size(GetBackingDC().GetSize());
for (const auto pOverlay : mOverlays) 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. // See what requires redrawing. If repainting, all.
// If not, then whatever is outdated, and whatever will be damaged by // 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(); auto it2 = pairs.begin();
for (auto pOverlay : mOverlays) { for (auto pOverlay : mOverlays) {
if (repaint_all || it2->second) if (repaint_all || it2->second)
pOverlay->Erase(dc, GetBackingDC()); pOverlay.lock()->Erase(dc, GetBackingDC());
++it2; ++it2;
} }
@ -107,11 +104,23 @@ void OverlayPanel::DrawOverlays(bool repaint_all, wxDC *pDC)
// Guarantee a clean state of the dc each pass: // Guarantee a clean state of the dc each pass:
ADCChanger changer{ &dc }; ADCChanger changer{ &dc };
pOverlay->Draw(*this, dc); pOverlay.lock()->Draw(*this, dc);
} }
++it2; ++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<Overlay> &pOverlay ){
return pOverlay.expired(); } );
if ( end != newEnd )
mOverlays.resize( newEnd - begin );
}
BEGIN_EVENT_TABLE(OverlayPanel, BackedPanel) BEGIN_EVENT_TABLE(OverlayPanel, BackedPanel)
END_EVENT_TABLE() END_EVENT_TABLE()

View File

@ -9,6 +9,7 @@
#ifndef __AUDACITY_OVERLAY_PANEL__ #ifndef __AUDACITY_OVERLAY_PANEL__
#define __AUDACITY_OVERLAY_PANEL__ #define __AUDACITY_OVERLAY_PANEL__
#include <memory>
#include <vector> #include <vector>
#include "BackedPanel.h" #include "BackedPanel.h"
@ -22,13 +23,11 @@ public:
// default as for wxPanel: // default as for wxPanel:
long style = wxTAB_TRAVERSAL | wxNO_BORDER); 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 // The sequence in which they were registered is the sequence in
// which they are painted. // which they are painted.
// OverlayPanel is not responsible for their memory management. // OverlayPanel is not responsible for their memory management.
void AddOverlay(Overlay *pOverlay); void AddOverlay( const std::weak_ptr<Overlay> &pOverlay );
// Returns true if the overlay was found
bool RemoveOverlay(Overlay *pOverlay);
void ClearOverlays(); void ClearOverlays();
// Erases and redraws to the client area the overlays that have // Erases and redraws to the client area the overlays that have
@ -41,7 +40,8 @@ public:
void DrawOverlays(bool repaint_all, wxDC *pDC = nullptr); void DrawOverlays(bool repaint_all, wxDC *pDC = nullptr);
private: private:
std::vector<Overlay*> mOverlays; void Compress();
std::vector< std::weak_ptr<Overlay> > mOverlays;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()