1/*
2 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#pragma once
8
9#include <QQuickItem>
10#include <memory>
11
12#include <QQmlEngine>
13
14class ShaderNode;
15
16class BorderGroup : public QObject
17{
18 Q_OBJECT
19 QML_ELEMENT
20 QML_UNCREATABLE("")
21
22 Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY changed FINAL)
23
24 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed FINAL)
25
26public:
27 explicit BorderGroup(QObject *parent = nullptr);
28
29 qreal width() const;
30 void setWidth(qreal newWidth);
31
32 QColor color() const;
33 void setColor(const QColor &newColor);
34
35 Q_SIGNAL void changed();
36
37 inline bool isEnabled() const
38 {
39 return !qFuzzyIsNull(d: m_width);
40 }
41
42private:
43 qreal m_width = 0.0;
44 QColor m_color = Qt::black;
45};
46
47class ShadowGroup : public QObject
48{
49 Q_OBJECT
50 QML_ELEMENT
51 QML_UNCREATABLE("")
52
53 Q_PROPERTY(qreal size READ size WRITE setSize NOTIFY changed FINAL)
54
55 Q_PROPERTY(qreal xOffset READ xOffset WRITE setXOffset NOTIFY changed FINAL)
56
57 Q_PROPERTY(qreal yOffset READ yOffset WRITE setYOffset NOTIFY changed FINAL)
58
59 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed FINAL)
60
61public:
62 explicit ShadowGroup(QObject *parent = nullptr);
63
64 qreal size() const;
65 void setSize(qreal newSize);
66
67 qreal xOffset() const;
68 void setXOffset(qreal newXOffset);
69
70 qreal yOffset() const;
71 void setYOffset(qreal newYOffset);
72
73 QColor color() const;
74 void setColor(const QColor &newShadowColor);
75
76 Q_SIGNAL void changed();
77
78private:
79 qreal m_size = 0.0;
80 qreal m_xOffset = 0.0;
81 qreal m_yOffset = 0.0;
82 QColor m_color = Qt::black;
83};
84
85class CornersGroup : public QObject
86{
87 Q_OBJECT
88 QML_ELEMENT
89 QML_UNCREATABLE("")
90
91 Q_PROPERTY(qreal topLeftRadius READ topLeft WRITE setTopLeft NOTIFY changed FINAL)
92
93 Q_PROPERTY(qreal topRightRadius READ topRight WRITE setTopRight NOTIFY changed FINAL)
94
95 Q_PROPERTY(qreal bottomLeftRadius READ bottomLeft WRITE setBottomLeft NOTIFY changed FINAL)
96
97 Q_PROPERTY(qreal bottomRightRadius READ bottomRight WRITE setBottomRight NOTIFY changed FINAL)
98
99public:
100 explicit CornersGroup(QObject *parent = nullptr);
101
102 qreal topLeft() const;
103 void setTopLeft(qreal newTopLeft);
104
105 qreal topRight() const;
106 void setTopRight(qreal newTopRight);
107
108 qreal bottomLeft() const;
109 void setBottomLeft(qreal newBottomLeft);
110
111 qreal bottomRight() const;
112 void setBottomRight(qreal newBottomRight);
113
114 Q_SIGNAL void changed();
115
116 QVector4D toVector4D(float all) const;
117
118private:
119 float m_topLeft = -1.0;
120 float m_topRight = -1.0;
121 float m_bottomLeft = -1.0;
122 float m_bottomRight = -1.0;
123};
124
125/*!
126 * \qmltype ShadowedRectangle
127 * \inqmlmodule org.kde.kirigami.primitives
128 *
129 * \brief A rectangle with a shadow behind it.
130 *
131 * This item will render a rectangle, with a shadow below it. The rendering is done
132 * using distance fields, which provide greatly improved performance. The shadow is
133 * rendered outside of the item's bounds, so the item's width and height are the
134 * rectangle's width and height.
135 *
136 * \since 5.69
137 */
138class ShadowedRectangle : public QQuickItem
139{
140 Q_OBJECT
141 QML_ELEMENT
142 /*!
143 * \qmlproperty real ShadowedRectangle::radius
144 *
145 * \brief This property holds the radii of the rectangle's corners.
146 *
147 * This is the amount of rounding to apply to all of the rectangle's
148 * corners, in pixels. Each corner can have a different radius.
149 *
150 * default: 0
151 */
152 Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged FINAL)
153
154 /*!
155 * \qmlproperty color ShadowedRectangle::color
156 * \brief This property holds the rectangle's color.
157 *
158 * Full RGBA colors are supported.
159 *
160 * default: Qt.white
161 */
162 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
163
164 /*!
165 * \qmlproperty real ShadowedRectangle::border.width
166 * \qmlproperty color ShadowedRectangle::border.color
167 *
168 * \brief This property holds the border's grouped property.
169 *
170 * width: The border's width in pixels. Default: 0
171 *
172 * color: The border's color. Full RGBA colors are supported. Default: Qt.black
173 *
174 * Example usage:
175 * \code
176 * Kirigami.ShadowedRectangle {
177 * border.width: 2
178 * border.color: Kirigami.Theme.textColor
179 * }
180 * \endcode
181 */
182 Q_PROPERTY(BorderGroup *border READ border CONSTANT FINAL)
183
184 /*!
185 * \qmlproperty real ShadowedRectangle::shadow.size
186 * \qmlproperty real ShadowedRectangle::shadow.xOffset
187 * \qmlproperty real ShadowedRectangle::shadow.yOffset
188 * \qmlproperty color ShadowedRectangle::shadow.color
189 *
190 * \brief This property group holds the shadow's properties.
191 *
192 * size: The shadow's approximate size in pixels. Note: The actual shadow size can be less than this value due to falloff. Default: 0px
193 *
194 * xOffset: The shadow's offset in pixels on the X axis. Default: 0px
195 *
196 * yOffset: The shadow's offset in pixels on the Y axis. Default: 0px
197 *
198 * color: The shadow's color. Full RGBA colors are supported. Default: Qt.black
199 *
200 * Example usage:
201 * \code
202 * Kirigami.ShadowedRectangle {
203 * shadow.size: 20
204 * shadow.xOffset: 5
205 * shadow.yOffset: 5
206 * }
207 * \endcode
208 */
209 Q_PROPERTY(ShadowGroup *shadow READ shadow CONSTANT FINAL)
210
211 /*!
212 * \qmlproperty real ShadowedRectangle::corners.topLeftRadius
213 * \qmlproperty real ShadowedRectangle::corners.topRightRadius
214 * \qmlproperty real ShadowedRectangle::corners.bottomLeftRadius
215 * \qmlproperty real ShadowedRectangle::corners.bottomRightRadius
216 *
217 * \brief This property holds the corners grouped property
218 *
219 * Note that the values from this group override the radius property for the
220 * corner they affect.
221 *
222 * Setting any value to -1 indicates that the value should be ignored.
223 *
224 * The default value is -1
225 *
226 * Example usage:
227 * \code
228 * Kirigami.ShadowedRectangle {
229 * corners.topLeftRadius: 4
230 * corners.topRightRadius: 5
231 * corners.bottomLeftRadius: 2
232 * corners.bottomRightRadius: 10
233 * \endcode
234 */
235 Q_PROPERTY(CornersGroup *corners READ corners CONSTANT FINAL)
236
237 /*!
238 * \qmlproperty enumeration ShadowedRectangle::renderType
239 *
240 * \brief This property holds the rectangle's render mode.
241 *
242 * \qmlenumeratorsfrom ShadowedRectangle::RenderType
243 *
244 * default: RenderType.Auto
245 */
246 Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged FINAL)
247
248 /*!
249 * \qmlproperty bool ShadowedRectangle::softwareRendering
250 *
251 * \brief This property tells whether software rendering is being used.
252 *
253 * default: false
254 */
255 Q_PROPERTY(bool softwareRendering READ isSoftwareRendering NOTIFY softwareRenderingChanged FINAL)
256
257public:
258 ShadowedRectangle(QQuickItem *parent = nullptr);
259 ~ShadowedRectangle() override;
260
261 /*!
262 * \brief Available rendering types for ShadowedRectangle.
263 *
264 * \value Auto Automatically determine the optimal rendering type. This will use the highest rendering quality possible, falling back to lower quality if
265 * the hardware doesn't support it. It will use software rendering if the QtQuick scene graph is set to use software rendering.
266 * \value HighQuality Use the highest rendering quality possible, even if the hardware might not be able to handle it normally.
267 * \value LowQuality Use the lowest rendering quality, even if the hardware could handle higher quality rendering. This might result in certain effects
268 * being omitted, like shadows.
269 * \value Software Always use software rendering for this rectangle. Software rendering is intended as a fallback when the QtQuick scene graph is configured
270 * to use software rendering. It will result in a number of missing features, like shadows and multiple corner radii.
271 */
272 enum RenderType {
273 Auto,
274 HighQuality,
275 LowQuality,
276 Software
277 };
278 Q_ENUM(RenderType)
279
280 BorderGroup *border() const;
281 ShadowGroup *shadow() const;
282 CornersGroup *corners() const;
283
284 qreal radius() const;
285 void setRadius(qreal newRadius);
286 Q_SIGNAL void radiusChanged();
287
288 QColor color() const;
289 void setColor(const QColor &newColor);
290 Q_SIGNAL void colorChanged();
291
292 RenderType renderType() const;
293 void setRenderType(RenderType renderType);
294 Q_SIGNAL void renderTypeChanged();
295
296 void componentComplete() override;
297
298Q_SIGNALS:
299 void softwareRenderingChanged();
300
301protected:
302 bool isSoftwareRendering() const;
303 bool isLowPowerRendering() const;
304
305 QSGNode *updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *data) override;
306 void updateShaderNode(ShaderNode *shaderNode);
307
308private:
309 const std::unique_ptr<BorderGroup> m_border;
310 const std::unique_ptr<ShadowGroup> m_shadow;
311 const std::unique_ptr<CornersGroup> m_corners;
312 qreal m_radius = 0.0;
313 QColor m_color = Qt::white;
314 RenderType m_renderType = RenderType::Auto;
315};
316

source code of kirigami/src/primitives/shadowedrectangle.h