diff --git a/examples/iotdashboard/LightDisplaySkinlet.cpp b/examples/iotdashboard/LightDisplaySkinlet.cpp index 865ae2b5..44d98e6b 100644 --- a/examples/iotdashboard/LightDisplaySkinlet.cpp +++ b/examples/iotdashboard/LightDisplaySkinlet.cpp @@ -135,27 +135,21 @@ QSGNode* LightDisplaySkinlet::updateSubNode( { return updateBoxNode( skinnable, node, LightDisplay::Panel ); } -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) case GrooveRole: { const QRectF grooveRect = display->subControlRect( LightDisplay::Groove ); if ( grooveRect.isEmpty() ) return nullptr; - auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node ); - const auto& shadowMetrics = display->shadow(); + const auto shadowRect = shadowMetrics.shadowRect( grooveRect ); - shadowNode->setRect( shadowMetrics.shadowRect( grooveRect ) ); - shadowNode->setShape( grooveRect.width() / 2 ); - shadowNode->setBlurRadius( shadowMetrics.blurRadius() ); - shadowNode->setColor( display->shadowColor() ); - - shadowNode->updateGeometry(); + auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node ); + shadowNode->setShadowData( shadowRect, grooveRect.width() / 2, + shadowMetrics.blurRadius(), display->shadowColor() ); return shadowNode; } -#endif case ColdAndWarmArcRole: { return updateArcNode( skinnable, node, LightDisplay::ColdAndWarmArc ); diff --git a/examples/iotdashboard/ShadowedBox.cpp b/examples/iotdashboard/ShadowedBox.cpp index de723f20..d89646ae 100644 --- a/examples/iotdashboard/ShadowedBox.cpp +++ b/examples/iotdashboard/ShadowedBox.cpp @@ -55,12 +55,8 @@ namespace auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node ); - shadowNode->setRect( shadowMetrics.shadowRect( r ) ); - shadowNode->setShape( box->shape() ); - shadowNode->setBlurRadius( shadowMetrics.blurRadius() ); - shadowNode->setColor( box->shadowColor() ); - - shadowNode->updateGeometry(); + shadowNode->setShadowData( shadowMetrics.shadowRect( r ), + box->shape(), shadowMetrics.blurRadius(), box->shadowColor() ); return shadowNode; } diff --git a/src/controls/QskPushButtonSkinlet.cpp b/src/controls/QskPushButtonSkinlet.cpp index b7fd445c..3eb73fbe 100644 --- a/src/controls/QskPushButtonSkinlet.cpp +++ b/src/controls/QskPushButtonSkinlet.cpp @@ -12,6 +12,19 @@ #include #include +static inline Qt::Orientation qskOrientation( const QskPushButton* button ) +{ + // For the moment we only handle the orientation TODO ... + + const auto direction = button->flagHint( + QskPushButton::Panel | QskAspect::Direction, Qsk::LeftToRight ); + + if ( direction == Qsk::LeftToRight || direction == Qsk::RightToLeft ) + return Qt::Horizontal; + else + return Qt::Vertical; +} + QskPushButtonSkinlet::QskPushButtonSkinlet( QskSkin* skin ) : Inherited( skin ) { @@ -71,29 +84,24 @@ QSGNode* QskPushButtonSkinlet::updateSubNode( QRectF QskPushButtonSkinlet::textRect( const QskPushButton* button, const QRectF& contentsRect ) const { - // buttonShift -> TODO + using Q = QskPushButton; - auto r = button->subControlContentsRect( contentsRect, QskPushButton::Panel ); + auto r = button->subControlContentsRect( contentsRect, Q::Panel ); if ( button->hasGraphic() ) { - const auto orientation = button->flagHint( QskPushButton::Panel | QskAspect::Direction, Qsk::LeftToRight ); - - switch( orientation ) + if ( qskOrientation( button ) == Qt::Horizontal ) { - case Qsk::LeftToRight: - { - const auto graphicsRect = subControlRect( button, contentsRect, QskPushButton::Graphic ); - const auto spacing = button->metric( QskPushButton::Panel | QskAspect::Spacing ); - r.setX( r.x() + graphicsRect.width() + spacing ); - break; - } - default: // Qsk::TopToBottom, the other ones are not handled yet - { - qreal h = button->effectiveFontHeight( QskPushButton::Text ); - if ( h < r.height() ) - r.setTop( r.bottom() - h ); - } + const auto graphicsRect = subControlRect( button, contentsRect, Q::Graphic ); + const auto spacing = button->spacingHint( Q::Panel ); + + r.setX( r.x() + graphicsRect.width() + spacing ); + } + else + { + const qreal h = button->effectiveFontHeight( Q::Text ); + if ( h < r.height() ) + r.setTop( r.bottom() - h ); } } @@ -103,17 +111,16 @@ QRectF QskPushButtonSkinlet::textRect( QRectF QskPushButtonSkinlet::graphicRect( const QskPushButton* button, const QRectF& contentsRect ) const { - // buttonShift -> TODO + using Q = QskPushButton; - auto r = button->subControlContentsRect( contentsRect, QskPushButton::Panel ); + auto r = button->subControlContentsRect( contentsRect, Q::Panel ); - const auto orientation = button->flagHint( QskPushButton::Panel - | QskAspect::Direction, Qsk::LeftToRight ); + const auto orientation = qskOrientation( button ); - if ( !button->text().isEmpty() && orientation == Qsk::TopToBottom ) + if ( !button->text().isEmpty() && orientation == Qt::Vertical ) { - const auto textRect = subControlRect( button, contentsRect, QskPushButton::Text ); - qreal h = textRect.height() + button->spacingHint( QskPushButton::Panel ); + const auto textRect = subControlRect( button, contentsRect, Q::Text ); + qreal h = textRect.height() + button->spacingHint( Q::Panel ); if ( h < r.height() ) r.setBottom( r.bottom() - h ); @@ -142,7 +149,7 @@ QRectF QskPushButtonSkinlet::graphicRect( } } - const QSizeF sz = button->graphic().defaultSize(); + const auto sz = button->graphic().defaultSize(); if ( !( r.isEmpty() || sz.isEmpty() ) ) { @@ -155,29 +162,23 @@ QRectF QskPushButtonSkinlet::graphicRect( const int h = qFloor( scaleFactor * sz.height() ); int x, y; - const auto orientation = button->flagHint( QskPushButton::Panel - | QskAspect::Direction, Qsk::LeftToRight ); - - switch( orientation ) + if ( orientation == Qt::Horizontal ) { - case Qsk::LeftToRight: - { - x = r.left(); - y = r.top(); - break; - } - default: // TopToBottom - { - // early aligning to avoid pointless operations, that finally will - // have no effect, when drawing to an integer based paint device + x = r.left(); + y = r.top(); + } + else + { + // early aligning to avoid pointless operations, that finally will + // have no effect, when drawing to an integer based paint device - x = qFloor( r.center().x() - 0.5 * w ); - y = qFloor( r.center().y() - 0.5 * h ); - } + x = qFloor( r.center().x() - 0.5 * w ); + y = qFloor( r.center().y() - 0.5 * h ); } r = QRectF( x, y, w, h ); - const auto padding = button->paddingHint( QskPushButton::Graphic ); + + const auto padding = button->paddingHint( Q::Graphic ); r = r.marginsRemoved( padding ); } @@ -187,21 +188,25 @@ QRectF QskPushButtonSkinlet::graphicRect( QSGNode* QskPushButtonSkinlet::updateTextNode( const QskPushButton* button, QSGNode* node ) const { - const auto rect = button->subControlRect( QskPushButton::Text ).toAlignedRect(); + using Q = QskPushButton; - const auto textHeight = button->effectiveFontHeight( QskPushButton::Text ); + const auto rect = button->subControlRect( Q::Text ).toAlignedRect(); + + const auto textHeight = button->effectiveFontHeight( Q::Text ); if ( !button->clip() && ( rect.height() < textHeight ) ) return nullptr; - const auto alignment = button->alignmentHint( QskPushButton::Text, Qt::AlignCenter ); + const auto alignment = button->alignmentHint( Q::Text, Qt::AlignCenter ); return QskSkinlet::updateTextNode( button, node, rect, alignment, - button->text(), button->textOptions(), QskPushButton::Text ); + button->text(), button->textOptions(), Q::Text ); } QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable, Qt::SizeHint which, const QSizeF& ) const { + using Q = QskPushButton; + if ( which != Qt::PreferredSize ) return QSizeF(); @@ -249,29 +254,23 @@ QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable, } } - const QMarginsF padding = button->paddingHint( QskPushButton::Graphic ); + const auto padding = button->paddingHint( Q::Graphic ); + const auto orientation = qskOrientation( button ); - const auto orientation = button->flagHint( QskPushButton::Panel - | QskAspect::Direction, Qsk::LeftToRight ); - - switch( orientation ) + if( orientation == Qt::Horizontal ) { - case Qsk::LeftToRight: - { - size.rwidth() += padding.left() + w + padding.right(); - size.rheight() = qMax( size.height(), h ); - break; - } - default: // TopToBottom - { - size.rheight() += padding.top() + h + padding.bottom(); - size.rwidth() = qMax( size.width(), w ); - } + size.rwidth() += padding.left() + w + padding.right(); + size.rheight() = qMax( size.height(), h ); + } + else + { + size.rheight() += padding.top() + h + padding.bottom(); + size.rwidth() = qMax( size.width(), w ); } } - size = size.expandedTo( button->strutSizeHint( QskPushButton::Panel ) ); - size = button->outerBoxSize( QskPushButton::Panel, size ); + size = size.expandedTo( button->strutSizeHint( Q::Panel ) ); + size = button->outerBoxSize( Q::Panel, size ); return size; } diff --git a/src/nodes/QskBoxShadowNode.cpp b/src/nodes/QskBoxShadowNode.cpp index 0c519c79..44a1af50 100644 --- a/src/nodes/QskBoxShadowNode.cpp +++ b/src/nodes/QskBoxShadowNode.cpp @@ -268,98 +268,77 @@ QskBoxShadowNode::~QskBoxShadowNode() { } -void QskBoxShadowNode::setRect( const QRectF& rect ) +void QskBoxShadowNode::setShadowData( + const QRectF& rect, const QskBoxShapeMetrics& shape, + qreal blurRadius, const QColor& color ) { Q_D( QskBoxShadowNode ); - if ( rect == d->rect ) - return; - - d->rect = rect; - - QVector2D aspect( 1.0, 1.0 ); - - if ( rect.width() >= rect.height() ) - aspect.setX( rect.width() / rect.height() ); - else - aspect.setY( rect.height() / rect.width() ); - - if ( d->material.m_aspect != aspect ) + if ( rect != d->rect ) { - d->material.m_aspect = aspect; - markDirty( QSGNode::DirtyMaterial ); + d->rect = rect; + + QSGGeometry::updateTexturedRectGeometry( + &d->geometry, d->rect, QRectF( -0.5, -0.5, 1.0, 1.0 ) ); + + markDirty( QSGNode::DirtyGeometry ); + + QVector2D aspect( 1.0, 1.0 ); + + if ( rect.width() >= rect.height() ) + aspect.setX( rect.width() / rect.height() ); + else + aspect.setY( rect.height() / rect.width() ); + + if ( d->material.m_aspect != aspect ) + { + d->material.m_aspect = aspect; + markDirty( QSGNode::DirtyMaterial ); + } + } + + { + const float t = std::min( d->rect.width(), d->rect.height() ); + + const float r1 = shape.radius( Qt::BottomRightCorner ).width(); + const float r2 = shape.radius( Qt::TopRightCorner ).width(); + const float r3 = shape.radius( Qt::BottomLeftCorner ).width(); + const float r4 = shape.radius( Qt::TopLeftCorner ).width(); + + const auto uniformRadius = QVector4D( + std::min( r1 / t, 1.0f ), std::min( r2 / t, 1.0f ), + std::min( r3 / t, 1.0f ), std::min( r4 / t, 1.0f ) ); + + if ( d->material.m_radius != uniformRadius ) + { + d->material.m_radius = uniformRadius; + markDirty( QSGNode::DirtyMaterial ); + } + } + + { + if ( blurRadius <= 0.0 ) + blurRadius = 0.0; + + const float t = 0.5 * std::min( d->rect.width(), d->rect.height() ); + const float uniformExtent = blurRadius / t; + + if ( !qFuzzyCompare( d->material.m_blurExtent, uniformExtent ) ) + { + d->material.m_blurExtent = uniformExtent; + markDirty( QSGNode::DirtyMaterial ); + } + } + + { + const auto a = color.alphaF(); + + const QVector4D c( color.redF() * a, color.greenF() * a, color.blueF() * a, a ); + + if ( d->material.m_color != c ) + { + d->material.m_color = c; + markDirty( QSGNode::DirtyMaterial ); + } } } - -void QskBoxShadowNode::setShape( const QskBoxShapeMetrics& shape ) -{ - Q_D( QskBoxShadowNode ); - - const float t = std::min( d->rect.width(), d->rect.height() ); - - const float r1 = shape.radius( Qt::BottomRightCorner ).width(); - const float r2 = shape.radius( Qt::TopRightCorner ).width(); - const float r3 = shape.radius( Qt::BottomLeftCorner ).width(); - const float r4 = shape.radius( Qt::TopLeftCorner ).width(); - - const auto uniformRadius = QVector4D( - std::min( r1 / t, 1.0f ), std::min( r2 / t, 1.0f ), - std::min( r3 / t, 1.0f ), std::min( r4 / t, 1.0f ) ); - - if ( d->material.m_radius != uniformRadius ) - { - d->material.m_radius = uniformRadius; - - markDirty( QSGNode::DirtyMaterial ); - } -} - -void QskBoxShadowNode::setColor( const QColor& color ) -{ - Q_D( QskBoxShadowNode ); - - const auto a = color.alphaF(); - - const QVector4D c( color.redF() * a, color.greenF() * a, color.blueF() * a, a ); - - if ( d->material.m_color != c ) - { - d->material.m_color = c; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void QskBoxShadowNode::setBlurRadius( qreal blurRadius ) -{ - Q_D( QskBoxShadowNode ); - - if ( blurRadius <= 0.0 ) - blurRadius = 0.0; - - const float t = 0.5 * std::min( d->rect.width(), d->rect.height() ); - const float uniformExtent = blurRadius / t; - - if ( !qFuzzyCompare( d->material.m_blurExtent, uniformExtent ) ) - { - d->material.m_blurExtent = uniformExtent; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void QskBoxShadowNode::setClipShape( const QskBoxShapeMetrics& ) -{ - /* - Usually only the parts, that are not covered by the related box - should be painted. TODO ... - */ -} - -void QskBoxShadowNode::updateGeometry() -{ - Q_D( QskBoxShadowNode ); - - QSGGeometry::updateTexturedRectGeometry( - &d->geometry, d->rect, QRectF( -0.5, -0.5, 1.0, 1.0 ) ); - - markDirty( QSGNode::DirtyGeometry ); -} diff --git a/src/nodes/QskBoxShadowNode.h b/src/nodes/QskBoxShadowNode.h index 25f09a10..56c8c0ca 100644 --- a/src/nodes/QskBoxShadowNode.h +++ b/src/nodes/QskBoxShadowNode.h @@ -20,14 +20,8 @@ class QSK_EXPORT QskBoxShadowNode : public QSGGeometryNode QskBoxShadowNode(); ~QskBoxShadowNode() override; - void setRect( const QRectF& ); - void setShape( const QskBoxShapeMetrics& ); - void setColor( const QColor& ); - void setBlurRadius( qreal ); - - void setClipShape( const QskBoxShapeMetrics& ); - - void updateGeometry(); + void setShadowData( const QRectF&, const QskBoxShapeMetrics&, + qreal blurRadius, const QColor& ); private: Q_DECLARE_PRIVATE( QskBoxShadowNode ) diff --git a/src/nodes/QskShadedBoxNode.cpp b/src/nodes/QskShadedBoxNode.cpp index 31bc7db7..1361cbfb 100644 --- a/src/nodes/QskShadedBoxNode.cpp +++ b/src/nodes/QskShadedBoxNode.cpp @@ -24,14 +24,9 @@ void QskShadedBoxNode::setBoxData( const QRectF& rect, const QskShadowMetrics& shadowMetrics, const QColor& shadowColor ) { m_boxNode.setBoxData( rect, shape, borderMetrics, borderColors, gradient ); - setShadowData( rect, shape, shadowMetrics, shadowColor ); -} -void QskShadedBoxNode::setShadowData( - const QRectF& rect, const QskBoxShapeMetrics& shape, - const QskShadowMetrics& metrics, const QColor& color ) -{ - if ( metrics.isNull() || !color.isValid() || color.alpha() == 0 ) + if ( shadowMetrics.isNull() + || !shadowColor.isValid() || shadowColor.alpha() == 0 ) { if ( m_shadowNode ) { @@ -48,13 +43,7 @@ void QskShadedBoxNode::setShadowData( insertChildNodeBefore( m_shadowNode, &m_boxNode ); } - m_shadowNode->setColor( color ); - - m_shadowNode->setRect( metrics.shadowRect( rect ) ); - m_shadowNode->setShape( shape ); - m_shadowNode->setBlurRadius( metrics.blurRadius() ); - m_shadowNode->setClipShape( shape ); - - m_shadowNode->updateGeometry(); + m_shadowNode->setShadowData( shadowMetrics.shadowRect( rect ), + shape, shadowMetrics.blurRadius(), shadowColor ); } } diff --git a/src/nodes/QskShadedBoxNode.h b/src/nodes/QskShadedBoxNode.h index cfff372f..3092b112 100644 --- a/src/nodes/QskShadedBoxNode.h +++ b/src/nodes/QskShadedBoxNode.h @@ -24,9 +24,6 @@ class QSK_EXPORT QskShadedBoxNode : public QSGNode const QskShadowMetrics&, const QColor& shadowColor ); private: - void setShadowData( const QRectF&, const QskBoxShapeMetrics&, - const QskShadowMetrics&, const QColor& ); - QskBoxNode m_boxNode; QskBoxShadowNode* m_shadowNode = nullptr; };