18#include "../../../../RefreshCode.h"
19#include "../../../../TrackPanelMouseEvent.h"
20#include "../../../../UIHandle.h"
22#include "../../../../prefs/WaveformSettings.h"
23#include "../../../../widgets/Ruler.h"
24#include "../../../../widgets/LinearUpdater.h"
25#include "../../../../widgets/RealFormat.h"
26#include "../../../../widgets/CustomUpdaterValue.h"
47 const double EPSILON = .1e-5;
51 const double CENTER = height / 2;
52 const int CENTER_SPACING = 30;
53 const double SIZE_SCALE = (max -
min) / 2;
55 double centerSpacingMark = 0;
57 for (
double major = 0.1; major < .95; major += .1) {
59 double mappedVal = std::trunc(-dBRange * val);
60 double pixDist = CENTER - ((1 -
DB_TO_LINEAR(mappedVal)) * CENTER) / SIZE_SCALE;
61 if (pixDist > CENTER_SPACING) {
62 centerSpacingMark = major;
67 for (
double minor = 0.05; minor < 1 ; minor += .1) {
69 double mappedVal = std::trunc(-dBRange * val);
70 if (minor < centerSpacingMark) {
75 for (
int minorMinor = 1; minorMinor < dBRange - EPSILON; minorMinor++) {
76 double absDist = fabs(fabs(dBRange - minorMinor) - dBRange) / dBRange;
77 if (absDist < centerSpacingMark) {
78 if ((minorMinor % (
int)
std::round(dBRange / 20)) != 0) {
91 std::vector<UIHandlePtr> results;
96 auto result = std::make_shared<WaveformVZoomHandle>(
99 results.push_back(result);
104 std::copy(more.begin(), more.end(), std::back_inserter(results));
116 const auto wt =
static_cast<WaveTrack*
>(pTrack.get());
138 const wxMouseEvent &
event = evt.
event;
140 if (!(event.ShiftDown() || event.CmdDown()))
145 evt.
event.Skip(
false);
147 auto steps = evt.
steps;
152 const bool isDB = !
settings.isLinear();
155 if (isDB && event.ShiftDown() && event.CmdDown()) {
157 cache.GetDisplayBounds(
min, max);
158 if (!(min < 0.0 && max > 0.0))
161 float olddBRange =
settings.dBRange;
166 channelSettings.NextLowerDBRange();
168 channelSettings.NextHigherDBRange();
171 float newdBRange =
settings.dBRange;
175 const auto &rect = evt.
rect;
176 const auto zeroLevel = cache.ZeroLevelYCoordinate(rect);
177 const bool fixedMagnification =
178 (4 * std::abs(event.GetY() - zeroLevel) < rect.GetHeight());
180 if (fixedMagnification) {
184 const float extreme = (
LINEAR_TO_DB(2) + newdBRange) / newdBRange;
185 max =
std::min(extreme, max * olddBRange / newdBRange);
186 min = std::max(-extreme,
min * olddBRange / newdBRange);
190 cache.SetDisplayBounds(
min, max);
194 else if (event.CmdDown() && !event.ShiftDown()) {
195 const int yy =
event.m_y;
201 evt.
rect, yy, yy,
true);
203 else if (!event.CmdDown() && event.ShiftDown()) {
205 static const float movement = 10.0f;
206 const int height = evt.
rect.GetHeight();
208 float topLimit = 2.0;
211 topLimit = (
LINEAR_TO_DB(topLimit) + dBRange) / dBRange;
213 const float bottomLimit = -topLimit;
216 cache.GetDisplayBounds(bottom, top);
217 const float range = top - bottom;
218 const float delta = range * steps * movement / height;
219 float newTop =
std::min(topLimit, top + delta);
220 const float newBottom = std::max(bottomLimit, newTop - range);
221 newTop =
std::min(topLimit, newBottom + range);
237 const wxRect &rect_,
unsigned iPass )
245 const auto wt = std::static_pointer_cast< WaveTrack >(
FindTrack() );
254 const wxRect &rect,
const WaveTrack *wt )
261 const float dBRange =
settings.dBRange;
265 cache.GetDisplayBounds(
min, max);
266 const float lastdBRange = cache.GetLastDBRange();
267 if (dBRange != lastdBRange)
270 auto scaleType =
settings.scaleType;
277 cache.GetLastScaleType() != -1)
282 float sign = (
min >= 0 ? 1 : -1);
289 sign = (max >= 0 ? 1 : -1);
297 cache.SetDisplayBounds(
min, max);
300 vruler->SetDbMirrorValue( 0.0 );
301 vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
302 vruler->SetOrientation(wxVERTICAL);
303 vruler->SetRange(max,
min);
306 vruler->SetLabelEdges(
false);
307 vruler->SetUnits({});
312 vruler->SetLabelEdges(
true);
313 vruler->SetUnits(
XO(
"dB"));
317 for (
int ii = 0; ii < 3; ii++) {
321 for (
int i = 0; i <
size; i++) {
326 if (value == -dBRange)
329 float sign = (value > -dBRange ? 1 : -1);
330 if (value < -dBRange)
331 value = -2 * dBRange - value;
335 wxString s = (value == -dBRange) ?
336 wxString(L
"-\u221e") : wxString::FromDouble(value);
355 vruler->SetUnits({});
361 cache.GetLastScaleType() != -1)
366 float sign = (
min >= 0 ? 1 : -1);
373 sign = (max >= 0 ? 1 : -1);
381 cache.SetDisplayBounds(
min, max);
383 else if (dBRange != lastdBRange) {
390#ifdef ONLY_LABEL_POSITIVE
391 const float sign = (max >= 0 ? 1 : -1);
395#define ZOOMLIMIT 0.001f
399 const float dB =
std::min(extreme, (
float(fabs(max)) * lastdBRange - lastdBRange));
402 newMax = sign * std::max(ZOOMLIMIT, (dBRange + dB) / dBRange);
406 min = std::max(-extreme, newMax *
min / max);
409 cache.SetDisplayBounds(
min, newMax);
416#ifdef ONLY_LABEL_POSITIVE
421 int bot = rect.height;
422 float botval = -dBRange;
424#ifdef ONLY_LABEL_POSITIVE
426 bot = top + (int)((max / (max -
min))*(bot - top));
431 top += (int)((max - 1) / (max -
min) * (bot - top));
435 if (max < 1 && max > 0)
436 topval = -((1 - max) * dBRange);
439 botval = -((1 -
min) * dBRange);
442 topval = -((1 - max) * dBRange);
443 botval = -((1 -
min) * dBRange);
444 vruler->SetDbMirrorValue( dBRange );
446 vruler->SetBounds(rect.x, rect.y + top, rect.x + rect.width, rect.y + bot - 1);
447 vruler->SetOrientation(wxVERTICAL);
448 vruler->SetRange(topval, botval);
449#ifdef ONLY_LABEL_POSITIVE
452 vruler->SetBounds(0.0, 0.0, 0.0, 0.0);
455 vruler->SetLabelEdges(
true);
static Settings & settings()
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
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...
std::shared_ptr< Track > FindTrack()
void SetData(RulerUpdater::Labels majorLabels, RulerUpdater::Labels minorLabels, RulerUpdater::Labels minorMinorLabels)
static const LinearUpdater & Instance()
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
std::vector< Label > Labels
std::pair< int, int > vrulerSize
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
A Track that contains audio waveform data.
Namespace containing an enum 'what to do on a refresh?'.
AUDACITY_DLL_API Ruler & ScratchRuler()
AUDACITY_DLL_API void DoDraw(TrackVRulerControls &controls, TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass)
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept
An array of these created by the Updater is used to determine what and where text annotations to the ...
std::optional< TranslatableString > text