API of classes dealing with arcs improved

This commit is contained in:
Uwe Rathmann 2023-04-11 13:04:10 +02:00
parent 8dbe622af1
commit 7ddae671e2
11 changed files with 66 additions and 57 deletions

View File

@ -152,7 +152,7 @@ bool LightDisplay::arcContainsPoint( const QRectF& rect, const QPointF& point )
// 2. check whether point is on arc // 2. check whether point is on arc
const qreal radiusMax = rect.width() / 2; const qreal radiusMax = rect.width() / 2;
const qreal arcWidth = metrics.width(); const qreal arcWidth = metrics.thickness();
const qreal radiusMin = radiusMax - arcWidth; const qreal radiusMin = radiusMax - arcWidth;
const qreal polarRadius = qSqrt( qPow( circlePos.x(), 2 ) + qPow( circlePos.y(), 2 ) ); const qreal polarRadius = qSqrt( qPow( circlePos.x(), 2 ) + qPow( circlePos.y(), 2 ) );

View File

@ -39,13 +39,13 @@ QRectF LightDisplaySkinlet::subControlRect( const QskSkinnable* skinnable,
const auto textSize = textLabelsSize( display ); const auto textSize = textLabelsSize( display );
const auto arcMetrics = display->arcMetricsHint( LightDisplay::ColdAndWarmArc ); const auto arcMetrics = display->arcMetricsHint( LightDisplay::ColdAndWarmArc );
const qreal ticksWidth = display->arcMetricsHint( 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() - const qreal w = contentsRect.width() -
( 2 * ( textSize.width() + arcMetrics.width() + ticksWidth ) ); ( 2 * ( textSize.width() + arcMetrics.thickness() + ticksWidth ) );
const qreal y = arcMetrics.width() + ticksWidth; const qreal y = arcMetrics.thickness() + ticksWidth;
const qreal h = contentsRect.height() - 2 * ( arcMetrics.width() + ticksWidth ); const qreal h = contentsRect.height() - 2 * ( arcMetrics.thickness() + ticksWidth );
const qreal diameter = qMin( w, h ); const qreal diameter = qMin( w, h );
@ -54,7 +54,7 @@ QRectF LightDisplaySkinlet::subControlRect( const QskSkinnable* skinnable,
else if( subControl == LightDisplay::ColdAndWarmArc ) else if( subControl == LightDisplay::ColdAndWarmArc )
{ {
const QRectF panelRect = subControlRect( skinnable, contentsRect, LightDisplay::Panel ); 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 } ); return panelRect.marginsAdded( { barWidth, barWidth, barWidth, barWidth } );
} }
@ -63,7 +63,7 @@ QRectF LightDisplaySkinlet::subControlRect( const QskSkinnable* skinnable,
const auto arcRect = subControlRect( const auto arcRect = subControlRect(
skinnable, contentsRect, LightDisplay::ColdAndWarmArc ); skinnable, contentsRect, LightDisplay::ColdAndWarmArc );
const qreal ticksWidth = display->arcMetricsHint( const qreal ticksWidth = display->arcMetricsHint(
LightDisplay::Tickmarks ).width() + ticksSpacing; LightDisplay::Tickmarks ).thickness() + ticksSpacing;
return arcRect.marginsAdded( { ticksWidth, ticksWidth, ticksWidth, ticksWidth } ); 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 arcMetrics = display->arcMetricsHint( LightDisplay::ColdAndWarmArc );
const auto knobSize = display->strutSizeHint( LightDisplay::Knob ); 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 angle = display->valueAsRatio() * 180;
const qreal cos = qFastCos( qDegreesToRadians( angle ) ); const qreal cos = qFastCos( qDegreesToRadians( angle ) );

View File

@ -132,10 +132,10 @@ void Skin::initHints( const Palette& palette )
ed.setGradient( TopBarItem::Item4, 0xff6100ff, 0xff6776ff ); ed.setGradient( TopBarItem::Item4, 0xff6100ff, 0xff6776ff );
// the bar gradient is defined through the top bar items above // 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 // the span angle will be set in the progress bar, we just give a dummy
// value here: // value here:
ed.setArcMetrics( CircularProgressBar::Bar, { 8.53, 90, -180 } ); ed.setArcMetrics( CircularProgressBar::Bar, 90, -180, 8.53 );
ed.setFontRole( TimeTitleLabel::Text, Skin::TitleFont ); ed.setFontRole( TimeTitleLabel::Text, Skin::TitleFont );
@ -237,10 +237,10 @@ void Skin::initHints( const Palette& palette )
// light intensity: // light intensity:
ed.setBoxShape( LightDisplay::Panel, 100, Qt::RelativeSize ); 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.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.setColor( LightDisplay::Tickmarks, 0x55929cb2 );
ed.setFontRole( LightDisplay::ValueText, QskSkin::LargeFont ); ed.setFontRole( LightDisplay::ValueText, QskSkin::LargeFont );

View File

@ -46,7 +46,7 @@ void RadialTickmarksNode::update( const QColor& color, const QRectF& rect,
const auto center = rect.center(); const auto center = rect.center();
const auto radius = 0.5 * rect.width(); const auto radius = 0.5 * rect.width();
const auto needleRadius = radius - arcMetrics.width(); const auto needleRadius = radius - arcMetrics.thickness();
using TM = QskScaleTickmarks; using TM = QskScaleTickmarks;

View File

@ -31,9 +31,9 @@ static inline qreal qskAbsoluted( qreal length, qreal percentage )
return percentage / 100.0 * 0.5 * length; 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 void QskArcMetrics::setStartAngle( qreal startAngle ) noexcept
@ -57,12 +57,12 @@ QskArcMetrics QskArcMetrics::interpolated(
if ( ( *this == to ) || ( m_sizeMode != to.m_sizeMode ) ) if ( ( *this == to ) || ( m_sizeMode != to.m_sizeMode ) )
return to; 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 s1 = qskInterpolated( m_startAngle, to.m_startAngle, ratio );
const qreal s2 = qskInterpolated( endAngle(), to.endAngle(), 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( QVariant QskArcMetrics::interpolate(
@ -81,9 +81,9 @@ QskArcMetrics QskArcMetrics::toAbsolute( const QSizeF& size ) const noexcept
const auto l = qMin( size.width(), size.height() ); const auto l = qMin( size.width(), size.height() );
if ( l <= 0.0 ) if ( l <= 0.0 )
absoluted.m_width = 0.0; absoluted.m_thickness = 0.0;
else else
absoluted.m_width = qskAbsoluted( l, absoluted.m_width ); absoluted.m_thickness = qskAbsoluted( l, absoluted.m_thickness );
absoluted.m_sizeMode = Qt::AbsoluteSize; absoluted.m_sizeMode = Qt::AbsoluteSize;
@ -92,7 +92,7 @@ QskArcMetrics QskArcMetrics::toAbsolute( const QSizeF& size ) const noexcept
QskHashValue QskArcMetrics::hash( QskHashValue seed ) 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_startAngle, hash );
hash = qHash( m_spanAngle, hash ); hash = qHash( m_spanAngle, hash );
@ -110,7 +110,7 @@ QDebug operator<<( QDebug debug, const QskArcMetrics& metrics )
debug.nospace(); debug.nospace();
debug << "QskArcMetrics" << '('; debug << "QskArcMetrics" << '(';
debug << metrics.width() << ',' << metrics.sizeMode(); debug << metrics.thickness() << ',' << metrics.sizeMode();
debug << ",[" << metrics.startAngle() << ',' << metrics.spanAngle() << ']'; debug << ",[" << metrics.startAngle() << ',' << metrics.spanAngle() << ']';
debug << ')'; debug << ')';

View File

@ -16,24 +16,26 @@ class QSK_EXPORT QskArcMetrics
{ {
Q_GADGET Q_GADGET
Q_PROPERTY( qreal width READ width WRITE setWidth )
Q_PROPERTY( qreal startAngle READ startAngle WRITE setStartAngle ) Q_PROPERTY( qreal startAngle READ startAngle WRITE setStartAngle )
Q_PROPERTY( qreal spanAngle READ spanAngle WRITE setSpanAngle ) 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 ) Q_PROPERTY( Qt::SizeMode sizeMode READ sizeMode WRITE setSizeMode )
public: public:
constexpr QskArcMetrics() noexcept; constexpr QskArcMetrics() noexcept = default;
constexpr QskArcMetrics( qreal width, qreal startAngle, qreal spanAngle,
constexpr QskArcMetrics( qreal thickness,
Qt::SizeMode = Qt::AbsoluteSize ) noexcept; 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;
bool operator!=( const QskArcMetrics& ) const noexcept; bool operator!=( const QskArcMetrics& ) const noexcept;
constexpr bool isNull() const noexcept; constexpr bool isNull() const noexcept;
void setWidth( qreal width ) noexcept;
constexpr qreal width() const noexcept;
void setStartAngle( qreal startAngle ) noexcept; void setStartAngle( qreal startAngle ) noexcept;
constexpr qreal startAngle() const noexcept; constexpr qreal startAngle() const noexcept;
@ -41,6 +43,10 @@ class QSK_EXPORT QskArcMetrics
constexpr qreal spanAngle() const noexcept; constexpr qreal spanAngle() const noexcept;
constexpr qreal endAngle() 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; void setSizeMode( Qt::SizeMode ) noexcept;
constexpr Qt::SizeMode sizeMode() const noexcept; constexpr Qt::SizeMode sizeMode() const noexcept;
@ -56,26 +62,25 @@ class QSK_EXPORT QskArcMetrics
const QskArcMetrics&, qreal progress ); const QskArcMetrics&, qreal progress );
private: private:
qreal m_width; qreal m_startAngle = 0.0;
qreal m_startAngle; qreal m_spanAngle = 0.0;
qreal m_spanAngle;
Qt::SizeMode m_sizeMode; qreal m_thickness = 0.0;
Qt::SizeMode m_sizeMode = Qt::AbsoluteSize;
}; };
inline constexpr QskArcMetrics::QskArcMetrics() noexcept inline constexpr QskArcMetrics::QskArcMetrics(
: m_width( 0 ) qreal thickness, Qt::SizeMode sizeMode ) noexcept
, m_startAngle( 0 ) : QskArcMetrics( 0.0, 360.0, thickness, sizeMode )
, m_spanAngle( 0 )
, m_sizeMode( Qt::AbsoluteSize )
{ {
} }
inline constexpr QskArcMetrics::QskArcMetrics( inline constexpr QskArcMetrics::QskArcMetrics(
qreal width, qreal startAngle, qreal spanAngle, qreal startAngle, qreal spanAngle,
Qt::SizeMode sizeMode ) noexcept qreal thickness, Qt::SizeMode sizeMode ) noexcept
: m_width( width ) : m_startAngle( startAngle )
, m_startAngle( startAngle )
, m_spanAngle( spanAngle ) , m_spanAngle( spanAngle )
, m_thickness( thickness )
, m_sizeMode( sizeMode ) , m_sizeMode( sizeMode )
{ {
} }
@ -83,7 +88,7 @@ inline constexpr QskArcMetrics::QskArcMetrics(
inline bool QskArcMetrics::operator==( inline bool QskArcMetrics::operator==(
const QskArcMetrics& other ) const noexcept 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_startAngle, other.m_startAngle )
&& qskFuzzyCompare( m_spanAngle, other.m_spanAngle ) && qskFuzzyCompare( m_spanAngle, other.m_spanAngle )
&& m_sizeMode == other.m_sizeMode ); && m_sizeMode == other.m_sizeMode );
@ -97,12 +102,12 @@ inline bool QskArcMetrics::operator!=(
inline constexpr bool QskArcMetrics::isNull() const noexcept 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 inline constexpr qreal QskArcMetrics::startAngle() const noexcept
@ -120,6 +125,11 @@ inline constexpr qreal QskArcMetrics::endAngle() const noexcept
return m_startAngle + m_spanAngle; 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 inline constexpr Qt::SizeMode QskArcMetrics::sizeMode() const noexcept
{ {
return m_sizeMode; return m_sizeMode;

View File

@ -570,11 +570,11 @@ QColor QskSkinHintTableEditor::shadowColor( QskAspect aspect ) const
return colorHint< QColor >( aspectShadow( aspect ) ); return colorHint< QColor >( aspectShadow( aspect ) );
} }
void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect, qreal width, void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect,
qreal startAngle, qreal spanAngle, Qt::SizeMode sizeMode ) qreal startAngle, qreal spanAngle, qreal thickness, Qt::SizeMode sizeMode )
{ {
setMetricHint( aspectShape( aspect ), setMetricHint( aspectShape( aspect ),
QskArcMetrics( width, startAngle, spanAngle, sizeMode ) ); QskArcMetrics( startAngle, spanAngle, thickness, sizeMode ) );
} }
void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect, void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect,

View File

@ -255,7 +255,8 @@ class QSK_EXPORT QskSkinHintTableEditor
// arcMetrics // 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, void setArcMetrics( QskAspect,
const QskArcMetrics&, QskStateCombination = QskStateCombination() ); const QskArcMetrics&, QskStateCombination = QskStateCombination() );

View File

@ -37,11 +37,10 @@ void QskArcNode::paint( QPainter* painter, const QSize& size, const void* nodeDa
{ {
const auto arcData = reinterpret_cast< const ArcData* >( nodeData ); const auto arcData = reinterpret_cast< const ArcData* >( nodeData );
const qreal w = arcData->metrics.width(); const qreal t = arcData->metrics.thickness();
const QRectF rect( 0.5 * w, 0.5 * w, size.width() - w, size.height() - w ); const QRectF rect( 0.5 * t, 0.5 * t, size.width() - t, size.height() - t );
QskArcRenderer renderer; QskArcRenderer::renderArc( rect, arcData->metrics, arcData->gradient, painter );
renderer.renderArc( rect, arcData->metrics, arcData->gradient, painter );
} }
QskHashValue QskArcNode::hash( const void* nodeData ) const QskHashValue QskArcNode::hash( const void* nodeData ) const

View File

@ -45,7 +45,7 @@ void QskArcRenderer::renderArc(const QRectF& rect,
} }
painter->setRenderHint( QPainter::Antialiasing, true ); 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 startAngle = qRound( metrics.startAngle() * 16 );
const int spanAngle = qRound( metrics.spanAngle() * 16 ); const int spanAngle = qRound( metrics.spanAngle() * 16 );

View File

@ -14,10 +14,9 @@ class QskGradient;
class QPainter; class QPainter;
class QRectF; class QRectF;
class QSK_EXPORT QskArcRenderer namespace QskArcRenderer
{ {
public: QSK_EXPORT void renderArc( const QRectF&, const QskArcMetrics&,
void renderArc( const QRectF&, const QskArcMetrics&,
const QskGradient&, QPainter* ); const QskGradient&, QPainter* );
}; };