From e6a91ad19d2e5fb3c72d8a9c848105bb23f63b42 Mon Sep 17 00:00:00 2001 From: Rick Vogel Date: Sun, 5 Nov 2023 18:29:56 +0100 Subject: [PATCH] add QskTickmarksMetrics --- examples/mycontrols/main.cpp | 99 ++++++++++++++++++++------ src/CMakeLists.txt | 2 + src/common/QskFunctions.h | 2 +- src/nodes/QskScaleRenderer.cpp | 3 +- src/nodes/QskTickmarksMetrics.cpp | 1 + src/nodes/QskTickmarksMetrics.h | 113 ++++++++++++++++++++++++++++++ src/nodes/QskTickmarksNode.cpp | 7 +- src/nodes/QskTickmarksNode.h | 3 +- 8 files changed, 204 insertions(+), 26 deletions(-) create mode 100644 src/nodes/QskTickmarksMetrics.cpp create mode 100644 src/nodes/QskTickmarksMetrics.h diff --git a/examples/mycontrols/main.cpp b/examples/mycontrols/main.cpp index e8795648..e2a64d36 100644 --- a/examples/mycontrols/main.cpp +++ b/examples/mycontrols/main.cpp @@ -19,6 +19,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include @@ -72,31 +78,82 @@ class ContentBox : public QskBox } }; +struct Tickmarks final : public QskControl +{ + public: + using QskControl::QskControl; + QskTickmarksMetrics metrics; +}; + +class TickmarksSkinlet final : public QskSkinlet +{ + Q_GADGET + public: + enum NodeRoles + { + TickmarksRole + }; + + Q_INVOKABLE TickmarksSkinlet(QskSkin* skin = nullptr) : QskSkinlet(skin) + { + setNodeRoles( { TickmarksRole } ); + } + + QSGNode* updateSubNode( const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node ) const override + { + const auto* const q = static_cast< const Tickmarks* >( skinnable ); + + if(nodeRole == TickmarksRole) + { + auto* const tickmarksNode = QskSGNode::ensureNode(node); + + const auto rect = q->contentsRect(); + + QskScaleTickmarks tickmarks; + QVector major, medium, minor; + for ( int i = -100; i <= +100; ++i ) + { + if(i % 50 == 0) major << i; + else if(i % 10 == 0) medium << i; + else minor << i; + } + tickmarks.setMajorTicks(major); + tickmarks.setMediumTicks(medium); + tickmarks.setMinorTicks(minor); + + tickmarksNode->update( + Qt::darkGray, rect, { -100, +100 }, tickmarks, 1, Qt::Horizontal, Qt::AlignBottom, q->metrics ); + + return tickmarksNode; + } + + return nullptr; + } +}; + class Window : public QskWindow { public: Window() { - auto button = new MyToggleButton(); - - button->setText( false, alternativeSkin( false ) ); - button->setText( true, alternativeSkin( true ) ); - button->setLayoutAlignmentHint( Qt::AlignRight ); - - auto box = new QskLinearBox( Qt::Vertical ); - - box->setMargins( 20 ); - box->addItem( button ); - box->addSpacer( 10 ); - box->addItem( new ContentBox() ); - - connect( button, &MyToggleButton::toggled, - this, &Window::setAlternativeSkin ); - - setAlternativeSkin( button->isChecked() ); - - addItem( box ); - addItem( new QskFocusIndicator() ); + auto* const layout = new QskLinearBox(Qt::Vertical, contentItem()); + { + (void) new QskTextLabel("Default", layout); + auto* const tickmarks = new Tickmarks(layout); + auto* const skinlet = new TickmarksSkinlet; + tickmarks->setSkinlet(skinlet); + skinlet->setOwnedBySkinnable(true); + } + { + (void) new QskTextLabel("Custom", layout); + auto* const tickmarks = new Tickmarks(layout); + tickmarks->metrics[QskScaleTickmarks::MajorTick] = 1.0; + tickmarks->metrics[QskScaleTickmarks::MediumTick] = 0.5; + tickmarks->metrics[QskScaleTickmarks::MinorTick] = 0.2; + auto* const skinlet = new TickmarksSkinlet; + tickmarks->setSkinlet(skinlet); + skinlet->setOwnedBySkinnable(true); + } } private: @@ -154,3 +211,5 @@ int main( int argc, char* argv[] ) return app.exec(); } + +#include "main.moc" \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2f36047..b2bd505e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -123,6 +123,7 @@ list(APPEND HEADERS nodes/QskTextRenderer.h nodes/QskTextureRenderer.h nodes/QskTickmarksNode.h + nodes/QskTickmarksMetrics.h nodes/QskVertex.h ) @@ -154,6 +155,7 @@ list(APPEND SOURCES nodes/QskTextRenderer.cpp nodes/QskTextureRenderer.cpp nodes/QskTickmarksNode.cpp + nodes/QskTickmarksMetrics.cpp nodes/QskVertex.cpp ) diff --git a/src/common/QskFunctions.h b/src/common/QskFunctions.h index c80c7a3f..fdcf774b 100644 --- a/src/common/QskFunctions.h +++ b/src/common/QskFunctions.h @@ -58,7 +58,7 @@ inline QMarginsF qskMargins( const QRectF& rect, const QRectF& innerRect ) rect.bottom() - innerRect.bottom() ); } -inline bool qskFuzzyCompare( qreal value1, qreal value2 ) +inline constexpr bool qskFuzzyCompare( qreal value1, qreal value2 ) { if ( qFuzzyIsNull( value1 ) ) return qFuzzyIsNull( value2 ); diff --git a/src/nodes/QskScaleRenderer.cpp b/src/nodes/QskScaleRenderer.cpp index 51877069..43a1fc53 100644 --- a/src/nodes/QskScaleRenderer.cpp +++ b/src/nodes/QskScaleRenderer.cpp @@ -7,6 +7,7 @@ #include "QskScaleTickmarks.h" #include "QskSkinlet.h" #include "QskSGNode.h" +#include "QskTickmarksMetrics.h" #include "QskTickmarksNode.h" #include "QskTextOptions.h" #include "QskTextColors.h" @@ -230,7 +231,7 @@ QSGNode* QskScaleRenderer::updateTicksNode( ticksNode->update( m_data->tickColor, rect, m_data->boundaries, m_data->tickmarks, tickWidth, m_data->orientation, - m_data->alignment ); + m_data->alignment, {}); return ticksNode; } diff --git a/src/nodes/QskTickmarksMetrics.cpp b/src/nodes/QskTickmarksMetrics.cpp new file mode 100644 index 00000000..5e0c3b9a --- /dev/null +++ b/src/nodes/QskTickmarksMetrics.cpp @@ -0,0 +1 @@ +#include "QskTickmarksMetrics.h" \ No newline at end of file diff --git a/src/nodes/QskTickmarksMetrics.h b/src/nodes/QskTickmarksMetrics.h new file mode 100644 index 00000000..f4209aed --- /dev/null +++ b/src/nodes/QskTickmarksMetrics.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_TICKMARKS_METRICS_H +#define QSK_TICKMARKS_METRICS_H + +#include "QskFunctions.h" + +#include + +class QSK_EXPORT QskTickmarksMetrics +{ + Q_GADGET + Q_PROPERTY( qreal majorRatio READ majorRatio WRITE setMajorRatio) + Q_PROPERTY( qreal mediumRatio READ mediumRatio WRITE setMediumRatio) + Q_PROPERTY( qreal minorRatio READ minorRatio WRITE setMinorRatio) + + public: + constexpr QskTickmarksMetrics() noexcept = default; + constexpr QskTickmarksMetrics( qreal minorRatio, qreal mediumRatio, qreal majorRatio ) noexcept; + constexpr QskTickmarksMetrics(const QskTickmarksMetrics&) noexcept = default; + constexpr QskTickmarksMetrics( QskTickmarksMetrics&& ) noexcept = default; + + constexpr QskTickmarksMetrics& operator=(const QskTickmarksMetrics&) noexcept = default; + constexpr QskTickmarksMetrics& operator=(QskTickmarksMetrics&&) noexcept = default; + + constexpr Q_REQUIRED_RESULT bool operator==(const QskTickmarksMetrics& rhs) const noexcept; + constexpr Q_REQUIRED_RESULT bool operator!=(const QskTickmarksMetrics& rhs) const noexcept; + + constexpr Q_REQUIRED_RESULT qreal majorRatio() const noexcept; + constexpr Q_REQUIRED_RESULT qreal mediumRatio() const noexcept; + constexpr Q_REQUIRED_RESULT qreal minorRatio() const noexcept; + + constexpr void setMajorRatio( qreal ratio ) noexcept; + constexpr void setMediumRatio( qreal ratio ) noexcept; + constexpr void setMinorRatio( qreal ratio ) noexcept; + + constexpr Q_REQUIRED_RESULT qreal operator[](int index) const noexcept; + constexpr Q_REQUIRED_RESULT qreal& operator[](int index) noexcept; + + private: + union + { + struct + { + qreal m_minorRatio; + qreal m_mediumRatio; + qreal m_majorRatio; + }; + qreal size[3] = { 0.7, 0.85, 1.0 }; + }; +}; + +inline constexpr QskTickmarksMetrics::QskTickmarksMetrics(qreal minorRatio, qreal mediumRatio, qreal majorRatio) noexcept + : m_minorRatio(minorRatio), m_mediumRatio(mediumRatio), m_majorRatio(majorRatio) +{ +} + +inline constexpr qreal QskTickmarksMetrics::majorRatio() const noexcept +{ + return m_majorRatio; +} + +inline constexpr qreal QskTickmarksMetrics::mediumRatio() const noexcept +{ + return m_mediumRatio; +} + +inline constexpr qreal QskTickmarksMetrics::minorRatio() const noexcept +{ + return m_minorRatio; +} + +inline constexpr void QskTickmarksMetrics::setMajorRatio( qreal ratio ) noexcept +{ + m_majorRatio = qBound( 0.0, ratio, 1.0 ); +} + +inline constexpr void QskTickmarksMetrics::setMediumRatio( qreal ratio ) noexcept +{ + m_mediumRatio = qBound( 0.0, ratio, 1.0 ); +} + +inline constexpr void QskTickmarksMetrics::setMinorRatio( qreal ratio ) noexcept +{ + m_minorRatio = qBound( 0.0, ratio, 1.0 ); +} + +inline constexpr bool QskTickmarksMetrics::operator==(const QskTickmarksMetrics& rhs) const noexcept +{ + return qskFuzzyCompare(m_minorRatio, rhs.m_minorRatio) && + qskFuzzyCompare(m_mediumRatio, rhs.m_mediumRatio) && + qskFuzzyCompare(m_majorRatio, rhs.m_majorRatio); +} + +inline constexpr bool QskTickmarksMetrics::operator!=(const QskTickmarksMetrics& rhs) const noexcept +{ + return !(*this == rhs); +} + +inline constexpr qreal QskTickmarksMetrics::operator[](int index) const noexcept +{ + return size[index % 3]; +} + +inline constexpr qreal& QskTickmarksMetrics::operator[](int index) noexcept +{ + return size[index % 3]; +} + +#endif \ No newline at end of file diff --git a/src/nodes/QskTickmarksNode.cpp b/src/nodes/QskTickmarksNode.cpp index 1753570d..31a6870d 100644 --- a/src/nodes/QskTickmarksNode.cpp +++ b/src/nodes/QskTickmarksNode.cpp @@ -1,5 +1,6 @@ #include "QskTickmarksNode.h" #include "QskScaleTickmarks.h" +#include "QskTickmarksMetrics.h" #include #include @@ -53,7 +54,7 @@ QskTickmarksNode::~QskTickmarksNode() void QskTickmarksNode::update( const QColor& color, const QRectF& rect, const QskIntervalF& boundaries, const QskScaleTickmarks& tickmarks, - int lineWidth, Qt::Orientation orientation, Qt::Alignment alignment ) + int lineWidth, Qt::Orientation orientation, Qt::Alignment alignment, const QskTickmarksMetrics& metrics ) { Q_D( QskTickmarksNode ); @@ -88,7 +89,7 @@ void QskTickmarksNode::update( if ( orientation == Qt::Horizontal ) { const qreal ratio = rect.width() / range; - const float len = rect.height() * qskTickFactor( tickType ); + const float len = rect.height() * metrics[tickType]; for( const auto tick : ticks ) { @@ -121,7 +122,7 @@ void QskTickmarksNode::update( else { const qreal ratio = rect.height() / range; - const float len = rect.width() * qskTickFactor( tickType ); + const float len = rect.width() * metrics[tickType]; for( const auto tick : ticks ) { diff --git a/src/nodes/QskTickmarksNode.h b/src/nodes/QskTickmarksNode.h index 7afdab7c..e0cd9b29 100644 --- a/src/nodes/QskTickmarksNode.h +++ b/src/nodes/QskTickmarksNode.h @@ -17,6 +17,7 @@ class QskIntervalF; class QskScaleTickmarks; class QskTickmarksNodePrivate; +class QskTickmarksMetrics; class QSK_EXPORT QskTickmarksNode : public QSGGeometryNode { @@ -26,7 +27,7 @@ class QSK_EXPORT QskTickmarksNode : public QSGGeometryNode void update(const QColor&, const QRectF&, const QskIntervalF&, const QskScaleTickmarks&, int tickLineWidth, Qt::Orientation, - Qt::Alignment ); + Qt::Alignment, const QskTickmarksMetrics& metrics ); private: Q_DECLARE_PRIVATE( QskTickmarksNode )