Audacity 3.2.0
TimeShiftHandle.h
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5TimeShiftHandle.h
6
7Paul Licameli
8
9**********************************************************************/
10
11#ifndef __AUDACITY_TIMESHIFT_HANDLE__
12#define __AUDACITY_TIMESHIFT_HANDLE__
13
14#include <functional>
15#include <unordered_map>
16#include <vector>
17
19#include "../../UIHandle.h"
20
22class SnapManager;
23class Track;
24using TrackArray = std::vector<Track*>;
25class TrackList;
26
27class Track;
28
29class ViewInfo;
30class wxMouseState;
31
33class AUDACITY_DLL_API TrackShifter {
34public:
36 TrackShifter(const TrackShifter&) = delete;
38
39 virtual ~TrackShifter() = 0;
41
44 virtual Track &GetTrack() const = 0;
45
47 enum class HitTestResult {
48 Miss,
49 Selection,
50 Intervals,
51 Track
52 };
53
56 wxRect rect;
57 wxCoord xx, yy;
58 };
59
61
67 double time,
68 const ViewInfo &viewInfo,
69 HitTestParams *pParams = nullptr
70 ) = 0;
71
72 using Intervals = std::vector<std::shared_ptr<ChannelGroupInterval>>;
73
75 const Intervals &FixedIntervals() const { return mFixed; }
76
78 const Intervals &MovingIntervals() const { return mMoving; }
79
81 void UnfixIntervals(std::function<bool(const ChannelGroupInterval&)> pred);
82
84 void UnfixAll();
85
87
88 virtual void SelectInterval(const ChannelGroupInterval &interval);
89
91 virtual bool SyncLocks() = 0;
92
94
101 virtual double HintOffsetLarger( double desiredOffset );
102
104
105 virtual double QuantizeOffset( double desiredOffset );
106
108
114 virtual double AdjustOffsetSmaller( double desiredOffset );
115
118
122 virtual bool MayMigrateTo(Track &otherTrack);
123
125
128 virtual Intervals Detach();
129
132
133 virtual bool AdjustFit(
134 const Track &otherTrack,
135 const Intervals &intervals,
138 double &desiredOffset,
139 double tolerance
141 );
142
144
152 virtual bool Attach(Intervals intervals, double offset);
153
155
160 virtual bool FinishMigration();
161
164 virtual void DoHorizontalOffset( double offset );
165
166 // This function is used by the keyboard interface for time shifting.
167 // It adjusts t0 after the move to take into account
168 // any rounding errors if this is necessary.
169 virtual double AdjustT0(double t0) const;
170
171protected:
173 void CommonSelectInterval(const ChannelGroupInterval &interval);
174
182 bool CommonMayMigrateTo(Track &otherTrack);
183
185
186 void InitIntervals();
187
188 bool AllFixed() const {
189 return mAllFixed && mMoving.empty();
190 }
191
194
195private:
196 bool mAllFixed = true;
198};
199
202class CoarseTrackShifter final : public TrackShifter {
203public:
209 Track &GetTrack() const override { return *mpTrack; }
210
211 HitTestResult HitTest(double, const ViewInfo&, HitTestParams*) override;
212
214 bool SyncLocks() override;
215
216private:
217 const std::shared_ptr<Track> mpTrack;
218};
219
220struct MakeTrackShifterTag;
222
226 MakeTrackShifterTag, std::unique_ptr<TrackShifter>, Track, AudacityProject&>;
228
229class ViewInfo;
230
231struct AUDACITY_DLL_API ClipMoveState {
232 ClipMoveState() = default;
233
234 ClipMoveState(const ClipMoveState&) = delete;
235 ClipMoveState& operator =(const ClipMoveState&) = delete;
236
238 ClipMoveState& operator =(ClipMoveState&&) = default;
239
240 using ShifterMap = std::unordered_map<Track*, std::unique_ptr<TrackShifter>>;
241
243
246 void Init(
248 Track &capturedTrack, //<! pHit if not null associates with this track
249 TrackShifter::HitTestResult hitTestResult,
250 std::unique_ptr<TrackShifter> pHit,
252 double clickTime,
253 const ViewInfo &viewInfo,
254 TrackList &trackList, bool syncLocked);
255
257
258 const ChannelGroupInterval *CapturedInterval() const;
259
261
262 double DoSlideHorizontal(double desiredSlideAmount);
263
265 void DoHorizontalOffset(double offset);
266
267 // This should be a leader track when not null
268 std::shared_ptr<Track> mCapturedTrack;
269
270 bool initialized{ false };
271 bool movingSelection {};
272 bool wasMoved{ false };
273 double hSlideAmount {};
278 wxInt64 snapLeft { -1 }, snapRight { -1 };
279
280 int mMouseClickX{};
281
282 void clear()
283 {
284 initialized = false;
285 wasMoved = false;
286 movingSelection = false;
287 hSlideAmount = 0;
288 shifters.clear();
289 snapLeft = snapRight = -1;
290 mMouseClickX = 0;
291 }
292};
293
294class AUDACITY_DLL_API TimeShiftHandle : public UIHandle
295{
298 (const AudacityProject *pProject, bool unsafe);
299
300public:
301 TimeShiftHandle(std::shared_ptr<Track> pTrack, bool gripHit);
302
304
305 bool IsGripHit() const { return mGripHit; }
306
307 static UIHandlePtr HitAnywhere(
308 std::weak_ptr<TimeShiftHandle> &holder,
309 const std::shared_ptr<Track> &pTrack, bool gripHit);
310 static UIHandlePtr HitTest(
311 std::weak_ptr<TimeShiftHandle> &holder,
312 const wxMouseState &state, const wxRect &rect,
313 const std::shared_ptr<Track> &pTrack);
314
315 virtual ~TimeShiftHandle();
316
317 void Enter(bool forward, AudacityProject *) override;
318
319 Result Click(
320 const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
321
322 Result Drag(
323 const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
324
325 HitTestPreview Preview(
326 const TrackPanelMouseState &state, AudacityProject *pProject)
327 override;
328
330 const TrackPanelMouseEvent &event, AudacityProject *pProject,
331 wxWindow *pParent) override;
332
333 Result Cancel(AudacityProject *pProject) override;
334
335 bool StopsOnKeystroke() override { return true; }
336
337 bool Clicked() const;
338
339protected:
343 std::shared_ptr<Track> GetTrack() const;
344 //There were attempt to move clip/track horizontally, or to move it vertically
345 bool WasMoved() const;
346private:
347
348 // Try to move clips from one track to another with offset, allowing 1px tolerance,
349 // that will move intervals and reset the origin
350 void DoSlideVertical(
351 ViewInfo &viewInfo, wxCoord xx,
352 TrackList &trackList, Track *dstTrack, double& desiredSlideAmount);
353
354 // TrackPanelDrawable implementation
355 void Draw(
357 const wxRect &rect, unsigned iPass ) override;
358
359 wxRect DrawingArea(
361 const wxRect &rect, const wxRect &panelRect, unsigned iPass ) override;
362
363 wxRect mRect{};
364
365 bool mDidSlideVertically{};
366 bool mSlideUpDownOnly{};
367
368 bool mSnapPreferRightEdge{};
369
370 // Handles snapping the selection boundaries or track boundaries to
371 // line up with existing tracks or labels. mSnapLeft and mSnapRight
372 // are the horizontal index of pixels to display user feedback
373 // guidelines so the user knows when such snapping is taking place.
374 std::shared_ptr<SnapManager> mSnapManager{};
375
376 ClipMoveState mClipMoveState{};
377 bool mGripHit {};
378};
379
380#endif
Utility for non-intrusive definition of a new method on a base class.
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
const auto project
std::vector< Track * > TrackArray
DECLARE_EXPORTED_ATTACHED_VIRTUAL(AUDACITY_DLL_API, MakeTrackShifter)
Class template generates single-dispatch, open method registry tables.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
A start and an end time, and whatever else subclasses associate with them.
Definition: Channel.h:30
CoarseTrackShifter(Track &track)
bool SyncLocks() override
Returns false.
Track & GetTrack() const override
There is always an associated track.
const std::shared_ptr< Track > mpTrack
~CoarseTrackShifter() override
HitTestResult HitTest(double, const ViewInfo &, HitTestParams *) override
Decide how shift behaves, based on the track that is clicked in.
TimeShiftHandle(const TimeShiftHandle &)=delete
bool StopsOnKeystroke() override
bool IsGripHit() const
TimeShiftHandle & operator=(TimeShiftHandle &&)=default
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:123
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:987
Abstract base class for policies to manipulate a track type for Time Shift.
Intervals mFixed
virtual Track & GetTrack() const =0
There is always an associated track.
virtual HitTestResult HitTest(double time, const ViewInfo &viewInfo, HitTestParams *pParams=nullptr)=0
Decide how shift behaves, based on the track that is clicked in.
bool AllFixed() const
const Intervals & MovingIntervals() const
Return special intervals of the track that may move.
virtual ~TrackShifter()=0
HitTestResult
Possibilities for HitTest on the clicked track.
virtual bool SyncLocks()=0
Whether unfixing of an interval should propagate to all overlapping intervals in the sync lock group.
TrackShifter(const TrackShifter &)=delete
const Intervals & FixedIntervals() const
Return special intervals of the track that will not move.
TrackShifter & operator=(const TrackShifter &)=delete
Intervals mMoving
std::vector< std::shared_ptr< ChannelGroupInterval > > Intervals
Short-lived drawing and event-handling object associated with a TrackPanelCell.
Definition: UIHandle.h:35
void Release(wxWindow *handler)
AUDACITY_DLL_API HitTestPreview HitPreview(const wxMouseState &state)
Track & GetTrack(Channel &channel)
void SelectInterval(AudacityProject &project, const WaveTrack::Interval &interval)
ClipMoveState(const ClipMoveState &)=delete
ClipMoveState(ClipMoveState &&)=default
ClipMoveState()=default
ShifterMap shifters
std::unordered_map< Track *, std::unique_ptr< TrackShifter > > ShifterMap
std::shared_ptr< Track > mCapturedTrack
Optional, more complete information for hit testing.