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:
parent
30ec8a1c90
commit
2806b509e2
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user