diff --git a/src/SelectionState.cpp b/src/SelectionState.cpp index 3f79712f8..03275d9b5 100644 --- a/src/SelectionState.cpp +++ b/src/SelectionState.cpp @@ -188,3 +188,39 @@ void SelectionState::TrackListUpdated( const TrackList &tracks ) if (mLastPickedTrack && !tracks.Contains(mLastPickedTrack)) mLastPickedTrack = nullptr; } + +SelectionStateChanger::SelectionStateChanger +( SelectionState &state, TrackList &tracks ) + : mpState{ &state } + , mTracks{ tracks } + , mInitialLastPickedTrack{ state.mLastPickedTrack } +{ + // Save initial state of track selections + mInitialTrackSelection.clear(); + TrackListIterator iter( &mTracks ); + for (Track *track = iter.First(); track; track = iter.Next()) { + const bool isSelected = track->GetSelected(); + mInitialTrackSelection.push_back(isSelected); + } +} + +SelectionStateChanger::~SelectionStateChanger() +{ + if ( mpState ) { + // roll back changes + mpState->mLastPickedTrack = mInitialLastPickedTrack; + TrackListIterator iter( &mTracks ); + std::vector::const_iterator + it = mInitialTrackSelection.begin(), + end = mInitialTrackSelection.end(); + for (Track *track = iter.First(); track && it != end; track = iter.Next()) { + // wxASSERT(it != end); + track->SetSelected( *it++ ); + } + } +} + +void SelectionStateChanger::Commit() +{ + mpState = nullptr; +} diff --git a/src/SelectionState.h b/src/SelectionState.h index b615e80a7..9797f8e21 100644 --- a/src/SelectionState.h +++ b/src/SelectionState.h @@ -13,6 +13,7 @@ class Track; class TrackList; class MixerBoard; class ViewInfo; +#include // State relating to the set of selected tracks class SelectionState @@ -37,7 +38,29 @@ public: void TrackListUpdated( const TrackList &tracks ); +private: + friend class SelectionStateChanger; + Track *mLastPickedTrack {}; }; +// For committing or rolling-back of changes in selectedness of tracks. +// When rolling back, it is assumed that no tracks have been added or removed. +class SelectionStateChanger +{ +public: + SelectionStateChanger( SelectionState &state, TrackList &tracks ); + SelectionStateChanger( const SelectionStateChanger& ) = delete; + SelectionStateChanger &operator=( const SelectionStateChanger& ) = delete; + + ~SelectionStateChanger(); + void Commit(); + +private: + SelectionState *mpState; + TrackList &mTracks; + Track *mInitialLastPickedTrack; + std::vector mInitialTrackSelection; +}; + #endif diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index a246fa48e..09a592dbc 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1151,15 +1151,7 @@ bool TrackPanel::HandleEscapeKey(bool down) { case IsSelecting: { - TrackListIterator iter(GetTracks()); - std::vector::const_iterator - it = mInitialTrackSelection.begin(), - end = mInitialTrackSelection.end(); - for (Track *t = iter.First(); t; t = iter.Next()) { - wxASSERT(it != end); - t->SetSelected(*it++); - } - GetSelectionState().mLastPickedTrack = mInitialLastPickedTrack; + mSelectionStateChanger.reset(); mViewInfo->selectedRegion = mInitialSelection; // Refresh mixer board for change of set of selected tracks @@ -1789,6 +1781,10 @@ void TrackPanel::HandleSelect(wxMouseEvent & event) SelectionHandleClick(event, t, rect); } else if (event.LeftUp() || event.RightUp()) { mSnapManager.reset(); + if (mSelectionStateChanger) { + mSelectionStateChanger->Commit(); + mSelectionStateChanger.reset(); + } bool left; if ( GetProject()->IsSyncLocked() && @@ -1931,17 +1927,8 @@ void TrackPanel::SelectionHandleClick(wxMouseEvent & event, mMouseCapture=IsSelecting; mInitialSelection = mViewInfo->selectedRegion; - mInitialLastPickedTrack = GetSelectionState().mLastPickedTrack; - - // Save initial state of track selections - mInitialTrackSelection.clear(); - { - TrackListIterator iter(GetTracks()); - for (Track *t = iter.First(); t; t = iter.Next()) { - const bool isSelected = t->GetSelected(); - mInitialTrackSelection.push_back(isSelected); - } - } + mSelectionStateChanger = std::make_unique< SelectionStateChanger > + ( GetSelectionState(), *mTracks ); // We create a NEW snap manager in case any snap-points have changed mSnapManager = std::make_unique(GetTracks(), mViewInfo); diff --git a/src/TrackPanel.h b/src/TrackPanel.h index e887a6f14..e948c8ab2 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -639,10 +639,9 @@ protected: bool mRefreshBacking; SelectedRegion mInitialSelection; - std::vector mInitialTrackSelection; SelectionState mSelectionState{}; SelectionState &GetSelectionState() { return mSelectionState; } - Track *mInitialLastPickedTrack {}; + std::unique_ptr mSelectionStateChanger{}; bool mSelStartValid; double mSelStart;