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 );
}
}
QRectF BlurringNode::rect() const
{
return d_func()->rect;
}

View File

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

View File

@ -13,6 +13,8 @@
#include <QskBoxBorderMetrics.h>
#include <QskBoxBorderColors.h>
#include <QskGradient.h>
#include <QskSGNode.h>
#include <QskRgbValue.h>
namespace
{
@ -28,6 +30,12 @@ namespace
setNodeRoles( { EffectRole, BorderRole } );
}
QRectF subControlRect( const QskSkinnable*,
const QRectF& contentsRect, QskAspect::Subcontrol ) const override
{
return contentsRect;
}
QSGNode* updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
@ -36,11 +44,10 @@ namespace
switch ( nodeRole )
{
case EffectRole:
return updateEffectNode( overlay, node );
return updateClippedEffectNode( overlay, node );
case BorderRole:
return updateBoxNode( overlay, node, overlay->contentsRect(),
QskBoxShapeMetrics(), 1, Qt::darkGray, QskGradient() );
return updateBoxNode( skinnable, node, Overlay::Panel );
break;
};
@ -48,6 +55,47 @@ namespace
}
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
{
const auto window = overlay->window();
@ -71,31 +119,48 @@ namespace
effectNode->setTexture( texture );
}
auto texture = qobject_cast< QskSceneTexture* >( effectNode->texture() );
Q_ASSERT( texture );
{
auto texture = qobject_cast< QskSceneTexture* >( effectNode->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 ) );
texture->render( rootNode, finalNode, overlay->geometry() );
auto finalNode = const_cast< QSGTransformNode* >( qskItemNode( overlay ) );
texture->render( rootNode, finalNode, overlay->geometry() );
}
effectNode->setRect( overlay->rect() );
{
const auto rect = overlay->subControlRect( Overlay::Panel );
effectNode->setRect( rect );
}
return effectNode;
}
};
}
QSK_SUBCONTROL( Overlay, Panel )
Overlay::Overlay( QQuickItem* parent )
: Inherited( parent )
{
setSkinlet( new Skinlet() );
setBoxBorderMetricsHint( Panel, 1 );
setBoxBorderColorsHint( Panel, QskRgb::toTransparent( QskRgb::DarkGrey, 100 ) );
setBoxShapeHint( Panel, QskBoxShapeMetrics( 25, Qt::RelativeSize ) );
}
Overlay::~Overlay()
{
}
QRectF Overlay::layoutRectForSize( const QSizeF& size ) const
{
return subControlContentsRect( size, Panel );
}
void Overlay::geometryChange(
const QRectF& newGeometry, const QRectF& oldGeometry )
{

View File

@ -14,9 +14,13 @@ class Overlay : public QskControl
using Inherited = QskControl;
public:
QSK_SUBCONTROLS( Panel )
Overlay( QQuickItem* = nullptr );
~Overlay() override;
QRectF layoutRectForSize( const QSizeF& ) const override;
protected:
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
{
using Inherited = QskControl;
@ -97,15 +67,11 @@ class BackgroundItem : public QskControl
{
setObjectName( "background" );
#if 1
m_label = new Image( this );
m_label->setFillMode( QskGraphicLabel::Stretch );
m_label->setObjectName( "parrots" );
#endif
#if 1
startTimer( 20 );
#endif
}
protected:
@ -162,7 +128,10 @@ class MainView : public QskControl
box->setObjectName( "redBox" );
}
#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 );
#if 0

View File

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