17#include "../../../ui/ChannelView.h"
20#include "../../../../RefreshCode.h"
21#include "../../../../TrackPanelMouseEvent.h"
22#include "../../../../UIHandle.h"
25#include "../../../../widgets/Ruler.h"
26#include "../../../../widgets/LinearUpdater.h"
27#include "../../../../widgets/RealFormat.h"
28#include "../../../../widgets/CustomUpdaterValue.h"
49 const double EPSILON = .1e-5;
53 const double CENTER = height / 2;
54 const int CENTER_SPACING = 30;
55 const double SIZE_SCALE = (max -
min) / 2;
57 double centerSpacingMark = 0;
59 for (
double major = 0.1; major < .95; major += .1) {
61 double mappedVal = std::trunc(-dBRange * val);
62 double pixDist = CENTER - ((1 -
DB_TO_LINEAR(mappedVal)) * CENTER) / SIZE_SCALE;
63 if (pixDist > CENTER_SPACING) {
64 centerSpacingMark = major;
69 for (
double minor = 0.05; minor < 1 ; minor += .1) {
71 double mappedVal = std::trunc(-dBRange * val);
72 if (minor < centerSpacingMark) {
77 for (
int minorMinor = 1; minorMinor < dBRange - EPSILON; minorMinor++) {
78 double absDist = fabs(fabs(dBRange - minorMinor) - dBRange) / dBRange;
79 if (absDist < centerSpacingMark) {
80 if ((minorMinor % (
int)
std::round(dBRange / 20)) != 0) {
93 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));
112 return FindChannel<WaveChannel>();
143 const wxMouseEvent &
event = evt.
event;
145 if (!(event.ShiftDown() || event.CmdDown()))
150 evt.
event.Skip(
false);
152 auto steps = evt.
steps;
157 const bool isDB = !
settings.isLinear();
160 if (isDB && event.ShiftDown() && event.CmdDown()) {
162 cache.GetDisplayBounds(
min, max);
163 if (!(min < 0.0 && max > 0.0))
166 float olddBRange =
settings.dBRange;
173 float newdBRange =
settings.dBRange;
177 const auto &rect = evt.
rect;
178 const auto zeroLevel = cache.ZeroLevelYCoordinate(rect);
179 const bool fixedMagnification =
180 (4 * std::abs(event.GetY() - zeroLevel) < rect.GetHeight());
182 if (fixedMagnification) {
186 const float extreme = (
LINEAR_TO_DB(2) + newdBRange) / newdBRange;
187 max =
std::min(extreme, max * olddBRange / newdBRange);
188 min = std::max(-extreme,
min * olddBRange / newdBRange);
190 cache.SetDisplayBounds(
min, max);
193 else if (event.CmdDown() && !event.ShiftDown()) {
194 const int yy =
event.m_y;
200 evt.
rect, yy, yy,
true);
202 else if (!event.CmdDown() && event.ShiftDown()) {
204 static const float movement = 10.0f;
205 const int height = evt.
rect.GetHeight();
207 float topLimit = 2.0;
209 const float dBRange =
settings.dBRange;
210 topLimit = (
LINEAR_TO_DB(topLimit) + dBRange) / dBRange;
212 const float bottomLimit = -topLimit;
214 cache.GetDisplayBounds(bottom, top);
215 const float range = top - bottom;
216 const float delta = range * steps * movement / height;
217 float newTop =
std::min(topLimit, top + delta);
218 const float newBottom = std::max(bottomLimit, newTop - range);
219 newTop =
std::min(topLimit, newBottom + range);
220 cache.SetDisplayBounds(newBottom, newTop);
233 const wxRect &rect_,
unsigned iPass )
257 const float dBRange =
settings.dBRange;
261 cache.GetDisplayBounds(
min, max);
262 const float lastdBRange = cache.GetLastDBRange();
263 if (dBRange != lastdBRange)
266 auto scaleType =
settings.scaleType;
273 cache.GetLastScaleType() != -1)
278 float sign = (
min >= 0 ? 1 : -1);
285 sign = (max >= 0 ? 1 : -1);
293 cache.SetDisplayBounds(
min, max);
296 vruler->SetDbMirrorValue(0.0);
298 rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
299 vruler->SetOrientation(wxVERTICAL);
300 vruler->SetRange(max,
min);
303 vruler->SetLabelEdges(
false);
304 vruler->SetUnits({});
309 vruler->SetLabelEdges(
true);
310 vruler->SetUnits(
XO(
"dB"));
313 std::vector<LinearDBValues>
values =
315 for (
int ii = 0; ii < 3; ii++) {
319 for (
int i = 0; i <
size; i++) {
324 if (value == -dBRange)
327 float sign = (value > -dBRange ? 1 : -1);
328 if (value < -dBRange)
329 value = -2 * dBRange - value;
333 wxString s = (value == -dBRange) ?
334 wxString(L
"-\u221e") : wxString::FromDouble(value);
353 vruler->SetUnits(
XO(
"dB"));
356 cache.GetLastScaleType() != -1)
361 float sign = (
min >= 0 ? 1 : -1);
368 sign = (max >= 0 ? 1 : -1);
376 cache.SetDisplayBounds(
min, max);
378 else if (dBRange != lastdBRange) {
385#ifdef ONLY_LABEL_POSITIVE
386 const float sign = (max >= 0 ? 1 : -1);
390#define ZOOMLIMIT 0.001f
395 extreme, (
float(fabs(max)) * lastdBRange - lastdBRange));
398 newMax = sign * std::max(ZOOMLIMIT, (dBRange + dB) / dBRange);
402 min = std::max(-extreme, newMax *
min / max);
405 cache.SetDisplayBounds(
min, newMax);
412#ifdef ONLY_LABEL_POSITIVE
417 int bot = rect.height;
418 float botval = -dBRange;
420#ifdef ONLY_LABEL_POSITIVE
422 bot = top + (int)((max / (max -
min))*(bot - top));
427 top += (int)((max - 1) / (max -
min) * (bot - top));
431 if (max < 1 && max > 0)
432 topval = -((1 - max) * dBRange);
435 botval = -((1 -
min) * dBRange);
438 topval = -((1 - max) * dBRange);
439 botval = -((1 -
min) * dBRange);
440 vruler->SetDbMirrorValue( dBRange );
442 vruler->SetBounds(rect.x, rect.y + top, rect.x + rect.width, rect.y + bot - 1);
443 vruler->SetOrientation(wxVERTICAL);
444 vruler->SetRange(topval, botval);
445#ifdef ONLY_LABEL_POSITIVE
448 vruler->SetBounds(0.0, 0.0, 0.0, 0.0);
451 vruler->SetLabelEdges(
true);
455 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
static ChannelView & Get(Channel &channel)
std::pair< int, int > vrulerSize
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
virtual void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass)
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