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 | /** |
28 | * @class IconSizes units.h <Kirigami/Units> |
29 | * |
30 | * Provides access to platform-dependent icon sizing |
31 | */ |
32 | class KIRIGAMIPLATFORM_EXPORT IconSizes : public QObject |
33 | { |
34 | Q_OBJECT |
35 | QML_ELEMENT |
36 | QML_UNCREATABLE("Grouped Property" ) |
37 | |
38 | Q_PROPERTY(int sizeForLabels READ sizeForLabels NOTIFY sizeForLabelsChanged FINAL) |
39 | Q_PROPERTY(int small READ small NOTIFY smallChanged FINAL) |
40 | Q_PROPERTY(int smallMedium READ smallMedium NOTIFY smallMediumChanged FINAL) |
41 | Q_PROPERTY(int medium READ medium NOTIFY mediumChanged FINAL) |
42 | Q_PROPERTY(int large READ large NOTIFY largeChanged FINAL) |
43 | Q_PROPERTY(int huge READ huge NOTIFY hugeChanged FINAL) |
44 | Q_PROPERTY(int enormous READ enormous NOTIFY enormousChanged FINAL) |
45 | |
46 | public: |
47 | IconSizes(Units *units); |
48 | |
49 | int sizeForLabels() const; |
50 | int small() const; |
51 | int smallMedium() const; |
52 | int medium() const; |
53 | int large() const; |
54 | int huge() const; |
55 | int enormous() const; |
56 | |
57 | Q_INVOKABLE int roundedIconSize(int size) const; |
58 | |
59 | private: |
60 | KIRIGAMIPLATFORM_NO_EXPORT float iconScaleFactor() const; |
61 | |
62 | Units *m_units; |
63 | |
64 | Q_SIGNALS: |
65 | void sizeForLabelsChanged(); |
66 | void smallChanged(); |
67 | void smallMediumChanged(); |
68 | void mediumChanged(); |
69 | void largeChanged(); |
70 | void hugeChanged(); |
71 | void enormousChanged(); |
72 | }; |
73 | |
74 | /** |
75 | * @class Units units.h <Kirigami/Units> |
76 | * |
77 | * A set of values to define semantically sizes and durations. |
78 | */ |
79 | class KIRIGAMIPLATFORM_EXPORT Units : public QObject |
80 | { |
81 | Q_OBJECT |
82 | QML_ELEMENT |
83 | QML_SINGLETON |
84 | |
85 | friend class IconSizes; |
86 | |
87 | /** |
88 | * The fundamental unit of space that should be used for sizes, expressed in pixels. |
89 | * Given the screen has an accurate DPI settings, it corresponds to the height of |
90 | * the font's boundingRect. |
91 | */ |
92 | Q_PROPERTY(int gridUnit READ gridUnit NOTIFY gridUnitChanged FINAL) |
93 | |
94 | /** |
95 | * units.iconSizes provides access to platform-dependent icon sizing |
96 | * |
97 | * The icon sizes provided are normalized for different DPI, so icons |
98 | * will scale depending on the DPI. |
99 | * |
100 | * * sizeForLabels (the largest icon size that fits within fontMetrics.height) @since 5.80 @since org.kde.kirigami 2.16 |
101 | * * small |
102 | * * smallMedium |
103 | * * medium |
104 | * * large |
105 | * * huge |
106 | * * enormous |
107 | */ |
108 | Q_PROPERTY(Kirigami::Platform::IconSizes *iconSizes READ iconSizes CONSTANT FINAL) |
109 | |
110 | /** |
111 | * This property holds the amount of spacing that should be used between smaller UI elements, |
112 | * such as a small icon and a label in a button. |
113 | */ |
114 | Q_PROPERTY(int smallSpacing READ smallSpacing NOTIFY smallSpacingChanged FINAL) |
115 | |
116 | /** |
117 | * This property holds the amount of spacing that should be used between medium UI elements, |
118 | * such as buttons and text fields in a toolbar. |
119 | */ |
120 | Q_PROPERTY(int mediumSpacing READ mediumSpacing NOTIFY mediumSpacingChanged FINAL) |
121 | |
122 | /** |
123 | * This property holds the amount of spacing that should be used between bigger UI elements, |
124 | * such as a large icon and a heading in a card. |
125 | */ |
126 | Q_PROPERTY(int largeSpacing READ largeSpacing NOTIFY largeSpacingChanged FINAL) |
127 | |
128 | /** |
129 | * units.veryLongDuration should be used for specialty animations that benefit |
130 | * from being even longer than longDuration. |
131 | */ |
132 | Q_PROPERTY(int veryLongDuration READ veryLongDuration NOTIFY veryLongDurationChanged FINAL) |
133 | |
134 | /** |
135 | * units.longDuration should be used for longer, screen-covering animations, for opening and |
136 | * closing of dialogs and other "not too small" animations |
137 | */ |
138 | Q_PROPERTY(int longDuration READ longDuration NOTIFY longDurationChanged FINAL) |
139 | |
140 | /** |
141 | * units.shortDuration should be used for short animations, such as accentuating a UI event, |
142 | * hover events, etc.. |
143 | */ |
144 | Q_PROPERTY(int shortDuration READ shortDuration NOTIFY shortDurationChanged FINAL) |
145 | |
146 | /** |
147 | * units.veryShortDuration should be used for elements that should have a hint of smoothness, |
148 | * but otherwise animate near instantly. |
149 | */ |
150 | Q_PROPERTY(int veryShortDuration READ veryShortDuration NOTIFY veryShortDurationChanged FINAL) |
151 | |
152 | /** |
153 | * Time in milliseconds equivalent to the theoretical human moment, which can be used |
154 | * to determine whether how long to wait until the user should be informed of something, |
155 | * or can be used as the limit for how long something should wait before being |
156 | * automatically initiated. |
157 | * |
158 | * Some examples: |
159 | * |
160 | * - When the user types text in a search field, wait no longer than this duration after |
161 | * the user completes typing before starting the search |
162 | * - When loading data which would commonly arrive rapidly enough to not require interaction, |
163 | * wait this long before showing a spinner |
164 | * |
165 | * This might seem an arbitrary number, but given the psychological effect that three |
166 | * seconds seems to be what humans consider a moment (and in the case of waiting for |
167 | * something to happen, a moment is that time when you think "this is taking a bit long, |
168 | * isn't it?"), the idea is to postpone for just before such a conceptual moment. The reason |
169 | * for the two seconds, rather than three, is to function as a middle ground: Not long enough |
170 | * that the user would think that something has taken too long, for also not so fast as to |
171 | * happen too soon. |
172 | * |
173 | * See also |
174 | * https://www.psychologytoday.com/blog/all-about-addiction/201101/tick-tock-tick-hugs-and-life-in-3-second-intervals |
175 | * (the actual paper is hidden behind an academic paywall and consequently not readily |
176 | * available to us, so the source will have to be the blog entry above) |
177 | * |
178 | * \note This should __not__ be used as an animation duration, as it is deliberately not scaled according |
179 | * to the animation settings. This is specifically for determining when something has taken too long and |
180 | * the user should expect some kind of feedback. See veryShortDuration, shortDuration, longDuration, and |
181 | * veryLongDuration for animation duration choices. |
182 | * |
183 | * @since 5.81 |
184 | * @since org.kde.kirigami 2.16 |
185 | */ |
186 | Q_PROPERTY(int humanMoment READ humanMoment NOTIFY humanMomentChanged FINAL) |
187 | |
188 | /** |
189 | * time in ms by which the display of tooltips will be delayed. |
190 | * |
191 | * @sa ToolTip.delay property |
192 | */ |
193 | Q_PROPERTY(int toolTipDelay READ toolTipDelay NOTIFY toolTipDelayChanged FINAL) |
194 | |
195 | /** |
196 | * Corner radius value shared by buttons and other rectangle elements |
197 | * |
198 | * @since 6.2 |
199 | */ |
200 | Q_PROPERTY(qreal cornerRadius READ cornerRadius NOTIFY cornerRadiusChanged FINAL) |
201 | |
202 | public: |
203 | ~Units() override; |
204 | |
205 | int gridUnit() const; |
206 | void setGridUnit(int size); |
207 | |
208 | int smallSpacing() const; |
209 | void setSmallSpacing(int size); |
210 | |
211 | int mediumSpacing() const; |
212 | void setMediumSpacing(int size); |
213 | |
214 | int largeSpacing() const; |
215 | void setLargeSpacing(int size); |
216 | |
217 | int veryLongDuration() const; |
218 | void setVeryLongDuration(int duration); |
219 | |
220 | int longDuration() const; |
221 | void setLongDuration(int duration); |
222 | |
223 | int shortDuration() const; |
224 | void setShortDuration(int duration); |
225 | |
226 | int veryShortDuration() const; |
227 | void setVeryShortDuration(int duration); |
228 | |
229 | int humanMoment() const; |
230 | void setHumanMoment(int duration); |
231 | |
232 | int toolTipDelay() const; |
233 | void setToolTipDelay(int delay); |
234 | |
235 | qreal cornerRadius() const; |
236 | void setcornerRadius(qreal cornerRadius); |
237 | |
238 | IconSizes *iconSizes() const; |
239 | |
240 | static Units *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine); |
241 | |
242 | Q_SIGNALS: |
243 | void gridUnitChanged(); |
244 | void smallSpacingChanged(); |
245 | void mediumSpacingChanged(); |
246 | void largeSpacingChanged(); |
247 | void veryLongDurationChanged(); |
248 | void longDurationChanged(); |
249 | void shortDurationChanged(); |
250 | void veryShortDurationChanged(); |
251 | void humanMomentChanged(); |
252 | void toolTipDelayChanged(); |
253 | void wheelScrollLinesChanged(); |
254 | void cornerRadiusChanged(); |
255 | |
256 | protected: |
257 | explicit Units(QObject *parent = nullptr); |
258 | bool eventFilter(QObject *watched, QEvent *event) override; |
259 | |
260 | private: |
261 | std::unique_ptr<UnitsPrivate> d; |
262 | }; |
263 | |
264 | } |
265 | } |
266 | |
267 | #endif |
268 | |