1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-15 16:17:41 +02:00

Implement TAB key rotation among hit targets...

... The old effect of TAB -- to rotate the selected label, when a Label track
has focus -- is still available, but only when the pointer is not on a text
box or a label glyph.

Some of the cases where this might make a difference:

Alternate the note track stretch cursor, or label glyph, or text box, with
selection.

Rotate among envelope, draw, and selection in WaveTrack and multi tool.
This commit is contained in:
Paul Licameli 2017-07-12 13:22:28 -04:00
commit c1cd324848
30 changed files with 262 additions and 116 deletions

View File

@ -1386,7 +1386,7 @@ void AudacityProject::RedrawProject(const bool bForceWaveTracks /*= false*/)
void AudacityProject::RefreshCursor()
{
mTrackPanel->HandleCursorForLastMouseState();
mTrackPanel->HandleCursorForPresentMouseState();
}
void AudacityProject::SetSel0(double newSel0)

View File

@ -757,7 +757,7 @@ void TrackPanel::Uncapture(wxMouseEvent *pEvent)
{
if (HasCapture())
ReleaseMouse();
HandleMotion( pEvent );
HandleMotion( *pEvent );
}
void TrackPanel::CancelDragging()
@ -812,14 +812,9 @@ void TrackPanel::UpdateMouseState(const wxMouseState &state)
void TrackPanel::HandleModifierKey()
{
// Get the button and key states
auto state = ::wxGetMouseState();
// Remap the position
state.SetPosition(this->ScreenToClient(state.GetPosition()));
UpdateMouseState(state);
HandleCursorForLastMouseState();
HandleCursorForPresentMouseState();
}
void TrackPanel::HandlePageUpKey()
{
mListener->TP_ScrollWindow(2 * mViewInfo->h - GetScreenEndTime());
@ -830,12 +825,19 @@ void TrackPanel::HandlePageDownKey()
mListener->TP_ScrollWindow(GetScreenEndTime());
}
void TrackPanel::HandleCursorForLastMouseState()
void TrackPanel::HandleCursorForPresentMouseState(bool doHit)
{
// Come here on modifier key or mouse button transitions,
// or on starting or stopping of play or record,
// or change of toolbar button,
// and change the cursor appropriately.
HandleMotion( &mLastMouseState );
// Get the button and key states
auto state = ::wxGetMouseState();
// Remap the position
state.SetPosition(this->ScreenToClient(state.GetPosition()));
HandleMotion( state, doHit );
}
bool TrackPanel::IsAudioActive()
@ -852,45 +854,51 @@ bool TrackPanel::IsAudioActive()
/// may cause the appropriate cursor and message to change.
/// As this procedure checks which region the mouse is over, it is
/// appropriate to establish the message in the status bar.
void TrackPanel::HandleMotion( wxMouseState *pState )
void TrackPanel::HandleMotion( wxMouseState &inState, bool doHit )
{
wxMouseState dummy;
if (!pState)
pState = &dummy;
else
UpdateMouseState( *pState ), pState = &mLastMouseState;
auto &state = *pState;
UpdateMouseState( inState );
const auto foundCell = FindCell( state.m_x, state.m_y );
const auto foundCell = FindCell( inState.m_x, inState.m_y );
auto &track = foundCell.pTrack;
auto &rect = foundCell.rect;
auto &pCell = foundCell.pCell;
const TrackPanelMouseState tpmState{ state, rect, pCell };
HandleMotion( tpmState );
const TrackPanelMouseState tpmState{ mLastMouseState, rect, pCell };
HandleMotion( tpmState, doHit );
}
void TrackPanel::HandleMotion( const TrackPanelMouseState &tpmState )
void TrackPanel::HandleMotion
( const TrackPanelMouseState &tpmState, bool doHit )
{
auto handle = mUIHandle;
auto oldHandle = mLastHitTest;
auto oldCell = mLastCell.lock();
auto newCell = tpmState.pCell;
std::shared_ptr<Track> newTrack;
if ( newCell )
newTrack = static_cast<CommonTrackPanelCell*>( newCell.get() )->FindTrack();
std::shared_ptr<Track> oldTrack;
if ( oldCell )
oldTrack = static_cast<CommonTrackPanelCell*>( oldCell.get() )->FindTrack();
newTrack = static_cast<CommonTrackPanelCell*>( newCell.get() )->
FindTrack();
wxString tip{};
wxCursor *pCursor{};
unsigned refreshCode = 0;
if ( !mUIHandle ) {
if ( ! doHit ) {
// Dragging or not
handle = Target();
// Assume cell does not change but target does
refreshCode = mMouseOverUpdateFlags;
mMouseOverUpdateFlags = 0;
}
else if ( !mUIHandle ) {
// Not yet dragging.
auto oldCell = mLastCell.lock();
std::shared_ptr<Track> oldTrack;
if ( oldCell )
oldTrack = static_cast<CommonTrackPanelCell*>( oldCell.get() )->
FindTrack();
unsigned updateFlags = mMouseOverUpdateFlags;
// First check whether crossing cell to cell
@ -906,19 +914,32 @@ void TrackPanel::HandleMotion( const TrackPanelMouseState &tpmState )
}
}
auto oldHandle = Target();
// Now do the
// UIHANDLE HIT TEST !
auto targets = newCell->HitTest(tpmState, GetProject());
mTargets = newCell->HitTest(tpmState, GetProject());
// No use, yet, of any but the first target
handle = targets.empty() ? UIHandlePtr{} : targets[0];
mTarget = 0;
// Find the old target's new place if we can
if (oldHandle) {
auto begin = mTargets.begin(), end = mTargets.end(),
iter = std::find(begin, end, oldHandle);
if (iter != end)
mTarget = iter - begin;
}
handle = Target();
mLastCell = newCell;
mLastHitTest = handle;
if (!oldCell && oldHandle != handle)
// Did not move cell to cell, but did change the target
refreshCode = updateFlags;
if (handle)
handle->Enter();
}
// UIHANDLE PREVIEW
@ -944,6 +965,21 @@ void TrackPanel::HandleMotion( const TrackPanelMouseState &tpmState )
this, GetRuler(), newTrack.get(), newTrack.get(), refreshCode);
}
bool TrackPanel::HasRotation() const
{
// Is there a nontrivial TAB key rotation?
return !mUIHandle && mTargets.size() > 1;
}
void TrackPanel::RotateTarget()
{
auto size = mTargets.size();
if (size > 1) {
mTarget = (mTarget + 1) % size;
Target()->Enter();
}
}
void TrackPanel::UpdateSelectionDisplay()
{
// Full refresh since the label area may need to indicate
@ -1036,7 +1072,7 @@ void TrackPanel::OnPlayback(wxCommandEvent &e)
// Starting or stopping of play or record affects some cursors.
// Start or stop is in progress now, not completed; so delay the cursor
// change until next idle time.
CallAfter( [this] { HandleCursorForLastMouseState(); } );
CallAfter( [this] { HandleCursorForPresentMouseState(); } );
}
// The tracks positions within the list have changed, so update the vertical
@ -1292,13 +1328,20 @@ void TrackPanel::HandleWheelRotation( TrackPanelMouseEvent &tpmEvent )
this, mRuler, pTrack.get(), pTrack.get(), result);
}
/// Filter captured keys typed into LabelTracks.
void TrackPanel::OnCaptureKey(wxCommandEvent & event)
{
wxKeyEvent *kevent = static_cast<wxKeyEvent *>(event.GetEventObject());
if ( WXK_ESCAPE != kevent->GetKeyCode() )
const auto code = kevent->GetKeyCode();
if ( WXK_ESCAPE != code )
HandleInterruptedDrag();
if ( WXK_TAB == code && HasRotation() ) {
// Override what the cell might do, don't call its CaptureKey;
// Also override TAB navigation in wxWidgets, by not skipping
event.Skip(false);
return;
}
Track * const t = GetFocusedTrack();
if (t) {
const unsigned refreshResult =
@ -1340,6 +1383,15 @@ void TrackPanel::OnKeyDown(wxKeyEvent & event)
case WXK_PAGEDOWN:
HandlePageDownKey();
return;
case WXK_TAB:
if ( HasRotation() ) {
RotateTarget();
HandleCursorForPresentMouseState(false);
return;
}
else
break;
}
Track *const t = GetFocusedTrack();
@ -1554,7 +1606,7 @@ try
// consider it not a drag, even if button is down during motion, if
// mUIHandle is null, as it becomes during interrupted drag
// (e.g. by hitting space to play while dragging an envelope point)
HandleMotion( &event );
HandleMotion( event );
else if ( event.ButtonDown() || event.ButtonDClick() )
HandleClick( tpmEvent );

View File

@ -334,7 +334,7 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
Track *GetFocusedTrack();
void SetFocusedTrack(Track *t);
void HandleCursorForLastMouseState();
void HandleCursorForPresentMouseState(bool doHit = true);
void UpdateVRulers();
void UpdateVRuler(Track *t);
@ -377,8 +377,9 @@ protected:
};
FoundCell FindCell(int mouseX, int mouseY);
void HandleMotion( wxMouseState *pState );
void HandleMotion( const TrackPanelMouseState &tpmState );
void HandleMotion( wxMouseState &state, bool doHit = true );
void HandleMotion
( const TrackPanelMouseState &tpmState, bool doHit = true );
// If label, rectangle includes track control panel only.
// If !label, rectangle includes all of that, and the vertical ruler, and
@ -524,13 +525,17 @@ protected:
protected:
std::weak_ptr<TrackPanelCell> mLastCell;
UIHandlePtr mLastHitTest;
std::vector<UIHandlePtr> mTargets;
size_t mTarget {};
unsigned mMouseOverUpdateFlags{};
public:
UIHandlePtr Target()
{
return mLastHitTest;
if (mTargets.size())
return mTargets[mTarget];
else
return {};
}
protected:
@ -539,10 +544,15 @@ protected:
// Forget the rotation of hit test candidates when the mouse moves from
// cell to cell or outside of the TrackPanel entirely.
mLastCell.reset();
mLastHitTest = {};
mTargets.clear();
mTarget = 0;
mMouseOverUpdateFlags = 0;
}
bool HasRotation() const;
void RotateTarget();
std::weak_ptr<Track> mpClickedTrack;
UIHandlePtr mUIHandle;

View File

@ -15,6 +15,10 @@ UIHandle::~UIHandle()
{
}
void UIHandle::Enter()
{
}
void UIHandle::DrawExtras
(DrawingPass, wxDC *, const wxRegion &, const wxRect &)
{

View File

@ -47,6 +47,10 @@ public:
virtual ~UIHandle() = 0;
// Before clicking, the handle is notified that it has been "hit"
// Default does nothing.
virtual void Enter();
// Assume hit test (implemented in other classes) was positive.
// May return Cancelled, overriding the hit test decision and stopping drag.
// Otherwise the framework will later call Release or Cancel after

View File

@ -29,6 +29,10 @@ LabelGlyphHandle::LabelGlyphHandle
: mpLT{ pLT }
, mRect{ rect }
, mHit{ hit }
{
}
void LabelGlyphHandle::Enter()
{
mChangeHighlight = RefreshCode::RefreshCell;
}

View File

@ -54,6 +54,8 @@ public:
virtual ~LabelGlyphHandle();
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -24,6 +24,10 @@ LabelTextHandle::LabelTextHandle
: mpLT{ pLT }
, mLabelNum{ labelNum }
{
}
void LabelTextHandle::Enter()
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
mChangeHighlight = RefreshCode::RefreshCell;
#endif

View File

@ -38,6 +38,8 @@ public:
std::shared_ptr<LabelTrack> GetTrack() const { return mpLT.lock(); }
int GetLabelNum() const { return mLabelNum; }
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -24,6 +24,10 @@ NoteTrackButtonHandle::NoteTrackButtonHandle
: mpTrack{ pTrack }
, mChannel{ channel }
, mRect{ rect }
{
}
void NoteTrackButtonHandle::Enter()
{
mChangeHighlight = RefreshCode::RefreshCell;
}

View File

@ -47,6 +47,8 @@ public:
const NoteTrackButtonHandle &newState);
protected:
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -40,6 +40,10 @@ NoteTrackVZoomHandle::NoteTrackVZoomHandle
: mZoomStart(y), mZoomEnd(y), mRect(rect)
, mpTrack{ pTrack }
{
}
void NoteTrackVZoomHandle::Enter()
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
mChangeHighlight = RefreshCode::RefreshCell;
#endif

View File

@ -38,6 +38,8 @@ public:
std::shared_ptr<NoteTrack> GetTrack() const { return mpTrack.lock(); }
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -71,20 +71,21 @@ public:
virtual ~StretchHandle();
virtual Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject);
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
virtual Result Drag
(const TrackPanelMouseEvent &event, AudacityProject *pProject);
Result Drag
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
virtual HitTestPreview Preview
(const TrackPanelMouseState &state, const AudacityProject *pProject);
HitTestPreview Preview
(const TrackPanelMouseState &state, const AudacityProject *pProject)
override;
virtual Result Release
Result Release
(const TrackPanelMouseEvent &event, AudacityProject *pProject,
wxWindow *pParent);
wxWindow *pParent) override;
virtual Result Cancel(AudacityProject *pProject);
Result Cancel(AudacityProject *pProject) override;
bool StopsOnKeystroke() override { return true; }

View File

@ -28,6 +28,10 @@ CutlineHandle::CutlineHandle
: mpTrack{ pTrack }
, mLocation{ location }
{
}
void CutlineHandle::Enter()
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
mChangeHighlight = RefreshCode::RefreshCell;
#endif

View File

@ -45,6 +45,8 @@ public:
const WaveTrackLocation &GetLocation() { return mLocation; }
std::shared_ptr<WaveTrack> GetTrack() { return mpTrack; }
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -38,6 +38,10 @@ static const double SMOOTHING_PROPORTION_MIN = 0.0;
SampleHandle::SampleHandle( const std::shared_ptr<WaveTrack> &pTrack )
: mClickedTrack{ pTrack }
{
}
void SampleHandle::Enter()
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
mChangeHighlight = RefreshCode::RefreshCell;
#endif

View File

@ -46,6 +46,8 @@ public:
std::shared_ptr<WaveTrack> GetTrack() const { return mClickedTrack; }
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -49,6 +49,10 @@ WaveTrackVZoomHandle::WaveTrackVZoomHandle
: mZoomStart(y), mZoomEnd(y), mRect(rect)
, mpTrack{ pTrack }
{
}
void WaveTrackVZoomHandle::Enter()
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
mChangeHighlight = RefreshCode::RefreshCell;
#endif

View File

@ -38,6 +38,8 @@ public:
std::shared_ptr<WaveTrack> GetTrack() const { return mpTrack.lock(); }
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -25,13 +25,17 @@ ButtonHandle::ButtonHandle
: mpTrack{ pTrack }
, mRect{ rect }
{
mChangeHighlight = RefreshCode::RefreshCell;
}
ButtonHandle::~ButtonHandle()
{
}
void ButtonHandle::Enter()
{
mChangeHighlight = RefreshCode::RefreshCell;
}
UIHandle::Result ButtonHandle::Click
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
{

View File

@ -42,6 +42,8 @@ protected:
virtual Result CommitChanges
(const wxMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) = 0;
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -30,6 +30,10 @@ Paul Licameli split from TrackPanel.cpp
EnvelopeHandle::EnvelopeHandle( Envelope *pEnvelope )
: mEnvelope{ pEnvelope }
{
}
void EnvelopeHandle::Enter()
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
mChangeHighlight = RefreshCode::RefreshCell;
#endif

View File

@ -56,6 +56,8 @@ public:
Envelope *GetEnvelope() const { return mEnvelope; }
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

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,35 +40,35 @@ public:
const TrackPanelMouseState &state, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack);
SelectHandle &operator=(const SelectHandle&) = default;
virtual ~SelectHandle();
bool IsClicked() const;
virtual Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject);
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
virtual Result Drag
(const TrackPanelMouseEvent &event, AudacityProject *pProject);
Result Drag
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
virtual HitTestPreview Preview
(const TrackPanelMouseState &state, const AudacityProject *pProject);
HitTestPreview Preview
(const TrackPanelMouseState &state, const AudacityProject *pProject)
override;
virtual Result Release
Result Release
(const TrackPanelMouseEvent &event, AudacityProject *pProject,
wxWindow *pParent);
wxWindow *pParent) override;
virtual Result Cancel(AudacityProject*);
Result Cancel(AudacityProject*) override;
virtual void DrawExtras
void DrawExtras
(DrawingPass pass,
wxDC * dc, const wxRegion &updateRegion, const wxRect &panelRect);
// Receives timer event notifications, to implement auto-scroll
void OnTimer(wxCommandEvent &event);
wxDC * dc, const wxRegion &updateRegion, const wxRect &panelRect)
override;
private:
void Connect(AudacityProject *pProject);
void Disconnect();
void StartSelection
(AudacityProject *pProject, int mouseXCoordinate, int trackLeftEdge);
@ -115,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 };
@ -143,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

View File

@ -21,6 +21,10 @@ SliderHandle::SliderHandle
: mSliderFn{ sliderFn }
, mRect{ rect }
, mpTrack{ pTrack }
{
}
void SliderHandle::Enter()
{
mChangeHighlight = RefreshCode::RefreshCell;
}

View File

@ -47,6 +47,8 @@ protected:
virtual Result CommitChanges
(const wxMouseEvent &event, AudacityProject *pProject) = 0;
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;

View File

@ -29,6 +29,10 @@ TimeShiftHandle::TimeShiftHandle
: mCapturedTrack{ pTrack }
, mGripHit{ gripHit }
{
}
void TimeShiftHandle::Enter()
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
mChangeHighlight = RefreshCode::RefreshCell;
#endif

View File

@ -75,6 +75,8 @@ public:
virtual ~TimeShiftHandle();
void Enter() override;
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;