1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-18 17:47:41 +02:00

Fix crashes in repainting, and update first visible track correctly

This commit is contained in:
Paul Licameli 2017-06-26 13:40:19 -04:00
parent 30ec8a1c90
commit 2806b509e2
7 changed files with 55 additions and 47 deletions

View File

@ -944,8 +944,16 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
mLastSavedTracks = NULL; mLastSavedTracks = NULL;
// Register for tracklist updates // Register for tracklist updates
mTracks->Connect(EVT_TRACKLIST_PERMUTED,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Connect(EVT_TRACKLIST_DELETION, mTracks->Connect(EVT_TRACKLIST_DELETION,
wxCommandEventHandler(AudacityProject::OnTrackListDeletion), wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Connect(EVT_TRACKLIST_RESIZING,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL, NULL,
this); this);
@ -1974,9 +1982,8 @@ void AudacityProject::FixScrollbars()
rescroll = false; rescroll = false;
} }
if (lastv != mViewInfo.vpos) { if (lastv != mViewInfo.vpos)
UpdateFirstVisible(); InvalidateFirstVisible();
}
// wxScrollbar only supports int values but we need a greater range, so // wxScrollbar only supports int values but we need a greater range, so
// we scale the scrollbar coordinates on demand. We only do this if we // we scale the scrollbar coordinates on demand. We only do this if we
@ -2020,51 +2027,30 @@ void AudacityProject::FixScrollbars()
} }
} }
Track *AudacityProject::GetFirstVisible() std::shared_ptr<Track> AudacityProject::GetFirstVisible()
{ {
if (!mViewInfo.track && GetTracks()) { auto pTrack = mViewInfo.track.lock();
if (!pTrack && GetTracks()) {
// Recompute on demand and memo-ize
TrackListIterator iter(GetTracks()); TrackListIterator iter(GetTracks());
for (Track *t = iter.First(); t; t = iter.Next()) { for (Track *t = iter.First(); t; t = iter.Next()) {
int y = t->GetY(); int y = t->GetY();
int h = t->GetHeight(); int h = t->GetHeight();
if (y + h - 1 >= mViewInfo.vpos) { if (y + h - 1 >= mViewInfo.vpos) {
// At least the bottom row of pixels is not scrolled away above // At least the bottom row of pixels is not scrolled away above
mViewInfo.track = t; pTrack = Track::Pointer(t);
break; break;
} }
} }
mViewInfo.track = pTrack;
} }
return mViewInfo.track; return pTrack;
} }
void AudacityProject::UpdateFirstVisible() void AudacityProject::InvalidateFirstVisible()
{ {
if (!mViewInfo.track || !GetTracks()) { mViewInfo.track.reset();
return;
}
Track *t = mViewInfo.track;
mViewInfo.track = NULL;
if (t->GetY() >= mViewInfo.vpos) {
while (t && t->GetY() >= mViewInfo.vpos) {
t = mTracks->GetPrev(t);
}
}
while (t) {
int y = t->GetY();
int h = t->GetHeight();
if (y + h - 1 >= mViewInfo.vpos) {
// At least the bottom row of pixels is not scrolled away above
mViewInfo.track = t;
return;
}
t = mTracks->GetNext(t);
}
return;
} }
void AudacityProject::UpdateLayout() void AudacityProject::UpdateLayout()
@ -2222,9 +2208,9 @@ void AudacityProject::OnToolBarUpdate(wxCommandEvent & event)
} }
// The projects tracklist has been updated // The projects tracklist has been updated
void AudacityProject::OnTrackListDeletion(wxCommandEvent & event) void AudacityProject::OnTrackListUpdate(wxCommandEvent & event)
{ {
mViewInfo.track = NULL; InvalidateFirstVisible();
event.Skip(); event.Skip();
} }
@ -2275,9 +2261,8 @@ void AudacityProject::DoScroll()
int lastv = mViewInfo.vpos; int lastv = mViewInfo.vpos;
mViewInfo.vpos = mVsbar->GetThumbPosition() * mViewInfo.scrollStep; mViewInfo.vpos = mVsbar->GetThumbPosition() * mViewInfo.scrollStep;
if (lastv != mViewInfo.vpos) { if (lastv != mViewInfo.vpos)
UpdateFirstVisible(); InvalidateFirstVisible();
}
//mchinen: do not always set this project to be the active one. //mchinen: do not always set this project to be the active one.
//a project may autoscroll while playing in the background //a project may autoscroll while playing in the background
@ -2692,8 +2677,16 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
mImportXMLTagHandler.reset(); mImportXMLTagHandler.reset();
// Unregister for tracklist updates // Unregister for tracklist updates
mTracks->Disconnect(EVT_TRACKLIST_PERMUTED,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Disconnect(EVT_TRACKLIST_DELETION, mTracks->Disconnect(EVT_TRACKLIST_DELETION,
wxCommandEventHandler(AudacityProject::OnTrackListDeletion), wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Disconnect(EVT_TRACKLIST_RESIZING,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL, NULL,
this); this);
@ -3529,7 +3522,7 @@ bool AudacityProject::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
if (longVpos != 0) { if (longVpos != 0) {
// PRL: It seems this must happen after SetSnapTo // PRL: It seems this must happen after SetSnapTo
mViewInfo.track = NULL; mViewInfo.track.reset();
mViewInfo.vpos = longVpos; mViewInfo.vpos = longVpos;
mbInitializingScrollbar = true; mbInitializingScrollbar = true;
} }

View File

@ -191,8 +191,8 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame,
const ViewInfo &GetViewInfo() const { return mViewInfo; } const ViewInfo &GetViewInfo() const { return mViewInfo; }
ViewInfo &GetViewInfo() { return mViewInfo; } ViewInfo &GetViewInfo() { return mViewInfo; }
Track *GetFirstVisible(); std::shared_ptr<Track> GetFirstVisible();
void UpdateFirstVisible(); void InvalidateFirstVisible();
void GetPlayRegion(double* playRegionStart, double *playRegionEnd); void GetPlayRegion(double* playRegionStart, double *playRegionEnd);
bool IsPlayRegionLocked() { return mLockPlayRegion; } bool IsPlayRegionLocked() { return mLockPlayRegion; }
@ -355,7 +355,7 @@ public:
void OnOpenAudioFile(wxCommandEvent & event); void OnOpenAudioFile(wxCommandEvent & event);
void OnODTaskUpdate(wxCommandEvent & event); void OnODTaskUpdate(wxCommandEvent & event);
void OnODTaskComplete(wxCommandEvent & event); void OnODTaskComplete(wxCommandEvent & event);
void OnTrackListDeletion(wxCommandEvent & event); void OnTrackListUpdate(wxCommandEvent & event);
void HandleResize(); void HandleResize();
void UpdateLayout(); void UpdateLayout();

View File

@ -741,6 +741,7 @@ Track *SyncLockedTracksIterator::Last(bool skiplinked)
// is managing. Any other classes that may be interested in get these updates // is managing. Any other classes that may be interested in get these updates
// should use TrackList::Connect() and TrackList::Disconnect(). // should use TrackList::Connect() and TrackList::Disconnect().
// //
DEFINE_EVENT_TYPE(EVT_TRACKLIST_PERMUTED);
DEFINE_EVENT_TYPE(EVT_TRACKLIST_RESIZING); DEFINE_EVENT_TYPE(EVT_TRACKLIST_RESIZING);
DEFINE_EVENT_TYPE(EVT_TRACKLIST_DELETION); DEFINE_EVENT_TYPE(EVT_TRACKLIST_DELETION);
@ -856,6 +857,13 @@ void TrackList::RecalcPositions(TrackNodePointer node)
#endif // EXPERIMENTAL_OUTPUT_DISPLAY #endif // EXPERIMENTAL_OUTPUT_DISPLAY
} }
void TrackList::PermutationEvent()
{
auto e = std::make_unique<wxCommandEvent>(EVT_TRACKLIST_PERMUTED);
// wxWidgets will own the event object
QueueEvent(e.release());
}
void TrackList::DeletionEvent() void TrackList::DeletionEvent()
{ {
auto e = std::make_unique<wxCommandEvent>(EVT_TRACKLIST_DELETION); auto e = std::make_unique<wxCommandEvent>(EVT_TRACKLIST_DELETION);
@ -882,6 +890,7 @@ void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
} }
auto n = begin(); auto n = begin();
RecalcPositions(n); RecalcPositions(n);
PermutationEvent();
} }
template<typename TrackKind> template<typename TrackKind>
@ -1152,6 +1161,7 @@ void TrackList::SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
// Now correct the Index in the tracks, and other things // Now correct the Index in the tracks, and other things
RecalcPositions(s1); RecalcPositions(s1);
PermutationEvent();
} }
bool TrackList::MoveUp(Track * t) bool TrackList::MoveUp(Track * t)

View File

@ -483,6 +483,9 @@ class AUDACITY_DLL_API SyncLockedTracksIterator final : public TrackListIterator
* Clear, and Contains, plus serialization of the list of tracks. * Clear, and Contains, plus serialization of the list of tracks.
*/ */
// Posted when tracks are reordered but otherwise unchanged.
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_PERMUTED, -1);
// Posted when some track was added or changed its height. // Posted when some track was added or changed its height.
// The wxCommandEvent::GetClientData() method can be used to retrieve it. // The wxCommandEvent::GetClientData() method can be used to retrieve it.
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_RESIZING, -1); DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_RESIZING, -1);
@ -607,6 +610,7 @@ private:
void DoAssign(const TrackList &that); void DoAssign(const TrackList &that);
void RecalcPositions(TrackNodePointer node); void RecalcPositions(TrackNodePointer node);
void PermutationEvent();
void DeletionEvent(); void DeletionEvent();
void ResizingEvent(TrackNodePointer node); void ResizingEvent(TrackNodePointer node);

View File

@ -1636,7 +1636,8 @@ void TrackPanel::DrawTracks(wxDC * dc)
bool sliderFlag = bMultiToolDown; bool sliderFlag = bMultiToolDown;
// The track artist actually draws the stuff inside each track // The track artist actually draws the stuff inside each track
mTrackArtist->DrawTracks(GetTracks(), GetProject()->GetFirstVisible(), auto first = GetProject()->GetFirstVisible();
mTrackArtist->DrawTracks(GetTracks(), first.get(),
*dc, region, tracksRect, clip, *dc, region, tracksRect, clip,
mViewInfo->selectedRegion, *mViewInfo, mViewInfo->selectedRegion, *mViewInfo,
envelopeFlag, bigPointsFlag, sliderFlag); envelopeFlag, bigPointsFlag, sliderFlag);

View File

@ -130,7 +130,6 @@ void ZoomInfo::FindIntervals
ViewInfo::ViewInfo(double start, double screenDuration, double pixelsPerSecond) ViewInfo::ViewInfo(double start, double screenDuration, double pixelsPerSecond)
: ZoomInfo(start, pixelsPerSecond) : ZoomInfo(start, pixelsPerSecond)
, selectedRegion() , selectedRegion()
, track(NULL)
, total(screenDuration) , total(screenDuration)
, sbarH(0) , sbarH(0)
, sbarScreen(1) , sbarScreen(1)

View File

@ -14,6 +14,7 @@
#include <vector> #include <vector>
#include <wx/event.h> #include <wx/event.h>
#include "SelectedRegion.h" #include "SelectedRegion.h"
#include "MemoryX.h"
class Track; class Track;
@ -157,7 +158,7 @@ public:
// Scroll info // Scroll info
Track *track; // first visible track std::weak_ptr<Track> track; // first visible track
double total; // total width in secs double total; // total width in secs
// Current horizontal scroll bar positions, in pixels // Current horizontal scroll bar positions, in pixels