mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-15 15:49:36 +02:00
Lower more into Init(); ClipMenus uses ClipMoveState opaquely
This commit is contained in:
parent
00f761eb5e
commit
329221b392
@ -639,22 +639,25 @@ double DoClipMove
|
||||
|
||||
auto t0 = selectedRegion.t0();
|
||||
|
||||
std::unique_ptr<TrackShifter> uShifter;
|
||||
|
||||
// Find the first channel that has a clip at time t0
|
||||
for (auto channel : TrackList::Channels(wt) ) {
|
||||
if( nullptr != (state.capturedClip = channel->GetClipAtTime( t0 )) ) {
|
||||
uShifter = MakeTrackShifter::Call( *wt );
|
||||
if( uShifter->HitTest( t0 ) == TrackShifter::HitTestResult::Miss )
|
||||
uShifter.reset();
|
||||
else {
|
||||
wt = channel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.capturedClip == nullptr)
|
||||
if (!uShifter)
|
||||
return 0.0;
|
||||
auto pShifter = uShifter.get();
|
||||
|
||||
state.capturedClipIsSelection =
|
||||
track->GetSelected() && !selectedRegion.isPoint();
|
||||
|
||||
TimeShiftHandle::Init(
|
||||
state, viewInfo, *track, trackList, syncLocked, t0 );
|
||||
state.Init( *track, std::move( uShifter ),
|
||||
t0, viewInfo, trackList, syncLocked );
|
||||
|
||||
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );
|
||||
auto desiredSlideAmount = desiredT0 - t0;
|
||||
@ -668,21 +671,26 @@ double DoClipMove
|
||||
if (!right)
|
||||
desiredSlideAmount *= -1;
|
||||
|
||||
state.hSlideAmount = desiredSlideAmount;
|
||||
TimeShiftHandle::DoSlideHorizontal( state, trackList, *track );
|
||||
auto hSlideAmount = state.DoSlideHorizontal(
|
||||
desiredSlideAmount, trackList, *track );
|
||||
|
||||
// update t0 and t1. There is the possibility that the updated
|
||||
// t0 may no longer be within the clip due to rounding errors,
|
||||
// so t0 is adjusted so that it is.
|
||||
double newT0 = t0 + state.hSlideAmount;
|
||||
if (newT0 < state.capturedClip->GetStartTime())
|
||||
newT0 = state.capturedClip->GetStartTime();
|
||||
if (newT0 > state.capturedClip->GetEndTime())
|
||||
newT0 = state.capturedClip->GetEndTime();
|
||||
double newT0 = t0 + hSlideAmount;
|
||||
// pShifter is still undestroyed in the ClipMoveState
|
||||
auto &intervals = pShifter->MovingIntervals();
|
||||
if ( !intervals.empty() ) {
|
||||
auto &interval = intervals[0];
|
||||
if (newT0 < interval.Start())
|
||||
newT0 = interval.Start();
|
||||
if (newT0 > interval.End())
|
||||
newT0 = interval.End();
|
||||
double diff = selectedRegion.duration();
|
||||
selectedRegion.setTimes(newT0, newT0 + diff);
|
||||
}
|
||||
|
||||
return state.hSlideAmount;
|
||||
return hSlideAmount;
|
||||
} );
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -304,19 +304,57 @@ template<> auto MakeTrackShifter::Implementation() -> Function {
|
||||
};
|
||||
}
|
||||
|
||||
void TimeShiftHandle::Init
|
||||
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
|
||||
TrackList &trackList, bool syncLocked, double clickTime,
|
||||
bool capturedAClip )
|
||||
void ClipMoveState::Init(
|
||||
Track &capturedTrack,
|
||||
std::unique_ptr<TrackShifter> pHit,
|
||||
double clickTime,
|
||||
const ViewInfo &viewInfo,
|
||||
TrackList &trackList, bool syncLocked )
|
||||
{
|
||||
capturedClipArray.clear();
|
||||
shifters.clear();
|
||||
auto cleanup = finally([&]{
|
||||
// In transition, this class holds two representations of what to shift.
|
||||
// Be sure each is filled only if the other is.
|
||||
wxASSERT( capturedClipArray.empty() == shifters.empty() );
|
||||
});
|
||||
|
||||
auto &state = *this;
|
||||
|
||||
state.movingSelection = capturedTrack.IsSelected() &&
|
||||
clickTime >= viewInfo.selectedRegion.t0() &&
|
||||
clickTime < viewInfo.selectedRegion.t1();
|
||||
|
||||
if (!pHit)
|
||||
return;
|
||||
|
||||
const bool capturedAClip =
|
||||
pHit && !pHit->MovingIntervals().empty();
|
||||
if ( capturedAClip ) {
|
||||
// There is still some code special to WaveTracks here that
|
||||
// needs to go elsewhere
|
||||
auto &interval = pHit->MovingIntervals()[0];
|
||||
auto pInfo =
|
||||
dynamic_cast<WaveTrack::IntervalData*>(interval.Extra());
|
||||
if ( pInfo )
|
||||
state.capturedClip = pInfo->GetClip().get();
|
||||
}
|
||||
|
||||
state.shifters[&capturedTrack] = std::move( pHit );
|
||||
|
||||
// Collect TrackShifters for the rest of the tracks
|
||||
for ( auto track : trackList.Any() ) {
|
||||
auto &pShifter = state.shifters[track];
|
||||
if (!pShifter)
|
||||
pShifter = MakeTrackShifter::Call( *track );
|
||||
}
|
||||
|
||||
// The captured clip is the focus, but we need to create a list
|
||||
// of all clips that have to move, also...
|
||||
|
||||
state.capturedClipArray.clear();
|
||||
|
||||
// First, if click was in selection, capture selected clips; otherwise
|
||||
// just the clicked-on clip
|
||||
if ( state.capturedClipIsSelection )
|
||||
if ( state.movingSelection )
|
||||
// All selected tracks may move some intervals
|
||||
for (auto t : trackList.Selected())
|
||||
AddClipsToCaptured( state, viewInfo, t );
|
||||
@ -372,7 +410,7 @@ void TimeShiftHandle::Init
|
||||
|
||||
// Analogy of the steps above, but with TrackShifters, follows below
|
||||
|
||||
if ( state.capturedClipIsSelection ) {
|
||||
if ( state.movingSelection ) {
|
||||
// All selected tracks may move some intervals
|
||||
const TrackInterval interval{
|
||||
viewInfo.selectedRegion.t0(),
|
||||
@ -435,9 +473,12 @@ void TimeShiftHandle::Init
|
||||
}
|
||||
}
|
||||
|
||||
void TimeShiftHandle::DoSlideHorizontal
|
||||
( ClipMoveState &state, TrackList &trackList, Track &capturedTrack )
|
||||
double ClipMoveState::DoSlideHorizontal(
|
||||
double desiredSlideAmount, TrackList &trackList, Track &capturedTrack )
|
||||
{
|
||||
auto &state = *this;
|
||||
state.hSlideAmount = desiredSlideAmount;
|
||||
|
||||
// Given a signed slide distance, move clips, but subject to constraint of
|
||||
// non-overlapping with other clips, so the distance may be adjusted toward
|
||||
// zero.
|
||||
@ -486,6 +527,8 @@ void TimeShiftHandle::DoSlideHorizontal
|
||||
// For Shift key down, or
|
||||
// For non wavetracks, specifically label tracks ...
|
||||
DoOffset( state, &capturedTrack, state.hSlideAmount );
|
||||
|
||||
return state.hSlideAmount;
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -536,16 +579,11 @@ UIHandle::Result TimeShiftHandle::Click
|
||||
|
||||
const double clickTime =
|
||||
viewInfo.PositionToTime(event.m_x, rect.x);
|
||||
mClipMoveState.capturedClipIsSelection =
|
||||
(pTrack->GetSelected() &&
|
||||
clickTime >= viewInfo.selectedRegion.t0() &&
|
||||
clickTime < viewInfo.selectedRegion.t1());
|
||||
|
||||
mClipMoveState.capturedClip = NULL;
|
||||
mClipMoveState.capturedClipArray.clear();
|
||||
|
||||
bool captureClips = false;
|
||||
bool capturedAClip = false;
|
||||
|
||||
auto pShifter = MakeTrackShifter::Call( *pTrack );
|
||||
|
||||
@ -555,17 +593,6 @@ UIHandle::Result TimeShiftHandle::Click
|
||||
return Cancelled;
|
||||
case TrackShifter::HitTestResult::Intervals: {
|
||||
captureClips = true;
|
||||
if ( !pShifter->MovingIntervals().empty() ) {
|
||||
capturedAClip = true;
|
||||
|
||||
// There is still some code special to WaveTracks here that
|
||||
// needs to go elsewhere
|
||||
auto &interval = pShifter->MovingIntervals()[0];
|
||||
auto pInfo =
|
||||
dynamic_cast<WaveTrack::IntervalData*>(interval.Extra());
|
||||
if ( pInfo )
|
||||
mClipMoveState.capturedClip = pInfo->GetClip().get();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TrackShifter::HitTestResult::Track:
|
||||
@ -577,20 +604,12 @@ UIHandle::Result TimeShiftHandle::Click
|
||||
// As in the default above: just do shifting of one whole track
|
||||
}
|
||||
|
||||
if ( captureClips ) {
|
||||
mClipMoveState.shifters[pTrack] = std::move( pShifter );
|
||||
mClipMoveState.Init( *pTrack,
|
||||
captureClips ? std::move( pShifter ) : nullptr,
|
||||
clickTime,
|
||||
|
||||
// Collect TrackShifters for the rest of the tracks
|
||||
for ( auto track : trackList.Any() ) {
|
||||
auto &pShifter = mClipMoveState.shifters[track];
|
||||
if (!pShifter)
|
||||
pShifter = MakeTrackShifter::Call( *track );
|
||||
}
|
||||
|
||||
Init(
|
||||
mClipMoveState, viewInfo, *pTrack, trackList,
|
||||
ProjectSettings::Get( *pProject ).IsSyncLocked(), clickTime, capturedAClip );
|
||||
}
|
||||
viewInfo, trackList,
|
||||
ProjectSettings::Get( *pProject ).IsSyncLocked() );
|
||||
|
||||
mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive;
|
||||
mRect = rect;
|
||||
@ -836,7 +855,7 @@ bool TimeShiftHandle::DoSlideVertical
|
||||
// Make the offset permanent; start from a "clean slate"
|
||||
if( ok ) {
|
||||
state.mMouseClickX = xx;
|
||||
if (state.capturedClipIsSelection) {
|
||||
if (state.movingSelection) {
|
||||
// Slide the selection, too
|
||||
viewInfo.selectedRegion.move( slide );
|
||||
}
|
||||
@ -897,7 +916,7 @@ UIHandle::Result TimeShiftHandle::Drag
|
||||
DoOffset(
|
||||
mClipMoveState, mCapturedTrack.get(), -mClipMoveState.hSlideAmount );
|
||||
|
||||
if ( mClipMoveState.capturedClipIsSelection ) {
|
||||
if ( mClipMoveState.movingSelection ) {
|
||||
// Slide the selection, too
|
||||
viewInfo.selectedRegion.move( -mClipMoveState.hSlideAmount );
|
||||
}
|
||||
@ -939,11 +958,10 @@ UIHandle::Result TimeShiftHandle::Drag
|
||||
if (desiredSlideAmount == 0.0)
|
||||
return RefreshAll;
|
||||
|
||||
mClipMoveState.hSlideAmount = desiredSlideAmount;
|
||||
mClipMoveState.DoSlideHorizontal(
|
||||
desiredSlideAmount, trackList, *mCapturedTrack );
|
||||
|
||||
DoSlideHorizontal( mClipMoveState, trackList, *mCapturedTrack );
|
||||
|
||||
if (mClipMoveState.capturedClipIsSelection) {
|
||||
if (mClipMoveState.movingSelection) {
|
||||
// Slide the selection, too
|
||||
viewInfo.selectedRegion.move( mClipMoveState.hSlideAmount );
|
||||
}
|
||||
|
@ -122,10 +122,23 @@ using TrackClipArray = std::vector <TrackClip>;
|
||||
struct ClipMoveState {
|
||||
using ShifterMap = std::unordered_map<Track*, std::unique_ptr<TrackShifter>>;
|
||||
|
||||
//! Will associate a TrackShifter with each track in the list
|
||||
void Init(
|
||||
Track &capturedTrack, //<! pHit if not null associates with this track
|
||||
std::unique_ptr<TrackShifter> pHit, /*!<
|
||||
If null, only capturedTrack (with any sister channels) shifts, as a whole */
|
||||
double clickTime,
|
||||
const ViewInfo &viewInfo,
|
||||
TrackList &trackList, bool syncLocked );
|
||||
|
||||
/*! @return actual slide amount, maybe adjusted toward zero from desired */
|
||||
double DoSlideHorizontal(
|
||||
double desiredSlideAmount, TrackList &trackList, Track &capturedTrack );
|
||||
|
||||
// non-NULL only if click was in a WaveTrack and without Shift key:
|
||||
WaveClip *capturedClip {};
|
||||
|
||||
bool capturedClipIsSelection {};
|
||||
bool movingSelection {};
|
||||
double hSlideAmount {};
|
||||
ShifterMap shifters;
|
||||
TrackClipArray capturedClipArray {};
|
||||
@ -136,7 +149,7 @@ struct ClipMoveState {
|
||||
void clear()
|
||||
{
|
||||
capturedClip = nullptr;
|
||||
capturedClipIsSelection = false;
|
||||
movingSelection = false;
|
||||
hSlideAmount = 0;
|
||||
shifters.clear();
|
||||
capturedClipArray.clear();
|
||||
@ -160,16 +173,6 @@ public:
|
||||
bool IsGripHit() const { return mGripHit; }
|
||||
std::shared_ptr<Track> GetTrack() const { return mCapturedTrack; }
|
||||
|
||||
// A utility function also used by menu commands
|
||||
static void Init
|
||||
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
|
||||
TrackList &trackList, bool syncLocked, double clickTime,
|
||||
bool capturedAClip = true );
|
||||
|
||||
// A utility function also used by menu commands
|
||||
static void DoSlideHorizontal
|
||||
( ClipMoveState &state, TrackList &trackList, Track &capturedTrack );
|
||||
|
||||
// Try to move clips from one WaveTrack to another, before also moving
|
||||
// by some horizontal amount, which may be slightly adjusted to fit the
|
||||
// destination tracks.
|
||||
|
Loading…
x
Reference in New Issue
Block a user