Audacity  3.0.3
CutlineHandle.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 CutlineHandle.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 
12 #include "CutlineHandle.h"
13 
14 #include "../../../../HitTestResult.h"
15 #include "../../../../ProjectAudioIO.h"
16 #include "../../../../ProjectHistory.h"
17 #include "../../../../RefreshCode.h"
18 #include "../../../../Snap.h" // for kPixelTolerance
19 #include "../../../../TrackPanelMouseEvent.h"
20 #include "../../../../UndoManager.h"
21 #include "ViewInfo.h"
22 #include "../../../../WaveTrack.h"
23 #include "../../../../../images/Cursors.h"
24 
26 ( const std::shared_ptr<WaveTrack> &pTrack, WaveTrackLocation location )
27  : mpTrack{ pTrack }
28  , mLocation{ location }
29 {
30 }
31 
33 {
34 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
36 #endif
37 }
38 
39 HitTestPreview CutlineHandle::HitPreview(bool cutline, bool unsafe)
40 {
41  static auto disabledCursor =
42  ::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
43  static wxCursor arrowCursor{ wxCURSOR_ARROW };
44  return {
45  (cutline
46  ? XO("Left-Click to expand, Right-Click to remove")
47  : XO("Left-Click to merge clips")),
48  (unsafe
49  ? &*disabledCursor
50  : &arrowCursor)
51  };
52 }
53 namespace
54 {
55  int FindMergeLine(WaveTrack *track, double time)
56  {
57  const double tolerance = 0.5 / track->GetRate();
58  int ii = 0;
59  for (const auto loc: track->GetCachedLocations()) {
61  fabs(time - loc.pos) < tolerance)
62  return ii;
63  ++ii;
64  }
65  return -1;
66  }
67 
69  (const ViewInfo &viewInfo, WaveTrack * track,
70  const wxRect &rect, const wxMouseState &state,
71  WaveTrackLocation *pmLocation)
72  {
73  for (auto loc: track->GetCachedLocations())
74  {
75  const double x = viewInfo.TimeToPosition(loc.pos);
76  if (x >= 0 && x < rect.width)
77  {
78  wxRect locRect;
79  locRect.width = 2 * kPixelTolerance - 1;
80  locRect.x = (int)(rect.x + x) - locRect.width / 2;
81  locRect.y = rect.y;
82  locRect.height = rect.height;
83  if (locRect.Contains(state.m_x, state.m_y))
84  {
85  if (pmLocation)
86  *pmLocation = loc;
87  return true;
88  }
89  }
90  }
91 
92  return false;
93  }
94 }
95 
97 (std::weak_ptr<CutlineHandle> &holder,
98  const wxMouseState &state, const wxRect &rect,
99  const AudacityProject *pProject,
100  const std::shared_ptr<WaveTrack> &pTrack)
101 {
102  auto &viewInfo = ViewInfo::Get( *pProject );
105 
106  WaveTrackLocation location;
107  if (!IsOverCutline(viewInfo, pTrack.get(), rect, state, &location))
108  return {};
109 
110  auto result = std::make_shared<CutlineHandle>( pTrack, location );
111  result = AssignUIHandlePtr( holder, result );
112  return result;
113 }
114 
116 {
117 }
118 
120 {
121  return true;
122 }
123 
125 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
126 {
127  using namespace RefreshCode;
128  const bool unsafe = ProjectAudioIO::Get( *pProject ).IsAudioActive();
129  if ( unsafe )
130  return Cancelled;
131 
132  const wxMouseEvent &event = evt.event;
133  auto &viewInfo = ViewInfo::Get( *pProject );
134 
135  // Can affect the track by merging clips, expanding a cutline, or
136  // deleting a cutline.
137  // All the change is done at button-down. Button-up just commits the undo item.
138 
140 
141  // FIXME: Disable this and return true when CutLines aren't showing?
142  // (Don't use gPrefs-> for the fix as registry access is slow).
143 
144  // Cutline data changed on either branch, so refresh the track display.
145  UIHandle::Result result = RefreshCell;
146 
147  if (event.LeftDown())
148  {
150  {
151  mOperation = Expand;
152  mStartTime = viewInfo.selectedRegion.t0();
153  mEndTime = viewInfo.selectedRegion.t1();
154 
155  // When user presses left button on cut line, expand the line again
156  double cutlineStart = 0, cutlineEnd = 0;
157  double *pCutlineStart = &cutlineStart, *pCutlineEnd = &cutlineEnd;
158 
159  for (auto channel :
160  TrackList::Channels(mpTrack.get())) {
161  channel->ExpandCutLine(
162  mLocation.pos, pCutlineStart, pCutlineEnd);
163  if ( channel == mpTrack.get() )
164  pCutlineStart = pCutlineEnd = nullptr;
165  }
166 
167  viewInfo.selectedRegion.setTimes(cutlineStart, cutlineEnd);
168  }
170  const double pos = mLocation.pos;
171  for (auto channel :
172  TrackList::Channels(mpTrack.get())) {
173  // Don't assume correspondence of merge points across channels!
174  int idx = FindMergeLine(channel, pos);
175  if (idx >= 0) {
176  WaveTrack::Location location =
177  channel->GetCachedLocations()[idx];
178  channel->MergeClips(
179  location.clipidx1, location.clipidx2);
180  }
181  }
182 
183  mOperation = Merge;
184  }
185  }
186  else if (event.RightDown())
187  {
188  bool removed = false;
189  for (auto channel :
191  removed = channel->RemoveCutLine(mLocation.pos) || removed;
192 
193  if (!removed)
194  // Nothing happened, make no Undo item
195  return Cancelled;
196 
197  mOperation = Remove;
198  }
199  else
200  result = RefreshNone;
201 
202  return result;
203 }
204 
207 {
209 }
210 
212 (const TrackPanelMouseState &, AudacityProject *pProject)
213 {
214  const bool unsafe = ProjectAudioIO::Get( *pProject ).IsAudioActive();
215  auto bCutline = (mLocation.typ == WaveTrackLocation::locationCutLine);
216  return HitPreview( bCutline, unsafe );
217 }
218 
220 (const TrackPanelMouseEvent &, AudacityProject *pProject, wxWindow *)
221 {
223 
224  // Only now commit the result to the undo stack
225  switch (mOperation) {
226  default:
227  wxASSERT(false);
228  case Merge:
229  ProjectHistory::Get( *pProject )
230  .PushState(XO("Merged Clips"), XO("Merge"), UndoPush::CONSOLIDATE);
231  break;
232  case Expand:
233  ProjectHistory::Get( *pProject )
234  .PushState(XO("Expanded Cut Line"), XO("Expand"));
235  break;
236  case Remove:
237  ProjectHistory::Get( *pProject )
238  .PushState(XO("Removed Cut Line"), XO("Remove"));
239  break;
240  }
241 
242  // Nothing to do for the display
243  return result;
244 }
245 
247 {
248  using namespace RefreshCode;
249  UIHandle::Result result = RefreshCell;
250  ProjectHistory::Get( *pProject ).RollbackState();
251  if (mOperation == Expand) {
252  AudacityProject &project = *pProject;
253  auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
254  selectedRegion.setTimes( mStartTime, mEndTime );
255  }
256  return result;
257 }
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:241
WaveTrackLocation::clipidx2
int clipidx2
Definition: WaveTrackLocation.h:36
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
RefreshCode::RefreshNone
@ RefreshNone
Definition: RefreshCode.h:21
WaveTrackLocation::typ
LocationType typ
Definition: WaveTrackLocation.h:32
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1484
MakeCursor
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:182
ViewInfo
Definition: ViewInfo.h:202
CutlineHandle::Merge
@ Merge
Definition: CutlineHandle.h:70
WaveTrackLocation::locationMergePoint
@ locationMergePoint
Definition: WaveTrackLocation.h:18
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
CutlineHandle::Enter
void Enter(bool forward, AudacityProject *) override
Definition: CutlineHandle.cpp:32
XO
#define XO(s)
Definition: Internat.h:31
WaveTrackLocation
Definition: WaveTrackLocation.h:14
ProjectAudioIO::Get
static ProjectAudioIO & Get(AudacityProject &project)
Definition: ProjectAudioIO.cpp:22
CutlineHandle::mStartTime
double mStartTime
Definition: CutlineHandle.h:72
ZoomInfo::TimeToPosition
wxInt64 TimeToPosition(double time, wxInt64 origin=0, bool ignoreFisheye=false) const
STM: Converts a project time to screen x position.
Definition: ZoomInfo.cpp:49
CutlineHandle::mEndTime
double mEndTime
Definition: CutlineHandle.h:72
ProjectAudioIO::IsAudioActive
bool IsAudioActive() const
Definition: ProjectAudioIO.cpp:51
WaveTrack::GetCachedLocations
const std::vector< Location > & GetCachedLocations() const
Definition: WaveTrack.h:531
CutlineHandle::mOperation
Operation mOperation
Definition: CutlineHandle.h:71
NotifyingSelectedRegion::setTimes
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:62
CutlineHandle::Remove
@ Remove
Definition: CutlineHandle.h:70
CutlineHandle::Drag
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: CutlineHandle.cpp:206
ViewInfo::selectedRegion
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:229
UIHandle::mChangeHighlight
Result mChangeHighlight
Definition: UIHandle.h:139
kPixelTolerance
const int kPixelTolerance
Definition: Snap.h:28
UIHandle::Result
unsigned Result
Definition: UIHandle.h:38
CutlineHandle.h
CutlineHandle::~CutlineHandle
virtual ~CutlineHandle()
Definition: CutlineHandle.cpp:115
UIHandlePtr
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
HitTestPreview
Definition: HitTestResult.h:20
CutlineHandle::HitPreview
static HitTestPreview HitPreview(bool cutline, bool unsafe)
Definition: CutlineHandle.cpp:39
anonymous_namespace{CutlineHandle.cpp}::IsOverCutline
bool IsOverCutline(const ViewInfo &viewInfo, WaveTrack *track, const wxRect &rect, const wxMouseState &state, WaveTrackLocation *pmLocation)
Definition: CutlineHandle.cpp:69
RefreshCode::RefreshCell
@ RefreshCell
Definition: RefreshCode.h:24
ViewInfo.h
CutlineHandle::mpTrack
std::shared_ptr< WaveTrack > mpTrack
Definition: CutlineHandle.h:69
anonymous_namespace{CutlineHandle.cpp}::FindMergeLine
int FindMergeLine(WaveTrack *track, double time)
Definition: CutlineHandle.cpp:55
CutlineHandle::mLocation
WaveTrackLocation mLocation
Definition: CutlineHandle.h:73
ProjectHistory::PushState
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
Definition: ProjectHistory.cpp:90
ProjectHistory::RollbackState
void RollbackState()
Definition: ProjectHistory.cpp:117
CutlineHandle::Preview
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Definition: CutlineHandle.cpp:212
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
CutlineHandle::Cancel
Result Cancel(AudacityProject *pProject) override
Definition: CutlineHandle.cpp:246
TrackPanelMouseEvent
Definition: TrackPanelMouseEvent.h:46
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
CutlineHandle::Release
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: CutlineHandle.cpp:220
UndoPush::CONSOLIDATE
@ CONSOLIDATE
CutlineHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< CutlineHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, const std::shared_ptr< WaveTrack > &pTrack)
Definition: CutlineHandle.cpp:97
WaveTrackLocation::locationCutLine
@ locationCutLine
Definition: WaveTrackLocation.h:17
CutlineHandle::HandlesRightClick
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
Definition: CutlineHandle.cpp:119
AssignUIHandlePtr
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:151
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
WaveTrackLocation::pos
double pos
Definition: WaveTrackLocation.h:29
TrackPanelMouseEvent::event
wxMouseEvent & event
Definition: TrackPanelMouseEvent.h:58
WaveTrackLocation::clipidx1
int clipidx1
Definition: WaveTrackLocation.h:35
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
CutlineHandle::CutlineHandle
CutlineHandle(const CutlineHandle &)=delete
CutlineHandle::Expand
@ Expand
Definition: CutlineHandle.h:70
CutlineHandle::Click
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: CutlineHandle.cpp:125
WaveTrack::GetRate
double GetRate() const
Definition: WaveTrack.cpp:457