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:
parent
9e0010ec5f
commit
bce3571372
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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; }
|
||||||
|
18
src/Track.h
18
src/Track.h
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user