mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-15 15:49:36 +02:00
Some last changes to TimeShiftHandle anticipating LabelTrack needs
This commit is contained in:
commit
583d347ae0
@ -627,10 +627,10 @@ void DoCursorClipBoundary
|
||||
}
|
||||
|
||||
// This function returns the amount moved. Possibly 0.0.
|
||||
double DoClipMove
|
||||
( ViewInfo &viewInfo, Track *track,
|
||||
double DoClipMove( AudacityProject &project, Track *track,
|
||||
TrackList &trackList, bool syncLocked, bool right )
|
||||
{
|
||||
auto &viewInfo = ViewInfo::Get(project);
|
||||
auto &selectedRegion = viewInfo.selectedRegion;
|
||||
|
||||
if (track) {
|
||||
@ -641,9 +641,11 @@ double DoClipMove
|
||||
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 );
|
||||
if( uShifter->HitTest( t0 ) == TrackShifter::HitTestResult::Miss )
|
||||
uShifter = MakeTrackShifter::Call( *track, project );
|
||||
if ( (hitTestResult = uShifter->HitTest( t0, viewInfo )) ==
|
||||
TrackShifter::HitTestResult::Miss )
|
||||
uShifter.reset();
|
||||
else
|
||||
break;
|
||||
@ -653,7 +655,7 @@ double DoClipMove
|
||||
return 0.0;
|
||||
auto pShifter = uShifter.get();
|
||||
|
||||
state.Init( *track, std::move( uShifter ),
|
||||
state.Init( project, *track, hitTestResult, std::move( uShifter ),
|
||||
t0, viewInfo, trackList, syncLocked );
|
||||
|
||||
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );
|
||||
@ -700,7 +702,7 @@ void DoClipLeftOrRight
|
||||
auto &tracks = TrackList::Get( project );
|
||||
auto isSyncLocked = settings.IsSyncLocked();
|
||||
|
||||
auto amount = DoClipMove( viewInfo, trackFocus.Get(),
|
||||
auto amount = DoClipMove( project, trackFocus.Get(),
|
||||
tracks, isSyncLocked, right );
|
||||
|
||||
window.ScrollIntoView(selectedRegion.t0());
|
||||
|
@ -742,9 +742,16 @@ public:
|
||||
~NoteTrackShifter() override {}
|
||||
Track &GetTrack() const override { return *mpTrack; }
|
||||
|
||||
HitTestResult HitTest( double ) 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
|
||||
@ -760,7 +767,7 @@ private:
|
||||
|
||||
using MakeNoteTrackShifter = MakeTrackShifter::Override<NoteTrack>;
|
||||
template<> template<> auto MakeNoteTrackShifter::Implementation() -> Function {
|
||||
return [](NoteTrack &track) {
|
||||
return [](NoteTrack &track, AudacityProject&) {
|
||||
return std::make_unique<NoteTrackShifter>(track);
|
||||
};
|
||||
}
|
||||
|
@ -1314,14 +1314,23 @@ public:
|
||||
~WaveTrackShifter() override {}
|
||||
Track &GetTrack() const override { return *mpTrack; }
|
||||
|
||||
HitTestResult HitTest( double time ) override
|
||||
HitTestResult HitTest(
|
||||
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())
|
||||
@ -1458,7 +1467,7 @@ private:
|
||||
|
||||
using MakeWaveTrackShifter = MakeTrackShifter::Override<WaveTrack>;
|
||||
template<> template<> auto MakeWaveTrackShifter::Implementation() -> Function {
|
||||
return [](WaveTrack &track) {
|
||||
return [](WaveTrack &track, AudacityProject&) {
|
||||
return std::make_unique<WaveTrackShifter>(track);
|
||||
};
|
||||
}
|
||||
|
@ -241,7 +241,8 @@ CoarseTrackShifter::CoarseTrackShifter( Track &track )
|
||||
|
||||
CoarseTrackShifter::~CoarseTrackShifter() = default;
|
||||
|
||||
auto CoarseTrackShifter::HitTest( double ) -> HitTestResult
|
||||
auto CoarseTrackShifter::HitTest(
|
||||
double, const ViewInfo&, HitTestParams* ) -> HitTestResult
|
||||
{
|
||||
return HitTestResult::Track;
|
||||
}
|
||||
@ -252,13 +253,15 @@ bool CoarseTrackShifter::SyncLocks()
|
||||
}
|
||||
|
||||
template<> auto MakeTrackShifter::Implementation() -> Function {
|
||||
return [](Track &track) {
|
||||
return [](Track &track, AudacityProject&) {
|
||||
return std::make_unique<CoarseTrackShifter>(track);
|
||||
};
|
||||
}
|
||||
|
||||
void ClipMoveState::Init(
|
||||
AudacityProject &project,
|
||||
Track &capturedTrack,
|
||||
TrackShifter::HitTestResult hitTestResult,
|
||||
std::unique_ptr<TrackShifter> pHit,
|
||||
double clickTime,
|
||||
const ViewInfo &viewInfo,
|
||||
@ -269,27 +272,35 @@ 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
|
||||
for ( auto track : trackList.Any() ) {
|
||||
auto &pShifter = state.shifters[track];
|
||||
if (!pShifter)
|
||||
pShifter = MakeTrackShifter::Call( *track );
|
||||
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{
|
||||
@ -299,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 );
|
||||
}
|
||||
@ -307,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});
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,29 +467,28 @@ UIHandle::Result TimeShiftHandle::Click
|
||||
const double clickTime =
|
||||
viewInfo.PositionToTime(event.m_x, rect.x);
|
||||
|
||||
bool captureClips = false;
|
||||
|
||||
auto pShifter = MakeTrackShifter::Call( *pTrack );
|
||||
auto pShifter = MakeTrackShifter::Call( *pTrack, *pProject );
|
||||
|
||||
auto hitTestResult = TrackShifter::HitTestResult::Track;
|
||||
if (!event.ShiftDown()) {
|
||||
switch( pShifter->HitTest( clickTime ) ) {
|
||||
TrackShifter::HitTestParams params{
|
||||
rect, event.m_x, event.m_y
|
||||
};
|
||||
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( *pTrack,
|
||||
captureClips ? std::move( pShifter ) : nullptr,
|
||||
mClipMoveState.Init( *pProject, *pTrack,
|
||||
hitTestResult,
|
||||
std::move( pShifter ),
|
||||
clickTime,
|
||||
|
||||
viewInfo, trackList,
|
||||
|
@ -25,6 +25,8 @@ class TrackList;
|
||||
class Track;
|
||||
class TrackInterval;
|
||||
|
||||
class ViewInfo;
|
||||
|
||||
//! Abstract base class for policies to manipulate a track type with the Time Shift tool
|
||||
class TrackShifter {
|
||||
public:
|
||||
@ -35,13 +37,28 @@ 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
|
||||
struct HitTestParams {
|
||||
wxRect rect;
|
||||
wxCoord xx, yy;
|
||||
};
|
||||
|
||||
//! 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 */
|
||||
virtual HitTestResult HitTest( double time ) = 0;
|
||||
/*! 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))`
|
||||
*/
|
||||
virtual HitTestResult HitTest(
|
||||
double time, //!< A time value to test
|
||||
const ViewInfo &viewInfo,
|
||||
HitTestParams *pParams = nullptr //!< Optional extra information
|
||||
) = 0;
|
||||
|
||||
using Intervals = std::vector<TrackInterval>;
|
||||
|
||||
@ -158,7 +175,7 @@ public:
|
||||
~CoarseTrackShifter() override;
|
||||
Track &GetTrack() const override { return *mpTrack; }
|
||||
|
||||
HitTestResult HitTest( double ) override;
|
||||
HitTestResult HitTest( double, const ViewInfo&, HitTestParams* ) override;
|
||||
|
||||
//! Returns false
|
||||
bool SyncLocks() override;
|
||||
@ -169,7 +186,7 @@ private:
|
||||
|
||||
struct MakeTrackShifterTag;
|
||||
using MakeTrackShifter = AttachedVirtualFunction<
|
||||
MakeTrackShifterTag, std::unique_ptr<TrackShifter>, Track>;
|
||||
MakeTrackShifterTag, std::unique_ptr<TrackShifter>, Track, AudacityProject&>;
|
||||
|
||||
class ViewInfo;
|
||||
|
||||
@ -178,9 +195,11 @@ struct ClipMoveState {
|
||||
|
||||
//! Will associate a TrackShifter with each track in the list
|
||||
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…
x
Reference in New Issue
Block a user