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;
96 auto result = std::make_shared<WaveformVZoomHandle>(
99 results.push_back(result);
104 std::copy(more.begin(), more.end(), std::back_inserter(results));
111 return FindChannel<WaveChannel>();
142 const wxMouseEvent &
event = evt.
event;
144 if (!(event.ShiftDown() || event.CmdDown()))
149 evt.
event.Skip(
false);
151 auto steps = evt.
steps;
156 const bool isDB = !
settings.isLinear();
159 if (isDB && event.ShiftDown() && event.CmdDown()) {
161 cache.GetDisplayBounds(
min, max);
162 if (!(min < 0.0 && max > 0.0))
165 float olddBRange =
settings.dBRange;
172 float newdBRange =
settings.dBRange;
176 const auto &rect = evt.
rect;
177 const auto zeroLevel = cache.ZeroLevelYCoordinate(rect);
178 const bool fixedMagnification =
179 (4 * std::abs(event.GetY() - zeroLevel) < rect.GetHeight());
181 if (fixedMagnification) {
185 const float extreme = (
LINEAR_TO_DB(2) + newdBRange) / newdBRange;
186 max =
std::min(extreme, max * olddBRange / newdBRange);
187 min = std::max(-extreme,
min * olddBRange / newdBRange);
189 cache.SetDisplayBounds(
min, max);
192 else if (event.CmdDown() && !event.ShiftDown()) {
193 const int yy =
event.m_y;
199 evt.
rect, yy, yy,
true);
201 else if (!event.CmdDown() && event.ShiftDown()) {
203 static const float movement = 10.0f;
204 const int height = evt.
rect.GetHeight();
206 float topLimit = 2.0;
208 const float dBRange =
settings.dBRange;
209 topLimit = (
LINEAR_TO_DB(topLimit) + dBRange) / dBRange;
211 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);
219 cache.SetDisplayBounds(newBottom, newTop);
232 const wxRect &rect_,
unsigned iPass )
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"));
355 cache.GetLastScaleType() != -1)
360 float sign = (
min >= 0 ? 1 : -1);
367 sign = (max >= 0 ? 1 : -1);
375 cache.SetDisplayBounds(
min, max);
377 else if (dBRange != lastdBRange) {
384#ifdef ONLY_LABEL_POSITIVE
385 const float sign = (max >= 0 ? 1 : -1);
389#define ZOOMLIMIT 0.001f
394 extreme, (
float(fabs(max)) * lastdBRange - lastdBRange));
397 newMax = sign * std::max(ZOOMLIMIT, (dBRange + dB) / dBRange);
401 min = std::max(-extreme, newMax *
min / max);
404 cache.SetDisplayBounds(
min, newMax);
411#ifdef ONLY_LABEL_POSITIVE
416 int bot = rect.height;
417 float botval = -dBRange;
419#ifdef ONLY_LABEL_POSITIVE
421 bot = top + (int)((max / (max -
min))*(bot - top));
426 top += (int)((max - 1) / (max -
min) * (bot - top));
430 if (max < 1 && max > 0)
431 topval = -((1 - max) * dBRange);
434 botval = -((1 -
min) * dBRange);
437 topval = -((1 - max) * dBRange);
438 botval = -((1 -
min) * dBRange);
439 vruler->SetDbMirrorValue( dBRange );
441 vruler->SetBounds(rect.x, rect.y + top, rect.x + rect.width, rect.y + bot - 1);
442 vruler->SetOrientation(wxVERTICAL);
443 vruler->SetRange(topval, botval);
444#ifdef ONLY_LABEL_POSITIVE
447 vruler->SetBounds(0.0, 0.0, 0.0, 0.0);
450 vruler->SetLabelEdges(
true);
454 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
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
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