From 2741d58880ca5b7d5ccd7c19a904b051c4da5c25 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 5 Feb 2018 17:56:46 -0500 Subject: [PATCH] TrackList emits more events for certain changes of state of tracks... ... Also rewrote some of the existing event handling so all events from TrackList are of the same, custom event class, and distinguishing addition from resizing events, though this distinction is not yet used --- src/NoteTrack.cpp | 8 +++++ src/NoteTrack.h | 2 +- src/Track.cpp | 85 ++++++++++++++++++++++++++++++++++++++-------- src/Track.h | 51 ++++++++++++++++++++++------ src/TrackPanel.cpp | 11 +++--- src/TrackPanel.h | 8 ++--- src/WaveTrack.cpp | 14 +++++--- 7 files changed, 140 insertions(+), 39 deletions(-) diff --git a/src/NoteTrack.cpp b/src/NoteTrack.cpp index 5bf790d04..4cb99f463 100644 --- a/src/NoteTrack.cpp +++ b/src/NoteTrack.cpp @@ -643,6 +643,14 @@ void NoteTrack::InsertSilence(double t, double len) // AddToDuration( len ); } +void NoteTrack::SetVelocity(float velocity) +{ + if (mVelocity != velocity) { + mVelocity = velocity; + Notify(); + } +} + // Call this function to manipulate the underlying sequence data. This is // NOT the function that handles horizontal dragging. bool NoteTrack::Shift(double t) // t is always seconds diff --git a/src/NoteTrack.h b/src/NoteTrack.h index 0066ce12d..6179c03cd 100644 --- a/src/NoteTrack.h +++ b/src/NoteTrack.h @@ -114,7 +114,7 @@ class AUDACITY_DLL_API NoteTrack final #ifdef EXPERIMENTAL_MIDI_OUT float GetVelocity() const { return mVelocity; } - void SetVelocity(float velocity) { mVelocity = velocity; } + void SetVelocity(float velocity); #endif QuantizedTimeAndBeat NearestBeatTime( double time ) const; diff --git a/src/Track.cpp b/src/Track.cpp index c090e0319..583535968 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -91,9 +91,22 @@ void Track::Init(const Track &orig) mChannel = orig.mChannel; } +void Track::SetName( const wxString &n ) +{ + if ( mName != n ) { + mName = n; + Notify(); + } +} + void Track::SetSelected(bool s) { - mSelected = s; + if (mSelected != s) { + mSelected = s; + auto pList = mList.lock(); + if (pList) + pList->SelectionEvent( Pointer( this ) ); + } } void Track::Merge(const Track &orig) @@ -328,6 +341,13 @@ bool Track::IsSyncLockSelected() const return false; } +void Track::Notify( int code ) +{ + auto pList = mList.lock(); + if (pList) + pList->DataEvent( Pointer(this), code ); +} + void Track::SyncLockAdjust(double oldT1, double newT1) { if (newT1 > oldT1) { @@ -367,6 +387,22 @@ void PlayableTrack::Merge( const Track &orig ) AudioTrack::Merge( *pOrig ); } +void PlayableTrack::SetMute( bool m ) +{ + if ( mMute != m ) { + mMute = m; + Notify(); + } +} + +void PlayableTrack::SetSolo( bool s ) +{ + if ( mSolo != s ) { + mSolo = s; + Notify(); + } +} + // Serialize, not with tags of its own, but as attributes within a tag. void PlayableTrack::WriteXMLAttributes(XMLWriter &xmlFile) const { @@ -513,9 +549,12 @@ std::pair TrackList::FindSyncLockGroup(Track *pMember) const // is managing. Any other classes that may be interested in get these updates // should use TrackList::Connect() or TrackList::Bind(). // -wxDEFINE_EVENT(EVT_TRACKLIST_PERMUTED, wxCommandEvent); -wxDEFINE_EVENT(EVT_TRACKLIST_RESIZING, wxCommandEvent); -wxDEFINE_EVENT(EVT_TRACKLIST_DELETION, wxCommandEvent); +wxDEFINE_EVENT(EVT_TRACKLIST_TRACK_DATA_CHANGE, TrackListEvent); +wxDEFINE_EVENT(EVT_TRACKLIST_SELECTION_CHANGE, TrackListEvent); +wxDEFINE_EVENT(EVT_TRACKLIST_PERMUTED, TrackListEvent); +wxDEFINE_EVENT(EVT_TRACKLIST_RESIZING, TrackListEvent); +wxDEFINE_EVENT(EVT_TRACKLIST_ADDITION, TrackListEvent); +wxDEFINE_EVENT(EVT_TRACKLIST_DELETION, TrackListEvent); // same value as in the default constructed TrackId: long TrackList::sCounter = -1; @@ -592,26 +631,42 @@ void TrackList::RecalcPositions(TrackNodePointer node) UpdatePendingTracks(); } +void TrackList::SelectionEvent( const std::shared_ptr &pTrack ) +{ + // wxWidgets will own the event object + QueueEvent( + safenew TrackListEvent{ EVT_TRACKLIST_SELECTION_CHANGE, pTrack } ); +} + +void TrackList::DataEvent( const std::shared_ptr &pTrack, int code ) +{ + // wxWidgets will own the event object + QueueEvent( + safenew TrackListEvent{ EVT_TRACKLIST_TRACK_DATA_CHANGE, pTrack, code } ); +} + void TrackList::PermutationEvent() { - auto e = std::make_unique(EVT_TRACKLIST_PERMUTED); // wxWidgets will own the event object - QueueEvent(e.release()); + QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_PERMUTED } ); } void TrackList::DeletionEvent() { - auto e = std::make_unique(EVT_TRACKLIST_DELETION); // wxWidgets will own the event object - QueueEvent(e.release()); + QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_DELETION } ); +} + +void TrackList::AdditionEvent(TrackNodePointer node) +{ + // wxWidgets will own the event object + QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_ADDITION, *node.first } ); } void TrackList::ResizingEvent(TrackNodePointer node) { - auto e = std::make_unique(EVT_TRACKLIST_RESIZING); - e->mpTrack = *node.first; // wxWidgets will own the event object - QueueEvent(e.release()); + QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_RESIZING, *node.first } ); } auto TrackList::EmptyRange() const @@ -678,7 +733,7 @@ Track *TrackList::Add(std::unique_ptr &&t) pTrack->SetOwner(mSelf, n); pTrack->SetId( TrackId{ ++sCounter } ); RecalcPositions(n); - ResizingEvent(n); + AdditionEvent(n); return back().get(); } @@ -700,7 +755,7 @@ Track *TrackList::AddToHead(std::unique_ptr &&t) pTrack->SetOwner(mSelf, n); pTrack->SetId( TrackId{ ++sCounter } ); RecalcPositions(n); - ResizingEvent(n); + AdditionEvent(n); return front().get(); } @@ -717,7 +772,7 @@ Track *TrackList::Add(std::shared_ptr &&t) t->SetOwner(mSelf, n); t->SetId( TrackId{ ++sCounter } ); RecalcPositions(n); - ResizingEvent(n); + AdditionEvent(n); return back().get(); } @@ -794,7 +849,7 @@ auto TrackList::Replace(Track * t, ListOfTracks::value_type &&with) -> RecalcPositions(node); DeletionEvent(); - ResizingEvent(node); + AdditionEvent(node); } return holder; } diff --git a/src/Track.h b/src/Track.h index 01f8c6fc9..795c411c7 100644 --- a/src/Track.h +++ b/src/Track.h @@ -205,8 +205,10 @@ class AUDACITY_DLL_API Track /* not final */ wxString mName; wxString mDefaultName; + private: bool mSelected; + protected: bool mLinked; bool mMinimized; @@ -367,7 +369,7 @@ private: virtual void Merge(const Track &orig); wxString GetName() const { return mName; } - void SetName( const wxString &n ) { mName = n; } + void SetName( const wxString &n ); wxString GetDefaultName() const { return mDefaultName; } void SetDefaultName( const wxString &n ) { mDefaultName = n; } @@ -714,6 +716,11 @@ public: // Checks if sync-lock is on and any track in its sync-lock group is selected. bool IsSyncLockSelected() const; + // Send an event to listeners when state of the track changes + // To do: define values for the argument to distinguish different parts + // of the state, perhaps with wxNewId + void Notify( int code = -1 ); + // An always-true predicate useful for defining iterators bool Any() const; @@ -763,8 +770,8 @@ public: bool GetMute () const { return mMute; } bool GetSolo () const { return mSolo; } - void SetMute (bool m) { mMute = m; } - void SetSolo (bool s) { mSolo = s; } + void SetMute (bool m); + void SetSolo (bool s); void Init( const PlayableTrack &init ); void Merge( const Track &init ) override; @@ -1086,31 +1093,50 @@ template < * Clear, and Contains, plus serialization of the list of tracks. */ -struct TrackListEvent : public wxCommandEvent +struct TrackListEvent : public wxEvent { - TrackListEvent(wxEventType commandType = wxEVT_NULL, int winid = 0) - : wxCommandEvent{ commandType, winid } {} + explicit + TrackListEvent( + wxEventType commandType, + const std::weak_ptr &pTrack = {}, int code = -1) + : wxEvent{ commandType } + , mpTrack{ pTrack } + , mCode{ code } + {} TrackListEvent( const TrackListEvent& ) = default; wxEvent *Clone() const override { return new TrackListEvent(*this); } std::weak_ptr mpTrack; + int mCode; }; +// 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. +wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, + EVT_TRACKLIST_TRACK_DATA_CHANGE, TrackListEvent); + // Posted when tracks are reordered but otherwise unchanged. wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, - EVT_TRACKLIST_PERMUTED, wxCommandEvent); + EVT_TRACKLIST_PERMUTED, TrackListEvent); -// Posted when some track was added or changed its height. -// Cast to TrackListEvent and examine mpTrack to retrieve it. +// Posted when some track changed its height. wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, - EVT_TRACKLIST_RESIZING, wxCommandEvent); + EVT_TRACKLIST_RESIZING, TrackListEvent); + +// 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 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, - EVT_TRACKLIST_DELETION, wxCommandEvent); + EVT_TRACKLIST_DELETION, TrackListEvent); class TrackList final : public wxEvtHandler, public ListOfTracks { @@ -1495,8 +1521,11 @@ private: } void RecalcPositions(TrackNodePointer node); + void SelectionEvent( const std::shared_ptr &pTrack ); void PermutationEvent(); + void DataEvent( const std::shared_ptr &pTrack, int code ); void DeletionEvent(); + void AdditionEvent(TrackNodePointer node); void ResizingEvent(TrackNodePointer node); void SwapNodes(TrackNodePointer s1, TrackNodePointer s2); diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 2ea6a23ce..7ee00e702 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -332,6 +332,9 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id, mTracks->Bind(EVT_TRACKLIST_RESIZING, &TrackPanel::OnTrackListResizing, this); + mTracks->Bind(EVT_TRACKLIST_ADDITION, + &TrackPanel::OnTrackListResizing, + this); mTracks->Bind(EVT_TRACKLIST_DELETION, &TrackPanel::OnTrackListDeletion, this); @@ -781,7 +784,7 @@ void TrackPanel::UpdateViewIfNoTracks() } } -void TrackPanel::OnPlayback(wxCommandEvent &e) +void TrackPanel::OnPlayback(wxEvent &e) { e.Skip(); // Starting or stopping of play or record affects some cursors. @@ -792,9 +795,9 @@ void TrackPanel::OnPlayback(wxCommandEvent &e) // The tracks positions within the list have changed, so update the vertical // ruler size for the track that triggered the event. -void TrackPanel::OnTrackListResizing(wxCommandEvent & e) +void TrackPanel::OnTrackListResizing(TrackListEvent & e) { - auto t = static_cast(e).mpTrack.lock(); + auto t = e.mpTrack.lock(); // A deleted track can trigger the event. In which case do nothing here. if( t ) UpdateVRuler(t.get()); @@ -802,7 +805,7 @@ void TrackPanel::OnTrackListResizing(wxCommandEvent & e) } // Tracks have been removed from the list. -void TrackPanel::OnTrackListDeletion(wxCommandEvent & e) +void TrackPanel::OnTrackListDeletion(wxEvent & e) { // copy shared_ptr for safety, as in HandleClick auto handle = Target(); diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 91e99acc4..17c8b08ec 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -33,6 +33,7 @@ class LabelTrack; class SpectrumAnalyst; class Track; class TrackList; +class TrackListEvent; class TrackPanel; class TrackArtist; class Ruler; @@ -41,7 +42,6 @@ class AdornedRulerPanel; class LWSlider; class ControlToolBar; //Needed because state of controls can affect what gets drawn. class ToolsToolBar; //Needed because state of controls can affect what gets drawn. -class MixerBoard; class TrackPanelAx; class TrackPanelCellIterator; @@ -257,9 +257,9 @@ class AUDACITY_DLL_API TrackPanel final : public CellularPanel { void OnMouseEvent(wxMouseEvent & event); void OnKeyDown(wxKeyEvent & event); - void OnPlayback(wxCommandEvent &); - void OnTrackListResizing(wxCommandEvent & event); - void OnTrackListDeletion(wxCommandEvent & event); + void OnPlayback(wxEvent &); + void OnTrackListResizing(TrackListEvent & event); + void OnTrackListDeletion(wxEvent & event); void UpdateViewIfNoTracks(); // Call this to update mViewInfo, etc, after track(s) removal, before Refresh(). double GetMostRecentXPos(); diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 815536a21..131fa1f66 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -422,7 +422,10 @@ float WaveTrack::GetGain() const void WaveTrack::SetGain(float newGain) { - mGain = newGain; + if (mGain != newGain) { + mGain = newGain; + Notify(); + } } float WaveTrack::GetPan() const @@ -433,11 +436,14 @@ float WaveTrack::GetPan() const void WaveTrack::SetPan(float newPan) { if (newPan > 1.0) - mPan = 1.0; + newPan = 1.0; else if (newPan < -1.0) - mPan = -1.0; - else + newPan = -1.0; + + if ( mPan != newPan ) { mPan = newPan; + Notify(); + } } float WaveTrack::GetChannelGain(int channel) const