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();
|
auto t0 = selectedRegion.t0();
|
||||||
|
|
||||||
|
std::unique_ptr<TrackShifter> uShifter;
|
||||||
|
|
||||||
// Find the first channel that has a clip at time t0
|
// Find the first channel that has a clip at time t0
|
||||||
for (auto channel : TrackList::Channels(wt) ) {
|
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;
|
wt = channel;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.capturedClip == nullptr)
|
if (!uShifter)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
auto pShifter = uShifter.get();
|
||||||
|
|
||||||
state.capturedClipIsSelection =
|
state.Init( *track, std::move( uShifter ),
|
||||||
track->GetSelected() && !selectedRegion.isPoint();
|
t0, viewInfo, trackList, syncLocked );
|
||||||
|
|
||||||
TimeShiftHandle::Init(
|
|
||||||
state, viewInfo, *track, trackList, syncLocked, t0 );
|
|
||||||
|
|
||||||
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );
|
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );
|
||||||
auto desiredSlideAmount = desiredT0 - t0;
|
auto desiredSlideAmount = desiredT0 - t0;
|
||||||
@ -668,21 +671,26 @@ double DoClipMove
|
|||||||
if (!right)
|
if (!right)
|
||||||
desiredSlideAmount *= -1;
|
desiredSlideAmount *= -1;
|
||||||
|
|
||||||
state.hSlideAmount = desiredSlideAmount;
|
auto hSlideAmount = state.DoSlideHorizontal(
|
||||||
TimeShiftHandle::DoSlideHorizontal( state, trackList, *track );
|
desiredSlideAmount, trackList, *track );
|
||||||
|
|
||||||
// update t0 and t1. There is the possibility that the updated
|
// update t0 and t1. There is the possibility that the updated
|
||||||
// t0 may no longer be within the clip due to rounding errors,
|
// t0 may no longer be within the clip due to rounding errors,
|
||||||
// so t0 is adjusted so that it is.
|
// so t0 is adjusted so that it is.
|
||||||
double newT0 = t0 + state.hSlideAmount;
|
double newT0 = t0 + hSlideAmount;
|
||||||
if (newT0 < state.capturedClip->GetStartTime())
|
// pShifter is still undestroyed in the ClipMoveState
|
||||||
newT0 = state.capturedClip->GetStartTime();
|
auto &intervals = pShifter->MovingIntervals();
|
||||||
if (newT0 > state.capturedClip->GetEndTime())
|
if ( !intervals.empty() ) {
|
||||||
newT0 = state.capturedClip->GetEndTime();
|
auto &interval = intervals[0];
|
||||||
double diff = selectedRegion.duration();
|
if (newT0 < interval.Start())
|
||||||
selectedRegion.setTimes(newT0, newT0 + diff);
|
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;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
@ -304,19 +304,57 @@ template<> auto MakeTrackShifter::Implementation() -> Function {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeShiftHandle::Init
|
void ClipMoveState::Init(
|
||||||
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
|
Track &capturedTrack,
|
||||||
TrackList &trackList, bool syncLocked, double clickTime,
|
std::unique_ptr<TrackShifter> pHit,
|
||||||
bool capturedAClip )
|
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
|
// The captured clip is the focus, but we need to create a list
|
||||||
// of all clips that have to move, also...
|
// of all clips that have to move, also...
|
||||||
|
|
||||||
state.capturedClipArray.clear();
|
|
||||||
|
|
||||||
// First, if click was in selection, capture selected clips; otherwise
|
// First, if click was in selection, capture selected clips; otherwise
|
||||||
// just the clicked-on clip
|
// just the clicked-on clip
|
||||||
if ( state.capturedClipIsSelection )
|
if ( state.movingSelection )
|
||||||
// All selected tracks may move some intervals
|
// All selected tracks may move some intervals
|
||||||
for (auto t : trackList.Selected())
|
for (auto t : trackList.Selected())
|
||||||
AddClipsToCaptured( state, viewInfo, t );
|
AddClipsToCaptured( state, viewInfo, t );
|
||||||
@ -372,7 +410,7 @@ void TimeShiftHandle::Init
|
|||||||
|
|
||||||
// Analogy of the steps above, but with TrackShifters, follows below
|
// Analogy of the steps above, but with TrackShifters, follows below
|
||||||
|
|
||||||
if ( state.capturedClipIsSelection ) {
|
if ( state.movingSelection ) {
|
||||||
// All selected tracks may move some intervals
|
// All selected tracks may move some intervals
|
||||||
const TrackInterval interval{
|
const TrackInterval interval{
|
||||||
viewInfo.selectedRegion.t0(),
|
viewInfo.selectedRegion.t0(),
|
||||||
@ -435,9 +473,12 @@ void TimeShiftHandle::Init
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeShiftHandle::DoSlideHorizontal
|
double ClipMoveState::DoSlideHorizontal(
|
||||||
( ClipMoveState &state, TrackList &trackList, Track &capturedTrack )
|
double desiredSlideAmount, TrackList &trackList, Track &capturedTrack )
|
||||||
{
|
{
|
||||||
|
auto &state = *this;
|
||||||
|
state.hSlideAmount = desiredSlideAmount;
|
||||||
|
|
||||||
// Given a signed slide distance, move clips, but subject to constraint of
|
// Given a signed slide distance, move clips, but subject to constraint of
|
||||||
// non-overlapping with other clips, so the distance may be adjusted toward
|
// non-overlapping with other clips, so the distance may be adjusted toward
|
||||||
// zero.
|
// zero.
|
||||||
@ -486,6 +527,8 @@ void TimeShiftHandle::DoSlideHorizontal
|
|||||||
// For Shift key down, or
|
// For Shift key down, or
|
||||||
// For non wavetracks, specifically label tracks ...
|
// For non wavetracks, specifically label tracks ...
|
||||||
DoOffset( state, &capturedTrack, state.hSlideAmount );
|
DoOffset( state, &capturedTrack, state.hSlideAmount );
|
||||||
|
|
||||||
|
return state.hSlideAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -536,16 +579,11 @@ UIHandle::Result TimeShiftHandle::Click
|
|||||||
|
|
||||||
const double clickTime =
|
const double clickTime =
|
||||||
viewInfo.PositionToTime(event.m_x, rect.x);
|
viewInfo.PositionToTime(event.m_x, rect.x);
|
||||||
mClipMoveState.capturedClipIsSelection =
|
|
||||||
(pTrack->GetSelected() &&
|
|
||||||
clickTime >= viewInfo.selectedRegion.t0() &&
|
|
||||||
clickTime < viewInfo.selectedRegion.t1());
|
|
||||||
|
|
||||||
mClipMoveState.capturedClip = NULL;
|
mClipMoveState.capturedClip = NULL;
|
||||||
mClipMoveState.capturedClipArray.clear();
|
mClipMoveState.capturedClipArray.clear();
|
||||||
|
|
||||||
bool captureClips = false;
|
bool captureClips = false;
|
||||||
bool capturedAClip = false;
|
|
||||||
|
|
||||||
auto pShifter = MakeTrackShifter::Call( *pTrack );
|
auto pShifter = MakeTrackShifter::Call( *pTrack );
|
||||||
|
|
||||||
@ -555,17 +593,6 @@ UIHandle::Result TimeShiftHandle::Click
|
|||||||
return Cancelled;
|
return Cancelled;
|
||||||
case TrackShifter::HitTestResult::Intervals: {
|
case TrackShifter::HitTestResult::Intervals: {
|
||||||
captureClips = true;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case TrackShifter::HitTestResult::Track:
|
case TrackShifter::HitTestResult::Track:
|
||||||
@ -577,20 +604,12 @@ UIHandle::Result TimeShiftHandle::Click
|
|||||||
// As in the default above: just do shifting of one whole track
|
// As in the default above: just do shifting of one whole track
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( captureClips ) {
|
mClipMoveState.Init( *pTrack,
|
||||||
mClipMoveState.shifters[pTrack] = std::move( pShifter );
|
captureClips ? std::move( pShifter ) : nullptr,
|
||||||
|
clickTime,
|
||||||
|
|
||||||
// Collect TrackShifters for the rest of the tracks
|
viewInfo, trackList,
|
||||||
for ( auto track : trackList.Any() ) {
|
ProjectSettings::Get( *pProject ).IsSyncLocked() );
|
||||||
auto &pShifter = mClipMoveState.shifters[track];
|
|
||||||
if (!pShifter)
|
|
||||||
pShifter = MakeTrackShifter::Call( *track );
|
|
||||||
}
|
|
||||||
|
|
||||||
Init(
|
|
||||||
mClipMoveState, viewInfo, *pTrack, trackList,
|
|
||||||
ProjectSettings::Get( *pProject ).IsSyncLocked(), clickTime, capturedAClip );
|
|
||||||
}
|
|
||||||
|
|
||||||
mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive;
|
mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive;
|
||||||
mRect = rect;
|
mRect = rect;
|
||||||
@ -836,7 +855,7 @@ bool TimeShiftHandle::DoSlideVertical
|
|||||||
// Make the offset permanent; start from a "clean slate"
|
// Make the offset permanent; start from a "clean slate"
|
||||||
if( ok ) {
|
if( ok ) {
|
||||||
state.mMouseClickX = xx;
|
state.mMouseClickX = xx;
|
||||||
if (state.capturedClipIsSelection) {
|
if (state.movingSelection) {
|
||||||
// Slide the selection, too
|
// Slide the selection, too
|
||||||
viewInfo.selectedRegion.move( slide );
|
viewInfo.selectedRegion.move( slide );
|
||||||
}
|
}
|
||||||
@ -897,7 +916,7 @@ UIHandle::Result TimeShiftHandle::Drag
|
|||||||
DoOffset(
|
DoOffset(
|
||||||
mClipMoveState, mCapturedTrack.get(), -mClipMoveState.hSlideAmount );
|
mClipMoveState, mCapturedTrack.get(), -mClipMoveState.hSlideAmount );
|
||||||
|
|
||||||
if ( mClipMoveState.capturedClipIsSelection ) {
|
if ( mClipMoveState.movingSelection ) {
|
||||||
// Slide the selection, too
|
// Slide the selection, too
|
||||||
viewInfo.selectedRegion.move( -mClipMoveState.hSlideAmount );
|
viewInfo.selectedRegion.move( -mClipMoveState.hSlideAmount );
|
||||||
}
|
}
|
||||||
@ -939,11 +958,10 @@ UIHandle::Result TimeShiftHandle::Drag
|
|||||||
if (desiredSlideAmount == 0.0)
|
if (desiredSlideAmount == 0.0)
|
||||||
return RefreshAll;
|
return RefreshAll;
|
||||||
|
|
||||||
mClipMoveState.hSlideAmount = desiredSlideAmount;
|
mClipMoveState.DoSlideHorizontal(
|
||||||
|
desiredSlideAmount, trackList, *mCapturedTrack );
|
||||||
|
|
||||||
DoSlideHorizontal( mClipMoveState, trackList, *mCapturedTrack );
|
if (mClipMoveState.movingSelection) {
|
||||||
|
|
||||||
if (mClipMoveState.capturedClipIsSelection) {
|
|
||||||
// Slide the selection, too
|
// Slide the selection, too
|
||||||
viewInfo.selectedRegion.move( mClipMoveState.hSlideAmount );
|
viewInfo.selectedRegion.move( mClipMoveState.hSlideAmount );
|
||||||
}
|
}
|
||||||
|
@ -122,10 +122,23 @@ using TrackClipArray = std::vector <TrackClip>;
|
|||||||
struct ClipMoveState {
|
struct ClipMoveState {
|
||||||
using ShifterMap = std::unordered_map<Track*, std::unique_ptr<TrackShifter>>;
|
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:
|
// non-NULL only if click was in a WaveTrack and without Shift key:
|
||||||
WaveClip *capturedClip {};
|
WaveClip *capturedClip {};
|
||||||
|
|
||||||
bool capturedClipIsSelection {};
|
bool movingSelection {};
|
||||||
double hSlideAmount {};
|
double hSlideAmount {};
|
||||||
ShifterMap shifters;
|
ShifterMap shifters;
|
||||||
TrackClipArray capturedClipArray {};
|
TrackClipArray capturedClipArray {};
|
||||||
@ -136,7 +149,7 @@ struct ClipMoveState {
|
|||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
capturedClip = nullptr;
|
capturedClip = nullptr;
|
||||||
capturedClipIsSelection = false;
|
movingSelection = false;
|
||||||
hSlideAmount = 0;
|
hSlideAmount = 0;
|
||||||
shifters.clear();
|
shifters.clear();
|
||||||
capturedClipArray.clear();
|
capturedClipArray.clear();
|
||||||
@ -160,16 +173,6 @@ public:
|
|||||||
bool IsGripHit() const { return mGripHit; }
|
bool IsGripHit() const { return mGripHit; }
|
||||||
std::shared_ptr<Track> GetTrack() const { return mCapturedTrack; }
|
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
|
// Try to move clips from one WaveTrack to another, before also moving
|
||||||
// by some horizontal amount, which may be slightly adjusted to fit the
|
// by some horizontal amount, which may be slightly adjusted to fit the
|
||||||
// destination tracks.
|
// destination tracks.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user