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;
// Register for tracklist updates
mTracks->Connect(EVT_TRACKLIST_PERMUTED,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Connect(EVT_TRACKLIST_DELETION,
wxCommandEventHandler(AudacityProject::OnTrackListDeletion),
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Connect(EVT_TRACKLIST_RESIZING,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
@ -1974,9 +1982,8 @@ void AudacityProject::FixScrollbars()
rescroll = false;
}
if (lastv != mViewInfo.vpos) {
UpdateFirstVisible();
}
if (lastv != mViewInfo.vpos)
InvalidateFirstVisible();
// 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
@ -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());
for (Track *t = iter.First(); t; t = iter.Next()) {
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;
pTrack = Track::Pointer(t);
break;
}
}
mViewInfo.track = pTrack;
}
return mViewInfo.track;
return pTrack;
}
void AudacityProject::UpdateFirstVisible()
void AudacityProject::InvalidateFirstVisible()
{
if (!mViewInfo.track || !GetTracks()) {
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;
mViewInfo.track.reset();
}
void AudacityProject::UpdateLayout()
@ -2222,9 +2208,9 @@ void AudacityProject::OnToolBarUpdate(wxCommandEvent & event)
}
// The projects tracklist has been updated
void AudacityProject::OnTrackListDeletion(wxCommandEvent & event)
void AudacityProject::OnTrackListUpdate(wxCommandEvent & event)
{
mViewInfo.track = NULL;
InvalidateFirstVisible();
event.Skip();
}
@ -2275,9 +2261,8 @@ void AudacityProject::DoScroll()
int lastv = mViewInfo.vpos;
mViewInfo.vpos = mVsbar->GetThumbPosition() * mViewInfo.scrollStep;
if (lastv != mViewInfo.vpos) {
UpdateFirstVisible();
}
if (lastv != mViewInfo.vpos)
InvalidateFirstVisible();
//mchinen: do not always set this project to be the active one.
//a project may autoscroll while playing in the background
@ -2692,8 +2677,16 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
mImportXMLTagHandler.reset();
// Unregister for tracklist updates
mTracks->Disconnect(EVT_TRACKLIST_PERMUTED,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Disconnect(EVT_TRACKLIST_DELETION,
wxCommandEventHandler(AudacityProject::OnTrackListDeletion),
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
mTracks->Disconnect(EVT_TRACKLIST_RESIZING,
wxCommandEventHandler(AudacityProject::OnTrackListUpdate),
NULL,
this);
@ -3529,7 +3522,7 @@ bool AudacityProject::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
if (longVpos != 0) {
// PRL: It seems this must happen after SetSnapTo
mViewInfo.track = NULL;
mViewInfo.track.reset();
mViewInfo.vpos = longVpos;
mbInitializingScrollbar = true;
}

View File

@ -191,8 +191,8 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame,
const ViewInfo &GetViewInfo() const { return mViewInfo; }
ViewInfo &GetViewInfo() { return mViewInfo; }
Track *GetFirstVisible();
void UpdateFirstVisible();
std::shared_ptr<Track> GetFirstVisible();
void InvalidateFirstVisible();
void GetPlayRegion(double* playRegionStart, double *playRegionEnd);
bool IsPlayRegionLocked() { return mLockPlayRegion; }
@ -355,7 +355,7 @@ public:
void OnOpenAudioFile(wxCommandEvent & event);
void OnODTaskUpdate(wxCommandEvent & event);
void OnODTaskComplete(wxCommandEvent & event);
void OnTrackListDeletion(wxCommandEvent & event);
void OnTrackListUpdate(wxCommandEvent & event);
void HandleResize();
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
// should use TrackList::Connect() and TrackList::Disconnect().
//
DEFINE_EVENT_TYPE(EVT_TRACKLIST_PERMUTED);
DEFINE_EVENT_TYPE(EVT_TRACKLIST_RESIZING);
DEFINE_EVENT_TYPE(EVT_TRACKLIST_DELETION);
@ -856,6 +857,13 @@ void TrackList::RecalcPositions(TrackNodePointer node)
#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()
{
auto e = std::make_unique<wxCommandEvent>(EVT_TRACKLIST_DELETION);
@ -882,6 +890,7 @@ void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
}
auto n = begin();
RecalcPositions(n);
PermutationEvent();
}
template<typename TrackKind>
@ -1152,6 +1161,7 @@ void TrackList::SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
// Now correct the Index in the tracks, and other things
RecalcPositions(s1);
PermutationEvent();
}
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.
*/
// 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.
// The wxCommandEvent::GetClientData() method can be used to retrieve it.
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_RESIZING, -1);
@ -607,6 +610,7 @@ private:
void DoAssign(const TrackList &that);
void RecalcPositions(TrackNodePointer node);
void PermutationEvent();
void DeletionEvent();
void ResizingEvent(TrackNodePointer node);

View File

@ -1636,7 +1636,8 @@ void TrackPanel::DrawTracks(wxDC * dc)
bool sliderFlag = bMultiToolDown;
// 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,
mViewInfo->selectedRegion, *mViewInfo,
envelopeFlag, bigPointsFlag, sliderFlag);

View File

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

View File

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