Merge branch 'uwerat-master' into material-theme

This commit is contained in:
Peter Hartmann 2022-06-15 14:37:49 +02:00
commit d88edb3a02
7 changed files with 145 additions and 197 deletions

View File

@ -135,27 +135,21 @@ QSGNode* LightDisplaySkinlet::updateSubNode(
{ {
return updateBoxNode( skinnable, node, LightDisplay::Panel ); return updateBoxNode( skinnable, node, LightDisplay::Panel );
} }
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
case GrooveRole: case GrooveRole:
{ {
const QRectF grooveRect = display->subControlRect( LightDisplay::Groove ); const QRectF grooveRect = display->subControlRect( LightDisplay::Groove );
if ( grooveRect.isEmpty() ) if ( grooveRect.isEmpty() )
return nullptr; return nullptr;
auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node );
const auto& shadowMetrics = display->shadow(); const auto& shadowMetrics = display->shadow();
const auto shadowRect = shadowMetrics.shadowRect( grooveRect );
shadowNode->setRect( shadowMetrics.shadowRect( grooveRect ) ); auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node );
shadowNode->setShape( grooveRect.width() / 2 ); shadowNode->setShadowData( shadowRect, grooveRect.width() / 2,
shadowNode->setBlurRadius( shadowMetrics.blurRadius() ); shadowMetrics.blurRadius(), display->shadowColor() );
shadowNode->setColor( display->shadowColor() );
shadowNode->updateGeometry();
return shadowNode; return shadowNode;
} }
#endif
case ColdAndWarmArcRole: case ColdAndWarmArcRole:
{ {
return updateArcNode( skinnable, node, LightDisplay::ColdAndWarmArc ); return updateArcNode( skinnable, node, LightDisplay::ColdAndWarmArc );

View File

@ -55,12 +55,8 @@ namespace
auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node ); auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node );
shadowNode->setRect( shadowMetrics.shadowRect( r ) ); shadowNode->setShadowData( shadowMetrics.shadowRect( r ),
shadowNode->setShape( box->shape() ); box->shape(), shadowMetrics.blurRadius(), box->shadowColor() );
shadowNode->setBlurRadius( shadowMetrics.blurRadius() );
shadowNode->setColor( box->shadowColor() );
shadowNode->updateGeometry();
return shadowNode; return shadowNode;
} }

View File

@ -12,6 +12,19 @@
#include <qfontmetrics.h> #include <qfontmetrics.h>
#include <qmath.h> #include <qmath.h>
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 ) QskPushButtonSkinlet::QskPushButtonSkinlet( QskSkin* skin )
: Inherited( skin ) : Inherited( skin )
{ {
@ -71,29 +84,24 @@ QSGNode* QskPushButtonSkinlet::updateSubNode(
QRectF QskPushButtonSkinlet::textRect( QRectF QskPushButtonSkinlet::textRect(
const QskPushButton* button, const QRectF& contentsRect ) const 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() ) if ( button->hasGraphic() )
{ {
const auto orientation = button->flagHint( QskPushButton::Panel | QskAspect::Direction, Qsk::LeftToRight ); if ( qskOrientation( button ) == Qt::Horizontal )
switch( orientation )
{ {
case Qsk::LeftToRight: const auto graphicsRect = subControlRect( button, contentsRect, Q::Graphic );
{ const auto spacing = button->spacingHint( Q::Panel );
const auto graphicsRect = subControlRect( button, contentsRect, QskPushButton::Graphic );
const auto spacing = button->metric( QskPushButton::Panel | QskAspect::Spacing ); r.setX( r.x() + graphicsRect.width() + spacing );
r.setX( r.x() + graphicsRect.width() + spacing ); }
break; else
} {
default: // Qsk::TopToBottom, the other ones are not handled yet const qreal h = button->effectiveFontHeight( Q::Text );
{ if ( h < r.height() )
qreal h = button->effectiveFontHeight( QskPushButton::Text ); r.setTop( r.bottom() - h );
if ( h < r.height() )
r.setTop( r.bottom() - h );
}
} }
} }
@ -103,17 +111,16 @@ QRectF QskPushButtonSkinlet::textRect(
QRectF QskPushButtonSkinlet::graphicRect( QRectF QskPushButtonSkinlet::graphicRect(
const QskPushButton* button, const QRectF& contentsRect ) const 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 const auto orientation = qskOrientation( button );
| QskAspect::Direction, Qsk::LeftToRight );
if ( !button->text().isEmpty() && orientation == Qsk::TopToBottom ) if ( !button->text().isEmpty() && orientation == Qt::Vertical )
{ {
const auto textRect = subControlRect( button, contentsRect, QskPushButton::Text ); const auto textRect = subControlRect( button, contentsRect, Q::Text );
qreal h = textRect.height() + button->spacingHint( QskPushButton::Panel ); qreal h = textRect.height() + button->spacingHint( Q::Panel );
if ( h < r.height() ) if ( h < r.height() )
r.setBottom( r.bottom() - h ); 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() ) ) if ( !( r.isEmpty() || sz.isEmpty() ) )
{ {
@ -155,29 +162,23 @@ QRectF QskPushButtonSkinlet::graphicRect(
const int h = qFloor( scaleFactor * sz.height() ); const int h = qFloor( scaleFactor * sz.height() );
int x, y; int x, y;
const auto orientation = button->flagHint( QskPushButton::Panel if ( orientation == Qt::Horizontal )
| QskAspect::Direction, Qsk::LeftToRight );
switch( orientation )
{ {
case Qsk::LeftToRight: x = r.left();
{ y = r.top();
x = r.left(); }
y = r.top(); else
break; {
} // early aligning to avoid pointless operations, that finally will
default: // TopToBottom // have no effect, when drawing to an integer based paint device
{
// 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 ); x = qFloor( r.center().x() - 0.5 * w );
y = qFloor( r.center().y() - 0.5 * h ); y = qFloor( r.center().y() - 0.5 * h );
}
} }
r = QRectF( x, y, w, 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 ); r = r.marginsRemoved( padding );
} }
@ -187,21 +188,25 @@ QRectF QskPushButtonSkinlet::graphicRect(
QSGNode* QskPushButtonSkinlet::updateTextNode( QSGNode* QskPushButtonSkinlet::updateTextNode(
const QskPushButton* button, QSGNode* node ) const 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 ) ) if ( !button->clip() && ( rect.height() < textHeight ) )
return nullptr; 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, 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, QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& ) const Qt::SizeHint which, const QSizeF& ) const
{ {
using Q = QskPushButton;
if ( which != Qt::PreferredSize ) if ( which != Qt::PreferredSize )
return QSizeF(); 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 if( orientation == Qt::Horizontal )
| QskAspect::Direction, Qsk::LeftToRight );
switch( orientation )
{ {
case Qsk::LeftToRight: size.rwidth() += padding.left() + w + padding.right();
{ size.rheight() = qMax( size.height(), h );
size.rwidth() += padding.left() + w + padding.right(); }
size.rheight() = qMax( size.height(), h ); else
break; {
} size.rheight() += padding.top() + h + padding.bottom();
default: // TopToBottom size.rwidth() = qMax( size.width(), w );
{
size.rheight() += padding.top() + h + padding.bottom();
size.rwidth() = qMax( size.width(), w );
}
} }
} }
size = size.expandedTo( button->strutSizeHint( QskPushButton::Panel ) ); size = size.expandedTo( button->strutSizeHint( Q::Panel ) );
size = button->outerBoxSize( QskPushButton::Panel, size ); size = button->outerBoxSize( Q::Panel, size );
return size; return size;
} }

View File

@ -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 ); Q_D( QskBoxShadowNode );
if ( rect == d->rect ) 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 )
{ {
d->material.m_aspect = aspect; d->rect = rect;
markDirty( QSGNode::DirtyMaterial );
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 );
}

View File

@ -20,14 +20,8 @@ class QSK_EXPORT QskBoxShadowNode : public QSGGeometryNode
QskBoxShadowNode(); QskBoxShadowNode();
~QskBoxShadowNode() override; ~QskBoxShadowNode() override;
void setRect( const QRectF& ); void setShadowData( const QRectF&, const QskBoxShapeMetrics&,
void setShape( const QskBoxShapeMetrics& ); qreal blurRadius, const QColor& );
void setColor( const QColor& );
void setBlurRadius( qreal );
void setClipShape( const QskBoxShapeMetrics& );
void updateGeometry();
private: private:
Q_DECLARE_PRIVATE( QskBoxShadowNode ) Q_DECLARE_PRIVATE( QskBoxShadowNode )

View File

@ -24,14 +24,9 @@ void QskShadedBoxNode::setBoxData( const QRectF& rect,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor ) const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
{ {
m_boxNode.setBoxData( rect, shape, borderMetrics, borderColors, gradient ); m_boxNode.setBoxData( rect, shape, borderMetrics, borderColors, gradient );
setShadowData( rect, shape, shadowMetrics, shadowColor );
}
void QskShadedBoxNode::setShadowData( if ( shadowMetrics.isNull()
const QRectF& rect, const QskBoxShapeMetrics& shape, || !shadowColor.isValid() || shadowColor.alpha() == 0 )
const QskShadowMetrics& metrics, const QColor& color )
{
if ( metrics.isNull() || !color.isValid() || color.alpha() == 0 )
{ {
if ( m_shadowNode ) if ( m_shadowNode )
{ {
@ -48,13 +43,7 @@ void QskShadedBoxNode::setShadowData(
insertChildNodeBefore( m_shadowNode, &m_boxNode ); insertChildNodeBefore( m_shadowNode, &m_boxNode );
} }
m_shadowNode->setColor( color ); m_shadowNode->setShadowData( shadowMetrics.shadowRect( rect ),
shape, shadowMetrics.blurRadius(), shadowColor );
m_shadowNode->setRect( metrics.shadowRect( rect ) );
m_shadowNode->setShape( shape );
m_shadowNode->setBlurRadius( metrics.blurRadius() );
m_shadowNode->setClipShape( shape );
m_shadowNode->updateGeometry();
} }
} }

View File

@ -24,9 +24,6 @@ class QSK_EXPORT QskShadedBoxNode : public QSGNode
const QskShadowMetrics&, const QColor& shadowColor ); const QskShadowMetrics&, const QColor& shadowColor );
private: private:
void setShadowData( const QRectF&, const QskBoxShapeMetrics&,
const QskShadowMetrics&, const QColor& );
QskBoxNode m_boxNode; QskBoxNode m_boxNode;
QskBoxShadowNode* m_shadowNode = nullptr; QskBoxShadowNode* m_shadowNode = nullptr;
}; };