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()->GetRect();
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 }
345
346 rect.SetPosition( GetWindow()->GetParent()->ClientToScreen( rect.GetPosition() ) );
347
348 return wxACC_OK;
349}
350
351// Gets the name of the specified object.
352wxAccStatus TrackPanelAx::GetName( int childId, wxString* name )
353{
354#if defined(__WXMSW__) || defined(__WXMAC__)
355 if (mTrackName)
356 {
357 if( childId == wxACC_SELF )
358 {
359 *name = _( "TrackView" );
360 }
361 else
362 {
363 auto t = FindTrack( childId );
364
365 if( t == NULL )
366 return wxACC_FAIL;
367
368 name->Printf("%d %s", TrackNum(t), t->GetName());
369
370 if(dynamic_cast<LabelTrack*>(t.get()))
371 {
372 const auto trackNameLower = t->GetName().Lower();
373 //Prior to version 3.2 "Label Track" was the default
374 //name for label tracks, don't append type part to the
375 //text to avoid verbosity.
376 if(trackNameLower.Find(wxString(_("Label Track")).Lower()) == wxNOT_FOUND &&
377 trackNameLower.Find(LabelTrack::GetDefaultName().Lower()) == wxNOT_FOUND)
378 /* i18n-hint: This is for screen reader software and indicates that
379 this is a Label track.*/
380 name->Append( wxT(" ") + wxString(_("Label Track")));
381 }
382 else if(dynamic_cast<TimeTrack*>(t.get()))
383 {
384 if(t->GetName().Lower().Find(TimeTrack::GetDefaultName().Lower()) == wxNOT_FOUND)
385 /* i18n-hint: This is for screen reader software and indicates that
386 this is a Time track.*/
387 name->Append(wxT(" ") + wxString(_("Time Track")));
388 }
389#ifdef USE_MIDI
390 else if(dynamic_cast<NoteTrack*>(t.get()))
391 /* i18n-hint: This is for screen reader software and indicates that
392 this is a Note track.*/
393 name->Append( wxT(" ") + wxString(_("Note Track")));
394#endif
395
396 // LLL: Remove these during "refactor"
397 auto pt = dynamic_cast<PlayableTrack *>(t.get());
398 if( pt && pt->GetMute() )
399 {
400 // The following comment also applies to the solo, selected,
401 // and synclockselected states.
402 // Many of translations of the strings with a leading space omitted
403 // the leading space. Therefore a space has been added using wxT(" ").
404 // Because screen readers won't be affected by multiple spaces, the
405 // leading spaces have not been removed, so that no NEW translations are needed.
406 /* i18n-hint: This is for screen reader software and indicates that
407 this track is muted. (The mute button is on.)*/
408 name->Append( wxT(" ") + wxString(_( " Muted" )) );
409 }
410
411 if( pt && pt->GetSolo() )
412 {
413 /* i18n-hint: This is for screen reader software and indicates that
414 this track is soloed. (The Solo button is on.)*/
415 name->Append( wxT(" ") + wxString(_( " Soloed" )) );
416 }
417 if( t->GetSelected() )
418 {
419 /* i18n-hint: This is for screen reader software and indicates that
420 this track is selected.*/
421 name->Append( wxT(" ") + wxString(_( " Selected" )) );
422 }
423 if (SyncLock::IsSyncLockSelected(t.get()))
424 {
425 /* i18n-hint: This is for screen reader software and indicates that
426 this track is shown with a sync-locked icon.*/
427 // The absence of a dash between Sync and Locked is deliberate -
428 // if present, Jaws reads it as "dash".
429 name->Append( wxT(" ") + wxString(_( " Sync Locked" )) );
430 }
431 }
432 }
433 else
434 {
435 *name = mMessage;
436 }
437
438 return wxACC_OK;
439#endif
440
441#if defined(__WXMAC__)
442 return wxACC_NOT_IMPLEMENTED;
443#endif
444}
445
446// Returns a role constant.
447wxAccStatus TrackPanelAx::GetRole( int childId, wxAccRole* role )
448{
449#if defined(__WXMSW__)
450 if (mTrackName)
451 {
452 if( childId == wxACC_SELF )
453 {
454 *role = wxROLE_SYSTEM_TABLE;
455 }
456 else
457 {
458 *role = wxROLE_SYSTEM_ROW;
459 }
460 }
461 else
462 {
463 *role = wxROLE_NONE;
464 }
465#endif
466
467#if defined(__WXMAC__)
468 if( childId == wxACC_SELF )
469 {
470 *role = wxROLE_SYSTEM_PANE;
471 }
472 else
473 {
474 *role = wxROLE_SYSTEM_STATICTEXT;
475 }
476#endif
477
478 return wxACC_OK;
479}
480
481// Gets a variant representing the selected children
482// of this object.
483// Acceptable values:
484// - a null variant (IsNull() returns TRUE)
485// - a list variant (GetType() == wxT("list"))
486// - an integer representing the selected child element,
487// or 0 if this object is selected (GetType() == wxT("long"))
488// - a "void*" pointer to a wxAccessible child object
489wxAccStatus TrackPanelAx::GetSelections( wxVariant * WXUNUSED(selections) )
490{
491 return wxACC_NOT_IMPLEMENTED;
492}
493
494// Returns a state constant.
495wxAccStatus TrackPanelAx::GetState( int childId, long* state )
496{
497#if defined(__WXMSW__)
498 if( childId > 0 )
499 {
500 auto t = FindTrack( childId );
501
502 *state = wxACC_STATE_SYSTEM_FOCUSABLE | wxACC_STATE_SYSTEM_SELECTABLE;
503 if (t)
504 {
505 if( t == mFocusedTrack.lock() )
506 {
507 *state |= wxACC_STATE_SYSTEM_FOCUSED;
508 }
509
510 if( t->GetSelected() && mTrackName )
511 {
512 *state |= wxACC_STATE_SYSTEM_SELECTED;
513 }
514 }
515 }
516 else // childId == wxACC_SELF
517 {
518 *state = wxACC_STATE_SYSTEM_FOCUSABLE + wxACC_STATE_SYSTEM_FOCUSED;
519 }
520#endif
521
522#if defined(__WXMAC__)
523 *state = wxACC_STATE_SYSTEM_FOCUSABLE | wxACC_STATE_SYSTEM_SELECTABLE;
524
525 if( childId > 0 )
526 {
527 auto t = FindTrack( childId );
528
529 if (t)
530 {
531 if( t == mFocusedTrack.lock() )
532 {
533 *state |= wxACC_STATE_SYSTEM_FOCUSED;
534 }
535
536 if( t->GetSelected() )
537 {
538 *state |= wxACC_STATE_SYSTEM_SELECTED;
539 }
540 }
541 }
542#endif
543
544 return wxACC_OK;
545}
546
547// Returns a localized string representing the value for the object
548// or child.
549#if defined(__WXMAC__)
550wxAccStatus TrackPanelAx::GetValue( int childId, wxString* strValue )
551#else
552wxAccStatus TrackPanelAx::GetValue( int WXUNUSED(childId), wxString* WXUNUSED(strValue) )
553#endif
554{
555#if defined(__WXMSW__)
556 return wxACC_NOT_IMPLEMENTED;
557#endif
558
559#if defined(__WXMAC__)
560 if( childId == wxACC_SELF )
561 {
562 *strValue = _( "TrackView" );
563 }
564 else
565 {
566 auto t = FindTrack( childId );
567
568 if( t == NULL )
569 {
570 return wxACC_FAIL;
571 }
572 else
573 {
574 /* i18n-hint: The %d is replaced by the number of the track.*/
575 strValue->Printf(_("Track %d"), TrackNum(t));
576 strValue->Append(" " + t->GetName());
577
578 // LLL: Remove these during "refactor"
579 auto pt = dynamic_cast<PlayableTrack *>(t.get());
580 if( pt && pt->GetMute() )
581 {
582 strValue->Append( _( " Mute On" ) );
583 }
584
585 if( pt && pt->GetSolo() )
586 {
587 strValue->Append( _( " Solo On" ) );
588 }
589 if( t->GetSelected() )
590 {
591 strValue->Append( _( " Select On" ) );
592 }
593 }
594 }
595 return wxACC_OK;
596#endif
597}
598
599// Gets the window with the keyboard focus.
600// If childId is 0 and child is NULL, no object in
601// this subhierarchy has the focus.
602// If this object has the focus, child should be 'this'.
603wxAccStatus TrackPanelAx::GetFocus( int *childId, wxAccessible **child )
604{
605#if defined(__WXMSW__)
606
607 if (GetWindow() == wxWindow::FindFocus())
608 {
609 auto focusedTrack = mFocusedTrack.lock();
610 if (focusedTrack)
611 {
612 *childId = TrackNum(focusedTrack);
613 }
614 else
615 {
616 *child = this;
617 }
618 }
619
620 return wxACC_OK;
621#endif
622
623#if defined(__WXMAC__)
624 if( GetWindow() == wxWindow::FindFocus() )
625 {
626 auto focusedTrack = mFocusedTrack.lock();
627 if( focusedTrack )
628 {
629 *childId = TrackNum( focusedTrack );
630 }
631 else
632 {
633 *childId = wxACC_SELF;
634 }
635
636 return wxACC_OK;
637 }
638
639 return wxACC_NOT_IMPLEMENTED;
640#endif
641}
642
643// Navigates from fromId to toId/toObject
644wxAccStatus TrackPanelAx::Navigate(wxNavDir navDir, int fromId, int* toId, wxAccessible** toObject)
645{
646 int childCount;
647 GetChildCount( &childCount );
648
649 if (fromId > childCount)
650 return wxACC_FAIL;
651
652 switch (navDir) {
653 case wxNAVDIR_FIRSTCHILD:
654 if (fromId == wxACC_SELF && childCount > 0 )
655 *toId = 1;
656 else
657 return wxACC_FALSE;
658 break;
659
660 case wxNAVDIR_LASTCHILD:
661 if (fromId == wxACC_SELF && childCount > 0 )
662 *toId = childCount;
663 else
664 return wxACC_FALSE;
665 break;
666
667 case wxNAVDIR_NEXT:
668 case wxNAVDIR_DOWN:
669 if (fromId != wxACC_SELF) {
670 *toId = fromId + 1;
671 if (*toId > childCount)
672 return wxACC_FALSE;
673 }
674 else
675 return wxACC_NOT_IMPLEMENTED;
676 break;
677
678 case wxNAVDIR_PREVIOUS:
679 case wxNAVDIR_UP:
680 if (fromId != wxACC_SELF) {
681 *toId = fromId - 1;
682 if (*toId < 1)
683 return wxACC_FALSE;
684 }
685 else
686 return wxACC_NOT_IMPLEMENTED;
687 break;
688
689 case wxNAVDIR_LEFT:
690 case wxNAVDIR_RIGHT:
691 if (fromId != wxACC_SELF)
692 return wxACC_FALSE;
693 else
694 return wxACC_NOT_IMPLEMENTED;
695 break;
696 }
697
698 *toObject = nullptr;
699 return wxACC_OK;
700}
701
702// Modify focus or selection
703wxAccStatus TrackPanelAx::Select(int childId, wxAccSelectionFlags selectFlags)
704{
705 // Only support change of focus
706 if (selectFlags != wxACC_SEL_TAKEFOCUS)
707 return wxACC_NOT_IMPLEMENTED;
708
709 if (childId != wxACC_SELF) {
710 int childCount;
711 GetChildCount( &childCount );
712 if (childId > childCount)
713 return wxACC_FAIL;
714
715 Track* t = FindTrack(childId).get();
716 if (t) {
717 SetFocus( t->SharedPointer() );
718 t->EnsureVisible();
719 }
720 }
721 else
722 return wxACC_NOT_IMPLEMENTED;
723
724 return wxACC_OK;
725}
726
727#endif // wxUSE_ACCESSIBILITY
728
730 []( AudacityProject &parent ){
731 return std::make_shared< TrackFocus >( parent );
732 }
733};
734
736{
737 return project.AttachedObjects::Get< TrackFocus >( key );
738}
739
741{
742 return Get( const_cast< AudacityProject & >( project ) );
743}
744
746 : mProject{ project }
747{
748}
749
751{
752}
753
755{
756 if (mAx)
757 return mAx->GetFocus().get();
758 return nullptr;
759}
760
761void TrackFocus::Set( Track *pTrack )
762{
763 if (mAx) {
764 pTrack = *TrackList::Get( mProject ).FindLeader( pTrack );
765 mAx->SetFocus( Track::SharedPointer( pTrack ) );
766 }
767}
768
769bool TrackFocus::IsFocused( const Track *pTrack )
770{
771 if (mAx)
772 return mAx->IsFocused( pTrack );
773 return false;
774}
775
777 wxWindow &owner,
778 std::unique_ptr< TrackPanelAx > pAx
779)
780{
781#if wxUSE_ACCESSIBILITY
782 // wxWidgets owns the accessible object
783 owner.SetAccessible(mAx = pAx.release());
784#else
785 // wxWidgets does not own the object, but we need to retain it
786 mAx = std::move(pAx);
787#endif
788}
789
791{
792 if (mAx)
793 mAx->MessageForScreenReader( message );
794}
795
797{
798 if (mAx)
799 mAx->Updated();
800}
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:67
AudioTrack subclass that can also be audibly replayed by the program.
Definition: Track.h:909
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:98
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:290
TrackId GetId() const
Definition: Track.h:280
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1330
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1463
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:468
Track * FindById(TrackId id)
Definition: Track.cpp:674
TrackIter< Track > FindLeader(Track *pTrack)
Definition: Track.cpp:630
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1533
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:38
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