18#include "../../SpectrumAnalyst.h"
19#include "../../LabelTrack.h"
22#include "../../ProjectAudioIO.h"
24#include "../../ProjectSettings.h"
25#include "../../ProjectWindow.h"
26#include "../../RefreshCode.h"
27#include "../../SelectUtilities.h"
28#include "../../SelectionState.h"
29#include "../../TrackArtist.h"
30#include "../../TrackPanelAx.h"
31#include "../../TrackPanel.h"
32#include "../../TrackPanelDrawingContext.h"
33#include "../../TrackPanelMouseEvent.h"
35#include "../../WaveClip.h"
36#include "../../WaveTrack.h"
37#include "../../prefs/SpectrogramSettings.h"
38#include "../../../images/Cursors.h"
70 float minFreq, maxFreq;
74 return trackTopEdge + wxInt64((1.0 - p) * trackHeight);
81 wxInt64 mouseYCoordinate,
85 const double rate = wt->
GetRate();
96 float minFreq, maxFreq;
99 const double p = double(mouseYCoordinate - trackTopEdge) / trackHeight;
117 pTrackView->
FindTrack()->TypeSwitch<
bool >(
120 return settings.SpectralSelectionEnabled();
127#ifdef EXPERIMENTAL_SPECTRAL_EDITING
128 SBBottom, SBTop, SBCenter, SBWidth,
134 const double t0,
const double t1,
136 double selend,
bool onlyWithinSnapDistance,
137 wxInt64 *pPixelDist,
double *pPinValue)
141 wxInt64 pixelDist = std::abs(posS - pos0);
142 bool chooseLeft =
true;
147 chooseLeft = (selend < t0);
150 const wxInt64 rightDist = std::abs(posS - pos1);
151 if (rightDist < pixelDist)
152 chooseLeft =
false, pixelDist = rightDist;
157 if (onlyWithinSnapDistance &&
162 else if (chooseLeft) {
174 wxCoord xx, wxCoord yy,
const TrackView *pTrackView,
const wxRect &rect,
175 bool mayDragWidth,
bool onlyWithinSnapDistance,
176 double *pPinValue = NULL)
184 wxInt64 pixelDist = 0;
190 &pixelDist, pPinValue);
192#ifdef EXPERIMENTAL_SPECTRAL_EDITING
200 bool chooseTime =
true;
201 bool chooseBottom =
true;
202 bool chooseCenter =
false;
206 t0 <= selend && selend < t1 &&
211 static_cast<const WaveTrack*
>(pTrack.get());
212 const wxInt64 bottomSel = (f0 >= 0)
214 : rect.y + rect.height;
215 const wxInt64 topSel = (f1 >= 0)
218 wxInt64 signedBottomDist = (int)(yy - bottomSel);
219 wxInt64 verticalDist = std::abs(signedBottomDist);
220 if (bottomSel == topSel)
222 chooseBottom = (signedBottomDist >= 0);
224 const wxInt64 topDist = std::abs((
int)(yy - topSel));
225 if (topDist < verticalDist)
226 chooseBottom =
false, verticalDist = topDist;
229#ifdef SPECTRAL_EDITING_ESC_KEY
233 const wxInt64 centerSel =
235 const wxInt64 centerDist = abs((
int)(yy - centerSel));
236 if (centerDist < verticalDist)
237 chooseCenter =
true, verticalDist = centerDist,
240 if (verticalDist >= 0 &&
241 verticalDist < pixelDist) {
242 pixelDist = verticalDist;
250 if (onlyWithinSnapDistance &&
255 else if (chooseCenter) {
259 else if (mayDragWidth && fc > 0) {
263 else if (chooseBottom) {
281 static auto selectCursor =
283 return &*selectCursor;
289 static auto envelopeCursor =
291 return &*envelopeCursor;
298 static wxCursor adjustLeftSelectionCursor{ wxCURSOR_POINT_LEFT };
299 static wxCursor adjustRightSelectionCursor{ wxCURSOR_POINT_RIGHT };
301 static auto bottomFrequencyCursor =
302 ::MakeCursor(wxCURSOR_ARROW, BottomFrequencyCursorXpm, 16, 16);
303 static auto topFrequencyCursor =
304 ::MakeCursor(wxCURSOR_ARROW, TopFrequencyCursorXpm, 16, 16);
305 static auto bandWidthCursor =
306 ::MakeCursor(wxCURSOR_ARROW, BandWidthCursorXpm, 16, 16);
313 tip =
XO(
"Click and drag to move left selection boundary.");
314 pCursor = &adjustLeftSelectionCursor;
317 tip =
XO(
"Click and drag to move right selection boundary.");
318 pCursor = &adjustRightSelectionCursor;
320#ifdef EXPERIMENTAL_SPECTRAL_EDITING
322 tip =
XO(
"Click and drag to move bottom selection frequency.");
323 pCursor = &*bottomFrequencyCursor;
326 tip =
XO(
"Click and drag to move top selection frequency.");
327 pCursor = &*topFrequencyCursor;
331#ifndef SPECTRAL_EDITING_ESC_KEY
334 XO(
"Click and drag to move center selection frequency to a spectral peak.") :
335 XO(
"Click and drag to move center selection frequency.");
341 XO(
"Click and drag to move center selection frequency.");
349 tip =
XO(
"Click and drag to adjust frequency bandwidth.");
350 pCursor = &*bandWidthCursor;
361(std::weak_ptr<SelectHandle> &holder,
363 const std::shared_ptr<TrackView> &pTrackView)
367 auto old = holder.lock();
368 bool oldUseSnap =
true;
371 if( old->mTimerHandler ) {
375 old->mTimerHandler.reset();
377 oldUseSnap = old->mUseSnap;
381 auto result = std::make_shared<SelectHandle>(
382 pTrackView, oldUseSnap,
TrackList::Get( *pProject ), st, viewInfo );
389 auto pTrack = pTrackView->FindTrack();
390 if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
396 const wxRect &rect = st.
rect;
397 wxInt64 leftSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t0(), rect.x);
398 wxInt64 rightSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t1(), rect.x);
400 wxASSERT(!(rightSel < leftSel));
401 static_cast<void>(leftSel);
402 static_cast<void>(rightSel);
413 wxASSERT( useSnap == newState.
mUseSnap );
419 if ( oldSnapState.Snapped() == newSnapState.Snapped() &&
420 (!oldSnapState.Snapped() ||
421 oldSnapState.outCoord == newSnapState.outCoord) )
428(
const std::shared_ptr<TrackView> &pTrackView,
bool useSnap,
431 : mpView{ pTrackView }
435 SnapPoint{ viewInfo.playRegion.GetLastActiveStart() },
436 SnapPoint{ viewInfo.playRegion.GetLastActiveEnd() },
439 const wxMouseState &state = st.
state;
443 auto pTrack = pTrackView->FindTrack();
459 template <
class A,
class B,
class DIST >
bool within(
A a, B b, DIST d)
461 return (a > b - d) && (a < b + d);
466 const double minFrequency = 1.0;
467 const double maxFrequency = (rate / 2.0);
468 const double frequency =
470 std::max(minFrequency, center));
472 std::min(frequency / minFrequency, maxFrequency / frequency);
527 const auto pView =
mpView.lock();
531 wxMouseEvent &
event = evt.
event;
533 const auto pTrack = sTrack.get();
540 bool selectChange = (
542 event.ControlDown() &&
546 bool bShift =
event.ShiftDown();
549 *pProject, pTrack, bShift,
true, !unsafe);
559 if (event.LeftDClick() && !event.ShiftDown()) {
563 selectionState.SelectNone( trackList );
565 selectionState.SelectTrack( *pTrack,
true,
true );
569 ( viewInfo, *pTrack,
settings.IsSyncLocked() );
573 pTrack->TypeSwitch( [&] (
WaveTrack *wt ) {
574 auto time = viewInfo.PositionToTime(event.m_x,
mRect.x);
577 viewInfo.selectedRegion.setTimes(
578 selectedClip->GetPlayStartTime(), selectedClip->GetPlayEndTime());
587 else if (!event.LeftDown())
594 std::make_shared< SelectionStateChanger >( selectionState, trackList );
598 bool bShiftDown =
event.ShiftDown();
599 bool bCtrlDown =
event.ControlDown();
605 if (bShiftDown || bCtrlDown) {
607 selectionState.ChangeSelectionOnShiftClick( trackList, *pTrack );
612 bool bIsSelected =
false;
614 if( !bIsSelected || trackPanel.GetSelectedTrackCount() > 1 )
615 selectionState.SelectTrack( *pTrack, !bIsSelected,
true );
622 pView.get(),
mRect,
false,
false, &value);
628#ifdef EXPERIMENTAL_SPECTRAL_EDITING
639#ifdef EXPERIMENTAL_SPECTRAL_EDITING
646 (boundary == SBBottom)
658 const auto wt =
static_cast<const WaveTrack*
>(pTrack);
681 bool startNewSelection =
true;
682 if (pTrack && pTrack->GetSelected()) {
685 if (viewInfo.bAdjustSelectionEdges) {
686#ifdef EXPERIMENTAL_SPECTRAL_EDITING
717 pView.get(),
mRect,
true,
true, &value);
725 startNewSelection =
false;
726#ifdef EXPERIMENTAL_SPECTRAL_EDITING
734#ifdef EXPERIMENTAL_SPECTRAL_EDITING
738 startNewSelection =
false;
750 const auto wt =
static_cast<const WaveTrack*
>(pTrack);
752 startNewSelection =
false;
765 if (startNewSelection) {
767 selectionState.SelectNone( trackList );
768#ifdef EXPERIMENTAL_SPECTRAL_EDITING
773 selectionState.SelectTrack( *pTrack,
true,
true );
790 const auto pView =
mpView.lock();
795 const wxMouseEvent &
event = evt.
event;
810 if (event.CmdDown()) {
826 enum { minimumSizedSelection = 5 };
832 if (wxLongLong(SelStart - x).Abs() < minimumSizedSelection)
837 if (
auto clickedTrack =
840 Track *sTrack = pTrack.get();
841 Track *eTrack = clickedTrack.get();
843 if ( sTrack && eTrack && !event.ControlDown() ) {
845 selectionState.SelectRangeOfTracks( trackList, *sTrack, *eTrack );
848 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
849 #ifndef SPECTRAL_EDITING_ESC_KEY
851 !viewInfo.selectedRegion.isPoint())
853 (pProject, viewInfo, y,
mRect.y,
mRect.height, pView.get());
886 const auto pView =
mpView.lock();
907 auto &state = st.
state;
909 auto xx = viewInfo.TimeToPosition(time,
mRect.x);
911 const bool bMultiToolMode =
915 if (bMultiToolMode) {
924 keyStr =
_(
"Edit, Preferences...");
927 tip =
XO(
"Multi-Tool Mode: %s for Mouse and Keyboard Preferences.")
930 if (!pTrack->GetSelected() ||
931 !viewInfo.bAdjustSelectionEdges)
934 const wxRect &rect = st.
rect;
935 const bool bShiftDown = state.ShiftDown();
936 const bool bCtrlDown = state.ControlDown();
937 const bool bModifierDown = bShiftDown || bCtrlDown;
944 pView.get(), rect, !bModifierDown, !bModifierDown);
954#ifdef EXPERIMENTAL_SPECTRAL_EDITING
958 tip =
XO(
"Click and drag to set frequency bandwidth.");
959 pCursor = &*envelopeCursor;
965 if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
968 const wxRect &rect = st.
rect;
969 const bool bShiftDown = state.ShiftDown();
970 const bool bCtrlDown = state.ControlDown();
971 const bool bModifierDown = bShiftDown || bCtrlDown;
973 viewInfo, xx, state.m_y,
974 pView.get(), rect, !bModifierDown, !bModifierDown);
979 tip =
XO(
"Click and drag to select audio");
984 XO(
"(snapping)"), wxT(
" ")
987 return { tip, pCursor };
1019 const wxRect &rect,
unsigned iPass )
1022 auto &dc = context.
dc;
1034 const wxRect &rect,
const wxRect &panelRect,
unsigned iPass )
1044 auto pView =
mpView.lock();
1048 return pView->FindTrack();
1053 mTimerHandler = std::make_shared<TimerHandler>(
this, pProject );
1101 window.TP_ScrollRight();
1105 window.TP_ScrollLeft();
1113 trackPanel.ClientToScreen(&xx, &yy);
1116 window.TP_ScrollLeft();
1120 ::wxDisplaySize(&width, &height);
1121 if (xx == width - 1) {
1123 window.TP_ScrollRight();
1135 wxMouseEvent evt(wxEVT_MOTION);
1136 const auto size = trackPanel.GetSize();
1166 ViewInfo &viewInfo,
int mouseXCoordinate,
int trackLeftEdge,
1174 std::max(0.0, viewInfo.
PositionToTime(mouseXCoordinate, trackLeftEdge));
1175 double origSelend = selend;
1199 selend = origSelend;
1223 int mouseYCoordinate,
int trackTopEdge,
1237 trackTopEdge, trackHeight);
1244 int mouseYCoordinate,
int trackTopEdge,
1254 const double rate = wt->
GetRate();
1255 const double frequency =
1257 trackTopEdge, trackHeight);
1261 if (frequency == rate || frequency < 1.0)
1271 frequency / ratio, frequency * ratio);
1277 if (frequency == rate || frequency < 1.0)
1289 ratio = 1.0 / ratio;
1298 const bool bottomDefined =
1300 const bool topDefined =
1302 if (!bottomDefined || (topDefined &&
mFreqSelPin < frequency)) {
1304 if (frequency == rate)
1314 if (frequency < 1.0)
1326(
const ViewInfo &viewInfo,
bool shiftDown,
const WaveTrack *pTrack,
double value)
1336#ifndef SPECTRAL_EDITING_ESC_KEY
1352 static const size_t minLength = 8;
1354 const double rate = pTrack->
GetRate();
1357 std::vector<float> frequencySnappingData;
1363 std::min(frequencySnappingData.max_size(),
1366 const auto effectiveLength = std::max(minLength, length);
1367 frequencySnappingData.resize(effectiveLength, 0.0f);
1369 &frequencySnappingData[0],
1378 auto windowSize =
settings.GetFFTLength();
1380 while(windowSize > effectiveLength)
1382 const int windowType =
settings.windowType;
1386 &frequencySnappingData[0], length);
1396 auto pTrack = pTrackView->
FindTrack().get();
1398 pTrack->GetSelected() &&
1409 const double rate = wt->
GetRate();
1410 const double frequency =
1412 trackTopEdge, trackHeight);
1413 const double snappedFrequency =
1415 const double maxRatio =
findMaxRatio(snappedFrequency, rate);
1420 if (f1 >= f0 && f0 >= 0)
1422 ratio = sqrt(f1 / f0);
1428 snappedFrequency / ratio, snappedFrequency * ratio);
1446 const auto windowSize =
settings.GetFFTLength();
1447 const double rate = pTrack->
GetRate();
1448 const double nyq = rate / 2.0;
1449 const double binFrequency = rate / windowSize;
1453 if (centerFrequency <= 0) {
1454 centerFrequency = up ? binFrequency : nyq;
1455 f1 = centerFrequency * sqrt(2.0);
1458 double ratio = f1 / centerFrequency;
1459 const int originalBin = floor(0.5 + centerFrequency / binFrequency);
1460 const int limitingBin = up ? floor(0.5 + nyq / binFrequency) : 1;
1466 double snappedFrequency = centerFrequency;
1467 int bin = originalBin;
1469 while (snappedFrequency <= centerFrequency &&
1471 snappedFrequency = analyst.
FindPeak(++bin * binFrequency, NULL);
1474 while (snappedFrequency >= centerFrequency &&
1476 snappedFrequency = analyst.
FindPeak(--bin * binFrequency, NULL);
1480 const double maxRatio =
findMaxRatio(snappedFrequency, rate);
1484 (snappedFrequency / ratio, snappedFrequency * ratio);
1489void SelectHandle::ResetFreqSelectionPin
1490 (
const ViewInfo &viewInfo,
double hintFrequency,
bool logF)
1492 switch (mFreqSelMode) {
1507 if (f0 >= 0 && f1 >= 0)
1527 const double logf1 = log(std::max(1.0, f1));
1528 const double logf0 = log(std::max(1.0, f0));
1529 const double logHint = log(std::max(1.0, hintFrequency));
1530 if (std::abs(logHint - logf1) < std::abs(logHint - logf0))
1538 std::abs(hintFrequency - f1) < std::abs(hintFrequency - f0))
std::shared_ptr< UIHandle > UIHandlePtr
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
@ SELECTION_RESIZE_REGION
std::vector< SnapPoint > SnapPointArray
static Settings & settings()
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
bool within(A a, B b, DIST d)
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static CommandManager & Get(AudacityProject &project)
NormalizedKeyString GetKeyFromName(const CommandID &name) const
std::shared_ptr< Track > FindTrack()
A LabelTrack is a Track that holds labels (LabelStruct).
bool setTimes(double t0, double t1)
bool setF0(double f, bool maySwap=true)
bool setFrequencies(double f0, double f1)
bool setF1(double f, bool maySwap=true)
float PositionToValue(float pp) const
float ValueToPosition(float val) const
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
A move-only handle representing a connection to a Publisher.
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
PlaybackScroller & GetPlaybackScroller()
static ProjectWindow & Get(AudacityProject &project)
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
Retrieve samples from a track in floating-point format, regardless of the storage format.
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
void OnTimer(Observer::Message)
TimerHandler(SelectHandle *pParent, AudacityProject *pProject)
AudacityProject * mConnectedProject
Observer::Subscription mSubscription
SelectHandle(const SelectHandle &)
Result Cancel(AudacityProject *) override
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
void MoveSnappingFreqSelection(AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight, TrackView *pTrackView)
void HandleCenterFrequencyClick(const ViewInfo &viewInfo, bool shiftDown, const WaveTrack *pTrack, double value)
std::weak_ptr< Track > FindTrack()
std::weak_ptr< TrackView > mpView
std::weak_ptr< const WaveTrack > mFreqSelTrack
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
void Enter(bool forward, AudacityProject *pProject) override
void SetUseSnap(bool use, AudacityProject *pProject)
void AssignSelection(ViewInfo &viewInfo, double selend, Track *pTrack)
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
static void SnapCenterOnce(SpectrumAnalyst &analyst, ViewInfo &viewInfo, const WaveTrack *pTrack, bool up)
bool HasEscape(AudacityProject *pProject) const override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::shared_ptr< TimerHandler > mTimerHandler
std::shared_ptr< SelectionStateChanger > mSelectionStateChanger
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::shared_ptr< SpectrumAnalyst > mFrequencySnapper
static void StartSnappingFreqSelection(SpectrumAnalyst &analyst, const ViewInfo &viewInfo, const WaveTrack *pTrack)
void AdjustSelection(AudacityProject *pProject, ViewInfo &viewInfo, int mouseXCoordinate, int trackLeftEdge, Track *pTrack)
Extend or contract the existing selection.
bool Escape(AudacityProject *pProject) override
std::shared_ptr< SnapManager > mSnapManager
static UIHandlePtr HitTest(std::weak_ptr< SelectHandle > &holder, const TrackPanelMouseState &state, const AudacityProject *pProject, const std::shared_ptr< TrackView > &pTrackView)
enum SelectHandle::eFreqSelMode FREQ_SEL_INVALID
@ FREQ_SEL_SNAPPING_CENTER
static UIHandle::Result NeedChangeHighlight(const SelectHandle &oldState, const SelectHandle &newState)
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
void StartFreqSelection(ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight, TrackView *pTrackView)
void AdjustFreqSelection(const WaveTrack *wt, ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight)
SelectedRegion mInitialSelection
void Connect(AudacityProject *pProject)
void StartSelection(AudacityProject *pProject)
Reset our selection markers.
static const int UndefinedFrequency
static void SelectTrackLength(ViewInfo &viewInfo, Track &track, bool syncLocked)
static SelectionState & Get(AudacityProject &project)
Spectrogram settings, either for one track or as defaults.
Used for finding the peaks, for snapping to peaks.
float FindPeak(float xPos, float *pY) const
bool Calculate(Algorithm alg, int windowFunc, size_t windowSize, double rate, const float *data, size_t dataLen, float *pYMin=NULL, float *pYMax=NULL, FreqGauge *progress=NULL)
Abstract base class for an object holding data associated with points on a time axis.
std::shared_ptr< Subclass > SharedPointer()
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
static TrackList & Get(AudacityProject &project)
static wxRect MaximizeHeight(const wxRect &rect, const wxRect &panelRect)
void Refresh(bool eraseBackground=true, const wxRect *rect=(const wxRect *) NULL) override
static TrackPanel & Get(AudacityProject &project)
virtual bool IsSpectral() const
static TrackView & Get(Track &)
Holds a msgid for the translation catalog; may also bind format arguments.
TranslatableString & Join(TranslatableString arg, const wxString &separator={}) &
Append another translatable string.
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
This allows multiple clips to be a part of one WaveTrack.
A Track that contains audio waveform data.
const SpectrogramSettings & GetSpectrogramSettings() const
WaveClip * GetClipAtTime(double time)
double GetRate() const override
void GetSpectrumBounds(float *min, float *max) const
double PositionToTime(wxInt64 position, wxInt64 origin=0, bool ignoreFisheye=false) const
wxInt64 TimeToPosition(double time, wxInt64 origin=0, bool ignoreFisheye=false) const
STM: Converts a project time to screen x position.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Namespace containing an enum 'what to do on a refresh?'.
void DoListSelection(AudacityProject &project, Track *t, bool shift, bool ctrl, bool modifyState)
wxCursor * EnvelopeCursor()
double findMaxRatio(double center, double rate)
void SetTipAndCursorForBoundary(SelectionBoundary boundary, bool frequencySnapping, TranslatableString &tip, wxCursor *&pCursor)
wxInt64 FrequencyToPosition(const WaveTrack *wt, double frequency, wxInt64 trackTopEdge, int trackHeight)
Converts a frequency to screen y position.
double PositionToFrequency(const WaveTrack *wt, bool maySnap, wxInt64 mouseYCoordinate, wxInt64 trackTopEdge, int trackHeight)
void SetIfNotNull(T *pValue, const T Value)
SelectionBoundary ChooseTimeBoundary(const double t0, const double t1, const ViewInfo &viewInfo, double selend, bool onlyWithinSnapDistance, wxInt64 *pPixelDist, double *pPinValue)
wxCursor * SelectCursor()
SelectionBoundary ChooseBoundary(const ViewInfo &viewInfo, wxCoord xx, wxCoord yy, const TrackView *pTrackView, const wxRect &rect, bool mayDragWidth, bool onlyWithinSnapDistance, double *pPinValue=NULL)
bool isSpectralSelectionView(const TrackView *pTrackView)
wxString Display(bool usesSpecialChars=false) const
Default message type for Publisher.
std::shared_ptr< TrackPanelCell > pCell