mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-01 08:29:27 +02:00
Iterate over the pending tracks for drawing
This commit is contained in:
parent
7d57a17ff4
commit
ce5a67a9e9
@ -2019,25 +2019,6 @@ void AudacityProject::FixScrollbars()
|
||||
GetTrackPanel()->HandleCursorForPresentMouseState(); } );
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> AudacityProject::GetFirstVisible()
|
||||
{
|
||||
std::shared_ptr<Track> pTrack;
|
||||
if (GetTracks()) {
|
||||
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
|
||||
pTrack = Track::Pointer(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pTrack;
|
||||
}
|
||||
|
||||
void AudacityProject::UpdateLayout()
|
||||
{
|
||||
if (!mTrackPanel)
|
||||
|
@ -192,8 +192,6 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame,
|
||||
const ViewInfo &GetViewInfo() const { return mViewInfo; }
|
||||
ViewInfo &GetViewInfo() { return mViewInfo; }
|
||||
|
||||
std::shared_ptr<Track> GetFirstVisible();
|
||||
|
||||
void GetPlayRegion(double* playRegionStart, double *playRegionEnd);
|
||||
bool IsPlayRegionLocked() { return mLockPlayRegion; }
|
||||
|
||||
|
@ -1560,3 +1560,69 @@ std::shared_ptr<Track> TrackList::FindPendingChangedTrack(TrackId id) const
|
||||
return {};
|
||||
return *it;
|
||||
}
|
||||
|
||||
// Make begin iterator
|
||||
PendingTrackIterator::PendingTrackIterator
|
||||
(TrackList *list, const std::shared_ptr<TrackListIterator> &pIter)
|
||||
: mList{ list }
|
||||
, mpIter{ pIter }
|
||||
{
|
||||
auto &pending = mList->FindPendingNewTracks();
|
||||
|
||||
// Assume no invalidation of these iterators happens during the lifetime
|
||||
// of this!
|
||||
mpPendingIt = pending.begin(), mpPendingEnd = pending.end();
|
||||
|
||||
mpTrack = Track::Pointer( mpIter->First() );
|
||||
SubstituteTrack();
|
||||
|
||||
mDoingExtras = !mpTrack;
|
||||
FindExtraTrack();
|
||||
}
|
||||
|
||||
// Make end iterator; the only important thing is to define operators == and
|
||||
// != with other iterators
|
||||
PendingTrackIterator::PendingTrackIterator()
|
||||
: mList{ nullptr }
|
||||
, mpIter{ }
|
||||
{
|
||||
mDoingExtras = true;
|
||||
}
|
||||
|
||||
PendingTrackIterator &PendingTrackIterator::operator++()
|
||||
{
|
||||
if (!mDoingExtras) {
|
||||
Track *next = mpIter->Next();
|
||||
if (next) {
|
||||
mpTrack = Track::Pointer( next );
|
||||
SubstituteTrack();
|
||||
}
|
||||
else
|
||||
mDoingExtras = true;
|
||||
}
|
||||
FindExtraTrack();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void PendingTrackIterator::SubstituteTrack()
|
||||
{
|
||||
if (mpTrack) {
|
||||
auto sub = mList->FindPendingChangedTrack( mpTrack->GetId() );
|
||||
if (sub)
|
||||
mpTrack = sub;
|
||||
}
|
||||
}
|
||||
|
||||
void PendingTrackIterator::FindExtraTrack()
|
||||
{
|
||||
if (mDoingExtras) {
|
||||
auto pCondIter = dynamic_cast<TrackListCondIterator*>(mpIter.get());
|
||||
while(
|
||||
mpTrack.reset(),
|
||||
mpPendingIt != mpPendingEnd &&
|
||||
(mpTrack = *mpPendingIt++,
|
||||
pCondIter &&
|
||||
!pCondIter->Condition(mpTrack.get())))
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
47
src/Track.h
47
src/Track.h
@ -501,7 +501,6 @@ class AUDACITY_DLL_API TrackListCondIterator /* not final */ : public TrackListI
|
||||
Track *Prev(bool skiplinked = false) override;
|
||||
Track *Last(bool skiplinked = false) override;
|
||||
|
||||
protected:
|
||||
// NEW virtual
|
||||
virtual bool Condition(Track *t) = 0;
|
||||
};
|
||||
@ -579,6 +578,52 @@ class AUDACITY_DLL_API SyncLockedTracksIterator final : public TrackListIterator
|
||||
};
|
||||
|
||||
|
||||
// Iterates over the tracks, substituting any pending replacement tracks
|
||||
// for the actual, and always appending the added tracks, but then
|
||||
// also filtering all tracks according to the criterion in the
|
||||
// TrackListIterator given to the constructor.
|
||||
// Iterator may be invalidated if the project's TrackList is mutated during
|
||||
// the iterator's lifetime (though not in case of RegisterPendingChangedTrack()).
|
||||
class PendingTrackIterator {
|
||||
public:
|
||||
// Construct a begin iterator
|
||||
PendingTrackIterator
|
||||
(TrackList *list,
|
||||
// Track iterator that can include a condition
|
||||
const std::shared_ptr<TrackListIterator> &pIter);
|
||||
|
||||
// Construct an end iterator
|
||||
PendingTrackIterator();
|
||||
|
||||
PendingTrackIterator &operator++();
|
||||
|
||||
const std::shared_ptr<Track> &operator* () const { return mpTrack; }
|
||||
|
||||
bool operator == (const PendingTrackIterator &other) const
|
||||
// Test for identity of the tracks pointed to should be a sufficient
|
||||
// test of iterator equality, assuming no track is ever duplicated in the
|
||||
// sequence, which should be the case, and that an end iterator stores a
|
||||
// null pointer.
|
||||
{ return mpTrack == other.mpTrack; }
|
||||
|
||||
bool operator != (const PendingTrackIterator &other) const
|
||||
{ return !(*this == other); }
|
||||
|
||||
protected:
|
||||
|
||||
std::shared_ptr<Track> mpTrack;
|
||||
|
||||
private:
|
||||
void SubstituteTrack();
|
||||
void FindExtraTrack();
|
||||
|
||||
TrackList *mList;
|
||||
std::shared_ptr<TrackListIterator> mpIter;
|
||||
|
||||
bool mDoingExtras{ false };
|
||||
ListOfTracks::const_iterator mpPendingIt, mpPendingEnd;
|
||||
};
|
||||
|
||||
/** \brief TrackList is a flat linked list of tracks supporting Add, Remove,
|
||||
* Clear, and Contains, plus serialization of the list of tracks.
|
||||
*/
|
||||
|
@ -339,8 +339,7 @@ void TrackArtist::SetMargins(int left, int top, int right, int bottom)
|
||||
}
|
||||
|
||||
void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
|
||||
TrackList * tracks,
|
||||
Track * start,
|
||||
const std::function< Range() > &range,
|
||||
const wxRegion & reg,
|
||||
const wxRect & rect,
|
||||
const wxRect & clip,
|
||||
@ -352,11 +351,10 @@ void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
|
||||
{
|
||||
wxRect trackRect = rect;
|
||||
wxRect stereoTrackRect;
|
||||
TrackListIterator iter(tracks);
|
||||
Track *t;
|
||||
|
||||
bool hasSolo = false;
|
||||
for (t = iter.First(); t; t = iter.Next()) {
|
||||
for (auto &track : range()) {
|
||||
auto t = track.get();
|
||||
auto pt = dynamic_cast<const PlayableTrack *>(t);
|
||||
if (pt && pt->GetSolo()) {
|
||||
hasSolo = true;
|
||||
@ -379,8 +377,8 @@ void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
|
||||
|
||||
gPrefs->Read(wxT("/GUI/ShowTrackNameInWaveform"), &mbShowTrackNameInWaveform, false);
|
||||
|
||||
t = iter.StartWith(start);
|
||||
while (t) {
|
||||
for (auto &track : range()) {
|
||||
auto t = track.get();
|
||||
trackRect.y = t->GetY() - zoomInfo.vpos;
|
||||
trackRect.height = t->GetHeight();
|
||||
|
||||
@ -430,8 +428,6 @@ void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
|
||||
selectedRegion, zoomInfo,
|
||||
drawEnvelope, bigPoints, drawSliders, hasSolo);
|
||||
}
|
||||
|
||||
t = iter.Next();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "Experimental.h"
|
||||
#include "audacity/Types.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class wxDC;
|
||||
class wxRect;
|
||||
class wxHashTable;
|
||||
@ -36,10 +38,10 @@ class WaveClip;
|
||||
class NoteTrack;
|
||||
class LabelTrack;
|
||||
class TimeTrack;
|
||||
class TrackList;
|
||||
class Ruler;
|
||||
class SelectedRegion;
|
||||
class ZoomInfo;
|
||||
class PendingTrackIterator;
|
||||
|
||||
struct TrackPanelDrawingContext;
|
||||
|
||||
@ -54,8 +56,10 @@ class AUDACITY_DLL_API TrackArtist {
|
||||
~TrackArtist();
|
||||
|
||||
void SetColours(int iColorIndex);
|
||||
|
||||
using Range = IteratorRange< PendingTrackIterator >;
|
||||
void DrawTracks(TrackPanelDrawingContext &context,
|
||||
TrackList *tracks, Track *start,
|
||||
const std::function< Range() > &range,
|
||||
const wxRegion & reg,
|
||||
const wxRect & rect, const wxRect & clip,
|
||||
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo,
|
||||
|
@ -1846,8 +1846,17 @@ void TrackPanel::DrawTracks(wxDC * dc)
|
||||
TrackPanelDrawingContext context{ *dc, Target(), mLastMouseState };
|
||||
|
||||
// The track artist actually draws the stuff inside each track
|
||||
auto first = GetProject()->GetFirstVisible();
|
||||
mTrackArtist->DrawTracks(context, GetTracks(), first.get(),
|
||||
auto project = GetProject();
|
||||
// Make a function that reproduces the range, because, quirkily, the range
|
||||
// can't be copied and iterated twice. Fix that later.
|
||||
auto range = [&]{
|
||||
return make_iterator_range(
|
||||
PendingTrackIterator{ project->GetTracks(),
|
||||
std::make_shared<VisibleTrackIterator>( project ) },
|
||||
PendingTrackIterator{}
|
||||
);
|
||||
};
|
||||
mTrackArtist->DrawTracks(context, range,
|
||||
region, tracksRect, clip,
|
||||
mViewInfo->selectedRegion, *mViewInfo,
|
||||
envelopeFlag, bigPointsFlag, sliderFlag);
|
||||
@ -1869,8 +1878,13 @@ void TrackPanel::DrawEverythingElse(TrackPanelDrawingContext &context,
|
||||
wxRect trackRect = clip;
|
||||
trackRect.height = 0; // for drawing background in no tracks case.
|
||||
|
||||
VisibleTrackIterator iter(GetProject());
|
||||
for (Track *t = iter.First(); t; t = iter.Next()) {
|
||||
auto project = GetProject();
|
||||
PendingTrackIterator
|
||||
begin{ project->GetTracks(),
|
||||
std::make_shared<VisibleTrackIterator>( project ) },
|
||||
end;
|
||||
for (const auto &track : make_iterator_range(begin, end)) {
|
||||
auto t = track.get();
|
||||
trackRect.y = t->GetY() - mViewInfo->vpos;
|
||||
trackRect.height = t->GetHeight();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user