More control over HitTest behavior moved into the Track Shifter classes
This commit is contained in:
parent
f204ee3192
commit
6e0b5b690a
|
@ -641,9 +641,10 @@ double DoClipMove( AudacityProject &project, Track *track,
|
|||
std::unique_ptr<TrackShifter> uShifter;
|
||||
|
||||
// Find the first channel that has a clip at time t0
|
||||
auto hitTestResult = TrackShifter::HitTestResult::Track;
|
||||
for (auto channel : TrackList::Channels(track) ) {
|
||||
uShifter = MakeTrackShifter::Call( *track, project );
|
||||
if ( uShifter->HitTest( t0, viewInfo ) ==
|
||||
if ( (hitTestResult = uShifter->HitTest( t0, viewInfo )) ==
|
||||
TrackShifter::HitTestResult::Miss )
|
||||
uShifter.reset();
|
||||
else
|
||||
|
@ -654,7 +655,7 @@ double DoClipMove( AudacityProject &project, Track *track,
|
|||
return 0.0;
|
||||
auto pShifter = uShifter.get();
|
||||
|
||||
state.Init( project, *track, std::move( uShifter ),
|
||||
state.Init( project, *track, hitTestResult, std::move( uShifter ),
|
||||
t0, viewInfo, trackList, syncLocked );
|
||||
|
||||
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );
|
||||
|
|
|
@ -742,9 +742,16 @@ public:
|
|||
~NoteTrackShifter() override {}
|
||||
Track &GetTrack() const override { return *mpTrack; }
|
||||
|
||||
HitTestResult HitTest( double, const ViewInfo&, HitTestParams* ) override
|
||||
HitTestResult HitTest(
|
||||
double time, const ViewInfo &viewInfo, HitTestParams* ) override
|
||||
{
|
||||
return HitTestResult::Intervals;
|
||||
UnfixAll();
|
||||
auto t0 = viewInfo.selectedRegion.t0();
|
||||
auto t1 = viewInfo.selectedRegion.t1();
|
||||
if ( mpTrack->IsSelected() && time >= t0 && time < t1 )
|
||||
return HitTestResult::Selection;
|
||||
else
|
||||
return HitTestResult::Intervals;
|
||||
}
|
||||
|
||||
void SelectInterval( const TrackInterval &interval ) override
|
||||
|
|
|
@ -1315,14 +1315,22 @@ public:
|
|||
Track &GetTrack() const override { return *mpTrack; }
|
||||
|
||||
HitTestResult HitTest(
|
||||
double time, const ViewInfo&, HitTestParams* ) override
|
||||
double time, const ViewInfo &viewInfo, HitTestParams* ) override
|
||||
{
|
||||
auto pClip = mpTrack->GetClipAtTime( time );
|
||||
|
||||
if (!pClip)
|
||||
return HitTestResult::Miss;
|
||||
|
||||
// Make a side-effect on our intervals
|
||||
auto t0 = viewInfo.selectedRegion.t0();
|
||||
auto t1 = viewInfo.selectedRegion.t1();
|
||||
if ( mpTrack->IsSelected() && time >= t0 && time < t1 ) {
|
||||
// Unfix maybe many intervals (at least one because of test above)
|
||||
SelectInterval({t0, t1});
|
||||
return HitTestResult::Selection;
|
||||
}
|
||||
|
||||
// Select just one interval
|
||||
UnfixIntervals( [&](const auto &interval){
|
||||
return
|
||||
static_cast<WaveTrack::IntervalData*>(interval.Extra())
|
||||
|
|
|
@ -261,6 +261,7 @@ template<> auto MakeTrackShifter::Implementation() -> Function {
|
|||
void ClipMoveState::Init(
|
||||
AudacityProject &project,
|
||||
Track &capturedTrack,
|
||||
TrackShifter::HitTestResult hitTestResult,
|
||||
std::unique_ptr<TrackShifter> pHit,
|
||||
double clickTime,
|
||||
const ViewInfo &viewInfo,
|
||||
|
@ -271,16 +272,26 @@ void ClipMoveState::Init(
|
|||
auto &state = *this;
|
||||
state.mCapturedTrack = capturedTrack.SharedPointer();
|
||||
|
||||
state.movingSelection = capturedTrack.IsSelected() &&
|
||||
clickTime >= viewInfo.selectedRegion.t0() &&
|
||||
clickTime < viewInfo.selectedRegion.t1();
|
||||
switch (hitTestResult) {
|
||||
case TrackShifter::HitTestResult::Miss:
|
||||
wxASSERT(false);
|
||||
pHit.reset();
|
||||
break;
|
||||
case TrackShifter::HitTestResult::Track:
|
||||
pHit.reset();
|
||||
break;
|
||||
case TrackShifter::HitTestResult::Intervals:
|
||||
break;
|
||||
case TrackShifter::HitTestResult::Selection:
|
||||
state.movingSelection = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pHit)
|
||||
return;
|
||||
|
||||
const bool capturedAClip =
|
||||
pHit && !pHit->MovingIntervals().empty();
|
||||
|
||||
state.shifters[&capturedTrack] = std::move( pHit );
|
||||
|
||||
// Collect TrackShifters for the rest of the tracks
|
||||
|
@ -290,8 +301,6 @@ void ClipMoveState::Init(
|
|||
pShifter = MakeTrackShifter::Call( *track, project );
|
||||
}
|
||||
|
||||
// Analogy of the steps above, but with TrackShifters, follows below
|
||||
|
||||
if ( state.movingSelection ) {
|
||||
// All selected tracks may move some intervals
|
||||
const TrackInterval interval{
|
||||
|
@ -301,6 +310,9 @@ void ClipMoveState::Init(
|
|||
for ( const auto &pair : state.shifters ) {
|
||||
auto &shifter = *pair.second;
|
||||
auto &track = shifter.GetTrack();
|
||||
if (&track == &capturedTrack)
|
||||
// Don't change the choice of intervals made by HitTest
|
||||
continue;
|
||||
if ( track.IsSelected() )
|
||||
shifter.SelectInterval( interval );
|
||||
}
|
||||
|
@ -309,12 +321,8 @@ void ClipMoveState::Init(
|
|||
// Move intervals only of the chosen channel group
|
||||
for ( auto channel : TrackList::Channels( &capturedTrack ) ) {
|
||||
auto &shifter = *state.shifters[channel];
|
||||
if ( capturedAClip ) {
|
||||
if ( channel != &capturedTrack )
|
||||
shifter.SelectInterval(TrackInterval{clickTime, clickTime});
|
||||
}
|
||||
else
|
||||
shifter.UnfixAll();
|
||||
if ( channel != &capturedTrack )
|
||||
shifter.SelectInterval(TrackInterval{clickTime, clickTime});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,32 +467,28 @@ UIHandle::Result TimeShiftHandle::Click
|
|||
const double clickTime =
|
||||
viewInfo.PositionToTime(event.m_x, rect.x);
|
||||
|
||||
bool captureClips = false;
|
||||
|
||||
auto pShifter = MakeTrackShifter::Call( *pTrack, *pProject );
|
||||
|
||||
auto hitTestResult = TrackShifter::HitTestResult::Track;
|
||||
if (!event.ShiftDown()) {
|
||||
TrackShifter::HitTestParams params{
|
||||
rect, event.m_x, event.m_y
|
||||
};
|
||||
switch( pShifter->HitTest( clickTime, viewInfo, ¶ms ) ) {
|
||||
hitTestResult = pShifter->HitTest( clickTime, viewInfo, ¶ms );
|
||||
switch( hitTestResult ) {
|
||||
case TrackShifter::HitTestResult::Miss:
|
||||
return Cancelled;
|
||||
case TrackShifter::HitTestResult::Intervals: {
|
||||
captureClips = true;
|
||||
break;
|
||||
}
|
||||
case TrackShifter::HitTestResult::Track:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// As in the default above: just do shifting of one whole track
|
||||
// just do shifting of one whole track
|
||||
}
|
||||
|
||||
mClipMoveState.Init( *pProject, *pTrack,
|
||||
captureClips ? std::move( pShifter ) : nullptr,
|
||||
hitTestResult,
|
||||
std::move( pShifter ),
|
||||
clickTime,
|
||||
|
||||
viewInfo, trackList,
|
||||
|
|
|
@ -37,8 +37,9 @@ public:
|
|||
//! Possibilities for HitTest on the clicked track
|
||||
enum class HitTestResult {
|
||||
Miss, //!< Don't shift anything
|
||||
Intervals, //<! May shift other tracks' intervals, if clicked in selection
|
||||
Track //<! Shift selected track only as a whole
|
||||
Selection, //!< Shfit chosen intervals of this track; may shift other tracks' intervals
|
||||
Intervals, //!< Shift intervals only of selected track and sister channels
|
||||
Track //!< Shift selected track and sister channels only, as a whole
|
||||
};
|
||||
|
||||
//! Optional, more complete information for hit testing
|
||||
|
@ -48,7 +49,8 @@ public:
|
|||
};
|
||||
|
||||
//! Decide how shift behaves, based on the track that is clicked in
|
||||
/*! If the return value is Intervals, then some intervals may be marked moving as a side effect */
|
||||
/*! If the return value is Intervals or Selection,
|
||||
then some intervals may be marked moving as a side effect */
|
||||
/*!
|
||||
@pre `!pParams || (time == pParams->viewInfo.PositionToTime(pParams->xx, pParams->rect.x))`
|
||||
*/
|
||||
|
@ -195,8 +197,9 @@ struct ClipMoveState {
|
|||
void Init(
|
||||
AudacityProject &project,
|
||||
Track &capturedTrack, //<! pHit if not null associates with this track
|
||||
TrackShifter::HitTestResult hitTestResult, //!< must not be `Miss`
|
||||
std::unique_ptr<TrackShifter> pHit, /*!<
|
||||
If null, only capturedTrack (with any sister channels) shifts, as a whole */
|
||||
If null, implies `Track`, overriding previous argument */
|
||||
double clickTime,
|
||||
const ViewInfo &viewInfo,
|
||||
TrackList &trackList, bool syncLocked );
|
||||
|
|
Loading…
Reference in New Issue