TrackPanelMouseEvent stores shared_ptr to cell; some handles too...

... those handles that force a simulated button-up when play interrupts drag,
and can assume that pointers to tracks remain nonNULL and part of the current
project state (not the undo history).

Also pass shared_ptr to Track into more hit test routines.
This commit is contained in:
Paul Licameli 2017-06-27 13:40:36 -04:00
parent 708d84ac22
commit b0c6a67c33
40 changed files with 166 additions and 150 deletions

View File

@ -855,7 +855,7 @@ void TrackPanel::HandleCursor( wxMouseEvent *pEvent )
auto &rect = foundCell.rect;
auto &pCell = foundCell.pCell;
const auto size = GetSize();
const TrackPanelMouseEvent tpmEvent{ event, rect, size, pCell.get() };
const TrackPanelMouseEvent tpmEvent{ event, rect, size, pCell };
HandleCursor( tpmEvent );
}
@ -875,7 +875,7 @@ void TrackPanel::HandleCursor( const TrackPanelMouseEvent &tpmEvent )
wxString tip;
auto pCell = tpmEvent.pCell;
auto track = static_cast<CommonTrackPanelCell*>( pCell )->FindTrack();
auto track = static_cast<CommonTrackPanelCell*>( pCell.get() )->FindTrack();
if (pCell && pCursor == NULL && tip == wxString()) {
const auto size = GetSize();
HitTestResult hitTest( pCell->HitTest(tpmEvent, GetProject()) );
@ -1234,7 +1234,7 @@ void TrackPanel::HandleWheelRotation( TrackPanelMouseEvent &tpmEvent )
unsigned result =
pCell->HandleWheelRotation( tpmEvent, GetProject() );
auto pTrack = static_cast<CommonTrackPanelCell*>(pCell)->FindTrack();
auto pTrack = static_cast<CommonTrackPanelCell*>(pCell.get())->FindTrack();
ProcessUIHandleResult(this, mRuler, pTrack.get(), pTrack.get(), result);
}
@ -1383,7 +1383,7 @@ try
auto &pTrack = foundCell.pTrack;
const auto size = GetSize();
TrackPanelMouseEvent tpmEvent{ event, rect, size, pCell.get() };
TrackPanelMouseEvent tpmEvent{ event, rect, size, pCell };
#if defined(__WXMAC__) && defined(EVT_MAGNIFY)
// PRL:
@ -1531,7 +1531,7 @@ void TrackPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent )
const auto &event = tpmEvent.event;
auto pCell = tpmEvent.pCell;
const auto &rect = tpmEvent.rect;
auto pTrack = static_cast<CommonTrackPanelCell *>( pCell )->FindTrack();
auto pTrack = static_cast<CommonTrackPanelCell *>( pCell.get() )->FindTrack();
if ( !mUIHandle && pCell )
mUIHandle =

View File

@ -15,6 +15,7 @@ class wxMouseEvent;
class wxRect;
class wxSize;
class TrackPanelCell;
#include "MemoryX.h"
// Augment a mouse event with information about which track panel cell and
// sub-rectangle was hit.
@ -22,7 +23,7 @@ struct TrackPanelMouseEvent
{
TrackPanelMouseEvent
( wxMouseEvent &event_, const wxRect &rect_, const wxSize &whole_,
TrackPanelCell *pCell_ )
const std::shared_ptr<TrackPanelCell> &pCell_ )
: event{ event_ }
, rect{ rect_ }
, whole{ whole_ }
@ -34,7 +35,7 @@ struct TrackPanelMouseEvent
wxMouseEvent &event;
const wxRect &rect;
const wxSize &whole;
TrackPanelCell *pCell; // may be NULL
std::shared_ptr<TrackPanelCell> pCell; // may be NULL
double steps; // for mouse wheel rotation
};

View File

@ -70,8 +70,8 @@ UIHandle::Result TrackPanelResizeHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{
const wxMouseEvent &event = evt.event;
CommonTrackPanelCell *const pCell =
static_cast<CommonTrackPanelCell*>(evt.pCell);
const auto pCell =
static_cast<CommonTrackPanelCell*>(evt.pCell.get());
auto track = pCell->FindTrack().get();
if (track && dynamic_cast< TrackControls * >( pCell )) {
// Clicked under a label;

View File

@ -66,7 +66,7 @@ UIHandle::Result LabelDefaultClickHandle::Click
// Redraw to show the change of text box selection status
UIHandle::Result result = RefreshAll;
LabelTrack *pLT = static_cast<LabelTrack*>(evt.pCell);
auto pLT = static_cast<LabelTrack*>(evt.pCell.get());
if (evt.event.LeftDown())
{
@ -77,7 +77,7 @@ UIHandle::Result LabelDefaultClickHandle::Click
Track *n = iter.First();
while (n) {
if (n->GetKind() == Track::Label && evt.pCell != n) {
if (n->GetKind() == Track::Label && evt.pCell.get() != n) {
LabelTrack *const lt = static_cast<LabelTrack*>(n);
lt->ResetFlags();
lt->Unselect();

View File

@ -49,7 +49,7 @@ HitTestPreview LabelGlyphHandle::HitPreview
}
HitTestResult LabelGlyphHandle::HitTest
(const wxMouseEvent &event, LabelTrack *pLT)
(const wxMouseEvent &event, const std::shared_ptr<LabelTrack> &pLT)
{
using namespace RefreshCode;
unsigned refreshResult = RefreshNone;
@ -93,11 +93,11 @@ UIHandle::Result LabelGlyphHandle::Click
{
auto result = LabelDefaultClickHandle::Click( evt, pProject );
TrackPanelCell *const pCell = evt.pCell;
const auto pCell = evt.pCell;
const wxMouseEvent &event = evt.event;
const wxRect &rect = evt.rect;
mpLT = static_cast<LabelTrack*>(pCell);
mpLT = std::static_pointer_cast<LabelTrack>(pCell);
mRect = rect;
ViewInfo &viewInfo = pProject->GetViewInfo();

View File

@ -13,6 +13,7 @@ Paul Licameli split from TrackPanel.cpp
#include "LabelDefaultClickHandle.h"
#include <wx/gdicmn.h>
#include "../../../MemoryX.h"
class wxMouseEvent;
struct HitTestResult;
@ -28,7 +29,7 @@ class LabelGlyphHandle final : public LabelDefaultClickHandle
public:
static HitTestResult HitTest
(const wxMouseEvent &event, LabelTrack *pLT);
(const wxMouseEvent &event, const std::shared_ptr<LabelTrack> &pLT);
virtual ~LabelGlyphHandle();
@ -51,7 +52,7 @@ public:
bool StopsOnKeystroke() override { return true; }
private:
LabelTrack *mpLT {};
std::shared_ptr<LabelTrack> mpLT {};
wxRect mRect {};
};

View File

@ -38,7 +38,8 @@ HitTestPreview LabelTextHandle::HitPreview()
};
}
HitTestResult LabelTextHandle::HitTest(const wxMouseEvent &event, LabelTrack *pLT)
HitTestResult LabelTextHandle::HitTest
(const wxMouseEvent &event, const std::shared_ptr<LabelTrack> &pLT)
{
// If Control is down, let the select handle be hit instead
if (!event.ControlDown() &&
@ -63,11 +64,11 @@ UIHandle::Result LabelTextHandle::Click
mChanger =
std::make_unique< SelectionStateChanger >( selectionState, *tracks );
TrackPanelCell *const pCell = evt.pCell;
const auto pCell = evt.pCell;
const wxMouseEvent &event = evt.event;
ViewInfo &viewInfo = pProject->GetViewInfo();
auto pLT = Track::Pointer<LabelTrack>( static_cast<Track*>(pCell) );
auto pLT = std::static_pointer_cast<LabelTrack>(pCell);
mpLT = pLT;
mSelectedRegion = viewInfo.selectedRegion;
pLT->HandleTextClick( event, evt.rect, viewInfo, &viewInfo.selectedRegion );

View File

@ -31,7 +31,8 @@ class LabelTextHandle final : public LabelDefaultClickHandle
static HitTestPreview HitPreview();
public:
static HitTestResult HitTest(const wxMouseEvent &event, LabelTrack *pLT);
static HitTestResult HitTest(
const wxMouseEvent &event, const std::shared_ptr<LabelTrack> &pLT);
virtual ~LabelTextHandle();

View File

@ -29,11 +29,11 @@ HitTestResult LabelTrack::DetailedHitTest
const wxMouseEvent &event = evt.event;
// Try label movement handles first
result = LabelGlyphHandle::HitTest(event, this);
result = LabelGlyphHandle::HitTest(event, Pointer<LabelTrack>(this));
if ( !result.handle )
// Missed glyph, try text box
result = LabelTextHandle::HitTest(event, this);
result = LabelTextHandle::HitTest(event, Pointer<LabelTrack>(this));
return result;
}

View File

@ -39,7 +39,8 @@ class NoteTrackClickHandle : public UIHandle
public:
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect, Track *pTrack);
(const wxMouseEvent &event, const wxRect &rect,
const std::shared_ptr<NoteTrack> &pTrack);
protected:
virtual Result Click
@ -76,7 +77,8 @@ NoteTrackClickHandle &NoteTrackClickHandle::Instance()
}
HitTestResult NoteTrackClickHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect, Track *pTrack)
(const wxMouseEvent &event, const wxRect &rect,
const std::shared_ptr<NoteTrack> &pTrack)
{
wxRect midiRect;
TrackInfo::GetMidiControlsRect(rect, midiRect);
@ -84,7 +86,7 @@ HitTestResult NoteTrackClickHandle::HitTest
return {};
if (pTrack->GetKind() == Track::Note &&
midiRect.Contains(event.m_x, event.m_y)) {
Instance().mpTrack = Track::Pointer<NoteTrack>( pTrack );
Instance().mpTrack = pTrack;
Instance().mRect = midiRect;
return {
HitTestPreview(),
@ -150,17 +152,17 @@ HitTestResult NoteTrackControls::HitTest
const wxMouseEvent &event = evt.event;
const wxRect &rect = evt.rect;
if (event.ButtonDown() || event.ButtonDClick()) {
auto track = FindTrack();
auto track = std::static_pointer_cast<NoteTrack>(FindTrack());
if (track && track->GetKind() == Track::Note) {
HitTestResult result;
if (NULL !=
(result = MuteButtonHandle::HitTest
(event, rect, pProject, track.get())).handle)
(event, rect, pProject, track)).handle)
return result;
if (NULL !=
(result = SoloButtonHandle::HitTest
(event, rect, pProject, track.get())).handle)
(event, rect, pProject, track)).handle)
return result;
#ifdef EXPERIMENTAL_MIDI_OUT
if (NULL != (result =

View File

@ -36,24 +36,25 @@ VelocitySliderHandle &VelocitySliderHandle::Instance()
return instance;
}
NoteTrack *VelocitySliderHandle::GetTrack()
std::shared_ptr<NoteTrack> VelocitySliderHandle::GetNoteTrack()
{
return static_cast<NoteTrack*>(mpTrack);
return std::static_pointer_cast<NoteTrack>(mpTrack.lock());
}
float VelocitySliderHandle::GetValue()
{
return GetTrack()->GetVelocity();
return GetNoteTrack()->GetVelocity();
}
UIHandle::Result VelocitySliderHandle::SetValue
(AudacityProject *pProject, float newValue)
{
GetTrack()->SetVelocity(newValue);
auto pTrack = GetNoteTrack();
pTrack->SetVelocity(newValue);
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->UpdateVelocity(GetTrack());
pMixerBoard->UpdateVelocity(pTrack.get());
return RefreshCode::RefreshCell;
}
@ -69,7 +70,7 @@ UIHandle::Result VelocitySliderHandle::CommitChanges
HitTestResult VelocitySliderHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack)
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
{
if (!event.Button(wxMOUSE_BTN_LEFT))
return {};

View File

@ -30,7 +30,7 @@ class VelocitySliderHandle final : public SliderHandle
virtual ~VelocitySliderHandle();
static VelocitySliderHandle& Instance();
NoteTrack *GetTrack();
std::shared_ptr<NoteTrack> GetNoteTrack();
protected:
float GetValue() override;
@ -44,7 +44,7 @@ protected:
public:
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack);
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
};
#endif

View File

@ -30,7 +30,7 @@ HitTestResult NoteTrack::DetailedHitTest
HitTestResult result;
#ifdef USE_MIDI
StretchHandle::StretchState state;
result = StretchHandle::HitTest( event, pProject, this, state );
result = StretchHandle::HitTest( event, pProject, Pointer<NoteTrack>(this), state );
#endif
return result;

View File

@ -110,7 +110,7 @@ UIHandle::Result NoteTrackVZoomHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{
mpTrack = std::static_pointer_cast<NoteTrack>(
static_cast<NoteTrackVRulerControls*>(evt.pCell)->FindTrack() );
static_cast<NoteTrackVRulerControls*>(evt.pCell.get())->FindTrack() );
mRect = evt.rect;
const wxMouseEvent &event = evt.event;

View File

@ -69,7 +69,7 @@ HitTestPreview StretchHandle::HitPreview( StretchEnum stretchMode, bool unsafe )
HitTestResult StretchHandle::HitTest
( const TrackPanelMouseEvent &evt, const AudacityProject *pProject,
NoteTrack *pTrack, StretchState &stretchState)
const std::shared_ptr<NoteTrack> &pTrack, StretchState &stretchState)
{
const wxMouseEvent &event = evt.event;
@ -165,7 +165,7 @@ UIHandle::Result StretchHandle::Click
mLeftEdge = evt.rect.GetLeft();
mpTrack = static_cast<NoteTrack*>(evt.pCell);
mpTrack = std::static_pointer_cast<NoteTrack>(evt.pCell);
ViewInfo &viewInfo = pProject->GetViewInfo();
// We must have hit if we got here, but repeat some
@ -196,10 +196,10 @@ UIHandle::Result StretchHandle::Drag
const int x = event.m_x;
Track *clickedTrack =
static_cast<CommonTrackPanelCell*>(evt.pCell)->FindTrack().get();
static_cast<CommonTrackPanelCell*>(evt.pCell.get())->FindTrack().get();
if (clickedTrack == NULL && mpTrack != NULL)
clickedTrack = mpTrack;
clickedTrack = mpTrack.get();
Stretch(pProject, x, mLeftEdge, clickedTrack);
return RefreshAll;
}
@ -229,9 +229,9 @@ UIHandle::Result StretchHandle::Release
( ( left = mStretchState.mMode == stretchLeft ) ||
mStretchState.mMode == stretchRight ) ) {
SyncLockedTracksIterator syncIter( pProject->GetTracks() );
for ( auto track = syncIter.StartWith( mpTrack ); track != nullptr;
for ( auto track = syncIter.StartWith( mpTrack.get() ); track != nullptr;
track = syncIter.Next() ) {
if ( track != mpTrack ) {
if ( track != mpTrack.get() ) {
if ( left ) {
auto origT0 = mStretchState.mOrigSel0Quantized;
auto diff = viewInfo.selectedRegion.t0() - origT0;
@ -275,7 +275,7 @@ void StretchHandle::Stretch(AudacityProject *pProject, int mouseXCoordinate, int
TrackList *const trackList = pProject->GetTracks();
if (pTrack == NULL && mpTrack != NULL)
pTrack = mpTrack;
pTrack = mpTrack.get();
if (!pTrack || pTrack->GetKind() != Track::Note) {
return;

View File

@ -64,7 +64,7 @@ private:
public:
static HitTestResult HitTest
( const TrackPanelMouseEvent &event, const AudacityProject *pProject,
NoteTrack *pTrack, StretchState &state );
const std::shared_ptr<NoteTrack> &pTrack, StretchState &state );
virtual ~StretchHandle();
@ -89,7 +89,7 @@ private:
void Stretch
(AudacityProject *pProject, int mouseXCoordinate, int trackLeftEdge, Track *pTrack);
NoteTrack *mpTrack{};
std::shared_ptr<NoteTrack> mpTrack{};
int mLeftEdge{ -1 };
StretchState mStretchState{};

View File

@ -45,12 +45,12 @@ UIHandle::Result MuteButtonHandle::CommitChanges
HitTestResult MuteButtonHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, const Track *pTrack)
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
{
wxRect buttonRect;
if ( pTrack )
TrackInfo::GetMuteSoloRect(rect, buttonRect, false,
!pProject->IsSoloNone(), pTrack);
!pProject->IsSoloNone(), pTrack.get());
if ( TrackInfo::HideTopItem( rect, buttonRect ) )
return {};
@ -94,12 +94,12 @@ UIHandle::Result SoloButtonHandle::CommitChanges
HitTestResult SoloButtonHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, const Track *pTrack)
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
{
wxRect buttonRect;
if ( pTrack )
TrackInfo::GetMuteSoloRect(rect, buttonRect, true,
!pProject->IsSoloNone(), pTrack);
!pProject->IsSoloNone(), pTrack.get());
if ( TrackInfo::HideTopItem( rect, buttonRect ) )
return {};

View File

@ -34,7 +34,7 @@ protected:
public:
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, const Track *pTrack);
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
};
////////////////////////////////////////////////////////////////////////////////
@ -58,7 +58,7 @@ protected:
public:
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, const Track *pTrack);
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
};
#endif

View File

@ -102,7 +102,8 @@ namespace
}
HitTestResult CutlineHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect, const AudacityProject *pProject, Track *pTrack)
(const wxMouseEvent &event, const wxRect &rect, const AudacityProject *pProject,
const std::shared_ptr<WaveTrack> &pTrack)
{
const ViewInfo &viewInfo = pProject->GetViewInfo();
/// method that tells us if the mouse event landed on an
@ -110,7 +111,7 @@ HitTestResult CutlineHandle::HitTest
if (pTrack->GetKind() != Track::Wave)
return {};
WaveTrack *wavetrack = static_cast<WaveTrack*>(pTrack);
WaveTrack *wavetrack = pTrack.get();
WaveTrackLocation location;
if (!IsOverCutline(viewInfo, wavetrack, rect, event, &location))
return {};
@ -127,7 +128,7 @@ UIHandle::Result CutlineHandle::Click
{
const wxMouseEvent &event = evt.event;
ViewInfo &viewInfo = pProject->GetViewInfo();
Track *const pTrack = static_cast<Track*>(evt.pCell);
const auto pTrack = static_cast<Track*>(evt.pCell.get());
// Can affect the track by merging clips, expanding a cutline, or
// deleting a cutline.

View File

@ -12,10 +12,11 @@ Paul Licameli
#define __AUDACITY_CUTLINE_HANDLE__
#include "../../../../UIHandle.h"
#include "../../../../MemoryX.h"
class wxMouseEvent;
struct HitTestResult;
class Track;
class WaveTrack;
class CutlineHandle final : public UIHandle
{
@ -29,7 +30,7 @@ public:
static HitTestResult HitAnywhere(const AudacityProject *pProject, bool cutline);
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack);
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &pTrack);
virtual ~CutlineHandle();

View File

@ -106,7 +106,7 @@ namespace {
HitTestResult SampleHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack)
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &pTrack)
{
const ViewInfo &viewInfo = pProject->GetViewInfo();
@ -115,7 +115,7 @@ HitTestResult SampleHandle::HitTest
if (pTrack->GetKind() != Track::Wave)
return {};
WaveTrack *wavetrack = static_cast<WaveTrack*>(pTrack);
WaveTrack *wavetrack = pTrack.get();
const int displayType = wavetrack->GetDisplay();
if (WaveTrack::Waveform != displayType)
@ -209,7 +209,7 @@ UIHandle::Result SampleHandle::Click
const wxMouseEvent &event = evt.event;
const wxRect &rect = evt.rect;
const ViewInfo &viewInfo = pProject->GetViewInfo();
Track *const pTrack = static_cast<Track*>(evt.pCell);
const auto pTrack = std::static_pointer_cast<WaveTrack>(evt.pCell);
using namespace RefreshCode;
@ -217,18 +217,18 @@ UIHandle::Result SampleHandle::Click
const bool unsafe = pProject->IsAudioActive();
if (unsafe)
return Cancelled;
if (!IsSampleEditingPossible
(event, rect, viewInfo, pTrack, rect.width))
if (!IsSampleEditingPossible(
event, rect, viewInfo, pTrack.get(), rect.width))
return Cancelled;
/// We're in a track view and zoomed enough to see the samples.
mClickedTrack = static_cast<WaveTrack*>(pTrack);
mClickedTrack = pTrack;
mRect = rect;
//If we are still around, we are drawing in earnest. Set some member data structures up:
//First, calculate the starting sample. To get this, we need the time
const double t0 =
adjustTime(mClickedTrack, viewInfo.PositionToTime(event.m_x, rect.x));
adjustTime(mClickedTrack.get(), viewInfo.PositionToTime(event.m_x, rect.x));
//convert t0 to samples
mClickedStartSample = mClickedTrack->TimeToLongSamples(t0);
@ -434,7 +434,7 @@ UIHandle::Result SampleHandle::Release
//*** UP-CLICK (Finish drawing) ***
//*************************************************
//On up-click, send the state to the undo stack
mClickedTrack = nullptr; //Set this to NULL so it will catch improper drag events.
mClickedTrack.reset(); //Set this to NULL so it will catch improper drag events.
pProject->PushState(_("Moved Samples"),
_("Sample Edit"),
UndoPush::CONSOLIDATE | UndoPush::AUTOSAVE);
@ -446,7 +446,7 @@ UIHandle::Result SampleHandle::Release
UIHandle::Result SampleHandle::Cancel(AudacityProject *pProject)
{
pProject->RollbackState();
mClickedTrack = nullptr;
mClickedTrack.reset();
return RefreshCode::RefreshCell;
}

View File

@ -13,6 +13,7 @@ Paul Licameli
#include "../../../../UIHandle.h"
#include "audacity/Types.h"
#include "MemoryX.h"
class wxMouseEvent;
#include <wx/gdicmn.h>
@ -36,7 +37,7 @@ public:
(const wxMouseEvent &event, const AudacityProject *pProject);
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack);
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &pTrack);
virtual ~SampleHandle();
@ -62,7 +63,7 @@ private:
float FindSampleEditingLevel
(const wxMouseEvent &event, const ViewInfo &viewInfo, double t0);
WaveTrack *mClickedTrack{};
std::shared_ptr<WaveTrack> mClickedTrack;
wxRect mRect{};
sampleCount mClickedStartSample{};

View File

@ -65,20 +65,20 @@ HitTestResult WaveTrackControls::HitTest
HitTestResult result;
if (NULL !=
(result = MuteButtonHandle::HitTest
(event, rect, pProject, track.get())).handle)
(event, rect, pProject, track)).handle)
return result;
if (NULL !=
(result = SoloButtonHandle::HitTest
(event, rect, pProject, track.get())).handle)
(event, rect, pProject, track)).handle)
return result;
if (NULL != (result =
GainSliderHandle::HitTest(event, rect, pProject, track.get())).handle)
GainSliderHandle::HitTest(event, rect, pProject, track)).handle)
return result;
if (NULL != (result =
PanSliderHandle::HitTest(event, rect, pProject, track.get())).handle)
PanSliderHandle::HitTest(event, rect, pProject, track)).handle)
return result;
}
}

View File

@ -1,5 +1,3 @@
#include "WaveTrackSliderHandles.h"
/**********************************************************************
Audacity: A Digital Audio Editor
@ -36,29 +34,30 @@ GainSliderHandle &GainSliderHandle::Instance()
return instance;
}
WaveTrack *GainSliderHandle::GetTrack()
std::shared_ptr<WaveTrack> GainSliderHandle::GetWaveTrack()
{
return static_cast<WaveTrack*>(mpTrack);
return std::static_pointer_cast<WaveTrack>(mpTrack.lock());
}
float GainSliderHandle::GetValue()
{
return static_cast<WaveTrack*>(mpTrack)->GetGain();
return GetWaveTrack()->GetGain();
}
UIHandle::Result GainSliderHandle::SetValue
(AudacityProject *pProject, float newValue)
{
GetTrack()->SetGain(newValue);
auto pTrack = GetWaveTrack();
pTrack->SetGain(newValue);
// Assume linked track is wave or null
const auto link = static_cast<WaveTrack*>(mpTrack->GetLink());
const auto link = static_cast<WaveTrack*>(mpTrack.lock()->GetLink());
if (link)
link->SetGain(newValue);
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->UpdateGain(GetTrack());
pMixerBoard->UpdateGain(pTrack.get());
return RefreshCode::RefreshNone;
}
@ -72,7 +71,7 @@ UIHandle::Result GainSliderHandle::CommitChanges
HitTestResult GainSliderHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *, Track *pTrack)
const AudacityProject *, const std::shared_ptr<Track> &pTrack)
{
if (!event.Button(wxMOUSE_BTN_LEFT))
return {};
@ -120,33 +119,34 @@ PanSliderHandle &PanSliderHandle::Instance()
return instance;
}
WaveTrack *PanSliderHandle::GetTrack()
std::shared_ptr<WaveTrack> PanSliderHandle::GetWaveTrack()
{
return static_cast<WaveTrack*>(mpTrack);
return std::static_pointer_cast<WaveTrack>(mpTrack.lock());
}
float PanSliderHandle::GetValue()
{
return GetTrack()->GetPan();
return GetWaveTrack()->GetPan();
}
UIHandle::Result PanSliderHandle::SetValue(AudacityProject *pProject, float newValue)
{
auto pTrack = GetWaveTrack();
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
bool panZero = false;
panZero = static_cast<WaveTrack*>(mpTrack)->SetPan(newValue);
#else
mpTrack->SetPan(newValue);
pTrack->SetPan(newValue);
#endif
// Assume linked track is wave or null
const auto link = static_cast<WaveTrack*>(mpTrack->GetLink());
const auto link = static_cast<WaveTrack*>(pTrack->GetLink());
if (link)
link->SetPan(newValue);
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->UpdatePan(GetTrack());
pMixerBoard->UpdatePan(pTrack.get());
using namespace RefreshCode;
Result result = RefreshNone;
@ -168,7 +168,7 @@ UIHandle::Result PanSliderHandle::CommitChanges
HitTestResult PanSliderHandle::HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack)
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
{
if (!event.Button(wxMOUSE_BTN_LEFT))
return {};

View File

@ -26,7 +26,7 @@ class GainSliderHandle final : public SliderHandle
virtual ~GainSliderHandle();
static GainSliderHandle& Instance();
WaveTrack *GetTrack();
std::shared_ptr<WaveTrack> GetWaveTrack();
protected:
float GetValue() override;
@ -40,7 +40,7 @@ protected:
public:
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack);
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
};
////////////////////////////////////////////////////////////////////////////////
@ -54,7 +54,7 @@ class PanSliderHandle final : public SliderHandle
virtual ~PanSliderHandle();
static PanSliderHandle& Instance();
WaveTrack *GetTrack();
std::shared_ptr<WaveTrack> GetWaveTrack();
protected:
float GetValue() override;
@ -67,7 +67,7 @@ protected:
public:
static HitTestResult HitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, Track *pTrack);
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
};
#endif

View File

@ -32,7 +32,7 @@ HitTestResult WaveTrack::DetailedHitTest
// If that toolbar were eliminated, this could simplify to a sequence of
// hit test routines describable by a table.
WaveTrack *const wavetrack = static_cast<WaveTrack*>(event.pCell);
const auto wavetrack = static_cast<WaveTrack*>(event.pCell.get());
bool isWaveform = (wavetrack->GetDisplay() == WaveTrack::Waveform);
if (bMultiTool && event.event.CmdDown())
@ -47,7 +47,7 @@ HitTestResult WaveTrack::DetailedHitTest
HitTestResult result;
if (NULL !=
(result = CutlineHandle::HitTest
(event.event, event.rect, pProject, this))
(event.event, event.rect, pProject, Pointer<WaveTrack>(this)))
.preview.cursor)
// This overriding test applies in all tools
return result;
@ -57,7 +57,7 @@ HitTestResult WaveTrack::DetailedHitTest
// The priority of these, in case more than one might apply at one
// point, seems arbitrary
if (NULL != (result = EnvelopeHandle::WaveTrackHitTest
(event.event, event.rect, pProject, *this))
(event.event, event.rect, pProject, Pointer<WaveTrack>(this)))
.preview.cursor)
;
else if (NULL != (result = TimeShiftHandle::HitTest
@ -66,7 +66,7 @@ HitTestResult WaveTrack::DetailedHitTest
// right in Multi only
;
else if (NULL != (result = SampleHandle::HitTest
(event.event, event.rect, pProject, this)).preview.cursor)
(event.event, event.rect, pProject, Pointer<WaveTrack>(this))).preview.cursor)
;
return result;
}

View File

@ -560,7 +560,7 @@ UIHandle::Result WaveTrackVZoomHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *)
{
mpTrack = std::static_pointer_cast<WaveTrack>(
static_cast<WaveTrackVRulerControls*>(evt.pCell)->FindTrack() );
static_cast<WaveTrackVRulerControls*>(evt.pCell.get())->FindTrack() );
mRect = evt.rect;
const wxMouseEvent &event = evt.event;

View File

@ -23,7 +23,7 @@ HitTestResult TimeTrack::DetailedHitTest
const AudacityProject *pProject, int, bool)
{
return EnvelopeHandle::TimeTrackHitTest
( event.event, event.rect, pProject, *this );
( event.event, event.rect, pProject, Pointer<TimeTrack>(this) );
}
std::shared_ptr<TrackControls> TimeTrack::GetControls()

View File

@ -39,7 +39,7 @@ UIHandle::Result ButtonHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *)
{
using namespace RefreshCode;
auto pTrack = static_cast<TrackControls*>(evt.pCell)->FindTrack();
auto pTrack = static_cast<TrackControls*>(evt.pCell.get())->FindTrack();
if ( !pTrack )
return Cancelled;

View File

@ -81,43 +81,43 @@ namespace {
HitTestResult EnvelopeHandle::TimeTrackHitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, TimeTrack &tt)
const AudacityProject *pProject, const std::shared_ptr<TimeTrack> &tt)
{
auto envelope = tt.GetEnvelope();
auto envelope = tt->GetEnvelope();
if (!envelope)
return {};
bool dB;
double dBRange;
float zoomMin, zoomMax;
GetTimeTrackData( *pProject, tt, dBRange, dB, zoomMin, zoomMax);
GetTimeTrackData( *pProject, *tt, dBRange, dB, zoomMin, zoomMax);
return EnvelopeHandle::HitEnvelope
(event, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange);
}
HitTestResult EnvelopeHandle::WaveTrackHitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, WaveTrack &wt)
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &wt)
{
/// method that tells us if the mouse event landed on an
/// envelope boundary.
const Envelope *const envelope = wt.GetEnvelopeAtX(event.GetX());
const Envelope *const envelope = wt->GetEnvelopeAtX(event.GetX());
if (!envelope)
return {};
const int displayType = wt.GetDisplay();
const int displayType = wt->GetDisplay();
// Not an envelope hit, unless we're using a type of wavetrack display
// suitable for envelopes operations, ie one of the Wave displays.
if (displayType != WaveTrack::Waveform)
return {}; // No envelope, not a hit, so return.
// Get envelope point, range 0.0 to 1.0
const bool dB = !wt.GetWaveformSettings().isLinear();
const bool dB = !wt->GetWaveformSettings().isLinear();
float zoomMin, zoomMax;
wt.GetDisplayBounds(&zoomMin, &zoomMax);
wt->GetDisplayBounds(&zoomMin, &zoomMax);
const float dBRange = wt.GetWaveformSettings().dBRange;
const float dBRange = wt->GetWaveformSettings().dBRange;
return EnvelopeHandle::HitEnvelope
(event, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange);
@ -184,7 +184,7 @@ UIHandle::Result EnvelopeHandle::Click
{
const wxMouseEvent &event = evt.event;
const ViewInfo &viewInfo = pProject->GetViewInfo();
Track *const pTrack = static_cast<Track*>(evt.pCell);
const auto pTrack = static_cast<Track*>(evt.pCell.get());
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();

View File

@ -42,10 +42,10 @@ public:
static HitTestResult HitAnywhere(const AudacityProject *pProject);
static HitTestResult TimeTrackHitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, TimeTrack &tt);
const AudacityProject *pProject, const std::shared_ptr<TimeTrack> &tt);
static HitTestResult WaveTrackHitTest
(const wxMouseEvent &event, const wxRect &rect,
const AudacityProject *pProject, WaveTrack &wt);
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &wt);
virtual ~EnvelopeHandle();

View File

@ -394,7 +394,8 @@ namespace
}
HitTestResult SelectHandle::HitTest
(const TrackPanelMouseEvent &evt, const AudacityProject *pProject, const Track *pTrack)
(const TrackPanelMouseEvent &evt, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack)
{
const wxMouseEvent &event = evt.event;
const wxRect &rect = evt.rect;
@ -429,7 +430,7 @@ HitTestResult SelectHandle::HitTest
// the preferences...
if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
{
MaySetOnDemandTip(pTrack, tip);
MaySetOnDemandTip(pTrack.get(), tip);
return { { tip, pCursor }, &Instance() };
}
@ -463,11 +464,11 @@ HitTestResult SelectHandle::HitTest
// choose boundaries only in snapping tolerance,
// and may choose center.
SelectionBoundary boundary =
ChooseBoundary(viewInfo, event, pTrack, rect, !bModifierDown, !bModifierDown);
ChooseBoundary(viewInfo, event, pTrack.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
MaySetOnDemandTip(pTrack, tip);
MaySetOnDemandTip(pTrack.get(), tip);
if (tip == "") {
const auto ttb = pProject->GetToolsToolBar();
@ -510,7 +511,7 @@ UIHandle::Result SelectHandle::Click
using namespace RefreshCode;
wxMouseEvent &event = evt.event;
Track *const pTrack = static_cast<Track*>(evt.pCell);
const auto pTrack = static_cast<Track*>(evt.pCell.get());
ViewInfo &viewInfo = pProject->GetViewInfo();
mMostRecentX = event.m_x;
@ -815,7 +816,7 @@ UIHandle::Result SelectHandle::Drag
}
if ( auto clickedTrack =
static_cast<CommonTrackPanelCell*>(evt.pCell)->FindTrack() ) {
static_cast<CommonTrackPanelCell*>(evt.pCell.get())->FindTrack() ) {
// Handle which tracks are selected
Track *sTrack = pTrack.get();
Track *eTrack = clickedTrack.get();
@ -1005,7 +1006,7 @@ void SelectHandle::OnTimer(wxCommandEvent &event)
// AS: For some reason, GCC won't let us pass this directly.
wxMouseEvent evt(wxEVT_MOTION);
const auto size = trackPanel->GetSize();
Drag(TrackPanelMouseEvent{ evt, mRect, size, pTrack.get() }, project);
Drag(TrackPanelMouseEvent{ evt, mRect, size, pTrack }, project);
mAutoScrolling = false;
mConnectedProject->GetTrackPanel()->Refresh(false);
}

View File

@ -40,7 +40,8 @@ public:
// This always hits, but details of the hit vary with mouse position and
// key state.
static HitTestResult HitTest
(const TrackPanelMouseEvent &event, const AudacityProject *pProject, const Track *pTrack);
(const TrackPanelMouseEvent &event, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack);
virtual ~SelectHandle();

View File

@ -84,7 +84,7 @@ UIHandle::Result SliderHandle::Release
result |= SetValue(pProject, newValue);
result |= CommitChanges(event, pProject);
mpTrack = nullptr;
mpTrack.reset();
return result;
}
@ -95,6 +95,6 @@ UIHandle::Result SliderHandle::Cancel(AudacityProject *pProject)
// Undo un-committed changes to project data:
auto result = SetValue(pProject, mStartingValue);
mpTrack = nullptr;
mpTrack.reset();
return RefreshCode::RefreshCell | result;
}

View File

@ -11,6 +11,7 @@ Paul Licameli
#ifndef __AUDACITY_SLIDER_HANDLE__
#define __AUDACITY_SLIDER_HANDLE__
#include "../../MemoryX.h"
#include "../../UIHandle.h"
#include <wx/gdicmn.h>
@ -55,13 +56,13 @@ protected:
Result Cancel(AudacityProject *pProject) override;
// Derived track is expected to set these two before Click():
Track *mpTrack {};
// Derived class is expected to set these two before Click():
std::weak_ptr<Track> mpTrack;
wxRect mRect{};
using SliderFn = LWSlider *(*)( AudacityProject*, const wxRect&, Track* );
SliderFn mSliderFn;
LWSlider *GetSlider( AudacityProject *pProject )
{ return mSliderFn( pProject, mRect, mpTrack ); }
{ return mSliderFn( pProject, mRect, mpTrack.lock().get() ); }
float mStartingValue {};
};

View File

@ -417,7 +417,7 @@ UIHandle::Result TimeShiftHandle::Click
const wxRect &rect = evt.rect;
const ViewInfo &viewInfo = pProject->GetViewInfo();
Track *const pTrack = static_cast<Track*>(evt.pCell);
const auto pTrack = std::static_pointer_cast<Track>(evt.pCell);
using namespace RefreshCode;
@ -441,7 +441,7 @@ UIHandle::Result TimeShiftHandle::Click
clickTime < viewInfo.selectedRegion.t1());
WaveTrack *wt = pTrack->GetKind() == Track::Wave
? static_cast<WaveTrack*>(pTrack) : nullptr;
? static_cast<WaveTrack*>(pTrack.get()) : nullptr;
if ((wt
#ifdef USE_MIDI
@ -497,24 +497,26 @@ UIHandle::Result TimeShiftHandle::Drag
ViewInfo &viewInfo = pProject->GetViewInfo();
// We may switch pTrack to its stereo partner below
Track *pTrack = dynamic_cast<Track*>(evt.pCell);
Track *track = dynamic_cast<Track*>(evt.pCell.get());
// Uncommenting this permits drag to continue to work even over the controls area
/*
pTrack = static_cast<CommonTrackPanelCell*>(evt.pCell)->FindTrack().get();
*/
if (!pTrack) {
if (!track) {
// Allow sliding if the pointer is not over any track, but only if x is
// within the bounds of the tracks area.
if (event.m_x >= mRect.GetX() &&
event.m_x < mRect.GetX() + mRect.GetWidth())
pTrack = mCapturedTrack;
track = mCapturedTrack.get();
}
auto pTrack = Track::Pointer( track );
if (!pTrack)
return RefreshCode::RefreshNone;
using namespace RefreshCode;
const bool unsafe = pProject->IsAudioActive();
if (unsafe) {
@ -571,7 +573,7 @@ UIHandle::Result TimeShiftHandle::Drag
double clipLeft = 0, clipRight = 0;
#ifdef USE_MIDI
if (pTrack->GetKind() == Track::Wave) {
WaveTrack *const mtw = static_cast<WaveTrack*>(pTrack);
WaveTrack *const mtw = static_cast<WaveTrack*>(pTrack.get());
const double rate = mtw->GetRate();
// set it to a sample point
desiredSlideAmount = rint(desiredSlideAmount * rate) / rate;
@ -614,9 +616,9 @@ UIHandle::Result TimeShiftHandle::Drag
double newClipRight = clipRight;
bool dummy1, dummy2;
mSnapManager->Snap(mCapturedTrack, clipLeft, false, &newClipLeft,
mSnapManager->Snap(mCapturedTrack.get(), clipLeft, false, &newClipLeft,
&dummy1, &dummy2);
mSnapManager->Snap(mCapturedTrack, clipRight, false, &newClipRight,
mSnapManager->Snap(mCapturedTrack.get(), clipRight, false, &newClipRight,
&dummy1, &dummy2);
// Only one of them is allowed to snap
@ -658,8 +660,8 @@ UIHandle::Result TimeShiftHandle::Drag
/* && !mCapturedClipIsSelection*/)
{
const int diff =
TrackPosition(*trackList, pTrack) -
TrackPosition(*trackList, mCapturedTrack);
TrackPosition(*trackList, pTrack.get()) -
TrackPosition(*trackList, mCapturedTrack.get());
for ( unsigned ii = 0, nn = mClipMoveState.capturedClipArray.size();
ii < nn; ++ii ) {
TrackClip &trackClip = mClipMoveState.capturedClipArray[ii];
@ -783,7 +785,7 @@ UIHandle::Result TimeShiftHandle::Release
Result result = RefreshNone;
mCapturedTrack = NULL;
mCapturedTrack.reset();
mSnapManager.reset(NULL);
mClipMoveState.capturedClipArray.clear();
@ -842,7 +844,7 @@ UIHandle::Result TimeShiftHandle::Release
UIHandle::Result TimeShiftHandle::Cancel(AudacityProject *pProject)
{
pProject->RollbackState();
mCapturedTrack = nullptr;
mCapturedTrack.reset();
mSnapManager.reset();
mClipMoveState.clear();
return RefreshCode::RefreshAll;

View File

@ -90,7 +90,7 @@ public:
bool StopsOnKeystroke() override { return true; }
private:
Track *mCapturedTrack{};
std::shared_ptr<Track> mCapturedTrack;
wxRect mRect{};
bool mDidSlideVertically{};

View File

@ -94,7 +94,7 @@ UIHandle::Result TrackSelectHandle::Click
if (!event.Button(wxMOUSE_BTN_LEFT))
return Cancelled;
TrackControls *const pControls = static_cast<TrackControls*>(evt.pCell);
const auto pControls = static_cast<TrackControls*>(evt.pCell.get());
const auto pTrack = pControls->FindTrack();
if (!pTrack)
return Cancelled;
@ -110,7 +110,7 @@ UIHandle::Result TrackSelectHandle::Click
result |= Cancelled;
else {
mRearrangeCount = 0;
mpTrack = pTrack.get();
mpTrack = pTrack;
CalculateRearrangingThresholds(event);
}
@ -137,18 +137,18 @@ UIHandle::Result TrackSelectHandle::Drag
MixerBoard* pMixerBoard = pProject->GetMixerBoard(); // Update mixer board, too.
if (event.m_y < mMoveUpThreshold || event.m_y < 0) {
tracks->MoveUp(mpTrack);
tracks->MoveUp(mpTrack.get());
--mRearrangeCount;
if (pMixerBoard)
if(auto pPlayable = dynamic_cast< const PlayableTrack* >( mpTrack ))
if(auto pPlayable = dynamic_cast< const PlayableTrack* >( mpTrack.get() ))
pMixerBoard->MoveTrackCluster(pPlayable, true /* up */);
}
else if ( event.m_y > mMoveDownThreshold
|| event.m_y > evt.whole.GetHeight() ) {
tracks->MoveDown(mpTrack);
tracks->MoveDown(mpTrack.get());
++mRearrangeCount;
if (pMixerBoard)
if(auto pPlayable = dynamic_cast< const PlayableTrack* >( mpTrack ))
if(auto pPlayable = dynamic_cast< const PlayableTrack* >( mpTrack.get() ))
pMixerBoard->MoveTrackCluster(pPlayable, false /* down */);
}
else
@ -215,15 +215,15 @@ void TrackSelectHandle::CalculateRearrangingThresholds(const wxMouseEvent & even
AudacityProject *const project = ::GetActiveProject();
TrackList *const tracks = project->GetTracks();
if (tracks->CanMoveUp(mpTrack))
if (tracks->CanMoveUp(mpTrack.get()))
mMoveUpThreshold =
event.m_y - tracks->GetGroupHeight(tracks->GetPrev(mpTrack, true));
event.m_y - tracks->GetGroupHeight(tracks->GetPrev(mpTrack.get(), true));
else
mMoveUpThreshold = INT_MIN;
if (tracks->CanMoveDown(mpTrack))
if (tracks->CanMoveDown(mpTrack.get()))
mMoveDownThreshold =
event.m_y + tracks->GetGroupHeight(tracks->GetNext(mpTrack, true));
event.m_y + tracks->GetGroupHeight(tracks->GetNext(mpTrack.get(), true));
else
mMoveDownThreshold = INT_MAX;
}

View File

@ -12,6 +12,7 @@ Paul Licameli split from TrackPanel.cpp
#define __AUDACITY_TRACK_SELECT_HANDLE__
#include "../../UIHandle.h"
#include "../../MemoryX.h"
class wxMouseEvent;
struct HitTestResult;
@ -49,7 +50,7 @@ public:
bool StopsOnKeystroke() override { return true; }
private:
Track *mpTrack {};
std::shared_ptr<Track> mpTrack;
// JH: if the user is dragging a track, at what y
// coordinate should the dragging track move up or down?

View File

@ -54,7 +54,7 @@ HitTestResult Track::HitTest
// Finally, default of all is adjustment of the selection box.
if ( !result.handle && ( isMultiTool || currentTool == selectTool) )
result = SelectHandle::HitTest(event, pProject, this);
result = SelectHandle::HitTest(event, pProject, Pointer(this));
return result;
}