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"
31#include "../../../../../images/Cursors.h"
41 : mClickedTrack{ pTrack }
47#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
53(
const wxMouseState &state,
const AudacityProject *WXUNUSED(pProject),
bool unsafe)
55 static auto disabledCursor =
56 ::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
57 static wxCursor smoothCursor{ wxCURSOR_SPRAYCAN };
58 static auto pencilCursor =
63 auto message =
XO(
"Click and drag to edit the samples");
76 const wxMouseState &,
const std::shared_ptr<WaveChannel> &pChannel)
78 auto result = std::make_shared<SampleHandle>(pChannel);
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 const wxMouseState &state,
const wxRect &rect,
119 const AudacityProject *pProject,
const std::shared_ptr<WaveChannel> &pChannel)
128 auto &waveChannel = *pChannel;
129 const auto time = viewInfo.PositionToTime(state.m_x, rect.x);
130 const auto clickedClip =
135 const double tt =
adjustTime(waveChannel, time);
136 const auto intervals = viewInfo.FindIntervals(rect.width);
142 constexpr auto mayThrow =
false;
144 tt, oneSample, mayThrow))
149 float zoomMin, zoomMax;
150 cache.GetDisplayBounds(zoomMin, zoomMax);
152 double envValue = 1.0;
156 envValue = env->GetValue(tt);
159 const bool dB = !
settings.isLinear();
162 rect.height, dB,
true,
166 int yMouse = state.m_y;
169 const int yTolerance = 10;
170 if (abs(yValue - yMouse) >= yTolerance)
194 const wxMouseEvent &
event = evt.
event;
195 const wxRect &rect = evt.
rect;
198 const double t0 = viewInfo.PositionToTime(event.m_x, rect.x);
204 const auto intervals = viewInfo.FindIntervals(rect.width);
209 XO(
"To use Draw, zoom in further until you can see the individual samples."),
239 Floats sampleRegion{ sampleRegionSize };
243 constexpr auto mayThrow =
false;
245 t0, sampleRegion.get(),
250 float sumOfSamples = 0;
253 const auto sampleRegionIndex =
255 const auto inRange = sampleRegionRange.first <= sampleRegionIndex &&
256 sampleRegionIndex < sampleRegionRange.second;
268 sampleRegion[sampleRegionIndex];
334 assert(n < sortedClips.size());
335 const auto increment =
forward ? 1 : -1;
336 int last = n + increment;
337 const auto limit =
forward ? sortedClips.size() : -1;
338 while (last != limit)
345 assert(last >= 0 && last < sortedClips.size());
355 const wxMouseEvent &
event = evt.
event;
380 const double t1 = viewInfo.PositionToTime(event.m_x,
mRect.x);
385 const auto start =
std::min(t0, t1);
386 const auto end = std::max(t0, t1);
394 const auto iter = std::find_if(clips.begin(), clips.end(),
396 [
this](
const auto &pClip){ return *pClip == *mClickedClip; });
397 const auto clickedClipIndex = std::distance(clips.begin(), iter);
399 const auto intervals = viewInfo.FindIntervals(
mRect.width);
401 clickedClipIndex, !
forward, clips, viewInfo, intervals);
403 clickedClipIndex,
forward, clips, viewInfo, intervals);
405 const auto editStart =
406 std::max(start, clips[leftmostEditable]->GetPlayStartTime());
408 std::min(
end, clips[rightmostEditable]->GetPlayEndTime());
413 v1 = newLevel](
double t) {
416 const auto gradient = (v1 - v0) / (t1 - t0);
417 const auto value =
static_cast<float>(gradient * (t - t0) + v0);
419 return std::clamp(value,
std::min(v0, v1), std::max(v0, v1));
443 return this->
Cancel(pProject);
467 (
const wxMouseEvent &event,
const ViewInfo &viewInfo,
double t0)
471 float zoomMin, zoomMax;
473 cache.GetDisplayBounds(zoomMin, zoomMax);
475 const int yy =
event.m_y -
mRect.y;
476 const int height =
mRect.GetHeight();
478 const bool dB = !
settings.isLinear();
481 settings.dBRange, zoomMin, zoomMax);
487 double envValue = env->GetValue(t0);
489 newLevel /= envValue;
494 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)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
std::shared_ptr< WaveClipChannel > mClickedClip
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
float FindSampleEditingLevel(const wxMouseEvent &event, const ViewInfo &viewInfo, double t0)
float mLastDragSampleValue
std::shared_ptr< WaveChannel > mClickedTrack
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< WaveChannel > &pChannel)
void Enter(bool forward, AudacityProject *) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::shared_ptr< const Track > FindTrack() const override
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
static UIHandlePtr HitTest(std::weak_ptr< SampleHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, const std::shared_ptr< WaveChannel > &pChannel)
SampleHandle(const SampleHandle &)=delete
static std::shared_ptr< const Track > TrackFromChannel(const std::shared_ptr< const Channel > &pChannel)
A frequent convenience in the definition of UIHandles.
static ViewInfo & Get(AudacityProject &project)
int GetRate() const override
double GetPlayStartTime() const override
double GetStretchRatio() const override
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.
Namespace containing an enum 'what to do on a refresh?'.
WAVE_TRACK_API void SetFloatsCenteredAroundTime(WaveChannel &channel, double t, const float *buffer, size_t numSideSamples, sampleFormat effectiveFormat)
Similar to GetFloatsCenteredAroundTime, but for writing. Sets as many samples as it can according to ...
std::vector< ClipPointer > ClipPointers
WAVE_TRACK_API void SetFloatsWithinTimeRange(WaveChannel &channel, double t0, double t1, const std::function< float(double sampleTime)> &producer, sampleFormat effectiveFormat)
Provides a means of setting clip values as a function of time. Included are closest sample to t0 up t...
WAVE_TRACK_API std::pair< size_t, size_t > GetFloatsCenteredAroundTime(const WaveChannel &channel, double t, float *buffer, size_t numSideSamples, bool mayThrow)
Gets as many samples as it can, but no more than 2 * numSideSamples + 1, centered around t....
WAVE_TRACK_API ClipPointer GetClipAtTime(WaveChannel &channel, double time)
WAVE_TRACK_API bool GetFloatAtTime(const WaveChannel &channel, double t, float &value, bool mayThrow)
WAVE_TRACK_API Envelope * GetEnvelopeAtTime(WaveChannel &channel, double time)
WAVE_TRACK_API void SetFloatAtTime(WaveChannel &channel, double t, float value, sampleFormat effectiveFormat)
Sets sample nearest to t to value. Silently fails if GetClipAtTime(t) == nullptr.
WAVE_TRACK_API ClipPointers SortedClipArray(WaveChannel &channel)
Get clips sorted by play start time.
size_t GetLastEditableClipStartingFromNthClip(size_t n, bool forward, const WaveChannelUtilities::ClipPointers &sortedClips, const ViewInfo &viewInfo, const ZoomInfo::Intervals &intervals)
double adjustTime(const WaveChannel &wt, double time)
bool SampleResolutionTest(const ViewInfo &viewInfo, const WaveChannelInterval &clip, const ZoomInfo::Intervals &intervals)
const char * end(const char *str) noexcept