QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskBoxNode.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskBoxNode.h"
7#include "QskBoxShadowNode.h"
8#include "QskBoxRectangleNode.h"
9#include "QskSGNode.h"
10
11#include "QskGradient.h"
12#include "QskGradientDirection.h"
13#include "QskShadowMetrics.h"
14#include "QskBoxBorderMetrics.h"
15#include "QskBoxBorderColors.h"
16#include "QskBoxShapeMetrics.h"
17#include "QskRgbValue.h"
18
19namespace
20{
21 enum Role
22 {
23 ShadowRole,
24 ShadowFillRole,
25 BoxRole,
26 FillRole
27 };
28}
29
30static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node )
31{
32 static const QVector< quint8 > roles =
33 { ShadowRole, ShadowFillRole, BoxRole, FillRole };
34
35 auto oldNode = QskSGNode::findChildNode( parentNode, role );
36 QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node );
37}
38
39template< typename Node >
40static inline Node* qskNode( QSGNode* parentNode, quint8 role )
41{
42 using namespace QskSGNode;
43
44 auto node = static_cast< Node* > ( findChildNode( parentNode, role ) );
45
46 if ( node == nullptr )
47 {
48 node = new Node();
49 setNodeRole( node, role );
50 }
51
52 return node;
53}
54
55QskBoxNode::QskBoxNode()
56{
57}
58
59QskBoxNode::~QskBoxNode()
60{
61}
62
63void QskBoxNode::updateNode( const QQuickWindow* window, const QRectF& rect,
64 const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
65 const QskBoxBorderColors& borderColors, const QskGradient& gradient,
66 const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
67{
68 using namespace QskSGNode;
69
70 QskBoxShadowNode* shadowNode = nullptr;
71 QskBoxRectangleNode* shadowFillNode = nullptr;
72 QskBoxRectangleNode* rectNode = nullptr;
73 QskBoxRectangleNode* fillNode = nullptr;
74
75 if ( !rect.isEmpty() )
76 {
77 const auto hasFilling = gradient.isVisible();
78 const auto hasBorder = !borderMetrics.isNull() && borderColors.isVisible();
79 const auto hasShadow = !shadowMetrics.isNull() && QskRgb::isVisible( shadowColor );
80
81 if ( hasShadow )
82 {
83 const auto shadow = shadowMetrics.toAbsolute( rect.size() );
84 const auto shadowRect = shadow.shadowRect( rect );
85
86 auto shadowShape = shapeMetrics;
87
88 switch( static_cast< int >( shadow.shapeMode() ) )
89 {
90 case QskShadowMetrics::Ellipse:
91 shadowShape.setRadius( 100.0, Qt::RelativeSize );
92 break;
93
94 case QskShadowMetrics::Rectangle:
95 shadowShape.setRadius( 0.0, Qt::AbsoluteSize );
96 break;
97 }
98
99 if ( shadow.blurRadius() <= 0.0 )
100 {
101 // QskBoxRectangleNode allows scene graph batching
102 shadowFillNode = qskNode< QskBoxRectangleNode >( this, ShadowFillRole );
103 shadowFillNode->updateFilling( window,
104 shadowRect, shadowShape, shadowColor );
105 }
106 else
107 {
108 shadowNode = qskNode< QskBoxShadowNode >( this, ShadowRole );
109 shadowNode->setShadowData( shadowRect,
110 shadowShape, shadow.blurRadius(), shadowColor );
111 }
112 }
113
114 if ( hasBorder || hasFilling )
115 {
116 rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
117
118 if ( hasBorder && hasFilling )
119 {
120 const bool doCombine = rectNode->hasHint( QskFillNode::PreferColoredGeometry )
121 && QskBoxRectangleNode::isCombinedGeometrySupported( gradient );
122
123 if ( !doCombine )
124 fillNode = qskNode< QskBoxRectangleNode >( this, FillRole );
125 }
126
127 if ( fillNode )
128 {
129 rectNode->updateBorder( window, rect,
130 shapeMetrics, borderMetrics, borderColors );
131
132 fillNode->updateFilling( window, rect,
133 shapeMetrics, borderMetrics, gradient );
134 }
135 else
136 {
137 rectNode->updateBox( window, rect,
138 shapeMetrics, borderMetrics, borderColors, gradient );
139 }
140 }
141 }
142
143 qskUpdateChildren( this, ShadowRole, shadowNode );
144 qskUpdateChildren( this, ShadowFillRole, shadowFillNode );
145 qskUpdateChildren( this, BoxRole, rectNode );
146 qskUpdateChildren( this, FillRole, fillNode );
147}