Audacity  3.0.3
TrackPanel.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  TrackPanel.cpp
6 
7  Dominic Mazzoni
8  and lots of other contributors
9 
10  Implements TrackPanel.
11 
12 ********************************************************************//***************************************************************//*****************************************************************//*****************************************************************/
45 
46 
47 #include "TrackPanel.h"
48 #include "TrackPanelConstants.h"
49 
50 #include <wx/app.h>
51 #include <wx/setup.h> // for wxUSE_* macros
52 
53 #include "AdornedRulerPanel.h"
55 #include "KeyboardCapture.h"
56 #include "Project.h"
57 #include "ProjectAudioIO.h"
58 #include "ProjectAudioManager.h"
59 #include "ProjectHistory.h"
60 #include "ProjectWindows.h"
61 #include "ProjectSettings.h"
62 #include "ProjectStatus.h"
63 #include "ProjectWindow.h"
64 #include "Theme.h"
65 #include "TrackPanelMouseEvent.h"
66 #include "TrackPanelResizeHandle.h"
67 //#define DEBUG_DRAW_TIMING 1
68 
69 #include "UndoManager.h"
70 
71 #include "AColor.h"
72 #include "AllThemeResources.h"
73 #include "AudioIO.h"
74 #include "float_cast.h"
75 
76 #include "Prefs.h"
77 #include "RefreshCode.h"
78 #include "TrackArtist.h"
79 #include "TrackPanelAx.h"
80 #include "TrackPanelResizerCell.h"
81 #include "WaveTrack.h"
82 
84 #include "tracks/ui/TrackView.h"
86 
87 //This loads the appropriate set of cursors, depending on platform.
88 #include "../images/Cursors.h"
89 
90 #include <algorithm>
91 
92 #include <wx/dc.h>
93 #include <wx/dcclient.h>
94 #include <wx/graphics.h>
95 
96 static_assert( kVerticalPadding == kTopMargin + kBottomMargin );
97 static_assert( kTrackInfoBtnSize == kAffordancesAreaHeight, "Drag bar is misaligned with the menu button");
98 
162 // Is the distance between A and B less than D?
163 template < class A, class B, class DIST > bool within(A a, B b, DIST d)
164 {
165  return (a > b - d) && (a < b + d);
166 }
167 
168 BEGIN_EVENT_TABLE(TrackPanel, CellularPanel)
169  EVT_MOUSE_EVENTS(TrackPanel::OnMouseEvent)
170  EVT_KEY_DOWN(TrackPanel::OnKeyDown)
171 
172  EVT_PAINT(TrackPanel::OnPaint)
173 
174  EVT_TIMER(wxID_ANY, TrackPanel::OnTimer)
175 
176  EVT_SIZE(TrackPanel::OnSize)
177 
179 
180 std::unique_ptr<wxCursor> MakeCursor( int WXUNUSED(CursorId), const char * const pXpm[36], int HotX, int HotY )
183 {
184 #define CURSORS_SIZE32
185 #ifdef CURSORS_SIZE32
186  const int HotAdjust =0;
187 #else
188  const int HotAdjust =8;
189 #endif
190 
191  wxImage Image = wxImage(wxBitmap(pXpm).ConvertToImage());
192  Image.SetMaskColour(255,0,0);
193  Image.SetMask();// Enable mask.
194 
195  Image.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_X, HotX-HotAdjust );
196  Image.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_Y, HotY-HotAdjust );
197  return std::make_unique<wxCursor>( Image );
198 }
199 
200 
201 namespace{
202 
203 AttachedWindows::RegisteredFactory sKey{
204  []( AudacityProject &project ) -> wxWeakRef< wxWindow > {
205  auto &ruler = AdornedRulerPanel::Get( project );
206  auto &viewInfo = ViewInfo::Get( project );
207  auto &window = ProjectWindow::Get( project );
208  auto mainPage = window.GetMainPage();
209  wxASSERT( mainPage ); // to justify safenew
210 
211  auto &tracks = TrackList::Get( project );
212  auto result = safenew TrackPanel(mainPage,
213  window.NextWindowID(),
214  wxDefaultPosition,
215  wxDefaultSize,
216  tracks.shared_from_this(),
217  &viewInfo,
218  &project,
219  &ruler);
220  SetProjectPanel( project, *result );
221  return result;
222  }
223 };
224 
225 }
226 
228 {
229  return GetAttachedWindows(project).Get< TrackPanel >( sKey );
230 }
231 
233 {
234  return Get( const_cast< AudacityProject & >( project ) );
235 }
236 
238 {
239  auto *pPanel = GetAttachedWindows(project).Find<TrackPanel>( sKey );
240  if (pPanel) {
241  pPanel->wxWindow::Destroy();
242  GetAttachedWindows(project).Assign(sKey, nullptr);
243  }
244 }
245 
246 // Don't warn us about using 'this' in the base member initializer list.
247 #ifndef __WXGTK__ //Get rid if this pragma for gtk
248 #pragma warning( disable: 4355 )
249 #endif
250 TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
251  const wxPoint & pos,
252  const wxSize & size,
253  const std::shared_ptr<TrackList> &tracks,
254  ViewInfo * viewInfo,
255  AudacityProject * project,
257  : CellularPanel(parent, id, pos, size, viewInfo,
258  wxWANTS_CHARS | wxNO_BORDER),
259  mListener( &ProjectWindow::Get( *project ) ),
260  mTracks(tracks),
261  mRuler(ruler),
262  mTrackArtist(nullptr),
263  mRefreshBacking(false)
264 #ifndef __WXGTK__ //Get rid if this pragma for gtk
265 #pragma warning( default: 4355 )
266 #endif
267 {
268  SetLayoutDirection(wxLayout_LeftToRight);
269  SetLabel(XO("Track Panel"));
270  SetName(XO("Track Panel"));
271  SetBackgroundStyle(wxBG_STYLE_PAINT);
272 
273  {
274  auto pAx = std::make_unique <TrackPanelAx>( *project );
275  pAx->SetWindow( this );
276  wxWeakRef< TrackPanel > weakThis{ this };
277  pAx->SetFinder(
278  [weakThis]( const Track &track ) -> wxRect {
279  if (weakThis)
280  return weakThis->FindTrackRect( &track );
281  return {};
282  }
283  );
284  TrackFocus::Get( *GetProject() ).SetAccessible(
285  *this, std::move( pAx ) );
286  }
287 
288  mTrackArtist = std::make_unique<TrackArtist>( this );
289 
290  mTimeCount = 0;
291  mTimer.parent = this;
292  // Timer is started after the window is visible
293  ProjectWindow::Get( *GetProject() ).Bind(wxEVT_IDLE,
294  &TrackPanel::OnIdle, this);
295 
296  // Register for tracklist updates
297  mTracks->Bind(EVT_TRACKLIST_RESIZING,
299  this);
300  mTracks->Bind(EVT_TRACKLIST_ADDITION,
302  this);
303  mTracks->Bind(EVT_TRACKLIST_DELETION,
305  this);
306  mTracks->Bind(EVT_TRACKLIST_TRACK_REQUEST_VISIBLE,
308  this);
309 
310  auto theProject = GetProject();
311  theProject->Bind(
312  EVT_PROJECT_SETTINGS_CHANGE, &TrackPanel::OnProjectSettingsChange, this);
313  theProject->Bind(
314  EVT_TRACK_FOCUS_CHANGE, &TrackPanel::OnTrackFocusChange, this );
315 
316  theProject->Bind(EVT_UNDO_RESET, &TrackPanel::OnUndoReset, this);
317 
318  wxTheApp->Bind(EVT_AUDIOIO_PLAYBACK,
320  this);
321  wxTheApp->Bind(EVT_AUDIOIO_CAPTURE,
323  this);
324  UpdatePrefs();
325 }
326 
327 
328 TrackPanel::~TrackPanel()
329 {
330  mTimer.Stop();
331 
332  // This can happen if a label is being edited and the user presses
333  // ALT+F4 or Command+Q
334  if (HasCapture())
335  ReleaseMouse();
336 }
337 
339 {
340  // All vertical rulers must be recalculated since the minimum and maximum
341  // frequencies may have been changed.
342  UpdateVRulers();
343 
344  Refresh();
345 }
346 
350 {
351  //JKC casting away constness here.
352  //Do it in two stages in case 'this' is not a wxWindow.
353  //when the compiler will flag the error.
354  wxWindow const * const pConstWind = this;
355  wxWindow * pWind=(wxWindow*)pConstWind;
356 #ifdef EXPERIMENTAL_NOTEBOOK
357  pWind = pWind->GetParent(); //Page
358  wxASSERT( pWind );
359  pWind = pWind->GetParent(); //Notebook
360  wxASSERT( pWind );
361 #endif
362  pWind = pWind->GetParent(); //MainPanel
363  wxASSERT( pWind );
364  pWind = pWind->GetParent(); //ProjectWindow
365  wxASSERT( pWind );
366  return &static_cast<ProjectWindow*>( pWind )->GetProject();
367 }
368 
369 void TrackPanel::OnSize( wxSizeEvent &evt )
370 {
371  evt.Skip();
372  const auto &size = evt.GetSize();
373  mViewInfo->SetWidth( size.GetWidth() );
374  mViewInfo->SetHeight( size.GetHeight() );
375 }
376 
377 void TrackPanel::OnIdle(wxIdleEvent& event)
378 {
379  event.Skip();
380  // The window must be ready when the timer fires (#1401)
381  if (IsShownOnScreen())
382  {
383  mTimer.Start(kTimerInterval, FALSE);
384 
385  // Timer is started, we don't need the event anymore
386  GetProjectFrame( *GetProject() ).Unbind(wxEVT_IDLE,
387  &TrackPanel::OnIdle, this);
388  }
389  else
390  {
391  // Get another idle event, wx only guarantees we get one
392  // event after "some other normal events occur"
393  event.RequestMore();
394  }
395 }
396 
398 void TrackPanel::OnTimer(wxTimerEvent& )
399 {
400  mTimeCount++;
401 
402  AudacityProject *const p = GetProject();
403  auto &window = ProjectWindow::Get( *p );
404 
405  auto &projectAudioIO = ProjectAudioIO::Get( *p );
406  auto gAudioIO = AudioIO::Get();
407 
408  // Check whether we were playing or recording, but the stream has stopped.
409  if (projectAudioIO.GetAudioIOToken()>0 && !IsAudioActive())
410  {
411  //the stream may have been started up after this one finished (by some other project)
412  //in that case reset the buttons don't stop the stream
413  auto &projectAudioManager = ProjectAudioManager::Get( *p );
414  projectAudioManager.Stop(!gAudioIO->IsStreamActive());
415  }
416 
417  // Next, check to see if we were playing or recording
418  // audio, but now Audio I/O is completely finished.
419  if (projectAudioIO.GetAudioIOToken()>0 &&
420  !gAudioIO->IsAudioTokenActive(projectAudioIO.GetAudioIOToken()))
421  {
422  projectAudioIO.SetAudioIOToken(0);
423  window.RedrawProject();
424  }
427  }
428 
429  // Notify listeners for timer ticks
430  {
431  wxCommandEvent e(EVT_TRACK_PANEL_TIMER);
432  p->ProcessEvent(e);
433  }
434 
435  DrawOverlays(false);
436  mRuler->DrawOverlays(false);
437 
438  if(IsAudioActive() && gAudioIO->GetNumCaptureChannels()) {
439 
440  // Periodically update the display while recording
441 
442  if ((mTimeCount % 5) == 0) {
443  // Must tell OnPaint() to recreate the backing bitmap
444  // since we've not done a full refresh.
445  mRefreshBacking = true;
446  Refresh( false );
447  }
448  }
449  if(mTimeCount > 1000)
450  mTimeCount = 0;
451 }
452 
453 void TrackPanel::OnProjectSettingsChange( wxCommandEvent &event )
454 {
455  event.Skip();
456  switch ( static_cast<ProjectSettings::EventCode>( event.GetInt() ) ) {
458  Refresh(false);
459  break;
460  default:
461  break;
462  }
463 }
464 
465 void TrackPanel::OnUndoReset( wxCommandEvent &event )
466 {
467  event.Skip();
468  TrackFocus::Get( *GetProject() ).Set( nullptr );
469  Refresh( false );
470 }
471 
474 void TrackPanel::OnPaint(wxPaintEvent & /* event */)
475 {
477 
478 #if DEBUG_DRAW_TIMING
479  wxStopWatch sw;
480 #endif
481 
482  {
483  wxPaintDC dc(this);
484 
485  // Retrieve the damage rectangle
486  wxRect box = GetUpdateRegion().GetBox();
487 
488  // Recreate the backing bitmap if we have a full refresh
489  // (See TrackPanel::Refresh())
490  if (mRefreshBacking || (box == GetRect()))
491  {
492  // Reset (should a mutex be used???)
493  mRefreshBacking = false;
494 
495  // Redraw the backing bitmap
497 
498  // Copy it to the display
499  DisplayBitmap(dc);
500  }
501  else
502  {
503  // Copy full, possibly clipped, damage rectangle
504  RepairBitmap(dc, box.x, box.y, box.width, box.height);
505  }
506 
507  // Done with the clipped DC
508 
509  // Drawing now goes directly to the client area.
510  // DrawOverlays() may need to draw outside the clipped region.
511  // (Used to make a NEW, separate wxClientDC, but that risks flashing
512  // problems on Mac.)
513  dc.DestroyClippingRegion();
514  DrawOverlays(true, &dc);
515  }
516 
517 #if DEBUG_DRAW_TIMING
518  sw.Pause();
519  wxLogDebug(wxT("Total: %ld milliseconds"), sw.Time());
520  wxPrintf(wxT("Total: %ld milliseconds\n"), sw.Time());
521 #endif
522 }
523 
525 {
527 }
528 
529 namespace {
530  std::shared_ptr<Track> FindTrack(TrackPanelCell *pCell )
531  {
532  if (pCell)
533  return static_cast<CommonTrackPanelCell*>( pCell )->FindTrack();
534  return {};
535  }
536 }
537 
539  (TrackPanelCell *pClickedCell, TrackPanelCell *pLatestCell,
540  UIHandle::Result refreshResult)
541 {
542  const auto panel = this;
543  auto pLatestTrack = FindTrack( pLatestCell ).get();
544 
545  // This precaution checks that the track is not only nonnull, but also
546  // really owned by the track list
547  auto pClickedTrack = GetTracks()->Lock(
548  std::weak_ptr<Track>{ FindTrack( pClickedCell ) }
549  ).get();
550 
551  // TODO: make a finer distinction between refreshing the track control area,
552  // and the waveform area. As it is, redraw both whenever you must redraw either.
553 
554  // Copy data from the underlying tracks to the pending tracks that are
555  // really displayed
556  TrackList::Get( *panel->GetProject() ).UpdatePendingTracks();
557 
558  using namespace RefreshCode;
559 
560  if (refreshResult & DestroyedCell) {
561  panel->UpdateViewIfNoTracks();
562  // Beware stale pointer!
563  if (pLatestTrack == pClickedTrack)
564  pLatestTrack = NULL;
565  pClickedTrack = NULL;
566  }
567 
568  if (pClickedTrack && (refreshResult & RefreshCode::UpdateVRuler))
569  panel->UpdateVRuler(pClickedTrack);
570 
571  if (refreshResult & RefreshCode::DrawOverlays) {
572  panel->DrawOverlays(false);
573  mRuler->DrawOverlays(false);
574  }
575 
576  // Refresh all if told to do so, or if told to refresh a track that
577  // is not known.
578  const bool refreshAll =
579  ( (refreshResult & RefreshAll)
580  || ((refreshResult & RefreshCell) && !pClickedTrack)
581  || ((refreshResult & RefreshLatestCell) && !pLatestTrack));
582 
583  if (refreshAll)
584  panel->Refresh(false);
585  else {
586  if (refreshResult & RefreshCell)
587  panel->RefreshTrack(pClickedTrack);
588  if (refreshResult & RefreshLatestCell)
589  panel->RefreshTrack(pLatestTrack);
590  }
591 
592  if (refreshResult & FixScrollbars)
593  panel->MakeParentRedrawScrollbars();
594 
595  if (refreshResult & Resize)
596  panel->GetListener()->TP_HandleResize();
597 
598  if ((refreshResult & RefreshCode::EnsureVisible) && pClickedTrack) {
599  TrackFocus::Get(*GetProject()).Set(pClickedTrack);
600  pClickedTrack->EnsureVisible();
601  }
602 }
603 
605 {
607 }
608 
610 {
612 }
613 
615 {
617  return ProjectAudioIO::Get( *p ).IsAudioActive();
618 }
619 
621 {
622  auto status = st;
623  if (HasEscape())
624  /* i18n-hint Esc is a key on the keyboard */
625  status.Join( XO("(Esc to cancel)"), " " );
626  ProjectStatus::Get( *GetProject() ).Set( status );
627 }
628 
630 {
631  // Full refresh since the label area may need to indicate
632  // newly selected tracks.
633  Refresh(false);
634 
635  // Make sure the ruler follows suit.
637 }
638 
639 // Counts selected tracks, counting stereo tracks as one track.
641 {
642  return GetTracks()->SelectedLeaders().size();
643 }
644 
646 {
647  if (mTracks->empty())
648  {
649  // BG: There are no more tracks on screen
650  //BG: Set zoom to normal
652 
653  //STM: Set selection to 0,0
654  //PRL: and default the rest of the selection information
656 
657  // PRL: Following causes the time ruler to align 0 with left edge.
658  // Bug 972
659  mViewInfo->h = 0;
660 
662  //STM: Clear message if all tracks are removed
664  }
665 }
666 
667 // The tracks positions within the list have changed, so update the vertical
668 // ruler size for the track that triggered the event.
670 {
671  auto t = e.mpTrack.lock();
672  // A deleted track can trigger the event. In which case do nothing here.
673  // A deleted track can have a valid pointer but no owner, bug 2060
674  if( t && t->HasOwner() )
675  UpdateVRuler(t.get());
676  e.Skip();
677 
678  // fix for bug 2477
680 }
681 
682 // Tracks have been removed from the list.
684 {
685  // copy shared_ptr for safety, as in HandleClick
686  auto handle = Target();
687  if (handle) {
688  handle->OnProjectChange(GetProject());
689  }
690 
691  // If the focused track disappeared but there are still other tracks,
692  // this reassigns focus.
693  TrackFocus( *GetProject() ).Get();
694 
696 
697  e.Skip();
698 }
699 
700 void TrackPanel::OnKeyDown(wxKeyEvent & event)
701 {
702  switch (event.GetKeyCode())
703  {
704  // Allow PageUp and PageDown keys to
705  //scroll the Track Panel left and right
706  case WXK_PAGEUP:
707  HandlePageUpKey();
708  return;
709 
710  case WXK_PAGEDOWN:
712  return;
713 
714  default:
715  // fall through to base class handler
716  event.Skip();
717  }
718 }
719 
720 void TrackPanel::OnMouseEvent(wxMouseEvent & event)
721 {
722  if (event.LeftDown()) {
723  // wxTimers seem to be a little unreliable, so this
724  // "primes" it to make sure it keeps going for a while...
725 
726  // When this timer fires, we call TrackPanel::OnTimer and
727  // possibly update the screen for offscreen scrolling.
728  mTimer.Stop();
729  mTimer.Start(kTimerInterval, FALSE);
730  }
731 
732 
733  if (event.ButtonUp()) {
734  //EnsureVisible should be called after processing the up-click.
735  this->CallAfter( [this, event]{
736  const auto foundCell = FindCell(event.m_x, event.m_y);
737  const auto t = FindTrack( foundCell.pCell.get() );
738  if ( t ) {
739  TrackFocus::Get(*GetProject()).Set(t.get());
740  t->EnsureVisible();
741  }
742  } );
743  }
744 
745  // Must also fall through to base class handler
746  event.Skip();
747 }
748 
750 {
751  return mViewInfo->PositionToTime(
753 }
754 
755 void TrackPanel::RefreshTrack(Track *trk, bool refreshbacking)
756 {
757  if (!trk)
758  return;
759 
760  // Always move to the first channel of the group, and use only
761  // the sum of channel heights, not the height of any channel alone!
762  trk = *GetTracks()->FindLeader(trk);
763  auto &view = TrackView::Get( *trk );
764  auto height =
766 
767  // Set rectangle top according to the scrolling position, `vpos`
768  // Subtract the inset (above) and shadow (below) from the height of the
769  // rectangle, but not the border
770  // This matters because some separators do paint over the border
771  const auto top =
772  -mViewInfo->vpos + view.GetCumulativeHeightBefore() + kTopInset;
773  height -= (kTopInset + kShadowThickness);
774 
775  // Width also subtracts insets (left and right) plus shadow (right)
776  const auto left = kLeftInset;
777  const auto width = GetRect().GetWidth()
779 
780  wxRect rect(left, top, width, height);
781 
782  if( refreshbacking )
783  mRefreshBacking = true;
784 
785  Refresh( false, &rect );
786 }
787 
788 
793 void TrackPanel::Refresh(bool eraseBackground /* = TRUE */,
794  const wxRect *rect /* = NULL */)
795 {
796  // Tell OnPaint() to refresh the backing bitmap.
797  //
798  // Originally I had the check within the OnPaint() routine and it
799  // was working fine. That was until I found that, even though a full
800  // refresh was requested, Windows only set the onscreen portion of a
801  // window as damaged.
802  //
803  // So, if any part of the trackpanel was off the screen, full refreshes
804  // didn't work and the display got corrupted.
805  if( !rect || ( *rect == GetRect() ) )
806  {
807  mRefreshBacking = true;
808  }
809  wxWindow::Refresh(eraseBackground, rect);
810 
812 }
813 
814 void TrackPanel::OnAudioIO(wxCommandEvent & evt)
815 {
816  evt.Skip();
817  // Some hit tests want to change their cursor to and from the ban symbol
819 }
820 
822 
826 void TrackPanel::DrawTracks(wxDC * dc)
827 {
828  wxRegion region = GetUpdateRegion();
829 
830  const wxRect clip = GetRect();
831 
833  mTrackArtist->pSelectedRegion = &sr;
834  mTrackArtist->pZoomInfo = mViewInfo;
835  TrackPanelDrawingContext context {
836  *dc, Target(), mLastMouseState, mTrackArtist.get()
837  };
838 
839  // Don't draw a bottom margin here.
840 
841  const auto &settings = ProjectSettings::Get( *GetProject() );
842  bool bMultiToolDown =
843  (ToolCodes::multiTool == settings.GetTool());
844  bool envelopeFlag =
845  bMultiToolDown || (ToolCodes::envelopeTool == settings.GetTool());
846  bool bigPointsFlag =
847  bMultiToolDown || (ToolCodes::drawTool == settings.GetTool());
848  bool sliderFlag = bMultiToolDown;
849  bool brushFlag = (ToolCodes::brushTool == settings.GetTool());
850 
851  const bool hasSolo = GetTracks()->Any< PlayableTrack >()
852  .any_of( []( const PlayableTrack *pt ) {
853  pt = static_cast< const PlayableTrack * >(
854  pt->SubstitutePendingChangedTrack().get() );
855  return (pt && pt->GetSolo());
856  } );
857 
858  mTrackArtist->drawEnvelope = envelopeFlag;
859  mTrackArtist->bigPoints = bigPointsFlag;
860  mTrackArtist->drawSliders = sliderFlag;
861  mTrackArtist->onBrushTool = brushFlag;
862  mTrackArtist->hasSolo = hasSolo;
863 
864  this->CellularPanel::Draw( context, TrackArtist::NPasses );
865 }
866 
868 (const std::shared_ptr< CommonTrackPanelCell > &pCell)
869 {
870  mpBackground = pCell;
871 }
872 
873 std::shared_ptr< CommonTrackPanelCell > TrackPanel::GetBackgroundCell()
874 {
875  return mpBackground;
876 }
877 
878 namespace {
879 std::vector<int> FindAdjustedChannelHeights( Track &t )
880 {
881  auto channels = TrackList::Channels(&t);
882  wxASSERT(!channels.empty());
883 
884  // Collect heights, and count affordances
885  int nAffordances = 0;
886  int totalHeight = 0;
887  std::vector<int> oldHeights;
888  for (auto channel : channels) {
889  auto &view = TrackView::Get( *channel );
890  const auto height = view.GetHeight();
891  totalHeight += height;
892  oldHeights.push_back( height );
893  if (view.GetAffordanceControls())
894  ++nAffordances;
895  }
896 
897  // Allocate results
898  auto nChannels = static_cast<int>(oldHeights.size());
899  std::vector<int> results;
900  results.reserve(nChannels);
901 
902  // Now reallocate the channel heights for the presence of affordances
903  // and separators
904  auto availableHeight = totalHeight
905  - nAffordances * kAffordancesAreaHeight
906  - (nChannels - 1) * kChannelSeparatorThickness
908  int cumulativeOldHeight = 0;
909  int cumulativeNewHeight = 0;
910  for (const auto &oldHeight : oldHeights) {
911  // Preserve the porportions among the stored heights
912  cumulativeOldHeight += oldHeight;
913  const auto newHeight =
914  cumulativeOldHeight * availableHeight / totalHeight
915  - cumulativeNewHeight;
916  cumulativeNewHeight += newHeight;
917  results.push_back(newHeight);
918  }
919 
920  return results;
921 }
922 }
923 
925 {
926  for (auto t : GetTracks()->Any< WaveTrack >())
928 
930 }
931 
933 {
934  if (t)
936 
938 }
939 
941 {
942  wxASSERT(t);
943  if (!t)
944  return;
945 
946  auto heights = FindAdjustedChannelHeights(*t);
947 
948  wxRect rect(mViewInfo->GetVRulerOffset(),
949  0,
951  0);
952 
953  auto pHeight = heights.begin();
954  for (auto channel : TrackList::Channels(t)) {
955  auto &view = TrackView::Get( *channel );
956  const auto height = *pHeight++;
957  rect.SetHeight( height );
958  const auto subViews = view.GetSubViews( rect );
959  if (subViews.empty())
960  continue;
961 
962  auto iter = subViews.begin(), end = subViews.end(), next = iter;
963  auto yy = iter->first;
964  wxSize vRulerSize{ 0, 0 };
965  for ( ; iter != end; iter = next ) {
966  ++next;
967  auto nextY = ( next == end )
968  ? height
969  : next->first;
970  rect.SetHeight( nextY - yy );
971  // This causes ruler size in the track to be reassigned:
972  TrackVRulerControls::Get( *iter->second ).UpdateRuler( rect );
973  // But we want to know the maximum width and height over all sub-views:
974  vRulerSize.IncTo( t->vrulerSize );
975  yy = nextY;
976  }
977  t->vrulerSize = vRulerSize;
978  }
979 }
980 
982 {
983  auto trackRange = GetTracks()->Any();
984  if (trackRange) {
985  wxSize s { 0, 0 };
986  for (auto t : trackRange)
987  s.IncTo(t->vrulerSize);
988 
989  if (mViewInfo->GetVRulerWidth() != s.GetWidth()) {
990  mViewInfo->SetVRulerWidth( s.GetWidth() );
992  mViewInfo->GetLeftOffset()); // bevel on AdornedRuler
993  mRuler->Refresh();
994  }
995  }
996  Refresh(false);
997 }
998 
1000 {
1001  CellularPanel::DoContextMenu( t ? &TrackView::Get( *t ) : nullptr );
1002 }
1003 
1004 // Tracks have been removed from the list.
1006 {
1007  e.Skip();
1008  bool modifyState = e.GetInt();
1009 
1010  auto pTrack = e.mpTrack.lock();
1011  auto t = pTrack.get();
1012 
1013  int trackTop = 0;
1014  int trackHeight =0;
1015 
1016  for (auto it : GetTracks()->Leaders()) {
1017  trackTop += trackHeight;
1018 
1019  auto channels = TrackList::Channels(it);
1020  trackHeight = channels.sum( TrackView::GetTrackHeight );
1021 
1022  //We have found the track we want to ensure is visible.
1023  if (channels.contains(t)) {
1024 
1025  //Get the size of the trackpanel.
1026  int width, height;
1027  GetSize(&width, &height);
1028 
1029  if (trackTop < mViewInfo->vpos) {
1030  height = mViewInfo->vpos - trackTop + mViewInfo->scrollStep;
1031  height /= mViewInfo->scrollStep;
1032  mListener->TP_ScrollUpDown(-height);
1033  }
1034  else if (trackTop + trackHeight > mViewInfo->vpos + height) {
1035  height = (trackTop + trackHeight) - (mViewInfo->vpos + height);
1036  height = (height + mViewInfo->scrollStep + 1) / mViewInfo->scrollStep;
1037  mListener->TP_ScrollUpDown(height);
1038  }
1039 
1040  break;
1041  }
1042  }
1043  Refresh(false);
1044 
1045  if ( modifyState )
1047 }
1048 
1049 // 0.0 scrolls to top
1050 // 1.0 scrolls to bottom.
1051 void TrackPanel::VerticalScroll( float fracPosition){
1052 
1053  int trackTop = 0;
1054  int trackHeight = 0;
1055 
1056  auto tracks = GetTracks();
1057 
1058  auto range = tracks->Leaders();
1059  if (!range.empty()) {
1060  trackHeight = TrackView::GetChannelGroupHeight( *range.rbegin() );
1061  --range.second;
1062  }
1063  trackTop = range.sum( TrackView::GetChannelGroupHeight );
1064 
1065  int delta;
1066 
1067  //Get the size of the trackpanel.
1068  int width, height;
1069  GetSize(&width, &height);
1070 
1071  delta = (fracPosition * (trackTop + trackHeight - height)) - mViewInfo->vpos + mViewInfo->scrollStep;
1072  //wxLogDebug( "Scroll down by %i pixels", delta );
1073  delta /= mViewInfo->scrollStep;
1074  mListener->TP_ScrollUpDown(delta);
1075  Refresh(false);
1076 }
1077 
1078 
1079 namespace {
1080  // Drawing constants
1081  // DisplaceX and MarginX are large enough to avoid overwriting <- symbol
1082  // See TrackArt::DrawNegativeOffsetTrackArrows
1083  enum : int {
1084  // Displacement of the rectangle from upper left corner
1086  // Size of margins about the text extent that determine the rectangle size
1087  MarginX = 8, MarginY = 2,
1088  // Derived constants
1090  };
1091 
1093  wxDC &dc, const Track *t, wxCoord *pW, wxCoord *pH )
1094 {
1095  wxFont labelFont(12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
1096  dc.SetFont(labelFont);
1097  dc.GetTextExtent( t->GetName(), pW, pH );
1098 }
1099 
1101  int leftOffset,
1102  const wxRect &trackRect, wxCoord textWidth, wxCoord textHeight )
1103 {
1104  return {
1105  leftOffset + DisplaceX,
1106  trackRect.y + DisplaceY,
1107  textWidth + MarginsX,
1108  textHeight + MarginsY
1109  };
1110 }
1111 
1112 // Draws the track name on the track, if it is needed.
1114  int leftOffset,
1115  TrackPanelDrawingContext &context, const Track * t, const wxRect & rect )
1116 {
1117  if( !TrackArtist::Get( context )->mbShowTrackNameInTrack )
1118  return;
1119  auto name = t->GetName();
1120  if( name.IsEmpty())
1121  return;
1122  if( !t->IsLeader())
1123  return;
1124  auto &dc = context.dc;
1125  wxBrush Brush;
1126  wxCoord textWidth, textHeight;
1127  GetTrackNameExtent( dc, t, &textWidth, &textHeight );
1128 
1129  // Logic for name background translucency (aka 'shields')
1130  // Tracks less than kOpaqueHeight high will have opaque shields.
1131  // Tracks more than kTranslucentHeight will have maximum translucency for shields.
1132  const int kOpaqueHeight = 44;
1133  const int kTranslucentHeight = 124;
1134 
1135  // PRL: to do: reexamine this strange use of TrackView::GetHeight,
1136  // ultimately to compute an opacity
1137  int h = TrackView::Get( *t ).GetHeight();
1138 
1139  // f codes the opacity as a number between 0.0 and 1.0
1140  float f = wxClip((h-kOpaqueHeight)/(float)(kTranslucentHeight-kOpaqueHeight),0.0,1.0);
1141  // kOpaque is the shield's alpha for tracks that are not tall
1142  // kTranslucent is the shield's alpha for tracks that are tall.
1143  const int kOpaque = 255;
1144  const int kTranslucent = 140;
1145  // 0.0 maps to full opacity, 1.0 maps to full translucency.
1146  int opacity = 255 - (255-140)*f;
1147 
1148  const auto nameRect =
1149  GetTrackNameRect( leftOffset, rect, textWidth, textHeight );
1150 
1151 #ifdef __WXMAC__
1152  // Mac dc is a graphics dc already.
1153  AColor::UseThemeColour( &dc, clrTrackInfoSelected, clrTrackPanelText, opacity );
1154  dc.DrawRoundedRectangle( nameRect, 8.0 );
1155 #else
1156  // This little dance with wxImage in order to draw to a graphic dc
1157  // which we can then paste as a translucent bitmap onto the real dc.
1158  enum : int {
1159  SecondMarginX = 1, SecondMarginY = 1,
1160  SecondMarginsX = 2 * SecondMarginX, SecondMarginsY = 2 * SecondMarginY,
1161  };
1162  wxImage image(
1163  textWidth + MarginsX + SecondMarginsX,
1164  textHeight + MarginsY + SecondMarginsY );
1165  image.InitAlpha();
1166  unsigned char *alpha=image.GetAlpha();
1167  memset(alpha, wxIMAGE_ALPHA_TRANSPARENT, image.GetWidth()*image.GetHeight());
1168 
1169  {
1170  std::unique_ptr< wxGraphicsContext >
1171  pGc{ wxGraphicsContext::Create(image) };
1172  auto &gc = *pGc;
1173  // This is to a gc, not a dc.
1174  AColor::UseThemeColour( &gc, clrTrackInfoSelected, clrTrackPanelText, opacity );
1175  // Draw at 1,1, not at 0,0 to avoid clipping of the antialiasing.
1176  gc.DrawRoundedRectangle(
1177  SecondMarginX, SecondMarginY,
1178  textWidth + MarginsX, textHeight + MarginsY, 8.0 );
1179  // destructor of gc updates the wxImage.
1180  }
1181  wxBitmap bitmap( image );
1182  dc.DrawBitmap( bitmap,
1183  nameRect.x - SecondMarginX, nameRect.y - SecondMarginY );
1184 #endif
1185  dc.SetTextForeground(theTheme.Colour( clrTrackPanelText ));
1186  dc.DrawText(t->GetName(),
1187  nameRect.x + MarginX,
1188  nameRect.y + MarginY);
1189 }
1190 
1191 /*
1192 
1193  The following classes define the subdivision of the area of the TrackPanel
1194  into cells with differing responses to mouse, keyboard, and scroll wheel
1195  events.
1196 
1197  The classes defining the less inclusive areas are earlier, while those
1198  defining ever larger hierarchical groupings of cells are later.
1199 
1200  To describe that subdivision again, informally, and top-down:
1201 
1202  Firstly subtract margin areas, on the left and right, that do not interact.
1203 
1204  Secondly subtract a noninterative margin above the first track, and an area
1205  below all tracks that causes deselection of all tracks if you click it.
1206  (One or both of those areas might be vertically scrolled off-screen, though.)
1207  Divide what remains into areas corresponding to the several tracks.
1208 
1209  Thirdly, for each track, subtract an area below, which you can click and drag
1210  to resize the track vertically.
1211 
1212  Fourthly, subtract an area at the left, which contains the track controls,
1213  such as the menu and delete and minimize buttons, and others appropriate
1214  to the track subtype.
1215 
1216  Fifthly, divide what remains into the vertically stacked channels, if there
1217  are more than one, alternating with separators, which can be clicked to
1218  resize the channel views.
1219 
1220  Sixthly, divide each channel into one or more vertically stacked sub-views.
1221 
1222  Lastly, split the area for each sub-view into a vertical ruler, and an area
1223  that displays the channel's own contents.
1224 
1225 */
1226 
1228  std::vector< UIHandlePtr > HitTest(
1229  const TrackPanelMouseState &, const AudacityProject *) override
1230  { return {}; }
1231  virtual std::shared_ptr< Track > DoFindTrack() override { return {}; }
1232  static std::shared_ptr<EmptyCell> Instance()
1233  {
1234  static auto instance = std::make_shared< EmptyCell >();
1235  return instance;
1236  }
1237 
1238  // TrackPanelDrawable implementation
1239  void Draw(
1240  TrackPanelDrawingContext &context,
1241  const wxRect &rect, unsigned iPass ) override
1242  {
1243  if ( iPass == TrackArtist::PassMargins ) {
1244  // Draw a margin area of TrackPanel
1245  auto dc = &context.dc;
1246 
1247  AColor::TrackPanelBackground( dc, false );
1248  dc->DrawRectangle( rect );
1249  }
1250  }
1251 };
1252 
1253 // A vertical ruler left of a channel
1256  const std::shared_ptr< TrackView > &pView, wxCoord leftOffset )
1257  : mpView{ pView }, mLeftOffset{ leftOffset } {}
1258  Subdivision Children( const wxRect &rect ) override
1259  {
1260  return { Axis::X, Refinement{
1261  { rect.GetLeft(),
1262  TrackVRulerControls::Get( *mpView ).shared_from_this() },
1263  { mLeftOffset, mpView }
1264  } };
1265  }
1266  std::shared_ptr< TrackView > mpView;
1267  wxCoord mLeftOffset;
1268 };
1269 
1270 // One or more sub-views of one channel, stacked vertically, each containing
1271 // a vertical ruler and a channel
1274  const std::shared_ptr<Track> &pTrack,
1275  TrackView::Refinement refinement, wxCoord leftOffset )
1276  : mpTrack{ pTrack }
1277  , mRefinement{ std::move( refinement ) }
1278  , mLeftOffset{ leftOffset } {}
1279  Subdivision Children( const wxRect &rect ) override
1280  {
1281  Refinement refinement;
1282  auto y1 = rect.GetTop();
1283  for ( const auto &subView : mRefinement ) {
1284  y1 = std::max( y1, subView.first );
1285  refinement.emplace_back( y1,
1286  std::make_shared< VRulerAndChannel >(
1287  subView.second, mLeftOffset ) );
1288  }
1289  return { Axis::Y, std::move( refinement ) };
1290  }
1291 
1292  // TrackPanelDrawable implementation
1293  void Draw(
1294  TrackPanelDrawingContext &context,
1295  const wxRect &rect, unsigned iPass ) override
1296  {
1297  // This overpaints the track area, but sometimes too the stereo channel
1298  // separator, so draw at least later than that
1299  if ( iPass == TrackArtist::PassBorders ) {
1300  DrawTrackName( mLeftOffset,
1301  context, mpTrack->SubstitutePendingChangedTrack().get(), rect );
1302  }
1303  if ( iPass == TrackArtist::PassControls ) {
1304  if (mRefinement.size() > 1) {
1305  // Draw lines separating sub-views
1306  auto &dc = context.dc;
1307  AColor::CursorColor( &dc );
1308  auto iter = mRefinement.begin() + 1, end = mRefinement.end();
1309  for ( ; iter != end; ++iter ) {
1310  auto yy = iter->first;
1311  AColor::Line( dc, mLeftOffset, yy, rect.GetRight(), yy );
1312  }
1313  }
1314  }
1315  }
1316 
1317  wxRect DrawingArea(
1318  TrackPanelDrawingContext &context,
1319  const wxRect &rect, const wxRect &panelRect, unsigned iPass ) override
1320  {
1321  auto result = rect;
1322  if ( iPass == TrackArtist::PassBorders ) {
1323  if ( true ) {
1324  wxCoord textWidth, textHeight;
1325  GetTrackNameExtent( context.dc, mpTrack.get(),
1326  &textWidth, &textHeight );
1327  result =
1328  GetTrackNameRect( mLeftOffset, rect, textWidth, textHeight );
1329  }
1330  }
1331  return result;
1332  }
1333 
1334  std::shared_ptr< Track > mpTrack;
1336  wxCoord mLeftOffset;
1337 };
1338 
1339 //Simply fills area using specified brush and outlines borders
1341 {
1342  //Required to keep selection behaviour similar to others
1343  std::shared_ptr<Track> mTrack;
1345 public:
1346  explicit EmptyPanelRect(const std::shared_ptr<Track>& track, int fillBrushName)
1347  : mTrack(track), mFillBrushName(fillBrushName)
1348  {
1349  }
1350 
1352 
1354  const wxRect& rect, unsigned iPass) override
1355  {
1356  if (iPass == TrackArtist::PassBackground)
1357  {
1358  context.dc.SetPen(*wxTRANSPARENT_PEN);
1359  AColor::UseThemeColour(&context.dc, mFillBrushName);
1360  context.dc.DrawRectangle(rect);
1361  wxRect bevel(rect.x, rect.y, rect.width - 1, rect.height - 1);
1362  AColor::BevelTrackInfo(context.dc, true, bevel, false);
1363  }
1364  }
1365 
1366  std::shared_ptr<Track> DoFindTrack() override
1367  {
1368  return mTrack;
1369  }
1370 
1371  std::vector<UIHandlePtr> HitTest(const TrackPanelMouseState& state,
1372  const AudacityProject* pProject) override
1373  {
1374  return {};
1375  }
1376 };
1377 
1378 //Simply place children one after another horizontally, without any specific logic
1380 
1382 
1384  : mRefinement(std::move(refinement))
1385  {
1386  }
1387 
1388  Subdivision Children(const wxRect& /*rect*/) override
1389  {
1390  return { Axis::X, mRefinement };
1391  }
1392 
1393 };
1394 
1395 
1396 // optional affordance areas, and n channels with vertical rulers,
1397 // alternating with n - 1 resizers;
1398 // each channel-ruler pair might be divided into multiple views
1400  ChannelGroup( const std::shared_ptr< Track > &pTrack, wxCoord leftOffset )
1401  : mpTrack{ pTrack }, mLeftOffset{ leftOffset } {}
1402  Subdivision Children( const wxRect &rect_ ) override
1403  {
1404  auto rect = rect_;
1405  Refinement refinement;
1406 
1407  const auto channels = TrackList::Channels( mpTrack.get() );
1408  const auto pLast = *channels.rbegin();
1409  wxCoord yy = rect.GetTop();
1410  auto heights = FindAdjustedChannelHeights(*mpTrack);
1411  auto pHeight = heights.begin();
1412  for ( auto channel : channels )
1413  {
1414  auto &view = TrackView::Get( *channel );
1415  if (auto affordance = view.GetAffordanceControls())
1416  {
1417  auto panelRect = std::make_shared<EmptyPanelRect>(
1418  channel->shared_from_this(),
1419  channel->GetSelected() ? clrTrackInfoSelected : clrTrackInfo);
1420  Refinement hgroup {
1421  std::make_pair(rect.GetLeft() + 1, panelRect),
1422  std::make_pair(mLeftOffset, affordance)
1423  };
1424  refinement.emplace_back(yy, std::make_shared<HorizontalGroup>(hgroup));
1425  yy += kAffordancesAreaHeight;
1426  }
1427 
1428  auto height = *pHeight++;
1429  rect.SetTop( yy );
1430  rect.SetHeight( height - kChannelSeparatorThickness );
1431  refinement.emplace_back( yy,
1432  std::make_shared< VRulersAndChannels >(
1433  channel->shared_from_this(),
1434  TrackView::Get( *channel ).GetSubViews( rect ),
1435  mLeftOffset ) );
1436  if ( channel != pLast ) {
1437  yy += height;
1438  refinement.emplace_back(
1440  TrackPanelResizerCell::Get( *channel ).shared_from_this() );
1441  }
1442  }
1443 
1444  return { Axis::Y, std::move( refinement ) };
1445  }
1446 
1447  void Draw(TrackPanelDrawingContext& context, const wxRect& rect, unsigned iPass) override
1448  {
1449  TrackPanelGroup::Draw(context, rect, iPass);
1450  if (iPass == TrackArtist::PassFocus && mpTrack->IsSelected())
1451  {
1452  const auto channels = TrackList::Channels(mpTrack.get());
1453  const auto pLast = *channels.rbegin();
1454  wxCoord yy = rect.GetTop();
1455  auto heights = FindAdjustedChannelHeights(*mpTrack);
1456  auto pHeight = heights.begin();
1457  for (auto channel : channels)
1458  {
1459  auto& view = TrackView::Get(*channel);
1460  auto height = *pHeight++;
1461  if (auto affordance = view.GetAffordanceControls())
1462  {
1463  height += kAffordancesAreaHeight;
1464  }
1465  auto trackRect = wxRect(
1466  mLeftOffset,
1467  yy,
1468  rect.GetRight() - mLeftOffset,
1469  height - kChannelSeparatorThickness);
1470  TrackArt::DrawCursor(context, trackRect, mpTrack.get());
1471  yy += height;
1472  }
1473  }
1474  }
1475 
1476  std::shared_ptr< Track > mpTrack;
1477  wxCoord mLeftOffset;
1478 };
1479 
1480 // A track control panel, left of n vertical rulers and n channels
1481 // alternating with n - 1 resizers
1484  const std::shared_ptr< Track > &pTrack, wxCoord leftOffset )
1485  : mpTrack{ pTrack }, mLeftOffset{ leftOffset } {}
1486  Subdivision Children( const wxRect &rect ) override
1487  { return { Axis::X, Refinement{
1488  { rect.GetLeft(),
1489  TrackControls::Get( *mpTrack ).shared_from_this() },
1490  { rect.GetLeft() + kTrackInfoWidth,
1491  std::make_shared< ChannelGroup >( mpTrack, mLeftOffset ) }
1492  } }; }
1493 
1494  // TrackPanelDrawable implementation
1496  const wxRect &rect, unsigned iPass ) override
1497  {
1498  if ( iPass == TrackArtist::PassBorders ) {
1499  auto &dc = context.dc;
1500  dc.SetBrush(*wxTRANSPARENT_BRUSH);
1501  dc.SetPen(*wxBLACK_PEN);
1502 
1503  // border
1504  dc.DrawRectangle(
1505  rect.x, rect.y,
1506  rect.width - kShadowThickness, rect.height - kShadowThickness
1507  );
1508 
1509  // shadow
1510  // Stroke lines along bottom and right, which are slightly short at
1511  // bottom-left and top-right
1512  const auto right = rect.GetRight();
1513  const auto bottom = rect.GetBottom();
1514 
1515  // bottom
1516  AColor::Line(dc, rect.x + 2, bottom, right, bottom);
1517  // right
1518  AColor::Line(dc, right, rect.y + 2, right, bottom);
1519  }
1520  if ( iPass == TrackArtist::PassFocus ) {
1521  // Sometimes highlight is not drawn on backing bitmap. I thought
1522  // it was because FindFocus did not return the TrackPanel on Mac, but
1523  // when I removed that test, yielding this condition:
1524  // if (GetFocusedTrack() != NULL) {
1525  // the highlight was reportedly drawn even when something else
1526  // was the focus and no highlight should be drawn. -RBD
1527  const auto artist = TrackArtist::Get( context );
1528  auto &trackPanel = *artist->parent;
1529  auto &trackFocus = TrackFocus::Get( *trackPanel.GetProject() );
1530  if (trackFocus.Get() == mpTrack.get() &&
1531  wxWindow::FindFocus() == &trackPanel ) {
1533  wxRect theRect = rect;
1534  auto &dc = context.dc;
1535  dc.SetBrush(*wxTRANSPARENT_BRUSH);
1536 
1537  AColor::TrackFocusPen( &dc, 2 );
1538  dc.DrawRectangle(theRect);
1539  theRect.Deflate(1);
1540 
1541  AColor::TrackFocusPen( &dc, 1 );
1542  dc.DrawRectangle(theRect);
1543  theRect.Deflate(1);
1544 
1545  AColor::TrackFocusPen( &dc, 0 );
1546  dc.DrawRectangle(theRect);
1547  }
1548  }
1549  }
1550 
1551  wxRect DrawingArea(
1553  const wxRect &rect, const wxRect &, unsigned iPass ) override
1554  {
1555  if ( iPass == TrackArtist::PassBorders )
1556  return {
1557  rect.x - kBorderThickness,
1558  rect.y - kBorderThickness,
1559  rect.width + 2 * kBorderThickness + kShadowThickness,
1560  rect.height + 2 * kBorderThickness + kShadowThickness
1561  };
1562  else if ( iPass == TrackArtist::PassFocus ) {
1563  constexpr auto extra = kBorderThickness + 3;
1564  return {
1565  rect.x - extra,
1566  rect.y - extra,
1567  rect.width + 2 * extra + kShadowThickness,
1568  rect.height + 2 * extra + kShadowThickness
1569  };
1570  }
1571  else
1572  return rect;
1573  }
1574 
1575  std::shared_ptr< Track > mpTrack;
1576  wxCoord mLeftOffset;
1577 };
1578 
1579 // Stacks a label and a single or multi-channel track on a resizer below,
1580 // which is associated with the last channel
1583  const std::shared_ptr< Track > &pTrack, wxCoord leftOffset )
1584  : mpTrack{ pTrack }, mLeftOffset{ leftOffset } {}
1585  Subdivision Children( const wxRect &rect ) override
1586  { return { Axis::Y, Refinement{
1587  { rect.GetTop(),
1588  std::make_shared< LabeledChannelGroup >( mpTrack, mLeftOffset ) },
1589  { rect.GetTop() + rect.GetHeight() - kTrackSeparatorThickness,
1591  **TrackList::Channels( mpTrack.get() ).rbegin() ).shared_from_this()
1592  }
1593  } }; }
1594  std::shared_ptr< Track > mpTrack;
1595  wxCoord mLeftOffset;
1596 };
1597 
1598 // Stacks a dead area at top, the tracks, and the click-to-deselect area below
1599 struct Subgroup final : TrackPanelGroup {
1600  explicit Subgroup( TrackPanel &panel ) : mPanel{ panel } {}
1601  Subdivision Children( const wxRect &rect ) override
1602  {
1603  const auto &viewInfo = *mPanel.GetViewInfo();
1604  wxCoord yy = -viewInfo.vpos;
1605  Refinement refinement;
1606 
1607  auto &tracks = *mPanel.GetTracks();
1608  if ( tracks.Any() )
1609  refinement.emplace_back( yy, EmptyCell::Instance() ),
1610  yy += kTopMargin;
1611 
1612  for ( const auto leader : tracks.Leaders() ) {
1613  wxCoord height = 0;
1614  for ( auto channel : TrackList::Channels( leader ) ) {
1615  auto &view = TrackView::Get( *channel );
1616  height += view.GetHeight();
1617  }
1618  refinement.emplace_back( yy,
1619  std::make_shared< ResizingChannelGroup >(
1620  leader->SharedPointer(), viewInfo.GetLeftOffset() )
1621  );
1622  yy += height;
1623  }
1624 
1625  refinement.emplace_back( std::max( 0, yy ), mPanel.GetBackgroundCell() );
1626 
1627  return { Axis::Y, std::move( refinement ) };
1628  }
1630 };
1631 
1632 // Main group shaves off the left and right margins
1633 struct MainGroup final : TrackPanelGroup {
1634  explicit MainGroup( TrackPanel &panel ) : mPanel{ panel } {}
1635  Subdivision Children( const wxRect &rect ) override
1636  { return { Axis::X, Refinement{
1637  { 0, EmptyCell::Instance() },
1638  { kLeftMargin, std::make_shared< Subgroup >( mPanel ) },
1639  { rect.GetRight() + 1 - kRightMargin, EmptyCell::Instance() }
1640  } }; }
1642 };
1643 
1644 }
1645 
1646 std::shared_ptr<TrackPanelNode> TrackPanel::Root()
1647 {
1648  // Root and other subgroup objects are throwaways.
1649  // They might instead be cached to avoid repeated allocation.
1650  // That cache would need invalidation when there is addition, deletion, or
1651  // permutation of tracks, or change of width of the vertical rulers.
1652  return std::make_shared< MainGroup >( *this );
1653 }
1654 
1655 // This finds the rectangle of a given track (including all channels),
1656 // either that of the label 'adornment' or the track itself
1657 // The given track is assumed to be the first channel
1658 wxRect TrackPanel::FindTrackRect( const Track * target )
1659 {
1660  auto leader = *GetTracks()->FindLeader( target );
1661  if (!leader) {
1662  return {};
1663  }
1664 
1665  return CellularPanel::FindRect( [&] ( TrackPanelNode &node ) {
1666  if (auto pGroup = dynamic_cast<const LabeledChannelGroup*>( &node ))
1667  return pGroup->mpTrack.get() == leader;
1668  return false;
1669  } );
1670 }
1671 
1672 wxRect TrackPanel::FindFocusedTrackRect( const Track * target )
1673 {
1674  auto rect = FindTrackRect(target);
1675  if (rect != wxRect{}) {
1676  // Enlarge horizontally.
1677  // PRL: perhaps it's one pixel too much each side, including some gray
1678  // beyond the yellow?
1679  rect.x = 0;
1680  GetClientSize(&rect.width, nullptr);
1681 
1682  // Enlarge vertically, enough to enclose the yellow focus border pixels
1683  // The the outermost ring of gray pixels is included on three sides
1684  // but not the top (should that be fixed?)
1685 
1686  // (Note that TrackPanel paints its focus over the "top margin" of the
1687  // rectangle allotted to the track, according to TrackView::GetY() and
1688  // TrackView::GetHeight(), but also over the margin of the next track.)
1689 
1690  rect.height += kBottomMargin;
1691  int dy = kTopMargin - 1;
1692  rect.Inflate( 0, dy );
1693 
1694  // Note that this rectangle does not coincide with any one of
1695  // the nodes in the subdivision.
1696  }
1697  return rect;
1698 }
1699 
1700 std::vector<wxRect> TrackPanel::FindRulerRects( const Track *target )
1701 {
1702  std::vector<wxRect> results;
1703  if (target)
1704  VisitCells( [&]( const wxRect &rect, TrackPanelCell &visited ) {
1705  if (auto pRuler = dynamic_cast<const TrackVRulerControls*>(&visited);
1706  pRuler && pRuler->FindTrack().get() == target)
1707  results.push_back(rect);
1708  } );
1709  return results;
1710 }
1711 
1713 {
1714  auto pTrack = TrackFocus::Get( *GetProject() ).Get();
1715  return pTrack ? &TrackView::Get( *pTrack ) : GetBackgroundCell().get();
1716 }
1717 
1719 {
1720  // This may have a side-effect of assigning a focus if there was none
1721  auto& trackFocus = TrackFocus::Get(*GetProject());
1722  trackFocus.Set(trackFocus.Get());
1724 }
1725 
1726 void TrackPanel::OnTrackFocusChange( wxCommandEvent &event )
1727 {
1728  event.Skip();
1729  auto cell = GetFocusedCell();
1730 
1731  if (cell) {
1732  Refresh( false );
1733  }
1734 }
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
WaveTrack.h
ZoomInfo::vpos
int vpos
Definition: ZoomInfo.h:58
TrackPanel::OnTrackListResizing
void OnTrackListResizing(TrackListEvent &event)
Definition: TrackPanel.cpp:669
anonymous_namespace{TrackPanel.cpp}::ChannelGroup::ChannelGroup
ChannelGroup(const std::shared_ptr< Track > &pTrack, wxCoord leftOffset)
Definition: TrackPanel.cpp:1400
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
kLeftInset
@ kLeftInset
Definition: ZoomInfo.h:31
anonymous_namespace{TrackPanel.cpp}::MarginsY
@ MarginsY
Definition: TrackPanel.cpp:1089
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
RefreshCode::DrawOverlays
@ DrawOverlays
Definition: RefreshCode.h:32
RefreshCode::FixScrollbars
@ FixScrollbars
Definition: RefreshCode.h:27
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:161
anonymous_namespace{TrackPanel.cpp}::EmptyCell::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: TrackPanel.cpp:1239
AColor::UseThemeColour
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
Definition: AColor.cpp:283
TrackPanel::GetTracks
const TrackList * GetTracks() const
Definition: TrackPanel.h:170
TrackPanel::UpdateVRulerSize
void UpdateVRulerSize()
Definition: TrackPanel.cpp:981
TrackPanelGroup::Refinement
std::vector< Child > Refinement
Definition: TrackPanelCell.h:64
TrackPanelMouseEvent.h
TrackPanelGroup::Subdivision
std::pair< Axis, Refinement > Subdivision
Definition: TrackPanelCell.h:65
AColor::TrackPanelBackground
static void TrackPanelBackground(wxDC *dc, bool selected)
Definition: AColor.cpp:365
AdornedRulerPanel::Refresh
void Refresh(bool eraseBackground=true, const wxRect *rect=(const wxRect *) NULL) override
Definition: AdornedRulerPanel.cpp:965
TrackPanel::DrawTracks
void DrawTracks(wxDC *dc)
Definition: TrackPanel.cpp:826
ProjectStatus.h
CellularPanel::HandleCursorForPresentMouseState
void HandleCursorForPresentMouseState(bool doHit=true)
Definition: CellularPanel.cpp:231
AColor::CursorColor
static void CursorColor(wxDC *dc)
Definition: AColor.cpp:374
TrackPanel::TrackPanel
TrackPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, const std::shared_ptr< TrackList > &tracks, ViewInfo *viewInfo, AudacityProject *project, AdornedRulerPanel *ruler)
Definition: TrackPanel.cpp:250
AdornedRulerPanel
This is an Audacity Specific ruler panel which additionally has border, selection markers,...
Definition: AdornedRulerPanel.h:28
PlayableTrack::GetSolo
bool GetSolo() const
Definition: Track.h:861
ProjectAudioManager::Get
static ProjectAudioManager & Get(AudacityProject &project)
Definition: ProjectAudioManager.cpp:53
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect::HitTest
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
Definition: TrackPanel.cpp:1371
anonymous_namespace{TrackPanel.cpp}::HorizontalGroup::HorizontalGroup
HorizontalGroup(Refinement refinement)
Definition: TrackPanel.cpp:1383
TrackVRulerControls.h
TrackPanelListener::TP_RedrawScrollbars
virtual void TP_RedrawScrollbars()=0
anonymous_namespace{TrackPanel.cpp}::LabeledChannelGroup
Definition: TrackPanel.cpp:1482
ToolCodes::drawTool
@ drawTool
Definition: ProjectSettings.h:38
TrackPanel::FindFocusedTrackRect
wxRect FindFocusedTrackRect(const Track *target)
Definition: TrackPanel.cpp:1672
RefreshCode::RefreshAll
@ RefreshAll
Definition: RefreshCode.h:26
ZoomInfo::GetVRulerOffset
int GetVRulerOffset() const
Definition: ZoomInfo.h:100
TrackArtist::NPasses
@ NPasses
Definition: TrackArtist.h:90
TrackView::Get
static TrackView & Get(Track &)
Definition: TrackView.cpp:63
TrackPanel::UpdateVRuler
void UpdateVRuler(Track *t)
Definition: TrackPanel.cpp:932
TrackArtist.h
BackedPanel::DisplayBitmap
void DisplayBitmap(wxDC &dc)
Definition: BackedPanel.cpp:65
BackedPanel::RepairBitmap
void RepairBitmap(wxDC &dc, wxCoord x, wxCoord y, wxCoord width, wxCoord height)
Definition: BackedPanel.cpp:60
ClientData::Site::Find
Subclass * Find(const RegisteredFactory &key)
Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand...
Definition: ClientData.h:333
TrackFocus
Definition: TrackPanelAx.h:161
AllThemeResources.h
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels::mRefinement
TrackView::Refinement mRefinement
Definition: TrackPanel.cpp:1335
TrackView.h
anonymous_namespace{TrackPanel.cpp}::Subgroup::Subgroup
Subgroup(TrackPanel &panel)
Definition: TrackPanel.cpp:1600
TrackList::Lock
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1542
Track::GetName
wxString GetName() const
Definition: Track.h:426
ZoomInfo::GetDefaultZoom
static double GetDefaultZoom()
Definition: ZoomInfo.h:123
Project.h
TrackPanel::OnIdle
void OnIdle(wxIdleEvent &event)
Definition: TrackPanel.cpp:377
Track::EnsureVisible
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:100
wxPanelWrapper::SetLabel
void SetLabel(const TranslatableString &label)
Definition: wxPanelWrapper.cpp:46
TrackPanelListener::TP_ScrollWindow
virtual void TP_ScrollWindow(double scrollto)=0
CellularPanel::mViewInfo
ViewInfo * mViewInfo
Definition: CellularPanel.h:161
ClientData::Site::Get
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
Definition: ClientData.h:309
TrackControls::Get
static TrackControls & Get(Track &track)
Definition: TrackControls.cpp:25
anonymous_namespace{TrackPanel.cpp}::ResizingChannelGroup::mLeftOffset
wxCoord mLeftOffset
Definition: TrackPanel.cpp:1595
TrackArtist::PassBorders
@ PassBorders
Definition: TrackArtist.h:83
KeyboardCapture.h
CommonTrackPanelCell::FindTrack
std::shared_ptr< Track > FindTrack()
Definition: CommonTrackPanelCell.h:46
TrackPanelDrawingContext
Definition: TrackPanelDrawingContext.h:22
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1484
MakeCursor
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:182
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:112
TrackPanel.h
ViewInfo
Definition: ViewInfo.h:169
kBorderThickness
@ kBorderThickness
Definition: ZoomInfo.h:28
anonymous_namespace{TrackPanel.cpp}::DisplaceX
@ DisplaceX
Definition: TrackPanel.cpp:1085
anonymous_namespace{TrackPanel.cpp}::LabeledChannelGroup::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: TrackPanel.cpp:1495
TrackPanelAx.h
AColor::TrackFocusPen
static void TrackFocusPen(wxDC *dc, int level)
Definition: AColor.cpp:400
kShadowThickness
@ kShadowThickness
Definition: ZoomInfo.h:29
TrackPanel::Get
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:227
TrackView::GetTrackHeight
static int GetTrackHeight(const Track *pTrack)
Definition: TrackView.cpp:29
XO
#define XO(s)
Definition: Internat.h:31
TrackPanel::OnKeyDown
void OnKeyDown(wxKeyEvent &event)
Definition: TrackPanel.cpp:700
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:41
TrackPanel::FindTrackRect
wxRect FindTrackRect(const Track *target)
Definition: TrackPanel.cpp:1658
anonymous_namespace{TrackPanel.cpp}::ChannelGroup::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: TrackPanel.cpp:1447
TrackPanel::GetMostRecentXPos
double GetMostRecentXPos()
Definition: TrackPanel.cpp:749
TrackPanel::AudacityTimer::parent
TrackPanel * parent
Definition: TrackPanel.h:210
anonymous_namespace{TrackPanel.cpp}::Subgroup
Definition: TrackPanel.cpp:1599
kTrackInfoBtnSize
@ kTrackInfoBtnSize
Definition: ViewInfo.h:108
TrackPanelDrawingContext::dc
wxDC & dc
Definition: TrackPanelDrawingContext.h:23
ZoomInfo::SetVRulerWidth
void SetVRulerWidth(int width)
Definition: ZoomInfo.h:99
kRightInset
@ kRightInset
Definition: ZoomInfo.h:32
ProjectSettings.h
ProjectWindow::Get
static ProjectWindow & Get(AudacityProject &project)
Definition: ProjectWindow.cpp:535
ZoomInfo::GetVRulerWidth
int GetVRulerWidth() const
Definition: ZoomInfo.h:98
CellularPanel::FindRect
wxRect FindRect(const TrackPanelCell &cell)
Definition: CellularPanel.cpp:1130
anonymous_namespace{TrackPanel.cpp}::MarginX
@ MarginX
Definition: TrackPanel.cpp:1087
BasicUI::CallAfter
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Definition: BasicUI.cpp:38
anonymous_namespace{TrackPanel.cpp}::HorizontalGroup::Children
Subdivision Children(const wxRect &) override
Definition: TrackPanel.cpp:1388
AColor::BevelTrackInfo
static void BevelTrackInfo(wxDC &dc, bool up, const wxRect &r, bool highlight=false)
Definition: AColor.cpp:251
ProjectAudioManager.h
ProjectAudioIO::Get
static ProjectAudioIO & Get(AudacityProject &project)
Definition: ProjectAudioIO.cpp:22
TrackPanel::UpdateViewIfNoTracks
void UpdateViewIfNoTracks()
Definition: TrackPanel.cpp:645
TrackPanel::MakeParentRedrawScrollbars
void MakeParentRedrawScrollbars()
Definition: TrackPanel.cpp:524
TrackPanel::OnMouseEvent
void OnMouseEvent(wxMouseEvent &event)
Definition: TrackPanel.cpp:720
anonymous_namespace{TrackPanel.cpp}::VRulerAndChannel
Definition: TrackPanel.cpp:1254
anonymous_namespace{TimeTrackVRulerControls.cpp}::ruler
Ruler & ruler()
Definition: TimeTrackVRulerControls.cpp:34
TrackPanel
The TrackPanel class coordinates updates and operations on the main part of the screen which contains...
Definition: TrackPanel.h:67
kBottomMargin
@ kBottomMargin
Definition: TrackPanelConstants.h:22
TrackList::SelectedLeaders
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1422
anonymous_namespace{TrackPanel.cpp}::HorizontalGroup
Definition: TrackPanel.cpp:1379
anonymous_namespace{TrackPanel.cpp}::LabeledChannelGroup::mpTrack
std::shared_ptr< Track > mpTrack
Definition: TrackPanel.cpp:1575
RefreshCode::EnsureVisible
@ EnsureVisible
Definition: RefreshCode.h:31
ProjectAudioIO::IsAudioActive
bool IsAudioActive() const
Definition: ProjectAudioIO.cpp:51
TrackPanel::ProcessUIHandleResult
void ProcessUIHandleResult(TrackPanelCell *pClickedTrack, TrackPanelCell *pLatestCell, unsigned refreshResult) override
Definition: TrackPanel.cpp:539
sKey
static const AudacityProject::AttachedObjects::RegisteredFactory sKey
Definition: ProjectRate.cpp:35
TrackPanelListener::TP_ScrollUpDown
virtual bool TP_ScrollUpDown(int delta)=0
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect::mFillBrushName
int mFillBrushName
Definition: TrackPanel.cpp:1344
anonymous_namespace{TrackPanel.cpp}::EmptyCell::DoFindTrack
virtual std::shared_ptr< Track > DoFindTrack() override
Definition: TrackPanel.cpp:1231
anonymous_namespace{TrackPanel.cpp}::LabeledChannelGroup::LabeledChannelGroup
LabeledChannelGroup(const std::shared_ptr< Track > &pTrack, wxCoord leftOffset)
Definition: TrackPanel.cpp:1483
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: TrackPanel.cpp:1353
anonymous_namespace{TrackPanel.cpp}::EmptyCell::HitTest
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &, const AudacityProject *) override
Definition: TrackPanel.cpp:1228
TrackPanel::GetSelectedTrackCount
size_t GetSelectedTrackCount() const
Definition: TrackPanel.cpp:640
TrackPanel::GetProject
AudacityProject * GetProject() const override
Definition: TrackPanel.cpp:349
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect::DoFindTrack
std::shared_ptr< Track > DoFindTrack() override
Definition: TrackPanel.cpp:1366
ZoomInfo::GetLeftOffset
int GetLeftOffset() const
Definition: ZoomInfo.h:103
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels::DrawingArea
wxRect DrawingArea(TrackPanelDrawingContext &context, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
Definition: TrackPanel.cpp:1317
TrackPanel::UpdatePrefs
void UpdatePrefs() override
Definition: TrackPanel.cpp:338
anonymous_namespace{TrackPanel.cpp}::MainGroup::MainGroup
MainGroup(TrackPanel &panel)
Definition: TrackPanel.cpp:1634
anonymous_namespace{TrackPanel.cpp}::FindAdjustedChannelHeights
std::vector< int > FindAdjustedChannelHeights(Track &t)
Definition: TrackPanel.cpp:879
ViewInfo::scrollStep
int scrollStep
Definition: ViewInfo.h:214
TrackPanel::UpdateSelectionDisplay
void UpdateSelectionDisplay()
Definition: TrackPanel.cpp:629
ClientData::Site::Assign
void Assign(const RegisteredFactory &key, ReplacementPointer &&replacement)
Reassign Site's pointer to ClientData.
Definition: ClientData.h:355
TrackPanel::OnTrackListDeletion
void OnTrackListDeletion(wxEvent &event)
Definition: TrackPanel.cpp:683
TrackVRulerControls
Definition: TrackVRulerControls.h:25
ProjectSettings::EventCode
EventCode
Definition: ProjectSettings.h:67
anonymous_namespace{TrackPanel.cpp}::LabeledChannelGroup::Children
Subdivision Children(const wxRect &rect) override
Definition: TrackPanel.cpp:1486
TrackPanel::GetFocusedCell
TrackPanelCell * GetFocusedCell() override
Definition: TrackPanel.cpp:1712
BackedPanel::GetBackingDCForRepaint
wxDC & GetBackingDCForRepaint()
Definition: BackedPanel.cpp:35
ProjectSettings::ChangedSyncLock
@ ChangedSyncLock
Definition: ProjectSettings.h:68
AdornedRulerPanel::Get
static AdornedRulerPanel & Get(AudacityProject &project)
Definition: AdornedRulerPanel.cpp:874
TrackPanelNode
The TrackPanel is built up of nodes, subtrees of the CellularPanel's area Common base class for Track...
Definition: TrackPanelCell.h:39
TrackList::FindLeader
TrackIter< Track > FindLeader(Track *pTrack)
Definition: Track.cpp:659
ProjectStatus::Set
void Set(const TranslatableString &msg, StatusBarField field=mainStatusBarField)
Definition: ProjectStatus.cpp:77
Track::SubstitutePendingChangedTrack
std::shared_ptr< Track > SubstitutePendingChangedTrack()
Definition: Track.cpp:1198
anonymous_namespace{TrackPanel.cpp}::EmptyCell
Definition: TrackPanel.cpp:1227
ViewInfo::selectedRegion
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:196
TrackArtist::Get
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:79
CommonTrackPanelCell.h
CellularPanel::MostRecentXCoord
wxCoord MostRecentXCoord() const
Definition: CellularPanel.cpp:1168
TrackFocus::Get
static TrackFocus & Get(AudacityProject &project)
Definition: TrackPanelAx.cpp:736
TrackPanel::OnProjectSettingsChange
void OnProjectSettingsChange(wxCommandEvent &event)
Definition: TrackPanel.cpp:453
ToolCodes::multiTool
@ multiTool
Definition: ProjectSettings.h:41
CellularPanel::HasEscape
bool HasEscape()
Definition: CellularPanel.cpp:422
TrackListEvent
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
Definition: Track.h:1222
anonymous_namespace{TrackPanel.cpp}::EmptyCell::Instance
static std::shared_ptr< EmptyCell > Instance()
Definition: TrackPanel.cpp:1232
TrackPanel::OnSize
void OnSize(wxSizeEvent &)
Definition: TrackPanel.cpp:369
ZoomInfo::SetZoom
void SetZoom(double pixelsPerSecond)
Definition: ZoomInfo.cpp:84
BasicUI::Get
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:26
anonymous_namespace{TrackPanel.cpp}::DisplaceY
@ DisplaceY
Definition: TrackPanel.cpp:1085
TrackPanel::mLastDrawnSelectedRegion
SelectedRegion mLastDrawnSelectedRegion
Definition: TrackPanel.h:220
TrackPanelListener::TP_HandleResize
virtual void TP_HandleResize()=0
ProjectWindow
A top-level window associated with a project, and handling scrollbars and zooming.
Definition: ProjectWindow.h:32
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect::mTrack
std::shared_ptr< Track > mTrack
Definition: TrackPanel.cpp:1343
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect::EmptyPanelRect
EmptyPanelRect(const std::shared_ptr< Track > &track, int fillBrushName)
Definition: TrackPanel.cpp:1346
anonymous_namespace{TrackPanel.cpp}::MainGroup
Definition: TrackPanel.cpp:1633
GetAttachedWindows
AUDACITY_DLL_API AttachedWindows & GetAttachedWindows(AudacityProject &project)
Definition: ProjectWindows.cpp:114
UIHandle::Result
unsigned Result
Definition: UIHandle.h:38
Theme.h
kVerticalPadding
@ kVerticalPadding
Definition: ViewInfo.h:104
AdornedRulerPanel::DrawSelection
void DrawSelection()
Definition: AdornedRulerPanel.cpp:2082
anonymous_namespace{TrackPanel.cpp}::ResizingChannelGroup::ResizingChannelGroup
ResizingChannelGroup(const std::shared_ptr< Track > &pTrack, wxCoord leftOffset)
Definition: TrackPanel.cpp:1582
kTopMargin
@ kTopMargin
Definition: TrackPanelConstants.h:21
KeyboardCapture::Capture
void Capture(wxWindow *handler)
Definition: KeyboardCapture.cpp:70
TrackVRulerControls::Get
static TrackVRulerControls & Get(TrackView &)
Definition: TrackVRulerControls.cpp:36
name
const TranslatableString name
Definition: Distortion.cpp:98
RefreshCode::Resize
@ Resize
Definition: RefreshCode.h:28
TrackPanelCell
Definition: TrackPanelCell.h:74
@0::kTimerInterval
@ kTimerInterval
ZoomInfo::GetScreenEndTime
double GetScreenEndTime() const
Definition: ZoomInfo.h:114
TrackControls.h
TrackArtist::PassControls
@ PassControls
Definition: TrackArtist.h:84
TrackPanel::SetBackgroundCell
void SetBackgroundCell(const std::shared_ptr< CommonTrackPanelCell > &pCell)
Definition: TrackPanel.cpp:868
AdornedRulerPanel::SetLeftOffset
void SetLeftOffset(int offset)
Definition: AdornedRulerPanel.cpp:2109
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels::mpTrack
std::shared_ptr< Track > mpTrack
Definition: TrackPanel.cpp:1334
CellularPanel::Target
UIHandlePtr Target()
Definition: CellularPanel.cpp:1159
UndoManager.h
TrackFocus::Get
Track * Get()
Definition: TrackPanelAx.cpp:755
RefreshCode::UpdateVRuler
@ UpdateVRuler
Definition: RefreshCode.h:30
TrackPanel::OnTimer
void OnTimer(wxTimerEvent &event)
AS: This gets called on our wx timer events.
Definition: TrackPanel.cpp:398
TrackPanel::SetFocusedCell
void SetFocusedCell() override
Definition: TrackPanel.cpp:1718
TrackPanel::mTimer
TrackPanel::AudacityTimer mTimer
TrackPanel::GetBackgroundCell
std::shared_ptr< CommonTrackPanelCell > GetBackgroundCell()
Definition: TrackPanel.cpp:873
RefreshCode::RefreshCell
@ RefreshCell
Definition: RefreshCode.h:24
TrackPanel::mRuler
AdornedRulerPanel * mRuler
Definition: TrackPanel.h:193
TrackPanelGroup
Definition: TrackPanelCell.h:47
anonymous_namespace{TrackPanel.cpp}::VRulerAndChannel::mpView
std::shared_ptr< TrackView > mpView
Definition: TrackPanel.cpp:1266
TrackPanel::Root
std::shared_ptr< TrackPanelNode > Root() override
Definition: TrackPanel.cpp:1646
anonymous_namespace{TrackPanel.cpp}::FindTrack
std::shared_ptr< Track > FindTrack(TrackPanelCell *pCell)
Definition: TrackPanel.cpp:530
TrackVRulerControls::UpdateRuler
virtual void UpdateRuler(const wxRect &rect)=0
PlayableTrack
AudioTrack subclass that can also be audibly replayed by the program.
Definition: Track.h:854
RefreshCode::RefreshLatestCell
@ RefreshLatestCell
Definition: RefreshCode.h:25
anonymous_namespace{TrackPanel.cpp}::VRulerAndChannel::VRulerAndChannel
VRulerAndChannel(const std::shared_ptr< TrackView > &pView, wxCoord leftOffset)
Definition: TrackPanel.cpp:1255
anonymous_namespace{TrackPanel.cpp}::VRulerAndChannel::Children
Subdivision Children(const wxRect &rect) override
Definition: TrackPanel.cpp:1258
TrackPanel::OnPaint
void OnPaint(wxPaintEvent &event)
Definition: TrackPanel.cpp:474
ProjectWindows.h
accessors for certain important windows associated with each project
anonymous_namespace{TrackPanel.cpp}::MarginsX
@ MarginsX
Definition: TrackPanel.cpp:1089
TrackPanel::HandlePageUpKey
void HandlePageUpKey()
Definition: TrackPanel.cpp:604
TrackList::UpdatePendingTracks
void UpdatePendingTracks()
Definition: Track.cpp:1072
CellularPanel::Draw
void Draw(TrackPanelDrawingContext &context, unsigned nPasses)
Definition: CellularPanel.cpp:1191
anonymous_namespace{TrackPanel.cpp}::GetTrackNameExtent
void GetTrackNameExtent(wxDC &dc, const Track *t, wxCoord *pW, wxCoord *pH)
Definition: TrackPanel.cpp:1092
RefreshCode::DestroyedCell
@ DestroyedCell
Definition: RefreshCode.h:34
anonymous_namespace{TrackPanel.cpp}::VRulerAndChannel::mLeftOffset
wxCoord mLeftOffset
Definition: TrackPanel.cpp:1267
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels::mLeftOffset
wxCoord mLeftOffset
Definition: TrackPanel.cpp:1336
TrackArt::DrawCursor
AUDACITY_DLL_API void DrawCursor(TrackPanelDrawingContext &context, const wxRect &rect, const Track *track)
Definition: TrackArtist.cpp:581
id
int id
Definition: WaveTrackControls.cpp:591
TrackPanel::mListener
TrackPanelListener * mListener
Definition: TrackPanel.h:189
TrackPanelDrawingContext.h
TrackPanel::UpdateVRulers
void UpdateVRulers()
Definition: TrackPanel.cpp:924
TrackPanel::UpdateStatusMessage
void UpdateStatusMessage(const TranslatableString &status) override
Definition: TrackPanel.cpp:620
wxPanelWrapper::SetName
void SetName()
Definition: wxPanelWrapper.cpp:61
anonymous_namespace{TrackPanel.cpp}::DrawTrackName
void DrawTrackName(int leftOffset, TrackPanelDrawingContext &context, const Track *t, const wxRect &rect)
Definition: TrackPanel.cpp:1113
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
Track::IsLeader
bool IsLeader() const
Definition: Track.cpp:379
ToolCodes::envelopeTool
@ envelopeTool
Definition: ProjectSettings.h:37
anonymous_namespace{TrackPanel.cpp}::Subgroup::Children
Subdivision Children(const wxRect &rect) override
Definition: TrackPanel.cpp:1601
TrackPanelResizeHandle.h
anonymous_namespace{TrackPanel.cpp}::MainGroup::mPanel
TrackPanel & mPanel
Definition: TrackPanel.cpp:1641
kTrackSeparatorThickness
@ kTrackSeparatorThickness
Definition: TrackPanelConstants.h:23
AudioIO.h
anonymous_namespace{TrackPanel.cpp}::ChannelGroup
Definition: TrackPanel.cpp:1399
ProjectStatus::Get
static ProjectStatus & Get(AudacityProject &project)
Definition: ProjectStatus.cpp:35
anonymous_namespace{TrackPanel.cpp}::ChannelGroup::mpTrack
std::shared_ptr< Track > mpTrack
Definition: TrackPanel.cpp:1476
kTopInset
@ kTopInset
Definition: TrackPanelConstants.h:20
TrackPanel::Refresh
void Refresh(bool eraseBackground=true, const wxRect *rect=(const wxRect *) NULL) override
Definition: TrackPanel.cpp:793
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
kAffordancesAreaHeight
@ kAffordancesAreaHeight
Definition: TrackPanelConstants.h:19
TrackPanel::mRefreshBacking
bool mRefreshBacking
Definition: TrackPanel.h:215
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels
Definition: TrackPanel.cpp:1272
CellularPanel
Formerly part of TrackPanel, this abstract base class has no special knowledge of Track objects and i...
Definition: CellularPanel.h:34
TrackView::GetSubViews
virtual Refinement GetSubViews(const wxRect &rect)
Definition: TrackView.cpp:116
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels::Children
Subdivision Children(const wxRect &rect) override
Definition: TrackPanel.cpp:1279
anonymous_namespace{TrackPanel.cpp}::MainGroup::Children
Subdivision Children(const wxRect &rect) override
Definition: TrackPanel.cpp:1635
TrackPanel::mTrackArtist
std::unique_ptr< TrackArtist > mTrackArtist
Definition: TrackPanel.h:195
GetProjectFrame
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
Definition: ProjectWindows.cpp:72
AdornedRulerPanel.h
SetProjectPanel
AUDACITY_DLL_API void SetProjectPanel(AudacityProject &project, wxWindow &panel)
Definition: ProjectWindows.cpp:66
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels::VRulersAndChannels
VRulersAndChannels(const std::shared_ptr< Track > &pTrack, TrackView::Refinement refinement, wxCoord leftOffset)
Definition: TrackPanel.cpp:1273
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
ProjectHistory.h
TrackPanel::OnTrackMenu
void OnTrackMenu(Track *t=NULL)
Definition: TrackPanel.cpp:999
CellularPanel::mLastMouseState
wxMouseState mLastMouseState
Definition: CellularPanel.h:164
CellularPanel::VisitCells
void VisitCells(const SimpleCellVisitor &visitor)
Definition: CellularPanel.cpp:1020
ViewInfo::SetHeight
void SetHeight(int height)
Definition: ViewInfo.h:179
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1197
anonymous_namespace{TrackPanel.cpp}::MarginY
@ MarginY
Definition: TrackPanel.cpp:1087
TrackPanel::OnAudioIO
void OnAudioIO(wxCommandEvent &evt)
Definition: TrackPanel.cpp:814
RefreshCode.h
TrackPanel::OnEnsureVisible
void OnEnsureVisible(TrackListEvent &event)
Definition: TrackPanel.cpp:1005
kRightMargin
@ kRightMargin
Definition: ZoomInfo.h:34
OverlayPanel::DrawOverlays
void DrawOverlays(bool repaint_all, wxDC *pDC=nullptr)
Definition: OverlayPanel.cpp:43
anonymous_namespace{TrackPanel.cpp}::HorizontalGroup::mRefinement
Refinement mRefinement
Definition: TrackPanel.cpp:1381
TrackPanel::OnTrackFocusChange
void OnTrackFocusChange(wxCommandEvent &event)
Definition: TrackPanel.cpp:1726
CellularPanel::DoContextMenu
void DoContextMenu(TrackPanelCell *pCell=nullptr)
Definition: CellularPanel.cpp:938
TrackView::GetChannelGroupHeight
static int GetChannelGroupHeight(const Track *pTrack)
Definition: TrackView.cpp:34
anonymous_namespace{TrackPanel.cpp}::ResizingChannelGroup
Definition: TrackPanel.cpp:1581
theTheme
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:203
Prefs.h
kChannelSeparatorThickness
@ kChannelSeparatorThickness
Definition: TrackPanelConstants.h:24
TrackListEvent::mpTrack
std::weak_ptr< Track > mpTrack
Definition: Track.h:1238
anonymous_namespace{TrackPanel.cpp}::GetTrackNameRect
wxRect GetTrackNameRect(int leftOffset, const wxRect &trackRect, wxCoord textWidth, wxCoord textHeight)
Definition: TrackPanel.cpp:1100
ProjectWindow.h
TrackPanel::mTracks
std::shared_ptr< TrackList > mTracks
Definition: TrackPanel.h:191
TrackArtist::PassMargins
@ PassMargins
Definition: TrackArtist.h:82
anonymous_namespace{TrackPanel.cpp}::ChannelGroup::mLeftOffset
wxCoord mLeftOffset
Definition: TrackPanel.cpp:1477
TrackList::Any
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1371
anonymous_namespace{TrackPanel.cpp}::VRulersAndChannels::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: TrackPanel.cpp:1293
anonymous_namespace{TrackPanel.cpp}::Subgroup::mPanel
TrackPanel & mPanel
Definition: TrackPanel.cpp:1629
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect
Definition: TrackPanel.cpp:1341
CommonTrackPanelCell
Definition: CommonTrackPanelCell.h:28
TranslatableString::Join
TranslatableString & Join(TranslatableString arg, const wxString &separator={}) &
Append another translatable string.
Definition: TranslatableString.cpp:124
TrackPanel::OnUndoReset
void OnUndoReset(wxCommandEvent &event)
Definition: TrackPanel.cpp:465
AudioIO::Get
static AudioIO * Get()
Definition: AudioIO.cpp:138
TrackPanelConstants.h
safenew
#define safenew
Definition: MemoryX.h:10
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
TrackArtist::PassBackground
@ PassBackground
Definition: TrackArtist.h:86
float_cast.h
AColor.h
kTrackInfoWidth
@ kTrackInfoWidth
Definition: ZoomInfo.h:36
within
bool within(A a, B b, DIST d)
Definition: TrackPanel.cpp:163
TrackPanel::HandlePageDownKey
void HandlePageDownKey()
Definition: TrackPanel.cpp:609
TrackPanelResizerCell.h
END_EVENT_TABLE
END_EVENT_TABLE()
CellularPanel::FindCell
FoundCell FindCell(int mouseX, int mouseY)
Definition: CellularPanel.cpp:1091
ProjectAudioIO.h
TrackPanel::Destroy
static void Destroy(AudacityProject &project)
Definition: TrackPanel.cpp:237
TrackPanel::mTimeCount
int mTimeCount
Definition: TrackPanel.h:213
TrackPanel::RefreshTrack
void RefreshTrack(Track *trk, bool refreshbacking=true)
Definition: TrackPanel.cpp:755
TrackPanel::VerticalScroll
void VerticalScroll(float fracPosition)
Definition: TrackPanel.cpp:1051
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
TrackArtist::PassFocus
@ PassFocus
Definition: TrackArtist.h:87
TrackPanelResizerCell::Get
static TrackPanelResizerCell & Get(Track &track)
Definition: TrackPanelResizerCell.cpp:119
ZoomInfo::h
double h
Definition: ZoomInfo.h:60
TrackPanel::FindRulerRects
std::vector< wxRect > FindRulerRects(const Track *target)
Definition: TrackPanel.cpp:1700
kLeftMargin
@ kLeftMargin
Definition: ZoomInfo.h:33
TrackPanel::IsAudioActive
bool IsAudioActive()
Definition: TrackPanel.cpp:614
ZoomInfo::PositionToTime
double PositionToTime(wxInt64 position, wxInt64 origin=0, bool ignoreFisheye=false) const
Definition: ZoomInfo.cpp:39
anonymous_namespace{TrackPanel.cpp}::LabeledChannelGroup::DrawingArea
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &, unsigned iPass) override
Definition: TrackPanel.cpp:1551
TrackView::GetHeight
int GetHeight() const
Definition: TrackView.cpp:149
anonymous_namespace{TrackPanel.cpp}::ResizingChannelGroup::Children
Subdivision Children(const wxRect &rect) override
Definition: TrackPanel.cpp:1585
anonymous_namespace{TrackPanel.cpp}::EmptyPanelRect::~EmptyPanelRect
~EmptyPanelRect()
Definition: TrackPanel.cpp:1351
anonymous_namespace{TrackPanel.cpp}::ChannelGroup::Children
Subdivision Children(const wxRect &rect_) override
Definition: TrackPanel.cpp:1402
TrackPanel::UpdateTrackVRuler
void UpdateTrackVRuler(Track *t)
Definition: TrackPanel.cpp:940
SelectedRegion
Defines a selected portion of a project.
Definition: SelectedRegion.h:35
ZoomInfo::SetWidth
void SetWidth(int width)
Definition: ZoomInfo.h:96
TrackPanel::mpBackground
std::shared_ptr< CommonTrackPanelCell > mpBackground
Definition: TrackPanel.h:224
Track::vrulerSize
wxSize vrulerSize
Definition: Track.h:354
anonymous_namespace{TrackPanel.cpp}::ResizingChannelGroup::mpTrack
std::shared_ptr< Track > mpTrack
Definition: TrackPanel.cpp:1594
anonymous_namespace{TrackPanel.cpp}::LabeledChannelGroup::mLeftOffset
wxCoord mLeftOffset
Definition: TrackPanel.cpp:1576
TrackPanelDrawable::Draw
virtual void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass)
Definition: TrackPanelDrawable.cpp:17