14#include "../lib-src/header-substitutes/allegro.h"
18#include "../../../ui/CommonTrackPanelCell.h"
19#include "../../../../HitTestResult.h"
20#include "../../../../NoteTrack.h"
23#include "../../../../RefreshCode.h"
25#include "../../../../TrackPanelMouseEvent.h"
28#include "../../../../../images/Cursors.h"
34(
const std::shared_ptr<NoteTrack> &pTrack,
const StretchState &stretchState )
36 , mStretchState{ stretchState }
41 static auto disabledCursor =
42 ::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
43 static auto stretchLeftCursor =
44 ::MakeCursor(wxCURSOR_BULLSEYE, StretchLeftCursorXpm, 16, 16);
45 static auto stretchRightCursor =
46 ::MakeCursor(wxCURSOR_BULLSEYE, StretchRightCursorXpm, 16, 16);
47 static auto stretchCursor =
48 ::MakeCursor(wxCURSOR_BULLSEYE, StretchCursorXpm, 16, 16);
51 return { {}, &*disabledCursor };
54 wxCursor *pCursor = NULL;
55 switch (stretchMode) {
59 pCursor = &*stretchLeftCursor;
break;
61 pCursor = &*stretchCursor;
break;
63 pCursor = &*stretchRightCursor;
break;
66 XO(
"Click and drag to stretch selected region."),
73(std::weak_ptr<StretchHandle> &holder,
75 const std::shared_ptr<NoteTrack> &pTrack)
78 const wxMouseState &state = st.
state;
85 if (!pTrack || !pTrack->GetSelected())
88 const wxRect &rect = st.
rect;
89 int center = rect.y + rect.height / 2;
90 int distance = abs(state.m_y - center);
91 const int yTolerance = 10;
92 wxInt64 leftSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t0(), rect.x);
93 wxInt64 rightSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t1(), rect.x);
95 wxASSERT(!(rightSel < leftSel));
96 if (!(leftSel <= state.m_x && state.m_x <= rightSel &&
97 distance < yTolerance))
101 static const double minPeriod = 0.05;
104 auto t0 =
GetT0(*pTrack, viewInfo);
105 auto t1 =
GetT1(*pTrack, viewInfo);
110 stretchState.
mBeat0 = pTrack->NearestBeatTime( t0 );
113 stretchState.
mBeat1 = pTrack->NearestBeatTime( t1 );
119 stretchState.
mBeat1.second, 0.9 ) ||
120 ( stretchState.
mBeat1.first - stretchState.
mBeat0.first ) /
121 ( stretchState.
mBeat1.second - stretchState.
mBeat0.second )
125 auto selStart = viewInfo.PositionToTime( state.m_x, rect.x );
126 selStart = std::max(t0,
std::min(t1, selStart));
127 stretchState.
mBeatCenter = pTrack->NearestBeatTime( selStart );
133 stretchState.
mBeat1.second - stretchState.
mBeat0.second;
139 stretchState.
mBeat1.second - stretchState.
mBeat0.second;
150 auto result = std::make_shared<StretchHandle>( pTrack, stretchState );
167 const wxMouseEvent &
event = evt.
event;
169 if (event.LeftDClick() ||
178 viewInfo.selectedRegion.setTimes
198 const wxMouseEvent &
event = evt.
event;
199 const int x =
event.m_x;
201 Track *clickedTrack=
nullptr;
206 if (clickedTrack ==
nullptr &&
mpTrack !=
nullptr)
237 if ( track !=
mpTrack.get() ) {
240 auto diff = viewInfo.selectedRegion.t0() - origT0;
242 track->SyncLockAdjust( origT0 + diff, origT0 );
244 track->SyncLockAdjust( origT0, origT0 - diff );
245 track->Offset( diff );
249 auto diff = viewInfo.selectedRegion.t1() - origT1;
250 track->SyncLockAdjust( origT1, origT1 + diff );
289 if (pTrack == NULL &&
mpTrack != NULL)
294 std::max(0.0, viewInfo.PositionToTime(mouseXCoordinate, trackLeftEdge));
296 double dur, left_dur, right_dur;
300 double minPeriod = 0.05;
313 pNt->
Offset( moveto - t0 );
315 viewInfo.selectedRegion.setT0(moveto);
324 viewInfo.selectedRegion.setT1(moveto);
329 moveto = std::max(t0,
std::min(t1, moveto));
330 left_dur = moveto - t0;
331 right_dur = t1 - moveto;
std::shared_ptr< UIHandle > UIHandlePtr
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
bool within(A a, B b, DIST d)
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
A Track that is used for Midi notes. (Somewhat old code).
bool StretchRegion(QuantizedTimeAndBeat t0, QuantizedTimeAndBeat t1, double newDur)
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
StretchState mStretchState
static double GetT0(const Track &track, const ViewInfo &viewInfo)
std::shared_ptr< NoteTrack > mpTrack
static double GetT1(const Track &track, const ViewInfo &viewInfo)
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
void Stretch(AudacityProject *pProject, int mouseXCoordinate, int trackLeftEdge, Track *pTrack)
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
StretchHandle(const StretchHandle &)
static HitTestPreview HitPreview(StretchEnum stretchMode, bool unsafe)
static UIHandlePtr HitTest(std::weak_ptr< StretchHandle > &holder, const TrackPanelMouseState &state, const AudacityProject *pProject, const std::shared_ptr< NoteTrack > &pTrack)
Result Cancel(AudacityProject *pProject) override
static TrackIterRange< Track > Group(Track *pTrack)
bool IsSyncLocked() const
static SyncLockState & Get(AudacityProject &project)
Abstract base class for an object holding data associated with points on a time axis.
virtual double GetStartTime() const =0
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
virtual double GetEndTime() const =0
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
Namespace containing an enum 'what to do on a refresh?'.
std::shared_ptr< Track > FindTrack(TrackPanelCell *pCell)
QuantizedTimeAndBeat mBeatCenter
QuantizedTimeAndBeat mBeat0
double mOrigSel1Quantized
QuantizedTimeAndBeat mBeat1
double mOrigSel0Quantized
std::shared_ptr< TrackPanelCell > pCell