QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskBoxShapeMetrics.h
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#ifndef QSK_BOX_SHAPE_METRICS_H
7#define QSK_BOX_SHAPE_METRICS_H
8
9#include "QskGlobal.h"
10
11#include <qmetatype.h>
12#include <qnamespace.h>
13#include <qsize.h>
14
15class QVariant;
16
17class QSK_EXPORT QskBoxShapeMetrics
18{
19 Q_GADGET
20
21 Q_PROPERTY( QSizeF topLeft READ topLeft WRITE setTopLeft )
22 Q_PROPERTY( QSizeF topRight READ topRight WRITE setTopRight )
23 Q_PROPERTY( QSizeF bottomLeft READ bottomLeft WRITE setBottomLeft )
24 Q_PROPERTY( QSizeF bottomRight READ bottomRight WRITE setBottomRight )
25
26 Q_PROPERTY( qreal radius READ radiusX WRITE setRadius )
27
28 Q_PROPERTY( Qt::SizeMode sizeMode READ sizeMode WRITE setSizeMode )
29 Q_PROPERTY( ScalingMode scalingMode READ scalingMode WRITE setScalingMode )
30
31 public:
32 /*
33 How to scale, when translating to Qt::AbsoluteSize
34
35 Symmetric/SymmetricByMaximum sets the aspect ratio between x/y radii
36 to 1:1, while Proportional preserves the aspect ratio of the relative radii.
37
38 Symmetric or Proportional shrink the larger radius, while SymmetricByMaximum
39 expands the smaller radius to achieve the desired aspect ratio.
40
41 The effect of the scaling on the implemented box rendering is:
42
43 - SymmetricByMaximum in combination with a relative radius of 100
44 results in an ellipse.
45
46 - Rectangles with rounded corners can be achieved by Symmetric in combination
47 with a relative radius < 100.
48
49 Note, that the scaling is affected by the aspect ratio of the relative radii and
50 the one of the absolute size.
51
52 The default setting is Symmetric.
53 */
54
55 enum ScalingMode
56 {
57 Symmetric,
58 SymmetricByMaximum,
59
60 Proportional
61 };
62 Q_ENUM( ScalingMode )
63
64 constexpr QskBoxShapeMetrics() noexcept;
65
66 constexpr QskBoxShapeMetrics( qreal topLeft, qreal topRight,
67 qreal bottomLeft, qreal bottomRight, Qt::SizeMode = Qt::AbsoluteSize ) noexcept;
68
69 constexpr QskBoxShapeMetrics(
70 qreal radius, Qt::SizeMode = Qt::AbsoluteSize ) noexcept;
71
72 constexpr QskBoxShapeMetrics( qreal radiusX, qreal radiusY,
73 Qt::SizeMode = Qt::AbsoluteSize ) noexcept;
74
75 constexpr bool operator==( const QskBoxShapeMetrics& ) const noexcept;
76 constexpr bool operator!=( const QskBoxShapeMetrics& ) const noexcept;
77
78 void setRadius( qreal radius ) noexcept;
79 void setRadius( qreal radius, Qt::SizeMode ) noexcept;
80 void setRadius( Qt::Corner, qreal radius ) noexcept;
81
82 void setRadius( qreal radiusX, qreal radiusY ) noexcept;
83 void setRadius( const QSizeF& ) noexcept;
84 void setRadius( Qt::Corner, qreal radiusX, qreal radiusY ) noexcept;
85 void setRadius( Qt::Corner, const QSizeF& radius ) noexcept;
86
87 void setRadius( qreal topLeft, qreal topRight,
88 qreal bottomLeft, qreal bottomRight ) noexcept;
89
90 void setRadius( const QSizeF& topLeft, const QSizeF& topRight,
91 const QSizeF& bottomLeft, const QSizeF& bottomRight ) noexcept;
92
93 void setRadius(
94 qreal topLeftX, qreal topLeftY,
95 qreal topRightX, qreal topRightY,
96 qreal bottomLeftX, qreal bottomLeftY,
97 qreal bottomRightX, qreal bottomRightY ) noexcept;
98
99 constexpr QSizeF radius( Qt::Corner ) const noexcept;
100
101 constexpr QSizeF topLeft() const noexcept;
102 constexpr QSizeF topRight() const noexcept;
103 constexpr QSizeF bottomLeft() const noexcept;
104 constexpr QSizeF bottomRight() const noexcept;
105
106 void setTopLeft( const QSizeF& ) noexcept;
107 void setTopRight( const QSizeF& ) noexcept;
108 void setBottomLeft( const QSizeF& ) noexcept;
109 void setBottomRight( const QSizeF& ) noexcept;
110
111 constexpr bool isRectangle() const noexcept;
112 constexpr bool isRectellipse() const noexcept;
113
114 void setSizeMode( Qt::SizeMode ) noexcept;
115 constexpr Qt::SizeMode sizeMode() const noexcept;
116
117 void setScalingMode( ScalingMode ) noexcept;
118 constexpr ScalingMode scalingMode() const noexcept;
119
120 QskBoxShapeMetrics interpolated(
121 const QskBoxShapeMetrics&, qreal value ) const noexcept;
122
123 QskBoxShapeMetrics toAbsolute( const QSizeF& ) const noexcept;
124
125 constexpr QskBoxShapeMetrics transposed() const noexcept;
126
127 QskHashValue hash( QskHashValue seed = 0 ) const noexcept;
128
129 static QVariant interpolate( const QskBoxShapeMetrics&,
130 const QskBoxShapeMetrics&, qreal progress ) noexcept;
131
132 private:
133 // dummy getter to suppress moc warnings
134 inline qreal radiusX() const { return radius( Qt::TopLeftCorner ).width(); }
135
136 inline constexpr QskBoxShapeMetrics(
137 const QSizeF& topLeft, const QSizeF& topRight,
138 const QSizeF& bottomLeft, const QSizeF& bottomRight,
139 Qt::SizeMode sizeMode, ScalingMode scalingMode ) noexcept
140 : m_radii{ topLeft, topRight, bottomLeft, bottomRight }
141 , m_sizeMode( sizeMode )
142 , m_scalingMode( scalingMode )
143 {
144 }
145
146 QSizeF m_radii[ 4 ];
147 Qt::SizeMode m_sizeMode : 2;
148 ScalingMode m_scalingMode : 2;
149};
150
151inline constexpr QskBoxShapeMetrics::QskBoxShapeMetrics() noexcept
152 : m_radii{ { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 } }
153 , m_sizeMode( Qt::AbsoluteSize )
154 , m_scalingMode( Symmetric )
155{
156}
157
158inline constexpr QskBoxShapeMetrics::QskBoxShapeMetrics(
159 qreal radius, Qt::SizeMode sizeMode ) noexcept
160 : QskBoxShapeMetrics( radius, radius, sizeMode )
161{
162}
163
164inline constexpr QskBoxShapeMetrics::QskBoxShapeMetrics(
165 qreal radiusX, qreal radiusY, Qt::SizeMode sizeMode ) noexcept
166 : m_radii{ { radiusX, radiusY }, { radiusX, radiusY },
167 { radiusX, radiusY }, { radiusX, radiusY } }
168 , m_sizeMode( sizeMode )
169 , m_scalingMode( Symmetric )
170{
171}
172
173inline constexpr QskBoxShapeMetrics::QskBoxShapeMetrics( qreal topLeft, qreal topRight,
174 qreal bottomLeft, qreal bottomRight, Qt::SizeMode sizeMode ) noexcept
175 : m_radii{ { topLeft, topLeft }, { topRight, topRight },
176 { bottomLeft, bottomLeft }, { bottomRight, bottomRight } }
177 , m_sizeMode( sizeMode )
178 , m_scalingMode( Symmetric )
179{
180}
181
182inline constexpr bool QskBoxShapeMetrics::operator==(
183 const QskBoxShapeMetrics& other ) const noexcept
184{
185 return ( m_sizeMode == other.m_sizeMode )
186 && ( m_scalingMode == other.m_scalingMode )
187 && ( m_radii[ 0 ] == other.m_radii[ 0 ] )
188 && ( m_radii[ 1 ] == other.m_radii[ 1 ] )
189 && ( m_radii[ 2 ] == other.m_radii[ 2 ] )
190 && ( m_radii[ 3 ] == other.m_radii[ 3 ] );
191}
192
193inline constexpr bool QskBoxShapeMetrics::operator!=(
194 const QskBoxShapeMetrics& other ) const noexcept
195{
196 return !( *this == other );
197}
198
199inline void QskBoxShapeMetrics::setRadius( qreal radius ) noexcept
200{
201 setRadius( radius, radius );
202}
203
204inline void QskBoxShapeMetrics::setRadius( qreal radius, Qt::SizeMode sizeMode ) noexcept
205{
206 setRadius( radius );
207 setSizeMode( sizeMode );
208}
209
210inline void QskBoxShapeMetrics::setRadius( qreal radiusX, qreal radiusY ) noexcept
211{
212 setRadius( radiusX, radiusY, radiusX, radiusY,
213 radiusX, radiusY, radiusX, radiusY );
214}
215
216inline void QskBoxShapeMetrics::setRadius( const QSizeF& radius ) noexcept
217{
218 setRadius( radius.width(), radius.height() );
219}
220
221inline void QskBoxShapeMetrics::setRadius( Qt::Corner corner, qreal radius ) noexcept
222{
223 setRadius( corner, radius, radius );
224}
225
226inline void QskBoxShapeMetrics::setRadius( Qt::Corner corner, const QSizeF& radius ) noexcept
227{
228 setRadius( corner, radius.width(), radius.height() );
229}
230
231inline void QskBoxShapeMetrics::setRadius(
232 qreal topLeft, qreal topRight, qreal bottomLeft, qreal bottomRight ) noexcept
233{
234 setRadius( topLeft, topLeft, topRight, topRight,
235 bottomLeft, bottomLeft, bottomRight, bottomRight );
236}
237
238inline void QskBoxShapeMetrics::setRadius(
239 const QSizeF& topLeft, const QSizeF& topRight,
240 const QSizeF& bottomLeft, const QSizeF& bottomRight ) noexcept
241{
242 setRadius( topLeft.width(), topLeft.height(),
243 topRight.width(), topRight.height(),
244 bottomLeft.width(), bottomLeft.height(),
245 bottomRight.width(), bottomRight.height() );
246}
247
248inline constexpr QSizeF QskBoxShapeMetrics::radius( Qt::Corner corner ) const noexcept
249{
250 return ( ( static_cast< int >( corner ) >= 0 ) && ( static_cast< int >( corner ) < 4 ) )
251 ? m_radii[ corner ] : QSizeF();
252}
253
254inline constexpr QSizeF QskBoxShapeMetrics::topLeft() const noexcept
255{
256 return radius( Qt::TopLeftCorner );
257}
258
259inline constexpr QSizeF QskBoxShapeMetrics::topRight() const noexcept
260{
261 return radius( Qt::TopRightCorner );
262}
263
264inline constexpr QSizeF QskBoxShapeMetrics::bottomLeft() const noexcept
265{
266 return radius( Qt::BottomLeftCorner );
267}
268
269inline constexpr QSizeF QskBoxShapeMetrics::bottomRight() const noexcept
270{
271 return radius( Qt::BottomRightCorner );
272}
273
274inline void QskBoxShapeMetrics::setSizeMode( Qt::SizeMode sizeMode ) noexcept
275{
276 m_sizeMode = sizeMode;
277}
278
279inline constexpr Qt::SizeMode QskBoxShapeMetrics::sizeMode() const noexcept
280{
281 return m_sizeMode;
282}
283
284inline void QskBoxShapeMetrics::setScalingMode( ScalingMode scalingMode ) noexcept
285{
286 m_scalingMode = scalingMode;
287}
288
289inline constexpr QskBoxShapeMetrics::ScalingMode
290 QskBoxShapeMetrics::scalingMode() const noexcept
291{
292 return m_scalingMode;
293}
294
295inline constexpr bool QskBoxShapeMetrics::isRectellipse() const noexcept
296{
297 return ( m_radii[ 1 ] == m_radii[ 0 ] )
298 && ( m_radii[ 2 ] == m_radii[ 1 ] )
299 && ( m_radii[ 3 ] == m_radii[ 2 ] );
300}
301
302inline constexpr bool QskBoxShapeMetrics::isRectangle() const noexcept
303{
304 return ( ( ( m_radii[ 0 ].width() <= 0.0 ) && ( m_radii[ 0 ].height() <= 0.0 ) )
305 && ( ( m_radii[ 1 ].width() <= 0.0 ) && ( m_radii[ 1 ].height() <= 0.0 ) )
306 && ( ( m_radii[ 2 ].width() <= 0.0 ) && ( m_radii[ 2 ].height() <= 0.0 ) )
307 && ( ( m_radii[ 3 ].width() <= 0.0 ) && ( m_radii[ 3 ].height() <= 0.0 ) ) );
308}
309
310inline constexpr QskBoxShapeMetrics QskBoxShapeMetrics::transposed() const noexcept
311{
312 return QskBoxShapeMetrics(
313 m_radii[ 0 ].transposed(), m_radii[ 1 ].transposed(),
314 m_radii[ 2 ].transposed(), m_radii[ 3 ].transposed(),
315 m_sizeMode, m_scalingMode );
316}
317
318#ifndef QT_NO_DEBUG_STREAM
319
320QSK_EXPORT QDebug operator<<( QDebug, const QskBoxShapeMetrics& );
321
322#endif
323
324Q_DECLARE_TYPEINFO( QskBoxShapeMetrics, Q_MOVABLE_TYPE );
325Q_DECLARE_METATYPE( QskBoxShapeMetrics )
326
327#endif