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 virtual Track &GetTrack() const = 0;
42
44 enum class HitTestResult {
45 Miss,
46 Selection,
47 Intervals,
48 Track
49 };
50
53 wxRect rect;
54 wxCoord xx, yy;
55 };
56
58
64 double time,
65 const ViewInfo &viewInfo,
66 HitTestParams *pParams = nullptr
67 ) = 0;
68
69 using Intervals = std::vector<std::shared_ptr<ChannelGroupInterval>>;
70
72 const Intervals &FixedIntervals() const { return mFixed; }
73
75 const Intervals &MovingIntervals() const { return mMoving; }
76
78 void UnfixIntervals(std::function<bool(const ChannelGroupInterval&)> pred);
79
81 void UnfixAll();
82
84
87 struct TimeInterval {
88 TimeInterval(double start, double end)
89 : mStart{ start }, mEnd{ std::max(start, end) }
90 {}
91
92 double Start() const { return mStart; }
93 double End() const { return mEnd; }
94 private:
95 const double mStart;
96 const double mEnd;
97 };
98
100
101 virtual void SelectInterval(TimeInterval interval);
102
104 virtual bool SyncLocks() = 0;
105
107
114 virtual double HintOffsetLarger( double desiredOffset );
115
117
118 virtual double QuantizeOffset( double desiredOffset );
119
121
127 virtual double AdjustOffsetSmaller( double desiredOffset );
128
131
134 virtual bool MayMigrateTo(Track &otherTrack);
135
137
140 virtual Intervals Detach();
141
144
145 virtual bool AdjustFit(
146 const Track &otherTrack,
147 const Intervals &intervals,
150 double &desiredOffset,
151 double tolerance
153 );
154
156
164 virtual bool Attach(Intervals intervals, double offset);
165
167
172 virtual bool FinishMigration();
173
176 virtual void DoHorizontalOffset( double offset );
177
178 // This function is used by the keyboard interface for time shifting.
179 // It adjusts t0 after the move to take into account
180 // any rounding errors if this is necessary.
181 virtual double AdjustT0(double t0) const;
182
183protected:
185 void CommonSelectInterval(TimeInterval interval);
186
193 bool CommonMayMigrateTo(Track &otherTrack);
194
196
197 void InitIntervals();
198
199 bool AllFixed() const {
200 return mAllFixed && mMoving.empty();
201 }
202
205
206private:
207 bool mAllFixed = true;
209};
210
213class CoarseTrackShifter final : public TrackShifter {
214public:
217 Track &GetTrack() const override { return *mpTrack; }
218
219 HitTestResult HitTest(double, const ViewInfo&, HitTestParams*) override;
220
222 bool SyncLocks() override;
223
224private:
225 const std::shared_ptr<Track> mpTrack;
226};
227
228struct MakeTrackShifterTag;
231 MakeTrackShifterTag, std::unique_ptr<TrackShifter>, Track, AudacityProject&>;
233
234class ViewInfo;
235
236struct AUDACITY_DLL_API ClipMoveState {
237 ClipMoveState() = default;
238
239 ClipMoveState(const ClipMoveState&) = delete;
240 ClipMoveState& operator =(const ClipMoveState&) = delete;
241
243 ClipMoveState& operator =(ClipMoveState&&) = default;
244
245 using ShifterMap = std::unordered_map<Track*, std::unique_ptr<TrackShifter>>;
246
248 void Init(
250 Track &capturedTrack, //<! pHit if not null associates with this track
251 TrackShifter::HitTestResult hitTestResult,
252 std::unique_ptr<TrackShifter> pHit,
254 double clickTime,
255 const ViewInfo &viewInfo,
256 TrackList &trackList, bool syncLocked);
257
259
260 const ChannelGroupInterval *CapturedInterval() const;
261
263
264 double DoSlideHorizontal(double desiredSlideAmount);
265
267 void DoHorizontalOffset(double offset);
268
269 std::shared_ptr<Track> mCapturedTrack;
270
271 bool initialized{ false };
272 bool movingSelection {};
273 bool wasMoved{ false };
274 double hSlideAmount {};
276 wxInt64 snapLeft { -1 }, snapRight { -1 };
277
278 int mMouseClickX{};
279
280 void clear()
281 {
282 initialized = false;
283 wasMoved = false;
284 movingSelection = false;
285 hSlideAmount = 0;
286 shifters.clear();
287 snapLeft = snapRight = -1;
288 mMouseClickX = 0;
289 }
290};
291
292class AUDACITY_DLL_API TimeShiftHandle : public UIHandle
293{
296 (const AudacityProject *pProject, bool unsafe);
297
298public:
299 TimeShiftHandle(std::shared_ptr<Track> pTrack, bool gripHit);
300
302
303 bool IsGripHit() const { return mGripHit; }
304
305 static UIHandlePtr HitAnywhere(
306 std::weak_ptr<TimeShiftHandle> &holder,
307 const std::shared_ptr<Track> &pTrack, bool gripHit);
308 static UIHandlePtr HitTest(
309 std::weak_ptr<TimeShiftHandle> &holder,
310 const wxMouseState &state, const wxRect &rect,
311 const std::shared_ptr<Track> &pTrack);
312
313 virtual ~TimeShiftHandle();
314
315 std::shared_ptr<const Track> FindTrack() const override;
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
339 std::shared_ptr<Track> GetTrack() const;
340
341protected:
342 //There were attempt to move clip/track horizontally, or to move it vertically
343 bool WasMoved() const;
344
345private:
346
347 // Try to move clips from one track to another with offset, allowing 1px tolerance,
348 // that will move intervals and reset the origin
349 void DoSlideVertical(
350 ViewInfo &viewInfo, wxCoord xx,
351 TrackList &trackList, Track *dstTrack, double& desiredSlideAmount);
352
353 // TrackPanelDrawable implementation
354 void Draw(
356 const wxRect &rect, unsigned iPass ) override;
357
358 wxRect DrawingArea(
360 const wxRect &rect, const wxRect &panelRect, unsigned iPass ) override;
361
362 wxRect mRect{};
363
364 bool mDidSlideVertically{};
365 bool mSlideUpDownOnly{};
366
367 bool mSnapPreferRightEdge{};
368
369 // Handles snapping the selection boundaries or track boundaries to
370 // line up with existing tracks or labels. mSnapLeft and mSnapRight
371 // are the horizontal index of pixels to display user feedback
372 // guidelines so the user knows when such snapping is taking place.
373 std::shared_ptr<SnapManager> mSnapManager{};
374
375 ClipMoveState mClipMoveState{};
376 bool mGripHit {};
377};
378
379#endif
Utility for non-intrusive definition of a new method on a base class.
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
@ Cancel
Open was cancelled by the extension.
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:29
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:110
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:850
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:37
void Release(wxWindow *handler)
bool HitTest(const RectangleArgs &args, const wxPoint &mousePos)
AUDACITY_DLL_API HitTestPreview HitPreview(const bool bVZoom)
void SelectInterval(AudacityProject &project, const WaveTrack::Interval &interval)
std::shared_ptr< Track > FindTrack(TrackPanelCell *pCell)
Definition: TrackPanel.cpp:538
Track & GetTrack(Channel &channel)
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
STL namespace.
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.
A simple time interval.
TimeInterval(double start, double end)