Audacity 3.2.0
TrackPanelAx.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 TrackPanelAx.cpp
6
7 Leland Lucius
8 and lots of other contributors
9
10******************************************************************//*******************************************************************/
16
17
18#include "TrackPanelAx.h"
19
20// For compilers that support precompilation, includes "wx/wx.h".
21#include <wx/wxprec.h>
22
23#include <wx/setup.h> // for wxUSE_* macros
24
25#ifndef WX_PRECOMP
26// Include your minimal set of headers here, or wx.h
27#include <wx/wx.h>
28#endif
29
30
31#include <wx/intl.h>
32
33#include "BasicUI.h"
34#include "Project.h"
35#include "SyncLock.h"
36#include "Track.h"
37#include "LabelTrack.h"
38#include "NoteTrack.h"
39#include "TimeTrack.h"
40
42 :
43#if wxUSE_ACCESSIBILITY
44 WindowAccessible( nullptr ) // window pointer must be set after construction
45 ,
46#endif
47 mProject{ project }
48{
49 mTrackName = true;
50 mMessageCount = 0;
52}
53
55{
56}
57
59{
60 return TrackList::Get( mProject );
61}
62
63// Returns currently focused track
64// if that track no longer exists, if there is a track at
65// the same position, use that, else if there is a first
66// track, use that.
67std::shared_ptr<Track> TrackPanelAx::GetFocus()
68{
69 auto focusedTrack = mFocusedTrack.lock();
70 if( !focusedTrack ) {
71 if (mNumFocusedTrack >=1) {
72 // This prevents the focus from being unnecessarily set to track 1
73 // when effects are applied. (Applying an effect can change
74 // the pointers of the selected tracks.)
75 focusedTrack = FindTrack(mNumFocusedTrack);
76 }
77 if (!focusedTrack) {
78 focusedTrack =
79 Track::SharedPointer( *GetTracks().Any().first );
80 // only call SetFocus if the focus has changed to avoid
81 // unnecessary focus events
82 if (focusedTrack)
83 focusedTrack = SetFocus();
84 }
85 }
86
87 if( !TrackNum( focusedTrack ) )
88 {
89 mFocusedTrack.reset();
90 return {};
91 }
92
93 return( focusedTrack );
94}
95
96// Changes focus to a specified track
97std::shared_ptr<Track> TrackPanelAx::SetFocus( std::shared_ptr<Track> track )
98{
99 mTrackName = true;
100
101#if wxUSE_ACCESSIBILITY
102
103 auto focusedTrack = mFocusedTrack.lock();
104 if( focusedTrack && !focusedTrack->GetSelected() )
105 {
106 NotifyEvent( wxACC_EVENT_OBJECT_SELECTIONREMOVE,
107 GetWindow(),
108 wxOBJID_CLIENT,
109 TrackNum( focusedTrack ) );
110 }
111#endif
112
113 if( !track )
114 track = Track::SharedPointer( *GetTracks().Any().begin() );
115
116 if ( mFocusedTrack.lock() != track ) {
117 mFocusedTrack = track;
118 BasicUI::CallAfter([wFocus = TrackFocus::Get(mProject).weak_from_this()]{
119 if (auto pFocus = wFocus.lock())
120 pFocus->Publish({});
121 });
122 }
123 mNumFocusedTrack = TrackNum(track);
124
125#if wxUSE_ACCESSIBILITY
126 if( track )
127 {
128 if (GetWindow() == wxWindow::FindFocus())
129 {
130 NotifyEvent( wxACC_EVENT_OBJECT_FOCUS,
131 GetWindow(),
132 wxOBJID_CLIENT,
134 }
135
136 if( track->GetSelected() )
137 {
138 NotifyEvent( wxACC_EVENT_OBJECT_SELECTION,
139 GetWindow(),
140 wxOBJID_CLIENT,
142 }
143 }
144 else
145 {
146 NotifyEvent(wxACC_EVENT_OBJECT_FOCUS,
147 GetWindow(),
148 wxOBJID_CLIENT,
149 wxACC_SELF);
150 }
151
152#endif
153
154 return track;
155}
156
157// Returns TRUE if passed track has the focus
158bool TrackPanelAx::IsFocused( const Track *track )
159{
160 auto focusedTrack = mFocusedTrack.lock();
161 if( !focusedTrack )
162 focusedTrack = SetFocus();
163
164 // Remap track pointer if there are outstanding pending updates
165 auto origTrack =
166 GetTracks().FindById( track->GetId() );
167 if (origTrack)
168 track = origTrack;
169
170 return focusedTrack
171 ? TrackList::Channels(focusedTrack.get()).contains(track)
172 : !track;
173}
174
175int TrackPanelAx::TrackNum( const std::shared_ptr<Track> &target )
176{
177 // Find 1-based position of the target in the visible tracks, or 0 if not
178 // found
179 int ndx = 0;
180
181 for ( auto t : GetTracks().Leaders() )
182 {
183 ndx++;
184 if( t == target.get() )
185 {
186 return ndx;
187 }
188 }
189
190 return 0;
191}
192
193std::shared_ptr<Track> TrackPanelAx::FindTrack( int num )
194{
195 int ndx = 0;
196
197 for ( auto t : GetTracks().Leaders() )
198 {
199 ndx++;
200 if( ndx == num )
201 return t->SharedPointer();
202 }
203
204 return {};
205}
206
208{
209#if wxUSE_ACCESSIBILITY
210 auto t = GetFocus();
211 mTrackName = true;
212
213 // The object_focus event is only needed by Window-Eyes
214 // and can be removed when we cease to support this screen reader.
215 NotifyEvent(wxACC_EVENT_OBJECT_FOCUS,
216 GetWindow(),
217 wxOBJID_CLIENT,
218 TrackNum(t));
219
220 NotifyEvent(wxACC_EVENT_OBJECT_NAMECHANGE,
221 GetWindow(),
222 wxOBJID_CLIENT,
223 TrackNum(t));
224#endif
225}
226
228{
229#if wxUSE_ACCESSIBILITY
230 if (GetWindow() == wxWindow::FindFocus())
231 {
232 auto t = GetFocus();
233 int childId = t ? TrackNum(t) : 0;
234
235 mMessage = message.Translation();
236
237 // append \a alternatively, so that the string is never the same as the previous string.
238 // This ensures that screen readers read it.
239 if (mMessageCount % 2 == 0)
240 mMessage.Append('\a');
242
243 mTrackName = false;
244 NotifyEvent(wxACC_EVENT_OBJECT_NAMECHANGE,
245 GetWindow(),
246 wxOBJID_CLIENT,
247 childId);
248 }
249
250#endif
251}
252
253#if wxUSE_ACCESSIBILITY
254
255// Retrieves the address of an IDispatch interface for the specified child.
256// All objects must support this property.
257wxAccStatus TrackPanelAx::GetChild( int childId, wxAccessible** child )
258{
259 if( childId == wxACC_SELF )
260 {
261 *child = this;
262 }
263 else
264 {
265 *child = NULL;
266 }
267
268 return wxACC_OK;
269}
270
271// Gets the number of children.
272wxAccStatus TrackPanelAx::GetChildCount( int* childCount )
273{
274 *childCount = GetTracks().Leaders().size();
275 return wxACC_OK;
276}
277
278// Gets the default action for this object (0) or > 0 (the action for a child).
279// Return wxACC_OK even if there is no action. actionName is the action, or the empty
280// string if there is no action.
281// The retrieved string describes the action that is performed on an object,
282// not what the object does as a result. For example, a toolbar button that prints
283// a document has a default action of "Press" rather than "Prints the current document."
284wxAccStatus TrackPanelAx::GetDefaultAction( int WXUNUSED(childId), wxString *actionName )
285{
286 actionName->clear();
287
288 return wxACC_OK;
289}
290
291// Returns the description for this object or a child.
292wxAccStatus TrackPanelAx::GetDescription( int WXUNUSED(childId), wxString *description )
293{
294 description->clear();
295
296 return wxACC_OK;
297}
298
299// Returns help text for this object or a child, similar to tooltip text.
300wxAccStatus TrackPanelAx::GetHelpText( int WXUNUSED(childId), wxString *helpText )
301{
302 helpText->clear();
303
304 return wxACC_OK;
305}
306
307// Returns the keyboard shortcut for this object or child.
308// Return e.g. ALT+K
309wxAccStatus TrackPanelAx::GetKeyboardShortcut( int WXUNUSED(childId), wxString *shortcut )
310{
311 shortcut->clear();
312
313 return wxACC_OK;
314}
315
316// Returns the rectangle for this object (id = 0) or a child element (id > 0).
317// rect is in screen coordinates.
318wxAccStatus TrackPanelAx::GetLocation( wxRect& rect, int elementId )
319{
320 wxRect client;
321
322 if( elementId == wxACC_SELF )
323 {
324 rect = GetWindow()->GetScreenRect();
325 }
326 else
327 {
328 auto t = FindTrack( elementId );
329
330 if( t == NULL )
331 {
332 return wxACC_FAIL;
333 }
334
335 rect = mFinder ? mFinder( *t ) : wxRect{};
336 // Inflate the screen reader's rectangle so it overpaints Audacity's own
337 // yellow focus rectangle.
338#ifdef __WXMAC__
339 const int dx = 2;
340#else
341 const int dx = 1;
342#endif
343 rect.Inflate(dx, dx);
344 rect.SetPosition(GetWindow()->ClientToScreen(rect.GetPosition()));
345 }
346
347 return wxACC_OK;
348}
349
350// Gets the name of the specified object.
351wxAccStatus TrackPanelAx::GetName( int childId, wxString* name )
352{
353#if defined(__WXMSW__) || defined(__WXMAC__)
354 if (mTrackName)
355 {
356 if( childId == wxACC_SELF )
357 {
358 *name = _( "TrackView" );
359 }
360 else
361 {
362 auto t = FindTrack( childId );
363
364 if( t == NULL )
365 return wxACC_FAIL;
366
367 name->Printf("%d %s", TrackNum(t), t->GetName());
368
369 if(dynamic_cast<LabelTrack*>(t.get()))
370 {
371 const auto trackNameLower = t->GetName().Lower();
372 //Prior to version 3.2 "Label Track" was the default
373 //name for label tracks, don't append type part to the
374 //text to avoid verbosity.
375 if(trackNameLower.Find(wxString(_("Label Track")).Lower()) == wxNOT_FOUND &&
376 trackNameLower.Find(LabelTrack::GetDefaultName().Lower()) == wxNOT_FOUND)
377 /* i18n-hint: This is for screen reader software and indicates that
378 this is a Label track.*/
379 name->Append( wxT(" ") + wxString(_("Label Track")));
380 }
381 else if(dynamic_cast<TimeTrack*>(t.get()))
382 {
383 if(t->GetName().Lower().Find(TimeTrack::GetDefaultName().Lower()) == wxNOT_FOUND)
384 /* i18n-hint: This is for screen reader software and indicates that
385 this is a Time track.*/
386 name->Append(wxT(" ") + wxString(_("Time Track")));
387 }
388#ifdef USE_MIDI
389 else if(dynamic_cast<NoteTrack*>(t.get()))
390 /* i18n-hint: This is for screen reader software and indicates that
391 this is a Note track.*/
392 name->Append( wxT(" ") + wxString(_("Note Track")));
393#endif
394
395 // LLL: Remove these during "refactor"
396 auto pt = dynamic_cast<PlayableTrack *>(t.get());
397 if( pt && pt->GetMute() )
398 {
399 // The following comment also applies to the solo, selected,
400 // and synclockselected states.
401 // Many of translations of the strings with a leading space omitted
402 // the leading space. Therefore a space has been added using wxT(" ").
403 // Because screen readers won't be affected by multiple spaces, the
404 // leading spaces have not been removed, so that no NEW translations are needed.
405 /* i18n-hint: This is for screen reader software and indicates that
406 this track is muted. (The mute button is on.)*/
407 name->Append( wxT(" ") + wxString(_( " Muted" )) );
408 }
409
410 if( pt && pt->GetSolo() )
411 {
412 /* i18n-hint: This is for screen reader software and indicates that
413 this track is soloed. (The Solo button is on.)*/
414 name->Append( wxT(" ") + wxString(_( " Soloed" )) );
415 }
416 if( t->GetSelected() )
417 {
418 /* i18n-hint: This is for screen reader software and indicates that
419 this track is selected.*/
420 name->Append( wxT(" ") + wxString(_( " Selected" )) );
421 }
422 if (SyncLock::IsSyncLockSelected(t.get()))
423 {
424 /* i18n-hint: This is for screen reader software and indicates that
425 this track is shown with a sync-locked icon.*/
426 // The absence of a dash between Sync and Locked is deliberate -
427 // if present, Jaws reads it as "dash".
428 name->Append( wxT(" ") + wxString(_( " Sync Locked" )) );
429 }
430 }
431 }
432 else
433 {
434 *name = mMessage;
435 }
436
437 return wxACC_OK;
438#endif
439
440#if defined(__WXMAC__)
441 return wxACC_NOT_IMPLEMENTED;
442#endif
443}
444
445// Returns a role constant.
446wxAccStatus TrackPanelAx::GetRole( int childId, wxAccRole* role )
447{
448#if defined(__WXMSW__)
449 if (mTrackName)
450 {
451 if( childId == wxACC_SELF )
452 {
453 *role = wxROLE_SYSTEM_TABLE;
454 }
455 else
456 {
457 *role = wxROLE_SYSTEM_ROW;
458 }
459 }
460 else
461 {
462 *role = wxROLE_NONE;
463 }
464#endif
465
466#if defined(__WXMAC__)
467 if( childId == wxACC_SELF )
468 {
469 *role = wxROLE_SYSTEM_PANE;
470 }
471 else
472 {
473 *role = wxROLE_SYSTEM_STATICTEXT;
474 }
475#endif
476
477 return wxACC_OK;
478}
479
480// Gets a variant representing the selected children
481// of this object.
482// Acceptable values:
483// - a null variant (IsNull() returns TRUE)
484// - a list variant (GetType() == wxT("list"))
485// - an integer representing the selected child element,
486// or 0 if this object is selected (GetType() == wxT("long"))
487// - a "void*" pointer to a wxAccessible child object
488wxAccStatus TrackPanelAx::GetSelections( wxVariant * WXUNUSED(selections) )
489{
490 return wxACC_NOT_IMPLEMENTED;
491}
492
493// Returns a state constant.
494wxAccStatus TrackPanelAx::GetState( int childId, long* state )
495{
496#if defined(__WXMSW__)
497 if( childId > 0 )
498 {
499 auto t = FindTrack( childId );
500
501 *state = wxACC_STATE_SYSTEM_FOCUSABLE | wxACC_STATE_SYSTEM_SELECTABLE;
502 if (t)
503 {
504 if( t == mFocusedTrack.lock() )
505 {
506 *state |= wxACC_STATE_SYSTEM_FOCUSED;
507 }
508
509 if( t->GetSelected() && mTrackName )
510 {
511 *state |= wxACC_STATE_SYSTEM_SELECTED;
512 }
513 }
514 }
515 else // childId == wxACC_SELF
516 {
517 *state = wxACC_STATE_SYSTEM_FOCUSABLE + wxACC_STATE_SYSTEM_FOCUSED;
518 }
519#endif
520
521#if defined(__WXMAC__)
522 *state = wxACC_STATE_SYSTEM_FOCUSABLE | wxACC_STATE_SYSTEM_SELECTABLE;
523
524 if( childId > 0 )
525 {
526 auto t = FindTrack( childId );
527
528 if (t)
529 {
530 if( t == mFocusedTrack.lock() )
531 {
532 *state |= wxACC_STATE_SYSTEM_FOCUSED;
533 }
534
535 if( t->GetSelected() )
536 {
537 *state |= wxACC_STATE_SYSTEM_SELECTED;
538 }
539 }
540 }
541#endif
542
543 return wxACC_OK;
544}
545
546// Returns a localized string representing the value for the object
547// or child.
548#if defined(__WXMAC__)
549wxAccStatus TrackPanelAx::GetValue( int childId, wxString* strValue )
550#else
551wxAccStatus TrackPanelAx::GetValue( int WXUNUSED(childId), wxString* WXUNUSED(strValue) )
552#endif
553{
554#if defined(__WXMSW__)
555 return wxACC_NOT_IMPLEMENTED;
556#endif
557
558#if defined(__WXMAC__)
559 if( childId == wxACC_SELF )
560 {
561 *strValue = _( "TrackView" );
562 }
563 else
564 {
565 auto t = FindTrack( childId );
566
567 if( t == NULL )
568 {
569 return wxACC_FAIL;
570 }
571 else
572 {
573 /* i18n-hint: The %d is replaced by the number of the track.*/
574 strValue->Printf(_("Track %d"), TrackNum(t));
575 strValue->Append(" " + t->GetName());
576
577 // LLL: Remove these during "refactor"
578 auto pt = dynamic_cast<PlayableTrack *>(t.get());
579 if( pt && pt->GetMute() )
580 {
581 strValue->Append( _( " Mute On" ) );
582 }
583
584 if( pt && pt->GetSolo() )
585 {
586 strValue->Append( _( " Solo On" ) );
587 }
588 if( t->GetSelected() )
589 {
590 strValue->Append( _( " Select On" ) );
591 }
592 }
593 }
594 return wxACC_OK;
595#endif
596}
597
598// Gets the window with the keyboard focus.
599// If childId is 0 and child is NULL, no object in
600// this subhierarchy has the focus.
601// If this object has the focus, child should be 'this'.
602wxAccStatus TrackPanelAx::GetFocus( int *childId, wxAccessible **child )
603{
604#if defined(__WXMSW__)
605
606 if (GetWindow() == wxWindow::FindFocus())
607 {
608 auto focusedTrack = mFocusedTrack.lock();
609 if (focusedTrack)
610 {
611 *childId = TrackNum(focusedTrack);
612 }
613 else
614 {
615 *child = this;
616 }
617 }
618
619 return wxACC_OK;
620#endif
621
622#if defined(__WXMAC__)
623 if( GetWindow() == wxWindow::FindFocus() )
624 {
625 auto focusedTrack = mFocusedTrack.lock();
626 if( focusedTrack )
627 {
628 *childId = TrackNum( focusedTrack );
629 }
630 else
631 {
632 *childId = wxACC_SELF;
633 }
634
635 return wxACC_OK;
636 }
637
638 return wxACC_NOT_IMPLEMENTED;
639#endif
640}
641
642// Navigates from fromId to toId/toObject
643wxAccStatus TrackPanelAx::Navigate(wxNavDir navDir, int fromId, int* toId, wxAccessible** toObject)
644{
645 int childCount;
646 GetChildCount( &childCount );
647
648 if (fromId > childCount)
649 return wxACC_FAIL;
650
651 switch (navDir) {
652 case wxNAVDIR_FIRSTCHILD:
653 if (fromId == wxACC_SELF && childCount > 0 )
654 *toId = 1;
655 else
656 return wxACC_FALSE;
657 break;
658
659 case wxNAVDIR_LASTCHILD:
660 if (fromId == wxACC_SELF && childCount > 0 )
661 *toId = childCount;
662 else
663 return wxACC_FALSE;
664 break;
665
666 case wxNAVDIR_NEXT:
667 case wxNAVDIR_DOWN:
668 if (fromId != wxACC_SELF) {
669 *toId = fromId + 1;
670 if (*toId > childCount)
671 return wxACC_FALSE;
672 }
673 else
674 return wxACC_NOT_IMPLEMENTED;
675 break;
676
677 case wxNAVDIR_PREVIOUS:
678 case wxNAVDIR_UP:
679 if (fromId != wxACC_SELF) {
680 *toId = fromId - 1;
681 if (*toId < 1)
682 return wxACC_FALSE;
683 }
684 else
685 return wxACC_NOT_IMPLEMENTED;
686 break;
687
688 case wxNAVDIR_LEFT:
689 case wxNAVDIR_RIGHT:
690 if (fromId != wxACC_SELF)
691 return wxACC_FALSE;
692 else
693 return wxACC_NOT_IMPLEMENTED;
694 break;
695 }
696
697 *toObject = nullptr;
698 return wxACC_OK;
699}
700
701// Modify focus or selection
702wxAccStatus TrackPanelAx::Select(int childId, wxAccSelectionFlags selectFlags)
703{
704 // Only support change of focus
705 if (selectFlags != wxACC_SEL_TAKEFOCUS)
706 return wxACC_NOT_IMPLEMENTED;
707
708 if (childId != wxACC_SELF) {
709 int childCount;
710 GetChildCount( &childCount );
711 if (childId > childCount)
712 return wxACC_FAIL;
713
714 Track* t = FindTrack(childId).get();
715 if (t) {
716 SetFocus( t->SharedPointer() );
717 t->EnsureVisible();
718 }
719 }
720 else
721 return wxACC_NOT_IMPLEMENTED;
722
723 return wxACC_OK;
724}
725
726#endif // wxUSE_ACCESSIBILITY
727
729 []( AudacityProject &parent ){
730 return std::make_shared< TrackFocus >( parent );
731 }
732};
733
735{
736 return project.AttachedObjects::Get< TrackFocus >( key );
737}
738
740{
741 return Get( const_cast< AudacityProject & >( project ) );
742}
743
745 : mProject{ project }
746{
747}
748
750{
751}
752
754{
755 if (mAx)
756 return mAx->GetFocus().get();
757 return nullptr;
758}
759
760void TrackFocus::Set( Track *pTrack )
761{
762 if (mAx) {
763 pTrack = *TrackList::Get( mProject ).FindLeader( pTrack );
764 mAx->SetFocus( Track::SharedPointer( pTrack ) );
765 }
766}
767
768bool TrackFocus::IsFocused( const Track *pTrack )
769{
770 if (mAx)
771 return mAx->IsFocused( pTrack );
772 return false;
773}
774
776 wxWindow &owner,
777 std::unique_ptr< TrackPanelAx > pAx
778)
779{
780#if wxUSE_ACCESSIBILITY
781 // wxWidgets owns the accessible object
782 owner.SetAccessible(mAx = pAx.release());
783#else
784 // wxWidgets does not own the object, but we need to retain it
785 mAx = std::move(pAx);
786#endif
787}
788
790{
791 if (mAx)
792 mAx->MessageForScreenReader( message );
793}
794
796{
797 if (mAx)
798 mAx->Updated();
799}
wxT("CloseDown"))
Toolkit-neutral facade for basic user interface services.
const TranslatableString name
Definition: Distortion.cpp:82
#define _(s)
Definition: Internat.h:75
declares abstract base class Track, TrackList, and iterators over TrackList
static const AudacityProject::AttachedObjects::RegisteredFactory key
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:89
static wxString GetDefaultName()
Definition: LabelTrack.cpp:58
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:63
AudioTrack subclass that can also be audibly replayed by the program.
Definition: Track.h:916
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:43
A kind of Track used to 'warp time'.
Definition: TimeTrack.h:24
static wxString GetDefaultName()
Definition: TimeTrack.cpp:41
~TrackFocus() override
void UpdateAccessibility()
void SetAccessible(wxWindow &owner, std::unique_ptr< TrackPanelAx > pAccessible)
void Set(Track *pTrack)
void MessageForScreenReader(const TranslatableString &message)
TrackFocus(AudacityProject &project)
std::unique_ptr< TrackPanelAx > mAx
Definition: TrackPanelAx.h:202
bool IsFocused(const Track *pTrack)
AudacityProject & mProject
Definition: TrackPanelAx.h:197
Track * Get()
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:97
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:297
TrackId GetId() const
Definition: Track.h:287
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1338
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1471
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486
Track * FindById(TrackId id)
Definition: Track.cpp:688
TrackIter< Track > FindLeader(Track *pTrack)
Definition: Track.cpp:644
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1541
RectangleFinder mFinder
Definition: TrackPanelAx.h:146
TrackPanelAx(AudacityProject &project)
std::weak_ptr< Track > mFocusedTrack
Definition: TrackPanelAx.h:148
void MessageForScreenReader(const TranslatableString &message)
std::shared_ptr< Track > GetFocus()
int mNumFocusedTrack
Definition: TrackPanelAx.h:149
virtual ~TrackPanelAx()
AudacityProject & mProject
Definition: TrackPanelAx.h:140
TrackList & GetTracks()
int TrackNum(const std::shared_ptr< Track > &track)
wxString mMessage
Definition: TrackPanelAx.h:151
std::shared_ptr< Track > SetFocus(std::shared_ptr< Track > track={})
bool IsFocused(const Track *track)
std::shared_ptr< Track > FindTrack(int num)
wxWindow * GetWindow() const
Definition: TrackPanelAx.h:130
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Definition: BasicUI.cpp:206
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
std::shared_ptr< Track > FindTrack(TrackPanelCell *pCell)
Definition: TrackPanel.cpp:526