1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-23 09:20:16 +01:00

Add two commands to move the cursor/selection to next/prev label

The two commands are "selection to next label" and "selection to previous label".
They have default shortcuts alt+right and alt+left.

A label track does not have to be the focus. If there is a single label track in the project, that it used. If there is more than one label track, then the first label track, if any, starting at the focused track is used.

If the commands are used during playback of the project, playback continues from the new cursor/selection.

The commands provide feedback to screen readers: the name of the label, and position in the form of "i of n".
This commit is contained in:
David Bailes
2016-10-18 15:50:42 +01:00
parent e239efe486
commit ff9763f984
8 changed files with 261 additions and 68 deletions

View File

@@ -37,6 +37,9 @@ TrackPanelAx::TrackPanelAx( wxWindow *window )
{
mTrackPanel = wxDynamicCast( window, TrackPanel );
mFocusedTrack = NULL;
mTrackName = true;
mMessageCount = 0;
}
TrackPanelAx::~TrackPanelAx()
@@ -62,8 +65,11 @@ Track *TrackPanelAx::GetFocus()
// Changes focus to a specified track
void TrackPanelAx::SetFocus( Track *track )
{
mTrackName = true;
#if wxUSE_ACCESSIBILITY
if( mFocusedTrack != NULL )
if( mFocusedTrack != NULL && !mFocusedTrack->GetSelected() )
{
NotifyEvent( wxACC_EVENT_OBJECT_SELECTIONREMOVE,
mTrackPanel,
@@ -164,6 +170,7 @@ void TrackPanelAx::Updated()
{
#if wxUSE_ACCESSIBILITY
Track *t = GetFocus();
mTrackName = true;
// logically, this should be an OBJECT_NAMECHANGE event, but Window eyes 9.1
// does not read out the name with this event type, hence use OBJECT_FOCUS.
@@ -174,6 +181,32 @@ void TrackPanelAx::Updated()
#endif
}
void TrackPanelAx::MessageForScreenReader(const wxString& message)
{
#if wxUSE_ACCESSIBILITY
if (mTrackPanel == wxWindow::FindFocus())
{
Track *t = GetFocus();
int childId = t ? TrackNum(t) : 0;
mMessage = message;
// append \a alernatively, so that the string is never the same as the previous string.
// This ensures that screen readers read it.
if (mMessageCount % 2 == 0)
mMessage.Append('\a');
mMessageCount++;
mTrackName = false;
NotifyEvent(wxACC_EVENT_OBJECT_FOCUS,
mTrackPanel,
wxOBJID_CLIENT,
childId);
}
#endif
}
#if wxUSE_ACCESSIBILITY
// Retrieves the address of an IDispatch interface for the specified child.
@@ -285,82 +318,89 @@ wxAccStatus TrackPanelAx::GetLocation( wxRect& rect, int elementId )
wxAccStatus TrackPanelAx::GetName( int childId, wxString* name )
{
#if defined(__WXMSW__) || defined(__WXMAC__)
if( childId == wxACC_SELF )
if (mTrackName)
{
*name = _( "TrackView" );
}
else
{
Track *t = FindTrack( childId );
if( t == NULL )
if( childId == wxACC_SELF )
{
return wxACC_FAIL;
*name = _( "TrackView" );
}
else
{
*name = t->GetName();
if( *name == t->GetDefaultName() )
{
/* i18n-hint: The %d is replaced by th enumber of the track.*/
name->Printf(_("Track %d"), TrackNum( t ) );
}
Track *t = FindTrack( childId );
if (t->GetKind() == Track::Label)
if( t == NULL )
{
/* i18n-hint: This is for screen reader software and indicates that
this is a Label track.*/
name->Append( wxT(" ") + wxString(_("Label Track")));
return wxACC_FAIL;
}
else if (t->GetKind() == Track::Time)
else
{
/* i18n-hint: This is for screen reader software and indicates that
this is a Time track.*/
name->Append( wxT(" ") + wxString(_("Time Track")));
}
else if (t->GetKind() == Track::Note)
{
/* i18n-hint: This is for screen reader software and indicates that
this is a Note track.*/
name->Append( wxT(" ") + wxString(_("Note Track")));
}
*name = t->GetName();
if( *name == t->GetDefaultName() )
{
/* i18n-hint: The %d is replaced by th enumber of the track.*/
name->Printf(_("Track %d"), TrackNum( t ) );
}
// LLL: Remove these during "refactor"
if( t->GetMute() )
{
// The following comment also applies to the solo, selected,
// and synclockselected states.
// Many of translations of the strings with a leading space omitted
// the leading space. Therefore a space has been added using wxT(" ").
// Because screen readers won't be affected by multiple spaces, the
// leading spaces have not been removed, so that no NEW translations are needed.
/* i18n-hint: This is for screen reader software and indicates that
on this track mute is on.*/
name->Append( wxT(" ") + wxString(_( " Mute On" )) );
}
if (t->GetKind() == Track::Label)
{
/* i18n-hint: This is for screen reader software and indicates that
this is a Label track.*/
name->Append( wxT(" ") + wxString(_("Label Track")));
}
else if (t->GetKind() == Track::Time)
{
/* i18n-hint: This is for screen reader software and indicates that
this is a Time track.*/
name->Append( wxT(" ") + wxString(_("Time Track")));
}
else if (t->GetKind() == Track::Note)
{
/* i18n-hint: This is for screen reader software and indicates that
this is a Note track.*/
name->Append( wxT(" ") + wxString(_("Note Track")));
}
if( t->GetSolo() )
{
/* i18n-hint: This is for screen reader software and indicates that
on this track solo is on.*/
name->Append( wxT(" ") + wxString(_( " Solo On" )) );
}
if( t->GetSelected() )
{
/* i18n-hint: This is for screen reader software and indicates that
this track is selected.*/
name->Append( wxT(" ") + wxString(_( " Select On" )) );
}
if( t->IsSyncLockSelected() )
{
/* i18n-hint: This is for screen reader software and indicates that
this track is shown with a sync-locked icon.*/
// The absence of a dash between Sync and Locked is deliberate -
// if present, Jaws reads it as "dash".
name->Append( wxT(" ") + wxString(_( " Sync Lock Selected" )) );
// LLL: Remove these during "refactor"
if( t->GetMute() )
{
// The following comment also applies to the solo, selected,
// and synclockselected states.
// Many of translations of the strings with a leading space omitted
// the leading space. Therefore a space has been added using wxT(" ").
// Because screen readers won't be affected by multiple spaces, the
// leading spaces have not been removed, so that no NEW translations are needed.
/* i18n-hint: This is for screen reader software and indicates that
on this track mute is on.*/
name->Append( wxT(" ") + wxString(_( " Mute On" )) );
}
if( t->GetSolo() )
{
/* i18n-hint: This is for screen reader software and indicates that
on this track solo is on.*/
name->Append( wxT(" ") + wxString(_( " Solo On" )) );
}
if( t->GetSelected() )
{
/* i18n-hint: This is for screen reader software and indicates that
this track is selected.*/
name->Append( wxT(" ") + wxString(_( " Select On" )) );
}
if( t->IsSyncLockSelected() )
{
/* i18n-hint: This is for screen reader software and indicates that
this track is shown with a sync-locked icon.*/
// The absence of a dash between Sync and Locked is deliberate -
// if present, Jaws reads it as "dash".
name->Append( wxT(" ") + wxString(_( " Sync Lock Selected" )) );
}
}
}
}
else
{
*name = mMessage;
}
return wxACC_OK;
#endif
@@ -374,13 +414,20 @@ wxAccStatus TrackPanelAx::GetName( int childId, wxString* name )
wxAccStatus TrackPanelAx::GetRole( int childId, wxAccRole* role )
{
#if defined(__WXMSW__)
if( childId == wxACC_SELF )
if (mTrackName)
{
*role = wxROLE_SYSTEM_TABLE;
if( childId == wxACC_SELF )
{
*role = wxROLE_SYSTEM_TABLE;
}
else
{
*role = wxROLE_SYSTEM_ROW;
}
}
else
{
*role = wxROLE_SYSTEM_ROW;
*role = wxROLE_NONE;
}
#endif
@@ -427,7 +474,7 @@ wxAccStatus TrackPanelAx::GetState( int childId, long* state )
*state |= wxACC_STATE_SYSTEM_FOCUSED;
}
if( t->GetSelected() )
if( t->GetSelected() && mTrackName )
{
*state |= wxACC_STATE_SYSTEM_SELECTED;
}