code moved from QskPopupSkinlet to QskSlideInNode

This commit is contained in:
Uwe Rathmann 2023-10-15 15:44:09 +02:00
parent 56446c26db
commit 3ecd8f337e
7 changed files with 228 additions and 147 deletions

View File

@ -115,6 +115,7 @@ list(APPEND HEADERS
nodes/QskRichTextRenderer.h nodes/QskRichTextRenderer.h
nodes/QskScaleRenderer.h nodes/QskScaleRenderer.h
nodes/QskSGNode.h nodes/QskSGNode.h
nodes/QskSlideInNode.h
nodes/QskStrokeNode.h nodes/QskStrokeNode.h
nodes/QskStippledLineRenderer.h nodes/QskStippledLineRenderer.h
nodes/QskShapeNode.h nodes/QskShapeNode.h
@ -146,6 +147,7 @@ list(APPEND SOURCES
nodes/QskRichTextRenderer.cpp nodes/QskRichTextRenderer.cpp
nodes/QskScaleRenderer.cpp nodes/QskScaleRenderer.cpp
nodes/QskSGNode.cpp nodes/QskSGNode.cpp
nodes/QskSlideInNode.cpp
nodes/QskStrokeNode.cpp nodes/QskStrokeNode.cpp
nodes/QskStippledLineRenderer.cpp nodes/QskStippledLineRenderer.cpp
nodes/QskShapeNode.cpp nodes/QskShapeNode.cpp

View File

@ -9,12 +9,14 @@
#include "QskGraphic.h" #include "QskGraphic.h"
#include "QskColorFilter.h" #include "QskColorFilter.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskSGNode.h"
#include "QskFunctions.h" #include "QskFunctions.h"
#include "QskMargins.h" #include "QskMargins.h"
#include "QskFunctions.h" #include "QskFunctions.h"
#include "QskLabelData.h" #include "QskLabelData.h"
#include "QskSGNode.h"
#include "QskSlideInNode.h"
#include <qfontmetrics.h> #include <qfontmetrics.h>
#include <qmath.h> #include <qmath.h>
@ -209,11 +211,44 @@ QskMenuSkinlet::QskMenuSkinlet( QskSkin* skin )
: Inherited( skin ) : Inherited( skin )
, m_data( new PrivateData() ) , m_data( new PrivateData() )
{ {
appendNodeRoles( { PanelRole } ); appendNodeRoles( { ContentsRole, PanelRole } );
} }
QskMenuSkinlet::~QskMenuSkinlet() = default; QskMenuSkinlet::~QskMenuSkinlet() = default;
QSGNode* QskMenuSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
switch ( nodeRole )
{
case ContentsRole:
{
/*
QskSlideInNode works for controls made of nodes - not for
containers of other quick items. TODO ...
*/
const auto popup = static_cast< const QskPopup* >( skinnable );
auto rect = popup->contentsRect();
if ( rect.isEmpty() )
return nullptr;
auto slideInNode = QskSGNode::ensureNode< QskSlideInNode >( node );
const auto progress = popup->metric( popup->faderAspect() );
slideInNode->updateTranslation( rect, Qt::TopEdge, progress );
auto contentsNode = updateContentsNode( popup, slideInNode->contentsNode() );
slideInNode->setContentsNode( contentsNode );
return slideInNode;
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QRectF QskMenuSkinlet::cursorRect( QRectF QskMenuSkinlet::cursorRect(
const QskSkinnable* skinnable, const QRectF& contentsRect, int index ) const const QskSkinnable* skinnable, const QRectF& contentsRect, int index ) const
{ {
@ -407,7 +442,8 @@ QskAspect::States QskMenuSkinlet::sampleStates(
} }
} }
const auto cursorPos = menu->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); const auto cursorPos = menu->effectiveSkinHint(
Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF();
if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index ) if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index )
{ {

View File

@ -20,7 +20,9 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
public: public:
enum NodeRole enum NodeRole
{ {
PanelRole = QskPopupSkinlet::RoleCount, ContentsRole = Inherited::RoleCount,
PanelRole,
RoleCount RoleCount
}; };
@ -48,7 +50,10 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
Qt::SizeHint, const QSizeF& ) const override; Qt::SizeHint, const QSizeF& ) const override;
protected: protected:
QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const override; QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const;
QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const; QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const;
QSGNode* updateSampleNode( const QskSkinnable*, QSGNode* updateSampleNode( const QskSkinnable*,

View File

@ -5,108 +5,11 @@
#include "QskPopupSkinlet.h" #include "QskPopupSkinlet.h"
#include "QskPopup.h" #include "QskPopup.h"
#include "QskSGNode.h"
#include <qtransform.h>
#include <qsgnode.h>
#include <qquickwindow.h>
namespace
{
class RootNode : public QSGNode
{
public:
~RootNode() override
{
delete m_clipNode;
delete m_transformNode;
delete m_contentsNode;
}
void setClipRect( const QRectF& rect )
{
if ( m_clipNode == nullptr )
{
m_clipNode = new QSGClipNode();
m_clipNode->setFlag( QSGNode::OwnedByParent, false );
m_clipNode->setIsRectangular( true );
}
m_clipNode->setClipRect( rect );
}
void resetClip()
{
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 ) QskPopupSkinlet::QskPopupSkinlet( QskSkin* skin )
: Inherited( skin ) : Inherited( skin )
{ {
appendNodeRoles( { OverlayRole, ContentsRole } ); appendNodeRoles( { OverlayRole } );
} }
QskPopupSkinlet::~QskPopupSkinlet() = default; QskPopupSkinlet::~QskPopupSkinlet() = default;
@ -131,48 +34,9 @@ QSGNode* QskPopupSkinlet::updateSubNode(
{ {
case OverlayRole: case OverlayRole:
return updateBoxNode( skinnable, node, QskPopup::Overlay ); return updateBoxNode( skinnable, node, QskPopup::Overlay );
case ContentsRole:
return updateExtraNode( popup, node );
} }
return Inherited::updateSubNode( skinnable, nodeRole, 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 )
{
auto clipRect = QRectF( popup->mapFromScene( QPointF() ), popup->window()->size() );
clipRect.setTop( cr.top() );
rootNode->setClipRect( clipRect );
}
else
{
rootNode->resetClip();
}
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" #include "moc_QskPopupSkinlet.cpp"

View File

@ -20,8 +20,6 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet
enum NodeRole enum NodeRole
{ {
OverlayRole, OverlayRole,
ContentsRole,
RoleCount RoleCount
}; };
@ -35,10 +33,7 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet
QSGNode* updateSubNode( const QskSkinnable*, QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override; quint8 nodeRole, QSGNode* ) const override;
virtual QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const;
private: private:
QSGNode* updateExtraNode( const QskPopup*, QSGNode* ) const;
QSGNode* updateOverlayNode( const QskPopup*, QSGNode* ) const; QSGNode* updateOverlayNode( const QskPopup*, QSGNode* ) const;
}; };

View File

@ -0,0 +1,146 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskSlideInNode.h"
#include "QskSGNode.h"
#include <qtransform.h>
QSK_QT_PRIVATE_BEGIN
#include <private/qsgnode_p.h>
QSK_QT_PRIVATE_END
class QskSlideInNodePrivate final : public QSGNodePrivate
{
public:
~QskSlideInNodePrivate()
{
delete clipNode;
delete transformNode;
delete contentsNode;
}
void reparentContentNode( QskSlideInNode* node )
{
if ( contentsNode )
{
QSGNode* parentNode = transformNode;
if ( parentNode == nullptr )
parentNode = clipNode;
if ( parentNode == nullptr )
parentNode = node;
QskSGNode::setParentNode( contentsNode, parentNode );
}
}
QSGClipNode* clipNode = nullptr;
QSGTransformNode* transformNode = nullptr;
QSGNode* contentsNode = nullptr;
};
QskSlideInNode::QskSlideInNode()
: QSGNode( *new QskSlideInNodePrivate, QSGNode::BasicNodeType )
{
}
QskSlideInNode::~QskSlideInNode() = default;
void QskSlideInNode::updateTranslation( const QRectF& rect,
Qt::Edge edge, qreal progress )
{
Q_UNUSED( edge ); // TODO ...
Q_D( QskSlideInNode );
{
// clipping
if ( progress > 0.0 && progress <= 1.0 )
{
if ( d->clipNode == nullptr )
{
d->clipNode = new QSGClipNode();
d->clipNode->setFlag( QSGNode::OwnedByParent, false );
d->clipNode->setIsRectangular( true );
}
d->clipNode->setClipRect( rect );
}
else
{
delete d->clipNode;
d->clipNode = nullptr;
}
if ( d->clipNode )
QskSGNode::setParentNode( d->clipNode, this );
}
{
// translation
qreal dx = 0.0;
qreal dy = -progress* rect.height();
if ( dx != 0.0 || dy != 0.0 )
{
if ( d->transformNode == nullptr )
{
d->transformNode = new QSGTransformNode();
d->transformNode->setFlag( QSGNode::OwnedByParent, false );
}
QTransform transform;
transform.translate( dx, dy );
d->transformNode->setMatrix( transform );
}
else
{
delete d->transformNode;
d->transformNode = nullptr;
}
if ( d->transformNode )
{
QSGNode* parentNode = d->clipNode;
if ( parentNode == nullptr )
parentNode = this;
QskSGNode::setParentNode( d->transformNode, parentNode );
}
}
d->reparentContentNode( this );
}
void QskSlideInNode::setContentsNode( QSGNode* node )
{
Q_D( QskSlideInNode );
if ( d->contentsNode == node )
return;
if ( node )
node->setFlag( QSGNode::OwnedByParent, false );
delete d->contentsNode;
d->contentsNode = node;
d->reparentContentNode( this );
}
QSGNode* QskSlideInNode::contentsNode()
{
return d_func()->contentsNode;
}
const QSGNode* QskSlideInNode::contentsNode() const
{
return d_func()->contentsNode;
}

View File

@ -0,0 +1,33 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_SLIDE_IN_NODE_H
#define QSK_SLIDE_IN_NODE_H
#include "QskGlobal.h"
#include <qsgnode.h>
#include <qnamespace.h>
class QskSlideInNodePrivate;
class QSK_EXPORT QskSlideInNode : public QSGNode
{
public:
QskSlideInNode();
~QskSlideInNode() override;
void updateTranslation( const QRectF&, Qt::Edge, qreal progress );
void setContentsNode( QSGNode* );
QSGNode* contentsNode();
const QSGNode* contentsNode() const;
private:
Q_DECLARE_PRIVATE( QskSlideInNode )
};
#endif