From bdf4bb045cbd38df338338eebbfa6595c75dab12 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 17 Dec 2023 17:28:00 +0100 Subject: [PATCH] QskTreeNode introduced --- src/CMakeLists.txt | 2 + src/controls/QskControl.cpp | 3 +- src/controls/QskQuickItemPrivate.cpp | 9 +- src/controls/QskQuickItemPrivate.h | 2 +- src/nodes/QskTreeNode.cpp | 165 +++++++++++++++++++++++++++ src/nodes/QskTreeNode.h | 63 ++++++++++ 6 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 src/nodes/QskTreeNode.cpp create mode 100644 src/nodes/QskTreeNode.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59ba35fa..1211c078 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -115,6 +115,7 @@ list(APPEND HEADERS nodes/QskGraduationNode.h nodes/QskGraduationRenderer.h nodes/QskGraphicNode.h + nodes/QskTreeNode.h nodes/QskLinesNode.h nodes/QskPaintedNode.h nodes/QskPlainTextRenderer.h @@ -160,6 +161,7 @@ list(APPEND SOURCES nodes/QskStrokeNode.cpp nodes/QskStippledLineRenderer.cpp nodes/QskShapeNode.cpp + nodes/QskTreeNode.cpp nodes/QskGradientMaterial.cpp nodes/QskTextNode.cpp nodes/QskTextRenderer.cpp diff --git a/src/controls/QskControl.cpp b/src/controls/QskControl.cpp index 9b3d5113..6867d6e7 100644 --- a/src/controls/QskControl.cpp +++ b/src/controls/QskControl.cpp @@ -15,6 +15,7 @@ #include "QskSkinlet.h" #include "QskSkinHintTable.h" #include "QskMargins.h" +#include "QskTreeNode.h" #include #include @@ -977,7 +978,7 @@ void QskControl::updateItemPolish() QSGNode* QskControl::updateItemPaintNode( QSGNode* node ) { if ( node == nullptr ) - node = new QSGNode; + node = new QskTreeNode(); updateNode( node ); return node; diff --git a/src/controls/QskQuickItemPrivate.cpp b/src/controls/QskQuickItemPrivate.cpp index 6f9fc3a2..52e86b6f 100644 --- a/src/controls/QskQuickItemPrivate.cpp +++ b/src/controls/QskQuickItemPrivate.cpp @@ -4,6 +4,7 @@ *****************************************************************************/ #include "QskQuickItemPrivate.h" +#include "QskTreeNode.h" #include "QskSetup.h" static inline void qskSendEventTo( QObject* object, QEvent::Type type ) @@ -240,11 +241,13 @@ void QskQuickItemPrivate::cleanupNodes() } } +QSGTransformNode* QskQuickItemPrivate::createTransformNode() +{ + return new QskItemNode(); +} + /* Can we do something useful with overloading: - - QQuickItemPrivate::createTransformNode - QQuickItemPrivate::transformChanged - - TODO ... */ diff --git a/src/controls/QskQuickItemPrivate.h b/src/controls/QskQuickItemPrivate.h index 0d7f41e6..150f4b93 100644 --- a/src/controls/QskQuickItemPrivate.h +++ b/src/controls/QskQuickItemPrivate.h @@ -23,13 +23,13 @@ class QskQuickItemPrivate : public QQuickItemPrivate public: void applyUpdateFlags( QskQuickItem::UpdateFlags ); + QSGTransformNode* createTransformNode() override; protected: virtual void layoutConstraintChanged(); virtual void implicitSizeChanged(); private: - void cleanupNodes(); void mirrorChange() override; diff --git a/src/nodes/QskTreeNode.cpp b/src/nodes/QskTreeNode.cpp new file mode 100644 index 00000000..f8d4c408 --- /dev/null +++ b/src/nodes/QskTreeNode.cpp @@ -0,0 +1,165 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskTreeNode.h" + +static constexpr auto extraFlag = + static_cast< QSGNode::Flag >( QSGNode::IsVisitableNode << 1 ); + +static inline QSGNode* qskCheckedNode( const QSGNode* node, QSGNode::NodeType type ) +{ + return node && ( node->type() == type ) && ( node->flags() & extraFlag ) + ? const_cast< QSGNode* >( node ) : nullptr; +} + +QskTreeNode::QskTreeNode() +{ + setFlag( extraFlag, true ); +} + +QskTreeNode::QskTreeNode( QSGNodePrivate& d ) + : QSGNode( d, QSGNode::BasicNodeType ) +{ + setFlag( extraFlag, true ); +} + +QskTreeNode::~QskTreeNode() +{ +} + +void QskTreeNode::setSubtreeBlocked( bool on, bool notify ) +{ + if ( on == m_isBlocked ) + return; + + m_isBlocked = on; + + if ( notify ) + markDirty( DirtySubtreeBlocked ); +} + +bool QskTreeNode::isSubtreeBlocked() const +{ + return m_isBlocked; +} + +QskTreeNode* qskTreeNodeCast( QSGNode* node ) +{ + return static_cast< QskTreeNode* >( + qskCheckedNode( node, QSGNode::BasicNodeType ) ); +} + +const QskTreeNode* qskTreeNodeCast( const QSGNode* node ) +{ + return static_cast< QskTreeNode* >( + qskCheckedNode( node, QSGNode::BasicNodeType ) ); +} + + +// == QskItemNode + +QskItemNode::QskItemNode() +{ + setFlag( extraFlag, true ); +} + +QskItemNode::~QskItemNode() +{ +} + +void QskItemNode::setSubtreeBlocked( bool on, bool notify ) +{ + if ( on == m_isBlocked ) + return; + + m_isBlocked = on; + + if ( notify ) + markDirty( DirtySubtreeBlocked ); +} + +bool QskItemNode::isSubtreeBlocked() const +{ + return m_isBlocked; +} + +QskItemNode* qskItemNodeCast( QSGNode* node ) +{ + return static_cast< QskItemNode* >( + qskCheckedNode( node, QSGNode::TransformNodeType ) ); +} + +const QskItemNode* qskItemNodeCast( const QSGNode* node ) +{ + return static_cast< QskItemNode* >( + qskCheckedNode( node, QSGNode::TransformNodeType ) ); +} + +bool qskIsBlockableNode( const QSGNode* node ) +{ + switch( node->type() ) + { + case QSGNode::BasicNodeType: + case QSGNode::TransformNodeType: + return node->flags() & extraFlag; + + default: + return false; + } +} + +bool qskTryBlockNode( QSGNode* node, bool on, bool notify ) +{ + if ( node && ( node->flags() & extraFlag ) ) + { + if ( node->type() == QSGNode::BasicNodeType ) + { + static_cast< QskTreeNode* >( node )->setSubtreeBlocked( on, notify ); + return true; + } + + if ( node->type() == QSGNode::TransformNodeType ) + { + static_cast< QskItemNode* >( node )->setSubtreeBlocked( on, notify ); + return true; + } + } + + return false; +} + +void qskTryBlockTree( QSGNode* node, bool on, bool notify ) +{ + if ( qskTryBlockNode( node, on, notify ) ) + return; + + for ( auto child = node->firstChild(); + child != nullptr; child = child->nextSibling() ) + { + qskTryBlockTree( child, on, notify ); + } +} + +void qskTryBlockTrailingNodes( + QSGNode* node, const QSGNode* ancestorNode, bool on, bool notify ) +{ + qskTryBlockTree( node, on, notify ); + + for ( auto sibling = node->nextSibling(); + sibling != nullptr; sibling = sibling->nextSibling() ) + { + qskTryBlockTree( sibling, on, notify ); + } + + if ( node != ancestorNode ) + { + if ( auto upperNode = node->parent() ) + { + upperNode = upperNode->nextSibling(); + if ( upperNode ) + qskTryBlockTrailingNodes( upperNode, ancestorNode, on, notify ); + } + } +} diff --git a/src/nodes/QskTreeNode.h b/src/nodes/QskTreeNode.h new file mode 100644 index 00000000..5adc141d --- /dev/null +++ b/src/nodes/QskTreeNode.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_TREE_NODE_H +#define QSK_TREE_NODE_H + +#include "QskGlobal.h" +#include + +/* + Used as paintNode in all QskControls ( see QskControl::updateItemPaintNode ) + */ +class QSK_EXPORT QskTreeNode final : public QSGNode +{ + public: + QskTreeNode(); + virtual ~QskTreeNode(); + + void setSubtreeBlocked( bool on, bool notify = true ); + bool isSubtreeBlocked() const override; + + protected: + QskTreeNode( QSGNodePrivate& ); + + private: + bool m_isBlocked = false;; +}; + +QSK_EXPORT QskTreeNode* qskTreeNodeCast( QSGNode* ); +QSK_EXPORT const QskTreeNode* qskTreeNodeCast( const QSGNode* ); + +/* + Used by all QskQuickItem as root node ( = itemNode ) of its subtree + ( see qskItemNode in QskQuick.h ) + */ +class QSK_EXPORT QskItemNode final : public QSGTransformNode +{ + public: + QskItemNode(); + virtual ~QskItemNode(); + + void setSubtreeBlocked( bool on, bool notify = true ); + bool isSubtreeBlocked() const override; + + private: + bool m_isBlocked = false;; +}; + +QSK_EXPORT QskItemNode* qskItemNodeCast( QSGNode* ); +QSK_EXPORT const QskItemNode* qskItemNodeCast( const QSGNode* ); + +QSK_EXPORT bool qskIsBlockableNode( const QSGNode* ); +QSK_EXPORT bool qskTryBlockNode( QSGNode*, bool on, bool notify = true ); + +QSK_EXPORT void qskTryBlockTree( QSGNode*, bool on, bool notify = true ); + +// un/block a node and all its successors in the rendering pipeline +QSK_EXPORT void qskTryBlockTrailingNodes( + QSGNode*, const QSGNode* ancestorNode, bool on, bool notify = true ); + +#endif