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