171 lines
4.6 KiB
C++
171 lines
4.6 KiB
C++
/******************************************************************************
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
*****************************************************************************/
|
|
|
|
#include "QskPopupSkinlet.h"
|
|
#include "QskPopup.h"
|
|
#include "QskSGNode.h"
|
|
|
|
#include <qtransform.h>
|
|
#include <qsgnode.h>
|
|
|
|
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, ContentsRole } );
|
|
}
|
|
|
|
QskPopupSkinlet::~QskPopupSkinlet() = default;
|
|
|
|
QRectF QskPopupSkinlet::subControlRect( const QskSkinnable* skinnable,
|
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
|
{
|
|
const auto popup = static_cast< const QskPopup* >( skinnable );
|
|
|
|
if ( subControl == QskPopup::Overlay )
|
|
return popup->overlayRect();
|
|
|
|
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
|
}
|
|
|
|
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"
|