From d97377b640c3f288ed68860a3ffcf60ad7b5c7d9 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:58:52 +0200 Subject: [PATCH] Lv2: Improve LED widget's digit calculation This improves the way digits are calculated for display in `Lv2ViewProc`: - More than 2 digits are now recognized - Minus signs are now recognized - Tests have been added --- include/lmms_math.h | 26 ++++++++++++++++++ src/gui/Lv2ViewBase.cpp | 7 +++-- tests/CMakeLists.txt | 1 + tests/src/core/MathTest.cpp | 53 +++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 tests/src/core/MathTest.cpp diff --git a/include/lmms_math.h b/include/lmms_math.h index b62da81c2..ea0a75581 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -325,6 +325,32 @@ static inline T absMin( T a, T b ) return std::abs(a) < std::abs(b) ? a : b; } +// @brief Calculate number of digits which LcdSpinBox would show for a given number +// @note Once we upgrade to C++20, we could probably use std::formatted_size +static inline int numDigitsAsInt(float f) +{ + // use rounding: + // LcdSpinBox sometimes uses roundf(), sometimes cast rounding + // we use rounding to be on the "safe side" + const float rounded = roundf(f); + int asInt = static_cast(rounded); + int digits = 1; // always at least 1 + if(asInt < 0) + { + ++digits; + asInt = -asInt; + } + // "asInt" is positive from now + int32_t power = 1; + for(int32_t i = 1; i<10; ++i) + { + power *= 10; + if(static_cast(asInt) >= power) { ++digits; } // 2 digits for >=10, 3 for >=100 + else { break; } + } + return digits; +} + } // namespace lmms diff --git a/src/gui/Lv2ViewBase.cpp b/src/gui/Lv2ViewBase.cpp index 12be5e069..830a994c8 100644 --- a/src/gui/Lv2ViewBase.cpp +++ b/src/gui/Lv2ViewBase.cpp @@ -39,6 +39,7 @@ #include "GuiApplication.h" #include "embed.h" #include "gui_templates.h" +#include "lmms_math.h" #include "Lv2ControlBase.h" #include "Lv2Manager.h" #include "Lv2Proc.h" @@ -74,8 +75,10 @@ Lv2ViewProc::Lv2ViewProc(QWidget* parent, Lv2Proc* proc, int colNum) : case PortVis::Integer: { sample_rate_t sr = Engine::audioEngine()->processingSampleRate(); - m_control = new LcdControl((port.max(sr) <= 9.0f) ? 1 : 2, - m_parent); + auto pMin = port.min(sr); + auto pMax = port.max(sr); + int numDigits = std::max(numDigitsAsInt(pMin), numDigitsAsInt(pMax)); + m_control = new LcdControl(numDigits, m_parent); break; } case PortVis::Enumeration: diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 514bf7815..ddf9e2962 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,6 +21,7 @@ ADD_EXECUTABLE(tests src/core/ArrayVectorTest.cpp src/core/AutomatableModelTest.cpp + src/core/MathTest.cpp src/core/ProjectVersionTest.cpp src/core/RelativePathsTest.cpp diff --git a/tests/src/core/MathTest.cpp b/tests/src/core/MathTest.cpp new file mode 100644 index 000000000..2b6404cfd --- /dev/null +++ b/tests/src/core/MathTest.cpp @@ -0,0 +1,53 @@ +/* + * MathTest.cpp + * + * Copyright (c) 2023 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "QTestSuite.h" + +#include "lmms_math.h" + +#include + +class MathTest : QTestSuite +{ + Q_OBJECT +private slots: + void NumDigitsTest() + { + using namespace lmms; + QCOMPARE(numDigitsAsInt(1.f), 1); + QCOMPARE(numDigitsAsInt(9.9f), 2); + QCOMPARE(numDigitsAsInt(10.f), 2); + QCOMPARE(numDigitsAsInt(0.f), 1); + QCOMPARE(numDigitsAsInt(-100.f), 4); + QCOMPARE(numDigitsAsInt(-99.f), 3); + QCOMPARE(numDigitsAsInt(-0.4f), 1); // there is no "-0" for LED spinbox + QCOMPARE(numDigitsAsInt(-0.99f), 2); + QCOMPARE(numDigitsAsInt(1000000000), 10); + QCOMPARE(numDigitsAsInt(-1000000000), 11); + QCOMPARE(numDigitsAsInt(900000000), 9); + QCOMPARE(numDigitsAsInt(-900000000), 10); + } +} MathTests; + +#include "MathTest.moc"