mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-16 08:34:10 +02:00
Use TypeSwitch and track_cast in TrackPanel
This commit is contained in:
parent
e17c4acd5d
commit
fd10ed26cd
@ -957,13 +957,22 @@ int totalTCPLines( const TCPLines &lines, bool omitLastExtra )
|
||||
|
||||
const TCPLines &getTCPLines( const Track &track )
|
||||
{
|
||||
auto lines = track.TypeSwitch< TCPLines * >(
|
||||
#ifdef USE_MIDI
|
||||
if ( track.GetKind() == Track::Note )
|
||||
return noteTrackTCPLines;
|
||||
[](const NoteTrack*){
|
||||
return ¬eTrackTCPLines;
|
||||
},
|
||||
#endif
|
||||
[](const WaveTrack*){
|
||||
return &waveTrackTCPLines;
|
||||
},
|
||||
[](const Track*){
|
||||
return &commonTrackTCPLines;
|
||||
}
|
||||
);
|
||||
|
||||
if ( track.GetKind() == Track::Wave )
|
||||
return waveTrackTCPLines;
|
||||
if (lines)
|
||||
return *lines;
|
||||
|
||||
return commonTrackTCPLines;
|
||||
}
|
||||
@ -1719,7 +1728,7 @@ void TrackPanel::DrawOutside
|
||||
const Track * t, const wxRect & rec)
|
||||
{
|
||||
auto dc = &context.dc;
|
||||
bool bIsWave = (t->GetKind() == Track::Wave);
|
||||
const auto wt = track_cast<const WaveTrack*>(t);
|
||||
|
||||
// Draw things that extend right of track control panel
|
||||
{
|
||||
@ -1735,7 +1744,7 @@ void TrackPanel::DrawOutside
|
||||
|
||||
int labelw = GetLabelWidth();
|
||||
int vrul = GetVRulerOffset();
|
||||
mTrackInfo.DrawBackground(dc, rect, t->GetSelected(), bIsWave, labelw, vrul);
|
||||
mTrackInfo.DrawBackground(dc, rect, t->GetSelected(), (wt != nullptr), labelw, vrul);
|
||||
|
||||
// Vaughan, 2010-08-24: No longer doing this.
|
||||
// Draw sync-lock tiles in ruler area.
|
||||
|
@ -373,26 +373,26 @@ wxAccStatus TrackPanelAx::GetName( int childId, wxString* name )
|
||||
name->Printf(_("Track %d"), TrackNum( t ) );
|
||||
}
|
||||
|
||||
if (t->GetKind() == Track::Label)
|
||||
{
|
||||
/* i18n-hint: This is for screen reader software and indicates that
|
||||
this is a Label track.*/
|
||||
name->Append( wxT(" ") + wxString(_("Label Track")));
|
||||
}
|
||||
else if (t->GetKind() == Track::Time)
|
||||
{
|
||||
/* i18n-hint: This is for screen reader software and indicates that
|
||||
this is a Time track.*/
|
||||
name->Append( wxT(" ") + wxString(_("Time Track")));
|
||||
}
|
||||
t->TypeSwitch(
|
||||
[&](const LabelTrack *) {
|
||||
/* i18n-hint: This is for screen reader software and indicates that
|
||||
this is a Label track.*/
|
||||
name->Append( wxT(" ") + wxString(_("Label Track")));
|
||||
},
|
||||
[&](const TimeTrack *) {
|
||||
/* i18n-hint: This is for screen reader software and indicates that
|
||||
this is a Time track.*/
|
||||
name->Append( wxT(" ") + wxString(_("Time Track")));
|
||||
}
|
||||
#ifdef USE_MIDI
|
||||
else if (t->GetKind() == Track::Note)
|
||||
{
|
||||
/* i18n-hint: This is for screen reader software and indicates that
|
||||
this is a Note track.*/
|
||||
name->Append( wxT(" ") + wxString(_("Note Track")));
|
||||
}
|
||||
,
|
||||
[&](const NoteTrack *) {
|
||||
/* i18n-hint: This is for screen reader software and indicates that
|
||||
this is a Note track.*/
|
||||
name->Append( wxT(" ") + wxString(_("Note Track")));
|
||||
}
|
||||
#endif
|
||||
);
|
||||
|
||||
// LLL: Remove these during "refactor"
|
||||
auto pt = dynamic_cast<PlayableTrack *>(t.get());
|
||||
|
@ -284,63 +284,60 @@ void StretchHandle::Stretch(AudacityProject *pProject, int mouseXCoordinate, int
|
||||
if (pTrack == NULL && mpTrack != NULL)
|
||||
pTrack = mpTrack.get();
|
||||
|
||||
if (!pTrack || pTrack->GetKind() != Track::Note) {
|
||||
return;
|
||||
}
|
||||
if (pTrack) pTrack->TypeSwitch( [&](NoteTrack *pNt) {
|
||||
double moveto =
|
||||
std::max(0.0, viewInfo.PositionToTime(mouseXCoordinate, trackLeftEdge));
|
||||
|
||||
NoteTrack *pNt = static_cast<NoteTrack *>(pTrack);
|
||||
double moveto =
|
||||
std::max(0.0, viewInfo.PositionToTime(mouseXCoordinate, trackLeftEdge));
|
||||
double dur, left_dur, right_dur;
|
||||
|
||||
double dur, left_dur, right_dur;
|
||||
// check to make sure tempo is not higher than 20 beats per second
|
||||
// (In principle, tempo can be higher, but not infinity.)
|
||||
double minPeriod = 0.05; // minimum beat period
|
||||
|
||||
// check to make sure tempo is not higher than 20 beats per second
|
||||
// (In principle, tempo can be higher, but not infinity.)
|
||||
double minPeriod = 0.05; // minimum beat period
|
||||
|
||||
// make sure target duration is not too short
|
||||
// Take quick exit if so, without changing the selection.
|
||||
auto t0 = mStretchState.mBeat0.first;
|
||||
auto t1 = mStretchState.mBeat1.first;
|
||||
switch ( mStretchState.mMode ) {
|
||||
case stretchLeft: {
|
||||
dur = t1 - moveto;
|
||||
if (dur < mStretchState.mRightBeats * minPeriod)
|
||||
return;
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeat0, mStretchState.mBeat1, dur );
|
||||
pNt->Offset( moveto - t0 );
|
||||
mStretchState.mBeat0.first = moveto;
|
||||
viewInfo.selectedRegion.setT0(moveto);
|
||||
break;
|
||||
}
|
||||
case stretchRight: {
|
||||
dur = moveto - t0;
|
||||
if (dur < mStretchState.mLeftBeats * minPeriod)
|
||||
return;
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeat0, mStretchState.mBeat1, dur );
|
||||
viewInfo.selectedRegion.setT1(moveto);
|
||||
mStretchState.mBeat1.first = moveto;
|
||||
break;
|
||||
}
|
||||
case stretchCenter: {
|
||||
moveto = std::max(t0, std::min(t1, moveto));
|
||||
left_dur = moveto - t0;
|
||||
right_dur = t1 - moveto;
|
||||
if ( left_dur < mStretchState.mLeftBeats * minPeriod ||
|
||||
right_dur < mStretchState.mRightBeats * minPeriod )
|
||||
return;
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeatCenter, mStretchState.mBeat1, right_dur );
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeat0, mStretchState.mBeatCenter, left_dur );
|
||||
mStretchState.mBeatCenter.first = moveto;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
wxASSERT(false);
|
||||
break;
|
||||
}
|
||||
// make sure target duration is not too short
|
||||
// Take quick exit if so, without changing the selection.
|
||||
auto t0 = mStretchState.mBeat0.first;
|
||||
auto t1 = mStretchState.mBeat1.first;
|
||||
switch ( mStretchState.mMode ) {
|
||||
case stretchLeft: {
|
||||
dur = t1 - moveto;
|
||||
if (dur < mStretchState.mRightBeats * minPeriod)
|
||||
return;
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeat0, mStretchState.mBeat1, dur );
|
||||
pNt->Offset( moveto - t0 );
|
||||
mStretchState.mBeat0.first = moveto;
|
||||
viewInfo.selectedRegion.setT0(moveto);
|
||||
break;
|
||||
}
|
||||
case stretchRight: {
|
||||
dur = moveto - t0;
|
||||
if (dur < mStretchState.mLeftBeats * minPeriod)
|
||||
return;
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeat0, mStretchState.mBeat1, dur );
|
||||
viewInfo.selectedRegion.setT1(moveto);
|
||||
mStretchState.mBeat1.first = moveto;
|
||||
break;
|
||||
}
|
||||
case stretchCenter: {
|
||||
moveto = std::max(t0, std::min(t1, moveto));
|
||||
left_dur = moveto - t0;
|
||||
right_dur = t1 - moveto;
|
||||
if ( left_dur < mStretchState.mLeftBeats * minPeriod ||
|
||||
right_dur < mStretchState.mRightBeats * minPeriod )
|
||||
return;
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeatCenter, mStretchState.mBeat1, right_dur );
|
||||
pNt->StretchRegion
|
||||
( mStretchState.mBeat0, mStretchState.mBeatCenter, left_dur );
|
||||
mStretchState.mBeatCenter.first = moveto;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
wxASSERT(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
@ -178,45 +178,52 @@ UIHandle::Result EnvelopeHandle::Click
|
||||
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
const auto pTrack = static_cast<Track*>(evt.pCell.get());
|
||||
|
||||
if (pTrack &&
|
||||
pTrack->GetKind() == Track::Wave) {
|
||||
WaveTrack *const wt = static_cast<WaveTrack*>(pTrack);
|
||||
if (wt->GetDisplay() != WaveTrack::Waveform)
|
||||
unsigned result = Cancelled;
|
||||
if (pTrack)
|
||||
result = pTrack->TypeSwitch< decltype(RefreshNone) >(
|
||||
[&](WaveTrack *wt) {
|
||||
if (wt->GetDisplay() != WaveTrack::Waveform)
|
||||
return Cancelled;
|
||||
|
||||
if (!mEnvelope)
|
||||
return Cancelled;
|
||||
|
||||
mLog = !wt->GetWaveformSettings().isLinear();
|
||||
wt->GetDisplayBounds(&mLower, &mUpper);
|
||||
mdBRange = wt->GetWaveformSettings().dBRange;
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, true );
|
||||
mEnvelopeEditorRight.reset();
|
||||
|
||||
// Assume linked track is wave or null
|
||||
auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||
if (partner)
|
||||
{
|
||||
auto clickedEnvelope = partner->GetEnvelopeAtX(event.GetX());
|
||||
if (clickedEnvelope)
|
||||
mEnvelopeEditorRight =
|
||||
std::make_unique< EnvelopeEditor >( *clickedEnvelope, true );
|
||||
}
|
||||
|
||||
return RefreshNone;
|
||||
},
|
||||
[&](TimeTrack *tt) {
|
||||
if (!mEnvelope)
|
||||
return Cancelled;
|
||||
GetTimeTrackData( *pProject, *tt, mdBRange, mLog, mLower, mUpper);
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, false );
|
||||
mEnvelopeEditorRight.reset();
|
||||
|
||||
return RefreshNone;
|
||||
},
|
||||
[](Track *) {
|
||||
return Cancelled;
|
||||
|
||||
if (!mEnvelope)
|
||||
return Cancelled;
|
||||
|
||||
mLog = !wt->GetWaveformSettings().isLinear();
|
||||
wt->GetDisplayBounds(&mLower, &mUpper);
|
||||
mdBRange = wt->GetWaveformSettings().dBRange;
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, true );
|
||||
mEnvelopeEditorRight.reset();
|
||||
|
||||
// Assume linked track is wave or null
|
||||
auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||
if (partner)
|
||||
{
|
||||
auto clickedEnvelope = partner->GetEnvelopeAtX(event.GetX());
|
||||
if (clickedEnvelope)
|
||||
mEnvelopeEditorRight =
|
||||
std::make_unique< EnvelopeEditor >( *clickedEnvelope, true );
|
||||
}
|
||||
}
|
||||
else if (pTrack &&
|
||||
pTrack->GetKind() == Track::Time)
|
||||
{
|
||||
TimeTrack *const tt = static_cast<TimeTrack*>(pTrack);
|
||||
if (!mEnvelope)
|
||||
return Cancelled;
|
||||
GetTimeTrackData( *pProject, *tt, mdBRange, mLog, mLower, mUpper);
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, false );
|
||||
mEnvelopeEditorRight.reset();
|
||||
}
|
||||
else
|
||||
return Cancelled;
|
||||
);
|
||||
|
||||
if (result & Cancelled)
|
||||
return result;
|
||||
|
||||
mRect = evt.rect;
|
||||
|
||||
|
@ -85,23 +85,21 @@ void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc)
|
||||
for ( const auto &data : tp->Cells() )
|
||||
{
|
||||
Track *const pTrack = dynamic_cast<Track*>(data.first.get());
|
||||
if (!pTrack)
|
||||
continue;
|
||||
|
||||
// Don't draw the indicator in label tracks
|
||||
if (pTrack->GetKind() == Track::Label)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Draw the NEW indicator in its NEW location
|
||||
// AColor::Line includes both endpoints so use GetBottom()
|
||||
const wxRect &rect = data.second;
|
||||
AColor::Line(dc,
|
||||
mLastIndicatorX,
|
||||
rect.GetTop(),
|
||||
mLastIndicatorX,
|
||||
rect.GetBottom());
|
||||
if (pTrack) pTrack->TypeSwitch(
|
||||
[](LabelTrack *) {
|
||||
// Don't draw the indicator in label tracks
|
||||
},
|
||||
[&](Track *) {
|
||||
// Draw the NEW indicator in its NEW location
|
||||
// AColor::Line includes both endpoints so use GetBottom()
|
||||
const wxRect &rect = data.second;
|
||||
AColor::Line(dc,
|
||||
mLastIndicatorX,
|
||||
rect.GetTop(),
|
||||
mLastIndicatorX,
|
||||
rect.GetBottom());
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
|
||||
|
@ -65,14 +65,13 @@ namespace
|
||||
wxASSERT(t);
|
||||
//For OD regions, we need to override and display the percent complete for this task.
|
||||
//first, make sure it's a wavetrack.
|
||||
if (t->GetKind() != Track::Wave)
|
||||
return;
|
||||
//see if the wavetrack exists in the ODManager (if the ODManager exists)
|
||||
if (!ODManager::IsInstanceCreated())
|
||||
return;
|
||||
//ask the wavetrack for the corresponding tip - it may not change tip, but that's fine.
|
||||
ODManager::Instance()->FillTipForWaveTrack(static_cast<const WaveTrack*>(t), tip);
|
||||
return;
|
||||
t->TypeSwitch( [&](const WaveTrack *wt) {
|
||||
//see if the wavetrack exists in the ODManager (if the ODManager exists)
|
||||
if (!ODManager::IsInstanceCreated())
|
||||
return;
|
||||
//ask the wavetrack for the corresponding tip - it may not change tip, but that's fine.
|
||||
ODManager::Instance()->FillTipForWaveTrack(wt, tip);
|
||||
});
|
||||
}
|
||||
|
||||
/// Converts a frequency to screen y position.
|
||||
@ -125,16 +124,12 @@ namespace
|
||||
|
||||
// This returns true if we're a spectral editing track.
|
||||
inline bool isSpectralSelectionTrack(const Track *pTrack) {
|
||||
if (pTrack &&
|
||||
pTrack->GetKind() == Track::Wave) {
|
||||
const WaveTrack *const wt = static_cast<const WaveTrack*>(pTrack);
|
||||
return pTrack && pTrack->TypeSwitch< bool >( [&](const WaveTrack *wt) {
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
const int display = wt->GetDisplay();
|
||||
return (display == WaveTrack::Spectrum) && settings.SpectralSelectionEnabled();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return (display == WaveTrack::Spectrum) &&
|
||||
settings.SpectralSelectionEnabled();
|
||||
});
|
||||
}
|
||||
|
||||
enum SelectionBoundary {
|
||||
@ -542,19 +537,23 @@ UIHandle::Result SelectHandle::Click
|
||||
|
||||
TrackPanel *const trackPanel = pProject->GetTrackPanel();
|
||||
|
||||
if( pTrack->GetKind() == Track::Label &&
|
||||
event.LeftDown() &&
|
||||
event.ControlDown() ){
|
||||
// We should reach this, only in default of other hits on glyphs or
|
||||
// text boxes.
|
||||
bool bShift = event.ShiftDown();
|
||||
bool unsafe = pProject->IsAudioActive();
|
||||
GetMenuCommandHandler(*pProject)
|
||||
.HandleListSelection(*pProject, pTrack, bShift, true, !unsafe);
|
||||
bool selectChange = (
|
||||
event.LeftDown() &&
|
||||
event.ControlDown() &&
|
||||
pTrack->TypeSwitch<bool>( [&](LabelTrack *){
|
||||
// We should reach this, only in default of other hits on glyphs or
|
||||
// text boxes.
|
||||
bool bShift = event.ShiftDown();
|
||||
bool unsafe = pProject->IsAudioActive();
|
||||
GetMenuCommandHandler(*pProject)
|
||||
.HandleListSelection(*pProject, pTrack, bShift, true, !unsafe);
|
||||
return true;
|
||||
} )
|
||||
);
|
||||
if ( selectChange )
|
||||
// Do not start a drag
|
||||
return RefreshAll | Cancelled;
|
||||
}
|
||||
|
||||
|
||||
auto &selectionState = pProject->GetSelectionState();
|
||||
if (event.LeftDClick() && !event.ShiftDown()) {
|
||||
TrackList *const trackList = pProject->GetTracks();
|
||||
@ -571,14 +570,13 @@ UIHandle::Result SelectHandle::Click
|
||||
|
||||
// Special case: if we're over a clip in a WaveTrack,
|
||||
// select just that clip
|
||||
if (pTrack->GetKind() == Track::Wave) {
|
||||
WaveTrack *const wt = static_cast<WaveTrack *>(pTrack);
|
||||
pTrack->TypeSwitch( [&] ( WaveTrack *wt ) {
|
||||
WaveClip *const selectedClip = wt->GetClipAtX(event.m_x);
|
||||
if (selectedClip) {
|
||||
viewInfo.selectedRegion.setTimes(
|
||||
selectedClip->GetOffset(), selectedClip->GetEndTime());
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
pProject->ModifyState(false);
|
||||
|
||||
@ -776,11 +774,10 @@ UIHandle::Result SelectHandle::Click
|
||||
( *pTrack, true, true, pMixerBoard );
|
||||
trackPanel->SetFocusedTrack(pTrack);
|
||||
//On-Demand: check to see if there is an OD thing associated with this track.
|
||||
if (pTrack->GetKind() == Track::Wave) {
|
||||
pTrack->TypeSwitch( [&](WaveTrack *wt) {
|
||||
if(ODManager::IsInstanceCreated())
|
||||
ODManager::Instance()->DemandTrackUpdate
|
||||
(static_cast<WaveTrack*>(pTrack),mSelStart);
|
||||
}
|
||||
ODManager::Instance()->DemandTrackUpdate(wt,mSelStart);
|
||||
});
|
||||
|
||||
Connect(pProject);
|
||||
return RefreshAll | UpdateSelection;
|
||||
@ -1201,9 +1198,11 @@ void SelectHandle::AssignSelection
|
||||
viewInfo.selectedRegion.setTimes(sel0, sel1);
|
||||
|
||||
//On-Demand: check to see if there is an OD thing associated with this track. If so we want to update the focal point for the task.
|
||||
if (pTrack && (pTrack->GetKind() == Track::Wave) && ODManager::IsInstanceCreated())
|
||||
ODManager::Instance()->DemandTrackUpdate
|
||||
(static_cast<WaveTrack*>(pTrack),sel0); //sel0 is sometimes less than mSelStart
|
||||
if (pTrack && ODManager::IsInstanceCreated())
|
||||
pTrack->TypeSwitch( [&](WaveTrack *wt) {
|
||||
ODManager::Instance()->DemandTrackUpdate(wt, sel0);
|
||||
//sel0 is sometimes less than mSelStart
|
||||
});
|
||||
}
|
||||
|
||||
void SelectHandle::StartFreqSelection(ViewInfo &viewInfo,
|
||||
|
@ -15,6 +15,7 @@ Paul Licameli split from TrackPanel.cpp
|
||||
#include "TrackControls.h"
|
||||
#include "../../AColor.h"
|
||||
#include "../../HitTestResult.h"
|
||||
#include "../../NoteTrack.h"
|
||||
#include "../../Project.h"
|
||||
#include "../../RefreshCode.h"
|
||||
#include "../../TrackPanelMouseEvent.h"
|
||||
@ -101,38 +102,40 @@ namespace
|
||||
void AddClipsToCaptured
|
||||
( ClipMoveState &state, Track *t, double t0, double t1 )
|
||||
{
|
||||
auto &clips = state.capturedClipArray;
|
||||
|
||||
bool exclude = true;
|
||||
if (t->GetKind() == Track::Wave)
|
||||
{
|
||||
exclude = false;
|
||||
for(const auto &clip: static_cast<WaveTrack*>(t)->GetClips())
|
||||
if ( ! clip->AfterClip(t0) && ! clip->BeforeClip(t1) &&
|
||||
// Avoid getting clips that were already captured
|
||||
! std::any_of( clips.begin(), clips.end(),
|
||||
[&](const TrackClip &c) { return c.clip == clip.get(); } ) )
|
||||
clips.emplace_back( t, clip.get() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// This handles label tracks rather heavy-handedly -- it would be nice to
|
||||
// treat individual labels like clips
|
||||
|
||||
// Avoid adding a track twice
|
||||
if( ! std::any_of( clips.begin(), clips.end(),
|
||||
[&](const TrackClip &c) { return c.track == t; } ) ) {
|
||||
#ifdef USE_MIDI
|
||||
auto &clips = state.capturedClipArray;
|
||||
t->TypeSwitch(
|
||||
[&](WaveTrack *wt) {
|
||||
exclude = false;
|
||||
for(const auto &clip: wt->GetClips())
|
||||
if ( ! clip->AfterClip(t0) && ! clip->BeforeClip(t1) &&
|
||||
// Avoid getting clips that were already captured
|
||||
! std::any_of( clips.begin(), clips.end(),
|
||||
[&](const TrackClip &c) { return c.clip == clip.get(); } ) )
|
||||
clips.emplace_back( t, clip.get() );
|
||||
},
|
||||
#ifdef USE_MIDI
|
||||
[&](NoteTrack *, const Track::Fallthrough &fallthrough){
|
||||
// do not add NoteTrack if the data is outside of time bounds
|
||||
if (t->GetKind() == Track::Note) {
|
||||
if (t->GetEndTime() < t0 || t->GetStartTime() > t1)
|
||||
return;
|
||||
if (t->GetEndTime() < t0 || t->GetStartTime() > t1)
|
||||
return;
|
||||
else
|
||||
fallthrough();
|
||||
},
|
||||
#endif
|
||||
[&](Track *t) {
|
||||
// This handles label tracks rather heavy-handedly --
|
||||
// it would be nice to
|
||||
// treat individual labels like clips
|
||||
|
||||
// Avoid adding a track twice
|
||||
if( !std::any_of( clips.begin(), clips.end(),
|
||||
[&](const TrackClip &c) { return c.track == t; } ) ) {
|
||||
clips.emplace_back( t, nullptr );
|
||||
}
|
||||
#endif
|
||||
clips.emplace_back( t, nullptr );
|
||||
}
|
||||
}
|
||||
if ( exclude )
|
||||
);
|
||||
if (exclude)
|
||||
state.trackExclusions.push_back(t);
|
||||
}
|
||||
|
||||
@ -273,14 +276,13 @@ void TimeShiftHandle::CreateListOfCapturedClips
|
||||
}
|
||||
#ifdef USE_MIDI
|
||||
// Capture additional clips from NoteTracks
|
||||
Track *nt = trackClip.track;
|
||||
if (nt->GetKind() == Track::Note) {
|
||||
trackClip.track->TypeSwitch( [&](NoteTrack *nt) {
|
||||
// Iterate over sync-lock group tracks.
|
||||
SyncLockedTracksIterator git( &trackList );
|
||||
for (Track *t = git.StartWith(nt); t; t = git.Next())
|
||||
AddClipsToCaptured
|
||||
( state, t, nt->GetStartTime(), nt->GetEndTime() );
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -376,24 +378,21 @@ UIHandle::Result TimeShiftHandle::Click
|
||||
bool ok = true;
|
||||
bool captureClips = false;
|
||||
|
||||
if (!event.ShiftDown()) {
|
||||
WaveTrack *wt = pTrack->GetKind() == Track::Wave
|
||||
? static_cast<WaveTrack*>(pTrack.get()) : nullptr;
|
||||
if (wt)
|
||||
{
|
||||
if (nullptr ==
|
||||
(mClipMoveState.capturedClip = wt->GetClipAtX(event.m_x)))
|
||||
ok = false;
|
||||
else
|
||||
captureClips = true;
|
||||
}
|
||||
if (!event.ShiftDown())
|
||||
pTrack->TypeSwitch(
|
||||
[&](WaveTrack *wt) {
|
||||
if (nullptr ==
|
||||
(mClipMoveState.capturedClip = wt->GetClipAtX(event.m_x)))
|
||||
ok = false;
|
||||
else
|
||||
captureClips = true;
|
||||
},
|
||||
#ifdef USE_MIDI
|
||||
else if (pTrack->GetKind() == Track::Note)
|
||||
{
|
||||
captureClips = true;
|
||||
}
|
||||
[&](NoteTrack *) {
|
||||
captureClips = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
);
|
||||
|
||||
if ( ! ok )
|
||||
return Cancelled;
|
||||
@ -436,12 +435,11 @@ namespace {
|
||||
viewInfo.PositionToTime(state.mMouseClickX);
|
||||
double clipLeft = 0, clipRight = 0;
|
||||
|
||||
if (track.GetKind() == Track::Wave) {
|
||||
WaveTrack *const mtw = static_cast<WaveTrack*>(&track);
|
||||
track.TypeSwitch( [&](WaveTrack *mtw){
|
||||
const double rate = mtw->GetRate();
|
||||
// set it to a sample point
|
||||
desiredSlideAmount = rint(desiredSlideAmount * rate) / rate;
|
||||
}
|
||||
});
|
||||
|
||||
// Adjust desiredSlideAmount using SnapManager
|
||||
if (pSnapManager) {
|
||||
@ -715,22 +713,27 @@ UIHandle::Result TimeShiftHandle::Drag
|
||||
|
||||
// If the mouse is over a track that isn't the captured track,
|
||||
// decide which tracks the captured clips should go to.
|
||||
if (mClipMoveState.capturedClip &&
|
||||
pTrack != mCapturedTrack &&
|
||||
pTrack->GetKind() == Track::Wave
|
||||
/* && !mCapturedClipIsSelection*/)
|
||||
{
|
||||
if ( DoSlideVertical( viewInfo, event.m_x, mClipMoveState,
|
||||
*trackList, *mCapturedTrack, *pTrack, desiredSlideAmount ) ) {
|
||||
mCapturedTrack = pTrack;
|
||||
mDidSlideVertically = true;
|
||||
}
|
||||
else
|
||||
return RefreshAll;
|
||||
bool fail = (
|
||||
mClipMoveState.capturedClip &&
|
||||
pTrack != mCapturedTrack
|
||||
/* && !mCapturedClipIsSelection*/
|
||||
&& pTrack->TypeSwitch<bool>( [&] (WaveTrack *) {
|
||||
if ( DoSlideVertical( viewInfo, event.m_x, mClipMoveState,
|
||||
*trackList, *mCapturedTrack, *pTrack, desiredSlideAmount ) ) {
|
||||
mCapturedTrack = pTrack;
|
||||
mDidSlideVertically = true;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
|
||||
// Not done yet, check for horizontal movement.
|
||||
slidVertically = true;
|
||||
}
|
||||
// Not done yet, check for horizontal movement.
|
||||
slidVertically = true;
|
||||
return false;
|
||||
})
|
||||
);
|
||||
|
||||
if (fail)
|
||||
return RefreshAll;
|
||||
|
||||
if (desiredSlideAmount == 0.0)
|
||||
return RefreshAll;
|
||||
|
Loading…
x
Reference in New Issue
Block a user