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
18class QQmlEngine;
19
20namespace Kirigami
21{
22namespace Platform
23{
24class Units;
25class UnitsPrivate;
26
27// TODO qdoc should this be documented as C++ API?
28class 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
42public:
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
55private:
56 KIRIGAMIPLATFORM_NO_EXPORT float iconScaleFactor() const;
57
58 Units *m_units;
59
60Q_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 */
84class 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
337public:
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
379Q_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
393protected:
394 explicit Units(QObject *parent = nullptr);
395 bool eventFilter(QObject *watched, QEvent *event) override;
396
397private:
398 std::unique_ptr<UnitsPrivate> d;
399};
400
401}
402}
403
404#endif
405

source code of kirigami/src/platform/units.h