From d8a894b95b60c3dfa578bf856e2c81030fa75de9 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 9 Sep 2020 05:10:23 -0400 Subject: [PATCH] Define TrackShifter, subclasses, factory method; collect them... ... in TimeShiftHandle. They do nothing useful yet, but responsibilities will shift into them. TypeSwitch is avoided and the subclasses are defined in appropriate places for dependency management, thanks to AttachedVirtualFunction. --- .../notetrack/ui/NoteTrackView.cpp | 23 ++++++++++++ .../wavetrack/ui/WaveTrackView.cpp | 21 +++++++++++ src/tracks/ui/TimeShiftHandle.cpp | 29 ++++++++++++++- src/tracks/ui/TimeShiftHandle.h | 35 ++++++++++++++++++- 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp index 655d2631d..09f4dc42f 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp @@ -729,4 +729,27 @@ void NoteTrackView::Draw( } CommonTrackView::Draw( context, rect, iPass ); } + +#include "../../../ui/TimeShiftHandle.h" + +class NoteTrackShifter final : public TrackShifter { +public: + NoteTrackShifter( NoteTrack &track ) + : mpTrack{ track.SharedPointer() } + {} + ~NoteTrackShifter() override {} + Track &GetTrack() const override { return *mpTrack; } + +private: + std::shared_ptr mpTrack; +}; + +using MakeNoteTrackShifter = MakeTrackShifter::Override; +template<> template<> auto MakeNoteTrackShifter::Implementation() -> Function { + return [](NoteTrack &track) { + return std::make_unique(track); + }; +} +static MakeNoteTrackShifter registerMakeNoteTrackShifter; + #endif diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp index 892a1b1cf..8739a62dd 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp @@ -1301,3 +1301,24 @@ void WaveTrackView::Draw( CommonTrackView::Draw( context, rect, iPass ); } + +class WaveTrackShifter final : public TrackShifter { +public: + WaveTrackShifter( WaveTrack &track ) + : mpTrack{ track.SharedPointer() } + { + } + ~WaveTrackShifter() override {} + Track &GetTrack() const override { return *mpTrack; } + +private: + std::shared_ptr mpTrack; +}; + +using MakeWaveTrackShifter = MakeTrackShifter::Override; +template<> template<> auto MakeWaveTrackShifter::Implementation() -> Function { + return [](WaveTrack &track) { + return std::make_unique(track); + }; +} +static MakeWaveTrackShifter registerMakeWaveTrackShifter; diff --git a/src/tracks/ui/TimeShiftHandle.cpp b/src/tracks/ui/TimeShiftHandle.cpp index 17ebcc2a7..acc58dbd9 100644 --- a/src/tracks/ui/TimeShiftHandle.cpp +++ b/src/tracks/ui/TimeShiftHandle.cpp @@ -244,6 +244,20 @@ namespace } } +TrackShifter::~TrackShifter() = default; + +CoarseTrackShifter::CoarseTrackShifter( Track &track ) + : mpTrack{ track.SharedPointer() } +{} + +CoarseTrackShifter::~CoarseTrackShifter() = default; + +template<> auto MakeTrackShifter::Implementation() -> Function { + return [](Track &track) { + return std::make_unique(track); + }; +} + void TimeShiftHandle::CreateListOfCapturedClips ( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack, TrackList &trackList, bool syncLocked, double clickTime ) @@ -456,6 +470,8 @@ UIHandle::Result TimeShiftHandle::Click bool ok = true; bool captureClips = false; + auto pShifter = MakeTrackShifter::Call( *pTrack ); + if (!event.ShiftDown()) pTrack->TypeSwitch( [&](WaveTrack *wt) { @@ -474,10 +490,21 @@ UIHandle::Result TimeShiftHandle::Click if ( ! ok ) return Cancelled; - else if ( captureClips ) + + if ( captureClips ) { + mClipMoveState.shifters[pTrack] = std::move( pShifter ); + + // Collect TrackShifters for the rest of the tracks + for ( auto track : trackList.Any() ) { + auto &pShifter = mClipMoveState.shifters[track]; + if (!pShifter) + pShifter = MakeTrackShifter::Call( *track ); + } + CreateListOfCapturedClips( mClipMoveState, viewInfo, *pTrack, trackList, ProjectSettings::Get( *pProject ).IsSyncLocked(), clickTime ); + } mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive; mRect = rect; diff --git a/src/tracks/ui/TimeShiftHandle.h b/src/tracks/ui/TimeShiftHandle.h index 7c3ec0c0a..8e68354ba 100644 --- a/src/tracks/ui/TimeShiftHandle.h +++ b/src/tracks/ui/TimeShiftHandle.h @@ -11,12 +11,41 @@ Paul Licameli #ifndef __AUDACITY_TIMESHIFT_HANDLE__ #define __AUDACITY_TIMESHIFT_HANDLE__ +#include + +#include "../../AttachedVirtualFunction.h" #include "../../UIHandle.h" class SnapManager; class Track; using TrackArray = std::vector; class TrackList; + +class Track; + +//! Abstract base class for policies to manipulate a track type with the Time Shift tool +class TrackShifter { +public: + virtual ~TrackShifter() = 0; + //! There is always an associated track + virtual Track &GetTrack() const = 0; +}; + +//! Used in default of other reimplementations to shift any track as a whole, invoking Track::Offset() +class CoarseTrackShifter final : public TrackShifter { +public: + CoarseTrackShifter( Track &track ); + ~CoarseTrackShifter() override; + Track &GetTrack() const override { return *mpTrack; } + +private: + std::shared_ptr mpTrack; +}; + +struct MakeTrackShifterTag; +using MakeTrackShifter = AttachedVirtualFunction< + MakeTrackShifterTag, std::unique_ptr, Track>; + class ViewInfo; class WaveClip; class WaveTrack; @@ -40,12 +69,15 @@ public: using TrackClipArray = std::vector ; struct ClipMoveState { + using ShifterMap = std::unordered_map>; + // non-NULL only if click was in a WaveTrack and without Shift key: WaveClip *capturedClip {}; bool capturedClipIsSelection {}; TrackArray trackExclusions {}; double hSlideAmount {}; + ShifterMap shifters; TrackClipArray capturedClipArray {}; wxInt64 snapLeft { -1 }, snapRight { -1 }; @@ -57,6 +89,7 @@ struct ClipMoveState { capturedClipIsSelection = false; trackExclusions.clear(); hSlideAmount = 0; + shifters.clear(); capturedClipArray.clear(); snapLeft = snapRight = -1; mMouseClickX = 0; @@ -73,7 +106,7 @@ public: explicit TimeShiftHandle ( const std::shared_ptr &pTrack, bool gripHit ); - TimeShiftHandle &operator=(const TimeShiftHandle&) = default; + TimeShiftHandle &operator=(TimeShiftHandle&&) = default; bool IsGripHit() const { return mGripHit; } std::shared_ptr GetTrack() const { return mCapturedTrack; }