1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-21 23:00:06 +02:00

Some reimplementation of track iterators and GetLink() ...

... avoiding direct usage of the inherited end() and of the increment and
decrement of the std::list iterators
This commit is contained in:
Paul Licameli 2018-01-12 20:17:30 -05:00
parent 9dd5b521ea
commit 242e9a5668
2 changed files with 123 additions and 110 deletions

View File

@ -209,20 +209,16 @@ Track *Track::GetLink() const
if (!pList->isNull(mNode)) { if (!pList->isNull(mNode)) {
if (mLinked) { if (mLinked) {
auto next = mNode; auto next = pList->getNext( mNode );
++next; if ( !pList->isNull( next ) )
if (!pList->isNull(next)) {
return next->get(); return next->get();
}
} }
if (pList->hasPrev(mNode)) { auto prev = pList->getPrev( mNode );
auto prev = mNode; if ( !pList->isNull( prev ) ) {
--prev;
auto track = prev->get(); auto track = prev->get();
if (track && track->GetLinked()) { if (track && track->GetLinked())
return track; return track;
}
} }
} }
@ -332,7 +328,7 @@ TrackListIterator::TrackListIterator(TrackList * val)
, cur{} , cur{}
{ {
if (l) if (l)
cur = l->ListOfTracks::begin(); cur = l->getBegin();
} }
Track *TrackListIterator::StartWith(Track * val) Track *TrackListIterator::StartWith(Track * val)
@ -362,13 +358,13 @@ Track *TrackListIterator::First(TrackList * val)
return NULL; return NULL;
} }
cur = l->ListOfTracks::begin(); cur = l->getBegin();
if (!l->isNull(cur)) { if (!l->isNull(cur)) {
return cur->get(); return cur->get();
} }
return NULL; return nullptr;
} }
Track *TrackListIterator::Last(bool skiplinked) Track *TrackListIterator::Last(bool skiplinked)
@ -377,18 +373,19 @@ Track *TrackListIterator::Last(bool skiplinked)
return NULL; return NULL;
} }
cur = l->ListOfTracks::end(); cur = l->getPrev( l->getEnd() );
if (l->hasPrev(cur)) if ( l->isNull( cur ) )
--cur; return nullptr;
else
return NULL;
// With skiplinked set, we won't return the second channel of a linked pair // With skiplinked set, we won't return the second channel of a linked pair
if (skiplinked && if (skiplinked) {
l->hasPrev(cur) && auto prev = l->getPrev( cur );
!(*cur)->GetLinked() && if ( !l->isNull( prev ) &&
(*cur)->GetLink()) !(*cur)->GetLinked() &&
--cur; (*cur)->GetLink()
)
cur = prev;
}
return cur->get(); return cur->get();
} }
@ -403,27 +400,24 @@ Track *TrackListIterator::Next(bool skipLinked)
return nullptr; return nullptr;
if (skipLinked && if (skipLinked &&
(*cur)->GetLinked()) { (*cur)->GetLinked())
++cur; cur = l->getNext( cur );
}
#ifdef DEBUG_TLI // if we are debugging this bit #ifdef DEBUG_TLI // if we are debugging this bit
wxASSERT_MSG((!cur || (*l).Contains((*cur).t)), wxT("cur invalid after skipping linked tracks.")); // check that cur is in the list wxASSERT_MSG((!cur || (*l).Contains((*cur).t)), wxT("cur invalid after skipping linked tracks.")); // check that cur is in the list
#endif #endif
if (!l->isNull(cur)) { if (!l->isNull(cur))
++cur; cur = l->getNext( cur );
}
#ifdef DEBUG_TLI // if we are debugging this bit #ifdef DEBUG_TLI // if we are debugging this bit
wxASSERT_MSG((!cur || (*l).Contains((*cur).t)), wxT("cur invalid after moving to next track.")); // check that cur is in the list if it is not null wxASSERT_MSG((!cur || (*l).Contains((*cur).t)), wxT("cur invalid after moving to next track.")); // check that cur is in the list if it is not null
#endif #endif
if (!l->isNull(cur)) { if (!l->isNull(cur))
return cur->get(); return cur->get();
}
return NULL; return nullptr;
} }
Track *TrackListIterator::Prev(bool skiplinked) Track *TrackListIterator::Prev(bool skiplinked)
@ -431,17 +425,13 @@ Track *TrackListIterator::Prev(bool skiplinked)
if (!l || l->isNull(cur)) if (!l || l->isNull(cur))
return nullptr; return nullptr;
if (!l->hasPrev(cur)) { cur = l->getPrev( cur );
l->setNull(cur); if ( l->isNull( cur ) )
return nullptr; return nullptr;
}
--cur; if ( skiplinked ) {
auto prev = l->getPrev( cur );
if (skiplinked && l->hasPrev(cur)) { if( !l->isNull( prev ) && (*prev)->GetLinked() )
auto prev = cur;
--prev;
if ((*prev)->GetLinked())
cur = prev; cur = prev;
} }
@ -458,20 +448,19 @@ Track *TrackListIterator::operator *() const
Track *TrackListIterator::RemoveCurrent() Track *TrackListIterator::RemoveCurrent()
{ {
if (!l || l->isNull(cur)) if ( !l || l->isNull( cur ) )
return nullptr; return nullptr;
cur = l->Remove(cur->get()); cur = l->Remove( cur->get() );
#ifdef DEBUG_TLI // if we are debugging this bit #ifdef DEBUG_TLI // if we are debugging this bit
wxASSERT_MSG((!cur || (*l).Contains((*cur).t)), wxT("cur invalid after deletion of track.")); // check that cur is in the list wxASSERT_MSG((!cur || (*l).Contains((*cur).t)), wxT("cur invalid after deletion of track.")); // check that cur is in the list
#endif #endif
if (!l->isNull(cur)) { if ( !l->isNull( cur ) )
return cur->get(); return cur->get();
}
return NULL; return nullptr;
} }
bool TrackListIterator::operator == (const TrackListIterator &other) const bool TrackListIterator::operator == (const TrackListIterator &other) const
@ -494,7 +483,7 @@ Track *TrackListCondIterator::StartWith(Track *val)
Track *t = TrackListIterator::StartWith(val); Track *t = TrackListIterator::StartWith(val);
if (t && !this->Condition(t)) if (t && !this->Condition(t))
return NULL; return nullptr;
return t; return t;
} }
@ -655,11 +644,11 @@ Track *SyncLockedTracksIterator::Next(bool skiplinked)
Track *t = TrackListIterator::Next(skiplinked); Track *t = TrackListIterator::Next(skiplinked);
if (!t) if (!t)
return NULL; return nullptr;
if ( ! IsGoodNextTrack(t) ) { if ( ! IsGoodNextTrack(t) ) {
l->setNull(cur); cur = l->getEnd();
return NULL; return nullptr;
} }
mInLabelSection = ( t->GetKind() == Track::Label ); mInLabelSection = ( t->GetKind() == Track::Label );
@ -677,19 +666,19 @@ Track *SyncLockedTracksIterator::Prev(bool skiplinked)
// Beginning of tracks // Beginning of tracks
if (!t) if (!t)
return NULL; return nullptr;
const bool isLabel = ( t->GetKind() == Track::Label ); const bool isLabel = ( t->GetKind() == Track::Label );
const bool isSyncLockable = IsSyncLockableNonLabelTrack( t ); const bool isSyncLockable = IsSyncLockableNonLabelTrack( t );
if ( !( isLabel || isSyncLockable ) ) { if ( !( isLabel || isSyncLockable ) ) {
l->setNull(cur); cur = l->getEnd();
return NULL; return nullptr;
} }
if ( !mInLabelSection && isLabel ) { if ( !mInLabelSection && isLabel ) {
l->setNull(cur); cur = l->getEnd();
return NULL; return nullptr;
} }
mInLabelSection = isLabel; mInLabelSection = isLabel;
@ -699,8 +688,8 @@ Track *SyncLockedTracksIterator::Prev(bool skiplinked)
Track *SyncLockedTracksIterator::Last(bool skiplinked) Track *SyncLockedTracksIterator::Last(bool skiplinked)
{ {
if (!l || l->isNull(cur)) if ( !l || l->isNull( cur ) )
return NULL; return nullptr;
Track *t = cur->get(); Track *t = cur->get();
@ -780,16 +769,15 @@ TrackList::~TrackList()
void TrackList::RecalcPositions(TrackNodePointer node) void TrackList::RecalcPositions(TrackNodePointer node)
{ {
if (isNull(node)) { if ( isNull( node ) )
return; return;
}
Track *t; Track *t;
int i = 0; int i = 0;
int y = 0; int y = 0;
if (hasPrev(node)) { auto prev = getPrev( node );
auto prev = node; if ( !isNull( prev ) ) {
--prev;
t = prev->get(); t = prev->get();
i = t->GetIndex() + 1; i = t->GetIndex() + 1;
y = t->GetY() + t->GetHeight(); y = t->GetY() + t->GetHeight();
@ -834,7 +822,7 @@ void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
Track *pTrack = track.get(); Track *pTrack = track.get();
pTrack->SetOwner(mSelf, insert(ListOfTracks::end(), std::move(track))); pTrack->SetOwner(mSelf, insert(ListOfTracks::end(), std::move(track)));
} }
auto n = ListOfTracks::begin(); auto n = getBegin();
RecalcPositions(n); RecalcPositions(n);
PermutationEvent(); PermutationEvent();
} }
@ -844,8 +832,9 @@ Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
{ {
Track *pTrack; Track *pTrack;
push_back(ListOfTracks::value_type(pTrack = t.release())); push_back(ListOfTracks::value_type(pTrack = t.release()));
auto n = ListOfTracks::end();
--n; auto n = getPrev( getEnd() );
pTrack->SetOwner(mSelf, n); pTrack->SetOwner(mSelf, n);
RecalcPositions(n); RecalcPositions(n);
ResizingEvent(n); ResizingEvent(n);
@ -866,7 +855,7 @@ Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
{ {
Track *pTrack; Track *pTrack;
push_front(ListOfTracks::value_type(pTrack = t.release())); push_front(ListOfTracks::value_type(pTrack = t.release()));
auto n = ListOfTracks::begin(); auto n = getBegin();
pTrack->SetOwner(mSelf, n); pTrack->SetOwner(mSelf, n);
RecalcPositions(n); RecalcPositions(n);
ResizingEvent(n); ResizingEvent(n);
@ -880,8 +869,9 @@ template<typename TrackKind>
Track *TrackList::Add(std::shared_ptr<TrackKind> &&t) Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
{ {
push_back(t); push_back(t);
auto n = ListOfTracks::end();
--n; auto n = getPrev( getEnd() );
t->SetOwner(mSelf, n); t->SetOwner(mSelf, n);
RecalcPositions(n); RecalcPositions(n);
ResizingEvent(n); ResizingEvent(n);
@ -915,18 +905,18 @@ auto TrackList::Replace(Track * t, ListOfTracks::value_type &&with) ->
TrackNodePointer TrackList::Remove(Track *t) TrackNodePointer TrackList::Remove(Track *t)
{ {
auto result = ListOfTracks::end(); auto result = getEnd();
if (t) { if (t) {
auto node = t->GetNode(); auto node = t->GetNode();
t->SetOwner({}, {}); t->SetOwner({}, {});
if (!isNull(node)) { if ( !isNull( node ) ) {
ListOfTracks::value_type holder = std::move( *node ); ListOfTracks::value_type holder = std::move( *node );
result = erase(node); result = getNext( node );
if (!isNull(result)) { erase(node);
if ( !isNull( result ) )
RecalcPositions(result); RecalcPositions(result);
}
DeletionEvent(); DeletionEvent();
} }
@ -951,19 +941,17 @@ void TrackList::Select(Track * t, bool selected /* = true */ )
{ {
if (t) { if (t) {
const auto node = t->GetNode(); const auto node = t->GetNode();
if (!isNull(node)) { if ( !isNull( node ) ) {
t->SetSelected(selected); t->SetSelected( selected );
auto next = node; if ( t->GetLinked() ) {
++next; auto next = getNext( node );
if (t->GetLinked() && !isNull(next)) { if ( !isNull( next ) )
(*next)->SetSelected(selected); (*next)->SetSelected( selected );
} }
else if (hasPrev(node)) { else {
auto prev = node; auto prev = getPrev( node );
--prev; if ( !isNull( prev ) && (*prev)->GetLinked() )
if ((*prev)->GetLinked()) { (*prev)->SetSelected( selected );
(*prev)->SetSelected(selected);
}
} }
} }
} }
@ -974,50 +962,55 @@ Track *TrackList::GetNext(Track * t, bool linked) const
{ {
if (t) { if (t) {
auto node = t->GetNode(); auto node = t->GetNode();
if (!isNull(node)) { if ( !isNull( node ) ) {
if (linked && t->GetLinked()) { if ( linked && t->GetLinked() )
++node; node = getNext( node );
}
if (!isNull(node)) { if ( !isNull( node ) )
++node; node = getNext( node );
}
if (!isNull(node)) { if ( !isNull( node ) )
return node->get(); return node->get();
}
} }
} }
return NULL; return nullptr;
} }
Track *TrackList::GetPrev(Track * t, bool linked) const Track *TrackList::GetPrev(Track * t, bool linked) const
{ {
if (t) { if (t) {
TrackNodePointer prev;
auto node = t->GetNode(); auto node = t->GetNode();
if (!isNull(node)) { if ( !isNull( node ) ) {
// linked is true and input track second in team? // linked is true and input track second in team?
if (linked && hasPrev(node) && if (linked) {
!t->GetLinked() && t->GetLink()) prev = getPrev( node );
if( !isNull( prev ) &&
!t->GetLinked() && t->GetLink() )
// Make it the first // Make it the first
--node; node = prev;
}
if (hasPrev(node)) { prev = getPrev( node );
if ( !isNull( prev ) ) {
// Back up once // Back up once
--node; node = prev;
// Back up twice sometimes when linked is true // Back up twice sometimes when linked is true
if (linked && hasPrev(node) && if (linked) {
!(*node)->GetLinked() && (*node)->GetLink()) prev = getPrev( node );
--node; if( !isNull( prev ) &&
!(*node)->GetLinked() && (*node)->GetLink() )
node = prev;
}
return node->get(); return node->get();
} }
} }
} }
return NULL; return nullptr;
} }
/// For mono track height of track /// For mono track height of track
@ -1152,7 +1145,7 @@ size_t TrackList::size() const
int cnt = 0; int cnt = 0;
if (!empty()) if (!empty())
cnt = back()->GetIndex() + 1; cnt = getPrev( getEnd() )->get()->GetIndex() + 1;
return cnt; return cnt;
} }
@ -1290,7 +1283,7 @@ int TrackList::GetHeight() const
int height = 0; int height = 0;
if (!empty()) { if (!empty()) {
const auto &track = back(); auto track = getPrev( getEnd() )->get();
height = track->GetY() + track->GetHeight(); height = track->GetY() + track->GetHeight();
} }

View File

@ -688,10 +688,30 @@ class TrackList final : public wxEvtHandler, public ListOfTracks
private: private:
bool isNull(TrackNodePointer p) const bool isNull(TrackNodePointer p) const
{ return p == ListOfTracks::end(); } { return p == ListOfTracks::end(); }
void setNull(TrackNodePointer &p) TrackNodePointer getEnd() const
{ p = ListOfTracks::end(); } { return const_cast<TrackList*>(this)->ListOfTracks::end(); }
bool hasPrev(TrackNodePointer p) const TrackNodePointer getBegin() const
{ return p != ListOfTracks::begin(); } { return const_cast<TrackList*>(this)->ListOfTracks::begin(); }
// Move an iterator to the next node, if any; else stay at end
TrackNodePointer getNext(TrackNodePointer p) const
{
if ( isNull(p) )
return p;
auto q = p;
return ++q;
}
// Move an iterator to the previous node, if any; else wrap to end
TrackNodePointer getPrev(TrackNodePointer p) const
{
if (p == this->ListOfTracks::begin())
return getEnd();
else {
auto q = p;
return --q;
}
}
void DoAssign(const TrackList &that); void DoAssign(const TrackList &that);