Skip to content

Commit

Permalink
Add two commands to move the cursor/selection to next/prev label
Browse files Browse the repository at this point in the history
The two commands are "selection to next label" and "selection to previous label".
They have default shortcuts alt+right and alt+left.

Primary motivation is for use by screen readers.
They use the first label track, if any, starting at the focused track.
  • Loading branch information
DavidBailes committed Oct 18, 2016
1 parent d5a6b83 commit b04a98e
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 69 deletions.
55 changes: 54 additions & 1 deletion src/LabelTrack.cpp
Expand Up @@ -105,7 +105,8 @@ LabelTrack::LabelTrack(const std::shared_ptr<DirManager> &projDirManager):
mMouseOverLabelRight(-1),
mRestoreFocus(-1),
mClipLen(0.0),
mIsAdjustingLabel(false)
mIsAdjustingLabel(false),
miLastLabel(-1)
{
SetDefaultName(_("Label Track"));
SetName(GetDefaultName());
Expand Down Expand Up @@ -2849,3 +2850,55 @@ wxString LabelTrack::GetTextOfLabels(double t0, double t1) const

return retVal;
}

int LabelTrack::FindNextLabel(const SelectedRegion& currentRegion)
{
int i = -1;

if (!mLabels.empty()) {
int len = (int) mLabels.size();
if (miLastLabel >= 0 && miLastLabel + 1 < len
&& currentRegion.t0() == mLabels[miLastLabel].getT0()
&& currentRegion.t0() == mLabels[miLastLabel + 1].getT0() ) {
i = miLastLabel + 1;
}
else {
i = 0;
if (currentRegion.t0() < mLabels[len - 1].getT0()) {
while (i < len &&
mLabels[i].getT0() <= currentRegion.t0()) {
i++;
}
}
}
}

miLastLabel = i;
return i;
}

int LabelTrack::FindPrevLabel(const SelectedRegion& currentRegion)
{
int i = -1;

if (!mLabels.empty()) {
int len = (int) mLabels.size();
if (miLastLabel > 0 && miLastLabel < len
&& currentRegion.t0() == mLabels[miLastLabel].getT0()
&& currentRegion.t0() == mLabels[miLastLabel - 1].getT0() ) {
i = miLastLabel - 1;
}
else {
i = len - 1;
if (currentRegion.t0() > mLabels[0].getT0()) {
while (i >=0 &&
mLabels[i].getT0() >= currentRegion.t0()) {
i--;
}
}
}
}

miLastLabel = i;
return i;
}
5 changes: 5 additions & 0 deletions src/LabelTrack.h
Expand Up @@ -232,6 +232,9 @@ class AUDACITY_DLL_API LabelTrack final : public Track
// Returns tab-separated text of all labels completely within given region
wxString GetTextOfLabels(double t0, double t1) const;

int FindNextLabel(const SelectedRegion& currentSelection);
int FindPrevLabel(const SelectedRegion& currentSelection);

public:
void SortLabels();
//These two are used by a TrackPanel KLUDGE, which is why they are public.
Expand Down Expand Up @@ -268,6 +271,8 @@ class AUDACITY_DLL_API LabelTrack final : public Track
// Set in copied label tracks
double mClipLen;

int miLastLabel; // used by FindNextLabel and FindPrevLabel

void ComputeLayout(const wxRect & r, const ZoomInfo &zoomInfo) const;
void ComputeTextPosition(const wxRect & r, int index) const;

Expand Down
50 changes: 50 additions & 0 deletions src/Menus.cpp
Expand Up @@ -1251,6 +1251,11 @@ void AudacityProject::CreateMenusAndCommands()
c->AddCommand(wxT("PlaySpeedInc"), _("Increase playback speed"), FN(OnPlaySpeedInc));
c->AddCommand(wxT("PlaySpeedDec"), _("Decrease playback speed"), FN(OnPlaySpeedDec));

c->AddCommand(wxT("SelToNextLabel"), _("Selection to next label"), FN(OnSelToNextLabel), wxT("Alt+Right"),
AudioIONotBusyFlag, AudioIONotBusyFlag);
c->AddCommand(wxT("SelToPrevLabel"), _("Selection to previous label"), FN(OnSelToPrevLabel), wxT("Alt+Left"),
AudioIONotBusyFlag, AudioIONotBusyFlag);

#ifdef __WXMAC__
/* i8n-hint: Shrink all project windows to icons on the Macintosh tooldock */
c->AddCommand(wxT("MacMinimizeAll"), _("Minimize all projects"),
Expand Down Expand Up @@ -2656,6 +2661,51 @@ void AudacityProject::OnSelToEnd()
ModifyState(false);
}

void AudacityProject::OnSelToNextLabel()
{
OnSelToLabel(true);
}

void AudacityProject::OnSelToPrevLabel()
{
OnSelToLabel(false);
}

void AudacityProject::OnSelToLabel(bool next)
{
Track* t = mTrackPanel->GetFocusedTrack();

// find first label track, if any, starting at the focused track
while (t && t->GetKind() != Track::Label) {
t = mTracks->GetNext(t, true);
}

if (t) {
LabelTrack* lt = static_cast<LabelTrack*>(t);
int i;
if (next)
i = lt->FindNextLabel(GetSelection());
else
i = lt->FindPrevLabel(GetSelection());

if (i >= 0) {
const LabelStruct* label = lt->GetLabel(i);
GetViewInfo().selectedRegion = label->selectedRegion;
RedrawProject();

wxString message;
message.Printf(wxT("%s %d of %d"), label->title, i + 1, lt->GetNumLabels() );
mTrackPanel->MessageForScreenReader(message);
}
else {
mTrackPanel->MessageForScreenReader(_("no labels in label track"));
}
}
else {
mTrackPanel->MessageForScreenReader(_("no label track"));
}
}

void AudacityProject::OnCursorUp()
{
mTrackPanel->OnPrevTrack( false );
Expand Down
4 changes: 4 additions & 0 deletions src/Menus.h
Expand Up @@ -170,6 +170,10 @@ void OnSetRightSelection();
void OnSelToStart();
void OnSelToEnd();

void OnSelToNextLabel();
void OnSelToPrevLabel();
void OnSelToLabel(bool next);

void OnZeroCrossing();

void OnLockPlayRegion();
Expand Down
6 changes: 6 additions & 0 deletions src/TrackPanel.cpp
Expand Up @@ -2408,6 +2408,12 @@ void TrackPanel::UpdateAccessibility()
mAx->Updated();
}

void TrackPanel::MessageForScreenReader(const wxString& message)
{
if (mAx)
mAx->MessageForScreenReader(message);
}

#ifdef EXPERIMENTAL_SPECTRAL_EDITING
namespace {

Expand Down
1 change: 1 addition & 0 deletions src/TrackPanel.h
Expand Up @@ -308,6 +308,7 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {

public:
virtual void UpdateAccessibility();
void MessageForScreenReader(const wxString& message);

#ifdef EXPERIMENTAL_SPECTRAL_EDITING
public:
Expand Down

0 comments on commit b04a98e

Please sign in to comment.