diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp index cab71a70f..d0c0ab732 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp @@ -1440,6 +1440,15 @@ public: return true; } + void DoHorizontalOffset( double offset ) override + { + for ( auto &interval : MovingIntervals() ) { + auto data = + static_cast( interval.Extra() ); + data->GetClip()->Offset( offset ); + } + } + private: std::shared_ptr mpTrack; diff --git a/src/tracks/ui/TimeShiftHandle.cpp b/src/tracks/ui/TimeShiftHandle.cpp index cad59810f..8b363c7e1 100644 --- a/src/tracks/ui/TimeShiftHandle.cpp +++ b/src/tracks/ui/TimeShiftHandle.cpp @@ -178,22 +178,17 @@ namespace return 0; } +} - void DoOffset( ClipMoveState &state, Track *pTrack, double offset ) - { - auto &clips = state.capturedClipArray; - if ( !clips.empty() ) { - for (auto &clip : clips) { - if (clip.clip) - clip.clip->Offset( offset ); - else - clip.track->Offset( offset ); - } - } - else if ( pTrack ) - // Was a shift-click - for (auto channel : TrackList::Channels( pTrack )) - channel->Offset( offset ); +void ClipMoveState::DoHorizontalOffset( double offset ) +{ + if ( !shifters.empty() ) { + for ( auto &pair : shifters ) + pair.second->DoHorizontalOffset( offset ); + } + else { + for (auto channel : TrackList::Channels( mCapturedTrack.get() )) + channel->Offset( offset ); } } @@ -206,6 +201,7 @@ void TrackShifter::UnfixIntervals( if ( pred( *iter) ) { mMoving.push_back( std::move( *iter ) ); iter = mFixed.erase( iter ); + mAllFixed = false; } else ++iter; @@ -216,6 +212,7 @@ void TrackShifter::UnfixAll() { std::move( mFixed.begin(), mFixed.end(), std::back_inserter(mMoving) ); mFixed = Intervals{}; + mAllFixed = false; } void TrackShifter::SelectInterval( const TrackInterval & ) @@ -303,6 +300,12 @@ bool TrackShifter::FinishMigration() return true; } +void TrackShifter::DoHorizontalOffset( double offset ) +{ + if (!AllFixed()) + GetTrack().Offset( offset ); +} + void TrackShifter::InitIntervals() { mMoving.clear(); @@ -548,14 +551,12 @@ double ClipMoveState::DoSlideHorizontal( double desiredSlideAmount ) break; } } while ( desiredSlideAmount != initialAllowed ); - - // finally, here is where clips are moved - if ( desiredSlideAmount != 0.0 ) - DoOffset( state, nullptr, desiredSlideAmount ); } - else - // Moving whole track - DoOffset( state, &capturedTrack, desiredSlideAmount ); + + // Whether moving intervals or a whole track, + // finally, here is where clips are moved + if ( desiredSlideAmount != 0.0 ) + state.DoHorizontalOffset( desiredSlideAmount ); return (state.hSlideAmount = desiredSlideAmount); } @@ -957,8 +958,7 @@ UIHandle::Result TimeShiftHandle::Drag // Start by undoing the current slide amount; everything // happens relative to the original horizontal position of // each clip... - DoOffset( - mClipMoveState, mClipMoveState.mCapturedTrack.get(), -mClipMoveState.hSlideAmount ); + mClipMoveState.DoHorizontalOffset( -mClipMoveState.hSlideAmount ); if ( mClipMoveState.movingSelection ) { // Slide the selection, too diff --git a/src/tracks/ui/TimeShiftHandle.h b/src/tracks/ui/TimeShiftHandle.h index 18d61dbca..8a553e2a8 100644 --- a/src/tracks/ui/TimeShiftHandle.h +++ b/src/tracks/ui/TimeShiftHandle.h @@ -122,6 +122,10 @@ public: Default implementation does nothing and returns true */ virtual bool FinishMigration(); + //! Shift all moving intervals horizontally + //! Default moves the whole track, provided `!AllFixed()`; else does nothing + virtual void DoHorizontalOffset( double offset ); + protected: /*! Unfix any of the intervals that intersect the given one; may be useful to override `SelectInterval()` */ void CommonSelectInterval( const TrackInterval &interval ); @@ -135,8 +139,16 @@ protected: /*! This can't be called by the base class constructor, when GetTrack() isn't yet callable */ void InitIntervals(); + bool AllFixed() const { + return mAllFixed && mMoving.empty(); + } + Intervals mFixed; Intervals mMoving; + +private: + bool mAllFixed = true; /*!< + Becomes false after `UnfixAll()`, even if there are no intervals, or if any one interval was unfixed */ }; //! Used in default of other reimplementations to shift any track as a whole, invoking Track::Offset() @@ -196,9 +208,13 @@ struct ClipMoveState { /*! Pointer may be invalidated by operations on the associated TrackShifter */ const TrackInterval *CapturedInterval() const; + //! Do sliding of tracks and intervals, maybe adjusting the offset /*! @return actual slide amount, maybe adjusted toward zero from desired */ double DoSlideHorizontal( double desiredSlideAmount ); + //! Offset tracks or intervals horizontally, without adjusting the offset + void DoHorizontalOffset( double offset ); + std::shared_ptr mCapturedTrack; // non-NULL only if click was in a WaveTrack and without Shift key: