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

View File

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