Audacity  3.0.3
WaveTrackView.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 WaveTrackView.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 #include "WaveTrackView.h"
12 
13 #include <unordered_set>
14 
15 #include "CutlineHandle.h"
16 
17 #include <numeric>
18 #include <wx/dc.h>
19 #include <wx/graphics.h>
20 
21 #include "../../../../AColor.h"
22 #include "../../../../WaveClip.h"
23 #include "../../../../WaveTrack.h"
24 
25 #include "../../../../../images/Cursors.h"
26 #include "../../../../AllThemeResources.h"
27 
28 #include "../../../../HitTestResult.h"
29 #include "../../../../ProjectHistory.h"
30 #include "../../../../RefreshCode.h"
31 #include "../../../../TrackArtist.h"
32 #include "../../../../TrackPanelDrawingContext.h"
33 #include "../../../../TrackPanelMouseEvent.h"
34 #include "../../../../ViewInfo.h"
35 #include "../../../../prefs/TracksPrefs.h"
36 
37 #include "../../../ui/TimeShiftHandle.h"
38 #include "../../../ui/ButtonHandle.h"
39 #include "../../../../TrackInfo.h"
40 
42 
43 namespace {
44 
45 
46 using WaveTrackSubViewPtrs = std::vector< std::shared_ptr< WaveTrackSubView > >;
47 
48 // Structure that collects and modifies information on sub-view positions
49 // Written with great generality, allowing any number of sub-views
51 {
52  enum { HotZoneSize = 5 }; // so many pixels at top and bottom of each subview
53 
55  : mwView{
56  std::static_pointer_cast<WaveTrackView>( view.shared_from_this() ) }
57  {
58  mSubViews = view.GetAllSubViews();
59  mOrigPlacements = mNewPlacements = view.SavePlacements();
60  FindPermutation();
61  }
62 
64  {
65  // Find a certain sort of the sub-views
66  auto size = mOrigPlacements.size();
67  wxASSERT( mSubViews.size() == size );
68  mPermutation.resize( size );
69  const auto begin = mPermutation.begin(), end = mPermutation.end();
70  std::iota( begin, end, 0 );
71  static auto invisible = []( const WaveTrackSubViewPlacement &placement ){
72  return placement.index < 0 || placement.fraction <= 0;
73  };
74  const auto comp = [this]( size_t ii, size_t jj ){
75  auto &pi = mOrigPlacements[ii];
76  bool iInvisible = invisible( pi );
77 
78  auto &pj = mOrigPlacements[jj];
79  bool jInvisible = invisible( pj );
80 
81  // Sort the invisibles to the front, rest by index
82  if ( iInvisible != jInvisible )
83  return iInvisible;
84  else if ( !iInvisible )
85  return pi.index < pj.index;
86  else
87  // Minor sort among the invisible views by their type
88  return mSubViews[ii]->SubViewType() < mSubViews[jj]->SubViewType();
89  };
90  std::sort( begin, end, comp );
91  // Find the start of visible sub-views
92  auto first = std::find_if( begin, end, [this](size_t ii){
93  return !invisible( mOrigPlacements[ii] );
94  } );
95  mFirstSubView = first - begin;
96  }
97 
98  size_t NVisible() const
99  { return mPermutation.size() - mFirstSubView; }
100 
101  bool ModifyPermutation( bool top )
102  {
103  bool rotated = false;
104  const auto pBegin = mPermutation.begin(), pEnd = mPermutation.end();
105  auto pFirst = pBegin + mFirstSubView;
106  if ( mFirstSubView > 0 ) {
107  // In case of dragging the top edge of the topmost view, or the
108  // bottom edge of the bottommost, decide which of the invisible
109  // views can become visible, and reassign the sequence.
110  // For definiteness, that choice depends on the subview type numbers;
111  // see the sorting criteria above.
112  --mFirstSubView;
113  --pFirst;
114  if ( top ) {
115  // If you drag down the top, the greatest-numbered invisible
116  // subview type will appear there.
117  mNewPlacements[ *pFirst ].fraction = 0;
118  }
119  else {
120  // If you drag up the bottom, let the least-numbered invisible
121  // subview type appear there.
122  mNewPlacements[ *pBegin ].fraction = 0;
123  std::rotate( pBegin, pBegin + 1, pEnd );
124  rotated = true;
125  }
126  }
127  // Reassign index numbers to all sub-views and 0 fraction to invisibles
128  for ( auto pIter = pBegin; pIter != pFirst; ++pIter ) {
129  auto &placement = mNewPlacements[ *pIter ];
130  placement.index = -1;
131  placement.fraction = 0;
132  }
133  size_t index = 0;
134  for ( auto pIter = pFirst; pIter != pEnd; ++pIter )
135  mNewPlacements[ *pIter ].index = index++;
136  return rotated;
137  }
138 
139  size_t FindIndex( WaveTrackSubView &subView ) const
140  {
141  const auto begin = mPermutation.begin(), end = mPermutation.end();
142  auto iter = std::find_if( begin, end, [&](size_t ii){
143  return mSubViews[ ii ].get() == &subView;
144  } );
145  return iter - begin;
146  }
147 
148  std::pair< size_t, bool >
150  wxCoord yy, wxCoord top, wxCoord height )
151  {
152  const auto index = FindIndex( subView );
153  auto size = mPermutation.size();
154  if ( index < (int)size ) {
155  yy -= top;
156  if ( yy >= 0 && yy < HotZoneSize && index > 0 )
157  return { index, true }; // top hit
158  if ( yy < height && yy >= height - HotZoneSize &&
159  // Have not yet called ModifyPermutation; dragging bottom of
160  // bottommost view allowed only if at least one view is invisible
161  ( index < (int)size - 1 || mFirstSubView > 0 ) )
162  return { index, false }; // bottom hit
163  }
164  return { size, false }; // not hit
165  }
166 
167  std::vector<wxCoord> ComputeHeights( wxCoord totalHeight )
168  {
169  // Compute integer-valued heights
170  float total = 0;
171  for (const auto index : mPermutation ) {
172  const auto &placement = mOrigPlacements[ index ];
173  total += std::max( 0.f, placement.fraction );
174  }
175  float partial = 0;
176  wxCoord lastCoord = 0;
177  std::vector<wxCoord> result;
178  for (const auto index : mPermutation ) {
179  const auto &placement = mOrigPlacements[ index ];
180  auto fraction = std::max( 0.f, placement.fraction );
181  wxCoord coord = ( (partial + fraction ) / total ) * totalHeight;
182  auto height = coord - lastCoord;
183  result.emplace_back( height );
184  mNewPlacements[ index ].fraction = height;
185  lastCoord = coord;
186  partial += fraction;
187  }
188  return result;
189  }
190 
191  void UpdateViews( bool rollback )
192  {
193  auto pView = mwView.lock();
194  if ( pView ) {
195  auto pTrack = static_cast< WaveTrack* >( pView->FindTrack().get() );
196  for ( auto pChannel : TrackList::Channels<WaveTrack>( pTrack ) )
198  rollback ? mOrigPlacements : mNewPlacements );
199  }
200  }
201 
202  std::weak_ptr< WaveTrackView > mwView;
205  // Array mapping ordinal into the placement and subview arrays
206  std::vector< size_t > mPermutation;
207  // index into mPermutation
208  size_t mFirstSubView{};
209 };
210 
212 {
213 public:
214  enum { MinHeight = SubViewAdjuster::HotZoneSize };
215 
216  static UIHandlePtr HitTest( std::weak_ptr<UIHandle> &holder,
217  WaveTrackView &view,
218  WaveTrackSubView &subView,
219  const TrackPanelMouseState &state )
220  {
221  if ( !view.GetMultiView() )
222  return {};
223 
224  SubViewAdjuster adjuster{ view };
225  auto hit = adjuster.HitTest( subView,
226  state.state.GetY(), state.rect.GetTop(), state.rect.GetHeight() );
227  auto index = hit.first;
228 
229  if ( index < adjuster.mPermutation.size() ) {
230  UIHandlePtr result = std::make_shared< SubViewAdjustHandle >(
231  std::move( adjuster ), index, view.GetLastHeight(), hit.second
232  );
233  result = AssignUIHandlePtr( holder, result );
234  return result;
235  }
236  else
237  return {};
238  }
239 
241  SubViewAdjuster &&adjuster, size_t subViewIndex,
242  wxCoord viewHeight, bool top )
243  : mAdjuster{ std::move( adjuster ) }
244  , mMySubView{ subViewIndex }
245  , mViewHeight{ viewHeight }
246  , mTop{ top }
247  {
248  if ( mAdjuster.ModifyPermutation( top ) )
249  --mMySubView;
250  }
251 
253  const TrackPanelMouseEvent &event, AudacityProject *pProject ) override
254  {
255  using namespace RefreshCode;
256  const auto &permutation = mAdjuster.mPermutation;
257  const auto size = permutation.size();
258  if ( mMySubView >= size )
259  return Cancelled;
260 
261  if (event.event.LeftDClick()) {
262  for ( auto &placement : mAdjuster.mNewPlacements ) {
263  if ( placement.index >= 0 )
264  placement.fraction = 1.0f;
265  else
266  placement.fraction = 0.0f;
267  }
268  mAdjuster.UpdateViews( false );
269  ProjectHistory::Get( *pProject ).ModifyState( false );
270 
271  // Do not start a drag
272  return Cancelled | RefreshAll;
273  }
274 
275  const auto &rect = event.rect;
276  const auto height = rect.GetHeight();
277  mOrigHeight = height;
278 
279  mOrigHeights = mAdjuster.ComputeHeights( mViewHeight );
280 
281  // Find the total height of the sub-views that may resize
282  mTotalHeight = 0;
283  auto index = ( mTop ? mAdjuster.mFirstSubView : mMySubView );
284  const auto end = ( mTop ? mMySubView + 1 : permutation.size() );
285  for (; index != end; ++index)
286  mTotalHeight += mOrigHeights[ index ];
287 
288  wxASSERT( height == mOrigHeights[ mMySubView ] );
289 
290  // Compute the maximum and minimum Y coordinates for drag effect
291  if ( mTop ) {
292  mOrigY = rect.GetTop();
293  mYMax = rect.GetBottom();
294  mYMin = mYMax - mTotalHeight + 1;
295  }
296  else {
297  mOrigY = rect.GetBottom();
298  mYMin = rect.GetTop();
299  mYMax = mYMin + mTotalHeight - 1;
300  }
301 
302  return RefreshNone;
303  }
304 
305  Result Drag( const TrackPanelMouseEvent &event, AudacityProject * ) override
306  {
307  using namespace RefreshCode;
308  auto pView = mAdjuster.mwView.lock();
309  if ( !pView )
310  return Cancelled;
311 
312  // Find new height for the dragged sub-view
313  auto newY = std::max( mYMin, std::min( mYMax, event.event.GetY() ) );
314  const auto delta = newY - mOrigY;
315  wxCoord newHeight = mTop
316  ? mOrigHeight - delta
317  : mOrigHeight + delta
318  ;
319  wxASSERT( newHeight >= 0 && newHeight <= mTotalHeight );
320  if ( newHeight < MinHeight )
321  // Snap the dragged sub-view to nothing
322  newHeight = 0;
323 
324  // Reassign height for the dragged sub-view
325  auto &myPlacement =
326  mAdjuster.mNewPlacements[ mAdjuster.mPermutation[ mMySubView ] ];
327  myPlacement.fraction = newHeight;
328 
329  // Grow or shrink other sub-views
330  auto excess = newHeight - mOrigHeight; // maybe negative
331  const auto adjustHeight = [&](size_t ii) {
332  if (excess == 0)
333  return true;
334 
335  const auto oldFraction = mOrigHeights[ ii ];
336 
337  auto index = mAdjuster.mPermutation[ ii ];
338  auto &placement = mAdjuster.mNewPlacements[ index ];
339  auto &fraction = placement.fraction;
340 
341  if (excess > oldFraction) {
342  excess -= oldFraction, fraction = 0;
343  return false;
344  }
345  else {
346  auto newFraction = oldFraction - excess;
347  if ( newFraction < MinHeight ) {
348  // This snaps very short sub-views to nothing
349  myPlacement.fraction += newFraction;
350  fraction = 0;
351  }
352  else
353  fraction = newFraction;
354  return true;
355  }
356  };
357  if ( mTop ) {
358  for ( size_t ii = mMySubView; ii > 0; ) {
359  --ii;
360  if ( adjustHeight( ii ) )
361  break;
362  }
363  }
364  else {
365  for ( size_t ii = mMySubView + 1, size = mAdjuster.mPermutation.size();
366  ii < size; ++ii
367  ) {
368  if ( adjustHeight( ii ) )
369  break;
370  }
371  }
372 
373  // Save adjustment to the track and request a redraw
374  mAdjuster.UpdateViews( false );
375  return RefreshAll;
376  }
377 
379  const TrackPanelMouseState &state, AudacityProject * ) override
380  {
381  static auto resizeCursor =
382  ::MakeCursor(wxCURSOR_ARROW, SubViewsCursorXpm, 16, 16);
383  return {
384  XO(
385 "Click and drag to adjust sizes of sub-views, double-click to split evenly"),
386  &*resizeCursor
387  };
388  }
389 
391  const TrackPanelMouseEvent &event, AudacityProject *pProject,
392  wxWindow *pParent) override
393  {
394  ProjectHistory::Get( *pProject ).ModifyState( false );
396  }
397 
399  {
400  mAdjuster.UpdateViews( true );
402  }
403 
404 private:
405 
407  std::vector<wxCoord> mOrigHeights;
408 
409  // An index into mAdjuster.mPermutation
410  size_t mMySubView{};
411 
412  wxCoord mYMin{}, mYMax{};
413  wxCoord mViewHeight{}; // Total height of all sub-views
414  wxCoord mTotalHeight{}; // Total height of adjusting sub-views only
415  wxCoord mOrigHeight{};
416  wxCoord mOrigY{};
417 
418  // Whether we drag the top or the bottom of the sub-view
419  bool mTop{};
420 };
421 
423 {
424 public:
425  // Make it somewhat wider than the close button
426  enum { HotZoneWidth = 3 * kTrackInfoBtnSize / 2 };
427 
428  static UIHandlePtr HitTest( std::weak_ptr<UIHandle> &holder,
429  WaveTrackView &view, WaveTrackSubView &subView,
430  const TrackPanelMouseState &state )
431  {
432  if ( !view.GetMultiView() )
433  return {};
434 
435  SubViewAdjuster adjuster{ view };
436  if ( adjuster.NVisible() < 2 )
437  return {};
438 
439  auto relX = state.state.GetX() - state.rect.GetLeft();
440  if ( relX >= HotZoneWidth )
441  return {};
442 
443  auto index = adjuster.FindIndex( subView );
444 
445  // Hit on the rearrange cursor only in the top and bottom thirds of
446  // sub-view height, leaving the rest free to hit the selection cursor
447  // first.
448  // And also exclude the top third of the topmost sub-view and bottom
449  // third of bottommost.
450  auto relY = state.state.GetY() - state.rect.GetTop();
451  auto height = state.rect.GetHeight();
452  bool hit =
453  ( ( 3 * relY < height ) && index > 0 ) // top hit
454  ||
455  ( ( 3 * relY > 2 * height ) &&
456  index < adjuster.mPermutation.size() - 1 ) // bottom
457  ;
458  if ( ! hit )
459  return {};
460 
461  UIHandlePtr result = std::make_shared< SubViewRearrangeHandle >(
462  std::move( adjuster ),
463  index, view.GetLastHeight()
464  );
465  result = AssignUIHandlePtr( holder, result );
466  return result;
467  }
468 
470  SubViewAdjuster &&adjuster, size_t subViewIndex,
471  wxCoord viewHeight )
472  : mAdjuster{ std::move( adjuster ) }
473  , mMySubView{ subViewIndex }
474  , mViewHeight{ viewHeight }
475  {
476  }
477 
479  const TrackPanelMouseEvent &event, AudacityProject *pProject ) override
480  {
481  using namespace RefreshCode;
482  const auto &permutation = mAdjuster.mPermutation;
483  const auto size = permutation.size();
484  if ( mMySubView >= size )
485  return Cancelled;
486 
487  mHeights = mAdjuster.ComputeHeights( mViewHeight );
488 
489  // Find y coordinate of first sub-view
490  wxCoord heightAbove = 0;
491  for (auto index = mAdjuster.mFirstSubView;
492  index != mMySubView; ++index)
493  heightAbove += mHeights[ index ];
494  mTopY = event.rect.GetTop() - heightAbove;
495 
496  return RefreshNone;
497  }
498 
499  bool Clicked() const { return !mHeights.empty(); }
500 
501  enum DragChoice_t{ Upward, Downward, Neutral };
502 
504  {
505  // Disregard x coordinate -- so the mouse need not be in any sub-view,
506  // just in the correct range of y coordinates
507  auto yy = event.event.GetY();
508  auto coord = mTopY;
509  size_t ii = mAdjuster.mFirstSubView;
510  if ( yy < mTopY )
511  return ( mMySubView == ii ) ? Neutral : Upward;
512 
513  for ( auto nn = mHeights.size(); ii < nn; ++ii ) {
514  const auto height = mHeights[ ii ];
515  coord += height;
516  if ( yy < coord )
517  break;
518  }
519 
520  if ( ii < mMySubView ) {
521  if ( yy < coord - mHeights[ ii ] + mHeights[ mMySubView ] )
522  return Upward;
523  }
524 
525  if ( ii > mMySubView ) {
526  if( mMySubView < mHeights.size() - 1 &&
527  yy >= coord - mHeights[ mMySubView ] )
528  return Downward;
529  }
530 
531  return Neutral;
532  }
533 
534  Result Drag( const TrackPanelMouseEvent &event, AudacityProject * ) override
535  {
536  using namespace RefreshCode;
537  auto pView = mAdjuster.mwView.lock();
538  if ( !pView )
539  return Cancelled;
540 
541  switch( DragChoice( event ) ) {
542  case Upward:
543  {
544  std::swap( mHeights[ mMySubView ], mHeights[ mMySubView - 1 ] );
545  std::swap(
546  mAdjuster.mNewPlacements[ mMySubView ].index,
547  mAdjuster.mNewPlacements[ mMySubView - 1 ].index
548  );
549  --mMySubView;
550  break;
551  }
552  case Downward:
553  {
554  std::swap( mHeights[ mMySubView ], mHeights[ mMySubView + 1 ] );
555  std::swap(
556  mAdjuster.mNewPlacements[ mMySubView ].index,
557  mAdjuster.mNewPlacements[ mMySubView + 1 ].index
558  );
559  ++mMySubView;
560  break;
561  }
562  default:
563  return RefreshNone;
564  }
565 
566  // Save adjustment to the track and request a redraw
567  mAdjuster.UpdateViews( false );
568  return RefreshAll;
569  }
570 
572  const TrackPanelMouseState &state, AudacityProject * ) override
573  {
574  static auto hoverCursor =
575  ::MakeCursor(wxCURSOR_HAND, RearrangeCursorXpm, 16, 16);
576  static auto clickedCursor =
577  ::MakeCursor(wxCURSOR_HAND, RearrangingCursorXpm, 16, 16);
578  return {
579  XO("Click and drag to rearrange sub-views"),
580  Clicked() ? &*clickedCursor : &*hoverCursor,
581  XO("Rearrange sub-views")
582  };
583  }
584 
586  const TrackPanelMouseEvent &event, AudacityProject *pProject,
587  wxWindow *pParent) override
588  {
589  ProjectHistory::Get( *pProject ).ModifyState( false );
591  }
592 
594  {
595  mAdjuster.UpdateViews( true );
597  }
598 
599 private:
600 
602  std::vector<wxCoord> mHeights;
603  wxCoord mTopY;
604 
605  // An index into mAdjuster.mPermutation
606  size_t mMySubView{};
607 
608  wxCoord mViewHeight{}; // Total height of all sub-views
609 };
610 
612 {
613  static wxRect GetButtonRect( const wxRect &rect )
614  {
615  return {
616  rect.GetLeft(),
617  rect.GetTop(),
620  };
621  }
622 
623 public:
624  static UIHandlePtr HitTest( std::weak_ptr<UIHandle> &holder,
625  WaveTrackView &view, WaveTrackSubView &subView,
626  const TrackPanelMouseState &state )
627  {
628  SubViewAdjuster adjuster{ view };
629  if ( adjuster.NVisible() < 2 )
630  return {};
631 
632  const auto rect = GetButtonRect( state.rect );
633  if ( !rect.Contains( state.state.GetPosition() ) )
634  return {};
635  auto index = adjuster.FindIndex( subView );
636  UIHandlePtr result = std::make_shared<SubViewCloseHandle>(
637  std::move( adjuster ), index, view.FindTrack(), rect );
638  result = AssignUIHandlePtr( holder, result );
639  return result;
640  }
641 
643  SubViewAdjuster &&adjuster, size_t index,
644  const std::shared_ptr<Track> &pTrack, const wxRect &rect )
645  : ButtonHandle{ pTrack, rect }
646  , mAdjuster{ std::move( adjuster ) }
647  , mMySubView{ index }
648  {
649  }
650 
652  const wxMouseEvent &event, AudacityProject *pProject, wxWindow *pParent)
653  override
654  {
655  ProjectHistory::Get( *pProject ).ModifyState( false );
656  auto &myPlacement =
657  mAdjuster.mNewPlacements[ mAdjuster.mPermutation[ mMySubView ] ];
658  myPlacement.fraction = 0;
659  mAdjuster.UpdateViews( false );
661  }
662 
664  const wxMouseState &state, AudacityProject &project) const override
665  {
666  return XO("Close sub-view");
667  }
668 
669  // TrackPanelDrawable implementation
670  void Draw(
671  TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass )
672  override
673  {
674  if ( iPass == TrackArtist::PassMargins ) { // after PassTracks
676  context, GetButtonRect(rect), GetTrack().get(), this );
677  }
678  }
679 
680 private:
682  size_t mMySubView{};
683 };
684 
685 }
686 
687 std::pair<
688  bool, // if true, hit-testing is finished
689  std::vector<UIHandlePtr>
691  const TrackPanelMouseState &state,
692  const AudacityProject *pProject, int currentTool, bool bMultiTool,
693  const std::shared_ptr<WaveTrack> &wt)
694 {
695  auto results = WaveTrackView::DoDetailedHitTest(
696  state, pProject, currentTool, bMultiTool, wt, *this );
697  if ( results.first )
698  return results;
699 
700  auto pWaveTrackView = mwWaveTrackView.lock();
701  if ( pWaveTrackView && !state.state.HasModifiers() ) {
702  if ( auto pHandle = SubViewCloseHandle::HitTest(
703  mCloseHandle,
704  *pWaveTrackView, *this, state ) )
705  results.second.push_back( pHandle );
706  if ( auto pHandle = SubViewAdjustHandle::HitTest(
707  mAdjustHandle,
708  *pWaveTrackView, *this, state ) )
709  results.second.push_back( pHandle );
710  if ( auto pHandle = SubViewRearrangeHandle::HitTest(
711  mRearrangeHandle,
712  *pWaveTrackView, *this, state ) )
713  results.second.push_back( pHandle );
714  }
715  if (auto result = CutlineHandle::HitTest(
716  mCutlineHandle, state.state, state.rect,
717  pProject, wt ))
718  // This overriding test applies in all tools
719  results.second.push_back(result);
720 
721  return results;
722 }
723 
724 
726  TrackPanelDrawingContext &context, const WaveTrack *track,
727  const wxRect &rect )
728 {
729  auto &dc = context.dc;
730  const auto artist = TrackArtist::Get( context );
731 
732  const auto &zoomInfo = *artist->pZoomInfo;
733 
734 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
735  auto target2 = dynamic_cast<CutlineHandle*>(context.target.get());
736 #endif
737  for (const auto loc : track->GetCachedLocations()) {
738  bool highlightLoc = false;
739 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
740  highlightLoc =
741  target2 && target2->GetTrack().get() == track &&
742  target2->GetLocation() == loc;
743 #endif
744  const int xx = zoomInfo.TimeToPosition(loc.pos);
745  if (xx >= 0 && xx < rect.width) {
746  dc.SetPen( highlightLoc ? AColor::uglyPen : *wxGREY_PEN );
747  AColor::Line(dc, (int) (rect.x + xx - 1), rect.y, (int) (rect.x + xx - 1), rect.y + rect.height);
748  if (loc.typ == WaveTrackLocation::locationCutLine) {
749  dc.SetPen( highlightLoc ? AColor::uglyPen : *wxRED_PEN );
750  }
751  else {
752 #ifdef EXPERIMENTAL_DA
753  // JKC Black does not show up enough.
754  dc.SetPen(highlightLoc ? AColor::uglyPen : *wxWHITE_PEN);
755 #else
756  dc.SetPen(highlightLoc ? AColor::uglyPen : *wxBLACK_PEN);
757 #endif
758  }
759  AColor::Line(dc, (int) (rect.x + xx), rect.y, (int) (rect.x + xx), rect.y + rect.height);
760  dc.SetPen( highlightLoc ? AColor::uglyPen : *wxGREY_PEN );
761  AColor::Line(dc, (int) (rect.x + xx + 1), rect.y, (int) (rect.x + xx + 1), rect.y + rect.height);
762  }
763  }
764 }
765 
766 std::weak_ptr<WaveTrackView> WaveTrackSubView::GetWaveTrackView() const
767 {
768  return mwWaveTrackView;
769 }
770 
772 {
773  return static_cast< WaveTrackView& >( TrackView::Get( track ) );
774 }
775 
777 {
778  return Get( const_cast<WaveTrack&>( track ) );
779 }
780 
781 WaveTrackView::WaveTrackView( const std::shared_ptr<Track> &pTrack )
782  : CommonTrackView{ pTrack }
783 {
784 }
785 
787  : CommonTrackView( waveTrackView.FindTrack() )
788 {
789  mwWaveTrackView = std::static_pointer_cast<WaveTrackView>(
790  waveTrackView.shared_from_this() );
791 }
792 
794 {
795 }
796 
797 void WaveTrackView::CopyTo( Track &track ) const
798 {
799  TrackView::CopyTo( track );
800  auto &other = TrackView::Get( track );
801 
802  if ( const auto pOther = dynamic_cast< WaveTrackView* >( &other ) ) {
803  // only these fields are important to preserve in undo/redo history
804  pOther->RestorePlacements( SavePlacements() );
805  pOther->mMultiView = mMultiView;
806  }
807 }
808 
809 std::vector<UIHandlePtr> WaveTrackView::DetailedHitTest
810 (const TrackPanelMouseState &st,
811  const AudacityProject *pProject, int currentTool, bool bMultiTool)
812 {
813  // should not come here any more, delegation to sub-view instead
814  wxASSERT( false );
815  return {};
816 }
817 
818 std::pair< bool, std::vector<UIHandlePtr> >
820 (const TrackPanelMouseState &st,
821  const AudacityProject *pProject, int currentTool, bool bMultiTool,
822  const std::shared_ptr<WaveTrack> &pTrack,
823  CommonTrackView &view)
824 {
825  // common hit-testing for different sub-view types, to help implement their
826  // DetailedHitTest()
827 
828  // This is the only override of Track::DetailedHitTest that still
829  // depends on the state of the Tools toolbar.
830  // If that toolbar were eliminated, this could simplify to a sequence of
831  // hit test routines describable by a table.
832 
833  UIHandlePtr result;
834  std::vector<UIHandlePtr> results;
835 
836  if (bMultiTool && st.state.CmdDown()) {
837  // Ctrl modifier key in multi-tool overrides everything else
838  // (But this does not do the time shift constrained to the vertical only,
839  // which is what happens when you hold Ctrl in the Time Shift tool mode)
841  view.mTimeShiftHandle, pTrack, false);
842  if (result)
843  results.push_back(result);
844  return { true, results };
845  }
846  return { false, results };
847 }
848 
850  -> std::vector< WaveTrackSubView::Type >
851 {
852  BuildSubViews();
853 
854  // Collect the display types of visible views and sort them by position
855  using Pair = std::pair< int, WaveTrackSubView::Type >;
856  std::vector< Pair > pairs;
857  size_t ii = 0;
858  WaveTrackSubViews::ForEach( [&]( const WaveTrackSubView &subView ){
859  auto &placement = mPlacements[ii];
860  if ( placement.fraction > 0 )
861  pairs.emplace_back( placement.index, subView.SubViewType() );
862  ++ii;
863  } );
864  std::sort( pairs.begin(), pairs.end() );
865  std::vector< WaveTrackSubView::Type > results;
866  for ( const auto &pair : pairs )
867  results.push_back( pair.second );
868  return results;
869 }
870 
871 void WaveTrackView::SetDisplay(Display display, bool exclusive)
872 {
873  BuildSubViews();
874  DoSetDisplay( display, exclusive );
875 }
876 
878 {
879  size_t ii = 0;
880  size_t found = 0;
881  if ( WaveTrackSubViews::FindIf( [&]( const WaveTrackSubView &subView ) {
882  if ( subView.SubViewType().id == display ) {
883  found = ii;
884  return true;
885  }
886  ++ii;
887  return false;
888  } ) ) {
889  auto &foundPlacement = mPlacements[found];
890  if ( foundPlacement.fraction > 0.0 ) {
891  // Toggle off
892 
893  if (GetDisplays().size() < 2)
894  // refuse to do it
895  return false;
896 
897  auto index = foundPlacement.index;
898  foundPlacement = { -1, 0.0 };
899  if (index >= 0) {
900  for ( auto &placement : mPlacements ) {
901  if ( placement.index > index )
902  --placement.index;
903  }
904  }
905 
906  return true;
907  }
908  else {
909  // Toggle on
910  float total = 0;
911  int greatest = -1;
912  unsigned nn = 0;
913  for ( const auto &placement : mPlacements ) {
914  if ( placement.fraction > 0.0 && placement.index >= 0 ) {
915  total += placement.fraction;
916  greatest = std::max( greatest, placement.index );
917  ++nn;
918  }
919  }
920  // Turn on the sub-view, putting it lowest, and with average of the
921  // heights of the other sub-views
922  foundPlacement = { greatest + 1, total / nn };
923 
924  return true;
925  }
926  }
927  else
928  // unknown sub-view
929  return false;
930 }
931 
932 // If exclusive, make the chosen view take up all the height. Else,
933 // partition equally, putting the specified view on top.
934 // Be sure the sequence in which the other views appear is determinate.
935 void WaveTrackView::DoSetDisplay(Display display, bool exclusive)
936 {
937  // Some generality here anticipating more than two views.
938  // The order of sub-views in the array is not specified, so make it definite
939  // by sorting by the view type constants.
940  size_t ii = 0;
941  std::vector< std::pair< WaveTrackViewConstants::Display, size_t > > pairs;
942  WaveTrackSubViews::ForEach( [&pairs, &ii]( WaveTrackSubView &subView ){
943  pairs.push_back( { subView.SubViewType().id, ii++ } );
944  } );
945  std::sort( pairs.begin(), pairs.end() );
946 
947  int jj = 1;
948  for ( const auto &pair : pairs ) {
949  auto &placement = mPlacements[ pair.second ];
950  if (pair.first == display) {
951  // 0 for first view
952  placement = { 0, 1.0 };
953  }
954  else if( exclusive )
955  // -1 for not displayed
956  placement = { -1, 0.0 };
957  else
958  // positions other than the first.
959  // (Note that the fractions in the placement don't need to be
960  // denominated to 1. Just make them all equal to get an equal
961  // partitioning of the sub-views.)
962  placement = { jj++, 1.0 };
963  }
964 }
965 
966 auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement
967 {
968  BuildSubViews();
969 
970  // Collect the visible views in the right sequence
971  struct Item {
972  int index; float fraction; std::shared_ptr< TrackView > pView;
973  };
974  std::vector< Item > items;
975  size_t ii = 0;
976  float total = 0;
978  auto &placement = mPlacements[ii];
979  auto index = placement.index;
980  auto fraction = placement.fraction;
981  if ( index >= 0 && fraction > 0.0 )
982  total += fraction,
983  items.push_back( { index, fraction, subView.shared_from_this() } );
984  ++ii;
985  } );
986  std::sort( items.begin(), items.end(), [](const Item &a, const Item &b){
987  return a.index < b.index;
988  } );
989 
990  // Remove views we don't need
991  auto begin = items.begin(), end = items.end(),
992  newEnd = std::remove_if( begin, end,
993  []( const Item &item ){ return !item.pView; } );
994  items.erase( newEnd, end );
995 
996  // Assign coordinates, redenominating to the total height,
997  // storing integer values
998  Refinement results;
999  results.reserve( items.size() );
1000  const auto top = rect.GetTop();
1001  const auto height = rect.GetHeight();
1002  float partial = 0;
1003  wxCoord lastCoord = 0;
1004  for ( const auto &item : items ) {
1005  wxCoord newCoord = top + (partial / total) * height;
1006  results.emplace_back( newCoord, item.pView );
1007  partial += item.fraction;
1008  }
1009 
1010  // Cache for the use of sub-view dragging
1011  mLastHeight = height;
1012 
1013  return results;
1014 }
1015 
1016 std::vector< std::shared_ptr< WaveTrackSubView > >
1018 {
1019  BuildSubViews();
1020 
1021  std::vector< std::shared_ptr< WaveTrackSubView > > results;
1023  results.push_back( std::static_pointer_cast<WaveTrackSubView>(
1024  subView.shared_from_this() ) );
1025  } );
1026  return results;
1027 }
1028 
1029 std::shared_ptr<CommonTrackCell> WaveTrackView::DoGetAffordanceControls()
1030 {
1031  return std::make_shared<WaveTrackAffordanceControls>(FindTrack());
1032 }
1033 
1034 void WaveTrackView::DoSetMinimized( bool minimized )
1035 {
1036  BuildSubViews();
1037 
1038  // May come here. Invoke also on sub-views.
1039  TrackView::DoSetMinimized( minimized );
1040  WaveTrackSubViews::ForEach( [minimized](WaveTrackSubView &subView){
1041  subView.DoSetMinimized( minimized );
1042  } );
1043 }
1044 
1046 template<> template<> auto DoGetWaveTrackView::Implementation() -> Function {
1047  return [](WaveTrack &track) {
1048  return std::make_shared<WaveTrackView>( track.SharedPointer() );
1049  };
1050 }
1052 
1053 std::shared_ptr<TrackVRulerControls> WaveTrackView::DoGetVRulerControls()
1054 {
1055  // This should never be called because of delegation to the spectrum or
1056  // waveform sub-view
1057  wxASSERT( false );
1058  return {};
1059 }
1060 
1061 #undef PROFILE_WAVEFORM
1062 #ifdef PROFILE_WAVEFORM
1063 #ifdef __WXMSW__
1064 #include <time.h>
1065 #else
1066 #include <sys/time.h>
1067 #endif
1068 double gWaveformTimeTotal = 0;
1069 int gWaveformTimeCount = 0;
1070 
1071 namespace {
1072  struct Profiler {
1073  Profiler()
1074  {
1075 # ifdef __WXMSW__
1076  _time64(&tv0);
1077 # else
1078  gettimeofday(&tv0, NULL);
1079 # endif
1080  }
1081 
1082  ~Profiler()
1083  {
1084 # ifdef __WXMSW__
1085  _time64(&tv1);
1086  double elapsed = _difftime64(tv1, tv0);
1087 # else
1088  gettimeofday(&tv1, NULL);
1089  double elapsed =
1090  (tv1.tv_sec + tv1.tv_usec*0.000001) -
1091  (tv0.tv_sec + tv0.tv_usec*0.000001);
1092 # endif
1093  gWaveformTimeTotal += elapsed;
1094  gWaveformTimeCount++;
1095  wxPrintf(wxT("Avg waveform drawing time: %f\n"),
1096  gWaveformTimeTotal / gWaveformTimeCount);
1097  }
1098 
1099 # ifdef __WXMSW__
1100  __time64_t tv0, tv1;
1101 #else
1102  struct timeval tv0, tv1;
1103 #endif
1104  };
1105 }
1106 #endif
1107 
1109  (bool spectrum, const WaveTrack *track, const WaveClip *clip, const wxRect &rect,
1110  const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo)
1111 {
1112  tOffset = clip->GetOffset();
1113  rate = clip->GetRate();
1114 
1115  h = zoomInfo.PositionToTime(0, 0
1116  , true
1117  );
1118  h1 = zoomInfo.PositionToTime(rect.width, 0
1119  , true
1120  );
1121 
1122  double sel0 = selectedRegion.t0(); //left selection bound
1123  double sel1 = selectedRegion.t1(); //right selection bound
1124 
1125  //If the track isn't selected, make the selection empty
1126  if (!track->GetSelected() &&
1127  (spectrum || !track->IsSyncLockSelected())) { // PRL: why was there a difference for spectrum?
1128  sel0 = sel1 = 0.0;
1129  }
1130 
1131  const double trackLen = clip->GetEndTime() - clip->GetStartTime();
1132 
1133  tpre = h - tOffset; // offset corrected time of
1134  // left edge of display
1135  tpost = h1 - tOffset; // offset corrected time of
1136  // right edge of display
1137 
1138  const double sps = 1. / rate; //seconds-per-sample
1139 
1140  // Determine whether we should show individual samples
1141  // or draw circular points as well
1142  averagePixelsPerSample = rect.width / (rate * (h1 - h));
1144 
1145  // Calculate actual selection bounds so that t0 > 0 and t1 < the
1146  // end of the track
1147  t0 = (tpre >= 0.0 ? tpre : 0.0);
1148  t1 = (tpost < trackLen - sps * .99 ? tpost : trackLen - sps * .99);
1149  if (showIndividualSamples) {
1150  // adjustment so that the last circular point doesn't appear
1151  // to be hanging off the end
1152  t1 += 2. / (averagePixelsPerSample * rate);
1153  }
1154 
1155  // Make sure t1 (the right bound) is greater than 0
1156  if (t1 < 0.0) {
1157  t1 = 0.0;
1158  }
1159 
1160  // Make sure t1 is greater than t0
1161  if (t0 > t1) {
1162  t0 = t1;
1163  }
1164 
1165  // Use the WaveTrack method to show what is selected and 'should' be copied, pasted etc.
1166  ssel0 = std::max(sampleCount(0), spectrum
1167  ? sampleCount((sel0 - tOffset) * rate + .99) // PRL: why?
1168  : track->TimeToLongSamples(sel0 - tOffset)
1169  );
1170  ssel1 = std::max(sampleCount(0), spectrum
1171  ? sampleCount((sel1 - tOffset) * rate + .99) // PRL: why?
1172  : track->TimeToLongSamples(sel1 - tOffset)
1173  );
1174 
1175  //trim selection so that it only contains the actual samples
1176  if (ssel0 != ssel1 && ssel1 > (sampleCount)(0.5 + trackLen * rate)) {
1177  ssel1 = sampleCount( 0.5 + trackLen * rate );
1178  }
1179 
1180  // The variable "hiddenMid" will be the rectangle containing the
1181  // actual waveform, as opposed to any blank area before
1182  // or after the track, as it would appear without the fisheye.
1183  hiddenMid = rect;
1184 
1185  // If the left edge of the track is to the right of the left
1186  // edge of the display, then there's some unused area to the
1187  // left of the track. Reduce the "hiddenMid"
1188  hiddenLeftOffset = 0;
1189  if (tpre < 0) {
1190  // Fix Bug #1296 caused by premature conversion to (int).
1191  wxInt64 time64 = zoomInfo.TimeToPosition(tOffset, 0 , true);
1192  if( time64 < 0 )
1193  time64 = 0;
1194  hiddenLeftOffset = (time64 < rect.width) ? (int)time64 : rect.width;
1195 
1197  hiddenMid.width -= hiddenLeftOffset;
1198  }
1199 
1200  // If the right edge of the track is to the left of the right
1201  // edge of the display, then there's some unused area to the right
1202  // of the track. Reduce the "hiddenMid" rect by the
1203  // size of the blank area.
1204  if (tpost > t1) {
1205  wxInt64 time64 = zoomInfo.TimeToPosition(tOffset+t1, 0 , true);
1206  if( time64 < 0 )
1207  time64 = 0;
1208  const int hiddenRightOffset = (time64 < rect.width) ? (int)time64 : rect.width;
1209 
1210  hiddenMid.width = std::max(0, hiddenRightOffset - hiddenLeftOffset);
1211  }
1212  // The variable "mid" will be the rectangle containing the
1213  // actual waveform, as distorted by the fisheye,
1214  // as opposed to any blank area before or after the track.
1215  mid = rect;
1216 
1217  // If the left edge of the track is to the right of the left
1218  // edge of the display, then there's some unused area to the
1219  // left of the track. Reduce the "mid"
1220  leftOffset = 0;
1221  if (tpre < 0) {
1222  wxInt64 time64 = zoomInfo.TimeToPosition(tOffset, 0 , false);
1223  if( time64 < 0 )
1224  time64 = 0;
1225  leftOffset = (time64 < rect.width) ? (int)time64 : rect.width;
1226 
1227  mid.x += leftOffset;
1228  mid.width -= leftOffset;
1229  }
1230 
1231  // If the right edge of the track is to the left of the right
1232  // edge of the display, then there's some unused area to the right
1233  // of the track. Reduce the "mid" rect by the
1234  // size of the blank area.
1235  if (tpost > t1) {
1236  wxInt64 time64 = zoomInfo.TimeToPosition(tOffset+t1, 0 , false);
1237  if( time64 < 0 )
1238  time64 = 0;
1239  const int distortedRightOffset = (time64 < rect.width) ? (int)time64 : rect.width;
1240 
1241  mid.width = std::max(0, distortedRightOffset - leftOffset);
1242  }
1243 }
1244 
1245 wxRect ClipParameters::GetClipRect(const WaveClip& clip, const ZoomInfo& zoomInfo, const wxRect& viewRect, int clipOffsetX)
1246 {
1247  auto srs = 1. / static_cast<double>(clip.GetRate());
1248  //to prevent overlap left and right most samples with frame border
1249  auto margin = .25 * srs;
1250  auto edgeLeft = static_cast<wxInt64>(viewRect.GetLeft());
1251  auto edgeRight = static_cast<wxInt64>(viewRect.GetRight());
1252  auto left = std::clamp(zoomInfo.TimeToPosition(clip.GetOffset() - margin, viewRect.x + clipOffsetX, true), edgeLeft, edgeRight);
1253  auto right = std::clamp(zoomInfo.TimeToPosition(clip.GetEndTime() - srs + margin, viewRect.x + clipOffsetX, true), edgeLeft, edgeRight);
1254  if (right - left > 0)
1255  {
1256  //after clamping we can expect that left and right
1257  //are small enough to be put into int
1258  return wxRect(static_cast<int>(left), viewRect.y, static_cast<int>(right - left), viewRect.height);
1259  }
1260  //off the screen
1261  return wxRect();
1262 }
1263 
1264 void WaveTrackView::Reparent( const std::shared_ptr<Track> &parent )
1265 {
1266  // BuildSubViews(); // not really needed
1267  CommonTrackView::Reparent( parent );
1268  WaveTrackSubViews::ForEach( [&parent](WaveTrackSubView &subView){
1269  subView.Reparent( parent );
1270  } );
1272  mpAffordanceCellControl->Reparent(parent);
1273 }
1274 
1275 std::weak_ptr<WaveClip> WaveTrackView::GetSelectedClip()
1276 {
1277  if (auto affordance = std::dynamic_pointer_cast<WaveTrackAffordanceControls>(GetAffordanceControls()))
1278  {
1279  return affordance->GetSelectedClip();
1280  }
1281  return {};
1282 }
1283 
1285 {
1286  if ( WaveTrackSubViews::size() == 0) {
1287  // On-demand steps that can't happen in the constructor
1288  auto pThis = const_cast<WaveTrackView*>( this );
1289  pThis->BuildAll();
1290  bool minimized = GetMinimized();
1291  pThis->WaveTrackSubViews::ForEach( [&]( WaveTrackSubView &subView ){
1292  subView.DoSetMinimized( minimized );
1293  } );
1294 
1295  if ( pThis->mPlacements.empty() ) {
1296  pThis->mPlacements.resize( WaveTrackSubViews::size() );
1297 
1298  auto pTrack = pThis->FindTrack();
1299  auto display = TracksPrefs::ViewModeChoice();
1300  bool multi = (display == WaveTrackViewConstants::MultiView);
1301  if ( multi ) {
1302  pThis->SetMultiView( true );
1303  display = WaveTrackSubViewType::Default();
1304  }
1305 
1306  pThis->DoSetDisplay( display, !multi );
1307  }
1308  }
1309 }
1310 
1312  TrackPanelDrawingContext &context,
1313  const wxRect &rect, unsigned iPass )
1314 {
1315  // Should not come here, drawing is now delegated to sub-views
1316  wxASSERT( false );
1317 
1318  CommonTrackView::Draw( context, rect, iPass );
1319 }
ClipParameters::tpost
double tpost
Definition: WaveTrackView.h:182
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
WaveTrackView::mPlacements
WaveTrackSubViewPlacements mPlacements
Definition: WaveTrackView.h:159
WaveTrackView::DetailedHitTest
std::vector< UIHandlePtr > DetailedHitTest(const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool) override
Definition: WaveTrackView.cpp:810
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::FindPermutation
void FindPermutation()
Definition: WaveTrackView.cpp:63
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle::GetButtonRect
static wxRect GetButtonRect(const wxRect &rect)
Definition: WaveTrackView.cpp:613
WaveTrackView::BuildSubViews
void BuildSubViews() const
Definition: WaveTrackView.cpp:1284
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< UIHandle > &holder, WaveTrackView &view, WaveTrackSubView &subView, const TrackPanelMouseState &state)
Definition: WaveTrackView.cpp:428
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
CommonTrackView
Definition: CommonTrackView.h:20
ClientData::Site::ForEach
void ForEach(const Function &function)
Invoke function on each ClientData object that has been created in this.
Definition: ClientData.h:380
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::Clicked
bool Clicked() const
Definition: WaveTrackView.cpp:499
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle
Definition: WaveTrackView.cpp:212
WaveTrackSubView::SubViewType
virtual const Type & SubViewType() const =0
ClipParameters::rate
double rate
Definition: WaveTrackView.h:178
WaveTrackView
Definition: WaveTrackView.h:77
WaveTrackView::DoGetAffordanceControls
std::shared_ptr< CommonTrackCell > DoGetAffordanceControls() override
Definition: WaveTrackView.cpp:1029
WaveTrackView::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: WaveTrackView.cpp:1311
RefreshCode::RefreshAll
@ RefreshAll
Definition: RefreshCode.h:26
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::Cancel
Result Cancel(AudacityProject *) override
Definition: WaveTrackView.cpp:398
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::mOrigPlacements
WaveTrackSubViewPlacements mOrigPlacements
Definition: WaveTrackView.cpp:204
TrackView::Get
static TrackView & Get(Track &)
Definition: TrackView.cpp:63
RefreshCode::RefreshNone
@ RefreshNone
Definition: RefreshCode.h:21
ClipParameters::averagePixelsPerSample
double averagePixelsPerSample
Definition: WaveTrackView.h:189
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster
Definition: WaveTrackView.cpp:51
CutlineHandle
Definition: CutlineHandle.h:22
TrackView::GetMinimized
bool GetMinimized() const
Definition: TrackView.h:49
SelectedRegion::t1
double t1() const
Definition: SelectedRegion.h:95
WaveTrackView::DoSetDisplay
void DoSetDisplay(Display display, bool exclusive=true)
Definition: WaveTrackView.cpp:935
WaveTrackView::GetAllSubViews
std::vector< std::shared_ptr< WaveTrackSubView > > GetAllSubViews()
Definition: WaveTrackView.cpp:1017
Profiler
A simple profiler to measure the average time lengths that a particular task/function takes....
Definition: Profiler.h:40
CommonTrackView::mTimeShiftHandle
std::weak_ptr< TimeShiftHandle > mTimeShiftHandle
Definition: CommonTrackView.h:48
WaveClip::GetOffset
double GetOffset() const
Definition: WaveClip.h:220
WaveTrackView::DoSetMinimized
void DoSetMinimized(bool minimized) override
Definition: WaveTrackView.cpp:1034
ClientData::Site::FindIf
ClientData * FindIf(const Function &function)
Return pointer to first attachment in this that is not null and satisfies a predicate,...
Definition: ClientData.h:412
ZoomInfo
Definition: ZoomInfo.h:47
WaveTrackSubViewType::id
Display id
Definition: WaveTrackViewConstants.h:96
WaveTrackSubViewType::Default
static Display Default()
Return a preferred type.
Definition: WaveTrackViewConstants.cpp:97
CommonTrackPanelCell::FindTrack
std::shared_ptr< Track > FindTrack()
Definition: CommonTrackPanelCell.h:44
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle::SubViewCloseHandle
SubViewCloseHandle(SubViewAdjuster &&adjuster, size_t index, const std::shared_ptr< Track > &pTrack, const wxRect &rect)
Definition: WaveTrackView.cpp:642
TrackPanelDrawingContext
Definition: TrackPanelDrawingContext.h:22
WaveClip::GetRate
int GetRate() const
Definition: WaveClip.h:208
MakeCursor
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:176
TrackView::Refinement
std::vector< std::pair< wxCoord, std::shared_ptr< TrackView > > > Refinement
Definition: TrackView.h:76
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:112
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::FindIndex
size_t FindIndex(WaveTrackSubView &subView) const
Definition: WaveTrackView.cpp:139
WaveTrackSubView::DrawBoldBoundaries
static void DrawBoldBoundaries(TrackPanelDrawingContext &context, const WaveTrack *track, const wxRect &rect)
Definition: WaveTrackView.cpp:725
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::Preview
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *) override
Definition: WaveTrackView.cpp:571
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::Preview
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *) override
Definition: WaveTrackView.cpp:378
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::UpdateViews
void UpdateViews(bool rollback)
Definition: WaveTrackView.cpp:191
WaveClip::GetEndTime
double GetEndTime() const
Definition: WaveClip.cpp:253
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::mAdjuster
SubViewAdjuster mAdjuster
Definition: WaveTrackView.cpp:601
WaveTrackView::GetSubViews
Refinement GetSubViews(const wxRect &rect) override
Definition: WaveTrackView.cpp:966
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle::Tip
TranslatableString Tip(const wxMouseState &state, AudacityProject &project) const override
Definition: WaveTrackView.cpp:663
XO
#define XO(s)
Definition: Internat.h:31
ClientData::Site::size
size_t size() const
How many attachment pointers are in the Site.
Definition: ClientData.h:251
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle
Definition: WaveTrackView.cpp:423
WaveTrackView::RestorePlacements
void RestorePlacements(const WaveTrackSubViewPlacements &placements)
Definition: WaveTrackView.h:113
WaveTrackView::GetMultiView
bool GetMultiView() const
Definition: WaveTrackView.h:127
ClipParameters::h
double h
Definition: WaveTrackView.h:179
kTrackInfoBtnSize
@ kTrackInfoBtnSize
Definition: ViewInfo.h:112
TrackPanelDrawingContext::dc
wxDC & dc
Definition: TrackPanelDrawingContext.h:23
WaveTrackView::GetSelectedClip
std::weak_ptr< WaveClip > GetSelectedClip()
Definition: WaveTrackView.cpp:1275
WaveTrackViewConstants::Display
Display
Definition: WaveTrackViewConstants.h:18
WaveTrackSubView::WaveTrackSubView
WaveTrackSubView(WaveTrackView &waveTrackView)
Definition: WaveTrackView.cpp:786
ClipParameters::hiddenLeftOffset
int hiddenLeftOffset
Definition: WaveTrackView.h:196
WaveTrackView::GetLastHeight
wxCoord GetLastHeight() const
Definition: WaveTrackView.h:125
TrackPanelMouseState::rect
const wxRect & rect
Definition: TrackPanelMouseEvent.h:39
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::NVisible
size_t NVisible() const
Definition: WaveTrackView.cpp:98
Track::IsSyncLockSelected
bool IsSyncLockSelected() const
Definition: Track.cpp:245
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:53
WaveTrackSubView
Definition: WaveTrackView.h:29
WaveTrack::GetCachedLocations
const std::vector< Location > & GetCachedLocations() const
Definition: WaveTrack.h:526
ClipParameters::ssel0
sampleCount ssel0
Definition: WaveTrackView.h:192
WaveTrackView::ToggleSubView
bool ToggleSubView(Display id)
Definition: WaveTrackView.cpp:877
WaveTrackSubView::DoDetailedHitTest
std::pair< bool, std::vector< UIHandlePtr > > DoDetailedHitTest(const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool, const std::shared_ptr< WaveTrack > &wt)
UIHandle
Short-lived drawing and event-handling object associated with a TrackPanelCell.
Definition: UIHandle.h:34
WaveTrackView.h
WaveClip::GetStartTime
double GetStartTime() const
Definition: WaveClip.cpp:247
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::ComputeHeights
std::vector< wxCoord > ComputeHeights(wxCoord totalHeight)
Definition: WaveTrackView.cpp:167
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< UIHandle > &holder, WaveTrackView &view, WaveTrackSubView &subView, const TrackPanelMouseState &state)
Definition: WaveTrackView.cpp:624
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::SubViewAdjuster
SubViewAdjuster(WaveTrackView &view)
Definition: WaveTrackView.cpp:54
ClipParameters::hiddenMid
wxRect hiddenMid
Definition: WaveTrackView.h:195
WaveTrackAffordanceControls.h
AttachedVirtualFunction::Override::Implementation
static Function Implementation()
A function returning a std::function that must be defined so that the program links.
Definition: LabelTrackControls.cpp:182
TracksPrefs::ViewModeChoice
static WaveTrackViewConstants::Display ViewModeChoice()
Definition: TracksPrefs.cpp:168
registerDoGetWaveTrackView
static DoGetWaveTrackView registerDoGetWaveTrackView
Definition: WaveTrackView.cpp:1051
WaveClip
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:173
CutlineHandle::GetTrack
std::shared_ptr< WaveTrack > GetTrack()
Definition: CutlineHandle.h:44
ClipParameters::showIndividualSamples
bool showIndividualSamples
Definition: WaveTrackView.h:190
TrackArtist::Get
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:78
WaveTrackView::WaveTrackView
WaveTrackView(const WaveTrackView &)=delete
Profiler::Profiler
Profiler()
private constructor - Singleton.
Definition: Profiler.h:56
ButtonHandle
A UIHandle for a TrackPanel button, such as the Mute and Solo buttons.
Definition: ButtonHandle.h:26
ClipParameters::ssel1
sampleCount ssel1
Definition: WaveTrackView.h:193
TrackInfo::DrawCloseButton
AUDACITY_DLL_API void DrawCloseButton(TrackPanelDrawingContext &context, const wxRect &bev, const Track *pTrack, ButtonHandle *target)
Definition: TrackInfo.cpp:266
BasicUI::Get
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:26
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::mOrigHeights
std::vector< wxCoord > mOrigHeights
Definition: WaveTrackView.cpp:407
TrackView::GetAffordanceControls
std::shared_ptr< CommonTrackCell > GetAffordanceControls()
Definition: TrackView.cpp:144
WaveTrackView::mMultiView
bool mMultiView
Definition: WaveTrackView.h:162
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle
Definition: WaveTrackView.cpp:612
UIHandle::Result
unsigned Result
Definition: UIHandle.h:37
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::mSubViews
WaveTrackSubViewPtrs mSubViews
Definition: WaveTrackView.cpp:203
CutlineHandle.h
CommonTrackView::HitTest
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &, const AudacityProject *pProject) final override
Definition: CommonTrackView.cpp:30
UIHandlePtr
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
WaveTrackView::~WaveTrackView
~WaveTrackView() override
Definition: WaveTrackView.cpp:793
anonymous_namespace{ProjectFileManager.cpp}::Pair
std::pair< const char *, const char * > Pair
Definition: ProjectFileManager.cpp:101
HitTestPreview
Definition: HitTestResult.h:20
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle::mAdjuster
SubViewAdjuster mAdjuster
Definition: WaveTrackView.cpp:681
AColor::uglyPen
static wxPen uglyPen
Definition: AColor.h:131
anonymous_namespace{NoteTrack.cpp}::swap
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:735
WaveTrackSubView::mwWaveTrackView
std::weak_ptr< WaveTrackView > mwWaveTrackView
Definition: WaveTrackView.h:60
WaveTrackSubViewPlacements
std::vector< WaveTrackSubViewPlacement > WaveTrackSubViewPlacements
Definition: WaveTrackView.h:67
TrackView::DoSetMinimized
virtual void DoSetMinimized(bool isMinimized)
Definition: TrackView.cpp:126
WaveTrackView::SavePlacements
const WaveTrackSubViewPlacements & SavePlacements() const
Definition: WaveTrackView.h:111
ClipParameters::tOffset
double tOffset
Definition: WaveTrackView.h:177
TrackView::mpAffordanceCellControl
std::shared_ptr< CommonTrackCell > mpAffordanceCellControl
Definition: TrackView.h:98
WaveTrackSubViewPlacement
Definition: WaveTrackView.h:63
anonymous_namespace{TrackPanel.cpp}::FindTrack
std::shared_ptr< Track > FindTrack(TrackPanelCell *pCell)
Definition: TrackPanel.cpp:524
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle::CommitChanges
Result CommitChanges(const wxMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: WaveTrackView.cpp:651
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::DragChoice_t
DragChoice_t
Definition: WaveTrackView.cpp:501
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::ModifyPermutation
bool ModifyPermutation(bool top)
Definition: WaveTrackView.cpp:101
ClipParameters::t0
double t0
Definition: WaveTrackView.h:186
WaveTrackView::GetDisplays
std::vector< WaveTrackSubView::Type > GetDisplays() const
Definition: WaveTrackView.cpp:849
Track::GetSelected
bool GetSelected() const
Definition: Track.h:415
ClipParameters::leftOffset
int leftOffset
Definition: WaveTrackView.h:199
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
SelectedRegion::t0
double t0() const
Definition: SelectedRegion.h:94
anonymous_namespace{WaveTrackView.cpp}::WaveTrackSubViewPtrs
std::vector< std::shared_ptr< WaveTrackSubView > > WaveTrackSubViewPtrs
Definition: WaveTrackView.cpp:46
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< UIHandle > &holder, WaveTrackView &view, WaveTrackSubView &subView, const TrackPanelMouseState &state)
Definition: WaveTrackView.cpp:216
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::Release
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: WaveTrackView.cpp:585
WaveTrack::TimeToLongSamples
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1770
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::DragChoice
DragChoice_t DragChoice(const TrackPanelMouseEvent &event) const
Definition: WaveTrackView.cpp:503
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::Drag
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *) override
Definition: WaveTrackView.cpp:534
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:113
WaveTrackView::Get
static WaveTrackView & Get(WaveTrack &track)
Definition: WaveTrackView.cpp:771
ClientData::Site::BuildAll
void BuildAll()
For each RegisteredFactory, if the corresponding attachment is absent in this, build and store it.
Definition: ClientData.h:441
ClipParameters::h1
double h1
Definition: WaveTrackView.h:181
TrackPanelMouseEvent
Definition: TrackPanelMouseEvent.h:46
ClipParameters::mid
wxRect mid
Definition: WaveTrackView.h:198
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::Click
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: WaveTrackView.cpp:252
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::Click
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: WaveTrackView.cpp:478
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
WaveTrackView::DoGetVRulerControls
std::shared_ptr< TrackVRulerControls > DoGetVRulerControls() override
Definition: WaveTrackView.cpp:1053
TrackView::CopyTo
void CopyTo(Track &track) const override
Definition: TrackView.cpp:52
anonymous_namespace{WaveTrackView.cpp}::SubViewCloseHandle::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: WaveTrackView.cpp:670
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::Cancel
Result Cancel(AudacityProject *) override
Definition: WaveTrackView.cpp:593
TrackPanelDrawingContext::target
UIHandlePtr target
Definition: TrackPanelDrawingContext.h:24
ClipParameters::t1
double t1
Definition: WaveTrackView.h:187
CommonTrackCell::Reparent
virtual void Reparent(const std::shared_ptr< Track > &parent)
Definition: CommonTrackPanelCell.cpp:64
WaveTrackSubView::GetWaveTrackView
std::weak_ptr< WaveTrackView > GetWaveTrackView() const
Definition: WaveTrackView.cpp:766
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::mAdjuster
SubViewAdjuster mAdjuster
Definition: WaveTrackView.cpp:406
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::SubViewRearrangeHandle
SubViewRearrangeHandle(SubViewAdjuster &&adjuster, size_t subViewIndex, wxCoord viewHeight)
Definition: WaveTrackView.cpp:469
AttachedVirtualFunction::Override
For defining overrides of the method.
Definition: AttachedVirtualFunction.h:190
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::mPermutation
std::vector< size_t > mPermutation
Definition: WaveTrackView.cpp:206
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
ClipParameters::tpre
double tpre
Definition: WaveTrackView.h:180
ClipParameters::ClipParameters
ClipParameters(bool spectrum, const WaveTrack *track, const WaveClip *clip, const wxRect &rect, const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo)
Definition: WaveTrackView.cpp:1109
WaveTrackLocation::locationCutLine
@ locationCutLine
Definition: WaveTrackLocation.h:17
WaveTrackView::Reparent
void Reparent(const std::shared_ptr< Track > &parent) override
Definition: WaveTrackView.cpp:1264
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::SubViewAdjustHandle
SubViewAdjustHandle(SubViewAdjuster &&adjuster, size_t subViewIndex, wxCoord viewHeight, bool top)
Definition: WaveTrackView.cpp:240
TrackArtist::PassMargins
@ PassMargins
Definition: TrackArtist.h:76
AssignUIHandlePtr
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:145
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::Release
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: WaveTrackView.cpp:390
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
WaveTrackView::SetDisplay
void SetDisplay(Display display, bool exclusive=true)
Definition: WaveTrackView.cpp:871
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::HitTest
std::pair< size_t, bool > HitTest(WaveTrackSubView &subView, wxCoord yy, wxCoord top, wxCoord height)
Definition: WaveTrackView.cpp:149
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjuster::mwView
std::weak_ptr< WaveTrackView > mwView
Definition: WaveTrackView.cpp:202
anonymous_namespace{WaveTrackView.cpp}::SubViewAdjustHandle::Drag
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *) override
Definition: WaveTrackView.cpp:305
TimeShiftHandle::HitAnywhere
static UIHandlePtr HitAnywhere(std::weak_ptr< TimeShiftHandle > &holder, const std::shared_ptr< Track > &pTrack, bool gripHit)
Definition: TimeShiftHandle.cpp:80
WaveTrackView::CopyTo
void CopyTo(Track &track) const override
Definition: WaveTrackView.cpp:797
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::mHeights
std::vector< wxCoord > mHeights
Definition: WaveTrackView.cpp:602
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::Upward
@ Upward
Definition: WaveTrackView.cpp:501
ClipParameters::GetClipRect
static wxRect GetClipRect(const WaveClip &clip, const ZoomInfo &zoomInfo, const wxRect &viewRect, int clipOffsetX=0)
Definition: WaveTrackView.cpp:1245
WaveTrackViewConstants::MultiView
@ MultiView
"Multi" is special, not really a view type on par with the others.
Definition: WaveTrackViewConstants.h:20
TrackPanelMouseEvent::event
wxMouseEvent & event
Definition: TrackPanelMouseEvent.h:58
WaveTrackView::DoDetailedHitTest
static std::pair< bool, std::vector< UIHandlePtr > > DoDetailedHitTest(const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool, const std::shared_ptr< WaveTrack > &wt, CommonTrackView &view)
Definition: WaveTrackView.cpp:820
TrackPanelMouseState::state
wxMouseState & state
Definition: TrackPanelMouseEvent.h:38
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
anonymous_namespace{WaveTrackView.cpp}::SubViewRearrangeHandle::mTopY
wxCoord mTopY
Definition: WaveTrackView.cpp:603
Profiler::~Profiler
virtual ~Profiler()
write to a profile at the end of the test.
Definition: Profiler.cpp:31
ZoomInfo::PositionToTime
double PositionToTime(wxInt64 position, wxInt64 origin=0, bool ignoreFisheye=false) const
Definition: ZoomInfo.cpp:43
SelectedRegion
Defines a selected portion of a project.
Definition: SelectedRegion.h:38
TrackPanelDrawable::Draw
virtual void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass)
Definition: TrackPanelDrawable.cpp:17