Overlay supports the box model now

This commit is contained in:
Uwe Rathmann 2023-12-18 09:02:45 +01:00
parent d9ebaa8b03
commit 0df5775e3e
9 changed files with 86 additions and 55 deletions

View File

@ -174,8 +174,3 @@ void BlurringNode::setRect( const QRectF& rect )
markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyGeometry );
} }
} }
QRectF BlurringNode::rect() const
{
return d_func()->rect;
}

View File

@ -9,6 +9,7 @@
class QRect; class QRect;
class QSGTexture; class QSGTexture;
class BlurringNodePrivate; class BlurringNodePrivate;
class BlurringNode : public QSGGeometryNode class BlurringNode : public QSGGeometryNode
@ -23,7 +24,6 @@ class BlurringNode : public QSGGeometryNode
QSGTexture* texture(); QSGTexture* texture();
void setRect( const QRectF& ); void setRect( const QRectF& );
QRectF rect() const;
private: private:
Q_DECLARE_PRIVATE( BlurringNode ) Q_DECLARE_PRIVATE( BlurringNode )

View File

@ -13,6 +13,8 @@
#include <QskBoxBorderMetrics.h> #include <QskBoxBorderMetrics.h>
#include <QskBoxBorderColors.h> #include <QskBoxBorderColors.h>
#include <QskGradient.h> #include <QskGradient.h>
#include <QskSGNode.h>
#include <QskRgbValue.h>
namespace namespace
{ {
@ -28,6 +30,12 @@ namespace
setNodeRoles( { EffectRole, BorderRole } ); setNodeRoles( { EffectRole, BorderRole } );
} }
QRectF subControlRect( const QskSkinnable*,
const QRectF& contentsRect, QskAspect::Subcontrol ) const override
{
return contentsRect;
}
QSGNode* updateSubNode( QSGNode* updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{ {
@ -36,11 +44,10 @@ namespace
switch ( nodeRole ) switch ( nodeRole )
{ {
case EffectRole: case EffectRole:
return updateEffectNode( overlay, node ); return updateClippedEffectNode( overlay, node );
case BorderRole: case BorderRole:
return updateBoxNode( overlay, node, overlay->contentsRect(), return updateBoxNode( skinnable, node, Overlay::Panel );
QskBoxShapeMetrics(), 1, Qt::darkGray, QskGradient() );
break; break;
}; };
@ -48,6 +55,47 @@ namespace
} }
private: private:
QSGNode* updateClippedEffectNode( const Overlay* overlay, QSGNode* node ) const
{
/*
There should be a way to avoid the clip node by passing the
vertex list directly to the effect node. TODO ...
*/
using Q = Overlay;
QSGNode* clipNode = nullptr;
QSGNode* effectNode = nullptr;
if ( node )
{
if ( node->firstChild() )
{
clipNode = node;
effectNode = node->firstChild();
}
else
{
effectNode = node;
}
}
effectNode = updateEffectNode( overlay, effectNode );
if ( overlay->boxShapeHint( Q::Panel ).isRectangle() )
{
delete clipNode;
clipNode = nullptr;
}
else
{
clipNode = updateBoxClipNode( overlay, clipNode, Q::Panel );
}
QskSGNode::setParentNode( effectNode, clipNode );
return clipNode ? clipNode : effectNode;
}
QSGNode* updateEffectNode( const Overlay* overlay, QSGNode* node ) const QSGNode* updateEffectNode( const Overlay* overlay, QSGNode* node ) const
{ {
const auto window = overlay->window(); const auto window = overlay->window();
@ -71,31 +119,48 @@ namespace
effectNode->setTexture( texture ); effectNode->setTexture( texture );
} }
{
auto texture = qobject_cast< QskSceneTexture* >( effectNode->texture() ); auto texture = qobject_cast< QskSceneTexture* >( effectNode->texture() );
Q_ASSERT( texture ); Q_ASSERT( texture );
texture->setFiltering( overlay->smooth() ? QSGTexture::Linear : QSGTexture::Nearest ); texture->setFiltering(
overlay->smooth() ? QSGTexture::Linear : QSGTexture::Nearest );
auto finalNode = const_cast< QSGTransformNode* >( qskItemNode( overlay ) ); auto finalNode = const_cast< QSGTransformNode* >( qskItemNode( overlay ) );
texture->render( rootNode, finalNode, overlay->geometry() ); texture->render( rootNode, finalNode, overlay->geometry() );
}
effectNode->setRect( overlay->rect() ); {
const auto rect = overlay->subControlRect( Overlay::Panel );
effectNode->setRect( rect );
}
return effectNode; return effectNode;
} }
}; };
} }
QSK_SUBCONTROL( Overlay, Panel )
Overlay::Overlay( QQuickItem* parent ) Overlay::Overlay( QQuickItem* parent )
: Inherited( parent ) : Inherited( parent )
{ {
setSkinlet( new Skinlet() ); setSkinlet( new Skinlet() );
setBoxBorderMetricsHint( Panel, 1 );
setBoxBorderColorsHint( Panel, QskRgb::toTransparent( QskRgb::DarkGrey, 100 ) );
setBoxShapeHint( Panel, QskBoxShapeMetrics( 25, Qt::RelativeSize ) );
} }
Overlay::~Overlay() Overlay::~Overlay()
{ {
} }
QRectF Overlay::layoutRectForSize( const QSizeF& size ) const
{
return subControlContentsRect( size, Panel );
}
void Overlay::geometryChange( void Overlay::geometryChange(
const QRectF& newGeometry, const QRectF& oldGeometry ) const QRectF& newGeometry, const QRectF& oldGeometry )
{ {

View File

@ -14,9 +14,13 @@ class Overlay : public QskControl
using Inherited = QskControl; using Inherited = QskControl;
public: public:
QSK_SUBCONTROLS( Panel )
Overlay( QQuickItem* = nullptr ); Overlay( QQuickItem* = nullptr );
~Overlay() override; ~Overlay() override;
QRectF layoutRectForSize( const QSizeF& ) const override;
protected: protected:
void geometryChange( const QRectF&, const QRectF& ) override; void geometryChange( const QRectF&, const QRectF& ) override;
}; };

View File

@ -57,36 +57,6 @@ class ForegroundItem : public QskLinearBox
} }
}; };
class OverlayBox : public Overlay
{
using Inherited = Overlay;
public:
OverlayBox( QQuickItem* parent = nullptr )
: Inherited( parent )
{
setObjectName( "overlay" );
}
protected:
void geometryChange( const QRectF& newRect, const QRectF& oldRect ) override
{
Inherited::geometryChange( newRect, oldRect );
const auto rect = qskItemRect( this );
const auto children = childItems();
for ( auto child : children )
{
if ( qskIsAdjustableByLayout( child ) )
{
const auto r = qskConstrainedItemRect( child, rect );
qskSetItemGeometry( child, r );
}
}
}
};
class BackgroundItem : public QskControl class BackgroundItem : public QskControl
{ {
using Inherited = QskControl; using Inherited = QskControl;
@ -97,15 +67,11 @@ class BackgroundItem : public QskControl
{ {
setObjectName( "background" ); setObjectName( "background" );
#if 1
m_label = new Image( this ); m_label = new Image( this );
m_label->setFillMode( QskGraphicLabel::Stretch ); m_label->setFillMode( QskGraphicLabel::Stretch );
m_label->setObjectName( "parrots" ); m_label->setObjectName( "parrots" );
#endif
#if 1
startTimer( 20 ); startTimer( 20 );
#endif
} }
protected: protected:
@ -162,7 +128,10 @@ class MainView : public QskControl
box->setObjectName( "redBox" ); box->setObjectName( "redBox" );
} }
#endif #endif
m_overlay = new OverlayBox( m_background ); m_overlay = new Overlay( m_background );
m_overlay->setAutoLayoutChildren( true );
m_overlay->setObjectName( "overlay" );
(void )new ForegroundItem( m_overlay ); (void )new ForegroundItem( m_overlay );
#if 0 #if 0

View File

@ -78,11 +78,9 @@ void QskBoxNode::updateNode( const QRectF& rect,
} }
/* /*
QskBoxRectangleNode supports vertical/horizontal and many tilted QskBoxRectangleNode is more efficient and creates batchable geometries.
linear gradients. If our gradient doesn't fall into this category So we prefer using it where possible.
we use a QskBoxFillNode. Note, that the border is always done with a QskBoxRectangleNode
However the border is always done with a QskBoxRectangleNode
*/ */
if ( QskBoxRenderer::isGradientSupported( shape, gradient ) ) if ( QskBoxRenderer::isGradientSupported( shape, gradient ) )