From 7ddae671e2107acc60594a2c8115634201bdef26 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 11 Apr 2023 13:04:10 +0200 Subject: [PATCH] API of classes dealing with arcs improved --- examples/iotdashboard/LightDisplay.cpp | 2 +- examples/iotdashboard/LightDisplaySkinlet.cpp | 16 +++--- examples/iotdashboard/Skin.cpp | 8 +-- .../nodes/RadialTickmarksNode.cpp | 2 +- src/common/QskArcMetrics.cpp | 16 +++--- src/common/QskArcMetrics.h | 56 +++++++++++-------- src/controls/QskSkinHintTableEditor.cpp | 6 +- src/controls/QskSkinHintTableEditor.h | 3 +- src/nodes/QskArcNode.cpp | 7 +-- src/nodes/QskArcRenderer.cpp | 2 +- src/nodes/QskArcRenderer.h | 5 +- 11 files changed, 66 insertions(+), 57 deletions(-) diff --git a/examples/iotdashboard/LightDisplay.cpp b/examples/iotdashboard/LightDisplay.cpp index e25433ce..9f305b51 100644 --- a/examples/iotdashboard/LightDisplay.cpp +++ b/examples/iotdashboard/LightDisplay.cpp @@ -152,7 +152,7 @@ bool LightDisplay::arcContainsPoint( const QRectF& rect, const QPointF& point ) // 2. check whether point is on arc const qreal radiusMax = rect.width() / 2; - const qreal arcWidth = metrics.width(); + const qreal arcWidth = metrics.thickness(); const qreal radiusMin = radiusMax - arcWidth; const qreal polarRadius = qSqrt( qPow( circlePos.x(), 2 ) + qPow( circlePos.y(), 2 ) ); diff --git a/examples/iotdashboard/LightDisplaySkinlet.cpp b/examples/iotdashboard/LightDisplaySkinlet.cpp index 33e4173c..4d5da6c9 100644 --- a/examples/iotdashboard/LightDisplaySkinlet.cpp +++ b/examples/iotdashboard/LightDisplaySkinlet.cpp @@ -39,13 +39,13 @@ QRectF LightDisplaySkinlet::subControlRect( const QskSkinnable* skinnable, const auto textSize = textLabelsSize( display ); const auto arcMetrics = display->arcMetricsHint( LightDisplay::ColdAndWarmArc ); const qreal ticksWidth = display->arcMetricsHint( - LightDisplay::Tickmarks ).width() + ticksSpacing; + LightDisplay::Tickmarks ).thickness() + ticksSpacing; - const qreal x = textSize.width() + arcMetrics.width() + ticksWidth; + const qreal x = textSize.width() + arcMetrics.thickness() + ticksWidth; const qreal w = contentsRect.width() - - ( 2 * ( textSize.width() + arcMetrics.width() + ticksWidth ) ); - const qreal y = arcMetrics.width() + ticksWidth; - const qreal h = contentsRect.height() - 2 * ( arcMetrics.width() + ticksWidth ); + ( 2 * ( textSize.width() + arcMetrics.thickness() + ticksWidth ) ); + const qreal y = arcMetrics.thickness() + ticksWidth; + const qreal h = contentsRect.height() - 2 * ( arcMetrics.thickness() + ticksWidth ); const qreal diameter = qMin( w, h ); @@ -54,7 +54,7 @@ QRectF LightDisplaySkinlet::subControlRect( const QskSkinnable* skinnable, else if( subControl == LightDisplay::ColdAndWarmArc ) { const QRectF panelRect = subControlRect( skinnable, contentsRect, LightDisplay::Panel ); - const auto barWidth = display->arcMetricsHint( LightDisplay::ColdAndWarmArc ).width(); + const auto barWidth = display->arcMetricsHint( LightDisplay::ColdAndWarmArc ).thickness(); return panelRect.marginsAdded( { barWidth, barWidth, barWidth, barWidth } ); } @@ -63,7 +63,7 @@ QRectF LightDisplaySkinlet::subControlRect( const QskSkinnable* skinnable, const auto arcRect = subControlRect( skinnable, contentsRect, LightDisplay::ColdAndWarmArc ); const qreal ticksWidth = display->arcMetricsHint( - LightDisplay::Tickmarks ).width() + ticksSpacing; + LightDisplay::Tickmarks ).thickness() + ticksSpacing; return arcRect.marginsAdded( { ticksWidth, ticksWidth, ticksWidth, ticksWidth } ); } @@ -112,7 +112,7 @@ QRectF LightDisplaySkinlet::subControlRect( const QskSkinnable* skinnable, const auto arcMetrics = display->arcMetricsHint( LightDisplay::ColdAndWarmArc ); const auto knobSize = display->strutSizeHint( LightDisplay::Knob ); - const qreal radius = ( arcRect.width() - arcMetrics.width() ) / 2; + const qreal radius = ( arcRect.width() - arcMetrics.thickness() ) / 2; const qreal angle = display->valueAsRatio() * 180; const qreal cos = qFastCos( qDegreesToRadians( angle ) ); diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index 3239a4bf..7c0a845f 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -132,10 +132,10 @@ void Skin::initHints( const Palette& palette ) ed.setGradient( TopBarItem::Item4, 0xff6100ff, 0xff6776ff ); // the bar gradient is defined through the top bar items above - ed.setArcMetrics( CircularProgressBar::Groove, { 8.53, 90, -360 } ); + ed.setArcMetrics( CircularProgressBar::Groove, 90, -360, 8.53 ); // the span angle will be set in the progress bar, we just give a dummy // value here: - ed.setArcMetrics( CircularProgressBar::Bar, { 8.53, 90, -180 } ); + ed.setArcMetrics( CircularProgressBar::Bar, 90, -180, 8.53 ); ed.setFontRole( TimeTitleLabel::Text, Skin::TitleFont ); @@ -237,10 +237,10 @@ void Skin::initHints( const Palette& palette ) // light intensity: ed.setBoxShape( LightDisplay::Panel, 100, Qt::RelativeSize ); - ed.setArcMetrics( LightDisplay::ColdAndWarmArc, 8.785, 0, 180 ); + ed.setArcMetrics( LightDisplay::ColdAndWarmArc, 0, 180, 8.785 ); ed.setMetric( LightDisplay::Tickmarks, 1 ); - ed.setArcMetrics( LightDisplay::Tickmarks, { 4.69, 0, 180 } ); + ed.setArcMetrics( LightDisplay::Tickmarks, 0, 180, 4.69 ); ed.setColor( LightDisplay::Tickmarks, 0x55929cb2 ); ed.setFontRole( LightDisplay::ValueText, QskSkin::LargeFont ); diff --git a/examples/iotdashboard/nodes/RadialTickmarksNode.cpp b/examples/iotdashboard/nodes/RadialTickmarksNode.cpp index 5cc9cb27..4ad7d7ef 100644 --- a/examples/iotdashboard/nodes/RadialTickmarksNode.cpp +++ b/examples/iotdashboard/nodes/RadialTickmarksNode.cpp @@ -46,7 +46,7 @@ void RadialTickmarksNode::update( const QColor& color, const QRectF& rect, const auto center = rect.center(); const auto radius = 0.5 * rect.width(); - const auto needleRadius = radius - arcMetrics.width(); + const auto needleRadius = radius - arcMetrics.thickness(); using TM = QskScaleTickmarks; diff --git a/src/common/QskArcMetrics.cpp b/src/common/QskArcMetrics.cpp index cfc1d452..545ce2ae 100644 --- a/src/common/QskArcMetrics.cpp +++ b/src/common/QskArcMetrics.cpp @@ -31,9 +31,9 @@ static inline qreal qskAbsoluted( qreal length, qreal percentage ) return percentage / 100.0 * 0.5 * length; } -void QskArcMetrics::setWidth( qreal width ) noexcept +void QskArcMetrics::setThickness( qreal thickness ) noexcept { - m_width = width; + m_thickness = thickness; } void QskArcMetrics::setStartAngle( qreal startAngle ) noexcept @@ -57,12 +57,12 @@ QskArcMetrics QskArcMetrics::interpolated( if ( ( *this == to ) || ( m_sizeMode != to.m_sizeMode ) ) return to; - const qreal width = qskInterpolated( m_width, to.m_width, ratio ); + const qreal thickness = qskInterpolated( m_thickness, to.m_thickness, ratio ); const qreal s1 = qskInterpolated( m_startAngle, to.m_startAngle, ratio ); const qreal s2 = qskInterpolated( endAngle(), to.endAngle(), ratio ); - return QskArcMetrics( width, s1, s2 - s1, m_sizeMode ); + return QskArcMetrics( s1, s2 - s1, thickness, m_sizeMode ); } QVariant QskArcMetrics::interpolate( @@ -81,9 +81,9 @@ QskArcMetrics QskArcMetrics::toAbsolute( const QSizeF& size ) const noexcept const auto l = qMin( size.width(), size.height() ); if ( l <= 0.0 ) - absoluted.m_width = 0.0; + absoluted.m_thickness = 0.0; else - absoluted.m_width = qskAbsoluted( l, absoluted.m_width ); + absoluted.m_thickness = qskAbsoluted( l, absoluted.m_thickness ); absoluted.m_sizeMode = Qt::AbsoluteSize; @@ -92,7 +92,7 @@ QskArcMetrics QskArcMetrics::toAbsolute( const QSizeF& size ) const noexcept QskHashValue QskArcMetrics::hash( QskHashValue seed ) const noexcept { - auto hash = qHash( m_width, seed ); + auto hash = qHash( m_thickness, seed ); hash = qHash( m_startAngle, hash ); hash = qHash( m_spanAngle, hash ); @@ -110,7 +110,7 @@ QDebug operator<<( QDebug debug, const QskArcMetrics& metrics ) debug.nospace(); debug << "QskArcMetrics" << '('; - debug << metrics.width() << ',' << metrics.sizeMode(); + debug << metrics.thickness() << ',' << metrics.sizeMode(); debug << ",[" << metrics.startAngle() << ',' << metrics.spanAngle() << ']'; debug << ')'; diff --git a/src/common/QskArcMetrics.h b/src/common/QskArcMetrics.h index 32e324ba..a211bf42 100644 --- a/src/common/QskArcMetrics.h +++ b/src/common/QskArcMetrics.h @@ -16,24 +16,26 @@ class QSK_EXPORT QskArcMetrics { Q_GADGET - Q_PROPERTY( qreal width READ width WRITE setWidth ) Q_PROPERTY( qreal startAngle READ startAngle WRITE setStartAngle ) Q_PROPERTY( qreal spanAngle READ spanAngle WRITE setSpanAngle ) + + Q_PROPERTY( qreal thickness READ thickness WRITE setThickness ) Q_PROPERTY( Qt::SizeMode sizeMode READ sizeMode WRITE setSizeMode ) public: - constexpr QskArcMetrics() noexcept; - constexpr QskArcMetrics( qreal width, qreal startAngle, qreal spanAngle, + constexpr QskArcMetrics() noexcept = default; + + constexpr QskArcMetrics( qreal thickness, Qt::SizeMode = Qt::AbsoluteSize ) noexcept; + constexpr QskArcMetrics( qreal startAngle, qreal spanAngle, + qreal thickness, Qt::SizeMode = Qt::AbsoluteSize ) noexcept; + bool operator==( const QskArcMetrics& ) const noexcept; bool operator!=( const QskArcMetrics& ) const noexcept; constexpr bool isNull() const noexcept; - void setWidth( qreal width ) noexcept; - constexpr qreal width() const noexcept; - void setStartAngle( qreal startAngle ) noexcept; constexpr qreal startAngle() const noexcept; @@ -41,6 +43,10 @@ class QSK_EXPORT QskArcMetrics constexpr qreal spanAngle() const noexcept; constexpr qreal endAngle() const noexcept; + constexpr qreal angleAtRatio( qreal ratio ) const noexcept; + + void setThickness( qreal ) noexcept; + constexpr qreal thickness() const noexcept; void setSizeMode( Qt::SizeMode ) noexcept; constexpr Qt::SizeMode sizeMode() const noexcept; @@ -56,26 +62,25 @@ class QSK_EXPORT QskArcMetrics const QskArcMetrics&, qreal progress ); private: - qreal m_width; - qreal m_startAngle; - qreal m_spanAngle; - Qt::SizeMode m_sizeMode; + qreal m_startAngle = 0.0; + qreal m_spanAngle = 0.0; + + qreal m_thickness = 0.0; + Qt::SizeMode m_sizeMode = Qt::AbsoluteSize; }; -inline constexpr QskArcMetrics::QskArcMetrics() noexcept - : m_width( 0 ) - , m_startAngle( 0 ) - , m_spanAngle( 0 ) - , m_sizeMode( Qt::AbsoluteSize ) +inline constexpr QskArcMetrics::QskArcMetrics( + qreal thickness, Qt::SizeMode sizeMode ) noexcept + : QskArcMetrics( 0.0, 360.0, thickness, sizeMode ) { } inline constexpr QskArcMetrics::QskArcMetrics( - qreal width, qreal startAngle, qreal spanAngle, - Qt::SizeMode sizeMode ) noexcept - : m_width( width ) - , m_startAngle( startAngle ) + qreal startAngle, qreal spanAngle, + qreal thickness, Qt::SizeMode sizeMode ) noexcept + : m_startAngle( startAngle ) , m_spanAngle( spanAngle ) + , m_thickness( thickness ) , m_sizeMode( sizeMode ) { } @@ -83,7 +88,7 @@ inline constexpr QskArcMetrics::QskArcMetrics( inline bool QskArcMetrics::operator==( const QskArcMetrics& other ) const noexcept { - return ( qskFuzzyCompare( m_width, other.m_width ) + return ( qskFuzzyCompare( m_thickness, other.m_thickness ) && qskFuzzyCompare( m_startAngle, other.m_startAngle ) && qskFuzzyCompare( m_spanAngle, other.m_spanAngle ) && m_sizeMode == other.m_sizeMode ); @@ -97,12 +102,12 @@ inline bool QskArcMetrics::operator!=( inline constexpr bool QskArcMetrics::isNull() const noexcept { - return qFuzzyIsNull( m_width ) || qFuzzyIsNull( m_spanAngle ); + return qFuzzyIsNull( m_thickness ) || qFuzzyIsNull( m_spanAngle ); } -inline constexpr qreal QskArcMetrics::width() const noexcept +inline constexpr qreal QskArcMetrics::thickness() const noexcept { - return m_width; + return m_thickness; } inline constexpr qreal QskArcMetrics::startAngle() const noexcept @@ -120,6 +125,11 @@ inline constexpr qreal QskArcMetrics::endAngle() const noexcept return m_startAngle + m_spanAngle; } +inline constexpr qreal QskArcMetrics::angleAtRatio( qreal ratio ) const noexcept +{ + return m_startAngle + ratio * m_spanAngle; +} + inline constexpr Qt::SizeMode QskArcMetrics::sizeMode() const noexcept { return m_sizeMode; diff --git a/src/controls/QskSkinHintTableEditor.cpp b/src/controls/QskSkinHintTableEditor.cpp index aeb2973d..99f402ea 100644 --- a/src/controls/QskSkinHintTableEditor.cpp +++ b/src/controls/QskSkinHintTableEditor.cpp @@ -570,11 +570,11 @@ QColor QskSkinHintTableEditor::shadowColor( QskAspect aspect ) const return colorHint< QColor >( aspectShadow( aspect ) ); } -void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect, qreal width, - qreal startAngle, qreal spanAngle, Qt::SizeMode sizeMode ) +void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect, + qreal startAngle, qreal spanAngle, qreal thickness, Qt::SizeMode sizeMode ) { setMetricHint( aspectShape( aspect ), - QskArcMetrics( width, startAngle, spanAngle, sizeMode ) ); + QskArcMetrics( startAngle, spanAngle, thickness, sizeMode ) ); } void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect, diff --git a/src/controls/QskSkinHintTableEditor.h b/src/controls/QskSkinHintTableEditor.h index 15789364..10565b81 100644 --- a/src/controls/QskSkinHintTableEditor.h +++ b/src/controls/QskSkinHintTableEditor.h @@ -255,7 +255,8 @@ class QSK_EXPORT QskSkinHintTableEditor // arcMetrics - void setArcMetrics( QskAspect, qreal, qreal, qreal, Qt::SizeMode = Qt::AbsoluteSize ); + void setArcMetrics( QskAspect, qreal startAngle, qreal spanAngle, + qreal thickness, Qt::SizeMode = Qt::AbsoluteSize ); void setArcMetrics( QskAspect, const QskArcMetrics&, QskStateCombination = QskStateCombination() ); diff --git a/src/nodes/QskArcNode.cpp b/src/nodes/QskArcNode.cpp index 03b1e4fc..8cff0c36 100644 --- a/src/nodes/QskArcNode.cpp +++ b/src/nodes/QskArcNode.cpp @@ -37,11 +37,10 @@ void QskArcNode::paint( QPainter* painter, const QSize& size, const void* nodeDa { const auto arcData = reinterpret_cast< const ArcData* >( nodeData ); - const qreal w = arcData->metrics.width(); - const QRectF rect( 0.5 * w, 0.5 * w, size.width() - w, size.height() - w ); + const qreal t = arcData->metrics.thickness(); + const QRectF rect( 0.5 * t, 0.5 * t, size.width() - t, size.height() - t ); - QskArcRenderer renderer; - renderer.renderArc( rect, arcData->metrics, arcData->gradient, painter ); + QskArcRenderer::renderArc( rect, arcData->metrics, arcData->gradient, painter ); } QskHashValue QskArcNode::hash( const void* nodeData ) const diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index 21c8693d..0b16eec9 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -45,7 +45,7 @@ void QskArcRenderer::renderArc(const QRectF& rect, } painter->setRenderHint( QPainter::Antialiasing, true ); - painter->setPen( QPen( brush, metrics.width(), Qt::SolidLine, Qt::FlatCap ) ); + painter->setPen( QPen( brush, metrics.thickness(), Qt::SolidLine, Qt::FlatCap ) ); const int startAngle = qRound( metrics.startAngle() * 16 ); const int spanAngle = qRound( metrics.spanAngle() * 16 ); diff --git a/src/nodes/QskArcRenderer.h b/src/nodes/QskArcRenderer.h index 3b0f360b..2ce8587d 100644 --- a/src/nodes/QskArcRenderer.h +++ b/src/nodes/QskArcRenderer.h @@ -14,10 +14,9 @@ class QskGradient; class QPainter; class QRectF; -class QSK_EXPORT QskArcRenderer +namespace QskArcRenderer { - public: - void renderArc( const QRectF&, const QskArcMetrics&, + QSK_EXPORT void renderArc( const QRectF&, const QskArcMetrics&, const QskGradient&, QPainter* ); };