QmlMaterial 0.1.0
Loading...
Searching...
No Matches
control.hpp
1#pragma once
2#include <QProperty>
3
4#include <QFont>
5#include <QLocale>
6#include <QPointer>
7#include <QQuickItem>
8#include <qqmlregistration.h>
9
10#include <optional>
11
12#include "qml_material/export.hpp"
13#include "qml_material/util/control_environment.hpp"
14
15class QFocusEvent;
16class QHoverEvent;
17
18namespace qml_material
19{
20
21class QML_MATERIAL_API Control : public QQuickItem, public ControlEnvironment {
22 Q_OBJECT
23 QML_NAMED_ELEMENT(Control)
24
25 Q_PROPERTY(QFont font READ font WRITE setFont RESET resetFont NOTIFY fontChanged FINAL)
26 Q_PROPERTY(
27 QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged FINAL)
28 Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection
29 RESET resetLayoutDirection NOTIFY layoutDirectionChanged FINAL)
30 Q_PROPERTY(bool mirrored READ mirrored NOTIFY mirroredChanged FINAL)
31
32 Q_PROPERTY(qreal availableWidth READ availableWidth NOTIFY availableWidthChanged FINAL)
33 Q_PROPERTY(qreal availableHeight READ availableHeight NOTIFY availableHeightChanged FINAL)
34 Q_PROPERTY(
35 qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged FINAL)
36 Q_PROPERTY(qreal horizontalPadding READ horizontalPadding WRITE setHorizontalPadding RESET
37 resetHorizontalPadding NOTIFY horizontalPaddingChanged FINAL)
38 Q_PROPERTY(qreal verticalPadding READ verticalPadding WRITE setVerticalPadding RESET
39 resetVerticalPadding NOTIFY verticalPaddingChanged FINAL)
40 Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY
41 topPaddingChanged FINAL)
42 Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY
43 leftPaddingChanged FINAL)
44 Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding
45 NOTIFY rightPaddingChanged FINAL)
46 Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET
47 resetBottomPadding NOTIFY bottomPaddingChanged FINAL)
48 Q_PROPERTY(
49 qreal spacing READ spacing WRITE setSpacing RESET resetSpacing NOTIFY spacingChanged FINAL)
50
51 Q_PROPERTY(qreal topInset READ topInset WRITE setTopInset RESET resetTopInset NOTIFY
52 topInsetChanged FINAL)
53 Q_PROPERTY(qreal leftInset READ leftInset WRITE setLeftInset RESET resetLeftInset NOTIFY
54 leftInsetChanged FINAL)
55 Q_PROPERTY(qreal rightInset READ rightInset WRITE setRightInset RESET resetRightInset NOTIFY
56 rightInsetChanged FINAL)
57 Q_PROPERTY(qreal bottomInset READ bottomInset WRITE setBottomInset RESET resetBottomInset NOTIFY
58 bottomInsetChanged FINAL)
59
60 Q_PROPERTY(QQuickItem* background READ background WRITE setBackground NOTIFY backgroundChanged
61 BINDABLE bindableBackground FINAL)
62 Q_PROPERTY(QQuickItem* contentItem READ contentItem WRITE setContentItem NOTIFY
63 contentItemChanged FINAL)
64 Q_PROPERTY(LayoutFlags backgroundLayout READ backgroundLayout WRITE setBackgroundLayout RESET
65 resetBackgroundLayout NOTIFY backgroundLayoutChanged FINAL)
66 Q_PROPERTY(LayoutFlags contentItemLayout READ contentItemLayout WRITE setContentItemLayout RESET
67 resetContentItemLayout NOTIFY contentItemLayoutChanged FINAL)
68
69 Q_PROPERTY(qreal implicitBackgroundWidth READ implicitBackgroundWidth NOTIFY
70 implicitBackgroundWidthChanged FINAL)
71 Q_PROPERTY(qreal implicitBackgroundHeight READ implicitBackgroundHeight NOTIFY
72 implicitBackgroundHeightChanged FINAL)
73 Q_PROPERTY(qreal implicitContentWidth READ implicitContentWidth NOTIFY
74 implicitContentWidthChanged FINAL)
75 Q_PROPERTY(qreal implicitContentHeight READ implicitContentHeight NOTIFY
76 implicitContentHeightChanged FINAL)
77 Q_PROPERTY(
78 qreal implicitLayoutWidth READ implicitLayoutWidth NOTIFY implicitLayoutWidthChanged FINAL)
79 Q_PROPERTY(qreal implicitLayoutHeight READ implicitLayoutHeight NOTIFY
80 implicitLayoutHeightChanged FINAL)
81 Q_PROPERTY(qreal extraImplicitWidth READ extraImplicitWidth WRITE setExtraImplicitWidth RESET
82 resetExtraImplicitWidth NOTIFY extraImplicitWidthChanged FINAL)
83 Q_PROPERTY(qreal extraImplicitHeight READ extraImplicitHeight WRITE setExtraImplicitHeight RESET
84 resetExtraImplicitHeight NOTIFY extraImplicitHeightChanged FINAL)
85
86 Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset RESET
87 resetBaselineOffset NOTIFY baselineOffsetChanged FINAL)
88 Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled RESET resetHoverEnabled
89 NOTIFY hoverEnabledChanged FINAL)
90 Q_PROPERTY(bool hovered READ hovered NOTIFY hoveredChanged BINDABLE bindableHovered FINAL)
91 Q_PROPERTY(Qt::FocusReason focusReason READ focusReason WRITE setFocusReason NOTIFY
92 focusReasonChanged FINAL)
93 Q_PROPERTY(bool visualFocus READ visualFocus NOTIFY visualFocusChanged BINDABLE
94 bindableVisualFocus FINAL)
95
96public:
97 enum LayoutFlag
98 {
99 LayoutNone = 0x0,
100 LayoutX = 0x1,
101 LayoutY = 0x2,
102 LayoutWidth = 0x4,
103 LayoutHeight = 0x8,
104 LayoutPosition = LayoutX | LayoutY,
105 LayoutSize = LayoutWidth | LayoutHeight,
106 LayoutAll = LayoutPosition | LayoutSize
107 };
108 Q_DECLARE_FLAGS(LayoutFlags, LayoutFlag)
109 Q_FLAG(LayoutFlags)
110
111 explicit Control(QQuickItem* parent = nullptr);
112 ~Control() override;
113
114 QFont font() const;
115 QFont effectiveFont() const override { return m_font; }
116 void inheritFont(const QFont&) override;
117 void inheritLocale(const QLocale&) override;
118 void inheritLayoutDirection(Qt::LayoutDirection) override;
119 void inheritHoverEnabled(bool) override;
120 std::optional<QLocale> effectiveLocale() const override { return m_locale; }
121 std::optional<Qt::LayoutDirection> effectiveLayoutDirection() const override {
122 return m_layout_direction;
123 }
124 void setFont(const QFont& value);
125 void resetFont();
126
127 QLocale locale() const;
128 void setLocale(const QLocale& value);
129 void resetLocale();
130
131 Qt::LayoutDirection layoutDirection() const;
132 void setLayoutDirection(Qt::LayoutDirection value);
133 void resetLayoutDirection();
134 bool mirrored() const;
135
136 qreal availableWidth() const;
137 qreal availableHeight() const;
138
139 qreal padding() const;
140 void setPadding(qreal value);
141 void resetPadding();
142
143 qreal horizontalPadding() const;
144 void setHorizontalPadding(qreal value);
145 void resetHorizontalPadding();
146
147 qreal verticalPadding() const;
148 void setVerticalPadding(qreal value);
149 void resetVerticalPadding();
150
151 qreal topPadding() const;
152 void setTopPadding(qreal value);
153 void resetTopPadding();
154
155 qreal leftPadding() const;
156 void setLeftPadding(qreal value);
157 void resetLeftPadding();
158
159 qreal rightPadding() const;
160 void setRightPadding(qreal value);
161 void resetRightPadding();
162
163 qreal bottomPadding() const;
164 void setBottomPadding(qreal value);
165 void resetBottomPadding();
166
167 qreal spacing() const;
168 void setSpacing(qreal value);
169 void resetSpacing();
170
171 qreal topInset() const;
172 void setTopInset(qreal value);
173 void resetTopInset();
174
175 qreal leftInset() const;
176 void setLeftInset(qreal value);
177 void resetLeftInset();
178
179 qreal rightInset() const;
180 void setRightInset(qreal value);
181 void resetRightInset();
182
183 qreal bottomInset() const;
184 void setBottomInset(qreal value);
185 void resetBottomInset();
186
187 QQuickItem* background() const;
188 QBindable<QQuickItem*> bindableBackground() { return QBindable<QQuickItem*>(&m_background); }
189 void setBackground(QQuickItem* item);
190
191 QQuickItem* contentItem() const;
192 void setContentItem(QQuickItem* item);
193
194 LayoutFlags backgroundLayout() const;
195 void setBackgroundLayout(LayoutFlags value);
196 void resetBackgroundLayout();
197
198 LayoutFlags contentItemLayout() const;
199 void setContentItemLayout(LayoutFlags value);
200 void resetContentItemLayout();
201
202 qreal implicitBackgroundWidth() const;
203 qreal implicitBackgroundHeight() const;
204 qreal implicitContentWidth() const;
205 qreal implicitContentHeight() const;
206 qreal implicitLayoutWidth() const;
207 qreal implicitLayoutHeight() const;
208
209 qreal extraImplicitWidth() const;
210 void setExtraImplicitWidth(qreal value);
211 void resetExtraImplicitWidth();
212
213 qreal extraImplicitHeight() const;
214 void setExtraImplicitHeight(qreal value);
215 void resetExtraImplicitHeight();
216
217 qreal baselineOffset() const;
218 void setBaselineOffset(qreal value);
219 void resetBaselineOffset();
220
221 bool hoverEnabled() const;
222 std::optional<bool> effectiveHoverEnabled() const override { return hoverEnabled(); }
223 void setHoverEnabled(bool value);
224 void resetHoverEnabled();
225
226 bool hovered() const;
227 QBindable<bool> bindableHovered() const { return QBindable<bool>(&m_hovered); }
228
229 Qt::FocusReason focusReason() const;
230 void setFocusReason(Qt::FocusReason value);
231 bool visualFocus() const;
232 QBindable<bool> bindableVisualFocus() const { return QBindable<bool>(&m_visual_focus); }
233
234 Q_SIGNAL void fontChanged();
235 Q_SIGNAL void localeChanged();
236 Q_SIGNAL void layoutDirectionChanged();
237 Q_SIGNAL void mirroredChanged();
238 Q_SIGNAL void availableWidthChanged();
239 Q_SIGNAL void availableHeightChanged();
240 Q_SIGNAL void paddingChanged();
241 Q_SIGNAL void horizontalPaddingChanged();
242 Q_SIGNAL void verticalPaddingChanged();
243 Q_SIGNAL void topPaddingChanged();
244 Q_SIGNAL void leftPaddingChanged();
245 Q_SIGNAL void rightPaddingChanged();
246 Q_SIGNAL void bottomPaddingChanged();
247 Q_SIGNAL void spacingChanged();
248 Q_SIGNAL void topInsetChanged();
249 Q_SIGNAL void leftInsetChanged();
250 Q_SIGNAL void rightInsetChanged();
251 Q_SIGNAL void bottomInsetChanged();
252 Q_SIGNAL void backgroundChanged();
253 Q_SIGNAL void contentItemChanged();
254 Q_SIGNAL void backgroundLayoutChanged();
255 Q_SIGNAL void contentItemLayoutChanged();
256 Q_SIGNAL void implicitBackgroundWidthChanged();
257 Q_SIGNAL void implicitBackgroundHeightChanged();
258 Q_SIGNAL void implicitContentWidthChanged();
259 Q_SIGNAL void implicitContentHeightChanged();
260 Q_SIGNAL void implicitLayoutWidthChanged();
261 Q_SIGNAL void implicitLayoutHeightChanged();
262 Q_SIGNAL void extraImplicitWidthChanged();
263 Q_SIGNAL void extraImplicitHeightChanged();
264 Q_SIGNAL void baselineOffsetChanged();
265 Q_SIGNAL void hoverEnabledChanged();
266 Q_SIGNAL void hoveredChanged();
267 Q_SIGNAL void focusReasonChanged();
268 Q_SIGNAL void visualFocusChanged();
269
270protected:
271 virtual qreal defaultSpacing() const { return 0; }
272 virtual QRectF contentRect() const;
273 void layoutContentItem();
274 virtual QSizeF measureImplicitContent() const;
275 void updateImplicitMetrics();
276 void classBegin() override;
277 void componentComplete() override;
278 void geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) override;
279 void itemChange(ItemChange change, const ItemChangeData& value) override;
280 void focusInEvent(QFocusEvent* event) override;
281 void focusOutEvent(QFocusEvent* event) override;
282 void hoverEnterEvent(QHoverEvent* event) override;
283 void hoverMoveEvent(QHoverEvent* event) override;
284 void hoverLeaveEvent(QHoverEvent* event) override;
285 bool eventFilter(QObject* watched, QEvent* event) override;
286
287private:
288 struct PaddingState {
289 qreal top;
290 qreal left;
291 qreal right;
292 qreal bottom;
293 qreal horizontal;
294 qreal vertical;
295 qreal availableWidth;
296 qreal availableHeight;
297 qreal implicitWidth;
298 qreal implicitHeight;
299 };
300
301 PaddingState paddingState() const;
302 void finishPaddingChange(const PaddingState& oldState);
303 void finishInsetChange(qreal oldImplicitWidth, qreal oldImplicitHeight);
304 void updateBaselineOffset();
305 void resolveEnvironment();
306 void resolveFont();
307 void resolveLocale();
308 void resolveLayoutDirection();
309 void resolveHoverEnabled();
310 void updateLocale(const QLocale&);
311 void updateLayoutDirection(Qt::LayoutDirection);
312 void updateHoverEnabled(bool);
313 void updateVisualFocus();
314 void setHovered(bool value);
315 void layoutItems();
316 void layoutBackground();
317 void orderManagedItems();
318 void disconnectBackground();
319 void backgroundChange();
320 void disconnectContentItem();
321
322 qreal m_padding { 0 };
323 std::optional<qreal> m_horizontal_padding;
324 std::optional<qreal> m_vertical_padding;
325 std::optional<qreal> m_top_padding;
326 std::optional<qreal> m_left_padding;
327 std::optional<qreal> m_right_padding;
328 std::optional<qreal> m_bottom_padding;
329 std::optional<qreal> m_spacing;
330 qreal m_top_inset { 0 };
331 qreal m_left_inset { 0 };
332 qreal m_right_inset { 0 };
333 qreal m_bottom_inset { 0 };
334
335 Q_OBJECT_BINDABLE_PROPERTY(Control, QQuickItem*, m_background, &Control::backgroundChange)
336 QPointer<QQuickItem> m_managed_background;
337 QPointer<QQuickItem> m_content_item;
338 QList<QMetaObject::Connection> m_control_connections;
339 QList<QMetaObject::Connection> m_background_connections;
340 QList<QMetaObject::Connection> m_content_connections;
341 LayoutFlags m_background_layout { LayoutAll };
342 LayoutFlags m_content_item_layout { LayoutAll };
343
344 qreal m_implicit_background_width { 0 };
345 qreal m_implicit_background_height { 0 };
346 qreal m_implicit_content_width { 0 };
347 qreal m_implicit_content_height { 0 };
348 qreal m_extra_implicit_width { 0 };
349 qreal m_extra_implicit_height { 0 };
350
351 QFont m_requested_font;
352 QFont m_font;
353 QLocale m_requested_locale;
354 QLocale m_locale;
355 Qt::LayoutDirection m_requested_layout_direction { Qt::LeftToRight };
356 Qt::LayoutDirection m_layout_direction { Qt::LeftToRight };
357 std::optional<bool> m_requested_hover_enabled;
358 bool m_font_explicit { false };
359 bool m_locale_explicit { false };
360 bool m_layout_direction_explicit { false };
361 bool m_hover_enabled { false };
362 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(Control, bool, m_hovered, false, &Control::hoveredChanged)
363 bool m_baseline_explicit { false };
364 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(Control, bool, m_visual_focus, false,
365 &Control::visualFocusChanged)
366 Qt::FocusReason m_focus_reason { Qt::OtherFocusReason };
367};
368
369} // namespace qml_material
370
371Q_DECLARE_OPERATORS_FOR_FLAGS(qml_material::Control::LayoutFlags)