18#include "../../SpectrumAnalyst.h"
19#include "../../LabelTrack.h"
24#include "../../ProjectSettings.h"
25#include "../../ProjectWindow.h"
26#include "../../RefreshCode.h"
27#include "../../SelectUtilities.h"
30#include "../../TrackArtist.h"
31#include "../../TrackPanelAx.h"
32#include "../../TrackPanel.h"
33#include "../../TrackPanelDrawingContext.h"
34#include "../../TrackPanelMouseEvent.h"
38#include "../../prefs/SpectrogramSettings.h"
39#include "../../../images/Cursors.h"
71 float minFreq, maxFreq;
75 return trackTopEdge + wxInt64((1.0 - p) * trackHeight);
82 wxInt64 mouseYCoordinate,
86 const double rate = wt->
GetRate();
97 float minFreq, maxFreq;
101 const double p = double(mouseYCoordinate - trackTopEdge) / trackHeight;
119 pTrackView->
FindTrack()->TypeSwitch<
bool >(
122 return settings.SpectralSelectionEnabled();
129#ifdef EXPERIMENTAL_SPECTRAL_EDITING
130 SBBottom, SBTop, SBCenter, SBWidth,
136 const double t0,
const double t1,
138 double selend,
bool onlyWithinSnapDistance,
139 wxInt64 *pPixelDist,
double *pPinValue)
143 wxInt64 pixelDist = std::abs(posS - pos0);
144 bool chooseLeft =
true;
149 chooseLeft = (selend < t0);
152 const wxInt64 rightDist = std::abs(posS - pos1);
153 if (rightDist < pixelDist)
154 chooseLeft =
false, pixelDist = rightDist;
159 if (onlyWithinSnapDistance &&
164 else if (chooseLeft) {
176 wxCoord xx, wxCoord yy,
const TrackView *pTrackView,
const wxRect &rect,
177 bool mayDragWidth,
bool onlyWithinSnapDistance,
178 double *pPinValue = NULL)
186 wxInt64 pixelDist = 0;
192 &pixelDist, pPinValue);
194#ifdef EXPERIMENTAL_SPECTRAL_EDITING
202 bool chooseTime =
true;
203 bool chooseBottom =
true;
204 bool chooseCenter =
false;
208 t0 <= selend && selend < t1 &&
213 static_cast<const WaveTrack*
>(pTrack.get());
214 const wxInt64 bottomSel = (f0 >= 0)
216 : rect.y + rect.height;
217 const wxInt64 topSel = (f1 >= 0)
220 wxInt64 signedBottomDist = (int)(yy - bottomSel);
221 wxInt64 verticalDist = std::abs(signedBottomDist);
222 if (bottomSel == topSel)
224 chooseBottom = (signedBottomDist >= 0);
226 const wxInt64 topDist = std::abs((
int)(yy - topSel));
227 if (topDist < verticalDist)
228 chooseBottom =
false, verticalDist = topDist;
231#ifdef SPECTRAL_EDITING_ESC_KEY
235 const wxInt64 centerSel =
237 const wxInt64 centerDist = abs((
int)(yy - centerSel));
238 if (centerDist < verticalDist)
239 chooseCenter =
true, verticalDist = centerDist,
242 if (verticalDist >= 0 &&
243 verticalDist < pixelDist) {
244 pixelDist = verticalDist;
252 if (onlyWithinSnapDistance &&
257 else if (chooseCenter) {
261 else if (mayDragWidth && fc > 0) {
265 else if (chooseBottom) {
283 static auto selectCursor =
285 return &*selectCursor;
291 static auto envelopeCursor =
293 return &*envelopeCursor;
300 static wxCursor adjustLeftSelectionCursor{ wxCURSOR_POINT_LEFT };
301 static wxCursor adjustRightSelectionCursor{ wxCURSOR_POINT_RIGHT };
303 static auto bottomFrequencyCursor =
304 ::MakeCursor(wxCURSOR_ARROW, BottomFrequencyCursorXpm, 16, 16);
305 static auto topFrequencyCursor =
306 ::MakeCursor(wxCURSOR_ARROW, TopFrequencyCursorXpm, 16, 16);
307 static auto bandWidthCursor =
308 ::MakeCursor(wxCURSOR_ARROW, BandWidthCursorXpm, 16, 16);
315 tip =
XO(
"Click and drag to move left selection boundary.");
316 pCursor = &adjustLeftSelectionCursor;
319 tip =
XO(
"Click and drag to move right selection boundary.");
320 pCursor = &adjustRightSelectionCursor;
322#ifdef EXPERIMENTAL_SPECTRAL_EDITING
324 tip =
XO(
"Click and drag to move bottom selection frequency.");
325 pCursor = &*bottomFrequencyCursor;
328 tip =
XO(
"Click and drag to move top selection frequency.");
329 pCursor = &*topFrequencyCursor;
333#ifndef SPECTRAL_EDITING_ESC_KEY
336 XO(
"Click and drag to move center selection frequency to a spectral peak.") :
337 XO(
"Click and drag to move center selection frequency.");
343 XO(
"Click and drag to move center selection frequency.");
351 tip =
XO(
"Click and drag to adjust frequency bandwidth.");
352 pCursor = &*bandWidthCursor;
363(std::weak_ptr<SelectHandle> &holder,
365 const std::shared_ptr<TrackView> &pTrackView)
369 auto old = holder.lock();
370 bool oldUseSnap =
true;
373 if( old->mTimerHandler ) {
377 old->mTimerHandler.reset();
379 oldUseSnap = old->mUseSnap;
383 auto result = std::make_shared<SelectHandle>(
384 pTrackView, oldUseSnap,
TrackList::Get( *pProject ), st, viewInfo );
391 auto pTrack = pTrackView->FindTrack();
392 if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
398 const wxRect &rect = st.
rect;
399 wxInt64 leftSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t0(), rect.x);
400 wxInt64 rightSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t1(), rect.x);
402 wxASSERT(!(rightSel < leftSel));
403 static_cast<void>(leftSel);
404 static_cast<void>(rightSel);
415 wxASSERT( useSnap == newState.
mUseSnap );
421 if ( oldSnapState.Snapped() == newSnapState.Snapped() &&
422 (!oldSnapState.Snapped() ||
423 oldSnapState.outCoord == newSnapState.outCoord) )
430(
const std::shared_ptr<TrackView> &pTrackView,
bool useSnap,
433 : mpView{ pTrackView }
437 SnapPoint{ viewInfo.playRegion.GetLastActiveStart() },
438 SnapPoint{ viewInfo.playRegion.GetLastActiveEnd() },
441 const wxMouseState &state = st.
state;
445 auto pTrack = pTrackView->FindTrack();
461 template <
class A,
class B,
class DIST >
bool within(
A a, B b, DIST d)
463 return (a > b - d) && (a < b + d);
468 const double minFrequency = 1.0;
469 const double maxFrequency = (rate / 2.0);
470 const double frequency =
472 std::max(minFrequency, center));
474 std::min(frequency / minFrequency, maxFrequency / frequency);
529 const auto pView =
mpView.lock();
533 wxMouseEvent &
event = evt.
event;
535 const auto pTrack = sTrack.get();
542 bool selectChange = (
544 event.ControlDown() &&
548 bool bShift =
event.ShiftDown();
551 *pProject, pTrack, bShift,
true, !unsafe);
560 if (event.LeftDClick() && !event.ShiftDown()) {
564 selectionState.SelectNone( trackList );
566 selectionState.SelectTrack( *pTrack,
true,
true );
574 pTrack->TypeSwitch( [&] (
WaveTrack *wt ) {
575 auto time = viewInfo.PositionToTime(event.m_x,
mRect.x);
578 viewInfo.selectedRegion.setTimes(
579 selectedClip->GetPlayStartTime(), selectedClip->GetPlayEndTime());
588 else if (!event.LeftDown())
595 std::make_shared< SelectionStateChanger >( selectionState, trackList );
599 bool bShiftDown =
event.ShiftDown();
600 bool bCtrlDown =
event.ControlDown();
606 if (bShiftDown || bCtrlDown) {
608 selectionState.ChangeSelectionOnShiftClick( trackList, *pTrack );
613 bool bIsSelected =
false;
615 if( !bIsSelected || trackPanel.GetSelectedTrackCount() > 1 )
616 selectionState.SelectTrack( *pTrack, !bIsSelected,
true );
623 pView.get(),
mRect,
false,
false, &value);
629#ifdef EXPERIMENTAL_SPECTRAL_EDITING
640#ifdef EXPERIMENTAL_SPECTRAL_EDITING
647 (boundary == SBBottom)
659 const auto wt =
static_cast<const WaveTrack*
>(pTrack);
682 bool startNewSelection =
true;
683 if (pTrack && pTrack->GetSelected()) {
686 if (viewInfo.bAdjustSelectionEdges) {
687#ifdef EXPERIMENTAL_SPECTRAL_EDITING
718 pView.get(),
mRect,
true,
true, &value);
726 startNewSelection =
false;
727#ifdef EXPERIMENTAL_SPECTRAL_EDITING
735#ifdef EXPERIMENTAL_SPECTRAL_EDITING
739 startNewSelection =
false;
751 const auto wt =
static_cast<const WaveTrack*
>(pTrack);
753 startNewSelection =
false;
766 if (startNewSelection) {
768 selectionState.SelectNone( trackList );
769#ifdef EXPERIMENTAL_SPECTRAL_EDITING
774 selectionState.SelectTrack( *pTrack,
true,
true );
791 const auto pView =
mpView.lock();
796 const wxMouseEvent &
event = evt.
event;
811 if (event.CmdDown()) {
827 enum { minimumSizedSelection = 5 };
833 if (wxLongLong(SelStart - x).Abs() < minimumSizedSelection)
838 if (
auto clickedTrack =
841 Track *sTrack = pTrack.get();
842 Track *eTrack = clickedTrack.get();
844 if ( sTrack && eTrack && !event.ControlDown() ) {
846 selectionState.SelectRangeOfTracks( trackList, *sTrack, *eTrack );
849 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
850 #ifndef SPECTRAL_EDITING_ESC_KEY
852 !viewInfo.selectedRegion.isPoint())
854 (pProject, viewInfo, y,
mRect.y,
mRect.height, pView.get());
887 const auto pView =
mpView.lock();
908 auto &state = st.
state;
910 auto xx = viewInfo.TimeToPosition(time,
mRect.x);
912 const bool bMultiToolMode =
916 if (bMultiToolMode) {
925 keyStr =
_(
"Edit, Preferences...");
928 tip =
XO(
"Multi-Tool Mode: %s for Mouse and Keyboard Preferences.")
931 if (!pTrack->GetSelected() ||
932 !viewInfo.bAdjustSelectionEdges)
935 const wxRect &rect = st.
rect;
936 const bool bShiftDown = state.ShiftDown();
937 const bool bCtrlDown = state.ControlDown();
938 const bool bModifierDown = bShiftDown || bCtrlDown;
945 pView.get(), rect, !bModifierDown, !bModifierDown);
955#ifdef EXPERIMENTAL_SPECTRAL_EDITING
959 tip =
XO(
"Click and drag to set frequency bandwidth.");
960 pCursor = &*envelopeCursor;
966 if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
969 const wxRect &rect = st.
rect;
970 const bool bShiftDown = state.ShiftDown();
971 const bool bCtrlDown = state.ControlDown();
972 const bool bModifierDown = bShiftDown || bCtrlDown;
974 viewInfo, xx, state.m_y,
975 pView.get(), rect, !bModifierDown, !bModifierDown);
980 tip =
XO(
"Click and drag to select audio");
985 XO(
"(snapping)"),
wxT(
" ")
988 return { tip, pCursor };
1020 const wxRect &rect,
unsigned iPass )
1023 auto &dc = context.
dc;
1035 const wxRect &rect,
const wxRect &panelRect,
unsigned iPass )
1045 auto pView =
mpView.lock();
1049 return pView->FindTrack();
1054 mTimerHandler = std::make_shared<TimerHandler>(
this, pProject );
1102 window.TP_ScrollRight();
1106 window.TP_ScrollLeft();
1114 trackPanel.ClientToScreen(&xx, &yy);
1117 window.TP_ScrollLeft();
1121 ::wxDisplaySize(&width, &height);
1122 if (xx == width - 1) {
1124 window.TP_ScrollRight();
1136 wxMouseEvent evt(wxEVT_MOTION);
1137 const auto size = trackPanel.GetSize();
1167 ViewInfo &viewInfo,
int mouseXCoordinate,
int trackLeftEdge,
1175 std::max(0.0, viewInfo.
PositionToTime(mouseXCoordinate, trackLeftEdge));
1176 double origSelend = selend;
1200 selend = origSelend;
1224 int mouseYCoordinate,
int trackTopEdge,
1238 trackTopEdge, trackHeight);
1245 int mouseYCoordinate,
int trackTopEdge,
1255 const double rate = wt->
GetRate();
1256 const double frequency =
1258 trackTopEdge, trackHeight);
1262 if (frequency == rate || frequency < 1.0)
1272 frequency / ratio, frequency * ratio);
1278 if (frequency == rate || frequency < 1.0)
1290 ratio = 1.0 / ratio;
1299 const bool bottomDefined =
1301 const bool topDefined =
1303 if (!bottomDefined || (topDefined &&
mFreqSelPin < frequency)) {
1305 if (frequency == rate)
1315 if (frequency < 1.0)
1327(
const ViewInfo &viewInfo,
bool shiftDown,
const WaveTrack *pTrack,
double value)
1337#ifndef SPECTRAL_EDITING_ESC_KEY
1353 static const size_t minLength = 8;
1355 const double rate = pTrack->
GetRate();
1358 std::vector<float> frequencySnappingData;
1364 std::min(frequencySnappingData.max_size(),
1367 const auto effectiveLength = std::max(minLength, length);
1368 frequencySnappingData.resize(effectiveLength, 0.0f);
1370 &frequencySnappingData[0],
1379 auto windowSize =
settings.GetFFTLength();
1381 while(windowSize > effectiveLength)
1383 const int windowType =
settings.windowType;
1387 &frequencySnappingData[0], length);
1397 auto pTrack = pTrackView->
FindTrack().get();
1399 pTrack->GetSelected() &&
1410 const double rate = wt->
GetRate();
1411 const double frequency =
1413 trackTopEdge, trackHeight);
1414 const double snappedFrequency =
1416 const double maxRatio =
findMaxRatio(snappedFrequency, rate);
1421 if (f1 >= f0 && f0 >= 0)
1423 ratio = sqrt(f1 / f0);
1429 snappedFrequency / ratio, snappedFrequency * ratio);
1447 const auto windowSize =
settings.GetFFTLength();
1448 const double rate = pTrack->
GetRate();
1449 const double nyq = rate / 2.0;
1450 const double binFrequency = rate / windowSize;
1454 if (centerFrequency <= 0) {
1455 centerFrequency = up ? binFrequency : nyq;
1456 f1 = centerFrequency * sqrt(2.0);
1459 double ratio = f1 / centerFrequency;
1460 const int originalBin = floor(0.5 + centerFrequency / binFrequency);
1461 const int limitingBin = up ? floor(0.5 + nyq / binFrequency) : 1;
1467 double snappedFrequency = centerFrequency;
1468 int bin = originalBin;
1470 while (snappedFrequency <= centerFrequency &&
1472 snappedFrequency = analyst.
FindPeak(++bin * binFrequency, NULL);
1475 while (snappedFrequency >= centerFrequency &&
1477 snappedFrequency = analyst.
FindPeak(--bin * binFrequency, NULL);
1481 const double maxRatio =
findMaxRatio(snappedFrequency, rate);
1485 (snappedFrequency / ratio, snappedFrequency * ratio);
1490void SelectHandle::ResetFreqSelectionPin
1491 (
const ViewInfo &viewInfo,
double hintFrequency,
bool logF)
1493 switch (mFreqSelMode) {
1508 if (f0 >= 0 && f1 >= 0)
1528 const double logf1 = log(std::max(1.0, f1));
1529 const double logf0 = log(std::max(1.0, f0));
1530 const double logHint = log(std::max(1.0, hintFrequency));
1531 if (std::abs(logHint - logf1) < std::abs(logHint - logf0))
1539 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)
void GetBounds(const WaveTrack &wt, float &min, float &max) const
static SpectrogramBounds & Get(WaveTrack &track)
Get either the global default settings, or the track's own if previously created.
static SpectrogramSettings & Get(const WaveTrack &track)
Mutative access to attachment even if the track argument is const.
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)
bool IsSyncLocked() const
static SyncLockState & Get(AudacityProject &project)
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.
WaveClip * GetClipAtTime(double time)
double GetRate() const override
double PositionToTime(int64 position, int64 origin=0, bool ignoreFisheye=false) const
int64 TimeToPosition(double time, int64 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