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 class PaintedRectangleItem; 13 14 /** 15 * Grouped property for rectangle border. 16 */ 17 class BorderGroup : public QObject 18 { 19 Q_OBJECT 20 /** 21 * The width of the border in pixels. 22 * 23 * Default is 0. 24 */ 25 Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY changed) 26 /** 27 * The color of the border. 28 * 29 * Full RGBA colors are supported. The default is fully opaque black. 30 */ 31 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed) 32 33 public: 34 explicit BorderGroup(QObject *parent = nullptr); 35 36 qreal width() const; 37 void setWidth(qreal newWidth); 38 39 QColor color() const; 40 void setColor(const QColor &newColor); 41 42 Q_SIGNAL void changed(); 43 isEnabled()44 inline bool isEnabled() const 45 { 46 return !qFuzzyIsNull(m_width); 47 } 48 49 private: 50 qreal m_width = 0.0; 51 QColor m_color = Qt::black; 52 }; 53 54 /** 55 * Grouped property for rectangle shadow. 56 */ 57 class ShadowGroup : public QObject 58 { 59 Q_OBJECT 60 /** 61 * The size of the shadow. 62 * 63 * This is the approximate size of the shadow in pixels. However, due to falloff 64 * the actual shadow size can differ. The default is 0, which means no shadow will 65 * be rendered. 66 */ 67 Q_PROPERTY(qreal size READ size WRITE setSize NOTIFY changed) 68 /** 69 * Offset of the shadow on the X axis. 70 * 71 * In pixels. The default is 0. 72 */ 73 Q_PROPERTY(qreal xOffset READ xOffset WRITE setXOffset NOTIFY changed) 74 /** 75 * Offset of the shadow on the Y axis. 76 * 77 * In pixels. The default is 0. 78 */ 79 Q_PROPERTY(qreal yOffset READ yOffset WRITE setYOffset NOTIFY changed) 80 /** 81 * The color of the shadow. 82 * 83 * Full RGBA colors are supported. The default is fully opaque black. 84 */ 85 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed) 86 87 public: 88 explicit ShadowGroup(QObject *parent = nullptr); 89 90 qreal size() const; 91 void setSize(qreal newSize); 92 93 qreal xOffset() const; 94 void setXOffset(qreal newXOffset); 95 96 qreal yOffset() const; 97 void setYOffset(qreal newYOffset); 98 99 QColor color() const; 100 void setColor(const QColor &newShadowColor); 101 102 Q_SIGNAL void changed(); 103 104 private: 105 qreal m_size = 0.0; 106 qreal m_xOffset = 0.0; 107 qreal m_yOffset = 0.0; 108 QColor m_color = Qt::black; 109 }; 110 111 /** 112 * Grouped property for corner radius. 113 */ 114 class CornersGroup : public QObject 115 { 116 Q_OBJECT 117 /** 118 * The radius of the top-left corner. 119 * 120 * In pixels. Defaults to -1, which indicates this value should not be used. 121 */ 122 Q_PROPERTY(qreal topLeftRadius READ topLeft WRITE setTopLeft NOTIFY changed) 123 /** 124 * The radius of the top-right corner. 125 * 126 * In pixels. Defaults to -1, which indicates this value should not be used. 127 */ 128 Q_PROPERTY(qreal topRightRadius READ topRight WRITE setTopRight NOTIFY changed) 129 /** 130 * The radius of the bottom-left corner. 131 * 132 * In pixels. Defaults to -1, which indicates this value should not be used. 133 */ 134 Q_PROPERTY(qreal bottomLeftRadius READ bottomLeft WRITE setBottomLeft NOTIFY changed) 135 /** 136 * The radius of the bottom-right corner. 137 * 138 * In pixels. Defaults to -1, which indicates this value should not be used. 139 */ 140 Q_PROPERTY(qreal bottomRightRadius READ bottomRight WRITE setBottomRight NOTIFY changed) 141 142 public: 143 explicit CornersGroup(QObject *parent = nullptr); 144 145 qreal topLeft() const; 146 void setTopLeft(qreal newTopLeft); 147 148 qreal topRight() const; 149 void setTopRight(qreal newTopRight); 150 151 qreal bottomLeft() const; 152 void setBottomLeft(qreal newBottomLeft); 153 154 qreal bottomRight() const; 155 void setBottomRight(qreal newBottomRight); 156 157 Q_SIGNAL void changed(); 158 159 QVector4D toVector4D(float all) const; 160 161 private: 162 float m_topLeft = -1.0; 163 float m_topRight = -1.0; 164 float m_bottomLeft = -1.0; 165 float m_bottomRight = -1.0; 166 }; 167 168 /** 169 * A rectangle with a shadow. 170 * 171 * This item will render a rectangle, with a shadow below it. The rendering is done 172 * using distance fields, which provide greatly improved performance. The shadow is 173 * rendered outside of the item's bounds, so the item's width and height are the 174 * rectangle's width and height. 175 * 176 * @since 5.69 / 2.12 177 */ 178 class ShadowedRectangle : public QQuickItem 179 { 180 Q_OBJECT 181 /** 182 * Corner radius of the rectangle. 183 * 184 * This is the amount of rounding to apply to all of the rectangle's 185 * corners, in pixels. Individual corners can have a different radius, see 186 * \property corners. 187 * 188 * The default is 0. 189 */ 190 Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged) 191 /** 192 * The color of the rectangle. 193 * 194 * Full RGBA colors are supported. The default is fully opaque white. 195 */ 196 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 197 /** 198 * Border properties. 199 * 200 * \sa BorderGroup 201 */ 202 Q_PROPERTY(BorderGroup *border READ border CONSTANT) 203 /** 204 * Shadow properties. 205 * 206 * \sa ShadowGroup 207 */ 208 Q_PROPERTY(ShadowGroup *shadow READ shadow CONSTANT) 209 /** 210 * Corner radius. 211 * 212 * Note that the values from this group override \property radius for the 213 * corner they affect. 214 * 215 * \sa CornerGroup 216 */ 217 Q_PROPERTY(CornersGroup *corners READ corners CONSTANT) 218 219 Q_PROPERTY(bool softwareRendering READ isSoftwareRendering NOTIFY softwareRenderingChanged) 220 public: 221 ShadowedRectangle(QQuickItem *parent = nullptr); 222 ~ShadowedRectangle() override; 223 224 BorderGroup *border() const; 225 ShadowGroup *shadow() const; 226 CornersGroup *corners() const; 227 228 qreal radius() const; 229 void setRadius(qreal newRadius); 230 Q_SIGNAL void radiusChanged(); 231 232 QColor color() const; 233 void setColor(const QColor &newColor); 234 Q_SIGNAL void colorChanged(); 235 236 void componentComplete() override; 237 238 bool isSoftwareRendering() const; 239 240 Q_SIGNALS: 241 void softwareRenderingChanged(); 242 243 protected: 244 PaintedRectangleItem *softwareItem() const; 245 void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override; 246 QSGNode *updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *data) override; 247 248 private: 249 void checkSoftwareItem(); 250 const std::unique_ptr<BorderGroup> m_border; 251 const std::unique_ptr<ShadowGroup> m_shadow; 252 const std::unique_ptr<CornersGroup> m_corners; 253 qreal m_radius = 0.0; 254 QColor m_color = Qt::white; 255 PaintedRectangleItem *m_softwareItem = nullptr; 256 }; 257