Audacity  3.0.3
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 
12 #include "TrackPanelResizeHandle.h"
13 
14 #include <wx/cursor.h>
15 #include <wx/translation.h>
16 
17 #include "HitTestResult.h"
18 #include "ProjectHistory.h"
19 #include "RefreshCode.h"
20 #include "Track.h"
21 #include "TrackPanelMouseEvent.h"
22 #include "tracks/ui/TrackView.h"
23 
25 {
26  // TODO: more-than-two-channels-message
27 
28  static wxCursor resizeCursor{ wxCURSOR_SIZENS };
29 
31  // Check to see whether it is the first channel of a stereo track
32  if (bLinked) {
33  // If we are in the label we got here 'by mistake' and we're
34  // not actually in the resize area at all. (The resize area
35  // is shorter when it is between stereo tracks).
36 
37  return {
38  XO(
39 "Click and drag to adjust relative size of stereo tracks, double-click to make heights equal"),
40  &resizeCursor
41  };
42  }
43  else {
44  return {
45  XO("Click and drag to resize the track."),
46  &resizeCursor
47  };
48  }
49 }
50 
52 {
53 }
54 
56  const TrackPanelMouseEvent &evt, AudacityProject *pProject )
57 {
58  using namespace RefreshCode;
59  if ( evt.event.LeftDClick() && mMode == IsResizingBetweenLinkedTracks ) {
60  auto &tracks = TrackList::Get( *pProject );
61  auto pTrack = tracks.Lock(mpTrack);
62  if (pTrack &&
63  !TrackView::Get(*pTrack).GetMinimized()) {
64  auto range = TrackList::Channels( pTrack.get() );
65  auto size = range.size();
66  auto height = range.sum( [](const Track *pTrack){
67  return TrackView::Get(*pTrack).GetHeight(); } );
68  int ii = 1;
69  int coord = 0;
70  for ( const auto channel : range ) {
71  int newCoord = ((double)ii++ /size) * height;
72  TrackView::Get(*channel).SetExpandedHeight( newCoord - coord );
73  coord = newCoord;
74  }
75  ProjectHistory::Get( *pProject ).ModifyState(false);
76  // Do not start a drag
77  return Cancelled | RefreshAll;
78  }
79  }
80  return RefreshNone;
81 }
82 
84 ( const std::shared_ptr<Track> &track, int y )
85  : mpTrack{ track }
86  , mMouseClickY( y )
87 {
88  // TODO: more-than-two-channels
89 
90  //STM: Determine whether we should rescale one or two tracks
91  auto channels = TrackList::Channels(track.get());
92  auto last = *channels.rbegin();
93  auto &lastView = TrackView::Get( *last );
94  mInitialTrackHeight = lastView.GetHeight();
95  mInitialExpandedHeight = lastView.GetExpandedHeight();
96  mInitialMinimized = lastView.GetMinimized();
97 
98  if (channels.size() > 1) {
99  auto first = *channels.begin();
100  auto &firstView = TrackView::Get( *first );
101 
102  mInitialUpperTrackHeight = firstView.GetHeight();
103  mInitialUpperExpandedHeight = firstView.GetExpandedHeight();
104 
105  if (track.get() == *channels.rbegin())
106  // capturedTrack is the lowest track
107  mMode = IsResizingBelowLinkedTracks;
108  else
109  // capturedTrack is not the lowest track
110  mMode = IsResizingBetweenLinkedTracks;
111  }
112  else
113  mMode = IsResizing;
114 }
115 
117 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
118 {
119  auto &tracks = TrackList::Get( *pProject );
120  auto pTrack = tracks.Lock(mpTrack);
121  if ( !pTrack )
122  return RefreshCode::Cancelled;
123 
124  auto &view = TrackView::Get( *pTrack );
125 
126  const wxMouseEvent &event = evt.event;
127 
128  int delta = (event.m_y - mMouseClickY);
129 
130  // On first drag, jump out of minimized mode. Initial height
131  // will be height of minimized track.
132  //
133  // This used to be in HandleResizeClick(), but simply clicking
134  // on a resize border would switch the minimized state.
135  auto &data = TrackView::Get( *pTrack );
136  if (data.GetMinimized()) {
137  auto channels = TrackList::Channels( pTrack.get() );
138  for (auto channel : channels) {
139  auto &channelView = TrackView::Get( *channel );
140  channelView.SetExpandedHeight(channelView.GetHeight());
141  channelView.SetMinimized( false );
142  }
143 
144  if (channels.size() > 1) {
145  // Initial values must be reset since they weren't based on the
146  // minimized heights.
147  auto &channelView = TrackView::Get( **channels.begin() );
148  mInitialUpperTrackHeight = channelView.GetHeight();
149  mInitialTrackHeight = channelView.GetHeight();
150  }
151  }
152 
153  // Common pieces of code for MONO_WAVE_PAN and otherwise.
154  auto doResizeBelow = [&] (Track *prev, bool WXUNUSED(vStereo)) {
155  // TODO: more-than-two-channels
156 
157  auto &prevView = TrackView::Get( *prev );
158 
159  double proportion = static_cast < double >(mInitialTrackHeight)
161 
162  int newTrackHeight = static_cast < int >
163  (mInitialTrackHeight + delta * proportion);
164 
165  int newUpperTrackHeight = static_cast < int >
166  (mInitialUpperTrackHeight + delta * (1.0 - proportion));
167 
168  //make sure neither track is smaller than its minimum height
169  if (newTrackHeight < view.GetMinimizedHeight())
170  newTrackHeight = view.GetMinimizedHeight();
171  if (newUpperTrackHeight < prevView.GetMinimizedHeight())
172  newUpperTrackHeight = prevView.GetMinimizedHeight();
173 
174  view.SetExpandedHeight(newTrackHeight);
175  prevView.SetExpandedHeight(newUpperTrackHeight);
176  };
177 
178  auto doResizeBetween = [&] (Track *next, bool WXUNUSED(vStereo)) {
179  // TODO: more-than-two-channels
180 
181  auto &nextView = TrackView::Get( *next );
182  int newUpperTrackHeight = mInitialUpperTrackHeight + delta;
183  int newTrackHeight = mInitialTrackHeight - delta;
184 
185  // make sure neither track is smaller than its minimum height
186  if (newTrackHeight < nextView.GetMinimizedHeight()) {
187  newTrackHeight = nextView.GetMinimizedHeight();
188  newUpperTrackHeight =
189  mInitialUpperTrackHeight + mInitialTrackHeight - nextView.GetMinimizedHeight();
190  }
191  if (newUpperTrackHeight < view.GetMinimizedHeight()) {
192  newUpperTrackHeight = view.GetMinimizedHeight();
193  newTrackHeight =
194  mInitialUpperTrackHeight + mInitialTrackHeight - view.GetMinimizedHeight();
195  }
196 
197  view.SetExpandedHeight(newUpperTrackHeight);
198  nextView.SetExpandedHeight(newTrackHeight);
199  };
200 
201  auto doResize = [&] {
202  int newTrackHeight = mInitialTrackHeight + delta;
203  if (newTrackHeight < view.GetMinimizedHeight())
204  newTrackHeight = view.GetMinimizedHeight();
205  view.SetExpandedHeight(newTrackHeight);
206  };
207 
208  //STM: We may be dragging one or two (stereo) tracks.
209  // If two, resize proportionally if we are dragging the lower track, and
210  // adjust compensatively if we are dragging the upper track.
211 
212  switch( mMode )
213  {
215  {
216  auto prev = * -- tracks.Find(pTrack.get());
217  doResizeBelow(prev, false);
218  break;
219  }
221  {
222  auto next = * ++ tracks.Find(pTrack.get());
223  doResizeBetween(next, false);
224  break;
225  }
226  case IsResizing:
227  {
228  doResize();
229  break;
230  }
231  default:
232  // don't refresh in this case.
234  }
235 
237 }
238 
241 {
243 }
244 
246 (const TrackPanelMouseEvent &, AudacityProject *pProject,
247  wxWindow *)
248 {
255  ProjectHistory::Get( *pProject ).ModifyState(false);
257 }
258 
260 {
261  auto &tracks = TrackList::Get( *pProject );
262  auto pTrack = tracks.Lock(mpTrack);
263  if ( !pTrack )
264  return RefreshCode::Cancelled;
265 
266 
267  switch (mMode) {
268  case IsResizing:
269  {
270  auto &view = TrackView::Get( *pTrack );
271  view.SetExpandedHeight(mInitialExpandedHeight);
272  view.SetMinimized( mInitialMinimized );
273  }
274  break;
276  {
277  Track *const next = * ++ tracks.Find(pTrack.get());
278  auto
279  &view = TrackView::Get( *pTrack ), &nextView = TrackView::Get( *next );
280  view.SetExpandedHeight(mInitialUpperExpandedHeight);
281  view.SetMinimized( mInitialMinimized );
282  nextView.SetExpandedHeight(mInitialExpandedHeight);
283  nextView.SetMinimized( mInitialMinimized );
284  }
285  break;
287  {
288  Track *const prev = * -- tracks.Find(pTrack.get());
289  auto
290  &view = TrackView::Get( *pTrack ), &prevView = TrackView::Get( *prev );
291  view.SetExpandedHeight(mInitialExpandedHeight);
292  view.SetMinimized( mInitialMinimized );
293  prevView.SetExpandedHeight(mInitialUpperExpandedHeight);
294  prevView.SetMinimized(mInitialMinimized);
295  }
296  break;
297  }
298 
300 }
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
TrackPanelResizeHandle::IsResizingBelowLinkedTracks
@ IsResizingBelowLinkedTracks
Definition: TrackPanelResizeHandle.h:53
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
RefreshCode::FixScrollbars
@ FixScrollbars
Definition: RefreshCode.h:27
TrackPanelMouseEvent.h
TrackPanelResizeHandle::IsResizingBetweenLinkedTracks
@ IsResizingBetweenLinkedTracks
Definition: TrackPanelResizeHandle.h:52
TrackPanelResizeHandle::mMouseClickY
int mMouseClickY
Definition: TrackPanelResizeHandle.h:65
RefreshCode::RefreshAll
@ RefreshAll
Definition: RefreshCode.h:26
TrackView::Get
static TrackView & Get(Track &)
Definition: TrackView.cpp:63
RefreshCode::RefreshNone
@ RefreshNone
Definition: RefreshCode.h:21
ClientData::Site::Find
Subclass * Find(const RegisteredFactory &key)
Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand...
Definition: ClientData.h:333
TrackView.h
TrackView::GetMinimized
bool GetMinimized() const
Definition: TrackView.h:49
TrackPanelResizeHandle::~TrackPanelResizeHandle
virtual ~TrackPanelResizeHandle()
Definition: TrackPanelResizeHandle.cpp:51
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1484
TrackView::SetExpandedHeight
void SetExpandedHeight(int height)
Definition: TrackView.cpp:157
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
XO
#define XO(s)
Definition: Internat.h:31
HitTestResult.h
TrackPanelResizeHandle::HitPreview
static HitTestPreview HitPreview(bool bLinked)
Definition: TrackPanelResizeHandle.cpp:24
TrackPanelResizeHandle::mInitialUpperTrackHeight
int mInitialUpperTrackHeight
Definition: TrackPanelResizeHandle.h:62
TrackPanelResizeHandle::Release
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: TrackPanelResizeHandle.cpp:246
TrackPanelResizeHandle::mpTrack
std::weak_ptr< Track > mpTrack
Definition: TrackPanelResizeHandle.h:57
TrackPanelResizeHandle::mInitialMinimized
bool mInitialMinimized
Definition: TrackPanelResizeHandle.h:59
UIHandle::Result
unsigned Result
Definition: UIHandle.h:38
TrackPanelResizeHandle::mMode
Mode mMode
Definition: TrackPanelResizeHandle.h:55
TrackPanelResizeHandle::IsResizing
@ IsResizing
Definition: TrackPanelResizeHandle.h:51
HitTestPreview
Definition: HitTestResult.h:20
TrackPanelResizeHandle::Click
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: TrackPanelResizeHandle.cpp:55
TrackPanelResizeHandle::mInitialTrackHeight
int mInitialTrackHeight
Definition: TrackPanelResizeHandle.h:60
TrackPanelResizeHandle::Preview
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Definition: TrackPanelResizeHandle.cpp:240
TrackPanelResizeHandle::Cancel
Result Cancel(AudacityProject *pProject) override
Definition: TrackPanelResizeHandle.cpp:259
TrackPanelResizeHandle::mInitialExpandedHeight
int mInitialExpandedHeight
Definition: TrackPanelResizeHandle.h:61
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
TrackPanelResizeHandle.h
TrackPanelResizeHandle::mInitialUpperExpandedHeight
int mInitialUpperExpandedHeight
Definition: TrackPanelResizeHandle.h:63
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
TrackPanelMouseEvent
Definition: TrackPanelMouseEvent.h:46
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
ProjectHistory.h
Track.h
declares abstract base class Track, TrackList, and iterators over TrackList
RefreshCode.h
TrackPanelResizeHandle::Drag
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: TrackPanelResizeHandle.cpp:117
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
TrackPanelMouseEvent::event
wxMouseEvent & event
Definition: TrackPanelMouseEvent.h:58
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
TrackView::GetHeight
int GetHeight() const
Definition: TrackView.cpp:149
TrackPanelResizeHandle::TrackPanelResizeHandle
TrackPanelResizeHandle(const TrackPanelResizeHandle &)=delete