1#include "../CommonCommandFlags.h"
13#include "../tracks/ui/TimeShiftHandle.h"
27 auto shortName = wxString::Format(
_(
"Track %d"), trackNum)
28 .Append(
" " + waveTrack->GetName());
63 auto q = std::find_if(clips.begin(), clips.end(),
64 [&] (
const auto& clip) {
65 return clip->GetPlayEndTime() == time; });
66 if (q != clips.end() && q + 1 != clips.end() &&
68 time = (*(q+1))->GetPlayStartTime();
85 auto q = std::find_if(clips.begin(), clips.end(),
87 return clip->GetPlayStartTime() == time; });
88 if (q != clips.end() && q != clips.begin() &&
90 time = (*(q-1))->GetPlayEndTime();
104 auto pStart = std::find_if(clips.begin(), clips.end(),
105 [&] (
const auto& clip) {
106 return clip->GetPlayStartTime() > timeStart; });
107 auto pEnd = std::find_if(clips.begin(), clips.end(),
108 [&] (
const auto& clip) {
109 return clip->GetPlayEndTime() > timeEnd; });
111 if (pStart != clips.end() && pEnd != clips.end()) {
115 result.time = (*pEnd)->GetPlayEndTime();
116 result.index1 = std::distance(clips.begin(), pEnd);
117 result.name1 = (*pEnd)->GetName();
118 result.clipStart1 =
false;
119 result.index2 = std::distance(clips.begin(), pStart);
120 result.name2 = (*pStart)->GetName();
121 result.clipStart2 =
true;
123 else if ((*pStart)->GetPlayStartTime() < (*pEnd)->GetPlayEndTime()) {
125 result.time = (*pStart)->GetPlayStartTime();
126 result.index1 = std::distance(clips.begin(), pStart);
127 result.name1 = (*pStart)->GetName();
128 result.clipStart1 =
true;
132 result.time = (*pEnd)->GetPlayEndTime();
133 result.index1 = std::distance(clips.begin(), pEnd);
134 result.name1 = (*pEnd)->GetName();
135 result.clipStart1 =
false;
138 else if (pEnd != clips.end()) {
140 result.time = (*pEnd)->GetPlayEndTime();
141 result.index1 = std::distance(clips.begin(), pEnd);
142 result.name1 = (*pEnd)->GetName();
143 result.clipStart1 =
false;
157 auto pStart = std::find_if(clips.rbegin(), clips.rend(),
158 [&] (
const auto& clip) {
159 return clip->GetPlayStartTime() < timeStart; });
160 auto pEnd = std::find_if(clips.rbegin(), clips.rend(),
161 [&] (
const auto& clip) {
162 return clip->GetPlayEndTime() < timeEnd; });
164 if (pStart != clips.rend() && pEnd != clips.rend()) {
168 result.time = (*pStart)->GetPlayStartTime();
170 static_cast<int>(clips.size()) - 1 -
171 std::distance(clips.rbegin(), pStart);
172 result.name1 = (*pStart)->GetName();
173 result.clipStart1 =
true;
175 static_cast<int>(clips.size()) - 1 -
176 std::distance(clips.rbegin(), pEnd);
177 result.name2 = (*pEnd)->GetName();
178 result.clipStart2 =
false;
180 else if ((*pStart)->GetPlayStartTime() > (*pEnd)->GetPlayEndTime()) {
182 result.time = (*pStart)->GetPlayStartTime();
184 static_cast<int>(clips.size()) - 1 -
185 std::distance(clips.rbegin(), pStart);
186 result.name1 = (*pStart)->GetName();
187 result.clipStart1 =
true;
191 result.time = (*pEnd)->GetPlayEndTime();
193 static_cast<int>(clips.size()) - 1 -
194 std::distance(clips.rbegin(), pEnd);
195 result.name1 = (*pEnd)->GetName();
196 result.clipStart1 =
false;
199 else if (pStart != clips.rend()) {
201 result.time = (*pStart)->GetPlayStartTime();
203 static_cast<int>(clips.size()) - 1 -
204 std::distance(clips.rbegin(), pStart);
205 result.name1 = (*pStart)->GetName();
206 result.clipStart1 =
true;
214 double time,
bool next, std::vector<FoundClipBoundary>& finalResults)
217 finalResults.clear();
224 std::vector<FoundClipBoundary> results;
226 int nTracksSearched = 0;
228 auto waveTracks = all.Filter<
const WaveTrack>();
229 if (anyWaveTracksSelected)
231 for (
auto waveTrack : waveTracks) {
234 if (result.nFound > 0) {
236 1 + std::distance(all.begin(), all.find(waveTrack));
237 results.push_back(result);
244 if (results.size() > 0) {
248 {
return a.
time < b.time; };
250 auto p = next ? min_element(results.begin(), results.end(), compare ) :
251 max_element(results.begin(), results.end(), compare);
253 for (
auto &r : results )
254 if ( r.time == (*p).time )
255 finalResults.push_back( r );
258 return nTracksSearched;
263 const std::vector<FoundClipBoundary>& results)
266 for (
auto& result : results) {
268 auto longName = result.ComposeTrackName();
271 auto nClips = result.waveTrack->GetNumClips();
272 if (result.nFound < 2) {
284 "%s %s, %d of %d clip %s",
285 "%s %s, %d of %d clips %s",
288 result.clipStart1 ?
XO(
"start") :
XO(
"end"),
307 "%s %s and %s %s, %d and %d of %d clip %s",
308 "%s %s and %s %s, %d and %d of %d clips %s",
311 result.clipStart1 ?
XO(
"start") :
XO(
"end"),
313 result.clipStart2 ?
XO(
"start") :
XO(
"end"),
325 message =
XO(
"%s, %s").Format( message,
str );
336 std::vector<FoundClipBoundary> results;
338 selectedRegion.t0(), next, results);
340 if (results.size() > 0) {
344 selectedRegion.setT1(results[0].time);
346 selectedRegion.setT0(results[0].time);
351 trackFocus.MessageForScreenReader(message);
364 auto p = std::find_if(clips.begin(), clips.end(),
365 [&] (
const auto& clip) {
366 return clip->GetPlayStartTime() == t0; });
367 if (p != clips.end() && (*p)->GetPlayEndTime() > t1) {
369 result.startTime = (*p)->GetPlayStartTime();
370 result.endTime = (*p)->GetPlayEndTime();
371 result.name = (*p)->GetName();
372 result.index = std::distance(clips.begin(), p);
378 auto p = std::find_if(clips.begin(), clips.end(),
379 [&] (
const auto& clip) {
380 return clip->GetPlayStartTime() > t0; });
381 if (p != clips.end()) {
383 result.startTime = (*p)->GetPlayStartTime();
384 result.endTime = (*p)->GetPlayEndTime();
385 result.name = (*p)->GetName();
386 result.index = std::distance(clips.begin(), p);
403 auto p = std::find_if(clips.begin(), clips.end(),
404 [&] (
const auto& clip) {
405 return clip->GetPlayStartTime() == t0; });
406 if (p != clips.end() && (*p)->GetPlayEndTime() < t1) {
408 result.startTime = (*p)->GetPlayStartTime();
409 result.endTime = (*p)->GetPlayEndTime();
410 result.name = (*p)->GetName();
411 result.index = std::distance(clips.begin(), p);
417 auto p = std::find_if(clips.rbegin(), clips.rend(),
418 [&] (
const auto& clip) {
419 return clip->GetPlayStartTime() < t0; });
420 if (p != clips.rend()) {
422 result.startTime = (*p)->GetPlayStartTime();
423 result.endTime = (*p)->GetPlayEndTime();
424 result.name = (*p)->GetName();
426 static_cast<int>(clips.size()) - 1 -
427 std::distance(clips.rbegin(), p);
437 double t0,
double t1,
bool next, std::vector<FoundClip>& finalResults)
440 finalResults.clear();
446 std::vector<FoundClip> results;
448 int nTracksSearched = 0;
450 auto waveTracks = all.Filter<
const WaveTrack>();
451 if (anyWaveTracksSelected)
453 for (
auto waveTrack : waveTracks) {
458 1 + std::distance(all.begin(), all.find(waveTrack));
459 results.push_back(result);
465 if (results.size() > 0) {
472 ? std::min_element(results.begin(), results.end(), compareStart)
473 : std::max_element(results.begin(), results.end(), compareStart);
475 std::vector<FoundClip> resultsStartTime;
476 for (
auto &r : results )
477 if ( r.startTime == (*pStart).startTime )
478 resultsStartTime.push_back( r );
480 if (resultsStartTime.size() > 1) {
484 {
return a.
endTime < b.endTime; };
486 auto pEnd = next ? std::min_element(resultsStartTime.begin(),
487 resultsStartTime.end(), compareEnd) :
488 std::max_element(resultsStartTime.begin(),
489 resultsStartTime.end(), compareEnd);
491 for (
auto &r : resultsStartTime )
492 if ( r.endTime == (*pEnd).endTime )
493 finalResults.push_back( r );
496 finalResults = resultsStartTime;
500 return nTracksSearched;
509 std::vector<FoundClip> results;
511 selectedRegion.t1(), next, results);
513 if (results.size() > 0) {
516 double t0 = results[0].startTime;
517 double t1 = results[0].endTime;
518 selectedRegion.setTimes(t0, t1);
520 viewport.ScrollIntoView(selectedRegion.t0());
524 for (
auto& result : results) {
525 auto longName = result.ComposeTrackName();
526 auto nClips = result.waveTrack->GetNumClips();
534 "%s, %d of %d clip %s",
535 "%s, %d of %d clips %s",
547 message =
XO(
"%s, %s").Format( message,
str );
549 trackFocus.MessageForScreenReader(message);
560 std::vector<FoundClipBoundary> results;
562 selectedRegion.t0(), next, results);
564 if (results.size() > 0) {
567 double time = results[0].time;
568 selectedRegion.setTimes(time, time);
570 viewport.ScrollIntoView(selectedRegion.t0());
573 trackFocus.MessageForScreenReader(message);
579 bool syncLocked,
bool right)
583 auto &selectedRegion = viewInfo.selectedRegion;
585 auto track = trackFocus.Get();
589 auto t0 = selectedRegion.t0();
591 std::unique_ptr<TrackShifter> uShifter;
595 if ((hitTestResult = uShifter->HitTest(t0, viewInfo)) ==
599 auto pShifter = uShifter.get();
600 auto desiredT0 = viewInfo.OffsetTimeByPixels(t0, (right ? 1 : -1));
601 auto desiredSlideAmount = pShifter->HintOffsetLarger(desiredT0 - t0);
603 state.
Init(
project, pShifter->GetTrack(), hitTestResult, move(uShifter),
604 t0, viewInfo, trackList, syncLocked);
608 double newT0 = t0 + hSlideAmount;
614 newT0 = pShifter->AdjustT0(newT0);
617 double diff = selectedRegion.duration();
618 selectedRegion.setTimes(newT0, newT0 + diff);
632 undoManager.StopConsolidating();
638 auto &selectedRegion = viewInfo.selectedRegion;
644 viewport.ScrollIntoView(selectedRegion.t0());
647 auto message = right?
XO(
"Moved clips to the right") :
648 XO(
"Moved clips to the left");
659 trackFocus.MessageForScreenReader(
XO(
"clip not moved"));
717 auto evt = context.
pEvt;
729 auto evt = context.
pEvt;
746 static auto menu = std::shared_ptr{
749 XXO(
"Pre&vious Clip Boundary to Cursor"),
753 XXO(
"Cursor to Ne&xt Clip Boundary"),
770 static auto items = std::shared_ptr{
772 Command(
wxT(
"CursPrevClipBoundary"),
XXO(
"Pre&vious Clip Boundary"),
776 Command(
wxT(
"CursNextClipBoundary"),
XXO(
"Ne&xt Clip Boundary"),
785 {
wxT(
"Transport/Basic/Cursor"),
786 { OrderingHint::Before,
wxT(
"CursProjectStart") } }
791 static auto items = std::shared_ptr{
802 {
wxT(
"Optional/Extra/Part1/Edit"), { OrderingHint::End, {} } }
AttachedItem sAttachment1
AttachedItem sAttachment3
AttachedItem sAttachment2
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
const ReservedCommandFlag & TrackPanelHasFocus()
XXO("&Cut/Copy/Paste Toolbar")
#define XP(sing, plur, n)
static Return Call(This &obj, Arguments ...arguments)
Invoke the method – but only after static initialization time.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
bool IsSyncLocked() const
static SyncLockState & Get(AudacityProject &project)
bool GetSelected() const
Selectedness is always the same for all channels of a group.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
static TrackList & Get(AudacityProject &project)
@ Track
Shift selected track and sister channels only, as a whole.
@ Miss
Don't shift anything.
Holds a msgid for the translation catalog; may also bind format arguments.
static UndoManager & Get(AudacityProject &project)
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
static Viewport & Get(AudacityProject &project)
A Track that contains audio waveform data.
IntervalHolders SortedIntervalArray()
Return all WaveClips sorted by clip play start time.
std::vector< IntervalConstHolder > IntervalConstHolders
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
WAVE_TRACK_API bool SharesBoundaryWithNextClip(const WaveTrack::Interval &prev, const WaveTrack::Interval &next)
used by commands which interact with clips using the keyboard
double DoSlideHorizontal(double desiredSlideAmount)
Do sliding of tracks and intervals, maybe adjusting the offset.
void Init(AudacityProject &project, Track &capturedTrack, TrackShifter::HitTestResult hitTestResult, std::unique_ptr< TrackShifter > pHit, double clickTime, const ViewInfo &viewInfo, TrackList &trackList, bool syncLocked)
Will associate a TrackShifter with each track in the list.