Audacity 3.2.0
CutlineHandle.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5CutlineHandle.cpp
6
7Paul Licameli split from TrackPanel.cpp
8
9**********************************************************************/
10
11
12#include "CutlineHandle.h"
13
14#include <wx/cursor.h>
15#include <wx/event.h>
16
17#include "../../../../HitTestResult.h"
18#include "ProjectAudioIO.h"
19#include "ProjectHistory.h"
20#include "../../../../RefreshCode.h"
21#include "Snap.h" // for kPixelTolerance
22#include "../../../../TrackPanelMouseEvent.h"
23#include "UndoManager.h"
24#include "ViewInfo.h"
25#include "WaveTrack.h"
26#include "../../../../../images/Cursors.h"
27
29 const std::shared_ptr<WaveTrack> &pTrack,
30 WaveTrackLocations locations, WaveTrackLocation location
31)
32 : mpTrack{ pTrack }
33 , mLocations{ move(locations) }
34 , mLocation{ location }
35{
36}
37
39{
40#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
42#endif
43}
44
46{
47 static auto disabledCursor =
48 ::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
49 static wxCursor arrowCursor{ wxCURSOR_ARROW };
50 return { XO("Left-Click to expand, Right-Click to remove"),
51 (unsafe ? &*disabledCursor : &arrowCursor) };
52}
53namespace
54{
55 bool IsOverCutline(const WaveTrackLocations &locations,
56 const ViewInfo &viewInfo,
57 const wxRect &rect, const wxMouseState &state,
58 WaveTrackLocation *pmLocation)
59 {
60 for (auto loc: locations) {
61 const double x = viewInfo.TimeToPosition(loc.pos);
62 if (x >= 0 && x < rect.width)
63 {
64 wxRect locRect;
65 locRect.width = 2 * kPixelTolerance - 1;
66 locRect.x = (int)(rect.x + x) - locRect.width / 2;
67 locRect.y = rect.y;
68 locRect.height = rect.height;
69 if (locRect.Contains(state.m_x, state.m_y))
70 {
71 if (pmLocation)
72 *pmLocation = loc;
73 return true;
74 }
75 }
76 }
77
78 return false;
79 }
80}
81
83 std::weak_ptr<CutlineHandle> &holder,
84 const wxMouseState &state, const wxRect &rect,
85 const AudacityProject *pProject,
86 std::shared_ptr<WaveTrack> pTrack)
87{
88 // Substitute the leader
89 if (!pTrack->GetOwner())
90 return {};
91 auto iter = pTrack->GetOwner()->Find(pTrack.get());
92 if (!*iter)
93 return {};
94 pTrack = (*iter)->SharedPointer<WaveTrack>();
95
96 auto &viewInfo = ViewInfo::Get(*pProject);
99
100 auto locations = FindWaveTrackLocations(*pTrack);
101 WaveTrackLocation location;
102 if (!IsOverCutline(locations, viewInfo, rect, state, &location))
103 return {};
104
105 auto result =
106 std::make_shared<CutlineHandle>(pTrack, move(locations), location);
107 result = AssignUIHandlePtr(holder, result);
108 return result;
109}
110
112{
113}
114
115std::shared_ptr<const Channel> CutlineHandle::FindChannel() const
116{
117 return mpTrack;
118}
119
121{
122 return true;
123}
124
126(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
127{
128 using namespace RefreshCode;
129 const bool unsafe = ProjectAudioIO::Get( *pProject ).IsAudioActive();
130 if ( unsafe )
131 return Cancelled;
132
133 const wxMouseEvent &event = evt.event;
134 auto &viewInfo = ViewInfo::Get( *pProject );
135
136 // Can affect the track by merging clips, expanding a cutline, or
137 // deleting a cutline.
138 // All the change is done at button-down. Button-up just commits the undo item.
139
141
142 // FIXME: Disable this and return true when CutLines aren't showing?
143 // (Don't use gPrefs-> for the fix as registry access is slow).
144
145 // Cutline data changed on either branch, so refresh the track display.
147
148 if (event.LeftDown())
149 {
151 mStartTime = viewInfo.selectedRegion.t0();
152 mEndTime = viewInfo.selectedRegion.t1();
153
154 // When user presses left button on cut line, expand the line again
155 double cutlineStart = 0, cutlineEnd = 0;
156 mpTrack->ExpandCutLine(mLocation.pos, &cutlineStart, &cutlineEnd);
157 viewInfo.selectedRegion.setTimes(cutlineStart, cutlineEnd);
158 }
159 else if (event.RightDown())
160 {
161 bool removed = mpTrack->RemoveCutLine(mLocation.pos);
162 if (!removed)
163 // Nothing happened, make no Undo item
164 return Cancelled;
166 }
167 else
168 result = RefreshNone;
169
170 return result;
171}
172
175{
177}
178
180(const TrackPanelMouseState &, AudacityProject *pProject)
181{
182 const bool unsafe = ProjectAudioIO::Get( *pProject ).IsAudioActive();
183 return HitPreview( unsafe );
184}
185
187(const TrackPanelMouseEvent &, AudacityProject *pProject, wxWindow *)
188{
190
191 // Only now commit the result to the undo stack
192 switch (mOperation) {
193 default:
194 wxASSERT(false);
195 case Expand:
196 ProjectHistory::Get( *pProject )
197 .PushState(XO("Expanded Cut Line"), XO("Expand"));
198 break;
199 case Remove:
200 ProjectHistory::Get( *pProject )
201 .PushState(XO("Removed Cut Line"), XO("Remove"));
202 break;
203 }
204
205 // Nothing to do for the display
206 return result;
207}
208
210{
211 using namespace RefreshCode;
213 ProjectHistory::Get( *pProject ).RollbackState();
214 if (mOperation == Expand) {
215 AudacityProject &project = *pProject;
216 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
217 selectedRegion.setTimes( mStartTime, mEndTime );
218 }
219 return result;
220}
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
XO("Cut/Copy/Paste")
const int kPixelTolerance
Definition: Snap.h:28
const auto project
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:188
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:159
WaveTrackLocations FindWaveTrackLocations(const WaveTrack &track)
std::vector< WaveTrackLocation > WaveTrackLocations
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Operation mOperation
Definition: CutlineHandle.h:72
CutlineHandle(const CutlineHandle &)=delete
std::shared_ptr< const Channel > FindChannel() const override
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
WaveTrackLocation mLocation
Definition: CutlineHandle.h:75
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
std::shared_ptr< WaveTrack > mpTrack
Definition: CutlineHandle.h:70
static UIHandlePtr HitTest(std::weak_ptr< CutlineHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, std::shared_ptr< WaveTrack > pTrack)
virtual ~CutlineHandle()
double mStartTime
Definition: CutlineHandle.h:73
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
static HitTestPreview HitPreview(bool unsafe)
void Enter(bool forward, AudacityProject *) override
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Result Cancel(AudacityProject *pProject) override
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:51
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
Result mChangeHighlight
Definition: UIHandle.h:147
unsigned Result
Definition: UIHandle.h:39
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:215
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
A Track that contains audio waveform data.
Definition: WaveTrack.h:222
int64 TimeToPosition(double time, int64 origin=0, bool ignoreFisheye=false) const
STM: Converts a project time to screen x position.
Definition: ZoomInfo.cpp:44
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
bool IsOverCutline(const WaveTrackLocations &locations, const ViewInfo &viewInfo, const wxRect &rect, const wxMouseState &state, WaveTrackLocation *pmLocation)