From d420fdecf4ce8a1849bef72eac3f440ab0fcf6e8 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 23 Aug 2020 07:51:01 -0400 Subject: [PATCH] Much Doxygen commentary for Track.h... ... Comments and indentation changes only, with a small bit of code movement to improve the sequence of items on the Doxygen page. Comments some obscurities of template usage and of iterators (TrackIter and TrackNodePointer). --- src/Track.cpp | 7 +- src/Track.h | 378 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 229 insertions(+), 156 deletions(-) diff --git a/src/Track.cpp b/src/Track.cpp index ef65e1e91..2f99f1c15 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -9,7 +9,7 @@ *******************************************************************//** \class Track -\brief Fundamental data object of Audacity, placed in the TrackPanel. +\brief Fundamental data object of Audacity, displayed in the TrackPanel. Classes derived form it include the WaveTrack, NoteTrack, LabelTrack and TimeTrack. @@ -800,8 +800,9 @@ TrackNodePointer TrackList::Remove(Track *t) void TrackList::Clear(bool sendEvent) { - // Null out the back-pointers in tracks, in case there are outstanding - // shared_ptrs to those tracks. + // Null out the back-pointers to this in tracks, in case there + // are outstanding shared_ptrs to those tracks, making them outlive + // the temporary ListOfTracks below. for ( auto pTrack: *this ) pTrack->SetOwner( {}, {} ); for ( auto pTrack: mPendingUpdates ) diff --git a/src/Track.h b/src/Track.h index 1c8002c5f..ca2b5ad1a 100644 --- a/src/Track.h +++ b/src/Track.h @@ -1,8 +1,9 @@ -/********************************************************************** +/*!******************************************************************** Audacity: A Digital Audio Editor - Track.h + @file Track.h + @brief declares abstract base class Track, TrackList, and iterators over TrackList Dominic Mazzoni @@ -50,6 +51,9 @@ class TrackList; using ListOfTracks = std::list< std::shared_ptr< Track > >; +//! Pairs a std::list iterator and a pointer to a list, for comparison purposes +/*! Compare owning lists first, and only if same, then the iterators; + else MSVC debug runtime complains. */ using TrackNodePointer = std::pair< ListOfTracks::iterator, ListOfTracks* >; @@ -59,21 +63,22 @@ inline bool operator == (const TrackNodePointer &a, const TrackNodePointer &b) inline bool operator != (const TrackNodePointer &a, const TrackNodePointer &b) { return !(a == b); } +//! Enumerates all subclasses of Track (not just the leaf classes) and the None value enum class TrackKind { - None, + None, //!< no class Wave, Note, Label, Time, - Audio, - Playable, - All + Audio, //!< nonleaf + Playable, //!< nonleaf + All //!< the root class }; -/// Compile-time function on enum values. -/// It knows all inheritance relations among Track subclasses -/// even where the track types are only forward declared. +//! Compile-time function on enum values +/*! It knows all inheritance relations among Track subclasses + even where the track types are only forward declared. */ constexpr bool CompatibleTrackKinds( TrackKind desired, TrackKind actual ) { return @@ -95,10 +100,10 @@ constexpr bool CompatibleTrackKinds( TrackKind desired, TrackKind actual ) ; } -/// \brief Metaprogramming in TrackTyper lets track_cast work even when the track -/// subclasses are visible only as incomplete types +//! Metaprogramming enabling track_cast even when the subclasses are incomplete types namespace TrackTyper { template struct Pair; + //! Compile-time map from types to enum values using List = std::tuple< Pair, Pair, @@ -109,13 +114,16 @@ namespace TrackTyper { Pair // New classes can be added easily to this list >; - template struct Lookup; + //! Variadic template implements metafunction with specializations, to associate enum values with types + template struct Lookup {}; + //! Base case of metafunction template struct Lookup< TrackType, std::tuple< Pair, Rest... > > { static constexpr TrackKind value() { return Here; } }; + //! Recursive case of metafunction template struct Lookup< TrackType, std::tuple< NotHere, Rest... > > { static constexpr TrackKind value() { @@ -124,6 +132,7 @@ namespace TrackTyper { }; }; +//! Metafunction from track subtype (as template parameter) to enum value template constexpr TrackKind track_kind () { using namespace TrackTyper; @@ -143,15 +152,14 @@ template >::type track_cast(const Track *track); -class ViewInfo; - -/// This is an in-session identifier of track objects across undo states -/// -/// It does not persist between sessions -/// Default constructed value is not equal to the id of any track that has ever -/// been added to a TrackList, or (directly or transitively) copied from such -/// (A pending additional track that is not yet applied is not considered added) -/// TrackIds are assigned uniquely across projects +//! An in-session identifier of track objects across undo states. It does not persist between sessions +/*! + Default constructed value is not equal to the id of any track that has ever + been added to a TrackList, or (directly or transitively) copied from such. + (A track added by TrackList::RegisterPendingNewTrack() that is not yet applied is not + considered added.) + + TrackIds are assigned uniquely across projects. */ class TrackId { public: @@ -173,10 +181,12 @@ private: long mValue; }; +//! Template generated base class for Track lets it host opaque UI related objects using AttachedTrackObjects = ClientData::Site< Track, ClientData::Base, ClientData::SkipCopying, std::shared_ptr >; +//! Abstract base class for an object holding data associated with points on a time axis class AUDACITY_DLL_API Track /* not final */ : public XMLTagHandler , public AttachedTrackObjects @@ -184,14 +194,15 @@ class AUDACITY_DLL_API Track /* not final */ { friend class TrackList; - // To be TrackDisplay private: - TrackId mId; + TrackId mId; //!< Identifies the track only in-session, not persistently protected: - std::weak_ptr mList; + std::weak_ptr mList; //!< Back pointer to owning TrackList + //! Holds iterator to self, so that TrackList::Find can be constant-time + /*! mNode's pointer to std::list might not be this TrackList, if it's a pending update track */ TrackNodePointer mNode{}; - int mIndex; + int mIndex; //!< 0-based position of this track in its TrackList wxString mName; wxString mDefaultName; @@ -203,6 +214,7 @@ class AUDACITY_DLL_API Track /* not final */ public: + //! Alias for my base type using AttachedObjects = ::AttachedTrackObjects; using ChannelType = XMLValueChecker::ChannelType; @@ -296,7 +308,9 @@ private: // No need yet to make this virtual void DoSetLinked(bool l); + //! Retrieve mNode with debug checks TrackNodePointer GetNode() const; + //! Update mNode when Track is added to TrackList, or removed from it void SetOwner (const std::weak_ptr &list, TrackNodePointer node); @@ -397,79 +411,63 @@ public: bool SameKindAs(const Track &track) const { return GetKind() == track.GetKind(); } + //! Type of arguments passed as optional second parameter to TypeSwitch() cases template < typename R = void > using Continuation = std::function< R() >; + //! Type of arguments passed as optional second parameter to TypeSwitch() cases using Fallthrough = Continuation<>; private: - - // Variadic template specialized below + //! Variadic template implements metafunction with specializations, to dispatch Track::TypeSwitch template< typename ...Params > - struct Executor; + struct Executor{}; - // This specialization grounds the recursion. - template< typename R, typename ConcreteType > - struct Executor< R, ConcreteType > - { - enum : unsigned { SetUsed = 0 }; - // No functions matched, so do nothing. - R operator () (const void *) { return R{}; } - }; - - // And another specialization is needed for void return. - template< typename ConcreteType > - struct Executor< void, ConcreteType > - { - enum : unsigned { SetUsed = 0 }; - // No functions matched, so do nothing. - void operator () (const void *) { } - }; - - // This struct groups some helpers needed to define the recursive cases of - // Executor. + //! Helper for recursive case of metafunction implementing Track::TypeSwitch + /*! Mutually recursive (in compile time) with tempate Track::Executor. */ struct Dispatcher { - // This implements the specialization of Executor - // for the first recursive case. + //! First, recursive case of metafunction, defers generation of operator () template< typename R, typename ConcreteType, typename Function, typename ...Functions > struct inapplicable { + //! The template specialization to recur with using Tail = Executor< R, ConcreteType, Functions... >; + //! Constant used in a compile-time check enum : unsigned { SetUsed = Tail::SetUsed << 1 }; - // Ignore the first, inapplicable function and try others. + //! Ignore the first, inapplicable function and try others. R operator () (const Track *pTrack, const Function &, const Functions &...functions) { return Tail{}( pTrack, functions... ); } }; - // This implements the specialization of Executor - // for the second recursive case. + //! Second, nonrecursive case of metafunction, generates operator () that calls function without fallthrough template< typename R, typename BaseClass, typename ConcreteType, typename Function, typename ...Functions > struct applicable1 { + //! Constant used in a compile-time check enum : unsigned { SetUsed = 1u }; - // Ignore the remaining functions and call the first only. + //! Ignore the remaining functions and call the first only. R operator () (const Track *pTrack, const Function &function, const Functions &...) { return function( (BaseClass *)pTrack ); } }; - // This implements the specialization of Executor - // for the third recursive case. + //! Third, recursive case of metafunction, generates operator () that calls function with fallthrough template< typename R, typename BaseClass, typename ConcreteType, typename Function, typename ...Functions > struct applicable2 { + //! The template specialization to recur with using Tail = Executor< R, ConcreteType, Functions... >; + //! Constant used in a compile-time check enum : unsigned { SetUsed = (Tail::SetUsed << 1) | 1u }; - // Call the first function, which may request dispatch to the further - // functions by invoking a continuation. + //! Call the first function, which may request dispatch to the further functions by invoking a continuation. R operator () (const Track *pTrack, const Function &function, const Functions &...functions) @@ -481,35 +479,40 @@ private: } }; - // This variadic template chooses among the implementations above. - template< typename ... > struct Switch; + //! Variadic template implements metafunction with specializations, to choose among implementations of operator () + template< typename ... > struct Switch {}; - // Ground the recursion. + //! Base case, no more base classes of ConcreteType + /*! Computes a type as the return type of undefined member test() */ template< typename R, typename ConcreteType > struct Switch< R, ConcreteType > { - // No BaseClass of ConcreteType is acceptable to Function. + //! No BaseClass of ConcreteType is acceptable to Function. template< typename Function, typename ...Functions > static auto test() -> inapplicable< R, ConcreteType, Function, Functions... >; }; - // Recursive case. + //! Recursive case, tries to match function with one base class of ConcreteType + /*! Computes a type as the return type of undefined member test() */ template< typename R, typename ConcreteType, typename BaseClass, typename ...BaseClasses > struct Switch< R, ConcreteType, BaseClass, BaseClasses... > { + //! Recur to this type to try the next base class using Retry = Switch< R, ConcreteType, BaseClasses... >; - // If ConcreteType is not compatible with BaseClass, or if - // Function does not accept BaseClass, try other BaseClasses. + //! Catch-all overload of undefined function used in decltype only + /*! If ConcreteType is not compatible with BaseClass, or if + Function does not accept BaseClass*, try other BaseClasses. */ template< typename Function, typename ...Functions > static auto test( const void * ) -> decltype( Retry::template test< Function, Functions... >() ); - // If BaseClass is a base of ConcreteType and Function can take it, - // then overload resolution chooses this. - // If not, then the sfinae rule makes this overload unavailable. + //! overload when upcast of ConcreteType* works, with sfinae'd return type + /*! If BaseClass is a base of ConcreteType and Function can take a pointer to it, + then overload resolution chooses this. + If not, then the sfinae rule makes this overload unavailable. */ template< typename Function, typename ...Functions > static auto test( std::true_type * ) -> decltype( @@ -519,10 +522,11 @@ private: Function, Functions... >{} ); - // If BaseClass is a base of ConcreteType and Function can take it, - // with a second argument for a continuation, - // then overload resolution chooses this. - // If not, then the sfinae rule makes this overload unavailable. + //! overload when upcast of ConcreteType* works, with sfinae'd return type + /*! If BaseClass is a base of ConcreteType and Function can take a pointer to it, + with a second argument for a continuation, + then overload resolution chooses this. + If not, then the sfinae rule makes this overload unavailable. */ template< typename Function, typename ...Functions > static auto test( std::true_type * ) -> decltype( @@ -533,8 +537,10 @@ private: Function, Functions... >{} ); + //! Whether upcast of ConcreteType* to first BaseClass* works static constexpr bool Compatible = CompatibleTrackKinds( track_kind(), track_kind() ); + //! undefined function used in decltype only to compute a type, using other overloads template< typename Function, typename ...Functions > static auto test() -> decltype( @@ -543,7 +549,28 @@ private: }; }; - // This specialization is the recursive case for non-const tracks. + //! Base case of metafunction implementing Track::TypeSwitch generates operator () with nonvoid return + template< typename R, typename ConcreteType > + struct Executor< R, ConcreteType > + { + //! Constant used in a compile-time check + enum : unsigned { SetUsed = 0 }; + //! No functions matched, so do nothing + R operator () (const void *) { return R{}; } + }; + + //! Base case of metafunction implementing Track::TypeSwitch generates operator () with void return + template< typename ConcreteType > + struct Executor< void, ConcreteType > + { + //! Constant used in a compile-time check + enum : unsigned { SetUsed = 0 }; + //! No functions matched, so do nothing + void operator () (const void *) { } + }; + + //! Implements Track::TypeSwitch, its operator() invokes the first function that can accept ConcreteType* + /*! Mutually recursive (in compile time) with template Track::Dispatcher. */ template< typename R, typename ConcreteType, typename Function, typename ...Functions > struct Executor< R, ConcreteType, Function, Functions... > @@ -555,7 +582,8 @@ private: ::template test()) {}; - // This specialization is the recursive case for const tracks. + //! Implements const overload of Track::TypeSwitch, its operator() invokes the first function that can accept ConcreteType* + /*! Mutually recursive (in compile time) with template Track::Dispatcher. */ template< typename R, typename ConcreteType, typename Function, typename ...Functions > struct Executor< R, const ConcreteType, Function, Functions... > @@ -569,17 +597,30 @@ private: public: - // A variadic function taking any number of function objects, each taking - // a pointer to Track or a subclass, maybe const-qualified, and maybe a - // second argument which is a fall-through continuation. - // Each of the function objects (and supplied continuations) returns R. - // Call the first in the sequence that accepts the actual type of the track. - // If no function accepts the track, do nothing and return R{} - // if R is not void. - // If one of the functions invokes the call-through, then the next following - // applicable function is called. - template< typename R = void, typename ...Functions > - R TypeSwitch(const Functions &...functions) + //! Use this function rather than testing track type explicitly and making down-casts. + /*! + A variadic function taking any number of function objects, each taking + a pointer to Track or a subclass, maybe const-qualified, and maybe a + second argument which is a fall-through continuation. + + Each of the function objects (and supplied continuations) returns R (or a type convertible to R). + Calls the first in the sequence that accepts the actual type of the track. + + If no function accepts the track, do nothing and return R{} + if R is not void. + + If one of the functions invokes the call-through, then the next following + applicable function is called. + + @tparam R Return type of this function and each function argument + @tparam Functions callable types deduced from arguments + @param functions typically lambdas, taking a pointer to a track subclass, and optionally a fall-through call-back + */ + template< + typename R = void, + typename ...Functions + > + R TypeSwitch( const Functions &...functions ) { using WaveExecutor = Executor< R, WaveTrack, Functions... >; @@ -618,9 +659,13 @@ public: } } - // This is the overload of TypeSwitch (see above) for const tracks, taking - // callable arguments that only accept arguments that are pointers to const - template< typename R = void, typename ...Functions > + /*! @copydoc Track::TypeSwitch */ + /*! This is the overload for const tracks, only taking + callable arguments that accept first arguments that are pointers to const. */ + template< + typename R = void, + typename ...Functions + > R TypeSwitch(const Functions &...functions) const { using WaveExecutor = @@ -702,6 +747,7 @@ protected: std::shared_ptr mpControls; }; +//! Track subclass holding data representing sound (as notes, or samples, or ...) class AUDACITY_DLL_API AudioTrack /* not final */ : public Track { public: @@ -717,6 +763,7 @@ public: { return false; } }; +//! AudioTrack subclass that can also be audibly replayed by the program class AUDACITY_DLL_API PlayableTrack /* not final */ : public AudioTrack { public: @@ -745,10 +792,14 @@ protected: bool mSolo { false }; }; -// Functions to encapsulate the checked down-casting of track pointers, -// eliminating possibility of error -- and not quietly casting away const -// typical usage: -// if (auto wt = track_cast(track)) { ... } +//! Encapsulate the checked down-casting of track pointers +/*! Eliminates possibility of error -- and not quietly casting away const + +Typical usage: +``` +if (auto wt = track_cast(track)) { ... } +``` + */ template inline typename std::enable_if< std::is_pointer::value, T >::type track_cast(Track *track) @@ -761,7 +812,8 @@ template return nullptr; } -// Overload for const pointers can cast only to other const pointer types +/*! @copydoc track_cast(Track*) +This overload for const pointers can cast only to other const pointer types. */ template inline typename std::enable_if< std::is_pointer::value && @@ -780,15 +832,22 @@ template template < typename TrackType > struct TrackIterRange; -// new track iterators can eliminate the need to cast the result +//! Iterator over only members of a TrackList of the specified subtype, optionally filtered by a predicate; past-end value dereferenceable, to nullptr +/*! Does not suffer invalidation when an underlying std::list iterator is deleted, provided that is not + equal to its current position or to the beginning or end iterator. + + The filtering predicate is tested only when the iterator is constructed or advanced. + + @tparam TrackType Track or a subclass, maybe const-qualified +*/ template < - typename TrackType // Track or a subclass, maybe const-qualified + typename TrackType > class TrackIter : public ValueIterator< TrackType *, std::bidirectional_iterator_tag > { public: - // Type of predicate taking pointer to const TrackType - // TODO C++14: simplify away ::type + //! Type of predicate taking pointer to const TrackType + /*! @todo C++14: simplify away ::type */ using FunctionType = std::function< bool( typename std::add_pointer< typename std::add_const< @@ -799,28 +858,32 @@ public: >::type ) >; - template - TrackIter( TrackNodePointer begin, TrackNodePointer iter, - TrackNodePointer end, const Predicate &pred = {} ) - : mBegin( begin ), mIter( iter ), mEnd( end ), mPred( pred ) + //! Constructor, usually not called directly except by methods of TrackList + TrackIter( + TrackNodePointer begin, //!< Remember lower bound + TrackNodePointer iter, //!< The actual pointer + TrackNodePointer end, //!< Remember upper bound + FunctionType pred = {} //!< %Optional filter + ) + : mBegin( begin ), mIter( iter ), mEnd( end ) + , mPred( std::move(pred) ) { // Establish the class invariant if (this->mIter != this->mEnd && !this->valid()) this->operator ++ (); } - // Return an iterator that replaces the predicate, advancing to the first - // position at or after the old position that satisfies the new predicate, - // or to the end. - template < typename Predicate2 > - TrackIter Filter( const Predicate2 &pred2 ) const + //! Return an iterator that replaces the predicate + /*! Advance to the first position at or after the old position that satisfies the new predicate, + or to the end */ + TrackIter Filter( FunctionType pred2 ) const { - return { this->mBegin, this->mIter, this->mEnd, pred2 }; + return { this->mBegin, this->mIter, this->mEnd, std::move(pred2) }; } - // Return an iterator that refines the subclass (and not removing const), - // advancing to the first position at or after the old position that - // satisfies the type constraint, or to the end + //! Return an iterator for a subclass of TrackType (and not removing const) with same predicate + /*! Advance to the first position at or after the old position that + satisfies the type constraint, or to the end */ template < typename TrackType2 > auto Filter() const -> typename std::enable_if< @@ -836,8 +899,8 @@ public: const FunctionType &GetPredicate() const { return this->mPred; } - // Unlike with STL iterators, this class gives well defined behavior when - // you increment an end iterator: you get the same. + //! Safe to call even when at the end + /*! In that case *this remains unchanged. */ TrackIter &operator ++ () { // Maintain the class invariant @@ -847,6 +910,7 @@ public: return *this; } + //! @copydoc operator++ TrackIter operator ++ (int) { TrackIter result { *this }; @@ -854,9 +918,8 @@ public: return result; } - // Unlike with STL iterators, this class gives well defined behavior when - // you decrement past the beginning of a range: you wrap and get an end - // iterator. + //! Safe to call even when at the beginning + /*! In that case *this wraps to the end. */ TrackIter &operator -- () { // Maintain the class invariant @@ -870,6 +933,7 @@ public: return *this; } + //! @copydoc operator-- TrackIter operator -- (int) { TrackIter result { *this }; @@ -877,8 +941,8 @@ public: return result; } - // Unlike with STL iterators, this class gives well defined behavior when - // you dereference an end iterator: you get a null pointer. + //! Safe to call even when at the end + /*! In that case you get nullptr. */ TrackType *operator * () const { if (this->mIter == this->mEnd) @@ -890,16 +954,17 @@ public: return static_cast< TrackType * >( &**this->mIter.first ); } - // This might be called operator + , - // but that might wrongly suggest constant time when the iterator is not - // random access. - TrackIter advance( long amount ) const + //! This might be called operator + , but it's not constant-time as with a random access iterator + TrackIter advance( + long amount //!< may be negative + ) const { auto copy = *this; std::advance( copy, amount ); return copy; } + //! Compares only current positions, assuming same beginnings and ends friend inline bool operator == (TrackIter a, TrackIter b) { // Assume the predicate is not stateful. Just compare the iterators. @@ -910,12 +975,18 @@ public: ; } + //! @copydoc operator== friend inline bool operator != (TrackIter a, TrackIter b) { return !(a == b); } private: + /*! @pre underlying iterators are still valid, and mPred, if not null, is well behaved */ + /*! @invariant mIter == mEnd, or else, mIter != mEnd, + and **mIter is of the appropriate subclass, and mPred is null or mPred(&**mIter) is true. */ + + //! Test satisfaction of the invariant, while initializing, incrementing, or decrementing bool valid() const { // assume mIter != mEnd @@ -925,16 +996,17 @@ private: return !this->mPred || this->mPred( pTrack ); } - // This friendship is needed in TrackIterRange::StartingWith and - // TrackIterRange::EndingAfter() + //! This friendship is needed in TrackIterRange::StartingWith and TrackIterRange::EndingAfter() friend TrackIterRange< TrackType >; - // The class invariant is that mIter == mEnd, or else, mIter != mEnd and - // **mIter is of the appropriate subclass and mPred(&**mIter) is true. - TrackNodePointer mBegin, mIter, mEnd; - FunctionType mPred; + TrackNodePointer + mBegin, //!< Allows end of reverse iteration to be detected without comparison to other TrackIter + mIter, //!< Current position + mEnd; //!< Allows end of iteration to be detected without comparison to other TrackIter + FunctionType mPred; //!< %Optional filter }; +//! Range between two @ref TrackIter "TrackIters", usable in range-for statements, and with Visit member functions template < typename TrackType // Track or a subclass, maybe const-qualified > struct TrackIterRange @@ -1036,7 +1108,7 @@ template < [=](const Track *pTrack){ return pExcluded == pTrack; } ); } - // See Track::TypeSwitch + //! See Track::TypeSwitch template< typename ...Functions > void Visit(const Functions &...functions) { @@ -1044,8 +1116,8 @@ template < track->TypeSwitch(functions...); } - // See Track::TypeSwitch - // Visit until flag is false, or no more tracks + //! See Track::TypeSwitch + /*! Visit until flag is false, or no more tracks */ template< typename Flag, typename ...Functions > void VisitWhile(Flag &flag, const Functions &...functions) { @@ -1058,6 +1130,7 @@ template < }; +//! Notification of changes in individual tracks of TrackList, or of TrackList's composition struct TrackListEvent : public wxCommandEvent { explicit @@ -1079,40 +1152,38 @@ struct TrackListEvent : public wxCommandEvent int mCode; }; -// Posted when the set of selected tracks changes. +//! Posted when the set of selected tracks changes. wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_SELECTION_CHANGE, TrackListEvent); -// Posted when certain fields of a track change. +//! Posted when certain fields of a track change. wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_TRACK_DATA_CHANGE, TrackListEvent); -// Posted when a track needs to be scrolled into view. +//! Posted when a track needs to be scrolled into view. wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_TRACK_REQUEST_VISIBLE, TrackListEvent); -// Posted when tracks are reordered but otherwise unchanged. -// mpTrack points to the moved track that is earliest in the New ordering. +//! Posted when tracks are reordered but otherwise unchanged. +/*! mpTrack points to the moved track that is earliest in the New ordering. */ wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_PERMUTED, TrackListEvent); -// Posted when some track changed its height. +//! Posted when some track changed its height. wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_RESIZING, TrackListEvent); -// Posted when a track has been added to a tracklist. -// Also posted when one track replaces another +//! Posted when a track has been added to a tracklist. Also posted when one track replaces another wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_ADDITION, TrackListEvent); -// Posted when a track has been deleted from a tracklist. -// Also posted when one track replaces another. -// mpTrack points to the first track after the deletion, if there is one. +//! Posted when a track has been deleted from a tracklist. Also posted when one track replaces another +/*! mpTrack points to the first track after the deletion, if there is one. */ wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_DELETION, TrackListEvent); -/** \brief TrackList is a flat linked list of tracks supporting Add, Remove, - * Clear, and Contains, plus serialization of the list of tracks. +/*! @brief A flat linked list of tracks supporting Add, Remove, + * Clear, and Contains, serialization of the list of tracks, event notifications */ class TrackList final : public wxEvtHandler @@ -1170,7 +1241,7 @@ class TrackList final const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } - // Turn a pointer into an iterator (constant time). + //! Turn a pointer into a TrackIter (constant time); get end iterator if this does not own the track template < typename TrackType = Track > auto Find(Track *pTrack) -> TrackIter< TrackType > @@ -1181,7 +1252,8 @@ class TrackList final return MakeTrackIterator( pTrack->GetNode() ); } - // Turn a pointer into an iterator (constant time). + //! @copydoc Find + /*! const overload will only produce iterators over const TrackType */ template < typename TrackType = const Track > auto Find(const Track *pTrack) const -> typename std::enable_if< std::is_const::value, @@ -1330,7 +1402,7 @@ public: friend class Track; - /// For use in sorting: assume each iterator points into this list, no duplications + //! For use in sorting: assume each iterator points into this list, no duplications void Permute(const std::vector &permutation); Track *FindById( TrackId id ); @@ -1359,8 +1431,7 @@ public: ListOfTracks::value_type Replace( Track * t, const ListOfTracks::value_type &with); - /// Remove this Track or all children of this TrackList. - /// Return an iterator to what followed the removed track. + //! Remove the Track and return an iterator to what followed it. TrackNodePointer Remove(Track *t); /// Make the list empty @@ -1373,7 +1444,7 @@ public: bool MoveDown(Track * t); bool Move(Track * t, bool up) { return up ? MoveUp(t) : MoveDown(t); } - /// Mainly a test function. Uses a linear search, so could be slow. + //! Mainly a test function. Uses a linear search, so could be slow. bool Contains(const Track * t) const; // Return non-null only if the weak pointer is not, and the track is @@ -1463,7 +1534,7 @@ private: { return { const_cast(this)->ListOfTracks::begin(), const_cast(this)}; } - // Move an iterator to the next node, if any; else stay at end + //! Move an iterator to the next node, if any; else stay at end TrackNodePointer getNext(TrackNodePointer p) const { if ( isNull(p) ) @@ -1473,7 +1544,7 @@ private: return q; } - // Move an iterator to the previous node, if any; else wrap to end + //! Move an iterator to the previous node, if any; else wrap to end TrackNodePointer getPrev(TrackNodePointer p) const { if (p == getBegin()) @@ -1550,9 +1621,10 @@ public: private: AudacityProject *mOwner; - // Need to put pending tracks into a list so that GetLink() works + //! Shadow tracks holding append-recording in progress; need to put them into a list so that GetLink() works + /*! Beware, they are in a disjoint iteration sequence from ordinary tracks */ ListOfTracks mPendingUpdates; - // This is in correspondence with mPendingUpdates + //! This is in correspondence with mPendingUpdates std::vector< Updater > mUpdaters; };