Changed lifetime management of UIHandle objects, no singletons...
... Rather, construct them during hit tests (also capturing more state sooner rather than at Click time, and adding some accessors for later use) This also fixes bug 1677 by other means and avoids similar problems. A cell may be implemented to re-use a previously hit handle object, not yet clicked, in a later hit test, by remembering a weak pointer, but TrackPanel holds the strong pointers that determine when the object is destroyed. And the objects will surely be destroyed after drag-release, or ESC key. For now they are also destroyed whenever not dragging, and hit-testing is re-invoked; that will be changed later, so that the re-use mentioned above becomes effective, but still they will be destroyed when the pointer moves from one cell to another.
This commit is contained in:
parent
d2fbca83b2
commit
2c1a16f593
|
@ -12,10 +12,13 @@ Paul Licameli
|
|||
#define __AUDACITY_HIT_TEST_RESULT__
|
||||
|
||||
#include <wx/string.h>
|
||||
#include "MemoryX.h"
|
||||
|
||||
class UIHandle;
|
||||
class wxCursor;
|
||||
|
||||
using UIHandlePtr = std::shared_ptr<UIHandle>;
|
||||
|
||||
struct HitTestPreview
|
||||
{
|
||||
HitTestPreview()
|
||||
|
@ -39,12 +42,12 @@ struct HitTestResult
|
|||
HitTestResult()
|
||||
{}
|
||||
|
||||
HitTestResult(HitTestPreview preview_, UIHandle *handle_)
|
||||
HitTestResult(HitTestPreview preview_, UIHandlePtr handle_)
|
||||
: preview(preview_), handle(handle_)
|
||||
{}
|
||||
|
||||
HitTestPreview preview {};
|
||||
UIHandle *handle {};
|
||||
UIHandlePtr handle {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -105,6 +105,8 @@ const int NUM_GLYPH_CONFIGS = 3;
|
|||
const int NUM_GLYPH_HIGHLIGHTS = 4;
|
||||
const int MAX_NUM_ROWS =80;
|
||||
|
||||
class LabelGlyphHandle;
|
||||
class LabelTextHandle;
|
||||
|
||||
class AUDACITY_DLL_API LabelTrack final : public Track
|
||||
{
|
||||
|
@ -317,6 +319,9 @@ private:
|
|||
|
||||
static wxFont msFont;
|
||||
|
||||
std::weak_ptr<LabelGlyphHandle> mGlyphHandle;
|
||||
std::weak_ptr<LabelTextHandle> mTextHandle;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<TrackControls> GetControls() override;
|
||||
std::shared_ptr<TrackVRulerControls> GetVRulerControls() override;
|
||||
|
|
|
@ -336,11 +336,7 @@ void NoteTrack::DrawLabelControls
|
|||
AColor::MIDIChannel(&dc, 0); // always return with gray color selected
|
||||
}
|
||||
|
||||
// Handles clicking within the midi controls rect (same as DrawLabelControls).
|
||||
// This is somewhat oddly written, as these aren't real buttons - they act
|
||||
// when the mouse goes down; you can't hold it pressed and move off of it.
|
||||
// Left-clicking toggles a single channel; right-clicking turns off all other channels.
|
||||
bool NoteTrack::LabelClick(const wxRect &rect, int mx, int my, bool right)
|
||||
int NoteTrack::FindChannel(const wxRect &rect, int mx, int my)
|
||||
{
|
||||
wxASSERT_MSG(rect.width % 4 == 0, "Midi channel control rect width must be divisible by 4");
|
||||
wxASSERT_MSG(rect.height % 4 == 0, "Midi channel control rect height must be divisible by 4");
|
||||
|
@ -351,8 +347,17 @@ bool NoteTrack::LabelClick(const wxRect &rect, int mx, int my, bool right)
|
|||
int col = (mx - rect.x) / cellWidth;
|
||||
int row = (my - rect.y) / cellHeight;
|
||||
|
||||
int channel = row * 4 + col;
|
||||
return row * 4 + col;
|
||||
}
|
||||
|
||||
|
||||
// Handles clicking within the midi controls rect (same as DrawLabelControls).
|
||||
// This is somewhat oddly written, as these aren't real buttons - they act
|
||||
// when the mouse goes down; you can't hold it pressed and move off of it.
|
||||
// Left-clicking toggles a single channel; right-clicking turns off all other channels.
|
||||
bool NoteTrack::LabelClick(const wxRect &rect, int mx, int my, bool right)
|
||||
{
|
||||
auto channel = FindChannel(rect, mx, my);
|
||||
if (right)
|
||||
SoloVisibleChan(channel);
|
||||
else
|
||||
|
|
|
@ -61,6 +61,8 @@ using NoteTrackBase =
|
|||
|
||||
using QuantizedTimeAndBeat = std::pair< double, double >;
|
||||
|
||||
class StretchHandle;
|
||||
|
||||
class AUDACITY_DLL_API NoteTrack final
|
||||
: public NoteTrackBase
|
||||
{
|
||||
|
@ -89,6 +91,7 @@ class AUDACITY_DLL_API NoteTrack final
|
|||
|
||||
static void DrawLabelControls
|
||||
( const NoteTrack *pTrack, wxDC & dc, const wxRect &rect );
|
||||
int FindChannel(const wxRect &rect, int mx, int my);
|
||||
bool LabelClick(const wxRect &rect, int x, int y, bool right);
|
||||
|
||||
void SetSequence(std::unique_ptr<Alg_seq> &&seq);
|
||||
|
@ -242,6 +245,8 @@ class AUDACITY_DLL_API NoteTrack final
|
|||
int mVisibleChannels; // bit set of visible channels
|
||||
int mLastMidiPosition;
|
||||
|
||||
std::weak_ptr<StretchHandle> mStretchHandle;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<TrackControls> GetControls() override;
|
||||
std::shared_ptr<TrackVRulerControls> GetVRulerControls() override;
|
||||
|
|
|
@ -806,6 +806,8 @@ public:
|
|||
|
||||
public:
|
||||
PlaybackScroller &GetPlaybackScroller() { return *mPlaybackScroller; }
|
||||
std::shared_ptr<BackgroundCell> GetBackgroundCell() const
|
||||
{ return mBackgroundCell; }
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
|
@ -23,6 +23,8 @@ class Envelope;
|
|||
class Ruler;
|
||||
class ZoomInfo;
|
||||
|
||||
class EnvelopeHandle;
|
||||
|
||||
class TimeTrack final : public Track {
|
||||
|
||||
public:
|
||||
|
@ -141,6 +143,8 @@ class TimeTrack final : public Track {
|
|||
bool mDisplayLog;
|
||||
bool mRescaleXMLValues; // needed for backward-compatibility with older project files
|
||||
|
||||
std::weak_ptr<EnvelopeHandle> mEnvelopeHandle;
|
||||
|
||||
/** @brief Copy the metadata from another track but not the points
|
||||
*
|
||||
* Copies the Name, DefaultName, Range and Display data from the source track
|
||||
|
|
|
@ -44,6 +44,9 @@ class NoteTrack;
|
|||
class AudacityProject;
|
||||
class ZoomInfo;
|
||||
|
||||
class SelectHandle;
|
||||
class TimeShiftHandle;
|
||||
|
||||
WX_DEFINE_USER_EXPORTED_ARRAY(Track*, TrackArray, class AUDACITY_DLL_API);
|
||||
using WaveTrackArray = std::vector < WaveTrack* > ;
|
||||
|
||||
|
@ -318,6 +321,9 @@ protected:
|
|||
std::shared_ptr<TrackControls> mpControls;
|
||||
std::shared_ptr<TrackVRulerControls> mpVRulerContols;
|
||||
std::shared_ptr<TrackPanelResizerCell> mpResizer;
|
||||
|
||||
std::weak_ptr<SelectHandle> mSelectHandle;
|
||||
std::weak_ptr<TimeShiftHandle> mTimeShiftHandle;
|
||||
};
|
||||
|
||||
class AUDACITY_DLL_API AudioTrack /* not final */ : public Track
|
||||
|
|
|
@ -770,7 +770,7 @@ void TrackPanel::CancelDragging()
|
|||
ProcessUIHandleResult(
|
||||
this, mRuler, pTrack.get(), NULL, refreshResult);
|
||||
mpClickedTrack.reset();
|
||||
mUIHandle = NULL;
|
||||
mUIHandle.reset();
|
||||
Uncapture();
|
||||
}
|
||||
}
|
||||
|
@ -1465,7 +1465,7 @@ try
|
|||
(this, mRuler, pClickedTrack.get(), pTrack.get(), refreshResult);
|
||||
if (refreshResult & RefreshCode::Cancelled) {
|
||||
// Drag decided to abort itself
|
||||
mUIHandle = NULL;
|
||||
mUIHandle.reset();
|
||||
mpClickedTrack.reset();
|
||||
Uncapture( &event );
|
||||
}
|
||||
|
@ -1484,7 +1484,7 @@ try
|
|||
// Null this pointer out first before calling Release -- because on Windows, we can
|
||||
// come back recursively to this place during handling of the context menu,
|
||||
// because of a capture lost event.
|
||||
mUIHandle = nullptr;
|
||||
mUIHandle.reset();
|
||||
UIHandle::Result refreshResult =
|
||||
uiHandle->Release( tpmEvent, GetProject(), this );
|
||||
ProcessUIHandleResult
|
||||
|
@ -1553,7 +1553,7 @@ void TrackPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent )
|
|||
UIHandle::Result refreshResult =
|
||||
mUIHandle->Click( tpmEvent, GetProject() );
|
||||
if (refreshResult & RefreshCode::Cancelled)
|
||||
mUIHandle = NULL;
|
||||
mUIHandle.reset();
|
||||
else
|
||||
mpClickedTrack = pTrack;
|
||||
ProcessUIHandleResult
|
||||
|
@ -3113,7 +3113,7 @@ TrackPanelCellIterator::TrackPanelCellIterator(TrackPanel *trackPanel, bool begi
|
|||
mpCell = mpTrack;
|
||||
else
|
||||
mpCell = trackPanel->GetBackgroundCell();
|
||||
}
|
||||
}
|
||||
|
||||
const auto size = mPanel->GetSize();
|
||||
mRect = { 0, 0, size.x, size.y };
|
||||
|
|
|
@ -54,6 +54,7 @@ class NoteTrack;
|
|||
class WaveTrack;
|
||||
class WaveClip;
|
||||
class UIHandle;
|
||||
using UIHandlePtr = std::shared_ptr<UIHandle>;
|
||||
|
||||
// Declared elsewhere, to reduce compilation dependencies
|
||||
class TrackPanelListener;
|
||||
|
@ -528,8 +529,7 @@ protected:
|
|||
|
||||
protected:
|
||||
std::weak_ptr<Track> mpClickedTrack;
|
||||
// TrackPanel is not responsible for memory management:
|
||||
UIHandle *mUIHandle {};
|
||||
UIHandlePtr mUIHandle;
|
||||
|
||||
std::shared_ptr<TrackPanelCell> mpBackground;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ public:
|
|||
// appropriate to the mouse position, modifier keys, and button-down state.
|
||||
// The button-down state passed to the function is as it will be at click
|
||||
// time -- not necessarily as it is now.
|
||||
// TrackPanel is not responsible for memory management of the handler.
|
||||
virtual HitTestResult HitTest
|
||||
(const TrackPanelMouseState &state,
|
||||
const AudacityProject *pProject) = 0;
|
||||
|
|
|
@ -28,16 +28,6 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "WaveTrack.h"
|
||||
#endif
|
||||
|
||||
TrackPanelResizeHandle::TrackPanelResizeHandle()
|
||||
{
|
||||
}
|
||||
|
||||
TrackPanelResizeHandle &TrackPanelResizeHandle::Instance()
|
||||
{
|
||||
static TrackPanelResizeHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
HitTestPreview TrackPanelResizeHandle::HitPreview(bool bLinked)
|
||||
{
|
||||
static wxCursor resizeCursor{ wxCURSOR_SIZENS };
|
||||
|
@ -69,30 +59,14 @@ TrackPanelResizeHandle::~TrackPanelResizeHandle()
|
|||
UIHandle::Result TrackPanelResizeHandle::Click
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||
{
|
||||
const wxMouseEvent &event = evt.event;
|
||||
const auto pCell =
|
||||
static_cast<CommonTrackPanelCell*>(evt.pCell.get());
|
||||
auto track = pCell->FindTrack().get();
|
||||
if (track && dynamic_cast< TrackControls * >( pCell )) {
|
||||
// Clicked under a label;
|
||||
// if stereo, replace left channel with the right:
|
||||
if (track && track->GetLinked())
|
||||
track = track->GetLink();
|
||||
}
|
||||
if (!track)
|
||||
return RefreshCode::Cancelled;
|
||||
|
||||
mpTrack = Track::Pointer( track );
|
||||
|
||||
/// ButtonDown means they just clicked and haven't released yet.
|
||||
/// We use this opportunity to save which track they clicked on,
|
||||
/// and the initial height of the track, so as they drag we can
|
||||
/// update the track size.
|
||||
|
||||
mMouseClickY = event.m_y;
|
||||
|
||||
TrackList *const tracks = pProject->GetTracks();
|
||||
return RefreshCode::RefreshNone;
|
||||
}
|
||||
|
||||
TrackPanelResizeHandle::TrackPanelResizeHandle
|
||||
( const std::shared_ptr<Track> &track, int y, const AudacityProject *pProject )
|
||||
: mpTrack{ track }
|
||||
, mMouseClickY( y )
|
||||
{
|
||||
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
|
||||
if (MONO_WAVE_PAN(track)){
|
||||
//STM: Determine whether we should rescale one or two tracks
|
||||
|
@ -116,11 +90,12 @@ UIHandle::Result TrackPanelResizeHandle::Click
|
|||
else
|
||||
#endif
|
||||
{
|
||||
Track *prev = tracks->GetPrev(track);
|
||||
Track *next = tracks->GetNext(track);
|
||||
auto tracks = pProject->GetTracks();
|
||||
Track *prev = tracks->GetPrev(track.get());
|
||||
Track *next = tracks->GetNext(track.get());
|
||||
|
||||
//STM: Determine whether we should rescale one or two tracks
|
||||
if (prev && prev->GetLink() == track) {
|
||||
if (prev && prev->GetLink() == track.get()) {
|
||||
// mpTrack is the lower track
|
||||
mInitialTrackHeight = track->GetHeight();
|
||||
mInitialActualHeight = track->GetActualHeight();
|
||||
|
@ -146,8 +121,6 @@ UIHandle::Result TrackPanelResizeHandle::Click
|
|||
mMode = IsResizing;
|
||||
}
|
||||
}
|
||||
|
||||
return RefreshCode::RefreshNone;
|
||||
}
|
||||
|
||||
UIHandle::Result TrackPanelResizeHandle::Drag
|
||||
|
|
|
@ -20,16 +20,21 @@ class TrackPanelCellIterator;
|
|||
|
||||
class TrackPanelResizeHandle final : public UIHandle
|
||||
{
|
||||
TrackPanelResizeHandle();
|
||||
TrackPanelResizeHandle(const TrackPanelResizeHandle&) = delete;
|
||||
TrackPanelResizeHandle &operator=(const TrackPanelResizeHandle&) = delete;
|
||||
|
||||
public:
|
||||
static TrackPanelResizeHandle& Instance();
|
||||
explicit TrackPanelResizeHandle
|
||||
( const std::shared_ptr<Track> &pTrack, int y,
|
||||
const AudacityProject *pProject );
|
||||
|
||||
TrackPanelResizeHandle &operator=(const TrackPanelResizeHandle&) = default;
|
||||
|
||||
static HitTestPreview HitPreview(bool bLinked);
|
||||
|
||||
virtual ~TrackPanelResizeHandle();
|
||||
|
||||
std::shared_ptr<Track> GetTrack() const { return mpTrack.lock(); }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
|
|
@ -10,18 +10,29 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "Audacity.h"
|
||||
#include "TrackPanelResizerCell.h"
|
||||
|
||||
#include "TrackPanelResizeHandle.h"
|
||||
#include "TrackPanelMouseEvent.h"
|
||||
#include "HitTestResult.h"
|
||||
|
||||
#include <wx/mousestate.h>
|
||||
|
||||
TrackPanelResizerCell::TrackPanelResizerCell( std::shared_ptr<Track> pTrack )
|
||||
: mpTrack{ pTrack }
|
||||
{}
|
||||
|
||||
HitTestResult TrackPanelResizerCell::HitTest
|
||||
(const TrackPanelMouseState &, const AudacityProject *)
|
||||
(const TrackPanelMouseState &st, const AudacityProject *pProject)
|
||||
{
|
||||
return {
|
||||
TrackPanelResizeHandle::HitPreview( mBetweenTracks ),
|
||||
&TrackPanelResizeHandle::Instance()
|
||||
};
|
||||
auto pTrack = mpTrack.lock();
|
||||
if (pTrack) {
|
||||
auto result = std::make_shared<TrackPanelResizeHandle>(
|
||||
pTrack, st.state.m_y, pProject );
|
||||
result = AssignUIHandlePtr(mResizeHandle, result);
|
||||
return {
|
||||
result->Preview(st, pProject),
|
||||
result
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "tracks/ui/CommonTrackPanelCell.h"
|
||||
|
||||
class TrackPanelResizeHandle;
|
||||
|
||||
class TrackPanelResizerCell : public CommonTrackPanelCell
|
||||
{
|
||||
TrackPanelResizerCell(const TrackPanelResizerCell&) = delete;
|
||||
|
@ -29,7 +31,8 @@ public:
|
|||
private:
|
||||
friend class TrackPanelCellIterator;
|
||||
std::weak_ptr<Track> mpTrack;
|
||||
bool mBetweenTracks {};
|
||||
|
||||
std::weak_ptr<TrackPanelResizeHandle> mResizeHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@ Paul Licameli
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "UIHandle.h"
|
||||
|
||||
UIHandle::~UIHandle()
|
||||
|
|
|
@ -24,6 +24,8 @@ class TrackPanelCell;
|
|||
struct TrackPanelMouseEvent;
|
||||
struct TrackPanelMouseState;
|
||||
|
||||
#include "MemoryX.h"
|
||||
|
||||
// A TrackPanelCell reports a handle object of some subclass, in response to a
|
||||
// hit test at a mouse position; then this handle processes certain events,
|
||||
// and maintains necessary state through click-drag-release event sequences.
|
||||
|
@ -99,4 +101,26 @@ public:
|
|||
virtual void OnProjectChange(AudacityProject *pProject);
|
||||
};
|
||||
|
||||
using UIHandlePtr = std::shared_ptr<UIHandle>;
|
||||
|
||||
// A frequent convenience
|
||||
template<typename Subclass>
|
||||
std::shared_ptr<Subclass> AssignUIHandlePtr
|
||||
( std::weak_ptr<Subclass> &holder, const std::shared_ptr<Subclass> &pNew )
|
||||
{
|
||||
// Either assign to a null weak_ptr, or else rewrite what the weak_ptr
|
||||
// points at. Thus a handle already pointed at changes its state but not its
|
||||
// identity. This may matter for the framework that holds the strong
|
||||
// pointers.
|
||||
auto ptr = holder.lock();
|
||||
if (!ptr) {
|
||||
holder = pNew;
|
||||
return pNew;
|
||||
}
|
||||
else {
|
||||
*ptr = std::move(*pNew);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,10 @@ class SpectrogramSettings;
|
|||
class WaveformSettings;
|
||||
class TimeWarper;
|
||||
|
||||
class CutlineHandle;
|
||||
class SampleHandle;
|
||||
class EnvelopeHandle;
|
||||
|
||||
//
|
||||
// Tolerance for merging wave tracks (in seconds)
|
||||
//
|
||||
|
@ -636,6 +640,10 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
|
|||
std::unique_ptr<SpectrogramSettings> mpSpectrumSettings;
|
||||
std::unique_ptr<WaveformSettings> mpWaveformSettings;
|
||||
|
||||
std::weak_ptr<CutlineHandle> mCutlineHandle;
|
||||
std::weak_ptr<SampleHandle> mSampleHandle;
|
||||
std::weak_ptr<EnvelopeHandle> mEnvelopeHandle;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<TrackControls> GetControls() override;
|
||||
std::shared_ptr<TrackVRulerControls> GetVRulerControls() override;
|
||||
|
|
|
@ -31,7 +31,7 @@ struct LabelDefaultClickHandle::LabelState {
|
|||
|
||||
void LabelDefaultClickHandle::SaveState( AudacityProject *pProject )
|
||||
{
|
||||
mLabelState = std::make_unique<LabelState>();
|
||||
mLabelState = std::make_shared<LabelState>();
|
||||
auto &pairs = mLabelState->mPairs;
|
||||
TrackList *const tracks = pProject->GetTracks();
|
||||
TrackListIterator iter(tracks);
|
||||
|
|
|
@ -23,12 +23,13 @@ class LabelTrack;
|
|||
class LabelDefaultClickHandle /* not final */ : public UIHandle
|
||||
{
|
||||
LabelDefaultClickHandle(const LabelDefaultClickHandle&) = delete;
|
||||
LabelDefaultClickHandle &operator=(const LabelDefaultClickHandle&) = delete;
|
||||
|
||||
public:
|
||||
LabelDefaultClickHandle();
|
||||
virtual ~LabelDefaultClickHandle();
|
||||
|
||||
LabelDefaultClickHandle &operator=(LabelDefaultClickHandle&&) = default;
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
@ -45,7 +46,7 @@ public:
|
|||
|
||||
private:
|
||||
struct LabelState;
|
||||
std::unique_ptr< LabelState > mLabelState;
|
||||
std::shared_ptr< LabelState > mLabelState;
|
||||
void SaveState( AudacityProject *pProject );
|
||||
void RestoreState( AudacityProject *pProject );
|
||||
};
|
||||
|
|
|
@ -23,18 +23,14 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include <wx/cursor.h>
|
||||
#include <wx/translation.h>
|
||||
|
||||
LabelGlyphHandle::LabelGlyphHandle()
|
||||
{
|
||||
}
|
||||
|
||||
LabelGlyphHandle &LabelGlyphHandle::Instance()
|
||||
{
|
||||
static LabelGlyphHandle instance;
|
||||
return instance;
|
||||
}
|
||||
LabelGlyphHandle::LabelGlyphHandle
|
||||
(const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect)
|
||||
: mpLT{ pLT }
|
||||
, mRect{ rect }
|
||||
{}
|
||||
|
||||
HitTestPreview LabelGlyphHandle::HitPreview
|
||||
(bool hitCenter, unsigned refreshResult)
|
||||
(bool hitCenter, unsigned refreshResult)
|
||||
{
|
||||
static wxCursor arrowCursor{ wxCURSOR_ARROW };
|
||||
return {
|
||||
|
@ -49,7 +45,9 @@ HitTestPreview LabelGlyphHandle::HitPreview
|
|||
}
|
||||
|
||||
HitTestResult LabelGlyphHandle::HitTest
|
||||
(const wxMouseState &state, const std::shared_ptr<LabelTrack> &pLT)
|
||||
(std::weak_ptr<LabelGlyphHandle> &holder,
|
||||
const wxMouseState &state,
|
||||
const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect)
|
||||
{
|
||||
using namespace RefreshCode;
|
||||
unsigned refreshResult = RefreshNone;
|
||||
|
@ -70,16 +68,18 @@ HitTestResult LabelGlyphHandle::HitTest
|
|||
// signal this by setting the tip.
|
||||
if (edge != 0)
|
||||
{
|
||||
auto result = std::make_shared<LabelGlyphHandle>( pLT, rect );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview(pLT->mbHitCenter, refreshResult),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
else {
|
||||
// An empty result, except maybe, unusually, the refresh
|
||||
return {
|
||||
{ wxString{}, nullptr, refreshResult },
|
||||
nullptr
|
||||
{}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -93,15 +93,10 @@ UIHandle::Result LabelGlyphHandle::Click
|
|||
{
|
||||
auto result = LabelDefaultClickHandle::Click( evt, pProject );
|
||||
|
||||
const auto pCell = evt.pCell;
|
||||
const wxMouseEvent &event = evt.event;
|
||||
const wxRect &rect = evt.rect;
|
||||
|
||||
mpLT = std::static_pointer_cast<LabelTrack>(pCell);
|
||||
mRect = rect;
|
||||
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
mpLT->HandleGlyphClick(event, rect, viewInfo, &viewInfo.selectedRegion);
|
||||
mpLT->HandleGlyphClick(event, mRect, viewInfo, &viewInfo.selectedRegion);
|
||||
|
||||
if (! mpLT->IsAdjustingLabel() )
|
||||
{
|
||||
|
|
|
@ -21,15 +21,19 @@ class LabelTrack;
|
|||
|
||||
class LabelGlyphHandle final : public LabelDefaultClickHandle
|
||||
{
|
||||
LabelGlyphHandle();
|
||||
LabelGlyphHandle(const LabelGlyphHandle&) = delete;
|
||||
LabelGlyphHandle &operator=(const LabelGlyphHandle&) = delete;
|
||||
static LabelGlyphHandle& Instance();
|
||||
static HitTestPreview HitPreview(bool hitCenter, unsigned refreshResult);
|
||||
|
||||
public:
|
||||
explicit LabelGlyphHandle
|
||||
(const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect);
|
||||
|
||||
LabelGlyphHandle &operator=(LabelGlyphHandle&&) = default;
|
||||
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const std::shared_ptr<LabelTrack> &pLT);
|
||||
(std::weak_ptr<LabelGlyphHandle> &holder,
|
||||
const wxMouseState &state,
|
||||
const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect);
|
||||
|
||||
virtual ~LabelGlyphHandle();
|
||||
|
||||
|
|
|
@ -18,15 +18,11 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../../ViewInfo.h"
|
||||
#include "../../../images/Cursors.h"
|
||||
|
||||
LabelTextHandle::LabelTextHandle()
|
||||
{
|
||||
}
|
||||
|
||||
LabelTextHandle &LabelTextHandle::Instance()
|
||||
{
|
||||
static LabelTextHandle instance;
|
||||
return instance;
|
||||
}
|
||||
LabelTextHandle::LabelTextHandle
|
||||
( const std::shared_ptr<LabelTrack> &pLT, int labelNum )
|
||||
: mpLT{ pLT }
|
||||
, mLabelNum{ labelNum }
|
||||
{}
|
||||
|
||||
HitTestPreview LabelTextHandle::HitPreview()
|
||||
{
|
||||
|
@ -39,13 +35,18 @@ HitTestPreview LabelTextHandle::HitPreview()
|
|||
}
|
||||
|
||||
HitTestResult LabelTextHandle::HitTest
|
||||
(const wxMouseState &state, const std::shared_ptr<LabelTrack> &pLT)
|
||||
(std::weak_ptr<LabelTextHandle> &holder,
|
||||
const wxMouseState &state, const std::shared_ptr<LabelTrack> &pLT)
|
||||
{
|
||||
// If Control is down, let the select handle be hit instead
|
||||
int labelNum;
|
||||
if (!state.ControlDown() &&
|
||||
pLT->OverATextBox(state.m_x, state.m_y) >= 0)
|
||||
(labelNum = pLT->OverATextBox(state.m_x, state.m_y) ) >= 0) {
|
||||
auto result = std::make_shared<LabelTextHandle>( pLT, labelNum );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
// There was no cursor change or status message for mousing over a label text box
|
||||
return { HitPreview(), &Instance() };
|
||||
return { HitPreview(), result };
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -57,6 +58,10 @@ LabelTextHandle::~LabelTextHandle()
|
|||
UIHandle::Result LabelTextHandle::Click
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||
{
|
||||
auto pLT = mpLT.lock();
|
||||
if (!pLT)
|
||||
return RefreshCode::Cancelled;
|
||||
|
||||
auto result = LabelDefaultClickHandle::Click( evt, pProject );
|
||||
|
||||
auto &selectionState = pProject->GetSelectionState();
|
||||
|
@ -64,12 +69,9 @@ UIHandle::Result LabelTextHandle::Click
|
|||
mChanger =
|
||||
std::make_unique< SelectionStateChanger >( selectionState, *tracks );
|
||||
|
||||
const auto pCell = evt.pCell;
|
||||
const wxMouseEvent &event = evt.event;
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
|
||||
auto pLT = std::static_pointer_cast<LabelTrack>(pCell);
|
||||
mpLT = pLT;
|
||||
mSelectedRegion = viewInfo.selectedRegion;
|
||||
pLT->HandleTextClick( event, evt.rect, viewInfo, &viewInfo.selectedRegion );
|
||||
wxASSERT(pLT->IsSelected());
|
||||
|
|
|
@ -23,19 +23,24 @@ class SelectionStateChanger;
|
|||
|
||||
class LabelTextHandle final : public LabelDefaultClickHandle
|
||||
{
|
||||
LabelTextHandle();
|
||||
LabelTextHandle(const LabelTextHandle&) = delete;
|
||||
LabelTextHandle &operator=(const LabelTextHandle&) = delete;
|
||||
static LabelTextHandle& Instance();
|
||||
|
||||
static HitTestPreview HitPreview();
|
||||
|
||||
public:
|
||||
static HitTestResult HitTest(
|
||||
const wxMouseState &state, const std::shared_ptr<LabelTrack> &pLT);
|
||||
static HitTestResult HitTest
|
||||
(std::weak_ptr<LabelTextHandle> &holder,
|
||||
const wxMouseState &state, const std::shared_ptr<LabelTrack> &pLT);
|
||||
|
||||
LabelTextHandle &operator=(LabelTextHandle&&) = default;
|
||||
|
||||
explicit LabelTextHandle
|
||||
( const std::shared_ptr<LabelTrack> &pLT, int labelNum );
|
||||
virtual ~LabelTextHandle();
|
||||
|
||||
std::shared_ptr<LabelTrack> GetTrack() const { return mpLT.lock(); }
|
||||
int GetLabelNum() const { return mLabelNum; }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
@ -54,6 +59,7 @@ public:
|
|||
|
||||
private:
|
||||
std::weak_ptr<LabelTrack> mpLT {};
|
||||
int mLabelNum{ -1 };
|
||||
int mLabelTrackStartXPos { -1 };
|
||||
int mLabelTrackStartYPos { -1 };
|
||||
SelectedRegion mSelectedRegion{};
|
||||
|
|
|
@ -29,12 +29,14 @@ HitTestResult LabelTrack::DetailedHitTest
|
|||
const wxMouseState &state = st.state;
|
||||
|
||||
// Try label movement handles first
|
||||
result = LabelGlyphHandle::HitTest(state, Pointer<LabelTrack>(this));
|
||||
result = LabelGlyphHandle::HitTest(
|
||||
mGlyphHandle, state, Pointer<LabelTrack>(this), st.rect);
|
||||
auto refresh = result.preview.refreshCode; // kludge
|
||||
|
||||
if ( !result.handle ) {
|
||||
// Missed glyph, try text box
|
||||
result = LabelTextHandle::HitTest(state, Pointer<LabelTrack>(this));
|
||||
result = LabelTextHandle::HitTest(
|
||||
mTextHandle, state, Pointer<LabelTrack>(this));
|
||||
result.preview.refreshCode |= refresh; // kludge
|
||||
}
|
||||
|
||||
|
|
|
@ -18,22 +18,21 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../../../RefreshCode.h"
|
||||
#include "../../../../TrackPanel.h"
|
||||
|
||||
NoteTrackButtonHandle::NoteTrackButtonHandle()
|
||||
{
|
||||
}
|
||||
NoteTrackButtonHandle::NoteTrackButtonHandle
|
||||
( const std::shared_ptr<NoteTrack> &pTrack,
|
||||
int channel, const wxRect &rect )
|
||||
: mpTrack{ pTrack }
|
||||
, mChannel{ channel }
|
||||
, mRect{ rect }
|
||||
{}
|
||||
|
||||
NoteTrackButtonHandle::~NoteTrackButtonHandle()
|
||||
{
|
||||
}
|
||||
|
||||
NoteTrackButtonHandle &NoteTrackButtonHandle::Instance()
|
||||
{
|
||||
static NoteTrackButtonHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
HitTestResult NoteTrackButtonHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<NoteTrackButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const std::shared_ptr<NoteTrack> &pTrack)
|
||||
{
|
||||
wxRect midiRect;
|
||||
|
@ -42,12 +41,14 @@ HitTestResult NoteTrackButtonHandle::HitTest
|
|||
return {};
|
||||
if (pTrack->GetKind() == Track::Note &&
|
||||
midiRect.Contains(state.m_x, state.m_y)) {
|
||||
Instance().mpTrack = pTrack;
|
||||
Instance().mRect = midiRect;
|
||||
return {
|
||||
HitTestPreview(),
|
||||
&Instance()
|
||||
};
|
||||
auto channel = pTrack->FindChannel(midiRect, state.m_x, state.m_y);
|
||||
auto result = std::make_shared<NoteTrackButtonHandle>(
|
||||
pTrack, channel, midiRect );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitTestPreview(),
|
||||
result
|
||||
};
|
||||
}
|
||||
else
|
||||
return {};
|
||||
|
@ -68,6 +69,10 @@ UIHandle::Result NoteTrackButtonHandle::Drag
|
|||
HitTestPreview NoteTrackButtonHandle::Preview
|
||||
(const TrackPanelMouseState &, const AudacityProject *)
|
||||
{
|
||||
// auto pTrack = pProject->GetTracks()->Lock(mpTrack);
|
||||
auto pTrack = mpTrack.lock();
|
||||
if ( !pTrack )
|
||||
return {};
|
||||
// No special message or cursor
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -24,15 +24,24 @@ struct HitTestResult;
|
|||
class NoteTrackButtonHandle : public UIHandle
|
||||
{
|
||||
NoteTrackButtonHandle(const NoteTrackButtonHandle&);
|
||||
NoteTrackButtonHandle &operator=(const NoteTrackButtonHandle&);
|
||||
NoteTrackButtonHandle();
|
||||
virtual ~NoteTrackButtonHandle();
|
||||
static NoteTrackButtonHandle& Instance();
|
||||
|
||||
public:
|
||||
explicit NoteTrackButtonHandle
|
||||
( const std::shared_ptr<NoteTrack> &pTrack,
|
||||
int channel, const wxRect &rect );
|
||||
|
||||
NoteTrackButtonHandle &operator=(const NoteTrackButtonHandle&) = default;
|
||||
|
||||
virtual ~NoteTrackButtonHandle();
|
||||
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
const std::shared_ptr<NoteTrack> &pTrack);
|
||||
(std::weak_ptr<NoteTrackButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const std::shared_ptr<NoteTrack> &pTrack);
|
||||
|
||||
int GetChannel() const { return mChannel; }
|
||||
|
||||
protected:
|
||||
Result Click
|
||||
|
@ -52,6 +61,7 @@ protected:
|
|||
Result Cancel(AudacityProject *pProject) override;
|
||||
|
||||
std::weak_ptr<NoteTrack> mpTrack;
|
||||
int mChannel{ -1 };
|
||||
wxRect mRect{};
|
||||
};
|
||||
|
||||
|
|
|
@ -40,21 +40,19 @@ HitTestResult NoteTrackControls::HitTest
|
|||
auto track = std::static_pointer_cast<NoteTrack>(FindTrack());
|
||||
if (track && track->GetKind() == Track::Note) {
|
||||
HitTestResult result;
|
||||
if (NULL !=
|
||||
(result = MuteButtonHandle::HitTest
|
||||
(state, rect, pProject, track)).handle)
|
||||
if (NULL != (result = MuteButtonHandle::HitTest(
|
||||
mMuteHandle, state, rect, pProject, track)).handle)
|
||||
return result;
|
||||
|
||||
if (NULL !=
|
||||
(result = SoloButtonHandle::HitTest
|
||||
(state, rect, pProject, track)).handle)
|
||||
if (NULL != (result = SoloButtonHandle::HitTest(
|
||||
mSoloHandle, state, rect, pProject, track)).handle)
|
||||
return result;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
if (NULL != (result =
|
||||
VelocitySliderHandle::HitTest(state, rect, pProject, track)).handle)
|
||||
if (NULL != (result = VelocitySliderHandle::HitTest(
|
||||
mVelocityHandle, state, rect, pProject, track)).handle)
|
||||
return result;
|
||||
if (NULL != (result =
|
||||
NoteTrackButtonHandle::HitTest(state, rect, track)).handle)
|
||||
if (NULL != (result = NoteTrackButtonHandle::HitTest(
|
||||
mClickHandle, state, rect, track)).handle)
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -12,12 +12,23 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#define __AUDACITY_NOTE_TRACK_CONTROLS__
|
||||
|
||||
#include "../../../ui/TrackControls.h"
|
||||
#include "../../../../MemoryX.h"
|
||||
class MuteButtonHandle;
|
||||
class SoloButtonHandle;
|
||||
class NoteTrackButtonHandle;
|
||||
class VelocitySliderHandle;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class NoteTrackControls : public TrackControls
|
||||
{
|
||||
NoteTrackControls(const NoteTrackControls&) = delete;
|
||||
NoteTrackControls &operator=(const NoteTrackControls&) = delete;
|
||||
|
||||
std::weak_ptr<MuteButtonHandle> mMuteHandle;
|
||||
std::weak_ptr<SoloButtonHandle> mSoloHandle;
|
||||
std::weak_ptr<NoteTrackButtonHandle> mClickHandle;
|
||||
std::weak_ptr<VelocitySliderHandle> mVelocityHandle;
|
||||
|
||||
public:
|
||||
explicit
|
||||
NoteTrackControls( std::shared_ptr<Track> pTrack )
|
||||
|
|
|
@ -21,21 +21,16 @@
|
|||
#include "../../../../UndoManager.h"
|
||||
#include "../../../../NoteTrack.h"
|
||||
|
||||
VelocitySliderHandle::VelocitySliderHandle()
|
||||
: SliderHandle()
|
||||
{
|
||||
}
|
||||
VelocitySliderHandle::VelocitySliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect,
|
||||
const std::shared_ptr<Track> &pTrack )
|
||||
: SliderHandle{ sliderFn, rect, pTrack }
|
||||
{}
|
||||
|
||||
VelocitySliderHandle::~VelocitySliderHandle()
|
||||
{
|
||||
}
|
||||
|
||||
VelocitySliderHandle &VelocitySliderHandle::Instance()
|
||||
{
|
||||
static VelocitySliderHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::shared_ptr<NoteTrack> VelocitySliderHandle::GetNoteTrack()
|
||||
{
|
||||
return std::static_pointer_cast<NoteTrack>(mpTrack.lock());
|
||||
|
@ -69,7 +64,8 @@ UIHandle::Result VelocitySliderHandle::CommitChanges
|
|||
|
||||
|
||||
HitTestResult VelocitySliderHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<VelocitySliderHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
|
||||
{
|
||||
if (!state.ButtonIsDown(wxMOUSE_BTN_LEFT))
|
||||
|
@ -80,16 +76,17 @@ HitTestResult VelocitySliderHandle::HitTest
|
|||
if ( TrackInfo::HideTopItem( rect, sliderRect, kTrackInfoSliderAllowance ) )
|
||||
return {};
|
||||
if (sliderRect.Contains(state.m_x, state.m_y)) {
|
||||
Instance().mSliderFn =
|
||||
auto sliderFn =
|
||||
[]( AudacityProject *pProject, const wxRect &sliderRect, Track *pTrack ) {
|
||||
return TrackInfo::VelocitySlider
|
||||
(sliderRect, static_cast<NoteTrack*>( pTrack ), true,
|
||||
const_cast<TrackPanel*>(pProject->GetTrackPanel()));
|
||||
};
|
||||
Instance().mRect = sliderRect;
|
||||
Instance().mpTrack = pTrack;
|
||||
auto result = std::make_shared<VelocitySliderHandle>(
|
||||
sliderFn, sliderRect, pTrack );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
|
||||
return { HitPreview(), &Instance() };
|
||||
return { HitPreview(), result };
|
||||
}
|
||||
else
|
||||
return {};
|
||||
|
|
|
@ -25,14 +25,18 @@ struct HitTestResult;
|
|||
class VelocitySliderHandle final : public SliderHandle
|
||||
{
|
||||
VelocitySliderHandle(const VelocitySliderHandle&) = delete;
|
||||
VelocitySliderHandle &operator=(const VelocitySliderHandle&) = delete;
|
||||
|
||||
VelocitySliderHandle();
|
||||
virtual ~VelocitySliderHandle();
|
||||
static VelocitySliderHandle& Instance();
|
||||
|
||||
std::shared_ptr<NoteTrack> GetNoteTrack();
|
||||
|
||||
public:
|
||||
explicit VelocitySliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect,
|
||||
const std::shared_ptr<Track> &pTrack );
|
||||
|
||||
VelocitySliderHandle &operator=(const VelocitySliderHandle&) = default;
|
||||
|
||||
virtual ~VelocitySliderHandle();
|
||||
|
||||
protected:
|
||||
float GetValue() override;
|
||||
Result SetValue
|
||||
|
@ -44,7 +48,8 @@ protected:
|
|||
|
||||
public:
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<VelocitySliderHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
|
||||
};
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ HitTestResult NoteTrack::DetailedHitTest
|
|||
// Eligible for stretch?
|
||||
HitTestResult result;
|
||||
#ifdef USE_MIDI
|
||||
StretchHandle::StretchState stretchState;
|
||||
result = StretchHandle::HitTest( state, pProject, Pointer<NoteTrack>(this), stretchState );
|
||||
result = StretchHandle::HitTest(
|
||||
mStretchHandle, state, pProject, Pointer<NoteTrack>(this) );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
|
|
@ -31,7 +31,10 @@ HitTestResult NoteTrackVRulerControls::HitTest
|
|||
(const TrackPanelMouseState &st,
|
||||
const AudacityProject *)
|
||||
{
|
||||
return NoteTrackVZoomHandle::HitTest(st.state);
|
||||
UIHandlePtr result;
|
||||
auto track = std::static_pointer_cast<NoteTrack>(FindTrack());
|
||||
return NoteTrackVZoomHandle::HitTest(
|
||||
mVZoomHandle, st.state, track, st.rect);
|
||||
}
|
||||
|
||||
unsigned NoteTrackVRulerControls::HandleWheelRotation
|
||||
|
|
|
@ -13,6 +13,8 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "../../../ui/TrackVRulerControls.h"
|
||||
|
||||
class NoteTrackVZoomHandle;
|
||||
|
||||
class NoteTrackVRulerControls final : public TrackVRulerControls
|
||||
{
|
||||
NoteTrackVRulerControls(const NoteTrackVRulerControls&) = delete;
|
||||
|
@ -31,6 +33,9 @@ public:
|
|||
unsigned HandleWheelRotation
|
||||
(const TrackPanelMouseEvent &event,
|
||||
AudacityProject *pProject) override;
|
||||
|
||||
private:
|
||||
std::weak_ptr<NoteTrackVZoomHandle> mVZoomHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,16 +34,11 @@ namespace
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NoteTrackVZoomHandle::NoteTrackVZoomHandle()
|
||||
: mZoomStart(0), mZoomEnd(0), mRect()
|
||||
{
|
||||
}
|
||||
|
||||
NoteTrackVZoomHandle &NoteTrackVZoomHandle::Instance()
|
||||
{
|
||||
static NoteTrackVZoomHandle instance;
|
||||
return instance;
|
||||
}
|
||||
NoteTrackVZoomHandle::NoteTrackVZoomHandle
|
||||
(const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect, int y)
|
||||
: mZoomStart(y), mZoomEnd(y), mRect(rect)
|
||||
, mpTrack{ pTrack }
|
||||
{}
|
||||
|
||||
HitTestPreview NoteTrackVZoomHandle::HitPreview(const wxMouseState &state)
|
||||
{
|
||||
|
@ -57,9 +52,18 @@ HitTestPreview NoteTrackVZoomHandle::HitPreview(const wxMouseState &state)
|
|||
};
|
||||
}
|
||||
|
||||
HitTestResult NoteTrackVZoomHandle::HitTest(const wxMouseState &state)
|
||||
HitTestResult NoteTrackVZoomHandle::HitTest
|
||||
(std::weak_ptr<NoteTrackVZoomHandle> &holder,
|
||||
const wxMouseState &state,
|
||||
const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect)
|
||||
{
|
||||
return HitTestResult(HitPreview(state), &Instance());
|
||||
if (pTrack) {
|
||||
auto result = std::make_shared<NoteTrackVZoomHandle>(
|
||||
pTrack, rect, state.m_y);
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return HitTestResult(HitPreview(state), result);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
NoteTrackVZoomHandle::~NoteTrackVZoomHandle()
|
||||
|
@ -67,16 +71,8 @@ NoteTrackVZoomHandle::~NoteTrackVZoomHandle()
|
|||
}
|
||||
|
||||
UIHandle::Result NoteTrackVZoomHandle::Click
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||
(const TrackPanelMouseEvent &, AudacityProject *)
|
||||
{
|
||||
mpTrack = std::static_pointer_cast<NoteTrack>(
|
||||
static_cast<NoteTrackVRulerControls*>(evt.pCell.get())->FindTrack() );
|
||||
mRect = evt.rect;
|
||||
|
||||
const wxMouseEvent &event = evt.event;
|
||||
mZoomStart = event.m_y;
|
||||
mZoomEnd = event.m_y;
|
||||
|
||||
// change note track to zoom like audio track
|
||||
// mpTrack->StartVScroll();
|
||||
|
||||
|
|
|
@ -21,17 +21,24 @@ class NoteTrack;
|
|||
|
||||
class NoteTrackVZoomHandle : public UIHandle
|
||||
{
|
||||
NoteTrackVZoomHandle();
|
||||
NoteTrackVZoomHandle(const NoteTrackVZoomHandle&);
|
||||
NoteTrackVZoomHandle &operator=(const NoteTrackVZoomHandle&);
|
||||
static NoteTrackVZoomHandle& Instance();
|
||||
static HitTestPreview HitPreview(const wxMouseState &state);
|
||||
|
||||
public:
|
||||
static HitTestResult HitTest(const wxMouseState &state);
|
||||
explicit NoteTrackVZoomHandle
|
||||
(const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect, int y);
|
||||
|
||||
NoteTrackVZoomHandle &operator=(const NoteTrackVZoomHandle&) = default;
|
||||
|
||||
static HitTestResult HitTest
|
||||
(std::weak_ptr<NoteTrackVZoomHandle> &holder,
|
||||
const wxMouseState &state,
|
||||
const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect);
|
||||
|
||||
virtual ~NoteTrackVZoomHandle();
|
||||
|
||||
std::shared_ptr<NoteTrack> GetTrack() const { return mpTrack.lock(); }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
|
|
@ -24,15 +24,11 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
StretchHandle::StretchHandle()
|
||||
{
|
||||
}
|
||||
|
||||
StretchHandle &StretchHandle::Instance()
|
||||
{
|
||||
static StretchHandle instance;
|
||||
return instance;
|
||||
}
|
||||
StretchHandle::StretchHandle
|
||||
( const std::shared_ptr<NoteTrack> &pTrack, const StretchState &stretchState )
|
||||
: mpTrack{ pTrack }
|
||||
, mStretchState{ stretchState }
|
||||
{}
|
||||
|
||||
HitTestPreview StretchHandle::HitPreview( StretchEnum stretchMode, bool unsafe )
|
||||
{
|
||||
|
@ -68,9 +64,11 @@ HitTestPreview StretchHandle::HitPreview( StretchEnum stretchMode, bool unsafe )
|
|||
}
|
||||
|
||||
HitTestResult StretchHandle::HitTest
|
||||
( const TrackPanelMouseState &st, const AudacityProject *pProject,
|
||||
const std::shared_ptr<NoteTrack> &pTrack, StretchState &stretchState)
|
||||
(std::weak_ptr<StretchHandle> &holder,
|
||||
const TrackPanelMouseState &st, const AudacityProject *pProject,
|
||||
const std::shared_ptr<NoteTrack> &pTrack)
|
||||
{
|
||||
StretchState stretchState;
|
||||
const wxMouseState &state = st.state;
|
||||
|
||||
// later, we may want a different policy, but for now, stretch is
|
||||
|
@ -140,9 +138,11 @@ HitTestResult StretchHandle::HitTest
|
|||
stretchState.mBeatCenter.second - stretchState.mBeat0.second;
|
||||
}
|
||||
|
||||
auto result = std::make_shared<StretchHandle>( pTrack, stretchState );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview( stretchState.mMode, unsafe ),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -167,14 +167,8 @@ UIHandle::Result StretchHandle::Click
|
|||
|
||||
|
||||
mLeftEdge = evt.rect.GetLeft();
|
||||
mpTrack = std::static_pointer_cast<NoteTrack>(evt.pCell);
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
|
||||
// We must have hit if we got here, but repeat some
|
||||
// calculations that set members
|
||||
TrackPanelMouseState tpmState{ evt.event, evt.rect, evt.pCell };
|
||||
HitTest( tpmState, pProject, mpTrack, mStretchState );
|
||||
|
||||
viewInfo.selectedRegion.setTimes
|
||||
( mStretchState.mBeat0.first, mStretchState.mBeat1.first );
|
||||
|
||||
|
|
|
@ -55,16 +55,20 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
StretchHandle();
|
||||
StretchHandle(const StretchHandle&);
|
||||
StretchHandle &operator=(const StretchHandle&);
|
||||
static StretchHandle& Instance();
|
||||
static HitTestPreview HitPreview(StretchEnum stretchMode, bool unsafe);
|
||||
|
||||
public:
|
||||
explicit StretchHandle
|
||||
( const std::shared_ptr<NoteTrack> &pTrack,
|
||||
const StretchState &stretchState );
|
||||
|
||||
StretchHandle &operator=(const StretchHandle&) = default;
|
||||
|
||||
static HitTestResult HitTest
|
||||
( const TrackPanelMouseState &state, const AudacityProject *pProject,
|
||||
const std::shared_ptr<NoteTrack> &pTrack, StretchState &stretchState );
|
||||
(std::weak_ptr<StretchHandle> &holder,
|
||||
const TrackPanelMouseState &state, const AudacityProject *pProject,
|
||||
const std::shared_ptr<NoteTrack> &pTrack );
|
||||
|
||||
virtual ~StretchHandle();
|
||||
|
||||
|
|
|
@ -18,21 +18,15 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../../TrackPanel.h"
|
||||
#include "../../../TrackPanelMouseEvent.h"
|
||||
|
||||
MuteButtonHandle::MuteButtonHandle()
|
||||
: ButtonHandle{ TrackPanel::IsMuting }
|
||||
{
|
||||
}
|
||||
MuteButtonHandle::MuteButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect )
|
||||
: ButtonHandle{ pTrack, rect, TrackPanel::IsMuting }
|
||||
{}
|
||||
|
||||
MuteButtonHandle::~MuteButtonHandle()
|
||||
{
|
||||
}
|
||||
|
||||
MuteButtonHandle &MuteButtonHandle::Instance()
|
||||
{
|
||||
static MuteButtonHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
UIHandle::Result MuteButtonHandle::CommitChanges
|
||||
(const wxMouseEvent &event, AudacityProject *pProject, wxWindow *)
|
||||
{
|
||||
|
@ -44,7 +38,8 @@ UIHandle::Result MuteButtonHandle::CommitChanges
|
|||
}
|
||||
|
||||
HitTestResult MuteButtonHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<MuteButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
|
||||
{
|
||||
wxRect buttonRect;
|
||||
|
@ -55,10 +50,11 @@ HitTestResult MuteButtonHandle::HitTest
|
|||
return {};
|
||||
|
||||
if ( pTrack && buttonRect.Contains(state.m_x, state.m_y) ) {
|
||||
Instance().mRect = buttonRect;
|
||||
auto result = std::make_shared<MuteButtonHandle>(pTrack, buttonRect);
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview(),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
else
|
||||
|
@ -67,21 +63,15 @@ HitTestResult MuteButtonHandle::HitTest
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SoloButtonHandle::SoloButtonHandle()
|
||||
: ButtonHandle{ TrackPanel::IsSoloing }
|
||||
{
|
||||
}
|
||||
SoloButtonHandle::SoloButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect )
|
||||
: ButtonHandle{ pTrack, rect, TrackPanel::IsSoloing }
|
||||
{}
|
||||
|
||||
SoloButtonHandle::~SoloButtonHandle()
|
||||
{
|
||||
}
|
||||
|
||||
SoloButtonHandle &SoloButtonHandle::Instance()
|
||||
{
|
||||
static SoloButtonHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
UIHandle::Result SoloButtonHandle::CommitChanges
|
||||
(const wxMouseEvent &event, AudacityProject *pProject, wxWindow *pParent)
|
||||
{
|
||||
|
@ -93,7 +83,8 @@ UIHandle::Result SoloButtonHandle::CommitChanges
|
|||
}
|
||||
|
||||
HitTestResult SoloButtonHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<SoloButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
|
||||
{
|
||||
wxRect buttonRect;
|
||||
|
@ -105,10 +96,11 @@ HitTestResult SoloButtonHandle::HitTest
|
|||
return {};
|
||||
|
||||
if ( pTrack && buttonRect.Contains(state.m_x, state.m_y) ) {
|
||||
Instance().mRect = buttonRect;
|
||||
auto result = std::make_shared<SoloButtonHandle>( pTrack, buttonRect );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return HitTestResult(
|
||||
HitPreview(),
|
||||
&Instance()
|
||||
result
|
||||
);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -12,18 +12,23 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#define __AUDACITY_PLAYABLE_TRACK_BUTTON_HANDLES__
|
||||
|
||||
#include "../../ui/ButtonHandle.h"
|
||||
#include "../../../TrackPanel.h"
|
||||
|
||||
struct HitTestResult;
|
||||
|
||||
class wxMouseState;
|
||||
|
||||
class MuteButtonHandle final : public ButtonHandle
|
||||
{
|
||||
MuteButtonHandle(const MuteButtonHandle&) = delete;
|
||||
MuteButtonHandle &operator=(const MuteButtonHandle&) = delete;
|
||||
|
||||
MuteButtonHandle();
|
||||
public:
|
||||
explicit MuteButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect );
|
||||
|
||||
MuteButtonHandle &operator=(const MuteButtonHandle&) = default;
|
||||
|
||||
virtual ~MuteButtonHandle();
|
||||
static MuteButtonHandle& Instance();
|
||||
|
||||
protected:
|
||||
Result CommitChanges
|
||||
|
@ -34,7 +39,8 @@ protected:
|
|||
|
||||
public:
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<MuteButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
|
||||
};
|
||||
|
||||
|
@ -43,11 +49,14 @@ public:
|
|||
class SoloButtonHandle final : public ButtonHandle
|
||||
{
|
||||
SoloButtonHandle(const SoloButtonHandle&) = delete;
|
||||
SoloButtonHandle &operator=(const SoloButtonHandle&) = delete;
|
||||
|
||||
SoloButtonHandle();
|
||||
public:
|
||||
explicit SoloButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect );
|
||||
|
||||
SoloButtonHandle &operator=(const SoloButtonHandle&) = default;
|
||||
|
||||
virtual ~SoloButtonHandle();
|
||||
static SoloButtonHandle& Instance();
|
||||
|
||||
protected:
|
||||
Result CommitChanges
|
||||
|
@ -58,7 +67,8 @@ protected:
|
|||
|
||||
public:
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<SoloButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
|
||||
};
|
||||
|
||||
|
|
|
@ -22,15 +22,11 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../../../WaveTrackLocation.h"
|
||||
#include "../../../../../images/Cursors.h"
|
||||
|
||||
CutlineHandle::CutlineHandle()
|
||||
{
|
||||
}
|
||||
|
||||
CutlineHandle &CutlineHandle::Instance()
|
||||
{
|
||||
static CutlineHandle instance;
|
||||
return instance;
|
||||
}
|
||||
CutlineHandle::CutlineHandle
|
||||
( const std::shared_ptr<WaveTrack> &pTrack, WaveTrackLocation location )
|
||||
: mpTrack{ pTrack }
|
||||
, mLocation{ location }
|
||||
{}
|
||||
|
||||
HitTestPreview CutlineHandle::HitPreview(bool cutline, bool unsafe)
|
||||
{
|
||||
|
@ -47,10 +43,11 @@ HitTestPreview CutlineHandle::HitPreview(bool cutline, bool unsafe)
|
|||
};
|
||||
}
|
||||
|
||||
HitTestResult CutlineHandle::HitAnywhere(const AudacityProject *pProject, bool cutline)
|
||||
HitTestResult CutlineHandle::HitAnywhere
|
||||
(const AudacityProject *pProject, bool cutline, UIHandlePtr ptr)
|
||||
{
|
||||
const bool unsafe = pProject->IsAudioActive();
|
||||
return { HitPreview(cutline, unsafe), &Instance() };
|
||||
return { HitPreview(cutline, unsafe), ptr };
|
||||
}
|
||||
|
||||
namespace
|
||||
|
@ -71,7 +68,7 @@ namespace
|
|||
bool IsOverCutline
|
||||
(const ViewInfo &viewInfo, WaveTrack * track,
|
||||
const wxRect &rect, const wxMouseState &state,
|
||||
WaveTrackLocation *pCapturedTrackLocation)
|
||||
WaveTrackLocation *pmLocation)
|
||||
{
|
||||
for (auto loc: track->GetCachedLocations())
|
||||
{
|
||||
|
@ -90,8 +87,8 @@ namespace
|
|||
}
|
||||
if (locRect.Contains(state.m_x, state.m_y))
|
||||
{
|
||||
if (pCapturedTrackLocation)
|
||||
*pCapturedTrackLocation = loc;
|
||||
if (pmLocation)
|
||||
*pmLocation = loc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +99,8 @@ namespace
|
|||
}
|
||||
|
||||
HitTestResult CutlineHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject,
|
||||
(std::weak_ptr<CutlineHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject,
|
||||
const std::shared_ptr<WaveTrack> &pTrack)
|
||||
{
|
||||
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
|
@ -116,7 +114,9 @@ HitTestResult CutlineHandle::HitTest
|
|||
if (!IsOverCutline(viewInfo, wavetrack, rect, state, &location))
|
||||
return {};
|
||||
|
||||
return HitAnywhere(pProject, location.typ == WaveTrackLocation::locationCutLine);
|
||||
auto result = std::make_shared<CutlineHandle>( pTrack, location );
|
||||
result = AssignUIHandlePtr( holder, result );
|
||||
return HitAnywhere(pProject, location.typ == WaveTrackLocation::locationCutLine, result);
|
||||
}
|
||||
|
||||
CutlineHandle::~CutlineHandle()
|
||||
|
@ -133,7 +133,6 @@ UIHandle::Result CutlineHandle::Click
|
|||
|
||||
const wxMouseEvent &event = evt.event;
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
const auto pTrack = static_cast<Track*>(evt.pCell.get());
|
||||
|
||||
// Can affect the track by merging clips, expanding a cutline, or
|
||||
// deleting a cutline.
|
||||
|
@ -141,24 +140,17 @@ UIHandle::Result CutlineHandle::Click
|
|||
|
||||
/// Someone has just clicked the mouse. What do we do?
|
||||
|
||||
WaveTrackLocation capturedTrackLocation;
|
||||
|
||||
WaveTrack *wavetrack = static_cast<WaveTrack*>(pTrack);
|
||||
if (!IsOverCutline(viewInfo, wavetrack, evt.rect, event, &capturedTrackLocation))
|
||||
return Cancelled;
|
||||
mbCutline = (capturedTrackLocation.typ == WaveTrackLocation::locationCutLine);
|
||||
|
||||
// FIXME: Disable this and return true when CutLines aren't showing?
|
||||
// (Don't use gPrefs-> for the fix as registry access is slow).
|
||||
|
||||
// Cutline data changed on either branch, so refresh the track display.
|
||||
UIHandle::Result result = RefreshCell;
|
||||
// Assume linked track is wave or null
|
||||
const auto linked = static_cast<WaveTrack*>(wavetrack->GetLink());
|
||||
const auto linked = static_cast<WaveTrack*>(mpTrack->GetLink());
|
||||
|
||||
if (event.LeftDown())
|
||||
{
|
||||
if (capturedTrackLocation.typ == WaveTrackLocation::locationCutLine)
|
||||
if (mLocation.typ == WaveTrackLocation::locationCutLine)
|
||||
{
|
||||
mOperation = Expand;
|
||||
mStartTime = viewInfo.selectedRegion.t0();
|
||||
|
@ -167,18 +159,18 @@ UIHandle::Result CutlineHandle::Click
|
|||
// When user presses left button on cut line, expand the line again
|
||||
double cutlineStart = 0, cutlineEnd = 0;
|
||||
|
||||
wavetrack->ExpandCutLine(capturedTrackLocation.pos, &cutlineStart, &cutlineEnd);
|
||||
mpTrack->ExpandCutLine(mLocation.pos, &cutlineStart, &cutlineEnd);
|
||||
|
||||
if (linked)
|
||||
// Expand the cutline in the opposite channel if it is present.
|
||||
linked->ExpandCutLine(capturedTrackLocation.pos);
|
||||
linked->ExpandCutLine(mLocation.pos);
|
||||
|
||||
viewInfo.selectedRegion.setTimes(cutlineStart, cutlineEnd);
|
||||
result |= UpdateSelection;
|
||||
}
|
||||
else if (capturedTrackLocation.typ == WaveTrackLocation::locationMergePoint) {
|
||||
const double pos = capturedTrackLocation.pos;
|
||||
wavetrack->MergeClips(capturedTrackLocation.clipidx1, capturedTrackLocation.clipidx2);
|
||||
else if (mLocation.typ == WaveTrackLocation::locationMergePoint) {
|
||||
const double pos = mLocation.pos;
|
||||
mpTrack->MergeClips(mLocation.clipidx1, mLocation.clipidx2);
|
||||
|
||||
if (linked) {
|
||||
// Don't assume correspondence of merge points across channels!
|
||||
|
@ -194,10 +186,10 @@ UIHandle::Result CutlineHandle::Click
|
|||
}
|
||||
else if (event.RightDown())
|
||||
{
|
||||
bool removed = wavetrack->RemoveCutLine(capturedTrackLocation.pos);
|
||||
bool removed = mpTrack->RemoveCutLine(mLocation.pos);
|
||||
|
||||
if (linked)
|
||||
removed = linked->RemoveCutLine(capturedTrackLocation.pos) || removed;
|
||||
removed = linked->RemoveCutLine(mLocation.pos) || removed;
|
||||
|
||||
if (!removed)
|
||||
// Nothing happened, make no Undo item
|
||||
|
@ -221,7 +213,8 @@ HitTestPreview CutlineHandle::Preview
|
|||
(const TrackPanelMouseState &, const AudacityProject *pProject)
|
||||
{
|
||||
const bool unsafe = pProject->IsAudioActive();
|
||||
return HitPreview( mbCutline, unsafe );
|
||||
auto bCutline = (mLocation.typ == WaveTrackLocation::locationCutLine);
|
||||
return HitPreview( bCutline, unsafe );
|
||||
}
|
||||
|
||||
UIHandle::Result CutlineHandle::Release
|
||||
|
|
|
@ -11,30 +11,43 @@ Paul Licameli
|
|||
#ifndef __AUDACITY_CUTLINE_HANDLE__
|
||||
#define __AUDACITY_CUTLINE_HANDLE__
|
||||
|
||||
#include "../../../../MemoryX.h"
|
||||
#include "../../../../UIHandle.h"
|
||||
#include "../../../../MemoryX.h"
|
||||
#include "../../../../WaveTrackLocation.h"
|
||||
|
||||
class wxMouseEvent;
|
||||
class wxMouseState;
|
||||
struct HitTestResult;
|
||||
class WaveTrack;
|
||||
|
||||
using UIHandlePtr = std::shared_ptr<UIHandle>;
|
||||
|
||||
class CutlineHandle final : public UIHandle
|
||||
{
|
||||
CutlineHandle();
|
||||
CutlineHandle(const CutlineHandle&) = delete;
|
||||
CutlineHandle &operator=(const CutlineHandle&) = delete;
|
||||
static CutlineHandle& Instance();
|
||||
static HitTestPreview HitPreview(bool cutline, bool unsafe);
|
||||
|
||||
public:
|
||||
static HitTestResult HitAnywhere(const AudacityProject *pProject, bool cutline);
|
||||
explicit CutlineHandle
|
||||
( const std::shared_ptr<WaveTrack> &pTrack,
|
||||
WaveTrackLocation location );
|
||||
|
||||
CutlineHandle &operator=(const CutlineHandle&) = default;
|
||||
|
||||
static HitTestResult HitAnywhere
|
||||
(const AudacityProject *pProject, bool cutline, UIHandlePtr ptr);
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &pTrack);
|
||||
(std::weak_ptr<CutlineHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject,
|
||||
const std::shared_ptr<WaveTrack> &pTrack);
|
||||
|
||||
virtual ~CutlineHandle();
|
||||
|
||||
const WaveTrackLocation &GetLocation() { return mLocation; }
|
||||
std::shared_ptr<WaveTrack> GetTrack() { return mpTrack; }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
@ -57,7 +70,8 @@ private:
|
|||
enum Operation { Merge, Expand, Remove };
|
||||
Operation mOperation{ Merge };
|
||||
double mStartTime{}, mEndTime{};
|
||||
bool mbCutline{};
|
||||
WaveTrackLocation mLocation {};
|
||||
std::shared_ptr<WaveTrack> mpTrack{};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,15 +34,9 @@ static const int SMOOTHING_BRUSH_RADIUS = 5;
|
|||
static const double SMOOTHING_PROPORTION_MAX = 0.7;
|
||||
static const double SMOOTHING_PROPORTION_MIN = 0.0;
|
||||
|
||||
SampleHandle::SampleHandle()
|
||||
{
|
||||
}
|
||||
|
||||
SampleHandle &SampleHandle::Instance()
|
||||
{
|
||||
static SampleHandle instance;
|
||||
return instance;
|
||||
}
|
||||
SampleHandle::SampleHandle( const std::shared_ptr<WaveTrack> &pTrack )
|
||||
: mClickedTrack{ pTrack }
|
||||
{}
|
||||
|
||||
HitTestPreview SampleHandle::HitPreview
|
||||
(const wxMouseState &state, const AudacityProject *pProject, bool unsafe)
|
||||
|
@ -64,10 +58,14 @@ HitTestPreview SampleHandle::HitPreview
|
|||
}
|
||||
|
||||
HitTestResult SampleHandle::HitAnywhere
|
||||
(const wxMouseState &state, const AudacityProject *pProject)
|
||||
(std::weak_ptr<SampleHandle> &holder,
|
||||
const wxMouseState &state, const AudacityProject *pProject,
|
||||
const std::shared_ptr<WaveTrack> &pTrack)
|
||||
{
|
||||
auto result = std::make_shared<SampleHandle>( pTrack );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
const bool unsafe = pProject->IsAudioActive();
|
||||
return { HitPreview(state, pProject, unsafe), &Instance() };
|
||||
return { HitPreview(state, pProject, unsafe), result };
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -100,16 +98,12 @@ namespace {
|
|||
}
|
||||
|
||||
HitTestResult SampleHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<SampleHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &pTrack)
|
||||
{
|
||||
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
|
||||
/// method that tells us if the mouse event landed on an
|
||||
/// editable sample
|
||||
if (pTrack->GetKind() != Track::Wave)
|
||||
return {};
|
||||
|
||||
WaveTrack *wavetrack = pTrack.get();
|
||||
|
||||
const int displayType = wavetrack->GetDisplay();
|
||||
|
@ -155,7 +149,7 @@ HitTestResult SampleHandle::HitTest
|
|||
if (abs(yValue - yMouse) >= yTolerance)
|
||||
return {};
|
||||
|
||||
return HitAnywhere(state, pProject);
|
||||
return HitAnywhere(holder, state, pProject, pTrack);
|
||||
}
|
||||
|
||||
SampleHandle::~SampleHandle()
|
||||
|
@ -209,15 +203,14 @@ UIHandle::Result SampleHandle::Click
|
|||
const wxMouseEvent &event = evt.event;
|
||||
const wxRect &rect = evt.rect;
|
||||
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
const auto pTrack = std::static_pointer_cast<WaveTrack>(evt.pCell);
|
||||
const auto pTrack = mClickedTrack.get();
|
||||
|
||||
/// Someone has just clicked the mouse. What do we do?
|
||||
if (!IsSampleEditingPossible(
|
||||
event, rect, viewInfo, pTrack.get(), rect.width))
|
||||
event, rect, viewInfo, pTrack, rect.width))
|
||||
return Cancelled;
|
||||
|
||||
/// We're in a track view and zoomed enough to see the samples.
|
||||
mClickedTrack = pTrack;
|
||||
mRect = rect;
|
||||
|
||||
//If we are still around, we are drawing in earnest. Set some member data structures up:
|
||||
|
|
|
@ -26,22 +26,28 @@ class WaveTrack;
|
|||
|
||||
class SampleHandle final : public UIHandle
|
||||
{
|
||||
SampleHandle();
|
||||
SampleHandle(const SampleHandle&) = delete;
|
||||
SampleHandle &operator=(const SampleHandle&) = delete;
|
||||
static SampleHandle& Instance();
|
||||
static HitTestPreview HitPreview
|
||||
(const wxMouseState &state, const AudacityProject *pProject, bool unsafe);
|
||||
|
||||
public:
|
||||
explicit SampleHandle( const std::shared_ptr<WaveTrack> &pTrack );
|
||||
|
||||
SampleHandle &operator=(const SampleHandle&) = default;
|
||||
|
||||
static HitTestResult HitAnywhere
|
||||
(const wxMouseState &state, const AudacityProject *pProject);
|
||||
(std::weak_ptr<SampleHandle> &holder,
|
||||
const wxMouseState &state, const AudacityProject *pProject,
|
||||
const std::shared_ptr<WaveTrack> &pTrack);
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<SampleHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &pTrack);
|
||||
|
||||
virtual ~SampleHandle();
|
||||
|
||||
std::shared_ptr<WaveTrack> GetTrack() const { return mClickedTrack; }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
|
|
@ -63,22 +63,20 @@ HitTestResult WaveTrackControls::HitTest
|
|||
auto track = FindTrack();
|
||||
if (track && track->GetKind() == Track::Wave) {
|
||||
HitTestResult result;
|
||||
if (NULL !=
|
||||
(result = MuteButtonHandle::HitTest
|
||||
(state, rect, pProject, track)).handle)
|
||||
if (NULL != (result = MuteButtonHandle::HitTest(
|
||||
mMuteHandle, state, rect, pProject, track)).handle)
|
||||
return result;
|
||||
|
||||
if (NULL !=
|
||||
(result = SoloButtonHandle::HitTest
|
||||
(state, rect, pProject, track)).handle)
|
||||
if (NULL != (result = SoloButtonHandle::HitTest(
|
||||
mSoloHandle, state, rect, pProject, track)).handle)
|
||||
return result;
|
||||
|
||||
if (NULL != (result =
|
||||
GainSliderHandle::HitTest(state, rect, pProject, track)).handle)
|
||||
if (NULL != (result = GainSliderHandle::HitTest(
|
||||
mGainHandle, state, rect, pProject, track)).handle)
|
||||
return result;
|
||||
|
||||
if (NULL != (result =
|
||||
PanSliderHandle::HitTest(state, rect, pProject, track)).handle)
|
||||
if (NULL != (result = PanSliderHandle::HitTest(
|
||||
mPanHandle, state, rect, pProject, track)).handle)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,11 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "../../../ui/TrackControls.h"
|
||||
|
||||
class MuteButtonHandle;
|
||||
class SoloButtonHandle;
|
||||
class GainSliderHandle;
|
||||
class PanSliderHandle;
|
||||
|
||||
class WaveTrackControls final : public TrackControls
|
||||
{
|
||||
WaveTrackControls(const WaveTrackControls&) = delete;
|
||||
|
@ -29,6 +34,12 @@ public:
|
|||
const AudacityProject *pProject) override;
|
||||
|
||||
PopupMenuTable *GetMenuExtension(Track *pTrack) override;
|
||||
|
||||
private:
|
||||
std::weak_ptr<MuteButtonHandle> mMuteHandle;
|
||||
std::weak_ptr<SoloButtonHandle> mSoloHandle;
|
||||
std::weak_ptr<GainSliderHandle> mGainHandle;
|
||||
std::weak_ptr<PanSliderHandle> mPanHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,21 +19,15 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../../../UndoManager.h"
|
||||
#include "../../../../WaveTrack.h"
|
||||
|
||||
GainSliderHandle::GainSliderHandle()
|
||||
: SliderHandle()
|
||||
{
|
||||
}
|
||||
GainSliderHandle::GainSliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect, const std::shared_ptr<Track> &pTrack )
|
||||
: SliderHandle{ sliderFn, rect, pTrack }
|
||||
{}
|
||||
|
||||
GainSliderHandle::~GainSliderHandle()
|
||||
{
|
||||
}
|
||||
|
||||
GainSliderHandle &GainSliderHandle::Instance()
|
||||
{
|
||||
static GainSliderHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::shared_ptr<WaveTrack> GainSliderHandle::GetWaveTrack()
|
||||
{
|
||||
return std::static_pointer_cast<WaveTrack>(mpTrack.lock());
|
||||
|
@ -70,7 +64,8 @@ UIHandle::Result GainSliderHandle::CommitChanges
|
|||
}
|
||||
|
||||
HitTestResult GainSliderHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<GainSliderHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *, const std::shared_ptr<Track> &pTrack)
|
||||
{
|
||||
if (!state.ButtonIsDown(wxMOUSE_BTN_LEFT))
|
||||
|
@ -83,19 +78,19 @@ HitTestResult GainSliderHandle::HitTest
|
|||
if (sliderRect.Contains(state.m_x, state.m_y)) {
|
||||
wxRect sliderRect;
|
||||
TrackInfo::GetGainRect(rect.GetTopLeft(), sliderRect);
|
||||
|
||||
Instance().mSliderFn =
|
||||
auto sliderFn =
|
||||
[]( AudacityProject *pProject, const wxRect &sliderRect, Track *pTrack ) {
|
||||
return TrackInfo::GainSlider
|
||||
(sliderRect, static_cast<WaveTrack*>( pTrack ), true,
|
||||
const_cast<TrackPanel*>(pProject->GetTrackPanel()));
|
||||
};
|
||||
Instance().mRect = sliderRect;
|
||||
Instance().mpTrack = pTrack;
|
||||
auto result =
|
||||
std::make_shared<GainSliderHandle>( sliderFn, sliderRect, pTrack );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
|
||||
return {
|
||||
HitPreview(),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
else
|
||||
|
@ -104,21 +99,15 @@ HitTestResult GainSliderHandle::HitTest
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PanSliderHandle::PanSliderHandle()
|
||||
: SliderHandle()
|
||||
{
|
||||
}
|
||||
PanSliderHandle::PanSliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect, const std::shared_ptr<Track> &pTrack )
|
||||
: SliderHandle{ sliderFn, rect, pTrack }
|
||||
{}
|
||||
|
||||
PanSliderHandle::~PanSliderHandle()
|
||||
{
|
||||
}
|
||||
|
||||
PanSliderHandle &PanSliderHandle::Instance()
|
||||
{
|
||||
static PanSliderHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::shared_ptr<WaveTrack> PanSliderHandle::GetWaveTrack()
|
||||
{
|
||||
return std::static_pointer_cast<WaveTrack>(mpTrack.lock());
|
||||
|
@ -167,7 +156,8 @@ UIHandle::Result PanSliderHandle::CommitChanges
|
|||
}
|
||||
|
||||
HitTestResult PanSliderHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<PanSliderHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack)
|
||||
{
|
||||
if (!state.ButtonIsDown(wxMOUSE_BTN_LEFT))
|
||||
|
@ -178,18 +168,19 @@ HitTestResult PanSliderHandle::HitTest
|
|||
if ( TrackInfo::HideTopItem( rect, sliderRect, kTrackInfoSliderAllowance ) )
|
||||
return {};
|
||||
if (sliderRect.Contains(state.m_x, state.m_y)) {
|
||||
Instance().mSliderFn =
|
||||
auto sliderFn =
|
||||
[]( AudacityProject *pProject, const wxRect &sliderRect, Track *pTrack ) {
|
||||
return TrackInfo::PanSlider
|
||||
(sliderRect, static_cast<WaveTrack*>( pTrack ), true,
|
||||
const_cast<TrackPanel*>(pProject->GetTrackPanel()));
|
||||
};
|
||||
Instance().mRect = sliderRect;
|
||||
Instance().mpTrack = pTrack;
|
||||
auto result = std::make_shared<PanSliderHandle>(
|
||||
sliderFn, sliderRect, pTrack );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
|
||||
return {
|
||||
HitPreview(),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
else
|
||||
|
|
|
@ -21,14 +21,18 @@ struct HitTestResult;
|
|||
class GainSliderHandle final : public SliderHandle
|
||||
{
|
||||
GainSliderHandle(const GainSliderHandle&) = delete;
|
||||
GainSliderHandle &operator=(const GainSliderHandle&) = delete;
|
||||
|
||||
GainSliderHandle();
|
||||
virtual ~GainSliderHandle();
|
||||
static GainSliderHandle& Instance();
|
||||
|
||||
std::shared_ptr<WaveTrack> GetWaveTrack();
|
||||
|
||||
public:
|
||||
explicit GainSliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect,
|
||||
const std::shared_ptr<Track> &pTrack );
|
||||
|
||||
GainSliderHandle &operator=(const GainSliderHandle&) = default;
|
||||
|
||||
virtual ~GainSliderHandle();
|
||||
|
||||
protected:
|
||||
float GetValue() override;
|
||||
Result SetValue
|
||||
|
@ -40,7 +44,8 @@ protected:
|
|||
|
||||
public:
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<GainSliderHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
|
||||
};
|
||||
|
||||
|
@ -49,14 +54,18 @@ public:
|
|||
class PanSliderHandle final : public SliderHandle
|
||||
{
|
||||
PanSliderHandle(const PanSliderHandle&) = delete;
|
||||
PanSliderHandle &operator=(const PanSliderHandle&) = delete;
|
||||
|
||||
PanSliderHandle();
|
||||
virtual ~PanSliderHandle();
|
||||
static PanSliderHandle& Instance();
|
||||
|
||||
std::shared_ptr<WaveTrack> GetWaveTrack();
|
||||
|
||||
public:
|
||||
explicit PanSliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect,
|
||||
const std::shared_ptr<Track> &pTrack );
|
||||
|
||||
PanSliderHandle &operator=(const PanSliderHandle&) = default;
|
||||
|
||||
virtual ~PanSliderHandle();
|
||||
|
||||
protected:
|
||||
float GetValue() override;
|
||||
Result SetValue(AudacityProject *pProject, float newValue) override;
|
||||
|
@ -67,7 +76,8 @@ protected:
|
|||
|
||||
public:
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<PanSliderHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<Track> &pTrack);
|
||||
};
|
||||
|
||||
|
|
|
@ -39,44 +39,51 @@ HitTestResult WaveTrack::DetailedHitTest
|
|||
// Ctrl modifier key in multi-tool overrides everything else
|
||||
// (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);
|
||||
return TimeShiftHandle::HitAnywhere(
|
||||
mTimeShiftHandle, pProject, Pointer(this), false);
|
||||
|
||||
// Some special targets are not drawn in spectrogram,
|
||||
// so don't hit them in such views.
|
||||
else if (isWaveform) {
|
||||
HitTestResult result;
|
||||
if (NULL !=
|
||||
(result = CutlineHandle::HitTest
|
||||
(st.state, st.rect, pProject, Pointer<WaveTrack>(this)))
|
||||
.preview.cursor)
|
||||
// This overriding test applies in all tools
|
||||
return result;
|
||||
if (NULL != (result = CutlineHandle::HitTest(
|
||||
mCutlineHandle, st.state, st.rect,
|
||||
pProject, Pointer<WaveTrack>(this))).preview.cursor)
|
||||
// This overriding test applies in all tools
|
||||
return result;
|
||||
else if (bMultiTool) {
|
||||
// Conditional hit tests
|
||||
// If Tools toolbar were eliminated, we would keep these
|
||||
// The priority of these, in case more than one might apply at one
|
||||
// point, seems arbitrary
|
||||
if (NULL != (result = EnvelopeHandle::WaveTrackHitTest
|
||||
(st.state, st.rect, pProject, Pointer<WaveTrack>(this)))
|
||||
.preview.cursor)
|
||||
if (NULL != (result = EnvelopeHandle::WaveTrackHitTest(
|
||||
mEnvelopeHandle, st.state, st.rect,
|
||||
pProject, Pointer<WaveTrack>(this)))
|
||||
.preview.cursor)
|
||||
;
|
||||
else if (NULL != (result = TimeShiftHandle::HitTest
|
||||
(st.state, st.rect, pProject)).preview.cursor)
|
||||
else if (NULL != (result = TimeShiftHandle::HitTest(
|
||||
mTimeShiftHandle, st.state, st.rect,
|
||||
pProject, Pointer(this))).preview.cursor)
|
||||
// This is the hit test on the "grips" drawn left and
|
||||
// right in Multi only
|
||||
;
|
||||
else if (NULL != (result = SampleHandle::HitTest
|
||||
(st.state, st.rect, pProject, Pointer<WaveTrack>(this))).preview.cursor)
|
||||
else if (NULL != (result = SampleHandle::HitTest(
|
||||
mSampleHandle, st.state, st.rect,
|
||||
pProject, Pointer<WaveTrack>(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 envelopeTool: {
|
||||
auto envelope = GetEnvelopeAtX( st.state.m_x );
|
||||
return EnvelopeHandle::HitAnywhere(
|
||||
mEnvelopeHandle, pProject, envelope);
|
||||
}
|
||||
case drawTool:
|
||||
return SampleHandle::HitAnywhere(st.state, pProject);
|
||||
return SampleHandle::HitAnywhere(
|
||||
mSampleHandle, st.state, pProject, Pointer<WaveTrack>(this));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,14 @@ HitTestResult WaveTrackVRulerControls::HitTest
|
|||
(const TrackPanelMouseState &st,
|
||||
const AudacityProject *)
|
||||
{
|
||||
return WaveTrackVZoomHandle::HitTest(st.state);
|
||||
auto pTrack = Track::Pointer<WaveTrack>( FindTrack().get() );
|
||||
if (pTrack) {
|
||||
auto result = std::make_shared<WaveTrackVZoomHandle>(
|
||||
pTrack, st.rect, st.state.m_y );
|
||||
result = AssignUIHandlePtr(mVZoomHandle, result);
|
||||
return WaveTrackVZoomHandle::HitTest(st.state, result);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
unsigned WaveTrackVRulerControls::HandleWheelRotation
|
||||
|
|
|
@ -13,6 +13,8 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "../../../ui/TrackVRulerControls.h"
|
||||
|
||||
class WaveTrackVZoomHandle;
|
||||
|
||||
class WaveTrackVRulerControls final : public TrackVRulerControls
|
||||
{
|
||||
WaveTrackVRulerControls(const WaveTrackVRulerControls&) = delete;
|
||||
|
@ -31,6 +33,9 @@ public:
|
|||
unsigned HandleWheelRotation
|
||||
(const TrackPanelMouseEvent &event,
|
||||
AudacityProject *pProject) override;
|
||||
|
||||
private:
|
||||
std::weak_ptr<WaveTrackVZoomHandle> mVZoomHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,6 +43,12 @@ bool IsDragZooming(int zoomStart, int zoomEnd)
|
|||
|
||||
}
|
||||
|
||||
WaveTrackVZoomHandle::WaveTrackVZoomHandle
|
||||
(const std::shared_ptr<WaveTrack> &pTrack, const wxRect &rect, int y)
|
||||
: mZoomStart(y), mZoomEnd(y), mRect(rect)
|
||||
, mpTrack{ pTrack }
|
||||
{}
|
||||
|
||||
void WaveTrackVZoomHandle::DoZoom
|
||||
(AudacityProject *pProject,
|
||||
WaveTrack *pTrack, bool shiftDown, bool rightUp,
|
||||
|
@ -480,16 +486,6 @@ void SpectrumVRulerMenuTable::OnSpectrumScaleType(wxCommandEvent &evt)
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WaveTrackVZoomHandle::WaveTrackVZoomHandle()
|
||||
{
|
||||
}
|
||||
|
||||
WaveTrackVZoomHandle &WaveTrackVZoomHandle::Instance()
|
||||
{
|
||||
static WaveTrackVZoomHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
HitTestPreview WaveTrackVZoomHandle::HitPreview(const wxMouseState &state)
|
||||
{
|
||||
static auto zoomInCursor =
|
||||
|
@ -502,9 +498,10 @@ HitTestPreview WaveTrackVZoomHandle::HitPreview(const wxMouseState &state)
|
|||
};
|
||||
}
|
||||
|
||||
HitTestResult WaveTrackVZoomHandle::HitTest(const wxMouseState &state)
|
||||
HitTestResult WaveTrackVZoomHandle::HitTest
|
||||
(const wxMouseState &state, UIHandlePtr result)
|
||||
{
|
||||
return { HitPreview(state), &Instance() };
|
||||
return { HitPreview(state), result };
|
||||
}
|
||||
|
||||
WaveTrackVZoomHandle::~WaveTrackVZoomHandle()
|
||||
|
@ -512,16 +509,8 @@ WaveTrackVZoomHandle::~WaveTrackVZoomHandle()
|
|||
}
|
||||
|
||||
UIHandle::Result WaveTrackVZoomHandle::Click
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *)
|
||||
(const TrackPanelMouseEvent &, AudacityProject *)
|
||||
{
|
||||
mpTrack = std::static_pointer_cast<WaveTrack>(
|
||||
static_cast<WaveTrackVRulerControls*>(evt.pCell.get())->FindTrack() );
|
||||
mRect = evt.rect;
|
||||
|
||||
const wxMouseEvent &event = evt.event;
|
||||
mZoomStart = event.m_y;
|
||||
mZoomEnd = event.m_y;
|
||||
|
||||
return RefreshCode::RefreshNone;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,14 +21,16 @@ struct HitTestResult;
|
|||
|
||||
class WaveTrackVZoomHandle : public UIHandle
|
||||
{
|
||||
WaveTrackVZoomHandle();
|
||||
WaveTrackVZoomHandle(const WaveTrackVZoomHandle&);
|
||||
WaveTrackVZoomHandle &operator=(const WaveTrackVZoomHandle&);
|
||||
static WaveTrackVZoomHandle& Instance();
|
||||
static HitTestPreview HitPreview(const wxMouseState &state);
|
||||
|
||||
public:
|
||||
static HitTestResult HitTest(const wxMouseState &state);
|
||||
explicit WaveTrackVZoomHandle
|
||||
(const std::shared_ptr<WaveTrack> &pTrack, const wxRect &rect, int y);
|
||||
|
||||
WaveTrackVZoomHandle &operator=(const WaveTrackVZoomHandle&) = default;
|
||||
|
||||
static HitTestResult HitTest(const wxMouseState &state, UIHandlePtr result);
|
||||
|
||||
static void DoZoom
|
||||
(AudacityProject *pProject,
|
||||
|
@ -38,6 +40,8 @@ public:
|
|||
|
||||
virtual ~WaveTrackVZoomHandle();
|
||||
|
||||
std::shared_ptr<WaveTrack> GetTrack() const { return mpTrack.lock(); }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ HitTestResult TimeTrack::DetailedHitTest
|
|||
const AudacityProject *pProject, int, bool)
|
||||
{
|
||||
return EnvelopeHandle::TimeTrackHitTest
|
||||
( st.state, st.rect, pProject, Pointer<TimeTrack>(this) );
|
||||
( mEnvelopeHandle, st.state, st.rect, pProject, Pointer<TimeTrack>(this) );
|
||||
}
|
||||
|
||||
std::shared_ptr<TrackControls> TimeTrack::GetControls()
|
||||
|
|
|
@ -20,76 +20,68 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include <wx/cursor.h>
|
||||
#include <wx/event.h>
|
||||
|
||||
namespace
|
||||
// Define this, just so the click to deselect can dispatch here
|
||||
// This handle class, unlike most, doesn't associate with any particular cell.
|
||||
class BackgroundHandle : public UIHandle
|
||||
{
|
||||
// Define this, just so the click to deselect can dispatch here
|
||||
class BackgroundHandle : public UIHandle
|
||||
BackgroundHandle(const BackgroundHandle&) = delete;
|
||||
BackgroundHandle &operator=(const BackgroundHandle&) = delete;
|
||||
|
||||
public:
|
||||
BackgroundHandle() {}
|
||||
|
||||
static HitTestPreview HitPreview()
|
||||
{
|
||||
BackgroundHandle() {}
|
||||
BackgroundHandle(const BackgroundHandle&) = delete;
|
||||
BackgroundHandle &operator=(const BackgroundHandle&) = delete;
|
||||
static wxCursor arrowCursor{ wxCURSOR_ARROW };
|
||||
return { {}, &arrowCursor };
|
||||
}
|
||||
|
||||
public:
|
||||
static HitTestResult HitAnywhere(UIHandlePtr result)
|
||||
{
|
||||
return {
|
||||
HitPreview(),
|
||||
result
|
||||
};
|
||||
}
|
||||
|
||||
static BackgroundHandle& Instance()
|
||||
{
|
||||
static BackgroundHandle instance;
|
||||
return instance;
|
||||
virtual ~BackgroundHandle()
|
||||
{}
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject) override
|
||||
{
|
||||
using namespace RefreshCode;
|
||||
const wxMouseEvent &event = evt.event;
|
||||
// Do not start a drag
|
||||
Result result = Cancelled;
|
||||
|
||||
// AS: If the user clicked outside all tracks, make nothing
|
||||
// selected.
|
||||
if ((event.ButtonDown() || event.ButtonDClick())) {
|
||||
pProject->GetSelectionState().SelectNone
|
||||
( *pProject->GetTracks(), pProject->GetMixerBoard() );
|
||||
result |= RefreshAll;
|
||||
}
|
||||
|
||||
static HitTestPreview HitPreview()
|
||||
{
|
||||
static wxCursor arrowCursor{ wxCURSOR_ARROW };
|
||||
return { {}, &arrowCursor };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static HitTestResult HitAnywhere()
|
||||
{
|
||||
return {
|
||||
HitPreview(),
|
||||
&BackgroundHandle::Instance()
|
||||
};
|
||||
}
|
||||
Result Drag
|
||||
(const TrackPanelMouseEvent &, AudacityProject *) override
|
||||
{ return RefreshCode::RefreshNone; }
|
||||
|
||||
virtual ~BackgroundHandle()
|
||||
{}
|
||||
HitTestPreview Preview
|
||||
(const TrackPanelMouseState &, const AudacityProject *) override
|
||||
{ return HitPreview(); }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject) override
|
||||
{
|
||||
using namespace RefreshCode;
|
||||
const wxMouseEvent &event = evt.event;
|
||||
// Do not start a drag
|
||||
Result result = Cancelled;
|
||||
Result Release
|
||||
(const TrackPanelMouseEvent &, AudacityProject *,
|
||||
wxWindow *) override
|
||||
{ return RefreshCode::RefreshNone; }
|
||||
|
||||
// AS: If the user clicked outside all tracks, make nothing
|
||||
// selected.
|
||||
if ((event.ButtonDown() || event.ButtonDClick())) {
|
||||
pProject->GetSelectionState().SelectNone
|
||||
( *pProject->GetTracks(), pProject->GetMixerBoard() );
|
||||
result |= RefreshAll;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result Drag
|
||||
(const TrackPanelMouseEvent &, AudacityProject *) override
|
||||
{ return RefreshCode::RefreshNone; }
|
||||
|
||||
HitTestPreview Preview
|
||||
(const TrackPanelMouseState &, const AudacityProject *) override
|
||||
{ return HitPreview(); }
|
||||
|
||||
Result Release
|
||||
(const TrackPanelMouseEvent &, AudacityProject *,
|
||||
wxWindow *) override
|
||||
{ return RefreshCode::RefreshNone; }
|
||||
|
||||
Result Cancel(AudacityProject *) override
|
||||
{ return RefreshCode::RefreshNone; }
|
||||
};
|
||||
}
|
||||
Result Cancel(AudacityProject *) override
|
||||
{ return RefreshCode::RefreshNone; }
|
||||
};
|
||||
|
||||
BackgroundCell::~BackgroundCell()
|
||||
{
|
||||
|
@ -99,7 +91,10 @@ HitTestResult BackgroundCell::HitTest
|
|||
(const TrackPanelMouseState &,
|
||||
const AudacityProject *)
|
||||
{
|
||||
return BackgroundHandle::HitAnywhere();
|
||||
auto result = mHandle.lock();
|
||||
if (!result)
|
||||
result = std::make_shared<BackgroundHandle>();
|
||||
return BackgroundHandle::HitAnywhere(result);
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> BackgroundCell::FindTrack()
|
||||
|
|
|
@ -12,9 +12,13 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#define __AUDACITY_BACKGROUND_CELL__
|
||||
|
||||
#include "CommonTrackPanelCell.h"
|
||||
#include "../../MemoryX.h"
|
||||
|
||||
class AudacityProject;
|
||||
|
||||
class BackgroundHandle;
|
||||
class ZoomHandle;
|
||||
|
||||
class BackgroundCell final : public CommonTrackPanelCell
|
||||
{
|
||||
public:
|
||||
|
@ -33,6 +37,12 @@ protected:
|
|||
|
||||
private:
|
||||
AudacityProject *mpProject;
|
||||
|
||||
std::weak_ptr<BackgroundHandle> mHandle;
|
||||
|
||||
public:
|
||||
// For want of a better place...
|
||||
std::weak_ptr<ZoomHandle> mZoomHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,10 +20,12 @@ Paul Licameli
|
|||
#include "../../TrackPanelMouseEvent.h"
|
||||
#include "../ui/TrackControls.h"
|
||||
|
||||
ButtonHandle::ButtonHandle(int dragCode)
|
||||
: mDragCode(dragCode)
|
||||
{
|
||||
}
|
||||
ButtonHandle::ButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect, int dragCode )
|
||||
: mpTrack{ pTrack }
|
||||
, mRect{ rect }
|
||||
, mDragCode{ dragCode }
|
||||
{}
|
||||
|
||||
ButtonHandle::~ButtonHandle()
|
||||
{
|
||||
|
@ -36,10 +38,10 @@ HitTestPreview ButtonHandle::HitPreview()
|
|||
}
|
||||
|
||||
UIHandle::Result ButtonHandle::Click
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *)
|
||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||
{
|
||||
using namespace RefreshCode;
|
||||
auto pTrack = static_cast<TrackControls*>(evt.pCell.get())->FindTrack();
|
||||
auto pTrack = pProject->GetTracks()->Lock(mpTrack);
|
||||
if ( !pTrack )
|
||||
return Cancelled;
|
||||
|
||||
|
@ -49,7 +51,6 @@ UIHandle::Result ButtonHandle::Click
|
|||
|
||||
// Come here for left click or double click
|
||||
if (mRect.Contains(event.m_x, event.m_y)) {
|
||||
mpTrack = pTrack;
|
||||
TrackControls::gCaptureState = mDragCode;
|
||||
// Toggle visible button state
|
||||
return RefreshCell;
|
||||
|
|
|
@ -22,10 +22,13 @@ class Track;
|
|||
class ButtonHandle /* not final */ : public UIHandle
|
||||
{
|
||||
ButtonHandle(const ButtonHandle&) = delete;
|
||||
ButtonHandle &operator=(const ButtonHandle&) = delete;
|
||||
|
||||
protected:
|
||||
explicit ButtonHandle(int dragCode);
|
||||
explicit ButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect, int dragCode );
|
||||
|
||||
ButtonHandle &operator=(const ButtonHandle&) = default;
|
||||
|
||||
virtual ~ButtonHandle();
|
||||
|
||||
// This new abstract virtual simplifies the duties of further subclasses.
|
||||
|
@ -54,9 +57,9 @@ protected:
|
|||
|
||||
Result Cancel(AudacityProject *pProject) override;
|
||||
|
||||
wxRect mRect {};
|
||||
std::weak_ptr<Track> mpTrack;
|
||||
const int mDragCode;
|
||||
wxRect mRect;
|
||||
int mDragCode;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,15 +26,12 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../WaveTrack.h"
|
||||
#include "../../../images/Cursors.h"
|
||||
|
||||
EnvelopeHandle::EnvelopeHandle()
|
||||
{
|
||||
}
|
||||
EnvelopeHandle::EnvelopeHandle( Envelope *pEnvelope )
|
||||
: mEnvelope{ pEnvelope }
|
||||
{}
|
||||
|
||||
EnvelopeHandle &EnvelopeHandle::Instance()
|
||||
{
|
||||
static EnvelopeHandle instance;
|
||||
return instance;
|
||||
}
|
||||
EnvelopeHandle::~EnvelopeHandle()
|
||||
{}
|
||||
|
||||
HitTestPreview EnvelopeHandle::HitPreview(const AudacityProject *pProject, bool unsafe)
|
||||
{
|
||||
|
@ -51,10 +48,13 @@ HitTestPreview EnvelopeHandle::HitPreview(const AudacityProject *pProject, bool
|
|||
};
|
||||
}
|
||||
|
||||
HitTestResult EnvelopeHandle::HitAnywhere(const AudacityProject *pProject)
|
||||
HitTestResult EnvelopeHandle::HitAnywhere
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const AudacityProject *pProject, Envelope *envelope)
|
||||
{
|
||||
const bool unsafe = pProject->IsAudioActive();
|
||||
return { HitPreview(pProject, unsafe), &Instance() };
|
||||
UIHandlePtr result = std::make_shared<EnvelopeHandle>( envelope );
|
||||
return { HitPreview(pProject, unsafe), result };
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -75,7 +75,8 @@ namespace {
|
|||
}
|
||||
|
||||
HitTestResult EnvelopeHandle::TimeTrackHitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<TimeTrack> &tt)
|
||||
{
|
||||
auto envelope = tt->GetEnvelope();
|
||||
|
@ -86,16 +87,17 @@ HitTestResult EnvelopeHandle::TimeTrackHitTest
|
|||
float zoomMin, zoomMax;
|
||||
GetTimeTrackData( *pProject, *tt, dBRange, dB, zoomMin, zoomMax);
|
||||
return EnvelopeHandle::HitEnvelope
|
||||
(state, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange);
|
||||
(holder, state, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange);
|
||||
}
|
||||
|
||||
HitTestResult EnvelopeHandle::WaveTrackHitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &wt)
|
||||
{
|
||||
/// method that tells us if the mouse event landed on an
|
||||
/// envelope boundary.
|
||||
const Envelope *const envelope = wt->GetEnvelopeAtX(state.GetX());
|
||||
Envelope *const envelope = wt->GetEnvelopeAtX(state.GetX());
|
||||
|
||||
if (!envelope)
|
||||
return {};
|
||||
|
@ -115,12 +117,13 @@ HitTestResult EnvelopeHandle::WaveTrackHitTest
|
|||
const float dBRange = wt->GetWaveformSettings().dBRange;
|
||||
|
||||
return EnvelopeHandle::HitEnvelope
|
||||
(state, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange);
|
||||
(holder, state, rect, pProject, envelope, zoomMin, zoomMax, dB, dBRange);
|
||||
}
|
||||
|
||||
HitTestResult EnvelopeHandle::HitEnvelope
|
||||
(const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject,
|
||||
const Envelope *envelope, float zoomMin, float zoomMax,
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject,
|
||||
Envelope *envelope, float zoomMin, float zoomMax,
|
||||
bool dB, float dBRange)
|
||||
{
|
||||
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
|
@ -167,11 +170,7 @@ HitTestResult EnvelopeHandle::HitEnvelope
|
|||
if (distance >= yTolerance)
|
||||
return {};
|
||||
|
||||
return HitAnywhere(pProject);
|
||||
}
|
||||
|
||||
EnvelopeHandle::~EnvelopeHandle()
|
||||
{
|
||||
return HitAnywhere(holder, pProject, envelope);
|
||||
}
|
||||
|
||||
UIHandle::Result EnvelopeHandle::Click
|
||||
|
@ -191,23 +190,21 @@ UIHandle::Result EnvelopeHandle::Click
|
|||
if (wt->GetDisplay() != WaveTrack::Waveform)
|
||||
return Cancelled;
|
||||
|
||||
auto clickedEnvelope =
|
||||
wt->GetEnvelopeAtX(event.GetX());
|
||||
if (!clickedEnvelope)
|
||||
if (!mEnvelope)
|
||||
return Cancelled;
|
||||
|
||||
mLog = !wt->GetWaveformSettings().isLinear();
|
||||
wt->GetDisplayBounds(&mLower, &mUpper);
|
||||
mdBRange = wt->GetWaveformSettings().dBRange;
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *clickedEnvelope, true );
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, true );
|
||||
mEnvelopeEditorRight.reset();
|
||||
|
||||
// Assume linked track is wave or null
|
||||
auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||
if (partner)
|
||||
{
|
||||
clickedEnvelope = partner->GetEnvelopeAtX(event.GetX());
|
||||
auto clickedEnvelope = partner->GetEnvelopeAtX(event.GetX());
|
||||
if (clickedEnvelope)
|
||||
mEnvelopeEditorRight =
|
||||
std::make_unique< EnvelopeEditor >( *clickedEnvelope, true );
|
||||
|
@ -216,12 +213,11 @@ UIHandle::Result EnvelopeHandle::Click
|
|||
else if (pTrack->GetKind() == Track::Time)
|
||||
{
|
||||
TimeTrack *const tt = static_cast<TimeTrack*>(pTrack);
|
||||
auto clickedEnvelope = tt->GetEnvelope();
|
||||
if (!clickedEnvelope)
|
||||
if (!mEnvelope)
|
||||
return Cancelled;
|
||||
GetTimeTrackData( *pProject, *tt, mdBRange, mLog, mLower, mUpper);
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *clickedEnvelope, false );
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, false );
|
||||
mEnvelopeEditorRight.reset();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -27,29 +27,36 @@ class WaveTrack;
|
|||
|
||||
class EnvelopeHandle final : public UIHandle
|
||||
{
|
||||
EnvelopeHandle();
|
||||
EnvelopeHandle(const EnvelopeHandle&) = delete;
|
||||
EnvelopeHandle &operator=(const EnvelopeHandle&) = delete;
|
||||
static EnvelopeHandle& Instance();
|
||||
static HitTestPreview HitPreview(const AudacityProject *pProject, bool unsafe);
|
||||
|
||||
static HitTestResult HitEnvelope
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject,
|
||||
const Envelope *envelope, float zoomMin, float zoomMax,
|
||||
Envelope *envelope, float zoomMin, float zoomMax,
|
||||
bool dB, float dBRange);
|
||||
|
||||
public:
|
||||
static HitTestResult HitAnywhere(const AudacityProject *pProject);
|
||||
static HitTestResult TimeTrackHitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<TimeTrack> &tt);
|
||||
static HitTestResult WaveTrackHitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &wt);
|
||||
explicit EnvelopeHandle( Envelope *pEnvelope );
|
||||
|
||||
virtual ~EnvelopeHandle();
|
||||
|
||||
static HitTestResult HitAnywhere
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const AudacityProject *pProject, Envelope *envelope);
|
||||
static HitTestResult TimeTrackHitTest
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<TimeTrack> &tt);
|
||||
static HitTestResult WaveTrackHitTest
|
||||
(std::weak_ptr<EnvelopeHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject, const std::shared_ptr<WaveTrack> &wt);
|
||||
|
||||
Envelope *GetEnvelope() const { return mEnvelope; }
|
||||
|
||||
Result Click
|
||||
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||
|
||||
|
@ -77,6 +84,7 @@ private:
|
|||
float mLower{}, mUpper{};
|
||||
double mdBRange{};
|
||||
|
||||
Envelope *mEnvelope{};
|
||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditor;
|
||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditorRight;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
#include "../../Audacity.h"
|
||||
#include "SelectHandle.h"
|
||||
|
||||
#include "Scrubbing.h"
|
||||
|
@ -54,16 +55,6 @@ bool SelectHandle::IsClicked() const
|
|||
return mSelectionStateChanger.get();
|
||||
}
|
||||
|
||||
SelectHandle::SelectHandle()
|
||||
{
|
||||
}
|
||||
|
||||
SelectHandle &SelectHandle::Instance()
|
||||
{
|
||||
static SelectHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// If we're in OnDemand mode, we may change the tip.
|
||||
|
@ -428,9 +419,31 @@ namespace
|
|||
}
|
||||
|
||||
HitTestResult SelectHandle::HitTest
|
||||
(const TrackPanelMouseState &st, const AudacityProject *pProject,
|
||||
(std::weak_ptr<SelectHandle> &holder,
|
||||
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.
|
||||
auto old = holder.lock();
|
||||
std::unique_ptr<SnapManager> oldSnapManager;
|
||||
wxInt64 oldSnapLeft = -1, oldSnapRight = -1;
|
||||
if (old) {
|
||||
// It should not have started listening to timer events
|
||||
wxASSERT( !old->mConnectedProject );
|
||||
oldSnapManager = std::move(old->mSnapManager);
|
||||
oldSnapLeft = old->mSnapLeft;
|
||||
oldSnapRight = old->mSnapRight;
|
||||
}
|
||||
|
||||
auto result = std::make_shared<SelectHandle>( pTrack );
|
||||
|
||||
// Copy the pre-dragging state
|
||||
result->mSnapManager = std::move( oldSnapManager );
|
||||
result->mSnapLeft = oldSnapLeft;
|
||||
result->mSnapRight = oldSnapRight;
|
||||
|
||||
const wxMouseState &state = st.state;
|
||||
const wxRect &rect = st.rect;
|
||||
|
||||
|
@ -465,7 +478,7 @@ HitTestResult SelectHandle::HitTest
|
|||
if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
|
||||
{
|
||||
MaySetOnDemandTip(pTrack.get(), tip);
|
||||
return { { tip, pCursor }, &Instance() };
|
||||
return { { tip, pCursor }, result };
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -510,9 +523,13 @@ HitTestResult SelectHandle::HitTest
|
|||
tip = ttb->GetMessageForTool(selectTool);
|
||||
}
|
||||
|
||||
return HitTestResult{ { tip, pCursor }, &Instance() };
|
||||
return HitTestResult{ { tip, pCursor }, result };
|
||||
}
|
||||
|
||||
SelectHandle::SelectHandle( const std::shared_ptr<Track> &pTrack )
|
||||
: mpTrack{ pTrack }
|
||||
{}
|
||||
|
||||
SelectHandle::~SelectHandle()
|
||||
{
|
||||
}
|
||||
|
@ -545,7 +562,8 @@ UIHandle::Result SelectHandle::Click
|
|||
using namespace RefreshCode;
|
||||
|
||||
wxMouseEvent &event = evt.event;
|
||||
const auto pTrack = static_cast<Track*>(evt.pCell.get());
|
||||
const auto sTrack = pProject->GetTracks()->Lock(mpTrack);
|
||||
const auto pTrack = sTrack.get();
|
||||
ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
|
||||
mMostRecentX = event.m_x;
|
||||
|
@ -598,7 +616,6 @@ UIHandle::Result SelectHandle::Click
|
|||
else if (!event.LeftDown())
|
||||
return Cancelled;
|
||||
|
||||
mpTrack = Track::Pointer( pTrack );
|
||||
mRect = evt.rect;
|
||||
mInitialSelection = viewInfo.selectedRegion;
|
||||
|
||||
|
@ -608,11 +625,12 @@ UIHandle::Result SelectHandle::Click
|
|||
|
||||
mSelectionBoundary = 0;
|
||||
|
||||
// We create a NEW snap manager in case any snap-points have changed
|
||||
mSnapManager = std::make_unique<SnapManager>(trackList, &viewInfo);
|
||||
|
||||
mSnapLeft = -1;
|
||||
mSnapRight = -1;
|
||||
if (!mSnapManager) {
|
||||
// We create a NEW snap manager in case any snap-points have changed
|
||||
mSnapManager = std::make_unique<SnapManager>(trackList, &viewInfo);
|
||||
mSnapLeft = -1;
|
||||
mSnapRight = -1;
|
||||
}
|
||||
|
||||
bool bShiftDown = event.ShiftDown();
|
||||
bool bCtrlDown = event.ControlDown();
|
||||
|
|
|
@ -30,17 +30,17 @@ class WaveTrack;
|
|||
|
||||
class SelectHandle : public wxEvtHandler, public UIHandle
|
||||
{
|
||||
SelectHandle();
|
||||
SelectHandle(const SelectHandle&);
|
||||
SelectHandle &operator=(const SelectHandle&);
|
||||
|
||||
public:
|
||||
static SelectHandle& Instance();
|
||||
explicit SelectHandle( const std::shared_ptr<Track> &pTrack );
|
||||
|
||||
// This always hits, but details of the hit vary with mouse position and
|
||||
// key state.
|
||||
static HitTestResult HitTest
|
||||
(const TrackPanelMouseState &state, const AudacityProject *pProject,
|
||||
(std::weak_ptr<SelectHandle> &holder,
|
||||
const TrackPanelMouseState &state, const AudacityProject *pProject,
|
||||
const std::shared_ptr<Track> &pTrack);
|
||||
|
||||
virtual ~SelectHandle();
|
||||
|
|
|
@ -16,9 +16,12 @@ Paul Licameli
|
|||
#include "../../RefreshCode.h"
|
||||
#include "../../TrackPanelMouseEvent.h"
|
||||
|
||||
SliderHandle::SliderHandle()
|
||||
{
|
||||
}
|
||||
SliderHandle::SliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect, const std::shared_ptr<Track> &pTrack )
|
||||
: mSliderFn{ sliderFn }
|
||||
, mRect{ rect }
|
||||
, mpTrack{ pTrack }
|
||||
{}
|
||||
|
||||
SliderHandle::~SliderHandle()
|
||||
{
|
||||
|
|
|
@ -22,10 +22,17 @@ class Track;
|
|||
class SliderHandle /* not final */ : public UIHandle
|
||||
{
|
||||
SliderHandle(const SliderHandle&) = delete;
|
||||
SliderHandle &operator=(const SliderHandle&) = delete;
|
||||
|
||||
public:
|
||||
using SliderFn = LWSlider *(*)( AudacityProject*, const wxRect&, Track* );
|
||||
|
||||
explicit SliderHandle
|
||||
( SliderFn sliderFn, const wxRect &rect,
|
||||
const std::shared_ptr<Track> &pTrack );
|
||||
|
||||
SliderHandle &operator=(const SliderHandle&) = default;
|
||||
|
||||
protected:
|
||||
SliderHandle();
|
||||
virtual ~SliderHandle();
|
||||
|
||||
// These new abstract virtuals simplify the duties of further subclasses.
|
||||
|
@ -59,7 +66,6 @@ protected:
|
|||
// Derived class is expected to set these two before Click():
|
||||
std::weak_ptr<Track> mpTrack;
|
||||
wxRect mRect{};
|
||||
using SliderFn = LWSlider *(*)( AudacityProject*, const wxRect&, Track* );
|
||||
SliderFn mSliderFn;
|
||||
LWSlider *GetSlider( AudacityProject *pProject );
|
||||
|
||||
|
|
|
@ -23,15 +23,11 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../WaveTrack.h"
|
||||
#include "../../../images/Cursors.h"
|
||||
|
||||
TimeShiftHandle::TimeShiftHandle()
|
||||
{
|
||||
}
|
||||
|
||||
TimeShiftHandle &TimeShiftHandle::Instance()
|
||||
{
|
||||
static TimeShiftHandle instance;
|
||||
return instance;
|
||||
}
|
||||
TimeShiftHandle::TimeShiftHandle
|
||||
( const std::shared_ptr<Track> &pTrack, bool gripHit )
|
||||
: mCapturedTrack{ pTrack }
|
||||
, mGripHit{ gripHit }
|
||||
{}
|
||||
|
||||
HitTestPreview TimeShiftHandle::HitPreview
|
||||
(const AudacityProject *pProject, bool unsafe)
|
||||
|
@ -49,16 +45,24 @@ HitTestPreview TimeShiftHandle::HitPreview
|
|||
};
|
||||
}
|
||||
|
||||
HitTestResult TimeShiftHandle::HitAnywhere(const AudacityProject *pProject)
|
||||
HitTestResult TimeShiftHandle::HitAnywhere
|
||||
(std::weak_ptr<TimeShiftHandle> &holder,
|
||||
const AudacityProject *pProject,
|
||||
const std::shared_ptr<Track> &pTrack, bool gripHit)
|
||||
{
|
||||
// After all that, it still may be unsafe to drag.
|
||||
// Even if so, make an informative cursor change from default to "banned."
|
||||
const bool unsafe = pProject->IsAudioActive();
|
||||
return { HitPreview(pProject, unsafe), &Instance() };
|
||||
auto result = std::make_shared<TimeShiftHandle>( pTrack, gripHit );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return { HitPreview(pProject, unsafe), result };
|
||||
}
|
||||
|
||||
HitTestResult TimeShiftHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject)
|
||||
(std::weak_ptr<TimeShiftHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject,
|
||||
const std::shared_ptr<Track> &pTrack)
|
||||
{
|
||||
/// method that tells us if the mouse event landed on a
|
||||
/// time-slider that allows us to time shift the sequence.
|
||||
|
@ -77,7 +81,7 @@ HitTestResult TimeShiftHandle::HitTest
|
|||
state.m_x + hotspotOffset >= rect.x + rect.width - adjustedDragHandleWidth))
|
||||
return {};
|
||||
|
||||
return HitAnywhere(pProject);
|
||||
return HitAnywhere( holder, pProject, pTrack, true );
|
||||
}
|
||||
|
||||
TimeShiftHandle::~TimeShiftHandle()
|
||||
|
@ -465,7 +469,6 @@ UIHandle::Result TimeShiftHandle::Click
|
|||
}
|
||||
|
||||
mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive;
|
||||
mCapturedTrack = pTrack;
|
||||
mRect = rect;
|
||||
mMouseClickX = event.m_x;
|
||||
const double selStart = viewInfo.PositionToTime(event.m_x, mRect.x);
|
||||
|
@ -506,6 +509,7 @@ UIHandle::Result TimeShiftHandle::Drag
|
|||
track = mCapturedTrack.get();
|
||||
}
|
||||
|
||||
// May need a shared_ptr to reassign mCapturedTrack below
|
||||
auto pTrack = Track::Pointer( track );
|
||||
if (!pTrack)
|
||||
return RefreshCode::RefreshNone;
|
||||
|
|
|
@ -21,6 +21,8 @@ Paul Licameli
|
|||
struct HitTestResult;
|
||||
class WaveClip;
|
||||
|
||||
using UIHandlePtr = std::shared_ptr<UIHandle>;
|
||||
|
||||
struct ClipMoveState {
|
||||
// non-NULL only if click was in a WaveTrack and without Shift key:
|
||||
WaveClip *capturedClip {};
|
||||
|
@ -44,14 +46,19 @@ struct ClipMoveState {
|
|||
|
||||
class TimeShiftHandle final : public UIHandle
|
||||
{
|
||||
TimeShiftHandle();
|
||||
TimeShiftHandle(const TimeShiftHandle&) = delete;
|
||||
TimeShiftHandle &operator=(const TimeShiftHandle&) = delete;
|
||||
static TimeShiftHandle& Instance();
|
||||
static HitTestPreview HitPreview
|
||||
(const AudacityProject *pProject, bool unsafe);
|
||||
|
||||
public:
|
||||
explicit TimeShiftHandle
|
||||
( const std::shared_ptr<Track> &pTrack, bool gripHit );
|
||||
|
||||
TimeShiftHandle &operator=(TimeShiftHandle&&) = default;
|
||||
|
||||
bool IsGripHit() const { return mGripHit; }
|
||||
std::shared_ptr<Track> GetTrack() const { return mCapturedTrack; }
|
||||
|
||||
// A utility function also used by menu commands
|
||||
static void CreateListOfCapturedClips
|
||||
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
|
||||
|
@ -61,9 +68,15 @@ public:
|
|||
static void DoSlideHorizontal
|
||||
( ClipMoveState &state, TrackList &trackList, Track &capturedTrack );
|
||||
|
||||
static HitTestResult HitAnywhere(const AudacityProject *pProject);
|
||||
static HitTestResult HitAnywhere
|
||||
(std::weak_ptr<TimeShiftHandle> &holder,
|
||||
const AudacityProject *pProject,
|
||||
const std::shared_ptr<Track> &pTrack, bool gripHit);
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject);
|
||||
(std::weak_ptr<TimeShiftHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const AudacityProject *pProject,
|
||||
const std::shared_ptr<Track> &pTrack);
|
||||
|
||||
virtual ~TimeShiftHandle();
|
||||
|
||||
|
@ -107,6 +120,7 @@ private:
|
|||
std::unique_ptr<SnapManager> mSnapManager{};
|
||||
|
||||
ClipMoveState mClipMoveState{};
|
||||
bool mGripHit {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,21 +17,15 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../Track.h"
|
||||
#include "../../TrackPanel.h"
|
||||
|
||||
MinimizeButtonHandle::MinimizeButtonHandle()
|
||||
: ButtonHandle{ TrackPanel::IsMinimizing }
|
||||
{
|
||||
}
|
||||
MinimizeButtonHandle::MinimizeButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect )
|
||||
: ButtonHandle{ pTrack, rect, TrackPanel::IsMinimizing }
|
||||
{}
|
||||
|
||||
MinimizeButtonHandle::~MinimizeButtonHandle()
|
||||
{
|
||||
}
|
||||
|
||||
MinimizeButtonHandle &MinimizeButtonHandle::Instance()
|
||||
{
|
||||
static MinimizeButtonHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
UIHandle::Result MinimizeButtonHandle::CommitChanges
|
||||
(const wxMouseEvent &, AudacityProject *pProject, wxWindow*)
|
||||
{
|
||||
|
@ -55,16 +49,19 @@ UIHandle::Result MinimizeButtonHandle::CommitChanges
|
|||
}
|
||||
|
||||
HitTestResult MinimizeButtonHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect)
|
||||
(std::weak_ptr<MinimizeButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell)
|
||||
{
|
||||
wxRect buttonRect;
|
||||
TrackInfo::GetMinimizeRect(rect, buttonRect);
|
||||
|
||||
if (buttonRect.Contains(state.m_x, state.m_y)) {
|
||||
Instance().mRect = buttonRect;
|
||||
auto pTrack = static_cast<CommonTrackPanelCell*>(pCell)->FindTrack();
|
||||
auto result = std::make_shared<MinimizeButtonHandle>( pTrack, buttonRect );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview(),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
else
|
||||
|
@ -73,21 +70,15 @@ HitTestResult MinimizeButtonHandle::HitTest
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CloseButtonHandle::CloseButtonHandle()
|
||||
: ButtonHandle{ TrackPanel::IsClosing }
|
||||
{
|
||||
}
|
||||
CloseButtonHandle::CloseButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect )
|
||||
: ButtonHandle{ pTrack, rect, TrackPanel::IsClosing }
|
||||
{}
|
||||
|
||||
CloseButtonHandle::~CloseButtonHandle()
|
||||
{
|
||||
}
|
||||
|
||||
CloseButtonHandle &CloseButtonHandle::Instance()
|
||||
{
|
||||
static CloseButtonHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
UIHandle::Result CloseButtonHandle::CommitChanges
|
||||
(const wxMouseEvent &, AudacityProject *pProject, wxWindow*)
|
||||
{
|
||||
|
@ -112,16 +103,19 @@ UIHandle::Result CloseButtonHandle::CommitChanges
|
|||
}
|
||||
|
||||
HitTestResult CloseButtonHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect)
|
||||
(std::weak_ptr<CloseButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell)
|
||||
{
|
||||
wxRect buttonRect;
|
||||
TrackInfo::GetCloseBoxRect(rect, buttonRect);
|
||||
|
||||
if (buttonRect.Contains(state.m_x, state.m_y)) {
|
||||
Instance().mRect = buttonRect;
|
||||
auto pTrack = static_cast<CommonTrackPanelCell*>(pCell)->FindTrack();
|
||||
auto result = std::make_shared<CloseButtonHandle>( pTrack, buttonRect );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview(),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
else
|
||||
|
@ -130,21 +124,17 @@ HitTestResult CloseButtonHandle::HitTest
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MenuButtonHandle::MenuButtonHandle()
|
||||
: ButtonHandle{ TrackPanel::IsPopping }
|
||||
{
|
||||
}
|
||||
MenuButtonHandle::MenuButtonHandle
|
||||
( const std::shared_ptr<TrackPanelCell> &pCell,
|
||||
const std::shared_ptr<Track> &pTrack, const wxRect &rect )
|
||||
: ButtonHandle{ pTrack, rect, TrackPanel::IsPopping }
|
||||
, mpCell{ pCell }
|
||||
{}
|
||||
|
||||
MenuButtonHandle::~MenuButtonHandle()
|
||||
{
|
||||
}
|
||||
|
||||
MenuButtonHandle &MenuButtonHandle::Instance()
|
||||
{
|
||||
static MenuButtonHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
UIHandle::Result MenuButtonHandle::CommitChanges
|
||||
(const wxMouseEvent &, AudacityProject *, wxWindow *pParent)
|
||||
{
|
||||
|
@ -155,18 +145,20 @@ UIHandle::Result MenuButtonHandle::CommitChanges
|
|||
}
|
||||
|
||||
HitTestResult MenuButtonHandle::HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<MenuButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const std::shared_ptr<TrackPanelCell> &pCell)
|
||||
{
|
||||
wxRect buttonRect;
|
||||
TrackInfo::GetTitleBarRect(rect, buttonRect);
|
||||
|
||||
if (buttonRect.Contains(state.m_x, state.m_y)) {
|
||||
Instance().mpCell = pCell;
|
||||
Instance().mRect = buttonRect;
|
||||
auto pTrack = static_cast<CommonTrackPanelCell*>(pCell.get())->FindTrack();
|
||||
auto result = std::make_shared<MenuButtonHandle>( pCell, pTrack, buttonRect );
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview(),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
else
|
||||
|
|
|
@ -12,6 +12,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#define __AUDACITY_TRACK_BUTTON_HANDLES__
|
||||
|
||||
#include "../ui/ButtonHandle.h"
|
||||
#include "../../TrackPanel.h"
|
||||
|
||||
class wxMouseState;
|
||||
struct HitTestResult;
|
||||
|
@ -19,11 +20,6 @@ struct HitTestResult;
|
|||
class MinimizeButtonHandle final : public ButtonHandle
|
||||
{
|
||||
MinimizeButtonHandle(const MinimizeButtonHandle&) = delete;
|
||||
MinimizeButtonHandle &operator=(const MinimizeButtonHandle&) = delete;
|
||||
|
||||
MinimizeButtonHandle();
|
||||
virtual ~MinimizeButtonHandle();
|
||||
static MinimizeButtonHandle& Instance();
|
||||
|
||||
protected:
|
||||
Result CommitChanges
|
||||
|
@ -31,7 +27,16 @@ protected:
|
|||
override;
|
||||
|
||||
public:
|
||||
static HitTestResult HitTest(const wxMouseState &state, const wxRect &rect);
|
||||
explicit MinimizeButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect );
|
||||
|
||||
MinimizeButtonHandle &operator=(const MinimizeButtonHandle&) = default;
|
||||
|
||||
virtual ~MinimizeButtonHandle();
|
||||
|
||||
static HitTestResult HitTest
|
||||
(std::weak_ptr<MinimizeButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -39,11 +44,6 @@ public:
|
|||
class CloseButtonHandle final : public ButtonHandle
|
||||
{
|
||||
CloseButtonHandle(const CloseButtonHandle&) = delete;
|
||||
CloseButtonHandle &operator=(const CloseButtonHandle&) = delete;
|
||||
|
||||
CloseButtonHandle();
|
||||
virtual ~CloseButtonHandle();
|
||||
static CloseButtonHandle& Instance();
|
||||
|
||||
protected:
|
||||
Result CommitChanges
|
||||
|
@ -53,7 +53,16 @@ protected:
|
|||
bool StopsOnKeystroke () override { return true; }
|
||||
|
||||
public:
|
||||
static HitTestResult HitTest(const wxMouseState &state, const wxRect &rect);
|
||||
explicit CloseButtonHandle
|
||||
( const std::shared_ptr<Track> &pTrack, const wxRect &rect );
|
||||
|
||||
CloseButtonHandle &operator=(const CloseButtonHandle&) = default;
|
||||
|
||||
virtual ~CloseButtonHandle();
|
||||
|
||||
static HitTestResult HitTest
|
||||
(std::weak_ptr<CloseButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect, TrackPanelCell *pCell);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -64,11 +73,6 @@ public:
|
|||
class MenuButtonHandle final : public ButtonHandle
|
||||
{
|
||||
MenuButtonHandle(const MenuButtonHandle&) = delete;
|
||||
MenuButtonHandle &operator=(const MenuButtonHandle&) = delete;
|
||||
|
||||
MenuButtonHandle();
|
||||
virtual ~MenuButtonHandle();
|
||||
static MenuButtonHandle& Instance();
|
||||
|
||||
protected:
|
||||
Result CommitChanges
|
||||
|
@ -76,8 +80,17 @@ protected:
|
|||
override;
|
||||
|
||||
public:
|
||||
explicit MenuButtonHandle
|
||||
( const std::shared_ptr<TrackPanelCell> &pCell,
|
||||
const std::shared_ptr<Track> &pTrack, const wxRect &rect );
|
||||
|
||||
MenuButtonHandle &operator=(const MenuButtonHandle&) = default;
|
||||
|
||||
virtual ~MenuButtonHandle();
|
||||
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const wxRect &rect,
|
||||
(std::weak_ptr<MenuButtonHandle> &holder,
|
||||
const wxMouseState &state, const wxRect &rect,
|
||||
const std::shared_ptr<TrackPanelCell> &pCell);
|
||||
|
||||
private:
|
||||
|
|
|
@ -45,18 +45,24 @@ HitTestResult TrackControls::HitTest
|
|||
const wxRect &rect = st.rect;
|
||||
HitTestResult result;
|
||||
|
||||
if (NULL != (result = CloseButtonHandle::HitTest(state, rect)).handle)
|
||||
auto pTrack = FindTrack();
|
||||
// shared pointer to this:
|
||||
auto sThis = pTrack->GetTrackControl();
|
||||
|
||||
if (NULL != (result = CloseButtonHandle::HitTest(
|
||||
mCloseHandle, state, rect, this)).handle)
|
||||
return result;
|
||||
|
||||
if (NULL != (result = MenuButtonHandle::HitTest(state, rect,
|
||||
this->FindTrack()->GetTrackControl())).handle)
|
||||
if (NULL != (result = MenuButtonHandle::HitTest(
|
||||
mMenuHandle, state, rect, sThis)).handle)
|
||||
return result;
|
||||
|
||||
if (NULL != (result = MinimizeButtonHandle::HitTest(state, rect)).handle)
|
||||
if (NULL != (result = MinimizeButtonHandle::HitTest(
|
||||
mMinimizeHandle, state, rect, this)).handle)
|
||||
return result;
|
||||
|
||||
return TrackSelectHandle::HitAnywhere
|
||||
(project->GetTrackPanel()->GetTrackCount());
|
||||
return TrackSelectHandle::HitAnywhere(
|
||||
mSelectHandle, pTrack, project->GetTrackPanel()->GetTrackCount());
|
||||
}
|
||||
|
||||
enum
|
||||
|
|
|
@ -17,6 +17,11 @@ Paul Licameli split from TrackPanel.cpp
|
|||
class PopupMenuTable;
|
||||
class Track;
|
||||
|
||||
class CloseButtonHandle;
|
||||
class MenuButtonHandle;
|
||||
class MinimizeButtonHandle;
|
||||
class TrackSelectHandle;
|
||||
|
||||
class TrackControls /* not final */ : public CommonTrackPanelCell
|
||||
{
|
||||
public:
|
||||
|
@ -54,6 +59,11 @@ protected:
|
|||
Track *GetTrack() const;
|
||||
|
||||
std::weak_ptr<Track> mwTrack;
|
||||
|
||||
std::weak_ptr<CloseButtonHandle> mCloseHandle;
|
||||
std::weak_ptr<MenuButtonHandle> mMenuHandle;
|
||||
std::weak_ptr<MinimizeButtonHandle> mMinimizeHandle;
|
||||
std::weak_ptr<TrackSelectHandle> mSelectHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,16 +26,6 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "../../../images/Cursors.h"
|
||||
|
||||
TrackSelectHandle::TrackSelectHandle()
|
||||
{
|
||||
}
|
||||
|
||||
TrackSelectHandle &TrackSelectHandle::Instance()
|
||||
{
|
||||
static TrackSelectHandle instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
/* i18n-hint: Command names a modifier key on Macintosh keyboards */
|
||||
#define CTRL_CLICK _("Command-Click")
|
||||
|
@ -59,6 +49,10 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
TrackSelectHandle::TrackSelectHandle( const std::shared_ptr<Track> &pTrack )
|
||||
: mpTrack( pTrack )
|
||||
{}
|
||||
|
||||
HitTestPreview TrackSelectHandle::HitPreview(unsigned trackCount)
|
||||
{
|
||||
static wxCursor arrowCursor{ wxCURSOR_ARROW };
|
||||
|
@ -68,11 +62,15 @@ HitTestPreview TrackSelectHandle::HitPreview(unsigned trackCount)
|
|||
};
|
||||
}
|
||||
|
||||
HitTestResult TrackSelectHandle::HitAnywhere(unsigned trackCount)
|
||||
HitTestResult TrackSelectHandle::HitAnywhere
|
||||
(std::weak_ptr<TrackSelectHandle> &holder,
|
||||
const std::shared_ptr<Track> &pTrack, unsigned trackCount)
|
||||
{
|
||||
auto result = std::make_shared<TrackSelectHandle>(pTrack);
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return {
|
||||
HitPreview(trackCount),
|
||||
&Instance()
|
||||
result
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -97,8 +95,7 @@ UIHandle::Result TrackSelectHandle::Click
|
|||
if (!event.Button(wxMOUSE_BTN_LEFT))
|
||||
return Cancelled;
|
||||
|
||||
const auto pControls = static_cast<TrackControls*>(evt.pCell.get());
|
||||
const auto pTrack = pControls->FindTrack();
|
||||
const auto pTrack = mpTrack;
|
||||
if (!pTrack)
|
||||
return Cancelled;
|
||||
TrackPanel *const trackPanel = pProject->GetTrackPanel();
|
||||
|
@ -113,7 +110,6 @@ UIHandle::Result TrackSelectHandle::Click
|
|||
result |= Cancelled;
|
||||
else {
|
||||
mRearrangeCount = 0;
|
||||
mpTrack = pTrack;
|
||||
CalculateRearrangingThresholds(event);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,17 @@ class Track;
|
|||
|
||||
class TrackSelectHandle final : public UIHandle
|
||||
{
|
||||
TrackSelectHandle();
|
||||
TrackSelectHandle(const TrackSelectHandle&) = delete;
|
||||
TrackSelectHandle &operator=(const TrackSelectHandle&) = delete;
|
||||
static TrackSelectHandle& Instance();
|
||||
static HitTestPreview HitPreview(unsigned trackCount);
|
||||
|
||||
public:
|
||||
static HitTestResult HitAnywhere(unsigned trackCount);
|
||||
explicit TrackSelectHandle( const std::shared_ptr<Track> &pTrack );
|
||||
|
||||
TrackSelectHandle &operator=(const TrackSelectHandle&) = default;
|
||||
|
||||
static HitTestResult HitAnywhere
|
||||
(std::weak_ptr<TrackSelectHandle> &holder,
|
||||
const std::shared_ptr<Track> &pTrack, unsigned trackCount);
|
||||
|
||||
virtual ~TrackSelectHandle();
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "ZoomHandle.h"
|
||||
#include "TimeShiftHandle.h"
|
||||
#include "../../TrackPanelResizerCell.h"
|
||||
#include "BackgroundCell.h"
|
||||
|
||||
HitTestResult Track::HitTest
|
||||
(const TrackPanelMouseState &st,
|
||||
|
@ -35,7 +36,8 @@ HitTestResult Track::HitTest
|
|||
if ( !isMultiTool && currentTool == zoomTool )
|
||||
// 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(st.state, pProject);
|
||||
return ZoomHandle::HitAnywhere(
|
||||
pProject->GetBackgroundCell()->mZoomHandle, st.state, pProject);
|
||||
|
||||
// In other tools, let subclasses determine detailed hits.
|
||||
HitTestResult result =
|
||||
|
@ -49,16 +51,19 @@ HitTestResult Track::HitTest
|
|||
|
||||
// Sliding applies in more than one track type.
|
||||
if ( !result.handle && !isMultiTool && currentTool == slideTool )
|
||||
result = TimeShiftHandle::HitAnywhere(pProject);
|
||||
result = TimeShiftHandle::HitAnywhere(
|
||||
mTimeShiftHandle, pProject, Pointer(this), false);
|
||||
|
||||
// Let the multi-tool right-click handler apply only in default of all
|
||||
// other detailed hits.
|
||||
if ( !result.handle && isMultiTool )
|
||||
result = ZoomHandle::HitTest(st.state, pProject);
|
||||
result = ZoomHandle::HitTest(
|
||||
pProject->GetBackgroundCell()->mZoomHandle, st.state, pProject);
|
||||
|
||||
// Finally, default of all is adjustment of the selection box.
|
||||
if ( !result.handle && ( isMultiTool || currentTool == selectTool) )
|
||||
result = SelectHandle::HitTest(st, pProject, Pointer(this));
|
||||
result = SelectHandle::HitTest(
|
||||
mSelectHandle, st, pProject, Pointer(this));
|
||||
|
||||
result.preview.refreshCode |= refresh;
|
||||
return result;
|
||||
|
|
|
@ -33,11 +33,11 @@ std::shared_ptr<Track> TrackVRulerControls::FindTrack()
|
|||
}
|
||||
|
||||
HitTestResult TrackVRulerControls::HitTest
|
||||
(const TrackPanelMouseState &, const AudacityProject *)
|
||||
(const TrackPanelMouseState &, const AudacityProject *)
|
||||
{
|
||||
// Use a space for the tip, otherwise we get the default message.
|
||||
static wxCursor arrowCursor{ wxCURSOR_ARROW };
|
||||
return { { _(" "), &arrowCursor }, nullptr };
|
||||
return { { _(" "), &arrowCursor }, {} };
|
||||
}
|
||||
|
||||
void TrackVRulerControls::DrawZooming
|
||||
|
|
|
@ -38,14 +38,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||
/// and forcing a refresh.
|
||||
|
||||
ZoomHandle::ZoomHandle()
|
||||
{
|
||||
}
|
||||
|
||||
ZoomHandle &ZoomHandle::Instance()
|
||||
{
|
||||
static ZoomHandle instance;
|
||||
return instance;
|
||||
}
|
||||
{}
|
||||
|
||||
HitTestPreview ZoomHandle::HitPreview
|
||||
(const wxMouseState &state, const AudacityProject *pProject)
|
||||
|
@ -62,16 +55,20 @@ HitTestPreview ZoomHandle::HitPreview
|
|||
}
|
||||
|
||||
HitTestResult ZoomHandle::HitAnywhere
|
||||
(const wxMouseState &state, const AudacityProject *pProject)
|
||||
(std::weak_ptr<ZoomHandle> &holder,
|
||||
const wxMouseState &state, const AudacityProject *pProject)
|
||||
{
|
||||
return { HitPreview(state, pProject), &Instance() };
|
||||
auto result = std::make_shared<ZoomHandle>();
|
||||
result = AssignUIHandlePtr(holder, result);
|
||||
return { HitPreview(state, pProject), result };
|
||||
}
|
||||
|
||||
HitTestResult ZoomHandle::HitTest
|
||||
(const wxMouseState &state, const AudacityProject *pProject)
|
||||
(std::weak_ptr<ZoomHandle> &holder,
|
||||
const wxMouseState &state, const AudacityProject *pProject)
|
||||
{
|
||||
if (state.ButtonIsDown(wxMOUSE_BTN_RIGHT))
|
||||
return HitAnywhere(state, pProject);
|
||||
return HitAnywhere(holder, state, pProject);
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -18,20 +18,24 @@ class wxMouseState;
|
|||
|
||||
struct HitTestResult;
|
||||
|
||||
// This handle class, unlike most, doesn't associate with any particular cell.
|
||||
class ZoomHandle final : public UIHandle
|
||||
{
|
||||
ZoomHandle();
|
||||
ZoomHandle(const ZoomHandle&) = delete;
|
||||
ZoomHandle &operator=(const ZoomHandle&) = delete;
|
||||
static ZoomHandle& Instance();
|
||||
static HitTestPreview HitPreview
|
||||
(const wxMouseState &state, const AudacityProject *pProject);
|
||||
|
||||
public:
|
||||
ZoomHandle();
|
||||
|
||||
ZoomHandle &operator=(const ZoomHandle&) = default;
|
||||
|
||||
static HitTestResult HitAnywhere
|
||||
(const wxMouseState &state, const AudacityProject *pProject);
|
||||
(std::weak_ptr<ZoomHandle> &holder,
|
||||
const wxMouseState &state, const AudacityProject *pProject);
|
||||
static HitTestResult HitTest
|
||||
(const wxMouseState &state, const AudacityProject *pProject);
|
||||
(std::weak_ptr<ZoomHandle> &holder,
|
||||
const wxMouseState &state, const AudacityProject *pProject);
|
||||
|
||||
virtual ~ZoomHandle();
|
||||
|
||||
|
|
Loading…
Reference in New Issue