From e984211cceac794945f8882e2447baae2f0466ff Mon Sep 17 00:00:00 2001 From: James Crook Date: Sat, 19 Aug 2017 22:46:33 +0100 Subject: [PATCH] Bug 1290 - "Split New" clips cannot be dragged back into the track they came from. Fixed by giving some tolerance in how the dragged clip(s) are placed. The tolerance is 1px, so it depends on the zoom. Therefore if zoomed in your positioning is more precise. --- src/WaveTrack.cpp | 27 +++++++++++++++++++++++---- src/WaveTrack.h | 2 +- src/tracks/ui/TimeShiftHandle.cpp | 18 ++++++++++++++++-- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index e2a0547eb..e7568a411 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -2372,13 +2372,32 @@ bool WaveTrack::CanOffsetClip(WaveClip* clip, double amount, return true; } -bool WaveTrack::CanInsertClip(WaveClip* clip, double slideBy) +bool WaveTrack::CanInsertClip(WaveClip* clip, double &slideBy, double &tolerance) { for (const auto &c : mClips) { - if (c->GetStartTime() < (clip->GetEndTime()+slideBy) && - c->GetEndTime() > (clip->GetStartTime()+slideBy)) - return false; // clips overlap + double d1 = c->GetStartTime() - (clip->GetEndTime()+slideBy); + double d2 = (clip->GetStartTime()+slideBy) - c->GetEndTime(); + if ( (d1<0) && (d2<0) ) + { + // clips overlap. + // Try to rescue it. + // The rescue logic is not perfect, but + // a) will not move the clip by more than once + // b) is OK in simple scenarios. + if( -d1 < tolerance ){ + slideBy +=d1; + d2 += d1; + tolerance /=1000; + } + + if( -d2 < tolerance ){ + slideBy -= d2; + tolerance /=1000; + } + else + return false; // clips overlap No tolerance left. + } } return true; diff --git a/src/WaveTrack.h b/src/WaveTrack.h index b69b46933..73dd722bf 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -491,7 +491,7 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack { // Before moving a clip into a track (or inserting a clip), use this // function to see if the times are valid (i.e. don't overlap with // existing clips). - bool CanInsertClip(WaveClip* clip, double slideBy=0.0); + bool CanInsertClip(WaveClip* clip, double &slideBy, double &tolerance); // Remove the clip from the track and return a SMART pointer to it. // You assume responsibility for its memory! diff --git a/src/tracks/ui/TimeShiftHandle.cpp b/src/tracks/ui/TimeShiftHandle.cpp index a42a85f93..0f89cad5c 100644 --- a/src/tracks/ui/TimeShiftHandle.cpp +++ b/src/tracks/ui/TimeShiftHandle.cpp @@ -707,25 +707,39 @@ UIHandle::Result TimeShiftHandle::Drag // Now check that the move is possible bool ok = true; + // The test for tolerance will need review with FishEye! + // The tolerance is supposed to be the time for one pixel, i.e. one pixel tolerance + // at current zoom. + double slide = desiredSlideAmount; // remember amount requested. + double tolerance = viewInfo.PositionToTime(event.m_x+1) - viewInfo.PositionToTime(event.m_x+1); + + // The desiredSlideAmount may change and the tolerance may get used up. for ( unsigned ii = 0, nn = mClipMoveState.capturedClipArray.size(); ok && ii < nn; ++ii) { TrackClip &trackClip = mClipMoveState.capturedClipArray[ii]; WaveClip *const pSrcClip = trackClip.clip; if (pSrcClip) - ok = trackClip.dstTrack->CanInsertClip(pSrcClip, desiredSlideAmount); + ok = trackClip.dstTrack->CanInsertClip(pSrcClip, desiredSlideAmount, tolerance); } if (!ok) { + // Failure, even with using tolerance. // Failure -- put clips back where they were for ( unsigned ii = 0, nn = mClipMoveState.capturedClipArray.size(); ii < nn; ++ii) { TrackClip &trackClip = mClipMoveState.capturedClipArray[ii]; WaveClip *const pSrcClip = trackClip.clip; - if (pSrcClip) + if (pSrcClip){ + // Attempt to move to a new track did not work. + // Put the clip back appropriately shifted! + trackClip.holder->Offset(slide); // Assume track is wave because it has a clip static_cast(trackClip.track)-> AddClip(std::move(trackClip.holder)); + } } + // Make the offset permanent; start from a "clean slate" + mMouseClickX = event.m_x; return RefreshAll; } else {