Audacity  2.2.2
TrackPanelResizeHandle.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 TrackPanelResizeHandle.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 #include "Audacity.h"
12 #include "TrackPanelResizeHandle.h"
13 #include "Experimental.h"
14 
15 #include "MemoryX.h"
16 
17 #include <wx/cursor.h>
18 #include <wx/translation.h>
19 
20 #include "HitTestResult.h"
21 #include "Project.h"
22 #include "RefreshCode.h"
23 #include "Track.h"
24 #include "TrackPanelMouseEvent.h"
26 
28 {
29  static wxCursor resizeCursor{ wxCURSOR_SIZENS };
30 
32  // Check to see whether it is the first channel of a stereo track
33  if (bLinked) {
34  // If we are in the label we got here 'by mistake' and we're
35  // not actually in the resize area at all. (The resize area
36  // is shorter when it is between stereo tracks).
37 
38  return {
39  _("Click and drag to adjust relative size of stereo tracks."),
40  &resizeCursor
41  };
42  }
43  else {
44  return {
45  _("Click and drag to resize the track."),
46  &resizeCursor
47  };
48  }
49 }
50 
52 {
53 }
54 
56 (const TrackPanelMouseEvent &WXUNUSED(evt), AudacityProject *WXUNUSED(pProject))
57 {
59 }
60 
62 ( const std::shared_ptr<Track> &track, int y, const AudacityProject *pProject )
63  : mpTrack{ track }
64  , mMouseClickY( y )
65 {
66  auto tracks = pProject->GetTracks();
67  Track *prev = tracks->GetPrev(track.get());
68  Track *next = tracks->GetNext(track.get());
69 
70  //STM: Determine whether we should rescale one or two tracks
71  if (prev && prev->GetLink() == track.get()) {
72  // mpTrack is the lower track
73  mInitialTrackHeight = track->GetHeight();
74  mInitialActualHeight = track->GetActualHeight();
75  mInitialMinimized = track->GetMinimized();
76  mInitialUpperTrackHeight = prev->GetHeight();
77  mInitialUpperActualHeight = prev->GetActualHeight();
78  mMode = IsResizingBelowLinkedTracks;
79  }
80  else if (next && track->GetLink() == next) {
81  // mpTrack is the upper track
82  mInitialTrackHeight = next->GetHeight();
83  mInitialActualHeight = next->GetActualHeight();
84  mInitialMinimized = next->GetMinimized();
85  mInitialUpperTrackHeight = track->GetHeight();
86  mInitialUpperActualHeight = track->GetActualHeight();
87  mMode = IsResizingBetweenLinkedTracks;
88  }
89  else {
90  // DM: Save the initial mouse location and the initial height
91  mInitialTrackHeight = track->GetHeight();
92  mInitialActualHeight = track->GetActualHeight();
93  mInitialMinimized = track->GetMinimized();
94  mMode = IsResizing;
95  }
96 }
97 
99 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
100 {
101  auto pTrack = pProject->GetTracks()->Lock(mpTrack);
102  if ( !pTrack )
103  return RefreshCode::Cancelled;
104 
105  const wxMouseEvent &event = evt.event;
106  TrackList *const tracks = pProject->GetTracks();
107 
108  int delta = (event.m_y - mMouseClickY);
109 
110  // On first drag, jump out of minimized mode. Initial height
111  // will be height of minimized track.
112  //
113  // This used to be in HandleResizeClick(), but simply clicking
114  // on a resize border would switch the minimized state.
115  if (pTrack->GetMinimized()) {
116  Track *link = pTrack->GetLink();
117 
118  pTrack->SetHeight(pTrack->GetHeight());
119  pTrack->SetMinimized(false);
120 
121  if (link) {
122  link->SetHeight(link->GetHeight());
123  link->SetMinimized(false);
124  // Initial values must be reset since they weren't based on the
125  // minimized heights.
126  mInitialUpperTrackHeight = link->GetHeight();
127  mInitialTrackHeight = pTrack->GetHeight();
128  }
129  }
130 
131  // Common pieces of code for MONO_WAVE_PAN and otherwise.
132  auto doResizeBelow = [&] (Track *prev, bool WXUNUSED(vStereo)) {
133  double proportion = static_cast < double >(mInitialTrackHeight)
134  / (mInitialTrackHeight + mInitialUpperTrackHeight);
135 
136  int newTrackHeight = static_cast < int >
137  (mInitialTrackHeight + delta * proportion);
138 
139  int newUpperTrackHeight = static_cast < int >
140  (mInitialUpperTrackHeight + delta * (1.0 - proportion));
141 
142  //make sure neither track is smaller than its minimum height
143  if (newTrackHeight < pTrack->GetMinimizedHeight())
144  newTrackHeight = pTrack->GetMinimizedHeight();
145  if (newUpperTrackHeight < prev->GetMinimizedHeight())
146  newUpperTrackHeight = prev->GetMinimizedHeight();
147 
148  pTrack->SetHeight(newTrackHeight);
149  prev->SetHeight(newUpperTrackHeight);
150  };
151 
152  auto doResizeBetween = [&] (Track *next, bool WXUNUSED(vStereo)) {
153  int newUpperTrackHeight = mInitialUpperTrackHeight + delta;
154  int newTrackHeight = mInitialTrackHeight - delta;
155 
156  // make sure neither track is smaller than its minimum height
157  if (newTrackHeight < next->GetMinimizedHeight()) {
158  newTrackHeight = next->GetMinimizedHeight();
159  newUpperTrackHeight =
160  mInitialUpperTrackHeight + mInitialTrackHeight - next->GetMinimizedHeight();
161  }
162  if (newUpperTrackHeight < pTrack->GetMinimizedHeight()) {
163  newUpperTrackHeight = pTrack->GetMinimizedHeight();
164  newTrackHeight =
165  mInitialUpperTrackHeight + mInitialTrackHeight - pTrack->GetMinimizedHeight();
166  }
167 
168  pTrack->SetHeight(newUpperTrackHeight);
169  next->SetHeight(newTrackHeight);
170  };
171 
172  auto doResize = [&] {
173  int newTrackHeight = mInitialTrackHeight + delta;
174  if (newTrackHeight < pTrack->GetMinimizedHeight())
175  newTrackHeight = pTrack->GetMinimizedHeight();
176  pTrack->SetHeight(newTrackHeight);
177  };
178 
179  //STM: We may be dragging one or two (stereo) tracks.
180  // If two, resize proportionally if we are dragging the lower track, and
181  // adjust compensatively if we are dragging the upper track.
182 
183  switch( mMode )
184  {
185  case IsResizingBelowLinkedTracks:
186  {
187  Track *prev = tracks->GetPrev(pTrack.get());
188  doResizeBelow(prev, false);
189  break;
190  }
191  case IsResizingBetweenLinkedTracks:
192  {
193  Track *next = tracks->GetNext(pTrack.get());
194  doResizeBetween(next, false);
195  break;
196  }
197  case IsResizing:
198  {
199  doResize();
200  break;
201  }
202  default:
203  // don't refresh in this case.
205  }
206 
208 }
209 
212 {
213  return HitPreview(mMode == IsResizingBetweenLinkedTracks);
214 }
215 
218  wxWindow *)
219 {
226  pProject->ModifyState(false);
228 }
229 
231 {
232  auto pTrack = pProject->GetTracks()->Lock(mpTrack);
233  if ( !pTrack )
234  return RefreshCode::Cancelled;
235 
236  TrackList *const tracks = pProject->GetTracks();
237 
238  switch (mMode) {
239  case IsResizing:
240  {
241  pTrack->SetHeight(mInitialActualHeight);
242  pTrack->SetMinimized(mInitialMinimized);
243  }
244  break;
246  {
247  Track *const next = tracks->GetNext(pTrack.get());
249  pTrack->SetMinimized(mInitialMinimized);
252  }
253  break;
255  {
256  Track *const prev = tracks->GetPrev(pTrack.get());
258  pTrack->SetMinimized(mInitialMinimized);
261  }
262  break;
263  }
264 
266 }
A list of TrackListNode items.
Definition: Track.h:611
int GetActualHeight() const
Definition: Track.h:185
Result Cancel(AudacityProject *pProject) override
void SetHeight(int h)
Definition: Track.cpp:187
bool GetMinimized() const
Definition: Track.cpp:212
virtual int GetMinimizedHeight() const
Definition: Track.cpp:127
void SetMinimized(bool isMinimized)
Definition: Track.cpp:217
std::weak_ptr< Track > mpTrack
TrackPanelResizeHandle(const TrackPanelResizeHandle &)=delete
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:158
unsigned Result
Definition: UIHandle.h:37
Track * GetNext(Track *t, bool linked=false) const
Return a track in the list that comes after Track t.
Definition: Track.cpp:1043
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
HitTestPreview Preview(const TrackPanelMouseState &state, const AudacityProject *pProject) override
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:94
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:725
void ModifyState(bool bWantsAutoSave)
Definition: Project.cpp:4547
static HitTestPreview HitPreview(bool bLinked)
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
Track * GetPrev(Track *t, bool linked=false) const
Definition: Track.cpp:1062
Track * GetLink() const
Definition: Track.cpp:267
TrackList * GetTracks()
Definition: Project.h:174
int GetHeight() const
Definition: Track.cpp:178