16#include "../../../ui/ChannelView.h"
19#include "../../../../RefreshCode.h"
20#include "../../../../TrackPanelMouseEvent.h"
21#include "../../../../UIHandle.h"
23#include "../../../../prefs/WaveformSettings.h"
24#include "../../../../widgets/Ruler.h"
25#include "../../../../widgets/LinearUpdater.h"
26#include "../../../../widgets/RealFormat.h"
27#include "../../../../widgets/CustomUpdaterValue.h"
48 const double EPSILON = .1e-5;
52 const double CENTER = height / 2;
53 const int CENTER_SPACING = 30;
54 const double SIZE_SCALE = (max -
min) / 2;
56 double centerSpacingMark = 0;
58 for (
double major = 0.1; major < .95; major += .1) {
60 double mappedVal = std::trunc(-dBRange * val);
61 double pixDist = CENTER - ((1 -
DB_TO_LINEAR(mappedVal)) * CENTER) / SIZE_SCALE;
62 if (pixDist > CENTER_SPACING) {
63 centerSpacingMark = major;
68 for (
double minor = 0.05; minor < 1 ; minor += .1) {
70 double mappedVal = std::trunc(-dBRange * val);
71 if (minor < centerSpacingMark) {
76 for (
int minorMinor = 1; minorMinor < dBRange - EPSILON; minorMinor++) {
77 double absDist = fabs(fabs(dBRange - minorMinor) - dBRange) / dBRange;
78 if (absDist < centerSpacingMark) {
79 if ((minorMinor % (
int)
std::round(dBRange / 20)) != 0) {
92 std::vector<UIHandlePtr> results;
97 auto result = std::make_shared<WaveformVZoomHandle>(
100 results.push_back(result);
105 std::copy(more.begin(), more.end(), std::back_inserter(results));
117 const auto wt =
static_cast<WaveTrack*
>(pTrack.get());
139 const wxMouseEvent &
event = evt.
event;
141 if (!(event.ShiftDown() || event.CmdDown()))
146 evt.
event.Skip(
false);
148 auto steps = evt.
steps;
153 const bool isDB = !
settings.isLinear();
156 if (isDB && event.ShiftDown() && event.CmdDown()) {
158 cache.GetDisplayBounds(
min, max);
159 if (!(min < 0.0 && max > 0.0))
162 float olddBRange =
settings.dBRange;
170 float newdBRange =
settings.dBRange;
174 const auto &rect = evt.
rect;
175 const auto zeroLevel = cache.ZeroLevelYCoordinate(rect);
176 const bool fixedMagnification =
177 (4 * std::abs(event.GetY() - zeroLevel) < rect.GetHeight());
179 if (fixedMagnification) {
183 const float extreme = (
LINEAR_TO_DB(2) + newdBRange) / newdBRange;
184 max =
std::min(extreme, max * olddBRange / newdBRange);
185 min = std::max(-extreme,
min * olddBRange / newdBRange);
188 cache.SetDisplayBounds(
min, max);
191 else if (event.CmdDown() && !event.ShiftDown()) {
192 const int yy =
event.m_y;
198 evt.
rect, yy, yy,
true);
200 else if (!event.CmdDown() && event.ShiftDown()) {
202 static const float movement = 10.0f;
203 const int height = evt.
rect.GetHeight();
205 float topLimit = 2.0;
208 topLimit = (
LINEAR_TO_DB(topLimit) + dBRange) / dBRange;
210 const float bottomLimit = -topLimit;
213 cache.GetDisplayBounds(bottom, top);
214 const float range = top - bottom;
215 const float delta = range * steps * movement / height;
216 float newTop =
std::min(topLimit, top + delta);
217 const float newBottom = std::max(bottomLimit, newTop - range);
218 newTop =
std::min(topLimit, newBottom + range);
232 const wxRect &rect_,
unsigned iPass )
240 const auto wt = std::static_pointer_cast< WaveTrack >(
FindTrack() );
256 const float dBRange =
settings.dBRange;
260 cache.GetDisplayBounds(
min, max);
261 const float lastdBRange = cache.GetLastDBRange();
262 if (dBRange != lastdBRange)
265 auto scaleType =
settings.scaleType;
272 cache.GetLastScaleType() != -1)
277 float sign = (
min >= 0 ? 1 : -1);
284 sign = (max >= 0 ? 1 : -1);
292 cache.SetDisplayBounds(
min, max);
295 vruler->SetDbMirrorValue(0.0);
297 rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
298 vruler->SetOrientation(wxVERTICAL);
299 vruler->SetRange(max,
min);
302 vruler->SetLabelEdges(
false);
303 vruler->SetUnits({});
308 vruler->SetLabelEdges(
true);
309 vruler->SetUnits(
XO(
"dB"));
312 std::vector<LinearDBValues>
values =
314 for (
int ii = 0; ii < 3; ii++) {
318 for (
int i = 0; i <
size; i++) {
323 if (value == -dBRange)
326 float sign = (value > -dBRange ? 1 : -1);
327 if (value < -dBRange)
328 value = -2 * dBRange - value;
332 wxString s = (value == -dBRange) ?
333 wxString(L
"-\u221e") : wxString::FromDouble(value);
352 vruler->SetUnits(
XO(
"dB"));
358 cache.GetLastScaleType() != -1)
363 float sign = (
min >= 0 ? 1 : -1);
370 sign = (max >= 0 ? 1 : -1);
378 cache.SetDisplayBounds(
min, max);
380 else if (dBRange != lastdBRange) {
387#ifdef ONLY_LABEL_POSITIVE
388 const float sign = (max >= 0 ? 1 : -1);
392#define ZOOMLIMIT 0.001f
397 extreme, (
float(fabs(max)) * lastdBRange - lastdBRange));
400 newMax = sign * std::max(ZOOMLIMIT, (dBRange + dB) / dBRange);
404 min = std::max(-extreme, newMax *
min / max);
407 cache.SetDisplayBounds(
min, newMax);
414#ifdef ONLY_LABEL_POSITIVE
419 int bot = rect.height;
420 float botval = -dBRange;
422#ifdef ONLY_LABEL_POSITIVE
424 bot = top + (int)((max / (max -
min))*(bot - top));
429 top += (int)((max - 1) / (max -
min) * (bot - top));
433 if (max < 1 && max > 0)
434 topval = -((1 - max) * dBRange);
437 botval = -((1 -
min) * dBRange);
440 topval = -((1 - max) * dBRange);
441 botval = -((1 -
min) * dBRange);
442 vruler->SetDbMirrorValue( dBRange );
444 vruler->SetBounds(rect.x, rect.y + top, rect.x + rect.width, rect.y + bot - 1);
445 vruler->SetOrientation(wxVERTICAL);
446 vruler->SetRange(topval, botval);
447#ifdef ONLY_LABEL_POSITIVE
450 vruler->SetBounds(0.0, 0.0, 0.0, 0.0);
453 vruler->SetLabelEdges(
true);
457 vruler->GetMaxSize(&
size.first, &
size.second);
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::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
static ChannelView & Get(Channel &channel)
std::pair< int, int > vrulerSize
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
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(ChannelVRulerControls &controls, TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass)
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept
void copy(const T *src, T *dst, int32_t n)
An array of these created by the Updater is used to determine what and where text annotations to the ...
std::optional< TranslatableString > text