From ac6c1454d93720e1561a00f0968d4630130ff0c6 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 3 Jul 2022 18:23:38 -0400 Subject: [PATCH 01/19] Split update across classes Modify the code of Ruler's Updater so that it is polymorphic and utilizes a pure virtual Update function. --- src/widgets/Ruler.cpp | 175 ++++++++++++++++++++++++++---------------- src/widgets/Ruler.h | 3 + 2 files changed, 111 insertions(+), 67 deletions(-) diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index df878074cbe0..872b743bdf9d 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -894,20 +894,54 @@ struct Ruler::Updater { static void ChooseFonts( std::unique_ptr &pFonts, const Fonts *pUserFonts, - wxDC &dc, int desiredPixelHeight ); + wxDC &dc, int desiredPixelHeight + ); struct UpdateOutputs; + + void BoxAdjust( + UpdateOutputs& allOutputs + ) + const; - void Update( + virtual void Update( wxDC &dc, const Envelope* envelope, UpdateOutputs &allOutputs )// Envelope *speedEnv, long minSpeed, long maxSpeed ) - const; + const = 0; +}; + +struct Ruler::LinearUpdater : public virtual Ruler::Updater { + explicit LinearUpdater( const Ruler &ruler, const ZoomInfo *z ) + : Updater{ ruler, z } + {} + + void Update( + wxDC &dc, const Envelope* envelope, + UpdateOutputs &allOutputs + ) const override; +}; + +struct Ruler::LogarithmicUpdater : public virtual Ruler::Updater { + explicit LogarithmicUpdater( const Ruler &ruler, const ZoomInfo *z ) + : Updater{ ruler, z } + {} - void UpdateCustom( wxDC &dc, UpdateOutputs &allOutputs ) const; - void UpdateLinear( - wxDC &dc, const Envelope *envelope, UpdateOutputs &allOutputs ) const; - void UpdateNonlinear( wxDC &dc, UpdateOutputs &allOutputs ) const; + void Update( + wxDC &dc, const Envelope* envelope, + UpdateOutputs &allOutputs + ) const override; +}; + +struct Ruler::CustomUpdater : public virtual Ruler::Updater { + explicit CustomUpdater( const Ruler &ruler, const ZoomInfo *z ) + : Updater{ ruler, z } + {} + + void Update( + wxDC &dc, const Envelope* envelope, + UpdateOutputs &allOutputs + ) const override; }; struct Ruler::Cache { @@ -1049,7 +1083,50 @@ void Ruler::Updater::ChooseFonts( fonts.minorMinor = wxFont{ fontSize - 1, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL }; } -void Ruler::Updater::UpdateCustom( wxDC &dc, UpdateOutputs &allOutputs ) const +void Ruler::Updater::BoxAdjust( + UpdateOutputs &allOutputs +) + const +{ + int displacementx=0, displacementy=0; + auto &box = allOutputs.box; + if (!mFlip) { + if (mOrientation==wxHORIZONTAL) { + int d = mTop + box.GetHeight() + 5; + box.Offset(0,d); + box.Inflate(0,5); + displacementx=0; + displacementy=d; + } + else { + int d = mLeft - box.GetLeft() + 5; + box.Offset(d,0); + box.Inflate(5,0); + displacementx=d; + displacementy=0; + } + } + else { + if (mOrientation==wxHORIZONTAL) { + box.Inflate(0,5); + displacementx=0; + displacementy=0; + } + } + auto update = [=]( Label &label ){ + label.lx += displacementx; + label.ly += displacementy; + }; + for( auto &label : allOutputs.majorLabels ) + update( label ); + for( auto &label : allOutputs.minorLabels ) + update( label ); + for( auto &label : allOutputs.minorMinorLabels ) + update( label ); +} + +void Ruler::CustomUpdater::Update( + wxDC &dc, const Envelope *envelope, UpdateOutputs &allOutputs ) const { TickOutputs majorOutputs{ allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; @@ -1061,9 +1138,11 @@ void Ruler::Updater::UpdateCustom( wxDC &dc, UpdateOutputs &allOutputs ) const for( int i = 0; (i(mLength + 1), false ); - // Keep Updater const! We want no hidden state changes affecting its - // computations. - const Updater updater{ *this, zoomInfo }; + Updater * updater; + if ( mCustom ) { + CustomUpdater cUpdater{ *this, zoomInfo }; + updater = &cUpdater; + } + else if ( !mLog ) { + LinearUpdater linUpdater{ *this, zoomInfo }; + updater = &linUpdater; + } + else { + LogarithmicUpdater logUpdater{ *this, zoomInfo }; + updater = &logUpdater; + } + Updater::UpdateOutputs allOutputs{ cache.mMajorLabels, cache.mMinorLabels, cache.mMinorMinorLabels, cache.mBits, cache.mRect }; - updater.Update(dc, envelope, allOutputs); + updater->Update(dc, envelope, allOutputs); } auto Ruler::GetFonts() const -> Fonts diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index 41b0155e0852..fc57ca944bd6 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -172,6 +172,9 @@ class AUDACITY_DLL_API Ruler { void UpdateCache( wxDC &dc, const Envelope* envelope ) const; struct Updater; + struct LinearUpdater; + struct LogarithmicUpdater; + struct CustomUpdater; public: bool mbTicksOnly; // true => no line the length of the ruler From 20b598f1b4a3c591f7caa384e966e05fe797e4e3 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 3 Jul 2022 18:30:41 -0400 Subject: [PATCH 02/19] Rename sg to sign As discussed, change the name of sg to sign to be more clear to developers. --- src/widgets/Ruler.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 872b743bdf9d..228b7cc0f1ac 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -1208,7 +1208,7 @@ void Ruler::LinearUpdater::Update( TickAtValue( 0.0 ); } - double sg = UPP > 0.0? 1.0: -1.0; + double sign = UPP > 0.0? 1.0: -1.0; int nDroppedMinorLabels=0; // Major and minor ticks @@ -1237,7 +1237,7 @@ void Ruler::LinearUpdater::Update( warpedD = d; // using ints doesn't work, as // this will overflow and be negative at high zoom. - double step = floor(sg * warpedD / denom); + double step = floor(sign * warpedD / denom); while (ii <= mLength) { ii++; if (zoomInfo) @@ -1255,11 +1255,11 @@ void Ruler::LinearUpdater::Update( warpedD = nextD; d = nextD; - if (floor(sg * warpedD / denom) > step) { - step = floor(sg * warpedD / denom); + if (floor(sign * warpedD / denom) > step) { + step = floor(sign * warpedD / denom); bool major = jj == 0; tickSizes.useMajor = major; - bool ticked = Tick( dc, ii, sg * step * denom, tickSizes, + bool ticked = Tick( dc, ii, sign * step * denom, tickSizes, font, outputs ); if( !major && !ticked ){ nDroppedMinorLabels++; From c5c7bbaa48ba99c56dc52a63ae3d75cfe52af128 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 11:52:33 -0400 Subject: [PATCH 03/19] Initial changes to Ruler.h Adding mpUpdater and SetUpdater to the ruler. This is assuming that Updater will still be a nested class of Ruler. I will make a later branch that will un-nest Updater and Format from Ruler to give multiple ways to proceed. Quick Fix Removed some faulty code from previous push Update Ruler.h --- src/widgets/Ruler.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index fc57ca944bd6..11e0820c9d06 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -24,6 +24,13 @@ class Envelope; class ZoomInfo; class AUDACITY_DLL_API Ruler { +private: + + struct Updater; + struct LinearUpdater; + struct LogarithmicUpdater; + struct CustomUpdater; + public: enum RulerFormat { @@ -62,6 +69,10 @@ class AUDACITY_DLL_API Ruler { // (at the center of the pixel, in both cases) void SetRange(double min, double max, double hiddenMin, double hiddenMax); + // Set the kind of updater the ruler will use + // (Linear, Logarithmic, Custom, etc.) + void SetUpdater(std::unique_ptr pUpdater); + // // Optional Ruler Parameters // @@ -170,11 +181,6 @@ class AUDACITY_DLL_API Ruler { void ChooseFonts( wxDC &dc ) const; void UpdateCache( wxDC &dc, const Envelope* envelope ) const; - - struct Updater; - struct LinearUpdater; - struct LogarithmicUpdater; - struct CustomUpdater; public: bool mbTicksOnly; // true => no line the length of the ruler @@ -190,6 +196,8 @@ class AUDACITY_DLL_API Ruler { std::unique_ptr mpUserFonts; mutable std::unique_ptr mpFonts; + std::unique_ptr mpUpdater; + double mMin, mMax; double mHiddenMin, mHiddenMax; From 3112164b6a39cb6a615d3536a3d7458e302febf7 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 14:44:51 -0400 Subject: [PATCH 04/19] Define functions and change existing updater code --- src/widgets/Ruler.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 228b7cc0f1ac..1c507f45898e 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -116,6 +116,9 @@ Ruler::Ruler() mTwoTone = false; mUseZoomInfo = NULL; + + // Default the updater to Linear, as it would be before removal of mLog + mpUpdater = std::make_unique( *this, mUseZoomInfo ); } Ruler::~Ruler() @@ -139,6 +142,14 @@ void Ruler::SetFormat(RulerFormat format) } } +void Ruler::SetUpdater(std::unique_ptr pUpdater) +{ + // Should a comparison be made between mpUpdater and pUpdater? + // Runtime type comparison isn't clean in c++ + mpUpdater = std::move(pUpdater); + Invalidate(); +} + void Ruler::SetLog(bool log) { // Logarithmic @@ -1434,26 +1445,12 @@ void Ruler::UpdateCache( cache.mBits = mUserBits; cache.mBits.resize( static_cast(mLength + 1), false ); - - Updater * updater; - if ( mCustom ) { - CustomUpdater cUpdater{ *this, zoomInfo }; - updater = &cUpdater; - } - else if ( !mLog ) { - LinearUpdater linUpdater{ *this, zoomInfo }; - updater = &linUpdater; - } - else { - LogarithmicUpdater logUpdater{ *this, zoomInfo }; - updater = &logUpdater; - } Updater::UpdateOutputs allOutputs{ cache.mMajorLabels, cache.mMinorLabels, cache.mMinorMinorLabels, cache.mBits, cache.mRect }; - updater->Update(dc, envelope, allOutputs); + mpUpdater->Update(dc, envelope, allOutputs); } auto Ruler::GetFonts() const -> Fonts From 58429815aac1a37ff556b669dc96264bd9ee7acb Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 15:52:03 -0400 Subject: [PATCH 05/19] Break into multiple files, import Also detach ChooseFonts from the Updater because it is completely unrelated quick fix --- src/widgets/CustomUpdater.h | 42 +++ src/widgets/LinearUpdater.h | 178 +++++++++++ src/widgets/LogarithmicUpdater.h | 127 ++++++++ src/widgets/Ruler.cpp | 507 ++----------------------------- src/widgets/Updater.cpp | 135 ++++++++ src/widgets/Updater.h | 76 +++++ 6 files changed, 578 insertions(+), 487 deletions(-) create mode 100644 src/widgets/CustomUpdater.h create mode 100644 src/widgets/LinearUpdater.h create mode 100644 src/widgets/LogarithmicUpdater.h create mode 100644 src/widgets/Updater.cpp create mode 100644 src/widgets/Updater.h diff --git a/src/widgets/CustomUpdater.h b/src/widgets/CustomUpdater.h new file mode 100644 index 000000000000..09efa61de2cc --- /dev/null +++ b/src/widgets/CustomUpdater.h @@ -0,0 +1,42 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + CustomUpdater.h + + Dominic Mazzoni + +**********************************************************************/ + +#ifndef __AUDACITY_CUSTOM_UPDATER__ +#define __AUDACITY_CUSTOM_UPDATER__ + +#include "Ruler.h" + +struct Ruler::CustomUpdater : public Ruler::Updater { + explicit CustomUpdater(const Ruler& ruler, const ZoomInfo* z) + : Updater{ ruler, z } + {} + + void Update( + wxDC& dc, const Envelope* envelope, + UpdateOutputs& allOutputs + ) const override; +}; + +void Ruler::CustomUpdater::Update( + wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const +{ + TickOutputs majorOutputs{ + allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + + // SET PARAMETER IN MCUSTOM CASE + // Works only with major labels + + int numLabel = allOutputs.majorLabels.size(); + + for (int i = 0; (i < numLabel) && (i <= mLength); ++i) + TickCustom(dc, i, mFonts.major, majorOutputs); + + BoxAdjust(allOutputs); +} diff --git a/src/widgets/LinearUpdater.h b/src/widgets/LinearUpdater.h new file mode 100644 index 000000000000..36d3c50fb60f --- /dev/null +++ b/src/widgets/LinearUpdater.h @@ -0,0 +1,178 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + LinearUpdater.h + + Dominic Mazzoni + +**********************************************************************/ + +#ifndef __AUDACITY_LINEAR_UPDATER__ +#define __AUDACITY_LINEAR_UPDATER__ + +#include "Ruler.h" + +struct LinearUpdater : public Updater { + explicit LinearUpdater(const Ruler& ruler, const ZoomInfo* z) + : Updater{ ruler, z } + {} + + void Update( + wxDC& dc, const Envelope* envelope, + UpdateOutputs& allOutputs + ) const override; +}; + + +void Ruler::LinearUpdater::Update( + wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const +{ + TickOutputs majorOutputs{ + allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + + // Use the "hidden" min and max to determine the tick size. + // That may make a difference with fisheye. + // Otherwise you may see the tick size for the whole ruler change + // when the fisheye approaches start or end. + double UPP = (mHiddenMax - mHiddenMin) / mLength; // Units per pixel + TickSizes tickSizes{ UPP, mOrientation, mFormat, false }; + + auto TickAtValue = + [this, &tickSizes, &dc, &majorOutputs] + (double value) -> int { + // Make a tick only if the value is strictly between the bounds + if (value <= std::min(mMin, mMax)) + return -1; + if (value >= std::max(mMin, mMax)) + return -1; + + int mid; + if (zoomInfo != NULL) { + // Tick only at zero + if (value) + return -1; + mid = (int)(zoomInfo->TimeToPosition(0.0, mLeftOffset)); + } + else + mid = (int)(mLength * ((mMin - value) / (mMin - mMax)) + 0.5); + + const int iMaxPos = (mOrientation == wxHORIZONTAL) ? mRight : mBottom - 5; + if (mid >= 0 && mid < iMaxPos) + Tick(dc, mid, value, tickSizes, mFonts.major, majorOutputs); + else + return -1; + + return mid; + }; + + if (mDbMirrorValue) { + // For dB scale, let the zeroes prevail over the extreme values if + // not the same, and let midline prevail over all + + // Do the midline + TickAtValue(-mDbMirrorValue); + + // Do the upper zero + TickAtValue(0.0); + + // Do the other zero + TickAtValue(-2 * mDbMirrorValue); + } + + // Extreme values + if (mLabelEdges) { + Tick(dc, 0, mMin, tickSizes, mFonts.major, majorOutputs); + Tick(dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs); + } + + if (!mDbMirrorValue) { + // Zero (if it's strictly in the middle somewhere) + TickAtValue(0.0); + } + + double sign = UPP > 0.0 ? 1.0 : -1.0; + + int nDroppedMinorLabels = 0; + // Major and minor ticks + for (int jj = 0; jj < 2; ++jj) { + const double denom = jj == 0 ? tickSizes.mMajor : tickSizes.mMinor; + auto font = jj == 0 ? mFonts.major : mFonts.minor; + TickOutputs outputs{ + (jj == 0 ? allOutputs.majorLabels : allOutputs.minorLabels), + allOutputs.bits, allOutputs.box + }; + int ii = -1, j = 0; + double d, warpedD, nextD; + + double prevTime = 0.0, time = 0.0; + if (zoomInfo != NULL) { + j = zoomInfo->TimeToPosition(mMin); + prevTime = zoomInfo->PositionToTime(--j); + time = zoomInfo->PositionToTime(++j); + d = (prevTime + time) / 2.0; + } + else + d = mMin - UPP / 2; + if (envelope) + warpedD = ComputeWarpedLength(*envelope, 0.0, d); + else + warpedD = d; + // using ints doesn't work, as + // this will overflow and be negative at high zoom. + double step = floor(sign * warpedD / denom); + while (ii <= mLength) { + ii++; + if (zoomInfo) + { + prevTime = time; + time = zoomInfo->PositionToTime(++j); + nextD = (prevTime + time) / 2.0; + // wxASSERT(time >= prevTime); + } + else + nextD = d + UPP; + if (envelope) + warpedD += ComputeWarpedLength(*envelope, d, nextD); + else + warpedD = nextD; + d = nextD; + + if (floor(sign * warpedD / denom) > step) { + step = floor(sign * warpedD / denom); + bool major = jj == 0; + tickSizes.useMajor = major; + bool ticked = Tick(dc, ii, sign * step * denom, tickSizes, + font, outputs); + if (!major && !ticked) { + nDroppedMinorLabels++; + } + } + } + } + + tickSizes.useMajor = true; + + // If we've dropped minor labels through overcrowding, then don't show + // any of them. We're allowed though to drop ones which correspond to the + // major numbers. + if (nDroppedMinorLabels > + (allOutputs.majorLabels.size() + (mLabelEdges ? 2 : 0))) { + // Old code dropped the labels AND their ticks, like so: + // mMinorLabels.clear(); + // Nowadays we just drop the labels. + for (auto& label : allOutputs.minorLabels) + label.text = {}; + } + + // Left and Right Edges + if (mLabelEdges) { + Tick(dc, 0, mMin, tickSizes, mFonts.major, majorOutputs); + Tick(dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs); + } + + BoxAdjust(allOutputs); +} + +#endif + diff --git a/src/widgets/LogarithmicUpdater.h b/src/widgets/LogarithmicUpdater.h new file mode 100644 index 000000000000..36d1344f847d --- /dev/null +++ b/src/widgets/LogarithmicUpdater.h @@ -0,0 +1,127 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + LogarithmicUpdater.h + + Dominic Mazzoni + +**********************************************************************/ + +#ifndef __AUDACITY_LOGARITHMIC_UPDATER__ +#define __AUDACITY_LOGARITHMIC_UPDATER__ + +#include "Ruler.h" + +struct LogarithmicUpdater : public Updater { + explicit LogarithmicUpdater(const Ruler& ruler, const ZoomInfo* z) + : Updater{ ruler, z } + {} + + void Update( + wxDC& dc, const Envelope* envelope, + UpdateOutputs& allOutputs + ) const override; +}; + + + +void Ruler::LogarithmicUpdater::Update( + wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const +{ + TickOutputs majorOutputs{ + allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + + auto numberScale = (mNumberScale == NumberScale{}) + ? NumberScale(nstLogarithmic, mMin, mMax) + : mNumberScale; + + double UPP = (mHiddenMax - mHiddenMin) / mLength; // Units per pixel + TickSizes tickSizes{ UPP, mOrientation, mFormat, true }; + + tickSizes.mDigits = 2; //TODO: implement dynamic digit computation + + double loLog = log10(mMin); + double hiLog = log10(mMax); + int loDecade = (int)floor(loLog); + + double val; + double startDecade = pow(10., (double)loDecade); + + // Major ticks are the decades + double decade = startDecade; + double delta = hiLog - loLog, steps = fabs(delta); + double step = delta >= 0 ? 10 : 0.1; + double rMin = std::min(mMin, mMax), rMax = std::max(mMin, mMax); + for (int i = 0; i <= steps; i++) + { // if(i!=0) + { val = decade; + if (val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); + Tick(dc, pos, val, tickSizes, mFonts.major, majorOutputs); + } + } + decade *= step; + } + + // Minor ticks are multiples of decades + decade = startDecade; + float start, end, mstep; + if (delta > 0) + { + start = 2; end = 10; mstep = 1; + } + else + { + start = 9; end = 1; mstep = -1; + } + steps++; + tickSizes.useMajor = false; + TickOutputs minorOutputs{ + allOutputs.minorLabels, allOutputs.bits, allOutputs.box }; + for (int i = 0; i <= steps; i++) { + for (int j = start; j != end; j += mstep) { + val = decade * j; + if (val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); + Tick(dc, pos, val, tickSizes, mFonts.minor, minorOutputs); + } + } + decade *= step; + } + + // MinorMinor ticks are multiples of decades + decade = startDecade; + if (delta > 0) + { + start = 10; end = 100; mstep = 1; + } + else + { + start = 100; end = 10; mstep = -1; + } + steps++; + TickOutputs minorMinorOutputs{ + allOutputs.minorMinorLabels, allOutputs.bits, allOutputs.box }; + for (int i = 0; i <= steps; i++) { + // PRL: Bug1038. Don't label 1.6, rounded, as a duplicate tick for "2" + if (!(mFormat == IntFormat && decade < 10.0)) { + for (int f = start; f != (int)(end); f += mstep) { + if ((int)(f / 10) != f / 10.0f) { + val = decade * f / 10; + if (val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); + Tick(dc, pos, val, tickSizes, + mFonts.minorMinor, minorMinorOutputs); + } + } + } + } + decade *= step; + } + + BoxAdjust(allOutputs); +} + + +#endif diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 1c507f45898e..d1b84995b7b8 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -67,6 +67,8 @@ array of Ruler::Label. #include "Theme.h" #include "ViewInfo.h" +#include "Updater.h" + using std::min; using std::max; @@ -118,7 +120,9 @@ Ruler::Ruler() mUseZoomInfo = NULL; // Default the updater to Linear, as it would be before removal of mLog - mpUpdater = std::make_unique( *this, mUseZoomInfo ); + // struct LinearUpdater; + // mpUpdater = std::make_unique( *this, mUseZoomInfo ); + mpUpdater = NULL; } Ruler::~Ruler() @@ -857,179 +861,12 @@ auto Ruler::MakeTick( return { { strLeft, strTop, strW, strH }, lab }; } -struct Ruler::Updater { - const Ruler &mRuler; - const ZoomInfo *zoomInfo; - - explicit Updater( const Ruler &ruler, const ZoomInfo *z ) - : mRuler{ ruler } - , zoomInfo{ z } - {} - - const double mDbMirrorValue = mRuler.mDbMirrorValue; - const int mLength = mRuler.mLength; - const RulerFormat mFormat = mRuler.mFormat; - const TranslatableString mUnits = mRuler.mUnits; - - const int mLeft = mRuler.mLeft; - const int mTop = mRuler.mTop; - const int mBottom = mRuler.mBottom; - const int mRight = mRuler.mRight; - - const int mSpacing = mRuler.mSpacing; - const int mOrientation = mRuler.mOrientation; - const bool mFlip = mRuler.mFlip; - - const bool mCustom = mRuler.mCustom; - const Fonts &mFonts = *mRuler.mpFonts; - const bool mLog = mRuler.mLog; - const double mHiddenMin = mRuler.mHiddenMin; - const double mHiddenMax = mRuler.mHiddenMax; - const bool mLabelEdges = mRuler.mLabelEdges; - const double mMin = mRuler.mMin; - const double mMax = mRuler.mMax; - const int mLeftOffset = mRuler.mLeftOffset; - const NumberScale mNumberScale = mRuler.mNumberScale; - - struct TickOutputs; - - bool Tick( wxDC &dc, - int pos, double d, const TickSizes &tickSizes, wxFont font, - TickOutputs outputs - ) const; - - // Another tick generator for custom ruler case (noauto) . - bool TickCustom( wxDC &dc, int labelIdx, wxFont font, - TickOutputs outputs - ) const; - - static void ChooseFonts( - std::unique_ptr &pFonts, const Fonts *pUserFonts, - wxDC &dc, int desiredPixelHeight - ); - - struct UpdateOutputs; - - void BoxAdjust( - UpdateOutputs& allOutputs - ) - const; - - virtual void Update( - wxDC &dc, const Envelope* envelope, - UpdateOutputs &allOutputs - )// Envelope *speedEnv, long minSpeed, long maxSpeed ) - const = 0; -}; - -struct Ruler::LinearUpdater : public virtual Ruler::Updater { - explicit LinearUpdater( const Ruler &ruler, const ZoomInfo *z ) - : Updater{ ruler, z } - {} - - void Update( - wxDC &dc, const Envelope* envelope, - UpdateOutputs &allOutputs - ) const override; -}; - -struct Ruler::LogarithmicUpdater : public virtual Ruler::Updater { - explicit LogarithmicUpdater( const Ruler &ruler, const ZoomInfo *z ) - : Updater{ ruler, z } - {} - - void Update( - wxDC &dc, const Envelope* envelope, - UpdateOutputs &allOutputs - ) const override; -}; - -struct Ruler::CustomUpdater : public virtual Ruler::Updater { - explicit CustomUpdater( const Ruler &ruler, const ZoomInfo *z ) - : Updater{ ruler, z } - {} - - void Update( - wxDC &dc, const Envelope* envelope, - UpdateOutputs &allOutputs - ) const override; -}; - struct Ruler::Cache { Bits mBits; Labels mMajorLabels, mMinorLabels, mMinorMinorLabels; wxRect mRect; }; -struct Ruler::Updater::TickOutputs{ Labels &labels; Bits &bits; wxRect &box; }; -struct Ruler::Updater::UpdateOutputs { - Labels &majorLabels, &minorLabels, &minorMinorLabels; - Bits &bits; - wxRect &box; -}; - -bool Ruler::Updater::Tick( wxDC &dc, - int pos, double d, const TickSizes &tickSizes, wxFont font, - // in/out: - TickOutputs outputs ) const -{ - // Bug 521. dB view for waveforms needs a 2-sided scale. - if(( mDbMirrorValue > 1.0 ) && ( -d > mDbMirrorValue )) - d = -2*mDbMirrorValue - d; - - // FIXME: We don't draw a tick if off end of our label arrays - // But we shouldn't have an array of labels. - if( outputs.labels.size() >= mLength ) - return false; - - Label lab; - lab.value = d; - lab.pos = pos; - lab.text = tickSizes.LabelString( d, mFormat, mUnits ); - - const auto result = MakeTick( - lab, - dc, font, - outputs.bits, - mLeft, mTop, mSpacing, mFonts.lead, - mFlip, - mOrientation ); - - auto &rect = result.first; - outputs.box.Union( rect ); - outputs.labels.emplace_back( result.second ); - return !rect.IsEmpty(); -} - -bool Ruler::Updater::TickCustom( wxDC &dc, int labelIdx, wxFont font, - // in/out: - TickOutputs outputs ) const -{ - // FIXME: We don't draw a tick if of end of our label arrays - // But we shouldn't have an array of labels. - if( labelIdx >= outputs.labels.size() ) - return false; - - //This should only used in the mCustom case - - Label lab; - lab.value = 0.0; - - const auto result = MakeTick( - lab, - - dc, font, - outputs.bits, - mLeft, mTop, mSpacing, mFonts.lead, - mFlip, - mOrientation ); - - auto &rect = result.first; - outputs.box.Union( rect ); - outputs.labels[labelIdx] = ( result.second ); - return !rect.IsEmpty(); -} - namespace { double ComputeWarpedLength(const Envelope &env, double t0, double t1) { @@ -1059,20 +896,23 @@ static constexpr int MaxPixelHeight = #endif -void Ruler::Updater::ChooseFonts( - std::unique_ptr &pFonts, const Fonts *pUserFonts, - wxDC &dc, int desiredPixelHeight ) +void Ruler::ChooseFonts( wxDC &dc ) const { - if ( pFonts ) + const Fonts* pUserFonts = mpUserFonts.get(); + int desiredPixelHeight = mOrientation == wxHORIZONTAL + ? mBottom - mTop - 5 // height less ticks and 1px gap + : MaxPixelHeight; + + if (mpFonts) return; - if ( pUserFonts ) { - pFonts = std::make_unique( *pUserFonts ); + if (pUserFonts) { + mpFonts = std::make_unique(*pUserFonts); return; } - pFonts = std::make_unique( Fonts{ {}, {}, {}, 0 } ); - auto &fonts = *pFonts; + mpFonts = std::make_unique(Fonts{ {}, {}, {}, 0 }); + auto& fonts = *mpFonts; int fontSize = 4; @@ -1081,325 +921,18 @@ void Ruler::Updater::ChooseFonts( // Keep making the font bigger until it's too big, then subtract one. wxCoord height; - FindFontHeights( height, fonts.lead, dc, fontSize, wxFONTWEIGHT_BOLD ); + FindFontHeights(height, fonts.lead, dc, fontSize, wxFONTWEIGHT_BOLD); while (height <= desiredPixelHeight && fontSize < 40) { fontSize++; - FindFontHeights( height, fonts.lead, dc, fontSize, wxFONTWEIGHT_BOLD ); + FindFontHeights(height, fonts.lead, dc, fontSize, wxFONTWEIGHT_BOLD); } fontSize--; - FindFontHeights( height, fonts.lead, dc, fontSize ); + FindFontHeights(height, fonts.lead, dc, fontSize); fonts.major = wxFont{ fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD }; fonts.minor = wxFont{ fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL }; fonts.minorMinor = wxFont{ fontSize - 1, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL }; -} - -void Ruler::Updater::BoxAdjust( - UpdateOutputs &allOutputs -) - const -{ - int displacementx=0, displacementy=0; - auto &box = allOutputs.box; - if (!mFlip) { - if (mOrientation==wxHORIZONTAL) { - int d = mTop + box.GetHeight() + 5; - box.Offset(0,d); - box.Inflate(0,5); - displacementx=0; - displacementy=d; - } - else { - int d = mLeft - box.GetLeft() + 5; - box.Offset(d,0); - box.Inflate(5,0); - displacementx=d; - displacementy=0; - } - } - else { - if (mOrientation==wxHORIZONTAL) { - box.Inflate(0,5); - displacementx=0; - displacementy=0; - } - } - auto update = [=]( Label &label ){ - label.lx += displacementx; - label.ly += displacementy; - }; - for( auto &label : allOutputs.majorLabels ) - update( label ); - for( auto &label : allOutputs.minorLabels ) - update( label ); - for( auto &label : allOutputs.minorMinorLabels ) - update( label ); -} - -void Ruler::CustomUpdater::Update( - wxDC &dc, const Envelope *envelope, UpdateOutputs &allOutputs ) const -{ - TickOutputs majorOutputs{ - allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; - - // SET PARAMETER IN MCUSTOM CASE - // Works only with major labels - - int numLabel = allOutputs.majorLabels.size(); - - for( int i = 0; (i int { - // Make a tick only if the value is strictly between the bounds - if ( value <= std::min( mMin, mMax ) ) - return -1; - if ( value >= std::max( mMin, mMax ) ) - return -1; - - int mid; - if (zoomInfo != NULL) { - // Tick only at zero - if ( value ) - return -1; - mid = (int)(zoomInfo->TimeToPosition(0.0, mLeftOffset)); - } - else - mid = (int)(mLength*((mMin - value) / (mMin - mMax)) + 0.5); - - const int iMaxPos = (mOrientation == wxHORIZONTAL) ? mRight : mBottom - 5; - if (mid >= 0 && mid < iMaxPos) - Tick( dc, mid, value, tickSizes, mFonts.major, majorOutputs ); - else - return -1; - - return mid; - }; - - if ( mDbMirrorValue ) { - // For dB scale, let the zeroes prevail over the extreme values if - // not the same, and let midline prevail over all - - // Do the midline - TickAtValue( -mDbMirrorValue ); - - // Do the upper zero - TickAtValue( 0.0 ); - - // Do the other zero - TickAtValue( -2 * mDbMirrorValue ); - } - - // Extreme values - if (mLabelEdges) { - Tick( dc, 0, mMin, tickSizes, mFonts.major, majorOutputs ); - Tick( dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs ); - } - - if ( !mDbMirrorValue ) { - // Zero (if it's strictly in the middle somewhere) - TickAtValue( 0.0 ); - } - - double sign = UPP > 0.0? 1.0: -1.0; - - int nDroppedMinorLabels=0; - // Major and minor ticks - for (int jj = 0; jj < 2; ++jj) { - const double denom = jj == 0 ? tickSizes.mMajor : tickSizes.mMinor; - auto font = jj == 0 ? mFonts.major : mFonts.minor; - TickOutputs outputs{ - (jj == 0 ? allOutputs.majorLabels : allOutputs.minorLabels), - allOutputs.bits, allOutputs.box - }; - int ii = -1, j = 0; - double d, warpedD, nextD; - - double prevTime = 0.0, time = 0.0; - if (zoomInfo != NULL) { - j = zoomInfo->TimeToPosition(mMin); - prevTime = zoomInfo->PositionToTime(--j); - time = zoomInfo->PositionToTime(++j); - d = (prevTime + time) / 2.0; - } - else - d = mMin - UPP / 2; - if (envelope) - warpedD = ComputeWarpedLength(*envelope, 0.0, d); - else - warpedD = d; - // using ints doesn't work, as - // this will overflow and be negative at high zoom. - double step = floor(sign * warpedD / denom); - while (ii <= mLength) { - ii++; - if (zoomInfo) - { - prevTime = time; - time = zoomInfo->PositionToTime(++j); - nextD = (prevTime + time) / 2.0; - // wxASSERT(time >= prevTime); - } - else - nextD = d + UPP; - if (envelope) - warpedD += ComputeWarpedLength(*envelope, d, nextD); - else - warpedD = nextD; - d = nextD; - - if (floor(sign * warpedD / denom) > step) { - step = floor(sign * warpedD / denom); - bool major = jj == 0; - tickSizes.useMajor = major; - bool ticked = Tick( dc, ii, sign * step * denom, tickSizes, - font, outputs ); - if( !major && !ticked ){ - nDroppedMinorLabels++; - } - } - } - } - - tickSizes.useMajor = true; - - // If we've dropped minor labels through overcrowding, then don't show - // any of them. We're allowed though to drop ones which correspond to the - // major numbers. - if( nDroppedMinorLabels > - (allOutputs.majorLabels.size() + (mLabelEdges ? 2:0)) ){ - // Old code dropped the labels AND their ticks, like so: - // mMinorLabels.clear(); - // Nowadays we just drop the labels. - for( auto &label : allOutputs.minorLabels ) - label.text = {}; - } - - // Left and Right Edges - if (mLabelEdges) { - Tick( dc, 0, mMin, tickSizes, mFonts.major, majorOutputs ); - Tick( dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs ); - } - - BoxAdjust(allOutputs); -} - -void Ruler::LogarithmicUpdater::Update( - wxDC &dc, const Envelope *envelope, UpdateOutputs &allOutputs) const -{ - TickOutputs majorOutputs{ - allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; - - auto numberScale = ( mNumberScale == NumberScale{} ) - ? NumberScale( nstLogarithmic, mMin, mMax ) - : mNumberScale; - - double UPP = (mHiddenMax-mHiddenMin)/mLength; // Units per pixel - TickSizes tickSizes{ UPP, mOrientation, mFormat, true }; - - tickSizes.mDigits = 2; //TODO: implement dynamic digit computation - - double loLog = log10(mMin); - double hiLog = log10(mMax); - int loDecade = (int) floor(loLog); - - double val; - double startDecade = pow(10., (double)loDecade); - - // Major ticks are the decades - double decade = startDecade; - double delta=hiLog-loLog, steps=fabs(delta); - double step = delta>=0 ? 10 : 0.1; - double rMin=std::min(mMin, mMax), rMax=std::max(mMin, mMax); - for(int i=0; i<=steps; i++) - { // if(i!=0) - { val = decade; - if(val >= rMin && val < rMax) { - const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); - Tick( dc, pos, val, tickSizes, mFonts.major, majorOutputs ); - } - } - decade *= step; - } - - // Minor ticks are multiples of decades - decade = startDecade; - float start, end, mstep; - if (delta > 0) - { start=2; end=10; mstep=1; - }else - { start=9; end=1; mstep=-1; - } - steps++; - tickSizes.useMajor = false; - TickOutputs minorOutputs{ - allOutputs.minorLabels, allOutputs.bits, allOutputs.box }; - for(int i=0; i<=steps; i++) { - for(int j=start; j!=end; j+=mstep) { - val = decade * j; - if(val >= rMin && val < rMax) { - const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); - Tick( dc, pos, val, tickSizes, mFonts.minor, minorOutputs ); - } - } - decade *= step; - } - - // MinorMinor ticks are multiples of decades - decade = startDecade; - if (delta > 0) - { start= 10; end=100; mstep= 1; - }else - { start=100; end= 10; mstep=-1; - } - steps++; - TickOutputs minorMinorOutputs{ - allOutputs.minorMinorLabels, allOutputs.bits, allOutputs.box }; - for (int i = 0; i <= steps; i++) { - // PRL: Bug1038. Don't label 1.6, rounded, as a duplicate tick for "2" - if (!(mFormat == IntFormat && decade < 10.0)) { - for (int f = start; f != (int)(end); f += mstep) { - if ((int)(f / 10) != f / 10.0f) { - val = decade * f / 10; - if (val >= rMin && val < rMax) { - const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); - Tick( dc, pos, val, tickSizes, - mFonts.minorMinor, minorMinorOutputs ); - } - } - } - } - decade *= step; - } - - BoxAdjust(allOutputs); -} - -void Ruler::ChooseFonts( wxDC &dc ) const -{ - Updater::ChooseFonts( mpFonts, mpUserFonts.get(), dc, - mOrientation == wxHORIZONTAL - ? mBottom - mTop - 5 // height less ticks and 1px gap - : MaxPixelHeight - ); + } void Ruler::UpdateCache( diff --git a/src/widgets/Updater.cpp b/src/widgets/Updater.cpp new file mode 100644 index 000000000000..9484c770a20a --- /dev/null +++ b/src/widgets/Updater.cpp @@ -0,0 +1,135 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + Updater.cpp + + Dominic Mazzoni + +*******************************************************************//** + +\class Updater +\brief Used to update a Ruler. + + This is a pure virtual class which sets how a ruler will generate + its values. + + It supports three subclasses: LinearUpdater, LogarithmicUpdater, + and CustomUpdater + +*//******************************************************************/ + +#include "Updater.h" +#include "Ruler.h" + +struct Ruler::Updater::TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; +struct Ruler::Updater::UpdateOutputs { + Labels& majorLabels, & minorLabels, & minorMinorLabels; + Bits& bits; + wxRect& box; +}; + + +void Ruler::Updater::BoxAdjust( + UpdateOutputs& allOutputs +) +const +{ + int displacementx = 0, displacementy = 0; + auto& box = allOutputs.box; + if (!mFlip) { + if (mOrientation == wxHORIZONTAL) { + int d = mTop + box.GetHeight() + 5; + box.Offset(0, d); + box.Inflate(0, 5); + displacementx = 0; + displacementy = d; + } + else { + int d = mLeft - box.GetLeft() + 5; + box.Offset(d, 0); + box.Inflate(5, 0); + displacementx = d; + displacementy = 0; + } + } + else { + if (mOrientation == wxHORIZONTAL) { + box.Inflate(0, 5); + displacementx = 0; + displacementy = 0; + } + } + auto update = [=](Label& label) { + label.lx += displacementx; + label.ly += displacementy; + }; + for (auto& label : allOutputs.majorLabels) + update(label); + for (auto& label : allOutputs.minorLabels) + update(label); + for (auto& label : allOutputs.minorMinorLabels) + update(label); +} + +bool Ruler::Updater::Tick(wxDC& dc, + int pos, double d, const TickSizes& tickSizes, wxFont font, + // in/out: + TickOutputs outputs) const +{ + // Bug 521. dB view for waveforms needs a 2-sided scale. + if ((mDbMirrorValue > 1.0) && (-d > mDbMirrorValue)) + d = -2 * mDbMirrorValue - d; + + // FIXME: We don't draw a tick if off end of our label arrays + // But we shouldn't have an array of labels. + if (outputs.labels.size() >= mLength) + return false; + + Label lab; + lab.value = d; + lab.pos = pos; + lab.text = tickSizes.LabelString(d, mFormat, mUnits); + + const auto result = MakeTick( + lab, + dc, font, + outputs.bits, + mLeft, mTop, mSpacing, mFonts.lead, + mFlip, + mOrientation); + + auto& rect = result.first; + outputs.box.Union(rect); + outputs.labels.emplace_back(result.second); + return !rect.IsEmpty(); +} + +bool Ruler::Updater::TickCustom(wxDC& dc, int labelIdx, wxFont font, + // in/out: + TickOutputs outputs) const +{ + // FIXME: We don't draw a tick if of end of our label arrays + // But we shouldn't have an array of labels. + if (labelIdx >= outputs.labels.size()) + return false; + + //This should only used in the mCustom case + + Label lab; + lab.value = 0.0; + + const auto result = MakeTick( + lab, + + dc, font, + outputs.bits, + mLeft, mTop, mSpacing, mFonts.lead, + mFlip, + mOrientation); + + auto& rect = result.first; + outputs.box.Union(rect); + outputs.labels[labelIdx] = (result.second); + return !rect.IsEmpty(); +} diff --git a/src/widgets/Updater.h b/src/widgets/Updater.h new file mode 100644 index 000000000000..6d86c5aa4d55 --- /dev/null +++ b/src/widgets/Updater.h @@ -0,0 +1,76 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + Updater.h + + Dominic Mazzoni + +**********************************************************************/ + +#ifndef __AUDACITY_UPDATER__ +#define __AUDACITY_UPDATER__ + +#include "Ruler.h" + +struct AUDACITY_DLL_API Ruler::Updater { + const Ruler& mRuler; + const ZoomInfo* zoomInfo; + + explicit Updater(const Ruler& ruler, const ZoomInfo* z) + : mRuler{ ruler } + , zoomInfo{ z } + {} + + const double mDbMirrorValue = mRuler.mDbMirrorValue; + const int mLength = mRuler.mLength; + const RulerFormat mFormat = mRuler.mFormat; + const TranslatableString mUnits = mRuler.mUnits; + + const int mLeft = mRuler.mLeft; + const int mTop = mRuler.mTop; + const int mBottom = mRuler.mBottom; + const int mRight = mRuler.mRight; + + const int mSpacing = mRuler.mSpacing; + const int mOrientation = mRuler.mOrientation; + const bool mFlip = mRuler.mFlip; + + const bool mCustom = mRuler.mCustom; + const Fonts& mFonts = *mRuler.mpFonts; + const bool mLog = mRuler.mLog; + const double mHiddenMin = mRuler.mHiddenMin; + const double mHiddenMax = mRuler.mHiddenMax; + const bool mLabelEdges = mRuler.mLabelEdges; + const double mMin = mRuler.mMin; + const double mMax = mRuler.mMax; + const int mLeftOffset = mRuler.mLeftOffset; + const NumberScale mNumberScale = mRuler.mNumberScale; + + struct TickOutputs; + + bool Tick(wxDC& dc, + int pos, double d, const TickSizes& tickSizes, wxFont font, + TickOutputs outputs + ) const; + + // Another tick generator for custom ruler case (noauto) . + bool TickCustom(wxDC& dc, int labelIdx, wxFont font, + TickOutputs outputs + ) const; + + struct UpdateOutputs; + + void BoxAdjust( + UpdateOutputs& allOutputs + ) + const; + + virtual void Update( + wxDC& dc, const Envelope* envelope, + UpdateOutputs& allOutputs + )// Envelope *speedEnv, long minSpeed, long maxSpeed ) + const = 0; +}; + +#endif //define __AUDACITY_UPDATER__ From 56c236012c44b47ddc4b9edddaecbf55cb7620a6 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 16:18:07 -0400 Subject: [PATCH 06/19] Simplify Updater Clean up ZoomInfo related code, and pull TickOutput and UpdateOutput out of Updater to be alongside TickSizes since they were separate but all serve similar purpose. If migrating them all back into Updater is a good idea, I will do so later --- src/widgets/CustomUpdater.h | 2 +- src/widgets/LogarithmicUpdater.h | 2 +- src/widgets/Ruler.cpp | 14 +++++++++----- src/widgets/Ruler.h | 2 ++ src/widgets/Updater.cpp | 10 +++------- src/widgets/Updater.h | 4 ---- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/widgets/CustomUpdater.h b/src/widgets/CustomUpdater.h index 09efa61de2cc..81199e697e9c 100644 --- a/src/widgets/CustomUpdater.h +++ b/src/widgets/CustomUpdater.h @@ -15,7 +15,7 @@ struct Ruler::CustomUpdater : public Ruler::Updater { explicit CustomUpdater(const Ruler& ruler, const ZoomInfo* z) - : Updater{ ruler, z } + : Updater{ ruler, NULL } {} void Update( diff --git a/src/widgets/LogarithmicUpdater.h b/src/widgets/LogarithmicUpdater.h index 36d1344f847d..b86deccb111a 100644 --- a/src/widgets/LogarithmicUpdater.h +++ b/src/widgets/LogarithmicUpdater.h @@ -15,7 +15,7 @@ struct LogarithmicUpdater : public Updater { explicit LogarithmicUpdater(const Ruler& ruler, const ZoomInfo* z) - : Updater{ ruler, z } + : Updater{ ruler, NULL } {} void Update( diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index d1b84995b7b8..7a253c4d498d 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -369,6 +369,14 @@ void Ruler::Invalidate() // mUserBits.clear(); } + +struct Ruler::TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; +struct Ruler::UpdateOutputs { + Labels& majorLabels, & minorLabels, & minorMinorLabels; + Bits& bits; + wxRect& box; +}; + struct Ruler::TickSizes { bool useMajor = true; @@ -942,10 +950,6 @@ void Ruler::UpdateCache( if ( mpCache ) return; - const ZoomInfo *zoomInfo = NULL; - if (!mLog && mOrientation == wxHORIZONTAL) - zoomInfo = mUseZoomInfo; - // This gets called when something has been changed // (i.e. we've been invalidated). Recompute all // tick positions and font size. @@ -979,7 +983,7 @@ void Ruler::UpdateCache( cache.mBits = mUserBits; cache.mBits.resize( static_cast(mLength + 1), false ); - Updater::UpdateOutputs allOutputs{ + UpdateOutputs allOutputs{ cache.mMajorLabels, cache.mMinorLabels, cache.mMinorMinorLabels, cache.mBits, cache.mRect }; diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index 11e0820c9d06..849cb60f1fe2 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -163,6 +163,8 @@ class AUDACITY_DLL_API Ruler { void Invalidate(); private: + struct TickOutputs; + struct UpdateOutputs; struct TickSizes; class Label { diff --git a/src/widgets/Updater.cpp b/src/widgets/Updater.cpp index 9484c770a20a..07c84647c9fc 100644 --- a/src/widgets/Updater.cpp +++ b/src/widgets/Updater.cpp @@ -22,13 +22,9 @@ #include "Updater.h" #include "Ruler.h" -struct Ruler::Updater::TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; -struct Ruler::Updater::UpdateOutputs { - Labels& majorLabels, & minorLabels, & minorMinorLabels; - Bits& bits; - wxRect& box; -}; - +struct TickOutputs; +struct UpdateOutputs; +struct TickSizes; void Ruler::Updater::BoxAdjust( UpdateOutputs& allOutputs diff --git a/src/widgets/Updater.h b/src/widgets/Updater.h index 6d86c5aa4d55..6b437abf1a5e 100644 --- a/src/widgets/Updater.h +++ b/src/widgets/Updater.h @@ -47,8 +47,6 @@ struct AUDACITY_DLL_API Ruler::Updater { const int mLeftOffset = mRuler.mLeftOffset; const NumberScale mNumberScale = mRuler.mNumberScale; - struct TickOutputs; - bool Tick(wxDC& dc, int pos, double d, const TickSizes& tickSizes, wxFont font, TickOutputs outputs @@ -59,8 +57,6 @@ struct AUDACITY_DLL_API Ruler::Updater { TickOutputs outputs ) const; - struct UpdateOutputs; - void BoxAdjust( UpdateOutputs& allOutputs ) From 897659e8ec05763c39136e009db1d7104e81840b Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 16:38:31 -0400 Subject: [PATCH 07/19] Add some includes --- src/widgets/CustomUpdater.h | 1 + src/widgets/LinearUpdater.h | 3 ++- src/widgets/LogarithmicUpdater.h | 3 ++- src/widgets/Updater.h | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/widgets/CustomUpdater.h b/src/widgets/CustomUpdater.h index 81199e697e9c..8c3eb80d90df 100644 --- a/src/widgets/CustomUpdater.h +++ b/src/widgets/CustomUpdater.h @@ -12,6 +12,7 @@ #define __AUDACITY_CUSTOM_UPDATER__ #include "Ruler.h" +#include "Updater.h" struct Ruler::CustomUpdater : public Ruler::Updater { explicit CustomUpdater(const Ruler& ruler, const ZoomInfo* z) diff --git a/src/widgets/LinearUpdater.h b/src/widgets/LinearUpdater.h index 36d3c50fb60f..efae426ac617 100644 --- a/src/widgets/LinearUpdater.h +++ b/src/widgets/LinearUpdater.h @@ -12,8 +12,9 @@ #define __AUDACITY_LINEAR_UPDATER__ #include "Ruler.h" +#include "Updater.h" -struct LinearUpdater : public Updater { +struct Ruler::LinearUpdater : public Ruler::Updater { explicit LinearUpdater(const Ruler& ruler, const ZoomInfo* z) : Updater{ ruler, z } {} diff --git a/src/widgets/LogarithmicUpdater.h b/src/widgets/LogarithmicUpdater.h index b86deccb111a..405c3dfb5b45 100644 --- a/src/widgets/LogarithmicUpdater.h +++ b/src/widgets/LogarithmicUpdater.h @@ -12,8 +12,9 @@ #define __AUDACITY_LOGARITHMIC_UPDATER__ #include "Ruler.h" +#include "Updater.h" -struct LogarithmicUpdater : public Updater { +struct Ruler::LogarithmicUpdater : public Ruler::Updater { explicit LogarithmicUpdater(const Ruler& ruler, const ZoomInfo* z) : Updater{ ruler, NULL } {} diff --git a/src/widgets/Updater.h b/src/widgets/Updater.h index 6b437abf1a5e..911c87eca5b2 100644 --- a/src/widgets/Updater.h +++ b/src/widgets/Updater.h @@ -13,7 +13,7 @@ #include "Ruler.h" -struct AUDACITY_DLL_API Ruler::Updater { +struct Ruler::Updater { const Ruler& mRuler; const ZoomInfo* zoomInfo; From 0d8a4d58c85fe3bf5016e7033f27702d349ed7f8 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 16:52:03 -0400 Subject: [PATCH 08/19] Merge SetUseZoomInfo into SetUpdater Necessary to add SetUpdater to all rulers --- src/widgets/Ruler.cpp | 17 +++++++++++++++++ src/widgets/Ruler.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 7a253c4d498d..0abfd09f27a4 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -154,6 +154,23 @@ void Ruler::SetUpdater(std::unique_ptr pUpdater) Invalidate(); } +void Ruler::SetUpdater + (std::unique_ptr pUpdater, int leftOffset, const ZoomInfo* zoomInfo) +{ + // Should a comparison be made between mpUpdater and pUpdater? + // Runtime type comparison isn't clean in c++ + mpUpdater = std::move(pUpdater); + + if (mLeftOffset != leftOffset) + mLeftOffset = leftOffset; + + // Hm, is this invalidation sufficient? What if *zoomInfo changes under us? + if (mUseZoomInfo != zoomInfo) + mUseZoomInfo = zoomInfo; + + Invalidate(); +} + void Ruler::SetLog(bool log) { // Logarithmic diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index 849cb60f1fe2..e7125be85ad9 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -73,6 +73,9 @@ class AUDACITY_DLL_API Ruler { // (Linear, Logarithmic, Custom, etc.) void SetUpdater(std::unique_ptr pUpdater); + // An overload to replace SetUseZoomInfo + void SetUpdater(std::unique_ptr pUpdater, int leftOffset, const ZoomInfo* zoomInfo); + // // Optional Ruler Parameters // From 0e222efa20835325f1b7ed004415decba839764c Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 20:05:49 -0400 Subject: [PATCH 09/19] Reformatting and changing Lots of changes now that Visual Studio functions correctly. Primarily turns Updater from a inner class to a friend class. --- src/AdornedRulerPanel.cpp | 2 + src/widgets/CustomUpdater.cpp | 29 ++ src/widgets/CustomUpdater.h | 20 +- src/widgets/LinearUpdater.cpp | 163 +++++++++++ src/widgets/LinearUpdater.h | 154 +---------- src/widgets/LogarithmicUpdater.cpp | 111 ++++++++ src/widgets/LogarithmicUpdater.h | 104 +------ src/widgets/Ruler.cpp | 411 +--------------------------- src/widgets/Ruler.h | 15 +- src/widgets/Updater.cpp | 418 ++++++++++++++++++++++++++++- src/widgets/Updater.h | 26 +- 11 files changed, 750 insertions(+), 703 deletions(-) create mode 100644 src/widgets/CustomUpdater.cpp create mode 100644 src/widgets/LinearUpdater.cpp create mode 100644 src/widgets/LogarithmicUpdater.cpp diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 5d16b098c35f..b14de330984e 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -55,6 +55,8 @@ #include "widgets/AButton.h" #include "widgets/AudacityMessageBox.h" #include "widgets/Grabber.h" +#include "widgets/LinearUpdater.h" +#include "widgets/LogarithmicUpdater.h" #include "widgets/wxWidgetsWindowPlacement.h" #include diff --git a/src/widgets/CustomUpdater.cpp b/src/widgets/CustomUpdater.cpp new file mode 100644 index 000000000000..2403c16569aa --- /dev/null +++ b/src/widgets/CustomUpdater.cpp @@ -0,0 +1,29 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + CustomUpdater.cpp + + Dominic Mazzoni + +**********************************************************************/ + + +#include "CustomUpdater.h" + +void CustomUpdater::Update( + wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const +{ + TickOutputs majorOutputs{ + allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + + // SET PARAMETER IN MCUSTOM CASE + // Works only with major labels + + int numLabel = allOutputs.majorLabels.size(); + + for (int i = 0; (i < numLabel) && (i <= mLength); ++i) + TickCustom(dc, i, mFonts.major, majorOutputs); + + BoxAdjust(allOutputs); +} diff --git a/src/widgets/CustomUpdater.h b/src/widgets/CustomUpdater.h index 8c3eb80d90df..760f6f728e42 100644 --- a/src/widgets/CustomUpdater.h +++ b/src/widgets/CustomUpdater.h @@ -11,10 +11,9 @@ #ifndef __AUDACITY_CUSTOM_UPDATER__ #define __AUDACITY_CUSTOM_UPDATER__ -#include "Ruler.h" #include "Updater.h" -struct Ruler::CustomUpdater : public Ruler::Updater { +struct CustomUpdater : public Updater { explicit CustomUpdater(const Ruler& ruler, const ZoomInfo* z) : Updater{ ruler, NULL } {} @@ -25,19 +24,4 @@ struct Ruler::CustomUpdater : public Ruler::Updater { ) const override; }; -void Ruler::CustomUpdater::Update( - wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const -{ - TickOutputs majorOutputs{ - allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; - - // SET PARAMETER IN MCUSTOM CASE - // Works only with major labels - - int numLabel = allOutputs.majorLabels.size(); - - for (int i = 0; (i < numLabel) && (i <= mLength); ++i) - TickCustom(dc, i, mFonts.major, majorOutputs); - - BoxAdjust(allOutputs); -} +#endif diff --git a/src/widgets/LinearUpdater.cpp b/src/widgets/LinearUpdater.cpp new file mode 100644 index 000000000000..27842082588c --- /dev/null +++ b/src/widgets/LinearUpdater.cpp @@ -0,0 +1,163 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + LinearUpdater.cpp + + Dominic Mazzoni + +**********************************************************************/ + +#include "LinearUpdater.h" + +void LinearUpdater::Update( + wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const +{ + TickOutputs majorOutputs{ + allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + + // Use the "hidden" min and max to determine the tick size. + // That may make a difference with fisheye. + // Otherwise you may see the tick size for the whole ruler change + // when the fisheye approaches start or end. + double UPP = (mHiddenMax - mHiddenMin) / mLength; // Units per pixel + TickSizes tickSizes{ UPP, mOrientation, mFormat, false }; + + auto TickAtValue = + [this, &tickSizes, &dc, &majorOutputs] + (double value) -> int { + // Make a tick only if the value is strictly between the bounds + if (value <= std::min(mMin, mMax)) + return -1; + if (value >= std::max(mMin, mMax)) + return -1; + + int mid; + if (zoomInfo != NULL) { + // Tick only at zero + if (value) + return -1; + mid = (int)(zoomInfo->TimeToPosition(0.0, mLeftOffset)); + } + else + mid = (int)(mLength * ((mMin - value) / (mMin - mMax)) + 0.5); + + const int iMaxPos = (mOrientation == wxHORIZONTAL) ? mRight : mBottom - 5; + if (mid >= 0 && mid < iMaxPos) + Tick(dc, mid, value, tickSizes, mFonts.major, majorOutputs); + else + return -1; + + return mid; + }; + + if (mDbMirrorValue) { + // For dB scale, let the zeroes prevail over the extreme values if + // not the same, and let midline prevail over all + + // Do the midline + TickAtValue(-mDbMirrorValue); + + // Do the upper zero + TickAtValue(0.0); + + // Do the other zero + TickAtValue(-2 * mDbMirrorValue); + } + + // Extreme values + if (mLabelEdges) { + Tick(dc, 0, mMin, tickSizes, mFonts.major, majorOutputs); + Tick(dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs); + } + + if (!mDbMirrorValue) { + // Zero (if it's strictly in the middle somewhere) + TickAtValue(0.0); + } + + double sign = UPP > 0.0 ? 1.0 : -1.0; + + int nDroppedMinorLabels = 0; + // Major and minor ticks + for (int jj = 0; jj < 2; ++jj) { + const double denom = jj == 0 ? tickSizes.mMajor : tickSizes.mMinor; + auto font = jj == 0 ? mFonts.major : mFonts.minor; + TickOutputs outputs{ + (jj == 0 ? allOutputs.majorLabels : allOutputs.minorLabels), + allOutputs.bits, allOutputs.box + }; + int ii = -1, j = 0; + double d, warpedD, nextD; + + double prevTime = 0.0, time = 0.0; + if (zoomInfo != NULL) { + j = zoomInfo->TimeToPosition(mMin); + prevTime = zoomInfo->PositionToTime(--j); + time = zoomInfo->PositionToTime(++j); + d = (prevTime + time) / 2.0; + } + else + d = mMin - UPP / 2; + if (envelope) + warpedD = ComputeWarpedLength(*envelope, 0.0, d); + else + warpedD = d; + // using ints doesn't work, as + // this will overflow and be negative at high zoom. + double step = floor(sign * warpedD / denom); + while (ii <= mLength) { + ii++; + if (zoomInfo) + { + prevTime = time; + time = zoomInfo->PositionToTime(++j); + nextD = (prevTime + time) / 2.0; + // wxASSERT(time >= prevTime); + } + else + nextD = d + UPP; + if (envelope) + warpedD += ComputeWarpedLength(*envelope, d, nextD); + else + warpedD = nextD; + d = nextD; + + if (floor(sign * warpedD / denom) > step) { + step = floor(sign * warpedD / denom); + bool major = jj == 0; + tickSizes.useMajor = major; + bool ticked = Tick(dc, ii, sign * step * denom, tickSizes, + font, outputs); + if (!major && !ticked) { + nDroppedMinorLabels++; + } + } + } + } + + tickSizes.useMajor = true; + + // If we've dropped minor labels through overcrowding, then don't show + // any of them. We're allowed though to drop ones which correspond to the + // major numbers. + if (nDroppedMinorLabels > + (allOutputs.majorLabels.size() + (mLabelEdges ? 2 : 0))) { + // Old code dropped the labels AND their ticks, like so: + // mMinorLabels.clear(); + // Nowadays we just drop the labels. + for (auto& label : allOutputs.minorLabels) + label.text = {}; + } + + // Left and Right Edges + if (mLabelEdges) { + Tick(dc, 0, mMin, tickSizes, mFonts.major, majorOutputs); + Tick(dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs); + } + + BoxAdjust(allOutputs); +} + +#endif + diff --git a/src/widgets/LinearUpdater.h b/src/widgets/LinearUpdater.h index efae426ac617..e35a49a6e7e5 100644 --- a/src/widgets/LinearUpdater.h +++ b/src/widgets/LinearUpdater.h @@ -11,10 +11,9 @@ #ifndef __AUDACITY_LINEAR_UPDATER__ #define __AUDACITY_LINEAR_UPDATER__ -#include "Ruler.h" #include "Updater.h" -struct Ruler::LinearUpdater : public Ruler::Updater { +struct LinearUpdater : public Updater { explicit LinearUpdater(const Ruler& ruler, const ZoomInfo* z) : Updater{ ruler, z } {} @@ -25,155 +24,4 @@ struct Ruler::LinearUpdater : public Ruler::Updater { ) const override; }; - -void Ruler::LinearUpdater::Update( - wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const -{ - TickOutputs majorOutputs{ - allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; - - // Use the "hidden" min and max to determine the tick size. - // That may make a difference with fisheye. - // Otherwise you may see the tick size for the whole ruler change - // when the fisheye approaches start or end. - double UPP = (mHiddenMax - mHiddenMin) / mLength; // Units per pixel - TickSizes tickSizes{ UPP, mOrientation, mFormat, false }; - - auto TickAtValue = - [this, &tickSizes, &dc, &majorOutputs] - (double value) -> int { - // Make a tick only if the value is strictly between the bounds - if (value <= std::min(mMin, mMax)) - return -1; - if (value >= std::max(mMin, mMax)) - return -1; - - int mid; - if (zoomInfo != NULL) { - // Tick only at zero - if (value) - return -1; - mid = (int)(zoomInfo->TimeToPosition(0.0, mLeftOffset)); - } - else - mid = (int)(mLength * ((mMin - value) / (mMin - mMax)) + 0.5); - - const int iMaxPos = (mOrientation == wxHORIZONTAL) ? mRight : mBottom - 5; - if (mid >= 0 && mid < iMaxPos) - Tick(dc, mid, value, tickSizes, mFonts.major, majorOutputs); - else - return -1; - - return mid; - }; - - if (mDbMirrorValue) { - // For dB scale, let the zeroes prevail over the extreme values if - // not the same, and let midline prevail over all - - // Do the midline - TickAtValue(-mDbMirrorValue); - - // Do the upper zero - TickAtValue(0.0); - - // Do the other zero - TickAtValue(-2 * mDbMirrorValue); - } - - // Extreme values - if (mLabelEdges) { - Tick(dc, 0, mMin, tickSizes, mFonts.major, majorOutputs); - Tick(dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs); - } - - if (!mDbMirrorValue) { - // Zero (if it's strictly in the middle somewhere) - TickAtValue(0.0); - } - - double sign = UPP > 0.0 ? 1.0 : -1.0; - - int nDroppedMinorLabels = 0; - // Major and minor ticks - for (int jj = 0; jj < 2; ++jj) { - const double denom = jj == 0 ? tickSizes.mMajor : tickSizes.mMinor; - auto font = jj == 0 ? mFonts.major : mFonts.minor; - TickOutputs outputs{ - (jj == 0 ? allOutputs.majorLabels : allOutputs.minorLabels), - allOutputs.bits, allOutputs.box - }; - int ii = -1, j = 0; - double d, warpedD, nextD; - - double prevTime = 0.0, time = 0.0; - if (zoomInfo != NULL) { - j = zoomInfo->TimeToPosition(mMin); - prevTime = zoomInfo->PositionToTime(--j); - time = zoomInfo->PositionToTime(++j); - d = (prevTime + time) / 2.0; - } - else - d = mMin - UPP / 2; - if (envelope) - warpedD = ComputeWarpedLength(*envelope, 0.0, d); - else - warpedD = d; - // using ints doesn't work, as - // this will overflow and be negative at high zoom. - double step = floor(sign * warpedD / denom); - while (ii <= mLength) { - ii++; - if (zoomInfo) - { - prevTime = time; - time = zoomInfo->PositionToTime(++j); - nextD = (prevTime + time) / 2.0; - // wxASSERT(time >= prevTime); - } - else - nextD = d + UPP; - if (envelope) - warpedD += ComputeWarpedLength(*envelope, d, nextD); - else - warpedD = nextD; - d = nextD; - - if (floor(sign * warpedD / denom) > step) { - step = floor(sign * warpedD / denom); - bool major = jj == 0; - tickSizes.useMajor = major; - bool ticked = Tick(dc, ii, sign * step * denom, tickSizes, - font, outputs); - if (!major && !ticked) { - nDroppedMinorLabels++; - } - } - } - } - - tickSizes.useMajor = true; - - // If we've dropped minor labels through overcrowding, then don't show - // any of them. We're allowed though to drop ones which correspond to the - // major numbers. - if (nDroppedMinorLabels > - (allOutputs.majorLabels.size() + (mLabelEdges ? 2 : 0))) { - // Old code dropped the labels AND their ticks, like so: - // mMinorLabels.clear(); - // Nowadays we just drop the labels. - for (auto& label : allOutputs.minorLabels) - label.text = {}; - } - - // Left and Right Edges - if (mLabelEdges) { - Tick(dc, 0, mMin, tickSizes, mFonts.major, majorOutputs); - Tick(dc, mLength, mMax, tickSizes, mFonts.major, majorOutputs); - } - - BoxAdjust(allOutputs); -} - #endif - diff --git a/src/widgets/LogarithmicUpdater.cpp b/src/widgets/LogarithmicUpdater.cpp new file mode 100644 index 000000000000..f3778f576dbd --- /dev/null +++ b/src/widgets/LogarithmicUpdater.cpp @@ -0,0 +1,111 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + LogarithmicUpdater.cpp + + Dominic Mazzoni + +**********************************************************************/ + +#include "LogarithmicUpdater.h" + +void LogarithmicUpdater::Update( + wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const +{ + TickOutputs majorOutputs{ + allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + + auto numberScale = (mNumberScale == NumberScale{}) + ? NumberScale(nstLogarithmic, mMin, mMax) + : mNumberScale; + + double UPP = (mHiddenMax - mHiddenMin) / mLength; // Units per pixel + TickSizes tickSizes{ UPP, mOrientation, mFormat, true }; + + tickSizes.mDigits = 2; //TODO: implement dynamic digit computation + + double loLog = log10(mMin); + double hiLog = log10(mMax); + int loDecade = (int)floor(loLog); + + double val; + double startDecade = pow(10., (double)loDecade); + + // Major ticks are the decades + double decade = startDecade; + double delta = hiLog - loLog, steps = fabs(delta); + double step = delta >= 0 ? 10 : 0.1; + double rMin = std::min(mMin, mMax), rMax = std::max(mMin, mMax); + for (int i = 0; i <= steps; i++) + { // if(i!=0) + { val = decade; + if (val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); + Tick(dc, pos, val, tickSizes, mFonts.major, majorOutputs); + } + } + decade *= step; + } + + // Minor ticks are multiples of decades + decade = startDecade; + float start, end, mstep; + if (delta > 0) + { + start = 2; end = 10; mstep = 1; + } + else + { + start = 9; end = 1; mstep = -1; + } + steps++; + tickSizes.useMajor = false; + TickOutputs minorOutputs{ + allOutputs.minorLabels, allOutputs.bits, allOutputs.box }; + for (int i = 0; i <= steps; i++) { + for (int j = start; j != end; j += mstep) { + val = decade * j; + if (val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); + Tick(dc, pos, val, tickSizes, mFonts.minor, minorOutputs); + } + } + decade *= step; + } + + // MinorMinor ticks are multiples of decades + decade = startDecade; + if (delta > 0) + { + start = 10; end = 100; mstep = 1; + } + else + { + start = 100; end = 10; mstep = -1; + } + steps++; + TickOutputs minorMinorOutputs{ + allOutputs.minorMinorLabels, allOutputs.bits, allOutputs.box }; + for (int i = 0; i <= steps; i++) { + // PRL: Bug1038. Don't label 1.6, rounded, as a duplicate tick for "2" + if (!(mFormat == IntFormat && decade < 10.0)) { + for (int f = start; f != (int)(end); f += mstep) { + if ((int)(f / 10) != f / 10.0f) { + val = decade * f / 10; + if (val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); + Tick(dc, pos, val, tickSizes, + mFonts.minorMinor, minorMinorOutputs); + } + } + } + } + decade *= step; + } + + BoxAdjust(allOutputs); +} + + +#endif diff --git a/src/widgets/LogarithmicUpdater.h b/src/widgets/LogarithmicUpdater.h index 405c3dfb5b45..bf02d0e92674 100644 --- a/src/widgets/LogarithmicUpdater.h +++ b/src/widgets/LogarithmicUpdater.h @@ -11,10 +11,9 @@ #ifndef __AUDACITY_LOGARITHMIC_UPDATER__ #define __AUDACITY_LOGARITHMIC_UPDATER__ -#include "Ruler.h" #include "Updater.h" -struct Ruler::LogarithmicUpdater : public Ruler::Updater { +struct LogarithmicUpdater : public Updater { explicit LogarithmicUpdater(const Ruler& ruler, const ZoomInfo* z) : Updater{ ruler, NULL } {} @@ -25,104 +24,5 @@ struct Ruler::LogarithmicUpdater : public Ruler::Updater { ) const override; }; - - -void Ruler::LogarithmicUpdater::Update( - wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const -{ - TickOutputs majorOutputs{ - allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; - - auto numberScale = (mNumberScale == NumberScale{}) - ? NumberScale(nstLogarithmic, mMin, mMax) - : mNumberScale; - - double UPP = (mHiddenMax - mHiddenMin) / mLength; // Units per pixel - TickSizes tickSizes{ UPP, mOrientation, mFormat, true }; - - tickSizes.mDigits = 2; //TODO: implement dynamic digit computation - - double loLog = log10(mMin); - double hiLog = log10(mMax); - int loDecade = (int)floor(loLog); - - double val; - double startDecade = pow(10., (double)loDecade); - - // Major ticks are the decades - double decade = startDecade; - double delta = hiLog - loLog, steps = fabs(delta); - double step = delta >= 0 ? 10 : 0.1; - double rMin = std::min(mMin, mMax), rMax = std::max(mMin, mMax); - for (int i = 0; i <= steps; i++) - { // if(i!=0) - { val = decade; - if (val >= rMin && val < rMax) { - const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); - Tick(dc, pos, val, tickSizes, mFonts.major, majorOutputs); - } - } - decade *= step; - } - - // Minor ticks are multiples of decades - decade = startDecade; - float start, end, mstep; - if (delta > 0) - { - start = 2; end = 10; mstep = 1; - } - else - { - start = 9; end = 1; mstep = -1; - } - steps++; - tickSizes.useMajor = false; - TickOutputs minorOutputs{ - allOutputs.minorLabels, allOutputs.bits, allOutputs.box }; - for (int i = 0; i <= steps; i++) { - for (int j = start; j != end; j += mstep) { - val = decade * j; - if (val >= rMin && val < rMax) { - const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); - Tick(dc, pos, val, tickSizes, mFonts.minor, minorOutputs); - } - } - decade *= step; - } - - // MinorMinor ticks are multiples of decades - decade = startDecade; - if (delta > 0) - { - start = 10; end = 100; mstep = 1; - } - else - { - start = 100; end = 10; mstep = -1; - } - steps++; - TickOutputs minorMinorOutputs{ - allOutputs.minorMinorLabels, allOutputs.bits, allOutputs.box }; - for (int i = 0; i <= steps; i++) { - // PRL: Bug1038. Don't label 1.6, rounded, as a duplicate tick for "2" - if (!(mFormat == IntFormat && decade < 10.0)) { - for (int f = start; f != (int)(end); f += mstep) { - if ((int)(f / 10) != f / 10.0f) { - val = decade * f / 10; - if (val >= rMin && val < rMax) { - const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); - Tick(dc, pos, val, tickSizes, - mFonts.minorMinor, minorMinorOutputs); - } - } - } - } - decade *= step; - } - - BoxAdjust(allOutputs); -} - - #endif + diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 0abfd09f27a4..f28813bb5499 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -386,415 +386,6 @@ void Ruler::Invalidate() // mUserBits.clear(); } - -struct Ruler::TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; -struct Ruler::UpdateOutputs { - Labels& majorLabels, & minorLabels, & minorMinorLabels; - Bits& bits; - wxRect& box; -}; - -struct Ruler::TickSizes -{ - bool useMajor = true; - - double mMajor; - double mMinor; - - int mDigits; - -TickSizes( double UPP, int orientation, RulerFormat format, bool log ) -{ - //TODO: better dynamic digit computation for the log case - (void)log; - - // Given the dimensions of the ruler, the range of values it - // has to display, and the format (i.e. Int, Real, Time), - // figure out how many units are in one Minor tick, and - // in one Major tick. - // - // The goal is to always put tick marks on nice round numbers - // that are easy for humans to grok. This is the most tricky - // with time. - - double d; - - // As a heuristic, we want at least 22 pixels between each - // minor tick. We want to show numbers like "-48" - // in that space. - // If vertical, we don't need as much space. - double units = ((orientation == wxHORIZONTAL) ? 22 : 16) * fabs(UPP); - - mDigits = 0; - - switch(format) { - case LinearDBFormat: - if (units < 0.001) { - mMinor = 0.001; - mMajor = 0.005; - return; - } - if (units < 0.01) { - mMinor = 0.01; - mMajor = 0.05; - return; - } - if (units < 0.1) { - mMinor = 0.1; - mMajor = 0.5; - return; - } - if (units < 1.0) { - mMinor = 1.0; - mMajor = 6.0; - return; - } - if (units < 3.0) { - mMinor = 3.0; - mMajor = 12.0; - return; - } - if (units < 6.0) { - mMinor = 6.0; - mMajor = 24.0; - return; - } - if (units < 12.0) { - mMinor = 12.0; - mMajor = 48.0; - return; - } - if (units < 24.0) { - mMinor = 24.0; - mMajor = 96.0; - return; - } - d = 20.0; - for(;;) { - if (units < d) { - mMinor = d; - mMajor = d*5.0; - return; - } - d *= 5.0; - if (units < d) { - mMinor = d; - mMajor = d*5.0; - return; - } - d *= 2.0; - } - break; - - case IntFormat: - d = 1.0; - for(;;) { - if (units < d) { - mMinor = d; - mMajor = d*5.0; - return; - } - d *= 5.0; - if (units < d) { - mMinor = d; - mMajor = d*2.0; - return; - } - d *= 2.0; - } - break; - - case TimeFormat: - if (units > 0.5) { - if (units < 1.0) { // 1 sec - mMinor = 1.0; - mMajor = 5.0; - return; - } - if (units < 5.0) { // 5 sec - mMinor = 5.0; - mMajor = 15.0; - return; - } - if (units < 10.0) { - mMinor = 10.0; - mMajor = 30.0; - return; - } - if (units < 15.0) { - mMinor = 15.0; - mMajor = 60.0; - return; - } - if (units < 30.0) { - mMinor = 30.0; - mMajor = 60.0; - return; - } - if (units < 60.0) { // 1 min - mMinor = 60.0; - mMajor = 300.0; - return; - } - if (units < 300.0) { // 5 min - mMinor = 300.0; - mMajor = 900.0; - return; - } - if (units < 600.0) { // 10 min - mMinor = 600.0; - mMajor = 1800.0; - return; - } - if (units < 900.0) { // 15 min - mMinor = 900.0; - mMajor = 3600.0; - return; - } - if (units < 1800.0) { // 30 min - mMinor = 1800.0; - mMajor = 3600.0; - return; - } - if (units < 3600.0) { // 1 hr - mMinor = 3600.0; - mMajor = 6*3600.0; - return; - } - if (units < 6*3600.0) { // 6 hrs - mMinor = 6*3600.0; - mMajor = 24*3600.0; - return; - } - if (units < 24*3600.0) { // 1 day - mMinor = 24*3600.0; - mMajor = 7*24*3600.0; - return; - } - - mMinor = 24.0 * 7.0 * 3600.0; // 1 week - mMajor = 24.0 * 7.0 * 3600.0; - } - - // Otherwise fall through to RealFormat - // (fractions of a second should be dealt with - // the same way as for RealFormat) - - case RealFormat: - d = 0.000001; - // mDigits is number of digits after the decimal point. - mDigits = 6; - for(;;) { - if (units < d) { - mMinor = d; - mMajor = d*5.0; - return; - } - d *= 5.0; - if (units < d) { - mMinor = d; - mMajor = d*2.0; - return; - } - d *= 2.0; - mDigits--; - // More than 10 digit numbers? Something is badly wrong. - // Probably units is coming in with too high a value. - wxASSERT( mDigits >= -10 ); - if( mDigits < -10 ) - break; - } - mMinor = d; - mMajor = d * 2.0; - break; - - case RealLogFormat: - d = 0.000001; - // mDigits is number of digits after the decimal point. - mDigits = 6; - for(;;) { - if (units < d) { - mMinor = d; - mMajor = d*5.0; - return; - } - d *= 5.0; - if (units < d) { - mMinor = d; - mMajor = d*2.0; - return; - } - d *= 2.0; - mDigits--; - // More than 10 digit numbers? Something is badly wrong. - // Probably units is coming in with too high a value. - wxASSERT( mDigits >= -10 ); - if( mDigits < -10 ) - break; - } - mDigits++; - mMinor = d; - mMajor = d * 2.0; - break; - } -} - -TranslatableString LabelString( - double d, RulerFormat format, const TranslatableString &units ) - const -{ - // Given a value, turn it into a string according - // to the current ruler format. The number of digits of - // accuracy depends on the resolution of the ruler, - // i.e. how far zoomed in or out you are. - - wxString s; - - // PRL Todo: are all these cases properly localized? (Decimal points, - // hour-minute-second, etc.?) - - // Replace -0 with 0 - if (d < 0.0 && (d+mMinor > 0.0) && ( format != RealLogFormat )) - d = 0.0; - - switch( format ) { - case IntFormat: - s.Printf(wxT("%d"), (int)floor(d+0.5)); - break; - case LinearDBFormat: - if (mMinor >= 1.0) - s.Printf(wxT("%d"), (int)floor(d+0.5)); - else { - int precision = -log10(mMinor); - s.Printf(wxT("%.*f"), precision, d); - } - break; - case RealFormat: - if (mMinor >= 1.0) - s.Printf(wxT("%d"), (int)floor(d+0.5)); - else { - s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d); - } - break; - case RealLogFormat: - if (mMinor >= 1.0) - s.Printf(wxT("%d"), (int)floor(d+0.5)); - else { - s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d); - } - break; - case TimeFormat: - if (useMajor) { - if (d < 0) { - s = wxT("-"); - d = -d; - } - - #if ALWAYS_HH_MM_SS - int secs = (int)(d + 0.5); - if (mMinor >= 1.0) { - s.Printf(wxT("%d:%02d:%02d"), secs/3600, (secs/60)%60, secs%60); - } - else { - wxString t1, t2, format; - t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60); - format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits); - t2.Printf(format, fmod(d, 60.0)); - s += t1 + t2; - } - break; - #endif - - if (mMinor >= 3600.0) { - int hrs = (int)(d / 3600.0 + 0.5); - wxString h; - h.Printf(wxT("%d:00:00"), hrs); - s += h; - } - else if (mMinor >= 60.0) { - int minutes = (int)(d / 60.0 + 0.5); - wxString m; - if (minutes >= 60) - m.Printf(wxT("%d:%02d:00"), minutes/60, minutes%60); - else - m.Printf(wxT("%d:00"), minutes); - s += m; - } - else if (mMinor >= 1.0) { - int secs = (int)(d + 0.5); - wxString t; - if (secs >= 3600) - t.Printf(wxT("%d:%02d:%02d"), secs/3600, (secs/60)%60, secs%60); - else if (secs >= 60) - t.Printf(wxT("%d:%02d"), secs/60, secs%60); - else - t.Printf(wxT("%d"), secs); - s += t; - } - else { -// Commented out old and incorrect code for avoiding the 40mins and 60 seconds problem -// It was causing Bug 463 - Incorrect Timeline numbering (where at high zoom and long tracks, -// numbers did not change. -#if 0 - // The casting to float is working around an issue where 59 seconds - // would show up as 60 when using g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3. - int secs = (int)(float)(d); - wxString t1, t2, format; - - if (secs >= 3600) - t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60); - else if (secs >= 60) - t1.Printf(wxT("%d:"), secs/60); - - if (secs >= 60) - format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits); - else - format.Printf(wxT("%%%d.%dlf"), mDigits+3, mDigits); - // The casting to float is working around an issue where 59 seconds - // would show up as 60 when using g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3. - t2.Printf(format, fmod((float)d, (float)60.0)); -#else - // For d in the range of hours, d is just very slightly below the value it should - // have, because of using a double, which in turn yields values like 59:59:999999 - // mins:secs:nanosecs when we want 1:00:00:000000 - // so adjust by less than a nano second per hour to get nicer number formatting. - double dd = d * 1.000000000000001; - int secs = (int)(dd); - wxString t1, t2, format; - - if (secs >= 3600) - t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60); - else if (secs >= 60) - t1.Printf(wxT("%d:"), secs/60); - - if (secs >= 60) - format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits); - else - format.Printf(wxT("%%%d.%dlf"), mDigits+3, mDigits); - // dd will be reduced to just the seconds and fractional part. - dd = dd - secs + (secs%60); - // truncate to appropriate number of digits, so that the print formatting - // doesn't round up 59.9999999 to 60. - double multiplier = pow( 10, mDigits); - dd = ((int)(dd * multiplier))/multiplier; - t2.Printf(format, dd); -#endif - s += t1 + t2; - } - } - else { - } - } - - auto result = Verbatim( s ); - if (!units.empty()) - result += units; - - return result; -} - -}; // struct Ruler::TickSizes - auto Ruler::MakeTick( Label lab, wxDC &dc, wxFont font, @@ -1000,7 +591,7 @@ void Ruler::UpdateCache( cache.mBits = mUserBits; cache.mBits.resize( static_cast(mLength + 1), false ); - UpdateOutputs allOutputs{ + Updater::UpdateOutputs allOutputs{ cache.mMajorLabels, cache.mMinorLabels, cache.mMinorMinorLabels, cache.mBits, cache.mRect }; diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index e7125be85ad9..daabfff62fc0 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -22,15 +22,9 @@ class wxFont; class Envelope; class ZoomInfo; +struct Updater; class AUDACITY_DLL_API Ruler { -private: - - struct Updater; - struct LinearUpdater; - struct LogarithmicUpdater; - struct CustomUpdater; - public: enum RulerFormat { @@ -166,9 +160,10 @@ class AUDACITY_DLL_API Ruler { void Invalidate(); private: - struct TickOutputs; - struct UpdateOutputs; - struct TickSizes; + friend class Updater; + friend class LinearUpdater; + friend class LogarithmicUpdater; + friend class CustomUpdater; class Label { public: diff --git a/src/widgets/Updater.cpp b/src/widgets/Updater.cpp index 07c84647c9fc..dafe34cfaba8 100644 --- a/src/widgets/Updater.cpp +++ b/src/widgets/Updater.cpp @@ -20,13 +20,417 @@ *//******************************************************************/ #include "Updater.h" -#include "Ruler.h" -struct TickOutputs; -struct UpdateOutputs; -struct TickSizes; -void Ruler::Updater::BoxAdjust( +struct TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; +struct UpdateOutputs { + Labels& majorLabels, & minorLabels, & minorMinorLabels; + Bits& bits; + wxRect& box; +}; + +struct TickSizes +{ + bool useMajor = true; + + double mMajor; + double mMinor; + + int mDigits; + + TickSizes(double UPP, int orientation, RulerFormat format, bool log) + { + //TODO: better dynamic digit computation for the log case + (void)log; + + // Given the dimensions of the ruler, the range of values it + // has to display, and the format (i.e. Int, Real, Time), + // figure out how many units are in one Minor tick, and + // in one Major tick. + // + // The goal is to always put tick marks on nice round numbers + // that are easy for humans to grok. This is the most tricky + // with time. + + double d; + + // As a heuristic, we want at least 22 pixels between each + // minor tick. We want to show numbers like "-48" + // in that space. + // If vertical, we don't need as much space. + double units = ((orientation == wxHORIZONTAL) ? 22 : 16) * fabs(UPP); + + mDigits = 0; + + switch (format) { + case LinearDBFormat: + if (units < 0.001) { + mMinor = 0.001; + mMajor = 0.005; + return; + } + if (units < 0.01) { + mMinor = 0.01; + mMajor = 0.05; + return; + } + if (units < 0.1) { + mMinor = 0.1; + mMajor = 0.5; + return; + } + if (units < 1.0) { + mMinor = 1.0; + mMajor = 6.0; + return; + } + if (units < 3.0) { + mMinor = 3.0; + mMajor = 12.0; + return; + } + if (units < 6.0) { + mMinor = 6.0; + mMajor = 24.0; + return; + } + if (units < 12.0) { + mMinor = 12.0; + mMajor = 48.0; + return; + } + if (units < 24.0) { + mMinor = 24.0; + mMajor = 96.0; + return; + } + d = 20.0; + for (;;) { + if (units < d) { + mMinor = d; + mMajor = d * 5.0; + return; + } + d *= 5.0; + if (units < d) { + mMinor = d; + mMajor = d * 5.0; + return; + } + d *= 2.0; + } + break; + + case IntFormat: + d = 1.0; + for (;;) { + if (units < d) { + mMinor = d; + mMajor = d * 5.0; + return; + } + d *= 5.0; + if (units < d) { + mMinor = d; + mMajor = d * 2.0; + return; + } + d *= 2.0; + } + break; + + case TimeFormat: + if (units > 0.5) { + if (units < 1.0) { // 1 sec + mMinor = 1.0; + mMajor = 5.0; + return; + } + if (units < 5.0) { // 5 sec + mMinor = 5.0; + mMajor = 15.0; + return; + } + if (units < 10.0) { + mMinor = 10.0; + mMajor = 30.0; + return; + } + if (units < 15.0) { + mMinor = 15.0; + mMajor = 60.0; + return; + } + if (units < 30.0) { + mMinor = 30.0; + mMajor = 60.0; + return; + } + if (units < 60.0) { // 1 min + mMinor = 60.0; + mMajor = 300.0; + return; + } + if (units < 300.0) { // 5 min + mMinor = 300.0; + mMajor = 900.0; + return; + } + if (units < 600.0) { // 10 min + mMinor = 600.0; + mMajor = 1800.0; + return; + } + if (units < 900.0) { // 15 min + mMinor = 900.0; + mMajor = 3600.0; + return; + } + if (units < 1800.0) { // 30 min + mMinor = 1800.0; + mMajor = 3600.0; + return; + } + if (units < 3600.0) { // 1 hr + mMinor = 3600.0; + mMajor = 6 * 3600.0; + return; + } + if (units < 6 * 3600.0) { // 6 hrs + mMinor = 6 * 3600.0; + mMajor = 24 * 3600.0; + return; + } + if (units < 24 * 3600.0) { // 1 day + mMinor = 24 * 3600.0; + mMajor = 7 * 24 * 3600.0; + return; + } + + mMinor = 24.0 * 7.0 * 3600.0; // 1 week + mMajor = 24.0 * 7.0 * 3600.0; + } + + // Otherwise fall through to RealFormat + // (fractions of a second should be dealt with + // the same way as for RealFormat) + + case RealFormat: + d = 0.000001; + // mDigits is number of digits after the decimal point. + mDigits = 6; + for (;;) { + if (units < d) { + mMinor = d; + mMajor = d * 5.0; + return; + } + d *= 5.0; + if (units < d) { + mMinor = d; + mMajor = d * 2.0; + return; + } + d *= 2.0; + mDigits--; + // More than 10 digit numbers? Something is badly wrong. + // Probably units is coming in with too high a value. + wxASSERT(mDigits >= -10); + if (mDigits < -10) + break; + } + mMinor = d; + mMajor = d * 2.0; + break; + + case RealLogFormat: + d = 0.000001; + // mDigits is number of digits after the decimal point. + mDigits = 6; + for (;;) { + if (units < d) { + mMinor = d; + mMajor = d * 5.0; + return; + } + d *= 5.0; + if (units < d) { + mMinor = d; + mMajor = d * 2.0; + return; + } + d *= 2.0; + mDigits--; + // More than 10 digit numbers? Something is badly wrong. + // Probably units is coming in with too high a value. + wxASSERT(mDigits >= -10); + if (mDigits < -10) + break; + } + mDigits++; + mMinor = d; + mMajor = d * 2.0; + break; + } + } + + TranslatableString LabelString( + double d, RulerFormat format, const TranslatableString& units) + const + { + // Given a value, turn it into a string according + // to the current ruler format. The number of digits of + // accuracy depends on the resolution of the ruler, + // i.e. how far zoomed in or out you are. + + wxString s; + + // PRL Todo: are all these cases properly localized? (Decimal points, + // hour-minute-second, etc.?) + + // Replace -0 with 0 + if (d < 0.0 && (d + mMinor > 0.0) && (format != RealLogFormat)) + d = 0.0; + + switch (format) { + case IntFormat: + s.Printf(wxT("%d"), (int)floor(d + 0.5)); + break; + case LinearDBFormat: + if (mMinor >= 1.0) + s.Printf(wxT("%d"), (int)floor(d + 0.5)); + else { + int precision = -log10(mMinor); + s.Printf(wxT("%.*f"), precision, d); + } + break; + case RealFormat: + if (mMinor >= 1.0) + s.Printf(wxT("%d"), (int)floor(d + 0.5)); + else { + s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d); + } + break; + case RealLogFormat: + if (mMinor >= 1.0) + s.Printf(wxT("%d"), (int)floor(d + 0.5)); + else { + s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d); + } + break; + case TimeFormat: + if (useMajor) { + if (d < 0) { + s = wxT("-"); + d = -d; + } + +#if ALWAYS_HH_MM_SS + int secs = (int)(d + 0.5); + if (mMinor >= 1.0) { + s.Printf(wxT("%d:%02d:%02d"), secs / 3600, (secs / 60) % 60, secs % 60); + } + else { + wxString t1, t2, format; + t1.Printf(wxT("%d:%02d:"), secs / 3600, (secs / 60) % 60); + format.Printf(wxT("%%0%d.%dlf"), mDigits + 3, mDigits); + t2.Printf(format, fmod(d, 60.0)); + s += t1 + t2; + } + break; +#endif + + if (mMinor >= 3600.0) { + int hrs = (int)(d / 3600.0 + 0.5); + wxString h; + h.Printf(wxT("%d:00:00"), hrs); + s += h; + } + else if (mMinor >= 60.0) { + int minutes = (int)(d / 60.0 + 0.5); + wxString m; + if (minutes >= 60) + m.Printf(wxT("%d:%02d:00"), minutes / 60, minutes % 60); + else + m.Printf(wxT("%d:00"), minutes); + s += m; + } + else if (mMinor >= 1.0) { + int secs = (int)(d + 0.5); + wxString t; + if (secs >= 3600) + t.Printf(wxT("%d:%02d:%02d"), secs / 3600, (secs / 60) % 60, secs % 60); + else if (secs >= 60) + t.Printf(wxT("%d:%02d"), secs / 60, secs % 60); + else + t.Printf(wxT("%d"), secs); + s += t; + } + else { + // Commented out old and incorrect code for avoiding the 40mins and 60 seconds problem + // It was causing Bug 463 - Incorrect Timeline numbering (where at high zoom and long tracks, + // numbers did not change. +#if 0 + // The casting to float is working around an issue where 59 seconds + // would show up as 60 when using g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3. + int secs = (int)(float)(d); + wxString t1, t2, format; + + if (secs >= 3600) + t1.Printf(wxT("%d:%02d:"), secs / 3600, (secs / 60) % 60); + else if (secs >= 60) + t1.Printf(wxT("%d:"), secs / 60); + + if (secs >= 60) + format.Printf(wxT("%%0%d.%dlf"), mDigits + 3, mDigits); + else + format.Printf(wxT("%%%d.%dlf"), mDigits + 3, mDigits); + // The casting to float is working around an issue where 59 seconds + // would show up as 60 when using g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3. + t2.Printf(format, fmod((float)d, (float)60.0)); +#else + // For d in the range of hours, d is just very slightly below the value it should + // have, because of using a double, which in turn yields values like 59:59:999999 + // mins:secs:nanosecs when we want 1:00:00:000000 + // so adjust by less than a nano second per hour to get nicer number formatting. + double dd = d * 1.000000000000001; + int secs = (int)(dd); + wxString t1, t2, format; + + if (secs >= 3600) + t1.Printf(wxT("%d:%02d:"), secs / 3600, (secs / 60) % 60); + else if (secs >= 60) + t1.Printf(wxT("%d:"), secs / 60); + + if (secs >= 60) + format.Printf(wxT("%%0%d.%dlf"), mDigits + 3, mDigits); + else + format.Printf(wxT("%%%d.%dlf"), mDigits + 3, mDigits); + // dd will be reduced to just the seconds and fractional part. + dd = dd - secs + (secs % 60); + // truncate to appropriate number of digits, so that the print formatting + // doesn't round up 59.9999999 to 60. + double multiplier = pow(10, mDigits); + dd = ((int)(dd * multiplier)) / multiplier; + t2.Printf(format, dd); +#endif + s += t1 + t2; + } + } + else { + } + } + + auto result = Verbatim(s); + if (!units.empty()) + result += units; + + return result; + } + +}; // struct Ruler::TickSizes + +void Updater::BoxAdjust( UpdateOutputs& allOutputs ) const @@ -68,7 +472,7 @@ const update(label); } -bool Ruler::Updater::Tick(wxDC& dc, +bool Updater::Tick(wxDC& dc, int pos, double d, const TickSizes& tickSizes, wxFont font, // in/out: TickOutputs outputs) const @@ -101,7 +505,7 @@ bool Ruler::Updater::Tick(wxDC& dc, return !rect.IsEmpty(); } -bool Ruler::Updater::TickCustom(wxDC& dc, int labelIdx, wxFont font, +bool Updater::TickCustom(wxDC& dc, int labelIdx, wxFont font, // in/out: TickOutputs outputs) const { diff --git a/src/widgets/Updater.h b/src/widgets/Updater.h index 911c87eca5b2..80d4c49b1695 100644 --- a/src/widgets/Updater.h +++ b/src/widgets/Updater.h @@ -13,7 +13,15 @@ #include "Ruler.h" -struct Ruler::Updater { +class Ruler::Label; + +struct Updater { +private: + using Labels = std::vector; + using Bits = std::vector< bool >; + +public: + const Ruler& mRuler; const ZoomInfo* zoomInfo; @@ -21,10 +29,11 @@ struct Ruler::Updater { : mRuler{ ruler } , zoomInfo{ z } {} + ~Updater() {} const double mDbMirrorValue = mRuler.mDbMirrorValue; const int mLength = mRuler.mLength; - const RulerFormat mFormat = mRuler.mFormat; + const Ruler::RulerFormat mFormat = mRuler.mFormat; const TranslatableString mUnits = mRuler.mUnits; const int mLeft = mRuler.mLeft; @@ -37,7 +46,7 @@ struct Ruler::Updater { const bool mFlip = mRuler.mFlip; const bool mCustom = mRuler.mCustom; - const Fonts& mFonts = *mRuler.mpFonts; + const Ruler::Fonts& mFonts = *mRuler.mpFonts; const bool mLog = mRuler.mLog; const double mHiddenMin = mRuler.mHiddenMin; const double mHiddenMax = mRuler.mHiddenMax; @@ -47,6 +56,17 @@ struct Ruler::Updater { const int mLeftOffset = mRuler.mLeftOffset; const NumberScale mNumberScale = mRuler.mNumberScale; + + + struct TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; + struct UpdateOutputs { + Labels& majorLabels, & minorLabels, & minorMinorLabels; + Bits& bits; + wxRect& box; + }; + + struct TickSizes; + bool Tick(wxDC& dc, int pos, double d, const TickSizes& tickSizes, wxFont font, TickOutputs outputs From bb2a44f77c4c19aeef15eb1e87b2de1e85a422eb Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 20:14:49 -0400 Subject: [PATCH 10/19] ZoomInfo rulers Replace all uses of SetUseZoomInfo with SetUpdater --- src/AdornedRulerPanel.cpp | 8 ++++++-- src/TimeTrack.cpp | 10 ++++++++-- src/widgets/LinearUpdater.cpp | 4 ++-- src/widgets/Ruler.cpp | 19 +++---------------- src/widgets/Ruler.h | 4 +--- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index b14de330984e..62686ae7fee2 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -1282,7 +1282,9 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* project, mOuter = GetClientRect(); - mRuler.SetUseZoomInfo(mLeftOffset, mViewInfo); + mRuler.SetUpdater + (std::make_unique(mRuler, mViewInfo), + mLeftOffset); mRuler.SetLabelEdges( false ); mRuler.SetFormat( Ruler::TimeFormat ); @@ -2579,7 +2581,9 @@ int AdornedRulerPanel::GetRulerHeight(bool showScrubBar) void AdornedRulerPanel::SetLeftOffset(int offset) { mLeftOffset = offset; - mRuler.SetUseZoomInfo(offset, mViewInfo); + mRuler.SetUpdater + ( std::make_unique( mRuler, mViewInfo ), + offset); } // Draws the scrubbing/seeking indicator. diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index bc80c566b2c0..ebe8bc2605f5 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -27,6 +27,7 @@ #include "Project.h" #include "ProjectRate.h" #include "ViewInfo.h" +#include "widgets/LinearUpdater.h" //TODO-MB: are these sensible values? @@ -74,7 +75,10 @@ void TimeTrack::CleanState() SetName(GetDefaultName()); mRuler = std::make_unique(); - mRuler->SetUseZoomInfo(0, mZoomInfo); + + mRuler->SetUpdater + (std::make_unique(mRuler, mZoomInfo), + 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } @@ -102,7 +106,9 @@ TimeTrack::TimeTrack(const TimeTrack &orig, ProtectedCreationArg &&a, ///@TODO: Give Ruler:: a copy-constructor instead of this? mRuler = std::make_unique(); - mRuler->SetUseZoomInfo(0, mZoomInfo); + mRuler->SetUpdater + (std::make_unique(mRuler, mZoomInfo), + 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } diff --git a/src/widgets/LinearUpdater.cpp b/src/widgets/LinearUpdater.cpp index 27842082588c..ef8b64e975a9 100644 --- a/src/widgets/LinearUpdater.cpp +++ b/src/widgets/LinearUpdater.cpp @@ -33,7 +33,7 @@ void LinearUpdater::Update( return -1; int mid; - if (zoomInfo != NULL) { + if (zoomInfo) { // Tick only at zero if (value) return -1; @@ -91,7 +91,7 @@ void LinearUpdater::Update( double d, warpedD, nextD; double prevTime = 0.0, time = 0.0; - if (zoomInfo != NULL) { + if (zoomInfo) { j = zoomInfo->TimeToPosition(mMin); prevTime = zoomInfo->PositionToTime(--j); time = zoomInfo->PositionToTime(++j); diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index f28813bb5499..daf268af807b 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -155,7 +155,7 @@ void Ruler::SetUpdater(std::unique_ptr pUpdater) } void Ruler::SetUpdater - (std::unique_ptr pUpdater, int leftOffset, const ZoomInfo* zoomInfo) + (std::unique_ptr pUpdater, int leftOffset) { // Should a comparison be made between mpUpdater and pUpdater? // Runtime type comparison isn't clean in c++ @@ -165,8 +165,8 @@ void Ruler::SetUpdater mLeftOffset = leftOffset; // Hm, is this invalidation sufficient? What if *zoomInfo changes under us? - if (mUseZoomInfo != zoomInfo) - mUseZoomInfo = zoomInfo; + if (mUseZoomInfo != mpUpdater->zoomInfo) + mUseZoomInfo = mpUpdater->zoomInfo; Invalidate(); } @@ -860,19 +860,6 @@ void Ruler::Label::Draw(wxDC&dc, bool twoTone, wxColour c) const } } -void Ruler::SetUseZoomInfo(int leftOffset, const ZoomInfo *zoomInfo) -{ - - if ( mLeftOffset != leftOffset || - // Hm, is this invalidation sufficient? What if *zoomInfo changes under us? - mUseZoomInfo != zoomInfo - ) { - mLeftOffset = leftOffset; - mUseZoomInfo = zoomInfo; - Invalidate(); - } -} - // // RulerPanel // diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index daabfff62fc0..fa7a9a10dc38 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -68,7 +68,7 @@ class AUDACITY_DLL_API Ruler { void SetUpdater(std::unique_ptr pUpdater); // An overload to replace SetUseZoomInfo - void SetUpdater(std::unique_ptr pUpdater, int leftOffset, const ZoomInfo* zoomInfo); + void SetUpdater(std::unique_ptr pUpdater, int leftOffset); // // Optional Ruler Parameters @@ -138,8 +138,6 @@ class AUDACITY_DLL_API Ruler { void SetCustomMinorLabels( const TranslatableStrings &labels, int start, int step); - void SetUseZoomInfo(int leftOffset, const ZoomInfo *zoomInfo); - // // Drawing // From f4e1c42ccbf739a4016d5f4bd233f2a64f372114 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 20:18:35 -0400 Subject: [PATCH 11/19] Finish off SetUpdater files and prettify Small edits --- src/AdornedRulerPanel.cpp | 8 ++------ src/TimeTrack.cpp | 10 +++------- src/widgets/Ruler.cpp | 4 ++-- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 62686ae7fee2..aadcdbe1542d 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -1282,9 +1282,7 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* project, mOuter = GetClientRect(); - mRuler.SetUpdater - (std::make_unique(mRuler, mViewInfo), - mLeftOffset); + mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), mLeftOffset ); mRuler.SetLabelEdges( false ); mRuler.SetFormat( Ruler::TimeFormat ); @@ -2581,9 +2579,7 @@ int AdornedRulerPanel::GetRulerHeight(bool showScrubBar) void AdornedRulerPanel::SetLeftOffset(int offset) { mLeftOffset = offset; - mRuler.SetUpdater - ( std::make_unique( mRuler, mViewInfo ), - offset); + mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), offset ); } // Draws the scrubbing/seeking indicator. diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index ebe8bc2605f5..b6e10194fd1c 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -22,12 +22,12 @@ #include #include #include "widgets/Ruler.h" +#include "widgets/LinearUpdater.h" #include "Envelope.h" #include "Mix.h" #include "Project.h" #include "ProjectRate.h" #include "ViewInfo.h" -#include "widgets/LinearUpdater.h" //TODO-MB: are these sensible values? @@ -76,9 +76,7 @@ void TimeTrack::CleanState() mRuler = std::make_unique(); - mRuler->SetUpdater - (std::make_unique(mRuler, mZoomInfo), - 0); + mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } @@ -106,9 +104,7 @@ TimeTrack::TimeTrack(const TimeTrack &orig, ProtectedCreationArg &&a, ///@TODO: Give Ruler:: a copy-constructor instead of this? mRuler = std::make_unique(); - mRuler->SetUpdater - (std::make_unique(mRuler, mZoomInfo), - 0); + mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index daf268af807b..710d641d0534 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -68,6 +68,8 @@ array of Ruler::Label. #include "ViewInfo.h" #include "Updater.h" +// Need to include to set default +// #include "LinearUpdater.h" using std::min; using std::max; @@ -119,8 +121,6 @@ Ruler::Ruler() mUseZoomInfo = NULL; - // Default the updater to Linear, as it would be before removal of mLog - // struct LinearUpdater; // mpUpdater = std::make_unique( *this, mUseZoomInfo ); mpUpdater = NULL; } From 5b37bfc77358bfcee42e0cf0da4dd0995e0b4535 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 22:17:57 -0400 Subject: [PATCH 12/19] Comment out SetUpdater --- src/AdornedRulerPanel.cpp | 4 ++-- src/TimeTrack.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index aadcdbe1542d..b0b794b1c9a2 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -1282,7 +1282,7 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* project, mOuter = GetClientRect(); - mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), mLeftOffset ); + // mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), mLeftOffset ); mRuler.SetLabelEdges( false ); mRuler.SetFormat( Ruler::TimeFormat ); @@ -2579,7 +2579,7 @@ int AdornedRulerPanel::GetRulerHeight(bool showScrubBar) void AdornedRulerPanel::SetLeftOffset(int offset) { mLeftOffset = offset; - mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), offset ); + // mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), offset ); } // Draws the scrubbing/seeking indicator. diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index b6e10194fd1c..f0db2d1a7a15 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -76,7 +76,7 @@ void TimeTrack::CleanState() mRuler = std::make_unique(); - mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); + // mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } @@ -104,7 +104,7 @@ TimeTrack::TimeTrack(const TimeTrack &orig, ProtectedCreationArg &&a, ///@TODO: Give Ruler:: a copy-constructor instead of this? mRuler = std::make_unique(); - mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); + // mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } From 57fa05ad9004d29545d471d7c4a85151a96b3d8b Mon Sep 17 00:00:00 2001 From: micpap25 Date: Sun, 10 Jul 2022 22:49:40 -0400 Subject: [PATCH 13/19] Replace SetLog with SetUpdater --- src/FreqWindow.cpp | 12 ++++++----- src/effects/Equalization.cpp | 10 ++++++---- .../wavetrack/ui/SpectrumVRulerControls.cpp | 6 ++++-- .../wavetrack/ui/WaveformVRulerControls.cpp | 5 +++-- .../timetrack/ui/TimeTrackVRulerControls.cpp | 7 ++++++- src/widgets/Ruler.cpp | 20 +++++++------------ src/widgets/Ruler.h | 3 --- 7 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/FreqWindow.cpp b/src/FreqWindow.cpp index 335df93968cf..95ad1c68966e 100644 --- a/src/FreqWindow.cpp +++ b/src/FreqWindow.cpp @@ -83,6 +83,8 @@ the mouse around. #include "./widgets/HelpSystem.h" #include "widgets/AudacityMessageBox.h" #include "widgets/Ruler.h" +#include "widgets/LinearUpdater.h" +#include "widgets/LogarithmicUpdater.h" #include "widgets/VetoDialogHook.h" #if wxUSE_ACCESSIBILITY @@ -674,10 +676,10 @@ void FrequencyPlotDialog::DrawPlot() if (!mData || mDataLen < mWindowSize || mAnalyst->GetProcessedSize() == 0) { wxMemoryDC memDC; - vRuler->ruler.SetLog(false); + // vRuler->SetUpdater(std::make_unique(vRuler.get(), NULL)); vRuler->ruler.SetRange(0.0, -dBRange); - hRuler->ruler.SetLog(false); + // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); hRuler->ruler.SetRange(0, 1); DrawBackground(memDC); @@ -752,19 +754,19 @@ void FrequencyPlotDialog::DrawPlot() if (mLogAxis) { xStep = pow(2.0f, (log(xRatio) / log(2.0f)) / width); - hRuler->ruler.SetLog(true); + // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); } else { xStep = (xMax - xMin) / width; - hRuler->ruler.SetLog(false); + // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); } hRuler->ruler.SetUnits(XO("Hz")); } else { xMin = 0; xMax = mAnalyst->GetProcessedSize() / mRate; xStep = (xMax - xMin) / width; - hRuler->ruler.SetLog(false); + // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); /* i18n-hint: short form of 'seconds'.*/ hRuler->ruler.SetUnits(XO("s")); } diff --git a/src/effects/Equalization.cpp b/src/effects/Equalization.cpp index 946813a8ef84..2b711140ebad 100644 --- a/src/effects/Equalization.cpp +++ b/src/effects/Equalization.cpp @@ -103,6 +103,8 @@ #include "../WaveClip.h" #include "ViewInfo.h" #include "../WaveTrack.h" +#include "../widgets/LinearUpdater.h" +#include "../widgets/LogarithmicUpdater.h" #include "../widgets/Ruler.h" #include "../widgets/AudacityTextEntryDialog.h" #include "XMLFileReader.h" @@ -2288,7 +2290,7 @@ void EffectEqualization::UpdateDraw() { EnvLogToLin(); mEnvelope = mLinEnvelope.get(); - mFreqRuler->ruler.SetLog(false); + // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); mFreqRuler->ruler.SetRange(0, mHiFreq); } @@ -2320,7 +2322,7 @@ void EffectEqualization::UpdateGraphic() EnvLinToLog(); mEnvelope = mLogEnvelope.get(); - mFreqRuler->ruler.SetLog(true); + // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); mFreqRuler->ruler.SetRange(mLoFreq, mHiFreq); } @@ -2909,7 +2911,7 @@ void EffectEqualization::OnLinFreq(wxCommandEvent & WXUNUSED(event)) mLin = mLinFreq->IsChecked(); if(IsLinear()) //going from log to lin freq scale { - mFreqRuler->ruler.SetLog(false); + // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); mFreqRuler->ruler.SetRange(0, mHiFreq); EnvLogToLin(); mEnvelope = mLinEnvelope.get(); @@ -2917,7 +2919,7 @@ void EffectEqualization::OnLinFreq(wxCommandEvent & WXUNUSED(event)) } else //going from lin to log freq scale { - mFreqRuler->ruler.SetLog(true); + // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); mFreqRuler->ruler.SetRange(mLoFreq, mHiFreq); EnvLinToLog(); mEnvelope = mLogEnvelope.get(); diff --git a/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp index 9d203217a0f4..d94c3d2bb37d 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp @@ -20,6 +20,8 @@ Paul Licameli split from WaveTrackVRulerControls.cpp #include "../../../../WaveTrack.h" #include "../../../../prefs/SpectrogramSettings.h" #include "../../../../widgets/Ruler.h" +#include "../../../../widgets/LinearUpdater.h" +#include "../../../../widgets/LogarithmicUpdater.h" SpectrumVRulerControls::~SpectrumVRulerControls() = default; @@ -167,7 +169,7 @@ void SpectrumVRulerControls::DoUpdateVRuler( vruler->SetRange((int)(maxFreq), (int)(minFreq)); vruler->SetUnits({}); } - vruler->SetLog(false); + // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); } break; case SpectrogramSettings::stLogarithmic: @@ -189,7 +191,7 @@ void SpectrumVRulerControls::DoUpdateVRuler( vruler->SetLabelEdges(true); vruler->SetRange(maxFreq, minFreq); vruler->SetUnits({}); - vruler->SetLog(true); + // vruler->SetUpdater(std::make_unique(vRuler.get(), NULL)); NumberScale scale( wt->GetSpectrogramSettings().GetScale( minFreq, maxFreq ) .Reversal() ); diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp index e0b8691c3cb6..048ff1c462f7 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp @@ -21,6 +21,7 @@ Paul Licameli split from WaveTrackVRulerControls.cpp #include "../../../../WaveTrack.h" #include "../../../../prefs/WaveformSettings.h" #include "../../../../widgets/Ruler.h" +#include "../../../../widgets/LinearUpdater.h" WaveformVRulerControls::~WaveformVRulerControls() = default; @@ -222,7 +223,7 @@ void WaveformVRulerControls::DoUpdateVRuler( vruler->SetFormat(Ruler::RealFormat); vruler->SetUnits({}); vruler->SetLabelEdges(false); - vruler->SetLog(false); + // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); } else { wxASSERT(scaleType == WaveformSettings::stLogarithmic); @@ -330,7 +331,7 @@ void WaveformVRulerControls::DoUpdateVRuler( #endif vruler->SetFormat(Ruler::RealLogFormat); vruler->SetLabelEdges(true); - vruler->SetLog(false); + // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); } vruler->GetMaxSize( &wt->vrulerSize.first, &wt->vrulerSize.second ); } diff --git a/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp b/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp index d7a3a0c88a0f..aa2309faba91 100644 --- a/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp +++ b/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp @@ -25,6 +25,8 @@ Paul Licameli split from TrackPanel.cpp #include "../../../TrackPanelMouseEvent.h" #include "../../../UIHandle.h" #include "../../../widgets/Ruler.h" +#include "../../../widgets/LinearUpdater.h" +#include "../../../widgets/LogarithmicUpdater.h" TimeTrackVRulerControls::~TimeTrackVRulerControls() { @@ -120,7 +122,10 @@ void TimeTrackVRulerControls::UpdateRuler( const wxRect &rect ) vruler->SetFormat((tt->GetDisplayLog()) ? Ruler::RealLogFormat : Ruler::RealFormat); vruler->SetUnits({}); vruler->SetLabelEdges(false); - vruler->SetLog(tt->GetDisplayLog()); + // if (tt->GetDisplayLog()) + // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); + // else + // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); vruler->GetMaxSize( &tt->vrulerSize.first, &tt->vrulerSize.second ); } diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 710d641d0534..619169bc8dc1 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -69,7 +69,9 @@ array of Ruler::Label. #include "Updater.h" // Need to include to set default -// #include "LinearUpdater.h" +#include "LinearUpdater.h" +// Needed for RulerPanel +#include "LogarithmicUpdater.h" using std::min; using std::max; @@ -171,17 +173,6 @@ void Ruler::SetUpdater Invalidate(); } -void Ruler::SetLog(bool log) -{ - // Logarithmic - - if (mLog != log) { - mLog = log; - - Invalidate(); - } -} - void Ruler::SetUnits(const TranslatableString &units) { // Specify the name of the units (like "dB") if you @@ -886,7 +877,10 @@ RulerPanel::RulerPanel(wxWindow* parent, wxWindowID id, ruler.SetBounds( 0, 0, bounds.x, bounds.y ); ruler.SetOrientation(orientation); ruler.SetRange( range.first, range.second ); - ruler.SetLog( options.log ); + // if (options.log) + // ruler->SetUpdater(std::make_unique(ruler.get(), NULL)); + // else + // ruler->SetUpdater(std::make_unique(ruler.get(), NULL)); ruler.SetFormat(format); ruler.SetUnits( units ); ruler.SetFlip( options.flip ); diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index fa7a9a10dc38..dcede69b6336 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -85,9 +85,6 @@ class AUDACITY_DLL_API Ruler { void SetUnits(const TranslatableString &units); void SetDbMirrorValue( const double d ); - // Logarithmic - void SetLog(bool log); - // Minimum number of pixels between labels void SetSpacing(int spacing); From edd4a590c1390c9e86d6e09628108d9fa6fa861c Mon Sep 17 00:00:00 2001 From: micpap25 Date: Mon, 11 Jul 2022 11:44:03 -0400 Subject: [PATCH 14/19] Fix mistaken comments --- src/FreqWindow.cpp | 10 +++++----- src/effects/Equalization.cpp | 8 ++++---- src/widgets/Ruler.cpp | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/FreqWindow.cpp b/src/FreqWindow.cpp index 95ad1c68966e..87f5c96a6476 100644 --- a/src/FreqWindow.cpp +++ b/src/FreqWindow.cpp @@ -676,10 +676,10 @@ void FrequencyPlotDialog::DrawPlot() if (!mData || mDataLen < mWindowSize || mAnalyst->GetProcessedSize() == 0) { wxMemoryDC memDC; - // vRuler->SetUpdater(std::make_unique(vRuler.get(), NULL)); + // vRuler->ruler.SetUpdater(std::make_unique(vRuler->ruler, NULL)); vRuler->ruler.SetRange(0.0, -dBRange); - // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); + // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); hRuler->ruler.SetRange(0, 1); DrawBackground(memDC); @@ -754,19 +754,19 @@ void FrequencyPlotDialog::DrawPlot() if (mLogAxis) { xStep = pow(2.0f, (log(xRatio) / log(2.0f)) / width); - // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); + // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); } else { xStep = (xMax - xMin) / width; - // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); + // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); } hRuler->ruler.SetUnits(XO("Hz")); } else { xMin = 0; xMax = mAnalyst->GetProcessedSize() / mRate; xStep = (xMax - xMin) / width; - // hRuler->SetUpdater(std::make_unique(hRuler.get(), NULL)); + // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); /* i18n-hint: short form of 'seconds'.*/ hRuler->ruler.SetUnits(XO("s")); } diff --git a/src/effects/Equalization.cpp b/src/effects/Equalization.cpp index 2b711140ebad..584aa338e45b 100644 --- a/src/effects/Equalization.cpp +++ b/src/effects/Equalization.cpp @@ -2290,7 +2290,7 @@ void EffectEqualization::UpdateDraw() { EnvLogToLin(); mEnvelope = mLinEnvelope.get(); - // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); + // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); mFreqRuler->ruler.SetRange(0, mHiFreq); } @@ -2322,7 +2322,7 @@ void EffectEqualization::UpdateGraphic() EnvLinToLog(); mEnvelope = mLogEnvelope.get(); - // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); + // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); mFreqRuler->ruler.SetRange(mLoFreq, mHiFreq); } @@ -2911,7 +2911,7 @@ void EffectEqualization::OnLinFreq(wxCommandEvent & WXUNUSED(event)) mLin = mLinFreq->IsChecked(); if(IsLinear()) //going from log to lin freq scale { - // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); + // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); mFreqRuler->ruler.SetRange(0, mHiFreq); EnvLogToLin(); mEnvelope = mLinEnvelope.get(); @@ -2919,7 +2919,7 @@ void EffectEqualization::OnLinFreq(wxCommandEvent & WXUNUSED(event)) } else //going from lin to log freq scale { - // mFreqRuler->SetUpdater(std::make_unique(mFreqRuler.get(), NULL)); + // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); mFreqRuler->ruler.SetRange(mLoFreq, mHiFreq); EnvLinToLog(); mEnvelope = mLogEnvelope.get(); diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 619169bc8dc1..4875ffacb0d4 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -878,9 +878,9 @@ RulerPanel::RulerPanel(wxWindow* parent, wxWindowID id, ruler.SetOrientation(orientation); ruler.SetRange( range.first, range.second ); // if (options.log) - // ruler->SetUpdater(std::make_unique(ruler.get(), NULL)); + // ruler.SetUpdater(std::make_unique(ruler, NULL)); // else - // ruler->SetUpdater(std::make_unique(ruler.get(), NULL)); + // ruler.SetUpdater(std::make_unique(ruler, NULL)); ruler.SetFormat(format); ruler.SetUnits( units ); ruler.SetFlip( options.flip ); From acfecca412a7c0ced10b8646e1b0586794e69502 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Mon, 11 Jul 2022 11:50:03 -0400 Subject: [PATCH 15/19] More comment fixes --- .../playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp | 4 ++-- .../playabletrack/wavetrack/ui/WaveformVRulerControls.cpp | 4 ++-- src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp index d94c3d2bb37d..0f05a3b36c5b 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp @@ -169,7 +169,7 @@ void SpectrumVRulerControls::DoUpdateVRuler( vruler->SetRange((int)(maxFreq), (int)(minFreq)); vruler->SetUnits({}); } - // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); + // vruler->SetUpdater(std::make_unique(vruler, NULL)); } break; case SpectrogramSettings::stLogarithmic: @@ -191,7 +191,7 @@ void SpectrumVRulerControls::DoUpdateVRuler( vruler->SetLabelEdges(true); vruler->SetRange(maxFreq, minFreq); vruler->SetUnits({}); - // vruler->SetUpdater(std::make_unique(vRuler.get(), NULL)); + // vruler->SetUpdater(std::make_unique(vruler, NULL)); NumberScale scale( wt->GetSpectrogramSettings().GetScale( minFreq, maxFreq ) .Reversal() ); diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp index 048ff1c462f7..4b98a1524248 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp @@ -223,7 +223,7 @@ void WaveformVRulerControls::DoUpdateVRuler( vruler->SetFormat(Ruler::RealFormat); vruler->SetUnits({}); vruler->SetLabelEdges(false); - // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); + // vruler->SetUpdater(std::make_unique(vruler, NULL)); } else { wxASSERT(scaleType == WaveformSettings::stLogarithmic); @@ -331,7 +331,7 @@ void WaveformVRulerControls::DoUpdateVRuler( #endif vruler->SetFormat(Ruler::RealLogFormat); vruler->SetLabelEdges(true); - // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); + // vruler->SetUpdater(std::make_unique(vruler, NULL)); } vruler->GetMaxSize( &wt->vrulerSize.first, &wt->vrulerSize.second ); } diff --git a/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp b/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp index aa2309faba91..a63357e376d0 100644 --- a/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp +++ b/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp @@ -123,9 +123,9 @@ void TimeTrackVRulerControls::UpdateRuler( const wxRect &rect ) vruler->SetUnits({}); vruler->SetLabelEdges(false); // if (tt->GetDisplayLog()) - // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); + // vruler->SetUpdater(std::make_unique(vruler, NULL)); // else - // vruler->SetUpdater(std::make_unique(vruler.get(), NULL)); + // vruler->SetUpdater(std::make_unique(vruler, NULL)); vruler->GetMaxSize( &tt->vrulerSize.first, &tt->vrulerSize.second ); } From c984921e57ae4b613c108425a1bf169d1e9125a8 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Mon, 11 Jul 2022 14:31:18 -0400 Subject: [PATCH 16/19] Uncommented code (Linker broken) --- src/AdornedRulerPanel.cpp | 4 ++-- src/FreqWindow.cpp | 10 +++++----- src/TimeTrack.cpp | 5 ++--- src/effects/Equalization.cpp | 8 ++++---- .../wavetrack/ui/SpectrumVRulerControls.cpp | 4 ++-- .../wavetrack/ui/WaveformVRulerControls.cpp | 4 ++-- src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp | 8 ++++---- src/widgets/Ruler.cpp | 13 ++++++++----- 8 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index b0b794b1c9a2..aadcdbe1542d 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -1282,7 +1282,7 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* project, mOuter = GetClientRect(); - // mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), mLeftOffset ); + mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), mLeftOffset ); mRuler.SetLabelEdges( false ); mRuler.SetFormat( Ruler::TimeFormat ); @@ -2579,7 +2579,7 @@ int AdornedRulerPanel::GetRulerHeight(bool showScrubBar) void AdornedRulerPanel::SetLeftOffset(int offset) { mLeftOffset = offset; - // mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), offset ); + mRuler.SetUpdater( std::make_unique( mRuler, mViewInfo ), offset ); } // Draws the scrubbing/seeking indicator. diff --git a/src/FreqWindow.cpp b/src/FreqWindow.cpp index 87f5c96a6476..071ec4397922 100644 --- a/src/FreqWindow.cpp +++ b/src/FreqWindow.cpp @@ -676,10 +676,10 @@ void FrequencyPlotDialog::DrawPlot() if (!mData || mDataLen < mWindowSize || mAnalyst->GetProcessedSize() == 0) { wxMemoryDC memDC; - // vRuler->ruler.SetUpdater(std::make_unique(vRuler->ruler, NULL)); + vRuler->ruler.SetUpdater(std::make_unique(vRuler->ruler, nullptr)); vRuler->ruler.SetRange(0.0, -dBRange); - // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); + hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, nullptr)); hRuler->ruler.SetRange(0, 1); DrawBackground(memDC); @@ -754,19 +754,19 @@ void FrequencyPlotDialog::DrawPlot() if (mLogAxis) { xStep = pow(2.0f, (log(xRatio) / log(2.0f)) / width); - // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); + hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, nullptr)); } else { xStep = (xMax - xMin) / width; - // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); + hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, nullptr)); } hRuler->ruler.SetUnits(XO("Hz")); } else { xMin = 0; xMax = mAnalyst->GetProcessedSize() / mRate; xStep = (xMax - xMin) / width; - // hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, NULL)); + hRuler->ruler.SetUpdater(std::make_unique(hRuler->ruler, nullptr)); /* i18n-hint: short form of 'seconds'.*/ hRuler->ruler.SetUnits(XO("s")); } diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index f0db2d1a7a15..6cd433ac57f8 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -75,8 +75,7 @@ void TimeTrack::CleanState() SetName(GetDefaultName()); mRuler = std::make_unique(); - - // mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); + mRuler->SetUpdater(std::make_unique(*(mRuler.get()), mZoomInfo), 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } @@ -104,7 +103,7 @@ TimeTrack::TimeTrack(const TimeTrack &orig, ProtectedCreationArg &&a, ///@TODO: Give Ruler:: a copy-constructor instead of this? mRuler = std::make_unique(); - // mRuler->SetUpdater(std::make_unique(mRuler.get(), mZoomInfo), 0); + mRuler->SetUpdater(std::make_unique(*(mRuler.get()), mZoomInfo), 0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); } diff --git a/src/effects/Equalization.cpp b/src/effects/Equalization.cpp index 584aa338e45b..e49463a475d2 100644 --- a/src/effects/Equalization.cpp +++ b/src/effects/Equalization.cpp @@ -2290,7 +2290,7 @@ void EffectEqualization::UpdateDraw() { EnvLogToLin(); mEnvelope = mLinEnvelope.get(); - // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); + mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, nullptr)); mFreqRuler->ruler.SetRange(0, mHiFreq); } @@ -2322,7 +2322,7 @@ void EffectEqualization::UpdateGraphic() EnvLinToLog(); mEnvelope = mLogEnvelope.get(); - // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); + mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, nullptr)); mFreqRuler->ruler.SetRange(mLoFreq, mHiFreq); } @@ -2911,7 +2911,7 @@ void EffectEqualization::OnLinFreq(wxCommandEvent & WXUNUSED(event)) mLin = mLinFreq->IsChecked(); if(IsLinear()) //going from log to lin freq scale { - // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); + mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, nullptr)); mFreqRuler->ruler.SetRange(0, mHiFreq); EnvLogToLin(); mEnvelope = mLinEnvelope.get(); @@ -2919,7 +2919,7 @@ void EffectEqualization::OnLinFreq(wxCommandEvent & WXUNUSED(event)) } else //going from lin to log freq scale { - // mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, NULL)); + mFreqRuler->ruler.SetUpdater(std::make_unique(mFreqRuler->ruler, nullptr)); mFreqRuler->ruler.SetRange(mLoFreq, mHiFreq); EnvLinToLog(); mEnvelope = mLogEnvelope.get(); diff --git a/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp index 0f05a3b36c5b..fe533718fe52 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/SpectrumVRulerControls.cpp @@ -169,7 +169,7 @@ void SpectrumVRulerControls::DoUpdateVRuler( vruler->SetRange((int)(maxFreq), (int)(minFreq)); vruler->SetUnits({}); } - // vruler->SetUpdater(std::make_unique(vruler, NULL)); + vruler->SetUpdater(std::make_unique(*vruler, nullptr)); } break; case SpectrogramSettings::stLogarithmic: @@ -191,7 +191,7 @@ void SpectrumVRulerControls::DoUpdateVRuler( vruler->SetLabelEdges(true); vruler->SetRange(maxFreq, minFreq); vruler->SetUnits({}); - // vruler->SetUpdater(std::make_unique(vruler, NULL)); + vruler->SetUpdater(std::make_unique(*vruler, nullptr)); NumberScale scale( wt->GetSpectrogramSettings().GetScale( minFreq, maxFreq ) .Reversal() ); diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp index 4b98a1524248..af2f7acd585f 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveformVRulerControls.cpp @@ -223,7 +223,7 @@ void WaveformVRulerControls::DoUpdateVRuler( vruler->SetFormat(Ruler::RealFormat); vruler->SetUnits({}); vruler->SetLabelEdges(false); - // vruler->SetUpdater(std::make_unique(vruler, NULL)); + vruler->SetUpdater(std::make_unique(*vruler, nullptr)); } else { wxASSERT(scaleType == WaveformSettings::stLogarithmic); @@ -331,7 +331,7 @@ void WaveformVRulerControls::DoUpdateVRuler( #endif vruler->SetFormat(Ruler::RealLogFormat); vruler->SetLabelEdges(true); - // vruler->SetUpdater(std::make_unique(vruler, NULL)); + vruler->SetUpdater(std::make_unique(*vruler, nullptr)); } vruler->GetMaxSize( &wt->vrulerSize.first, &wt->vrulerSize.second ); } diff --git a/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp b/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp index a63357e376d0..541500d1e2fd 100644 --- a/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp +++ b/src/tracks/timetrack/ui/TimeTrackVRulerControls.cpp @@ -122,10 +122,10 @@ void TimeTrackVRulerControls::UpdateRuler( const wxRect &rect ) vruler->SetFormat((tt->GetDisplayLog()) ? Ruler::RealLogFormat : Ruler::RealFormat); vruler->SetUnits({}); vruler->SetLabelEdges(false); - // if (tt->GetDisplayLog()) - // vruler->SetUpdater(std::make_unique(vruler, NULL)); - // else - // vruler->SetUpdater(std::make_unique(vruler, NULL)); + if (tt->GetDisplayLog()) + vruler->SetUpdater(std::make_unique(*vruler, nullptr)); + else + vruler->SetUpdater(std::make_unique(*vruler, nullptr)); vruler->GetMaxSize( &tt->vrulerSize.first, &tt->vrulerSize.second ); } diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 4875ffacb0d4..cad2e6ca2679 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -123,8 +123,11 @@ Ruler::Ruler() mUseZoomInfo = NULL; + // This part in particular needs inspection, not giving an error + // But is this corret? And should it be set to NULL or nullptr if a default + // cannot be made? // mpUpdater = std::make_unique( *this, mUseZoomInfo ); - mpUpdater = NULL; + mpUpdater = nullptr; } Ruler::~Ruler() @@ -877,10 +880,10 @@ RulerPanel::RulerPanel(wxWindow* parent, wxWindowID id, ruler.SetBounds( 0, 0, bounds.x, bounds.y ); ruler.SetOrientation(orientation); ruler.SetRange( range.first, range.second ); - // if (options.log) - // ruler.SetUpdater(std::make_unique(ruler, NULL)); - // else - // ruler.SetUpdater(std::make_unique(ruler, NULL)); + if (options.log) + ruler.SetUpdater(std::make_unique(ruler, nullptr)); + else + ruler.SetUpdater(std::make_unique(ruler, nullptr)); ruler.SetFormat(format); ruler.SetUnits( units ); ruler.SetFlip( options.flip ); From 986120c1f7e766673b3b3f29493a56616b963f9f Mon Sep 17 00:00:00 2001 From: micpap25 Date: Mon, 11 Jul 2022 16:23:57 -0400 Subject: [PATCH 17/19] Attempted fix of linker issues (doesn't work) --- src/widgets/LinearUpdater.cpp | 3 --- src/widgets/LogarithmicUpdater.cpp | 3 --- src/widgets/Updater.cpp | 6 ++++++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/widgets/LinearUpdater.cpp b/src/widgets/LinearUpdater.cpp index ef8b64e975a9..5a528e784a7e 100644 --- a/src/widgets/LinearUpdater.cpp +++ b/src/widgets/LinearUpdater.cpp @@ -158,6 +158,3 @@ void LinearUpdater::Update( BoxAdjust(allOutputs); } - -#endif - diff --git a/src/widgets/LogarithmicUpdater.cpp b/src/widgets/LogarithmicUpdater.cpp index f3778f576dbd..3cfcaac22a8e 100644 --- a/src/widgets/LogarithmicUpdater.cpp +++ b/src/widgets/LogarithmicUpdater.cpp @@ -106,6 +106,3 @@ void LogarithmicUpdater::Update( BoxAdjust(allOutputs); } - - -#endif diff --git a/src/widgets/Updater.cpp b/src/widgets/Updater.cpp index dafe34cfaba8..eba1ec36de02 100644 --- a/src/widgets/Updater.cpp +++ b/src/widgets/Updater.cpp @@ -533,3 +533,9 @@ bool Updater::TickCustom(wxDC& dc, int labelIdx, wxFont font, outputs.labels[labelIdx] = (result.second); return !rect.IsEmpty(); } + +// Theoretically this helps +void Updater::Update( + wxDC& dc, const Envelope* envelope, + UpdateOutputs& allOutputs +) const {} From c58b93dc6dd577de068b7ecae57a7208934e657a Mon Sep 17 00:00:00 2001 From: micpap25 Date: Mon, 11 Jul 2022 23:40:47 -0400 Subject: [PATCH 18/19] Update compilation --- src/AudacityHeaders.h | 1 - src/CMakeLists.txt | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/AudacityHeaders.h b/src/AudacityHeaders.h index 7a7d7d6dce9c..fac0071b771d 100644 --- a/src/AudacityHeaders.h +++ b/src/AudacityHeaders.h @@ -57,7 +57,6 @@ #include "UndoManager.h" #include "WaveTrack.h" #include "widgets/ASlider.h" -#include "widgets/Ruler.h" // PRL: These lines allow you to remove Project.h above. // They must be included before the definition of macro NEW below. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2262b211e43..a2b8d84d18d7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1013,6 +1013,8 @@ list( APPEND SOURCES widgets/BackedPanel.h widgets/BasicMenu.cpp widgets/BasicMenu.h + widgets/CustomUpdater.cpp + widgets/CustomUpdater.h widgets/ErrorDialog.cpp widgets/ErrorDialog.h widgets/ExpandingToolBar.cpp @@ -1045,6 +1047,10 @@ list( APPEND SOURCES widgets/ImageRoll.h widgets/KeyView.cpp widgets/KeyView.h + widgets/LinearUpdater.cpp + widgets/LinearUpdater.h + widgets/LogarithmicUpdater.cpp + widgets/LogarithmicUpdater.h widgets/MeterPanel.cpp widgets/MeterPanel.h widgets/MeterPanelBase.cpp @@ -1070,6 +1076,8 @@ list( APPEND SOURCES > widgets/UnwritableLocationErrorDialog.cpp widgets/UnwritableLocationErrorDialog.h + widgets/Updater.cpp + widgets/Updater.h widgets/VetoDialogHook.h widgets/Warning.cpp widgets/Warning.h From 330be7351b7176f5fd8272451ec014b86f2a6a17 Mon Sep 17 00:00:00 2001 From: micpap25 Date: Fri, 15 Jul 2022 06:28:09 -0400 Subject: [PATCH 19/19] Fix scoping and variable issues --- src/widgets/CustomUpdater.cpp | 3 + src/widgets/LinearUpdater.cpp | 22 +++++++- src/widgets/LogarithmicUpdater.cpp | 15 ++++- src/widgets/Ruler.cpp | 16 +----- src/widgets/Updater.cpp | 89 +++++++++++++++++------------- src/widgets/Updater.h | 61 +++++++++----------- 6 files changed, 116 insertions(+), 90 deletions(-) diff --git a/src/widgets/CustomUpdater.cpp b/src/widgets/CustomUpdater.cpp index 2403c16569aa..f4b74520f264 100644 --- a/src/widgets/CustomUpdater.cpp +++ b/src/widgets/CustomUpdater.cpp @@ -14,6 +14,9 @@ void CustomUpdater::Update( wxDC& dc, const Envelope* envelope, UpdateOutputs& allOutputs) const { + const int mLength = mRuler.mLength; + const Ruler::Fonts& mFonts = *mRuler.mpFonts; + TickOutputs majorOutputs{ allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; diff --git a/src/widgets/LinearUpdater.cpp b/src/widgets/LinearUpdater.cpp index 5a528e784a7e..9251c08c0fb2 100644 --- a/src/widgets/LinearUpdater.cpp +++ b/src/widgets/LinearUpdater.cpp @@ -16,6 +16,25 @@ void LinearUpdater::Update( TickOutputs majorOutputs{ allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + const double mDbMirrorValue = mRuler.mDbMirrorValue; + const int mLength = mRuler.mLength; + const Ruler::RulerFormat mFormat = mRuler.mFormat; + + const int mLeft = mRuler.mLeft; + const int mTop = mRuler.mTop; + const int mBottom = mRuler.mBottom; + const int mRight = mRuler.mRight; + const int mOrientation = mRuler.mOrientation; + + const double mMin = mRuler.mMin; + const double mMax = mRuler.mMax; + const double mHiddenMin = mRuler.mHiddenMin; + const double mHiddenMax = mRuler.mHiddenMax; + + const Ruler::Fonts& mFonts = *mRuler.mpFonts; + const bool mLabelEdges = mRuler.mLabelEdges; + const int mLeftOffset = mRuler.mLeftOffset; + // Use the "hidden" min and max to determine the tick size. // That may make a difference with fisheye. // Otherwise you may see the tick size for the whole ruler change @@ -24,7 +43,8 @@ void LinearUpdater::Update( TickSizes tickSizes{ UPP, mOrientation, mFormat, false }; auto TickAtValue = - [this, &tickSizes, &dc, &majorOutputs] + [this, &tickSizes, &dc, &majorOutputs, &mFonts, mOrientation, + mMin, mMax, mLength, mLeftOffset, mRight, mBottom] (double value) -> int { // Make a tick only if the value is strictly between the bounds if (value <= std::min(mMin, mMax)) diff --git a/src/widgets/LogarithmicUpdater.cpp b/src/widgets/LogarithmicUpdater.cpp index 3cfcaac22a8e..8a3f43424b6c 100644 --- a/src/widgets/LogarithmicUpdater.cpp +++ b/src/widgets/LogarithmicUpdater.cpp @@ -16,6 +16,19 @@ void LogarithmicUpdater::Update( TickOutputs majorOutputs{ allOutputs.majorLabels, allOutputs.bits, allOutputs.box }; + const int mLength = mRuler.mLength; + const Ruler::RulerFormat mFormat = mRuler.mFormat; + + const int mOrientation = mRuler.mOrientation; + + const double mMin = mRuler.mMin; + const double mMax = mRuler.mMax; + const double mHiddenMin = mRuler.mHiddenMin; + const double mHiddenMax = mRuler.mHiddenMax; + + const Ruler::Fonts& mFonts = *mRuler.mpFonts; + const NumberScale mNumberScale = mRuler.mNumberScale; + auto numberScale = (mNumberScale == NumberScale{}) ? NumberScale(nstLogarithmic, mMin, mMax) : mNumberScale; @@ -89,7 +102,7 @@ void LogarithmicUpdater::Update( allOutputs.minorMinorLabels, allOutputs.bits, allOutputs.box }; for (int i = 0; i <= steps; i++) { // PRL: Bug1038. Don't label 1.6, rounded, as a duplicate tick for "2" - if (!(mFormat == IntFormat && decade < 10.0)) { + if (!(mFormat == Ruler::IntFormat && decade < 10.0)) { for (int f = start; f != (int)(end); f += mstep) { if ((int)(f / 10) != f / 10.0f) { val = decade * f / 10; diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index cad2e6ca2679..9aa6314ca3ab 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -126,8 +126,8 @@ Ruler::Ruler() // This part in particular needs inspection, not giving an error // But is this corret? And should it be set to NULL or nullptr if a default // cannot be made? - // mpUpdater = std::make_unique( *this, mUseZoomInfo ); - mpUpdater = nullptr; + mpUpdater = std::make_unique( *this, mUseZoomInfo ); + // mpUpdater = nullptr; } Ruler::~Ruler() @@ -477,18 +477,6 @@ struct Ruler::Cache { wxRect mRect; }; -namespace { -double ComputeWarpedLength(const Envelope &env, double t0, double t1) -{ - return env.IntegralOfInverse(t0, t1); -} - -double SolveWarpedLength(const Envelope &env, double t0, double length) -{ - return env.SolveIntegralOfInverse(t0, length); -} -} - static constexpr int MinPixelHeight = #ifdef __WXMSW__ 12; diff --git a/src/widgets/Updater.cpp b/src/widgets/Updater.cpp index eba1ec36de02..df5d04a06df9 100644 --- a/src/widgets/Updater.cpp +++ b/src/widgets/Updater.cpp @@ -21,24 +21,7 @@ #include "Updater.h" - -struct TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; -struct UpdateOutputs { - Labels& majorLabels, & minorLabels, & minorMinorLabels; - Bits& bits; - wxRect& box; -}; - -struct TickSizes -{ - bool useMajor = true; - - double mMajor; - double mMinor; - - int mDigits; - - TickSizes(double UPP, int orientation, RulerFormat format, bool log) +Updater::TickSizes::TickSizes(double UPP, int orientation, Ruler::RulerFormat format, bool log) { //TODO: better dynamic digit computation for the log case (void)log; @@ -63,7 +46,7 @@ struct TickSizes mDigits = 0; switch (format) { - case LinearDBFormat: + case Ruler::LinearDBFormat: if (units < 0.001) { mMinor = 0.001; mMajor = 0.005; @@ -121,7 +104,7 @@ struct TickSizes } break; - case IntFormat: + case Ruler::IntFormat: d = 1.0; for (;;) { if (units < d) { @@ -139,7 +122,7 @@ struct TickSizes } break; - case TimeFormat: + case Ruler::TimeFormat: if (units > 0.5) { if (units < 1.0) { // 1 sec mMinor = 1.0; @@ -215,7 +198,7 @@ struct TickSizes // (fractions of a second should be dealt with // the same way as for RealFormat) - case RealFormat: + case Ruler::RealFormat: d = 0.000001; // mDigits is number of digits after the decimal point. mDigits = 6; @@ -243,7 +226,7 @@ struct TickSizes mMajor = d * 2.0; break; - case RealLogFormat: + case Ruler::RealLogFormat: d = 0.000001; // mDigits is number of digits after the decimal point. mDigits = 6; @@ -274,8 +257,8 @@ struct TickSizes } } - TranslatableString LabelString( - double d, RulerFormat format, const TranslatableString& units) +TranslatableString Updater::TickSizes::LabelString( + double d, Ruler::RulerFormat format, const TranslatableString& units) const { // Given a value, turn it into a string according @@ -289,14 +272,14 @@ struct TickSizes // hour-minute-second, etc.?) // Replace -0 with 0 - if (d < 0.0 && (d + mMinor > 0.0) && (format != RealLogFormat)) + if (d < 0.0 && (d + mMinor > 0.0) && (format != Ruler::RealLogFormat)) d = 0.0; switch (format) { - case IntFormat: + case Ruler::IntFormat: s.Printf(wxT("%d"), (int)floor(d + 0.5)); break; - case LinearDBFormat: + case Ruler::LinearDBFormat: if (mMinor >= 1.0) s.Printf(wxT("%d"), (int)floor(d + 0.5)); else { @@ -304,21 +287,21 @@ struct TickSizes s.Printf(wxT("%.*f"), precision, d); } break; - case RealFormat: + case Ruler::RealFormat: if (mMinor >= 1.0) s.Printf(wxT("%d"), (int)floor(d + 0.5)); else { s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d); } break; - case RealLogFormat: + case Ruler::RealLogFormat: if (mMinor >= 1.0) s.Printf(wxT("%d"), (int)floor(d + 0.5)); else { s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d); } break; - case TimeFormat: + case Ruler::TimeFormat: if (useMajor) { if (d < 0) { s = wxT("-"); @@ -426,15 +409,20 @@ struct TickSizes result += units; return result; - } - -}; // struct Ruler::TickSizes + } void Updater::BoxAdjust( UpdateOutputs& allOutputs ) const { + const int mLeft = mRuler.mLeft; + const int mTop = mRuler.mTop; + const int mBottom = mRuler.mBottom; + const int mRight = mRuler.mRight; + const int mOrientation = mRuler.mOrientation; + const bool mFlip = mRuler.mFlip; + int displacementx = 0, displacementy = 0; auto& box = allOutputs.box; if (!mFlip) { @@ -460,7 +448,7 @@ const displacementy = 0; } } - auto update = [=](Label& label) { + auto update = [=](Ruler::Label& label) { label.lx += displacementx; label.ly += displacementy; }; @@ -477,6 +465,21 @@ bool Updater::Tick(wxDC& dc, // in/out: TickOutputs outputs) const { + const double mDbMirrorValue = mRuler.mDbMirrorValue; + const int mLength = mRuler.mLength; + const Ruler::RulerFormat mFormat = mRuler.mFormat; + + const int mLeft = mRuler.mLeft; + const int mTop = mRuler.mTop; + const int mBottom = mRuler.mBottom; + const int mRight = mRuler.mRight; + const int mOrientation = mRuler.mOrientation; + + const Ruler::Fonts& mFonts = *mRuler.mpFonts; + const TranslatableString mUnits = mRuler.mUnits; + const int mSpacing = mRuler.mSpacing; + const bool mFlip = mRuler.mFlip; + // Bug 521. dB view for waveforms needs a 2-sided scale. if ((mDbMirrorValue > 1.0) && (-d > mDbMirrorValue)) d = -2 * mDbMirrorValue - d; @@ -486,12 +489,12 @@ bool Updater::Tick(wxDC& dc, if (outputs.labels.size() >= mLength) return false; - Label lab; + Ruler::Label lab; lab.value = d; lab.pos = pos; lab.text = tickSizes.LabelString(d, mFormat, mUnits); - const auto result = MakeTick( + const auto result = Ruler::MakeTick( lab, dc, font, outputs.bits, @@ -509,6 +512,14 @@ bool Updater::TickCustom(wxDC& dc, int labelIdx, wxFont font, // in/out: TickOutputs outputs) const { + const int mLeft = mRuler.mLeft; + const int mTop = mRuler.mTop; + const int mOrientation = mRuler.mOrientation; + + const Ruler::Fonts& mFonts = *mRuler.mpFonts; + const int mSpacing = mRuler.mSpacing; + const bool mFlip = mRuler.mFlip; + // FIXME: We don't draw a tick if of end of our label arrays // But we shouldn't have an array of labels. if (labelIdx >= outputs.labels.size()) @@ -516,10 +527,10 @@ bool Updater::TickCustom(wxDC& dc, int labelIdx, wxFont font, //This should only used in the mCustom case - Label lab; + Ruler::Label lab; lab.value = 0.0; - const auto result = MakeTick( + const auto result = Ruler::MakeTick( lab, dc, font, diff --git a/src/widgets/Updater.h b/src/widgets/Updater.h index 80d4c49b1695..9bbc8e401fa5 100644 --- a/src/widgets/Updater.h +++ b/src/widgets/Updater.h @@ -12,16 +12,9 @@ #define __AUDACITY_UPDATER__ #include "Ruler.h" - -class Ruler::Label; +#include "ViewInfo.h" // for children struct Updater { -private: - using Labels = std::vector; - using Bits = std::vector< bool >; - -public: - const Ruler& mRuler; const ZoomInfo* zoomInfo; @@ -31,41 +24,39 @@ struct Updater { {} ~Updater() {} - const double mDbMirrorValue = mRuler.mDbMirrorValue; - const int mLength = mRuler.mLength; - const Ruler::RulerFormat mFormat = mRuler.mFormat; - const TranslatableString mUnits = mRuler.mUnits; + struct TickOutputs { Ruler::Labels& labels; Ruler::Bits& bits; wxRect& box; }; + struct UpdateOutputs { + Ruler::Labels& majorLabels, & minorLabels, & minorMinorLabels; + Ruler::Bits& bits; + wxRect& box; + }; - const int mLeft = mRuler.mLeft; - const int mTop = mRuler.mTop; - const int mBottom = mRuler.mBottom; - const int mRight = mRuler.mRight; - const int mSpacing = mRuler.mSpacing; - const int mOrientation = mRuler.mOrientation; - const bool mFlip = mRuler.mFlip; + struct TickSizes + { + bool useMajor = true; - const bool mCustom = mRuler.mCustom; - const Ruler::Fonts& mFonts = *mRuler.mpFonts; - const bool mLog = mRuler.mLog; - const double mHiddenMin = mRuler.mHiddenMin; - const double mHiddenMax = mRuler.mHiddenMax; - const bool mLabelEdges = mRuler.mLabelEdges; - const double mMin = mRuler.mMin; - const double mMax = mRuler.mMax; - const int mLeftOffset = mRuler.mLeftOffset; - const NumberScale mNumberScale = mRuler.mNumberScale; + double mMajor; + double mMinor; + int mDigits; + TickSizes(double UPP, int orientation, Ruler::RulerFormat format, bool log); - struct TickOutputs { Labels& labels; Bits& bits; wxRect& box; }; - struct UpdateOutputs { - Labels& majorLabels, & minorLabels, & minorMinorLabels; - Bits& bits; - wxRect& box; + TranslatableString LabelString( + double d, Ruler::RulerFormat format, const TranslatableString& units) + const; }; - struct TickSizes; + double ComputeWarpedLength(const Envelope& env, double t0, double t1) const + { + return env.IntegralOfInverse(t0, t1); + } + + double SolveWarpedLength(const Envelope& env, double t0, double length) const + { + return env.SolveIntegralOfInverse(t0, length); + } bool Tick(wxDC& dc, int pos, double d, const TickSizes& tickSizes, wxFont font,