1 | /* |
2 | * SPDX-FileCopyrightText: 2021 Jonah BrĂ¼chert <jbb@kaidan.im> |
3 | * SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org> |
4 | * |
5 | * SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #ifndef KIRIGAMI_UNITS_H |
9 | #define KIRIGAMI_UNITS_H |
10 | |
11 | #include <memory> |
12 | |
13 | #include <QObject> |
14 | #include <QQmlEngine> |
15 | |
16 | #include "kirigamiplatform_export.h" |
17 | |
18 | class QQmlEngine; |
19 | |
20 | namespace Kirigami |
21 | { |
22 | namespace Platform |
23 | { |
24 | class Units; |
25 | class UnitsPrivate; |
26 | |
27 | // TODO qdoc should this be documented as C++ API? |
28 | class KIRIGAMIPLATFORM_EXPORT IconSizes : public QObject |
29 | { |
30 | Q_OBJECT |
31 | QML_ELEMENT |
32 | QML_UNCREATABLE("Grouped Property" ) |
33 | |
34 | Q_PROPERTY(int sizeForLabels READ sizeForLabels NOTIFY sizeForLabelsChanged FINAL) |
35 | Q_PROPERTY(int small READ small NOTIFY smallChanged FINAL) |
36 | Q_PROPERTY(int smallMedium READ smallMedium NOTIFY smallMediumChanged FINAL) |
37 | Q_PROPERTY(int medium READ medium NOTIFY mediumChanged FINAL) |
38 | Q_PROPERTY(int large READ large NOTIFY largeChanged FINAL) |
39 | Q_PROPERTY(int huge READ huge NOTIFY hugeChanged FINAL) |
40 | Q_PROPERTY(int enormous READ enormous NOTIFY enormousChanged FINAL) |
41 | |
42 | public: |
43 | IconSizes(Units *units); |
44 | |
45 | int sizeForLabels() const; |
46 | int small() const; |
47 | int smallMedium() const; |
48 | int medium() const; |
49 | int large() const; |
50 | int huge() const; |
51 | int enormous() const; |
52 | |
53 | Q_INVOKABLE int roundedIconSize(int size) const; |
54 | |
55 | private: |
56 | KIRIGAMIPLATFORM_NO_EXPORT float iconScaleFactor() const; |
57 | |
58 | Units *m_units; |
59 | |
60 | Q_SIGNALS: |
61 | void sizeForLabelsChanged(); |
62 | void smallChanged(); |
63 | void smallMediumChanged(); |
64 | void mediumChanged(); |
65 | void largeChanged(); |
66 | void hugeChanged(); |
67 | void enormousChanged(); |
68 | }; |
69 | |
70 | /*! |
71 | * \qmltype Units |
72 | * \inqmlmodule org.kde.kirigami.platform |
73 | * \nativetype Kirigami::Platform::Units |
74 | * |
75 | * \brief A set of values to define semantically sizes and durations. |
76 | */ |
77 | /*! |
78 | * \class Kirigami::Platform::Units |
79 | * \inheaderfile Kirigami/Platform/Units |
80 | * \inmodule KirigamiPlatform |
81 | * |
82 | * \brief A set of values to define semantically sizes and durations. |
83 | */ |
84 | class KIRIGAMIPLATFORM_EXPORT Units : public QObject |
85 | { |
86 | Q_OBJECT |
87 | QML_ELEMENT |
88 | QML_SINGLETON |
89 | |
90 | friend class IconSizes; |
91 | |
92 | /*! |
93 | * \qmlproperty int Units::gridUnit |
94 | * |
95 | * The fundamental unit of space that should be used for sizes, expressed in pixels. |
96 | */ |
97 | /*! |
98 | * \property Kirigami::Platform::Units::gridUnit |
99 | * |
100 | * The fundamental unit of space that should be used for sizes, expressed in pixels. |
101 | */ |
102 | Q_PROPERTY(int gridUnit READ gridUnit NOTIFY gridUnitChanged FINAL) |
103 | |
104 | /*! |
105 | * \qmlproperty int Units::iconSizes.sizeForLabels |
106 | * \qmlproperty int Units::iconSizes.small |
107 | * \qmlproperty int Units::iconSizes.smallMedium |
108 | * \qmlproperty int Units::iconSizes.medium |
109 | * \qmlproperty int Units::iconSizes.large |
110 | * \qmlproperty int Units::iconSizes.huge |
111 | * \qmlproperty int Units::iconSizes.enormous |
112 | * |
113 | * The units.iconSizes group provides access to platform-dependent icon sizing. |
114 | * |
115 | * The icon sizes provided are normalized for different DPI, so icons |
116 | * will scale depending on the DPI. |
117 | * |
118 | * \list |
119 | * \li sizeForLabels (the largest icon size that fits within fontMetrics.height) |
120 | * \li small |
121 | * \li smallMedium |
122 | * \li medium |
123 | * \li large |
124 | * \li huge |
125 | * \li enormous |
126 | * \endlist |
127 | */ |
128 | /*! |
129 | * \property Kirigami::Platform::Units::iconSizes |
130 | */ |
131 | Q_PROPERTY(Kirigami::Platform::IconSizes *iconSizes READ iconSizes CONSTANT FINAL) |
132 | |
133 | /*! |
134 | * \qmlproperty int Units::smallSpacing |
135 | * |
136 | * This property holds the amount of spacing that should be used between smaller UI elements, |
137 | * such as a small icon and a label in a button. |
138 | */ |
139 | /*! |
140 | * \property Kirigami::Platform::Units::smallSpacing |
141 | * |
142 | * This property holds the amount of spacing that should be used between smaller UI elements, |
143 | * such as a small icon and a label in a button. |
144 | */ |
145 | Q_PROPERTY(int smallSpacing READ smallSpacing NOTIFY smallSpacingChanged FINAL) |
146 | |
147 | /*! |
148 | * \qmlproperty int Units::mediumSpacing |
149 | * |
150 | * This property holds the amount of spacing that should be used between medium UI elements, |
151 | * such as buttons and text fields in a toolbar. |
152 | */ |
153 | /*! |
154 | * \property Kirigami::Platform::Units::mediumSpacing |
155 | * |
156 | * This property holds the amount of spacing that should be used between medium UI elements, |
157 | * such as buttons and text fields in a toolbar. |
158 | */ |
159 | Q_PROPERTY(int mediumSpacing READ mediumSpacing NOTIFY mediumSpacingChanged FINAL) |
160 | |
161 | /*! |
162 | * \qmlproperty int Units::largeSpacing |
163 | * |
164 | * This property holds the amount of spacing that should be used between bigger UI elements, |
165 | * such as a large icon and a heading in a card. |
166 | */ |
167 | /*! |
168 | * \property Kirigami::Platform::Units::largeSpacing |
169 | * |
170 | * This property holds the amount of spacing that should be used between bigger UI elements, |
171 | * such as a large icon and a heading in a card. |
172 | */ |
173 | Q_PROPERTY(int largeSpacing READ largeSpacing NOTIFY largeSpacingChanged FINAL) |
174 | |
175 | /*! |
176 | * \qmlproperty int Units::veryLongDuration |
177 | * |
178 | * units.veryLongDuration should be used for specialty animations that benefit |
179 | * from being even longer than longDuration. |
180 | */ |
181 | /*! |
182 | * \property Kirigami::Platform::Units::veryLongDuration |
183 | * |
184 | * units.veryLongDuration should be used for specialty animations that benefit |
185 | * from being even longer than longDuration. |
186 | */ |
187 | Q_PROPERTY(int veryLongDuration READ veryLongDuration NOTIFY veryLongDurationChanged FINAL) |
188 | |
189 | /*! |
190 | * \qmlproperty int Units::longDuration |
191 | * |
192 | * units.longDuration should be used for longer, screen-covering animations, for opening and |
193 | * closing of dialogs and other "not too small" animations |
194 | */ |
195 | /*! |
196 | * \property Kirigami::Platform::Units::longDuration |
197 | * |
198 | * units.longDuration should be used for longer, screen-covering animations, for opening and |
199 | * closing of dialogs and other "not too small" animations |
200 | */ |
201 | Q_PROPERTY(int longDuration READ longDuration NOTIFY longDurationChanged FINAL) |
202 | |
203 | /*! |
204 | * \qmlproperty int Units::shortDuration |
205 | * |
206 | * units.shortDuration should be used for short animations, such as accentuating a UI event, |
207 | * hover events, etc.. |
208 | */ |
209 | /*! |
210 | * \property Kirigami::Platform::Units::shortDuration |
211 | * |
212 | * units.shortDuration should be used for short animations, such as accentuating a UI event, |
213 | * hover events, etc.. |
214 | */ |
215 | Q_PROPERTY(int shortDuration READ shortDuration NOTIFY shortDurationChanged FINAL) |
216 | |
217 | /*! |
218 | * \qmlproperty int Units::veryShortDuration |
219 | * |
220 | * units.veryShortDuration should be used for elements that should have a hint of smoothness, |
221 | * but otherwise animate near instantly. |
222 | */ |
223 | /*! |
224 | * \property Kirigami::Platform::Units::veryShortDuration |
225 | * |
226 | * units.veryShortDuration should be used for elements that should have a hint of smoothness, |
227 | * but otherwise animate near instantly. |
228 | */ |
229 | Q_PROPERTY(int veryShortDuration READ veryShortDuration NOTIFY veryShortDurationChanged FINAL) |
230 | |
231 | /*! |
232 | * \qmlproperty int Units::humanMoment |
233 | * |
234 | * Time in milliseconds equivalent to the theoretical human moment, which can be used |
235 | * to determine whether how long to wait until the user should be informed of something, |
236 | * or can be used as the limit for how long something should wait before being |
237 | * automatically initiated. |
238 | * |
239 | * Some examples: |
240 | * |
241 | * \list |
242 | * \li When the user types text in a search field, wait no longer than this duration after |
243 | * the user completes typing before starting the search. |
244 | * \li When loading data which would commonly arrive rapidly enough to not require interaction, |
245 | * wait this long before showing a spinner. |
246 | * \endlist |
247 | * |
248 | * This might seem an arbitrary number, but given the psychological effect that three |
249 | * seconds seems to be what humans consider a moment (and in the case of waiting for |
250 | * something to happen, a moment is that time when you think "this is taking a bit long, |
251 | * isn't it?"), the idea is to postpone for just before such a conceptual moment. The reason |
252 | * for the two seconds, rather than three, is to function as a middle ground: Not long enough |
253 | * that the user would think that something has taken too long, for also not so fast as to |
254 | * happen too soon. |
255 | * |
256 | * See \l {https://www.psychologytoday.com/blog/all-about-addiction/201101/tick-tock-tick-hugs-and-life-in-3-second-intervals} |
257 | * {Tick, tock, tick - Hugs and life in 3 second intervals (Psychology Today)} |
258 | * (the actual paper is hidden behind an academic paywall and consequently not readily |
259 | * available to us, so the source will have to be the blog entry above). |
260 | * |
261 | * \note This should __not__ be used as an animation duration, as it is deliberately not scaled according |
262 | * to the animation settings. This is specifically for determining when something has taken too long and |
263 | * the user should expect some kind of feedback. See veryShortDuration, shortDuration, longDuration, and |
264 | * veryLongDuration for animation duration choices. |
265 | * |
266 | * \since 5.81 |
267 | */ |
268 | /*! |
269 | * \property Kirigami::Platform::Units::humanMoment |
270 | * |
271 | * Time in milliseconds equivalent to the theoretical human moment, which can be used |
272 | * to determine whether how long to wait until the user should be informed of something, |
273 | * or can be used as the limit for how long something should wait before being |
274 | * automatically initiated. |
275 | * |
276 | * Some examples: |
277 | * |
278 | * \list |
279 | * \li When the user types text in a search field, wait no longer than this duration after |
280 | * the user completes typing before starting the search. |
281 | * \li When loading data which would commonly arrive rapidly enough to not require interaction, |
282 | * wait this long before showing a spinner. |
283 | * \endlist |
284 | * |
285 | * This might seem an arbitrary number, but given the psychological effect that three |
286 | * seconds seems to be what humans consider a moment (and in the case of waiting for |
287 | * something to happen, a moment is that time when you think "this is taking a bit long, |
288 | * isn't it?"), the idea is to postpone for just before such a conceptual moment. The reason |
289 | * for the two seconds, rather than three, is to function as a middle ground: Not long enough |
290 | * that the user would think that something has taken too long, for also not so fast as to |
291 | * happen too soon. |
292 | * |
293 | * See \l {https://www.psychologytoday.com/blog/all-about-addiction/201101/tick-tock-tick-hugs-and-life-in-3-second-intervals} |
294 | * {Tick, tock, tick - Hugs and life in 3 second intervals (Psychology Today)} |
295 | * (the actual paper is hidden behind an academic paywall and consequently not readily |
296 | * available to us, so the source will have to be the blog entry above). |
297 | * |
298 | * \note This should __not__ be used as an animation duration, as it is deliberately not scaled according |
299 | * to the animation settings. This is specifically for determining when something has taken too long and |
300 | * the user should expect some kind of feedback. See veryShortDuration, shortDuration, longDuration, and |
301 | * veryLongDuration for animation duration choices. |
302 | * |
303 | * \since 5.81 |
304 | */ |
305 | Q_PROPERTY(int humanMoment READ humanMoment NOTIFY humanMomentChanged FINAL) |
306 | |
307 | /*! |
308 | * \qmlproperty int Units::toolTipDelay |
309 | * |
310 | * time in ms by which the display of tooltips will be delayed. |
311 | * |
312 | */ |
313 | /*! |
314 | * \property Kirigami::Platform::Units::toolTipDelay |
315 | * |
316 | * time in ms by which the display of tooltips will be delayed. |
317 | * |
318 | */ |
319 | Q_PROPERTY(int toolTipDelay READ toolTipDelay NOTIFY toolTipDelayChanged FINAL) |
320 | |
321 | /*! |
322 | * \qmlproperty real Units::cornerRadius |
323 | * |
324 | * Corner radius value shared by buttons and other rectangle elements. |
325 | * |
326 | * \since 6.2 |
327 | */ |
328 | /*! |
329 | * \property Kirigami::Platform::Units::cornerRadius |
330 | * |
331 | * Corner radius value shared by buttons and other rectangle elements |
332 | * |
333 | * \since 6.2 |
334 | */ |
335 | Q_PROPERTY(qreal cornerRadius READ cornerRadius NOTIFY cornerRadiusChanged FINAL) |
336 | |
337 | public: |
338 | ~Units() override; |
339 | |
340 | // TODO qdoc document setters for platform integration plugins? |
341 | |
342 | int gridUnit() const; |
343 | void setGridUnit(int size); |
344 | |
345 | int smallSpacing() const; |
346 | void setSmallSpacing(int size); |
347 | |
348 | int mediumSpacing() const; |
349 | void setMediumSpacing(int size); |
350 | |
351 | int largeSpacing() const; |
352 | void setLargeSpacing(int size); |
353 | |
354 | int veryLongDuration() const; |
355 | void setVeryLongDuration(int duration); |
356 | |
357 | int longDuration() const; |
358 | void setLongDuration(int duration); |
359 | |
360 | int shortDuration() const; |
361 | void setShortDuration(int duration); |
362 | |
363 | int veryShortDuration() const; |
364 | void setVeryShortDuration(int duration); |
365 | |
366 | int humanMoment() const; |
367 | void setHumanMoment(int duration); |
368 | |
369 | int toolTipDelay() const; |
370 | void setToolTipDelay(int delay); |
371 | |
372 | qreal cornerRadius() const; |
373 | void setcornerRadius(qreal cornerRadius); |
374 | |
375 | IconSizes *iconSizes() const; |
376 | |
377 | static Units *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine); |
378 | |
379 | Q_SIGNALS: |
380 | void gridUnitChanged(); |
381 | void smallSpacingChanged(); |
382 | void mediumSpacingChanged(); |
383 | void largeSpacingChanged(); |
384 | void veryLongDurationChanged(); |
385 | void longDurationChanged(); |
386 | void shortDurationChanged(); |
387 | void veryShortDurationChanged(); |
388 | void humanMomentChanged(); |
389 | void toolTipDelayChanged(); |
390 | void wheelScrollLinesChanged(); |
391 | void cornerRadiusChanged(); |
392 | |
393 | protected: |
394 | explicit Units(QObject *parent = nullptr); |
395 | bool eventFilter(QObject *watched, QEvent *event) override; |
396 | |
397 | private: |
398 | std::unique_ptr<UnitsPrivate> d; |
399 | }; |
400 | |
401 | } |
402 | } |
403 | |
404 | #endif |
405 | |