18#include "../../../../HitTestResult.h"
19#include "../../../../prefs/WaveformSettings.h"
22#include "../../../../RefreshCode.h"
23#include "../../../../TrackArt.h"
24#include "../../../../TrackArtist.h"
25#include "../../../../TrackPanelMouseEvent.h"
30#include "../../../../../images/Cursors.h"
40 : mClickedTrack{ pTrack }
46#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
52(
const wxMouseState &state,
const AudacityProject *WXUNUSED(pProject),
bool unsafe)
54 static auto disabledCursor =
55 ::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
56 static wxCursor smoothCursor{ wxCURSOR_SPRAYCAN };
57 static auto pencilCursor =
62 auto message =
XO(
"Click and drag to edit the samples");
75(std::weak_ptr<SampleHandle> &holder,
76 const wxMouseState &WXUNUSED(state),
const std::shared_ptr<WaveTrack> &pTrack)
78 auto result = std::make_shared<SampleHandle>( pTrack );
90 const auto sampleOffset =
91 clip->TimeToSamples(time - clip->GetPlayStartTime());
92 return clip->SamplesToTime(sampleOffset) + clip->GetPlayStartTime();
102 const auto xx = std::max<ZoomInfo::int64>(
105 ZoomInfo::Intervals::const_iterator it = intervals.begin(),
106 end = intervals.end(), prev;
107 wxASSERT(it !=
end && it->position == 0);
110 while (it !=
end && it->position <= xx);
111 const double threshold = 3 * rate;
113 return prev->averageZoom > threshold;
118(std::weak_ptr<SampleHandle> &holder,
119 const wxMouseState &state,
const wxRect &rect,
120 const AudacityProject *pProject,
const std::shared_ptr<WaveTrack> &pTrack)
126 const auto wavetrack = pTrack.get();
127 const auto time = viewInfo.PositionToTime(state.m_x, rect.x);
128 const auto clickedClip = wavetrack->GetClipAtTime(time);
132 const double tt =
adjustTime(*wavetrack, time);
133 const auto intervals = viewInfo.FindIntervals(rect.width);
140 constexpr auto mayThrow =
false;
141 if (!wavetrack->GetFloatAtTime(tt,
iChannel, oneSample, mayThrow))
146 float zoomMin, zoomMax;
147 cache.GetDisplayBounds(zoomMin, zoomMax);
149 double envValue = 1.0;
150 Envelope* env = wavetrack->GetEnvelopeAtTime(time);
156 const bool dB = !
settings.isLinear();
159 rect.height, dB,
true,
163 int yMouse = state.m_y;
166 const int yTolerance = 10;
167 if (abs(yValue - yMouse) >= yTolerance)
190 const wxMouseEvent &
event = evt.
event;
191 const wxRect &rect = evt.
rect;
194 const double t0 = viewInfo.PositionToTime(event.m_x, rect.x);
200 const auto intervals = viewInfo.FindIntervals(rect.width);
205 XO(
"To use Draw, zoom in further until you can see the individual samples."),
235 Floats sampleRegion{ sampleRegionSize };
240 constexpr auto mayThrow =
false;
241 const auto sampleRegionRange =
mClickedTrack->GetFloatsCenteredAroundTime(
247 float sumOfSamples = 0;
250 const auto sampleRegionIndex =
252 const auto inRange = sampleRegionRange.first <= sampleRegionIndex &&
253 sampleRegionIndex < sampleRegionRange.second;
265 sampleRegion[sampleRegionIndex];
333 assert(n < sortedClips.size());
334 const auto increment =
forward ? 1 : -1;
335 int last = n + increment;
336 const auto limit =
forward ? sortedClips.size() : -1;
337 while (last != limit)
344 assert(last >= 0 && last < sortedClips.size());
353 const wxMouseEvent &
event = evt.
event;
378 const double t1 = viewInfo.PositionToTime(event.m_x,
mRect.x);
383 const auto start =
std::min(t0, t1);
384 const auto end = std::max(t0, t1);
392 const auto clickedClipIndex = std::distance(
393 clips.begin(), std::find(clips.begin(), clips.end(),
mClickedClip));
395 const auto intervals = viewInfo.FindIntervals(
mRect.width);
397 clickedClipIndex, !
forward, clips, viewInfo, intervals);
399 clickedClipIndex,
forward, clips, viewInfo, intervals);
401 const auto editStart =
402 std::max(start, clips[leftmostEditable]->GetPlayStartTime());
404 std::min(
end, clips[rightmostEditable]->GetPlayEndTime());
409 v1 = newLevel](
double t) {
412 const auto gradient = (v1 - v0) / (t1 - t0);
413 const auto value =
static_cast<float>(gradient * (t - t0) + v0);
415 return std::clamp(value,
std::min(v0, v1), std::max(v0, v1));
440 return this->
Cancel(pProject);
464 (
const wxMouseEvent &event,
const ViewInfo &viewInfo,
double t0)
467 float zoomMin, zoomMax;
469 cache.GetDisplayBounds(zoomMin, zoomMax);
471 const int yy =
event.m_y -
mRect.y;
472 const int height =
mRect.GetHeight();
474 const bool dB = !
settings.isLinear();
477 settings.dBRange, zoomMin, zoomMax);
485 double envValue = env->
GetValue(t0);
487 newLevel /= envValue;
492 newLevel = std::max(-1.0f,
std::min(1.0f, newLevel));
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
std::shared_ptr< UIHandle > UIHandlePtr
static const int SMOOTHING_BRUSH_RADIUS
static const double SMOOTHING_PROPORTION_MAX
static const int SMOOTHING_KERNEL_RADIUS
static const double SMOOTHING_PROPORTION_MIN
int GetWaveYPos(float value, float min, float max, int height, bool dB, bool outer, float dBr, bool clip)
float ValueOfPixel(int yy, int height, bool offset, bool dB, double dBRange, float zoomMin, float zoomMax)
static Settings & settings()
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
std::vector< WaveClip * > WaveClipPointers
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Piecewise linear or piecewise exponential function from double to double.
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
float FindSampleEditingLevel(const wxMouseEvent &event, const ViewInfo &viewInfo, double t0)
float mLastDragSampleValue
Result Cancel(AudacityProject *pProject) override
static HitTestPreview HitPreview(const wxMouseState &state, const AudacityProject *pProject, bool unsafe)
static UIHandlePtr HitAnywhere(std::weak_ptr< SampleHandle > &holder, const wxMouseState &state, const std::shared_ptr< WaveTrack > &pTrack)
void Enter(bool forward, AudacityProject *) override
static UIHandlePtr HitTest(std::weak_ptr< SampleHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, const std::shared_ptr< WaveTrack > &pTrack)
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::shared_ptr< WaveTrack > mClickedTrack
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
SampleHandle(const SampleHandle &)=delete
std::shared_ptr< const Channel > FindChannel() const override
static ViewInfo & Get(AudacityProject &project)
This allows multiple clips to be a part of one WaveTrack.
double GetStretchRatio() const override
double GetPlayStartTime() const noexcept override
int GetRate() const override
A Track that contains audio waveform data.
const WaveClip * GetClipAtTime(double time) const
double SnapToSample(double t) const
double PositionToTime(int64 position, int64 origin=0, bool ignoreFisheye=false) const
std::vector< Interval > Intervals
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?'.
double adjustTime(const WaveTrack &wt, double time)
bool SampleResolutionTest(const ViewInfo &viewInfo, const WaveClip &clip, const ZoomInfo::Intervals &intervals)
size_t GetLastEditableClipStartingFromNthClip(size_t n, bool forward, const WaveClipPointers &sortedClips, const ViewInfo &viewInfo, const ZoomInfo::Intervals &intervals)