mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-16 08:37:42 +02:00
New commands for clip boundaries using the keyboard
Added the commands: Cursor to > Previous clip boundary Cursor to > Next clip boundary Select > Previous clip boundary to cursor Select > Cursor to next clip boundary
This commit is contained in:
parent
8c8f38079d
commit
a519e6fc7d
182
src/Menus.cpp
182
src/Menus.cpp
@ -35,6 +35,7 @@ simplifies construction of menu items.
|
|||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
@ -586,6 +587,12 @@ void AudacityProject::CreateMenusAndCommands()
|
|||||||
|
|
||||||
c->AddItem(wxT("SelStartCursor"), _("Track &Start to Cursor"), FN(OnSelectStartCursor), wxT("Shift+J"));
|
c->AddItem(wxT("SelStartCursor"), _("Track &Start to Cursor"), FN(OnSelectStartCursor), wxT("Shift+J"));
|
||||||
c->AddItem(wxT("SelCursorEnd"), _("Cursor to Track &End"), FN(OnSelectCursorEnd), wxT("Shift+K"));
|
c->AddItem(wxT("SelCursorEnd"), _("Cursor to Track &End"), FN(OnSelectCursorEnd), wxT("Shift+K"));
|
||||||
|
c->AddItem(wxT("SelPrevClipBoundaryToCursor"), _("Pre&vious Clip Boundary to Cursor"),
|
||||||
|
FN(OnSelectPrevClipBoundaryToCursor), wxT(""),
|
||||||
|
TrackPanelHasFocus | WaveTracksExistFlag, TrackPanelHasFocus | WaveTracksExistFlag);
|
||||||
|
c->AddItem(wxT("SelCursorToNextClipBoundary"), _("Cursor to Ne&xt Clip Boundary"),
|
||||||
|
FN(OnSelectCursorToNextClipBoundary), wxT(""),
|
||||||
|
TrackPanelHasFocus |WaveTracksExistFlag, TrackPanelHasFocus | WaveTracksExistFlag);
|
||||||
c->AddItem(wxT("SelCursorStoredCursor"), _("Cursor to Saved &Cursor Position"), FN(OnSelectCursorStoredCursor),
|
c->AddItem(wxT("SelCursorStoredCursor"), _("Cursor to Saved &Cursor Position"), FN(OnSelectCursorStoredCursor),
|
||||||
wxT(""), TracksExistFlag, TracksExistFlag);
|
wxT(""), TracksExistFlag, TracksExistFlag);
|
||||||
|
|
||||||
@ -817,6 +824,11 @@ void AudacityProject::CreateMenusAndCommands()
|
|||||||
c->AddItem(wxT("CursTrackStart"), _("Track &Start"), FN(OnCursorTrackStart), wxT("J"));
|
c->AddItem(wxT("CursTrackStart"), _("Track &Start"), FN(OnCursorTrackStart), wxT("J"));
|
||||||
c->AddItem(wxT("CursTrackEnd"), _("Track &End"), FN(OnCursorTrackEnd), wxT("K"));
|
c->AddItem(wxT("CursTrackEnd"), _("Track &End"), FN(OnCursorTrackEnd), wxT("K"));
|
||||||
|
|
||||||
|
c->AddItem(wxT("CursPrevClipBoundary"), _("Pre&vious Clip Boundary"), FN(OnCursorPrevClipBoundary), wxT(""),
|
||||||
|
TrackPanelHasFocus | WaveTracksExistFlag, TrackPanelHasFocus | WaveTracksExistFlag);
|
||||||
|
c->AddItem(wxT("CursNextClipBoundary"), _("Ne&xt Clip Boundary"), FN(OnCursorNextClipBoundary), wxT(""),
|
||||||
|
TrackPanelHasFocus | WaveTracksExistFlag, TrackPanelHasFocus | WaveTracksExistFlag);
|
||||||
|
|
||||||
c->AddItem(wxT("CursProjectStart"), _("&Project Start"), FN(OnSkipStart), wxT("Home"));
|
c->AddItem(wxT("CursProjectStart"), _("&Project Start"), FN(OnSkipStart), wxT("Home"));
|
||||||
c->AddItem(wxT("CursProjectEnd"), _("Project E&nd"), FN(OnSkipEnd), wxT("End"));
|
c->AddItem(wxT("CursProjectEnd"), _("Project E&nd"), FN(OnSkipEnd), wxT("End"));
|
||||||
|
|
||||||
@ -5309,6 +5321,51 @@ void AudacityProject::OnSelectStartCursor()
|
|||||||
mTrackPanel->Refresh(false);
|
mTrackPanel->Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudacityProject::OnSelectPrevClipBoundaryToCursor()
|
||||||
|
{
|
||||||
|
OnSelectClipBoundary(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::OnSelectCursorToNextClipBoundary()
|
||||||
|
{
|
||||||
|
OnSelectClipBoundary(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::OnSelectClipBoundary(bool next)
|
||||||
|
{
|
||||||
|
const auto track = mTrackPanel->GetFocusedTrack();
|
||||||
|
|
||||||
|
if (track && track->GetKind() == Track::Wave) {
|
||||||
|
const auto wt = static_cast<WaveTrack*>(track);
|
||||||
|
if (wt->GetNumClips()) {
|
||||||
|
auto result = next ? FindNextClipBoundary(wt, mViewInfo.selectedRegion.t1()) :
|
||||||
|
FindPrevClipBoundary(wt, mViewInfo.selectedRegion.t0());
|
||||||
|
|
||||||
|
if (result.nFound > 0) {
|
||||||
|
if (next)
|
||||||
|
mViewInfo.selectedRegion.setT1(result.time);
|
||||||
|
else
|
||||||
|
mViewInfo.selectedRegion.setT0(result.time);
|
||||||
|
|
||||||
|
ModifyState(false);
|
||||||
|
mTrackPanel->Refresh(false);
|
||||||
|
|
||||||
|
wxString message;
|
||||||
|
message.Printf(wxT("%d %s %d %s"), result.index1 + 1, _("of"), wt->GetNumClips(),
|
||||||
|
result.clipStart1 ? _("start") : _("end"));
|
||||||
|
if (result.nFound == 2) {
|
||||||
|
wxString messageAdd;
|
||||||
|
messageAdd.Printf(wxT(" %s %d %s"), _("and"), result.index2 + 1,
|
||||||
|
result.clipStart2 ? _("start") : _("end"));
|
||||||
|
message += messageAdd;
|
||||||
|
}
|
||||||
|
mTrackPanel->MessageForScreenReader(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void AudacityProject::OnSelectCursorStoredCursor()
|
void AudacityProject::OnSelectCursorStoredCursor()
|
||||||
{
|
{
|
||||||
if (mCursorPositionHasBeenStored) {
|
if (mCursorPositionHasBeenStored) {
|
||||||
@ -6136,6 +6193,131 @@ void AudacityProject::OnCursorSelEnd()
|
|||||||
mTrackPanel->Refresh(false);
|
mTrackPanel->Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudacityProject::FoundClipBoundary AudacityProject::FindNextClipBoundary(const WaveTrack* wt, double time)
|
||||||
|
{
|
||||||
|
AudacityProject::FoundClipBoundary result{};
|
||||||
|
|
||||||
|
const auto clips = wt->SortedClipArray();
|
||||||
|
auto resultStart = find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||||
|
return clip->GetStartTime() > time; });
|
||||||
|
auto resultEnd = find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||||
|
return clip->GetEndTime() > time; });
|
||||||
|
|
||||||
|
if (resultStart != clips.end() && resultEnd != clips.end()) {
|
||||||
|
if ((*resultStart)->GetStartTime() < (*resultEnd)->GetEndTime()) {
|
||||||
|
result.nFound = 1;
|
||||||
|
result.time = (*resultStart)->GetStartTime();
|
||||||
|
result.index1 = resultStart - clips.begin();
|
||||||
|
result.clipStart1 = true;
|
||||||
|
}
|
||||||
|
else if ((*resultStart)->GetStartTime() > (*resultEnd)->GetEndTime()) {
|
||||||
|
result.nFound = 1;
|
||||||
|
result.time = (*resultEnd)->GetEndTime();
|
||||||
|
result.index1 = resultEnd - clips.begin();
|
||||||
|
result.clipStart1 = false;
|
||||||
|
}
|
||||||
|
else { // both the end of one clip and the start of the next clip
|
||||||
|
result.nFound = 2;
|
||||||
|
result.time = (*resultEnd)->GetEndTime();
|
||||||
|
result.index1 = resultEnd - clips.begin();
|
||||||
|
result.clipStart1 = false;
|
||||||
|
result.index2 = resultStart - clips.begin();
|
||||||
|
result.clipStart2 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (resultEnd != clips.end()) {
|
||||||
|
result.nFound = 1;
|
||||||
|
result.time = (*resultEnd)->GetEndTime();
|
||||||
|
result.index1 = resultEnd - clips.begin();
|
||||||
|
result.clipStart1 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudacityProject::FoundClipBoundary AudacityProject::FindPrevClipBoundary(const WaveTrack* wt, double time)
|
||||||
|
{
|
||||||
|
AudacityProject::FoundClipBoundary result{};
|
||||||
|
|
||||||
|
const auto clips = wt->SortedClipArray();
|
||||||
|
auto resultStart = find_if(clips.rbegin(), clips.rend(), [&] (const WaveClip* const& clip) {
|
||||||
|
return clip->GetStartTime() < time; });
|
||||||
|
auto resultEnd = find_if(clips.rbegin(), clips.rend(), [&] (const WaveClip* const& clip) {
|
||||||
|
return clip->GetEndTime() < time; });
|
||||||
|
|
||||||
|
if (resultStart != clips.rend() && resultEnd != clips.rend()) {
|
||||||
|
if ((*resultStart)->GetStartTime() > (*resultEnd)->GetEndTime()) {
|
||||||
|
result.nFound = 1;
|
||||||
|
result.time = (*resultStart)->GetStartTime();
|
||||||
|
result.index1 = static_cast<int>(clips.size()) - 1 - (resultStart - clips.rbegin());
|
||||||
|
result.clipStart1 = true;
|
||||||
|
}
|
||||||
|
else if ((*resultStart)->GetStartTime() < (*resultEnd)->GetEndTime()) {
|
||||||
|
result.nFound = 1;
|
||||||
|
result.time = (*resultEnd)->GetEndTime();
|
||||||
|
result.index1 = static_cast<int>(clips.size()) - 1 - (resultEnd - clips.rbegin());
|
||||||
|
result.clipStart1 = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.nFound = 2; // both the start of one clip and the end of the previous clip
|
||||||
|
result.time = (*resultStart)->GetStartTime();
|
||||||
|
result.index1 = static_cast<int>(clips.size()) - 1 - (resultStart - clips.rbegin());
|
||||||
|
result.clipStart1 = true;
|
||||||
|
result.index2 = static_cast<int>(clips.size()) - 1 - (resultEnd - clips.rbegin());
|
||||||
|
result.clipStart2 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (resultStart != clips.rend()) {
|
||||||
|
result.nFound = 1;
|
||||||
|
result.time = (*resultStart)->GetStartTime();
|
||||||
|
result.index1 = static_cast<int>(clips.size()) - 1 - (resultStart - clips.rbegin());
|
||||||
|
result.clipStart1 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::OnCursorNextClipBoundary()
|
||||||
|
{
|
||||||
|
OnCursorClipBoundary(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::OnCursorPrevClipBoundary()
|
||||||
|
{
|
||||||
|
OnCursorClipBoundary(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::OnCursorClipBoundary(bool next)
|
||||||
|
{
|
||||||
|
const auto track = mTrackPanel->GetFocusedTrack();
|
||||||
|
|
||||||
|
if (track && track->GetKind() == Track::Wave) {
|
||||||
|
const auto wt = static_cast<WaveTrack*>(track);
|
||||||
|
if (wt->GetNumClips()) {
|
||||||
|
auto result = next ? FindNextClipBoundary(wt, mViewInfo.selectedRegion.t0()) :
|
||||||
|
FindPrevClipBoundary(wt, mViewInfo.selectedRegion.t0());
|
||||||
|
|
||||||
|
if (result.nFound > 0) {
|
||||||
|
mViewInfo.selectedRegion.setTimes(result.time, result.time);
|
||||||
|
ModifyState(false);
|
||||||
|
mTrackPanel->ScrollIntoView(mViewInfo.selectedRegion.t0());
|
||||||
|
mTrackPanel->Refresh(false);
|
||||||
|
|
||||||
|
wxString message;
|
||||||
|
message.Printf(wxT("%d %s %d %s"), result.index1 + 1, _("of"), wt->GetNumClips(),
|
||||||
|
result.clipStart1 ? _("start") : _("end"));
|
||||||
|
if (result.nFound == 2) {
|
||||||
|
wxString messageAdd;
|
||||||
|
messageAdd.Printf(wxT(" %s %d %s"), _("and"), result.index2 + 1,
|
||||||
|
result.clipStart2 ? _("start") : _("end"));
|
||||||
|
message += messageAdd;
|
||||||
|
}
|
||||||
|
mTrackPanel->MessageForScreenReader(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AudacityProject::HandleAlign(int index, bool moveSel)
|
void AudacityProject::HandleAlign(int index, bool moveSel)
|
||||||
{
|
{
|
||||||
TrackListIterator iter(GetTracks());
|
TrackListIterator iter(GetTracks());
|
||||||
|
16
src/Menus.h
16
src/Menus.h
@ -282,6 +282,9 @@ void OnNextLowerPeakFrequency();
|
|||||||
#endif
|
#endif
|
||||||
void OnSelectCursorEnd();
|
void OnSelectCursorEnd();
|
||||||
void OnSelectStartCursor();
|
void OnSelectStartCursor();
|
||||||
|
void OnSelectPrevClipBoundaryToCursor();
|
||||||
|
void OnSelectCursorToNextClipBoundary();
|
||||||
|
void OnSelectClipBoundary(bool next);
|
||||||
void OnSelectCursorStoredCursor();
|
void OnSelectCursorStoredCursor();
|
||||||
void OnSelectSyncLockSel();
|
void OnSelectSyncLockSel();
|
||||||
void OnSelectAllTracks();
|
void OnSelectAllTracks();
|
||||||
@ -375,6 +378,19 @@ void OnCursorTrackStart();
|
|||||||
void OnCursorTrackEnd();
|
void OnCursorTrackEnd();
|
||||||
void OnCursorSelStart();
|
void OnCursorSelStart();
|
||||||
void OnCursorSelEnd();
|
void OnCursorSelEnd();
|
||||||
|
typedef struct FoundClipBoundary {
|
||||||
|
int nFound; // 0, 1, or 2
|
||||||
|
double time;
|
||||||
|
int index1;
|
||||||
|
bool clipStart1;
|
||||||
|
int index2;
|
||||||
|
bool clipStart2;
|
||||||
|
} FoundClipBoundary;
|
||||||
|
FoundClipBoundary FindNextClipBoundary(const WaveTrack* wt, double time);
|
||||||
|
FoundClipBoundary FindPrevClipBoundary(const WaveTrack* wt, double time);
|
||||||
|
void OnCursorNextClipBoundary();
|
||||||
|
void OnCursorPrevClipBoundary();
|
||||||
|
void OnCursorClipBoundary(bool next);
|
||||||
|
|
||||||
void OnAlignNoSync(int index);
|
void OnAlignNoSync(int index);
|
||||||
void OnAlign(int index);
|
void OnAlign(int index);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user