From 8d2ff3c3fe586ccc3eca7bda17d8413453a0a854 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 23 Dec 2021 18:19:52 +0100 Subject: [PATCH] QskPopup improvements --- skins/squiek/QskSquiekSkin.cpp | 1 + src/controls/QskPopupSkinlet.cpp | 132 ++++++++++++++++++++++++++++++- src/controls/QskPopupSkinlet.h | 5 ++ 3 files changed, 137 insertions(+), 1 deletion(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index f462cbd1..0487b10d 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/src/controls/QskPopupSkinlet.cpp b/src/controls/QskPopupSkinlet.cpp index 9ac3642f..371371f7 100644 --- a/src/controls/QskPopupSkinlet.cpp +++ b/src/controls/QskPopupSkinlet.cpp @@ -5,11 +5,109 @@ #include "QskPopupSkinlet.h" #include "QskPopup.h" +#include "QskSGNode.h" + +#include +#include + +namespace +{ + class RootNode : public QSGNode + { + public: + ~RootNode() + { + delete m_clipNode; + delete m_transformNode; + delete m_contentsNode; + } + + void setClipRect( const QRectF& rect ) + { + if ( rect.isValid() ) + { + if ( m_clipNode == nullptr ) + { + m_clipNode = new QSGClipNode(); + m_clipNode->setFlag( QSGNode::OwnedByParent, false ); + m_clipNode->setIsRectangular( true ); + } + + m_clipNode->setClipRect( rect ); + } + else + { + delete m_clipNode; + m_clipNode = nullptr; + } + } + + void setTranslation( qreal dx, qreal dy ) + { + if ( dx != 0.0 || dy != 0.0 ) + { + if ( m_transformNode == nullptr ) + { + m_transformNode = new QSGTransformNode(); + m_transformNode->setFlag( QSGNode::OwnedByParent, false ); + } + + QTransform transform; + transform.translate( dx, dy ); + + m_transformNode->setMatrix( transform ); + } + else + { + delete m_transformNode; + m_transformNode = nullptr; + } + } + + void setContentsNode( QSGNode* contentsNode ) + { + if ( m_contentsNode != contentsNode ) + { + if ( contentsNode ) + contentsNode->setFlag( QSGNode::OwnedByParent, false ); + + delete m_contentsNode; + m_contentsNode = contentsNode; + } + } + + void rearrangeNodes() + { + const std::initializer_list< QSGNode* > nodes = + { m_clipNode, m_transformNode, m_contentsNode }; + + QSGNode* parentNode = this; + for ( auto node : nodes ) + { + if ( node ) + { + QskSGNode::setParentNode( node, parentNode ); + parentNode = node; + } + } + } + + inline QSGNode* contentsNode() + { + return m_contentsNode; + } + + private: + QSGClipNode* m_clipNode = nullptr; + QSGTransformNode* m_transformNode = nullptr; + QSGNode* m_contentsNode = nullptr; + }; +} QskPopupSkinlet::QskPopupSkinlet( QskSkin* skin ) : Inherited( skin ) { - appendNodeRoles( { OverlayRole } ); + appendNodeRoles( { OverlayRole, ContentsRole } ); } QskPopupSkinlet::~QskPopupSkinlet() = default; @@ -28,13 +126,45 @@ QRectF QskPopupSkinlet::subControlRect( const QskSkinnable* skinnable, QSGNode* QskPopupSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { + const auto popup = static_cast< const QskPopup* >( skinnable ); + switch ( nodeRole ) { case OverlayRole: return updateBoxNode( skinnable, node, QskPopup::Overlay ); + + case ContentsRole: + return updateExtraNode( popup, node ); } return Inherited::updateSubNode( skinnable, nodeRole, node ); } +QSGNode* QskPopupSkinlet::updateExtraNode( const QskPopup* popup, QSGNode* node ) const +{ + auto cr = popup->contentsRect(); + if ( cr.isEmpty() ) + return nullptr; + + auto rootNode = QskSGNode::ensureNode< RootNode >( node ); + + const auto faderProgress = popup->metric( popup->faderAspect() ); + if ( faderProgress > 0.0 && faderProgress < 1.0 ) + rootNode->setClipRect( cr ); + + rootNode->setTranslation( 0.0, -faderProgress * cr.height() ); + + auto contentsNode = updateContentsNode( popup, rootNode->contentsNode() ); + rootNode->setContentsNode( contentsNode ); + + rootNode->rearrangeNodes(); + + return rootNode; +} + +QSGNode* QskPopupSkinlet::updateContentsNode( const QskPopup*, QSGNode* ) const +{ + return nullptr; +} + #include "moc_QskPopupSkinlet.cpp" diff --git a/src/controls/QskPopupSkinlet.h b/src/controls/QskPopupSkinlet.h index 58914939..0332e4de 100644 --- a/src/controls/QskPopupSkinlet.h +++ b/src/controls/QskPopupSkinlet.h @@ -20,6 +20,8 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet enum NodeRole { OverlayRole, + ContentsRole, + RoleCount }; @@ -33,7 +35,10 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override; + virtual QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const; + private: + QSGNode* updateExtraNode( const QskPopup*, QSGNode* ) const; QSGNode* updateOverlayNode( const QskPopup*, QSGNode* ) const; };