1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-16 08:34:10 +02:00

Reuse SelectHandle object during movement, as with other handle types

This commit is contained in:
Paul Licameli 2017-07-12 12:54:11 -04:00
parent d148c39c2d
commit 308d89b0e6
2 changed files with 58 additions and 51 deletions

View File

@ -32,6 +32,8 @@ Paul Licameli split from TrackPanel.cpp
#include "../../toolbars/ToolsToolBar.h" #include "../../toolbars/ToolsToolBar.h"
#include "../../../images/Cursors.h" #include "../../../images/Cursors.h"
#include <wx/event.h>
// Only for definition of SonifyBeginModifyState: // Only for definition of SonifyBeginModifyState:
//#include "../../NoteTrack.h" //#include "../../NoteTrack.h"
@ -423,21 +425,21 @@ UIHandlePtr SelectHandle::HitTest
const TrackPanelMouseState &st, const AudacityProject *pProject, const TrackPanelMouseState &st, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack) const std::shared_ptr<Track> &pTrack)
{ {
// This handle is a little special, not following the pattern of calling // This handle is a little special because there may be some state to
// AssignUIHandlePtr(); there may be some state to preserve during movement // preserve during movement before the click.
// before the click.
auto old = holder.lock(); auto old = holder.lock();
std::unique_ptr<SnapManager> oldSnapManager; std::shared_ptr<SnapManager> oldSnapManager;
wxInt64 oldSnapLeft = -1, oldSnapRight = -1; wxInt64 oldSnapLeft = -1, oldSnapRight = -1;
if (old) { if (old) {
// It should not have started listening to timer events // It should not have started listening to timer events
wxASSERT( !old->mConnectedProject ); wxASSERT( !old->mTimerHandler );
oldSnapManager = std::move(old->mSnapManager); oldSnapManager = std::move(old->mSnapManager);
oldSnapLeft = old->mSnapLeft; oldSnapLeft = old->mSnapLeft;
oldSnapRight = old->mSnapRight; oldSnapRight = old->mSnapRight;
} }
auto result = std::make_shared<SelectHandle>( pTrack ); auto result = std::make_shared<SelectHandle>( pTrack );
result = AssignUIHandlePtr(holder, result);
// Copy the pre-dragging state // Copy the pre-dragging state
result->mSnapManager = std::move( oldSnapManager ); result->mSnapManager = std::move( oldSnapManager );
@ -561,14 +563,14 @@ UIHandle::Result SelectHandle::Click
mInitialSelection = viewInfo.selectedRegion; mInitialSelection = viewInfo.selectedRegion;
TrackList *const trackList = pProject->GetTracks(); TrackList *const trackList = pProject->GetTracks();
mSelectionStateChanger = std::make_unique< SelectionStateChanger > mSelectionStateChanger = std::make_shared< SelectionStateChanger >
( selectionState, *trackList ); ( selectionState, *trackList );
mSelectionBoundary = 0; mSelectionBoundary = 0;
if (!mSnapManager) { if (!mSnapManager) {
// We create a NEW snap manager in case any snap-points have changed // We create a NEW snap manager in case any snap-points have changed
mSnapManager = std::make_unique<SnapManager>(trackList, &viewInfo); mSnapManager = std::make_shared<SnapManager>(trackList, &viewInfo);
mSnapLeft = -1; mSnapLeft = -1;
mSnapRight = -1; mSnapRight = -1;
} }
@ -954,7 +956,6 @@ UIHandle::Result SelectHandle::Release
wxWindow *) wxWindow *)
{ {
using namespace RefreshCode; using namespace RefreshCode;
Disconnect();
pProject->ModifyState(false); pProject->ModifyState(false);
mFrequencySnapper.reset(); mFrequencySnapper.reset();
mSnapManager.reset(); mSnapManager.reset();
@ -971,8 +972,6 @@ UIHandle::Result SelectHandle::Release
UIHandle::Result SelectHandle::Cancel(AudacityProject *pProject) UIHandle::Result SelectHandle::Cancel(AudacityProject *pProject)
{ {
Disconnect();
mSelectionStateChanger.reset(); mSelectionStateChanger.reset();
pProject->GetViewInfo().selectedRegion = mInitialSelection; pProject->GetViewInfo().selectedRegion = mInitialSelection;
@ -995,31 +994,41 @@ void SelectHandle::DrawExtras
void SelectHandle::Connect(AudacityProject *pProject) void SelectHandle::Connect(AudacityProject *pProject)
{ {
mConnectedProject = pProject; mTimerHandler = std::make_shared<TimerHandler>( this, pProject );
mConnectedProject->Connect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(SelectHandle::OnTimer),
NULL,
this);
} }
void SelectHandle::Disconnect() class SelectHandle::TimerHandler : public wxEvtHandler
{ {
public:
TimerHandler( SelectHandle *pParent, AudacityProject *pProject )
: mParent{ pParent }
, mConnectedProject{ pProject }
{
if (mConnectedProject)
mConnectedProject->Connect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(SelectHandle::TimerHandler::OnTimer),
NULL,
this);
}
~TimerHandler()
{
if (mConnectedProject) if (mConnectedProject)
mConnectedProject->Disconnect(EVT_TRACK_PANEL_TIMER, mConnectedProject->Disconnect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(SelectHandle::OnTimer), wxCommandEventHandler(SelectHandle::TimerHandler::OnTimer),
NULL, NULL,
this); this);
mConnectedProject = NULL; }
mpTrack.reset(); // Receives timer event notifications, to implement auto-scroll
mFreqSelTrack.reset(); void OnTimer(wxCommandEvent &event);
mSnapManager.reset(NULL); private:
SelectHandle *mParent;
AudacityProject *mConnectedProject;
};
mFreqSelMode = FREQ_SEL_INVALID; void SelectHandle::TimerHandler::OnTimer(wxCommandEvent &event)
}
void SelectHandle::OnTimer(wxCommandEvent &event)
{ {
event.Skip(); event.Skip();
@ -1042,12 +1051,12 @@ void SelectHandle::OnTimer(wxCommandEvent &event)
const auto project = mConnectedProject; const auto project = mConnectedProject;
const auto trackPanel = project->GetTrackPanel(); const auto trackPanel = project->GetTrackPanel();
if (mMostRecentX >= mRect.x + mRect.width) { if (mParent->mMostRecentX >= mParent->mRect.x + mParent->mRect.width) {
mAutoScrolling = true; mParent->mAutoScrolling = true;
project->TP_ScrollRight(); project->TP_ScrollRight();
} }
else if (mMostRecentX < mRect.x) { else if (mParent->mMostRecentX < mParent->mRect.x) {
mAutoScrolling = true; mParent->mAutoScrolling = true;
project->TP_ScrollLeft(); project->TP_ScrollLeft();
} }
else { else {
@ -1055,24 +1064,24 @@ void SelectHandle::OnTimer(wxCommandEvent &event)
// extreme x coordinate of the screen, even if that is still within the // extreme x coordinate of the screen, even if that is still within the
// track area. // track area.
int xx = mMostRecentX, yy = 0; int xx = mParent->mMostRecentX, yy = 0;
trackPanel->ClientToScreen(&xx, &yy); trackPanel->ClientToScreen(&xx, &yy);
if (xx == 0) { if (xx == 0) {
mAutoScrolling = true; mParent->mAutoScrolling = true;
project->TP_ScrollLeft(); project->TP_ScrollLeft();
} }
else { else {
int width, height; int width, height;
::wxDisplaySize(&width, &height); ::wxDisplaySize(&width, &height);
if (xx == width - 1) { if (xx == width - 1) {
mAutoScrolling = true; mParent->mAutoScrolling = true;
project->TP_ScrollRight(); project->TP_ScrollRight();
} }
} }
} }
auto pTrack = mpTrack.lock(); // TrackList::Lock() ? auto pTrack = mParent->mpTrack.lock(); // TrackList::Lock() ?
if (mAutoScrolling && pTrack) { if (mParent->mAutoScrolling && pTrack) {
// AS: To keep the selection working properly as we scroll, // AS: To keep the selection working properly as we scroll,
// we fake a mouse event (remember, this method is called // we fake a mouse event (remember, this method is called
// from a timer tick). // from a timer tick).
@ -1080,8 +1089,8 @@ void SelectHandle::OnTimer(wxCommandEvent &event)
// AS: For some reason, GCC won't let us pass this directly. // AS: For some reason, GCC won't let us pass this directly.
wxMouseEvent evt(wxEVT_MOTION); wxMouseEvent evt(wxEVT_MOTION);
const auto size = trackPanel->GetSize(); const auto size = trackPanel->GetSize();
Drag(TrackPanelMouseEvent{ evt, mRect, size, pTrack }, project); mParent->Drag(TrackPanelMouseEvent{ evt, mParent->mRect, size, pTrack }, project);
mAutoScrolling = false; mParent->mAutoScrolling = false;
mConnectedProject->GetTrackPanel()->Refresh(false); mConnectedProject->GetTrackPanel()->Refresh(false);
} }
} }
@ -1304,7 +1313,7 @@ void SelectHandle::HandleCenterFrequencyClick
mFreqSelMode = FREQ_SEL_SNAPPING_CENTER; mFreqSelMode = FREQ_SEL_SNAPPING_CENTER;
// Disable time selection // Disable time selection
mSelStartValid = false; mSelStartValid = false;
mFrequencySnapper = std::make_unique<SpectrumAnalyst>(); mFrequencySnapper = std::make_shared<SpectrumAnalyst>();
StartSnappingFreqSelection(*mFrequencySnapper, viewInfo, pTrack); StartSnappingFreqSelection(*mFrequencySnapper, viewInfo, pTrack);
#endif #endif
} }

View File

@ -17,7 +17,6 @@ Paul Licameli split from TrackPanel.cpp
#include "../../MemoryX.h" #include "../../MemoryX.h"
#include <vector> #include <vector>
#include <wx/event.h>
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
class SelectionStateChanger; class SelectionStateChanger;
@ -27,10 +26,9 @@ class Track;
class ViewInfo; class ViewInfo;
class WaveTrack; class WaveTrack;
class SelectHandle : public wxEvtHandler, public UIHandle class SelectHandle : public UIHandle
{ {
SelectHandle(const SelectHandle&); SelectHandle(const SelectHandle&);
SelectHandle &operator=(const SelectHandle&);
public: public:
explicit SelectHandle( const std::shared_ptr<Track> &pTrack ); explicit SelectHandle( const std::shared_ptr<Track> &pTrack );
@ -42,6 +40,8 @@ public:
const TrackPanelMouseState &state, const AudacityProject *pProject, const TrackPanelMouseState &state, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack); const std::shared_ptr<Track> &pTrack);
SelectHandle &operator=(const SelectHandle&) = default;
virtual ~SelectHandle(); virtual ~SelectHandle();
bool IsClicked() const; bool IsClicked() const;
@ -67,12 +67,8 @@ public:
wxDC * dc, const wxRegion &updateRegion, const wxRect &panelRect) wxDC * dc, const wxRegion &updateRegion, const wxRect &panelRect)
override; override;
// Receives timer event notifications, to implement auto-scroll
void OnTimer(wxCommandEvent &event);
private: private:
void Connect(AudacityProject *pProject); void Connect(AudacityProject *pProject);
void Disconnect();
void StartSelection void StartSelection
(AudacityProject *pProject, int mouseXCoordinate, int trackLeftEdge); (AudacityProject *pProject, int mouseXCoordinate, int trackLeftEdge);
@ -117,7 +113,7 @@ private:
// line up with existing tracks or labels. mSnapLeft and mSnapRight // line up with existing tracks or labels. mSnapLeft and mSnapRight
// are the horizontal index of pixels to display user feedback // are the horizontal index of pixels to display user feedback
// guidelines so the user knows when such snapping is taking place. // guidelines so the user knows when such snapping is taking place.
std::unique_ptr<SnapManager> mSnapManager; std::shared_ptr<SnapManager> mSnapManager;
wxInt64 mSnapLeft{ -1 }; wxInt64 mSnapLeft{ -1 };
wxInt64 mSnapRight{ -1 }; wxInt64 mSnapRight{ -1 };
@ -145,14 +141,16 @@ private:
// FREQ_SEL_BOTTOM_FREE, // FREQ_SEL_BOTTOM_FREE,
// and is ignored otherwise. // and is ignored otherwise.
double mFreqSelPin{ -1.0 }; double mFreqSelPin{ -1.0 };
std::unique_ptr<SpectrumAnalyst> mFrequencySnapper; std::shared_ptr<SpectrumAnalyst> mFrequencySnapper;
int mMostRecentX{ -1 }, mMostRecentY{ -1 }; int mMostRecentX{ -1 }, mMostRecentY{ -1 };
bool mAutoScrolling{}; bool mAutoScrolling{};
AudacityProject *mConnectedProject{}; std::shared_ptr<SelectionStateChanger> mSelectionStateChanger;
std::unique_ptr<SelectionStateChanger> mSelectionStateChanger; class TimerHandler;
friend TimerHandler;
std::shared_ptr<TimerHandler> mTimerHandler;
}; };
#endif #endif