diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index c4d8940cc..38d5ed662 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1000,10 +1000,9 @@ void TrackPanel::OnTrackListDeletion(wxCommandEvent & e) if (mUIHandle) mUIHandle->OnProjectChange(GetProject()); - // Tracks may have been deleted, so check to see if the focused track was on of them. - if (!mTracks->Contains(GetFocusedTrack())) { - SetFocusedTrack(NULL); - } + // If the focused track disappeared but there are still other tracks, + // this reassigns focus. + GetFocusedTrack(); UpdateVRulerSize(); @@ -2573,7 +2572,7 @@ void TrackPanel::DisplaySelection() Track *TrackPanel::GetFocusedTrack() { - return mAx->GetFocus(); + return mAx->GetFocus().get(); } void TrackPanel::SetFocusedTrack( Track *t ) @@ -2590,7 +2589,7 @@ void TrackPanel::SetFocusedTrack( Track *t ) AudacityProject::CaptureKeyboard(this); } - mAx->SetFocus( t ); + mAx->SetFocus( Track::Pointer( t ) ); Refresh( false ); } diff --git a/src/TrackPanelAx.cpp b/src/TrackPanelAx.cpp index fe959da98..50d5666d1 100644 --- a/src/TrackPanelAx.cpp +++ b/src/TrackPanelAx.cpp @@ -36,7 +36,6 @@ TrackPanelAx::TrackPanelAx( wxWindow *window ) #endif { mTrackPanel = wxDynamicCast( window, TrackPanel ); - mFocusedTrack = NULL; mTrackName = true; mMessageCount = 0; @@ -47,56 +46,56 @@ TrackPanelAx::~TrackPanelAx() } // Returns currently focused track or first one if none focused -Track *TrackPanelAx::GetFocus() +std::shared_ptr TrackPanelAx::GetFocus() { - if( !mFocusedTrack ) + auto focusedTrack = mFocusedTrack.lock(); + if( !focusedTrack ) + focusedTrack = SetFocus(); + + if( !TrackNum( focusedTrack ) ) { - SetFocus( NULL ); + mFocusedTrack.reset(); + return {}; } - if( !TrackNum( mFocusedTrack ) ) - { - mFocusedTrack = NULL; - } - - return( mFocusedTrack ); + return( focusedTrack ); } // Changes focus to a specified track -void TrackPanelAx::SetFocus( Track *track ) +std::shared_ptr TrackPanelAx::SetFocus( std::shared_ptr track ) { mTrackName = true; #if wxUSE_ACCESSIBILITY - if( mFocusedTrack != NULL && !mFocusedTrack->GetSelected() ) + auto focusedTrack = mFocusedTrack.lock(); + if( focusedTrack && !focusedTrack->GetSelected() ) { NotifyEvent( wxACC_EVENT_OBJECT_SELECTIONREMOVE, mTrackPanel, wxOBJID_CLIENT, - TrackNum( mFocusedTrack ) ); + TrackNum( focusedTrack ) ); } #endif - if( track == NULL ) + if( !track ) { TrackListIterator iter( mTrackPanel->GetTracks() ); - track = iter.First(); + track = Track::Pointer( iter.First() ); } - mFocusedTrack = track; #if wxUSE_ACCESSIBILITY - if( mFocusedTrack != NULL ) + if( track ) { - int num = TrackNum( mFocusedTrack ); + int num = TrackNum( track ); NotifyEvent( wxACC_EVENT_OBJECT_FOCUS, mTrackPanel, wxOBJID_CLIENT, num ); - if( mFocusedTrack->GetSelected() ) + if( track->GetSelected() ) { NotifyEvent( wxACC_EVENT_OBJECT_SELECTION, mTrackPanel, @@ -106,19 +105,20 @@ void TrackPanelAx::SetFocus( Track *track ) } #endif - return; + mFocusedTrack = track; + + return track; } // Returns TRUE if passed track has the focus bool TrackPanelAx::IsFocused( Track *track ) { - if( !mFocusedTrack ) - { - SetFocus( NULL ); - } + auto focusedTrack = mFocusedTrack.lock(); + if( !focusedTrack ) + focusedTrack = SetFocus(); - if( ( track == mFocusedTrack ) || - ( track == mFocusedTrack->GetLink() ) ) + if( ( track == focusedTrack.get() ) || + ( track == focusedTrack->GetLink() ) ) { return true; } @@ -126,7 +126,7 @@ bool TrackPanelAx::IsFocused( Track *track ) return false; } -int TrackPanelAx::TrackNum( Track *target ) +int TrackPanelAx::TrackNum( const std::shared_ptr &target ) { TrackListIterator iter( mTrackPanel->GetTracks() ); Track *t = iter.First(); @@ -135,7 +135,7 @@ int TrackPanelAx::TrackNum( Track *target ) while( t != NULL ) { ndx++; - if( t == target ) + if( t == target.get() ) { return ndx; } @@ -146,7 +146,7 @@ int TrackPanelAx::TrackNum( Track *target ) return 0; } -Track *TrackPanelAx::FindTrack( int num ) +std::shared_ptr TrackPanelAx::FindTrack( int num ) { TrackListIterator iter( mTrackPanel->GetTracks() ); Track *t = iter.First(); @@ -163,13 +163,13 @@ Track *TrackPanelAx::FindTrack( int num ) t = iter.Next( true ); } - return t; + return Track::Pointer( t ); } void TrackPanelAx::Updated() { #if wxUSE_ACCESSIBILITY - Track *t = GetFocus(); + auto t = GetFocus(); mTrackName = true; // logically, this should be an OBJECT_NAMECHANGE event, but Window eyes 9.1 @@ -186,7 +186,7 @@ void TrackPanelAx::MessageForScreenReader(const wxString& message) #if wxUSE_ACCESSIBILITY if (mTrackPanel == wxWindow::FindFocus()) { - Track *t = GetFocus(); + auto t = GetFocus(); int childId = t ? TrackNum(t) : 0; mMessage = message; @@ -299,14 +299,14 @@ wxAccStatus TrackPanelAx::GetLocation( wxRect& rect, int elementId ) } else { - Track *t = FindTrack( elementId ); + auto t = FindTrack( elementId ); if( t == NULL ) { return wxACC_FAIL; } - rect = mTrackPanel->FindTrackRect( t, false ); + rect = mTrackPanel->FindTrackRect( t.get(), false ); // Inflate the screen reader's rectangle so it overpaints Audacity's own // yellow focus rectangle. #ifdef __WXMAC__ @@ -334,7 +334,7 @@ wxAccStatus TrackPanelAx::GetName( int childId, wxString* name ) } else { - Track *t = FindTrack( childId ); + auto t = FindTrack( childId ); if( t == NULL ) { @@ -371,7 +371,7 @@ wxAccStatus TrackPanelAx::GetName( int childId, wxString* name ) #endif // LLL: Remove these during "refactor" - auto pt = dynamic_cast(t); + auto pt = dynamic_cast(t.get()); if( pt && pt->GetMute() ) { // The following comment also applies to the solo, selected, @@ -475,7 +475,7 @@ wxAccStatus TrackPanelAx::GetState( int childId, long* state ) #if defined(__WXMSW__) if( childId > 0 ) { - Track *t = FindTrack( childId ); + auto t = FindTrack( childId ); *state = wxACC_STATE_SYSTEM_FOCUSABLE | wxACC_STATE_SYSTEM_SELECTABLE; if (t) @@ -502,11 +502,11 @@ wxAccStatus TrackPanelAx::GetState( int childId, long* state ) if( childId > 0 ) { - Track *t = FindTrack( childId ); + auto t = FindTrack( childId ); if (t) { - if( t == mFocusedTrack ) + if( t == mFocusedTrack.lock() ) { *state |= wxACC_STATE_SYSTEM_FOCUSED; } @@ -541,7 +541,7 @@ wxAccStatus TrackPanelAx::GetValue( int WXUNUSED(childId), wxString* WXUNUSED(st } else { - Track *t = FindTrack( childId ); + auto t = FindTrack( childId ); if( t == NULL ) { @@ -556,7 +556,7 @@ wxAccStatus TrackPanelAx::GetValue( int WXUNUSED(childId), wxString* WXUNUSED(st } // LLL: Remove these during "refactor" - auto pt = dynamic_cast(t); + auto pt = dynamic_cast(t.get()); if( pt && pt->GetMute() ) { strValue->Append( _( " Mute On" ) ); @@ -602,14 +602,15 @@ wxAccStatus TrackPanelAx::GetFocus( int *childId, wxAccessible **child ) #if defined(__WXMAC__) if( GetWindow() == wxWindow::FindFocus() ) { - if( mFocusedTrack ) + auto focusedTrack = mFocusedTrack.lock(); + if( focusedTrack ) { - *childId = TrackNum( mFocusedTrack ); + *childId = TrackNum( focusedTrack ); } else { *childId = wxACC_SELF; -} + } return wxACC_OK; } diff --git a/src/TrackPanelAx.h b/src/TrackPanelAx.h index 41e546f6c..cc6097e3d 100644 --- a/src/TrackPanelAx.h +++ b/src/TrackPanelAx.h @@ -32,10 +32,12 @@ public: virtual ~ TrackPanelAx(); // Returns currently focused track or first one if none focused - Track *GetFocus(); + std::shared_ptr GetFocus(); // Changes focus to a specified track - void SetFocus( Track *track ); + // Return is the actual focused track, which may be different from + // the argument when that is null + std::shared_ptr SetFocus( std::shared_ptr track = {} ); // Returns TRUE if passed track has the focus bool IsFocused( Track *track ); @@ -107,11 +109,12 @@ public: private: - int TrackNum( Track *track ); - Track *FindTrack( int num ); + int TrackNum( const std::shared_ptr &track ); + std::shared_ptr FindTrack( int num ); TrackPanel *mTrackPanel; - Track *mFocusedTrack; + + std::weak_ptr mFocusedTrack; wxString mMessage; bool mTrackName;