mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-21 06:40:08 +02:00
Update to Select Previous/Next clip commands
Previously, these two commands used the clips in the focused track. They now have similar to the Tracks->Pan->Left/Right/Center commands. That is if any audio tracks are selected, the clips in these tracks are used, otherwise the clips in all audio tracks are used.
This commit is contained in:
parent
ce1d067f84
commit
baf46c1f85
185
src/Menus.cpp
185
src/Menus.cpp
@ -5509,6 +5509,120 @@ void AudacityProject::OnSelectClipBoundary(bool next)
|
||||
}
|
||||
}
|
||||
|
||||
AudacityProject::FoundClip AudacityProject::FindNextClip(const WaveTrack* wt, double t0, double t1)
|
||||
{
|
||||
AudacityProject::FoundClip result{};
|
||||
result.waveTrack = wt;
|
||||
const auto clips = wt->SortedClipArray();
|
||||
|
||||
auto p = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() == t0; });
|
||||
if (p != clips.end() && (*p)->GetEndTime() > t1) {
|
||||
result.found = true;
|
||||
result.startTime = (*p)->GetStartTime();
|
||||
result.endTime = (*p)->GetEndTime();
|
||||
result.index = std::distance(clips.begin(), p);
|
||||
}
|
||||
else {
|
||||
auto p = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() > t0; });
|
||||
if (p != clips.end()) {
|
||||
result.found = true;
|
||||
result.startTime = (*p)->GetStartTime();
|
||||
result.endTime = (*p)->GetEndTime();
|
||||
result.index = std::distance(clips.begin(), p);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AudacityProject::FoundClip AudacityProject::FindPrevClip(const WaveTrack* wt, double t0, double t1)
|
||||
{
|
||||
AudacityProject::FoundClip result{};
|
||||
result.waveTrack = wt;
|
||||
const auto clips = wt->SortedClipArray();
|
||||
|
||||
auto p = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() == t0; });
|
||||
if (p != clips.end() && (*p)->GetEndTime() < t1) {
|
||||
result.found = true;
|
||||
result.startTime = (*p)->GetStartTime();
|
||||
result.endTime = (*p)->GetEndTime();
|
||||
result.index = std::distance(clips.begin(), p);
|
||||
}
|
||||
else {
|
||||
auto p = std::find_if(clips.rbegin(), clips.rend(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() < t0; });
|
||||
if (p != clips.rend()) {
|
||||
result.found = true;
|
||||
result.startTime = (*p)->GetStartTime();
|
||||
result.endTime = (*p)->GetEndTime();
|
||||
result.index = static_cast<int>(clips.size()) - 1 - std::distance(clips.rbegin(), p);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int AudacityProject::FindClips(double t0, double t1, bool next, std::vector<FoundClip>& finalResults)
|
||||
{
|
||||
const TrackList* tracks = GetTracks();
|
||||
finalResults.clear();
|
||||
|
||||
bool anyWaveTracksSelected = std::any_of(tracks->begin(), tracks->end(), [] (const movable_ptr<Track>& t) {
|
||||
return t->GetSelected() && t->GetKind() == Track::Wave; });
|
||||
|
||||
// first search the tracks individually
|
||||
std::vector<FoundClip> results;
|
||||
int nTracksSearched = 0;
|
||||
for (auto& track : *tracks) {
|
||||
if (track->GetKind() == Track::Wave && (!anyWaveTracksSelected || track->GetSelected())) {
|
||||
auto waveTrack = static_cast<const WaveTrack*>(track.get());
|
||||
auto result = next ? FindNextClip(waveTrack, t0, t1) :
|
||||
FindPrevClip(waveTrack, t0, t1);
|
||||
nTracksSearched++;
|
||||
if (result.found)
|
||||
results.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.size() > 0) {
|
||||
// if any clips were found,
|
||||
// find the clip or clips with the min/max start time
|
||||
auto compareStart = [] (const FoundClip& a, const FoundClip& b)
|
||||
{ return a.startTime < b.startTime; };
|
||||
|
||||
auto p = next ? std::min_element(results.begin(), results.end(), compareStart) :
|
||||
std::max_element(results.begin(), results.end(), compareStart);
|
||||
|
||||
std::vector<FoundClip> resultsStartTime;
|
||||
std::copy_if(results.begin(), results.end(), std::back_inserter(resultsStartTime),
|
||||
[&] (const FoundClip& r) { return r.startTime == (*p).startTime; } );
|
||||
|
||||
if (resultsStartTime.size() > 1) {
|
||||
// more than one clip with same start time so
|
||||
// find the clip or clips with the min/max end time
|
||||
auto compareEnd = [] (const FoundClip& a, const FoundClip& b)
|
||||
{ return a.endTime < b.endTime; };
|
||||
|
||||
auto p = next ? std::min_element(resultsStartTime.begin(),
|
||||
resultsStartTime.end(), compareEnd) :
|
||||
std::max_element(resultsStartTime.begin(),
|
||||
resultsStartTime.end(), compareEnd);
|
||||
|
||||
std::copy_if(resultsStartTime.begin(), resultsStartTime.end(),
|
||||
std::back_inserter(finalResults),
|
||||
[&] (const FoundClip& r) { return r.endTime == (*p).endTime; } );
|
||||
}
|
||||
else {
|
||||
finalResults = resultsStartTime;
|
||||
}
|
||||
}
|
||||
|
||||
return nTracksSearched;
|
||||
}
|
||||
|
||||
void AudacityProject::OnSelectPrevClip()
|
||||
{
|
||||
OnSelectClip(false);
|
||||
@ -5521,50 +5635,43 @@ void AudacityProject::OnSelectNextClip()
|
||||
|
||||
void AudacityProject::OnSelectClip(bool next)
|
||||
{
|
||||
auto track = mTrackPanel->GetFocusedTrack();
|
||||
std::vector<FoundClip> results;
|
||||
int nTracksSearched = FindClips(mViewInfo.selectedRegion.t0(),
|
||||
mViewInfo.selectedRegion.t1(), next, results);
|
||||
|
||||
if (track && track->GetKind() == Track::Wave) {
|
||||
auto wt = static_cast<WaveTrack*>(track);
|
||||
const auto clips = wt->SortedClipArray();
|
||||
double t0 = mViewInfo.selectedRegion.t0();
|
||||
double t1 = mViewInfo.selectedRegion.t1();
|
||||
WaveClip* clip = nullptr;
|
||||
int i = 0;
|
||||
if (results.size() > 0) {
|
||||
// note that if there is more than one result, each has the same start
|
||||
// and end time
|
||||
double t0 = results[0].startTime;
|
||||
double t1 = results[0].endTime;
|
||||
mViewInfo.selectedRegion.setTimes(t0, t1);
|
||||
ModifyState(false);
|
||||
mTrackPanel->ScrollIntoView(mViewInfo.selectedRegion.t0());
|
||||
mTrackPanel->Refresh(false);
|
||||
|
||||
if (next) {
|
||||
auto result = std::find_if(clips.begin(), clips.end(), [&] (WaveClip* const& clip) {
|
||||
return clip->GetStartTime() == t0; });
|
||||
if (result != clips.end() && (*result)->GetEndTime() != t1 ) {
|
||||
clip = *result;
|
||||
i = result - clips.begin();
|
||||
}
|
||||
else {
|
||||
auto result = std::find_if(clips.begin(), clips.end(), [&] (WaveClip* const& clip) {
|
||||
return clip->GetStartTime() > t0; });
|
||||
if (result != clips.end()) {
|
||||
clip = *result;
|
||||
i = result - clips.begin();
|
||||
// create and send message to screen reader
|
||||
wxString message;
|
||||
for (auto& result : results) {
|
||||
wxString temp;
|
||||
|
||||
if (nTracksSearched > 1) {
|
||||
if (result.waveTrack->GetName() == result.waveTrack->GetDefaultName()) {
|
||||
auto track = std::find_if(GetTracks()->begin(), GetTracks()->end(),
|
||||
[&] (const movable_ptr<Track>& t) { return t.get() == result.waveTrack; });
|
||||
temp.Printf(wxT("%s %d "), _("Track"), std::distance(GetTracks()->begin(), track) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto result = std::find_if(clips.rbegin(), clips.rend(), [&] (WaveClip* const& clip) {
|
||||
return clip->GetStartTime() < t0; });
|
||||
if (result != clips.rend()) {
|
||||
clip = *result;
|
||||
i = static_cast<int>(clips.size()) - 1 - (result - clips.rbegin());
|
||||
}
|
||||
}
|
||||
else
|
||||
temp.Printf(wxT("%s "), result.waveTrack->GetName());
|
||||
|
||||
if (clip) {
|
||||
mViewInfo.selectedRegion.setTimes(clip->GetStartTime(), clip->GetEndTime());
|
||||
mTrackPanel->ScrollIntoView(mViewInfo.selectedRegion.t0());
|
||||
ModifyState(false);
|
||||
mTrackPanel->Refresh(false);
|
||||
wxString message;
|
||||
message.Printf(wxT("%d %s %d %s"), i + 1, _("of"), clips.size(), _("selected"));
|
||||
mTrackPanel->MessageForScreenReader(message);
|
||||
message += temp;
|
||||
}
|
||||
if (result.waveTrack->GetNumClips() > 1 || nTracksSearched == 1) {
|
||||
temp.Printf(wxT("%d %s %d "), result.index + 1, _("of"), result.waveTrack->GetNumClips());
|
||||
message += temp;
|
||||
}
|
||||
message += wxT(", ");
|
||||
}
|
||||
mTrackPanel->MessageForScreenReader(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
10
src/Menus.h
10
src/Menus.h
@ -288,6 +288,16 @@ void OnSelectStartCursor();
|
||||
void OnSelectPrevClipBoundaryToCursor();
|
||||
void OnSelectCursorToNextClipBoundary();
|
||||
void OnSelectClipBoundary(bool next);
|
||||
typedef struct FoundClip {
|
||||
const WaveTrack* waveTrack;
|
||||
bool found;
|
||||
double startTime;
|
||||
double endTime;
|
||||
int index;
|
||||
} FoundClip;
|
||||
FoundClip FindNextClip(const WaveTrack* wt, double t0, double t1);
|
||||
FoundClip FindPrevClip(const WaveTrack* wt, double t0, double t1);
|
||||
int FindClips(double t0, double t1, bool next, std::vector<FoundClip>& results);
|
||||
void OnSelectPrevClip();
|
||||
void OnSelectNextClip();
|
||||
void OnSelectClip(bool next);
|
||||
|
Loading…
x
Reference in New Issue
Block a user