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