1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-25 00:30:07 +02:00

Redo hit test priorities in TrackPanel...

Zoom tool takes precedence;

Otherwise do special hits appropriate to the track subclass -- and only
WaveTrack here uses Tools toolbar state, and now disallows clicks on things
when they are not drawn because the view is spectrogram;

Finally, default to right button zooming in Multi tool, or to time shift in
that tool, or to selection adjustment in Multi or in Select tool.
This commit is contained in:
Paul Licameli 2017-06-19 15:02:45 -04:00
parent 9e0010ec5f
commit bce3571372
10 changed files with 109 additions and 118 deletions

View File

@ -121,9 +121,10 @@ class AUDACITY_DLL_API LabelTrack final : public Track
virtual ~ LabelTrack(); virtual ~ LabelTrack();
HitTestResult HitTest HitTestResult DetailedHitTest
(const TrackPanelMouseEvent &event, (const TrackPanelMouseEvent &event,
const AudacityProject *pProject) override; const AudacityProject *pProject, int currentTool, bool bMultiTool)
override;
bool DoCaptureKey(wxKeyEvent &event); bool DoCaptureKey(wxKeyEvent &event);
unsigned CaptureKey unsigned CaptureKey

View File

@ -68,9 +68,10 @@ class AUDACITY_DLL_API NoteTrack final
NoteTrack(const std::shared_ptr<DirManager> &projDirManager); NoteTrack(const std::shared_ptr<DirManager> &projDirManager);
virtual ~NoteTrack(); virtual ~NoteTrack();
HitTestResult HitTest HitTestResult DetailedHitTest
(const TrackPanelMouseEvent &event, (const TrackPanelMouseEvent &event,
const AudacityProject *pProject) override; const AudacityProject *pProject, int currentTool, bool bMultiTool)
override;
using Holder = std::unique_ptr<NoteTrack>; using Holder = std::unique_ptr<NoteTrack>;
Track::Holder Duplicate() const override; Track::Holder Duplicate() const override;

View File

@ -49,9 +49,10 @@ class TimeTrack final : public Track {
void Silence(double t0, double t1) override; void Silence(double t0, double t1) override;
void InsertSilence(double t, double len) override; void InsertSilence(double t, double len) override;
HitTestResult HitTest HitTestResult DetailedHitTest
(const TrackPanelMouseEvent &event, (const TrackPanelMouseEvent &event,
const AudacityProject *pProject) override; const AudacityProject *pProject, int currentTool, bool bMultiTool)
override;
// Identifying the type of track // Identifying the type of track
int GetKind() const override { return Time; } int GetKind() const override { return Time; }

View File

@ -108,7 +108,6 @@ class AUDACITY_DLL_API Track /* not final */
bool mMinimized; bool mMinimized;
public: public:
mutable wxSize vrulerSize;
// Given a bare pointer, find a shared_ptr. But this is not possible for // Given a bare pointer, find a shared_ptr. But this is not possible for
// a track not owned by any list, so the result can be null. // a track not owned by any list, so the result can be null.
@ -131,11 +130,22 @@ class AUDACITY_DLL_API Track /* not final */
return {}; return {};
} }
// An implementation is defined for call-through from subclasses, but // Cause certain overriding tool modes (Zoom; future ones?) to behave
// the inherited method is still marked pure virtual // uniformly in all tracks, disregarding track contents.
// Do not further override this...
HitTestResult HitTest HitTestResult HitTest
(const TrackPanelMouseEvent &, const AudacityProject *pProject) (const TrackPanelMouseEvent &, const AudacityProject *pProject)
override = 0; final;
public:
// Rather override this for subclasses:
virtual HitTestResult DetailedHitTest
(const TrackPanelMouseEvent &,
const AudacityProject *pProject, int currentTool, bool bMultiTool)
= 0;
mutable wxSize vrulerSize;
// Return another, associated TrackPanelCell object that implements the // Return another, associated TrackPanelCell object that implements the
// drop-down, close and minimize buttons, etc. // drop-down, close and minimize buttons, etc.

View File

@ -103,9 +103,10 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
virtual ~WaveTrack(); virtual ~WaveTrack();
HitTestResult HitTest HitTestResult DetailedHitTest
(const TrackPanelMouseEvent &event, (const TrackPanelMouseEvent &event,
const AudacityProject *pProject) override; const AudacityProject *pProject, int currentTool, bool bMultiTool)
override;
double GetOffset() const override; double GetOffset() const override;
void SetOffset(double o) override; void SetOffset(double o) override;

View File

@ -20,11 +20,10 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../HitTestResult.h" #include "../../../HitTestResult.h"
#include "../../../Project.h" #include "../../../Project.h"
#include "../../../TrackPanelMouseEvent.h" #include "../../../TrackPanelMouseEvent.h"
#include "../../../toolbars/ToolsToolBar.h"
HitTestResult LabelTrack::HitTest HitTestResult LabelTrack::DetailedHitTest
(const TrackPanelMouseEvent &evt, (const TrackPanelMouseEvent &evt,
const AudacityProject *pProject) const AudacityProject *pProject, int, bool)
{ {
HitTestResult result; HitTestResult result;
const wxMouseEvent &event = evt.event; const wxMouseEvent &event = evt.event;
@ -36,16 +35,6 @@ HitTestResult LabelTrack::HitTest
// Missed glyph, try text box // Missed glyph, try text box
result = LabelTextHandle::HitTest(event, this); result = LabelTextHandle::HitTest(event, this);
if ( !result.handle )
result = Track::HitTest(evt, pProject);
if ( !result.handle ) {
// In case of multi tool, default to selection.
const ToolsToolBar *const pTtb = pProject->GetToolsToolBar();
if (pTtb->IsDown(multiTool))
result = SelectHandle::HitTest(evt, pProject, this);
}
return result; return result;
} }

View File

@ -21,44 +21,18 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../../TrackPanelMouseEvent.h" #include "../../../../TrackPanelMouseEvent.h"
#include "../../../ui/SelectHandle.h" #include "../../../ui/SelectHandle.h"
#include "StretchHandle.h" #include "StretchHandle.h"
#include "../../../../toolbars/ToolsToolBar.h"
HitTestResult NoteTrack::HitTest HitTestResult NoteTrack::DetailedHitTest
(const TrackPanelMouseEvent &event, (const TrackPanelMouseEvent &event,
const AudacityProject *pProject) const AudacityProject *pProject, int, bool )
{ {
const ToolsToolBar *const pTtb = pProject->GetToolsToolBar();
// If the cursor is in the hot zone for stretching, that takes precedence
// over selection, but it didn't take precedence over other hits.
// That was the old logic, and maybe I tried too hard to preserve it just so.
// PRL.
// Eligible for stretch? // Eligible for stretch?
HitTestResult result1; HitTestResult result;
#ifdef USE_MIDI #ifdef USE_MIDI
StretchHandle::StretchState state; StretchHandle::StretchState state;
result1 = StretchHandle::HitTest( event, pProject, this, state ); result = StretchHandle::HitTest( event, pProject, this, state );
#endif #endif
// But some other non-select tool like zoom may take priority.
HitTestResult result = Track::HitTest(event, pProject);
if (result.preview.cursor &&
!(result1.preview.cursor && pTtb->GetCurrentTool() == selectTool))
return result;
if (pTtb->IsDown(multiTool)) {
// Default to selection
if (!result1.preview.cursor &&
NULL != (result =
SelectHandle::HitTest(event, pProject, this)).preview.cursor)
return result;
}
// Do stretch!
if (result1.preview.cursor)
return result1;
return result; return result;
} }

View File

@ -23,47 +23,66 @@ Paul Licameli split from TrackPanel.cpp
#include "SampleHandle.h" #include "SampleHandle.h"
#include "../../../ui/TimeShiftHandle.h" #include "../../../ui/TimeShiftHandle.h"
HitTestResult WaveTrack::HitTest HitTestResult WaveTrack::DetailedHitTest
(const TrackPanelMouseEvent &event, (const TrackPanelMouseEvent &event,
const AudacityProject *pProject) const AudacityProject *pProject, int currentTool, bool bMultiTool)
{ {
// FIXME: Should similar logic apply to NoteTrack (#if defined(USE_MIDI)) ? // This is the only override of Track::DetailedHitTest that still
// From here on the order in which we hit test determines // depends on the state of the Tools toolbar.
// which tool takes priority in the rare cases where it // If that toolbar were eliminated, this could simplify to a sequence of
// could be more than one. // hit test routines describable by a table.
// This hit was always tested first no matter which tool: WaveTrack *const wavetrack = static_cast<WaveTrack*>(event.pCell);
HitTestResult result = CutlineHandle::HitTest(event.event, event.rect, pProject, this); bool isWaveform = (wavetrack->GetDisplay() == WaveTrack::Waveform);
if (result.preview.cursor)
return result;
result = Track::HitTest(event, pProject); if (bMultiTool && event.event.CmdDown())
if (result.preview.cursor) // Ctrl modifier key in multi-tool overrides everything else
return result; // (But this does not do the time shift constrained to the vertical only,
// which is what happens when you hold Ctrl in the Time Shift tool mode)
return TimeShiftHandle::HitAnywhere(pProject);
const ToolsToolBar *const pTtb = pProject->GetToolsToolBar(); // Some special targets are not drawn in spectrogram,
if (pTtb->IsDown(multiTool)) { // so don't hit them in such views.
// Replicate some of the logic of TrackPanel::DetermineToolToUse else if (isWaveform) {
int currentTool = -1; HitTestResult result;
if (event.event.CmdDown()) if (NULL !=
result = TimeShiftHandle::HitAnywhere(pProject); (result = CutlineHandle::HitTest
else if (NULL != (event.event, event.rect, pProject, this))
(result = EnvelopeHandle::WaveTrackHitTest(event.event, event.rect, pProject, *this)) .preview.cursor)
.preview.cursor) // This overriding test applies in all tools
; return result;
else if (NULL != (result = else if (bMultiTool) {
TimeShiftHandle::HitTest(event.event, event.rect, pProject)).preview.cursor) // Conditional hit tests
; // If Tools toolbar were eliminated, we would keep these
else if (NULL != (result = // The priority of these, in case more than one might apply at one
SampleHandle::HitTest(event.event, event.rect, pProject, this)).preview.cursor) // point, seems arbitrary
; if (NULL != (result = EnvelopeHandle::WaveTrackHitTest
else if (NULL != (result = (event.event, event.rect, pProject, *this))
SelectHandle::HitTest(event, pProject, this)).preview.cursor) .preview.cursor)
// default of all other hit tests ;
; else if (NULL != (result = TimeShiftHandle::HitTest
(event.event, event.rect, pProject)).preview.cursor)
// This is the hit test on the "grips" drawn left and
// right in Multi only
;
else if (NULL != (result = SampleHandle::HitTest
(event.event, event.rect, pProject, this)).preview.cursor)
;
return result;
}
else switch ( currentTool ) {
// Unconditional hits appropriate to the tool
// If tools toolbar were eliminated, we would eliminate these
case envelopeTool:
return EnvelopeHandle::HitAnywhere(pProject);
case drawTool:
return SampleHandle::HitAnywhere(event.event, pProject);
default:
break;
}
} }
return result; return {};
} }
std::shared_ptr<TrackControls> WaveTrack::GetControls() std::shared_ptr<TrackControls> WaveTrack::GetControls()

View File

@ -15,18 +15,13 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../HitTestResult.h" #include "../../../HitTestResult.h"
#include "../../../TrackPanelMouseEvent.h" #include "../../../TrackPanelMouseEvent.h"
#include "../../../Project.h" #include "../../../Project.h"
#include "../../../toolbars/ToolsToolBar.h"
#include "../../ui/EnvelopeHandle.h" #include "../../ui/EnvelopeHandle.h"
HitTestResult TimeTrack::HitTest HitTestResult TimeTrack::DetailedHitTest
(const TrackPanelMouseEvent &event, (const TrackPanelMouseEvent &event,
const AudacityProject *pProject) const AudacityProject *pProject, int, bool)
{ {
HitTestResult result = Track::HitTest(event, pProject);
if (result.preview.cursor)
return result;
return EnvelopeHandle::TimeTrackHitTest return EnvelopeHandle::TimeTrackHitTest
( event.event, event.rect, pProject, *this ); ( event.event, event.rect, pProject, *this );
} }

View File

@ -28,34 +28,34 @@ HitTestResult Track::HitTest
const AudacityProject *pProject) const AudacityProject *pProject)
{ {
const ToolsToolBar * pTtb = pProject->GetToolsToolBar(); const ToolsToolBar * pTtb = pProject->GetToolsToolBar();
// Unless in Multimode keep using the current tool.
const bool isMultiTool = pTtb->IsDown(multiTool); const bool isMultiTool = pTtb->IsDown(multiTool);
if (!isMultiTool) { const auto currentTool = pTtb->GetCurrentTool();
switch (pTtb->GetCurrentTool()) {
case envelopeTool:
// Pass "false" for unsafe -- let the tool decide to cancel itself
return EnvelopeHandle::HitAnywhere(pProject);
case drawTool:
return SampleHandle::HitAnywhere(event.event, pProject);
case zoomTool:
return ZoomHandle::HitAnywhere(event.event, pProject);
case slideTool:
return TimeShiftHandle::HitAnywhere(pProject);
case selectTool:
return SelectHandle::HitTest(event, pProject, this);
default: if ( !isMultiTool && currentTool == zoomTool )
// fallthru // Zoom tool is a non-selecting tool that takes precedence in all tracks
; // over all other tools, no matter what detail you point at.
} return ZoomHandle::HitAnywhere(event.event, pProject);
}
// Replicate some of the logic of TrackPanel::DetermineToolToUse // In other tools, let subclasses determine detailed hits.
HitTestResult result; HitTestResult result =
DetailedHitTest( event, pProject, currentTool, isMultiTool );
if (isMultiTool) // If there is no detailed hit for the subclass, there are still some
// general cases.
// Sliding applies in more than one track type.
if ( !result.handle && !isMultiTool && currentTool == slideTool )
result = TimeShiftHandle::HitAnywhere(pProject);
// Let the multi-tool right-click handler apply only in default of all
// other detailed hits.
if ( !result.handle && isMultiTool )
result = ZoomHandle::HitTest(event.event, pProject); result = ZoomHandle::HitTest(event.event, pProject);
// Finally, default of all is adjustment of the selection box.
if ( !result.handle && ( isMultiTool || currentTool == selectTool) )
result = SelectHandle::HitTest(event, pProject, this);
return result; return result;
} }