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 | |
14 | class ShaderNode; |
15 | |
16 | class 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 | |
26 | public: |
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 | |
42 | private: |
43 | qreal m_width = 0.0; |
44 | QColor m_color = Qt::black; |
45 | }; |
46 | |
47 | class 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 | |
61 | public: |
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 | |
78 | private: |
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 | |
85 | class 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 | |
99 | public: |
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 | |
118 | private: |
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 | */ |
138 | class 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 | |
257 | public: |
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 | |
298 | Q_SIGNALS: |
299 | void softwareRenderingChanged(); |
300 | |
301 | protected: |
302 | bool isSoftwareRendering() const; |
303 | bool isLowPowerRendering() const; |
304 | |
305 | QSGNode *updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *data) override; |
306 | void updateShaderNode(ShaderNode *shaderNode); |
307 | |
308 | private: |
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 | |