QmlMaterial 0.1.0
Loading...
Searching...
No Matches
popup.hpp
1#pragma once
2
3#include "qml_material/export.hpp"
4#include <QFont>
5#include <QLocale>
6#include <QPointer>
7#include <QQuickItem>
8#include <QQmlListProperty>
9#include <QQmlParserStatus>
10#include <QtQml/qqmlregistration.h>
11#include <QTimer>
12#include <optional>
13#include <memory>
14#include <functional>
15
16QT_BEGIN_NAMESPACE
17class QQuickTransition;
18QT_END_NAMESPACE
19
20Q_MOC_INCLUDE("qml_material/control/panel.hpp")
21Q_MOC_INCLUDE("QtQuick/private/qquicktransition_p.h")
22
23namespace qml_material
24{
25class Control;
26class Panel;
27class OverlayManager;
28class PopupMotion;
29
30class QML_MATERIAL_API Popup : public QObject, public QQmlParserStatus {
31 Q_OBJECT
32 QML_NAMED_ELEMENT(PopupBase)
33 Q_INTERFACES(QQmlParserStatus)
34 Q_CLASSINFO("DefaultProperty", "contentData")
35 Q_PROPERTY(QQuickItem* parent READ parentItem WRITE setParentItem NOTIFY parentChanged FINAL)
36 Q_PROPERTY(QQuickItem* positioningItem READ positioningItem WRITE setPositioningItem NOTIFY
37 positioningItemChanged FINAL)
38 Q_PROPERTY(QQuickItem* surfaceItem READ surfaceItem CONSTANT FINAL)
39 Q_PROPERTY(
40 QQuickItem* popupItem READ popupItem WRITE setPopupItem NOTIFY popupItemChanged FINAL)
41 Q_PROPERTY(QQuickItem* overlayItem READ overlayItem NOTIFY overlayItemChanged FINAL)
42 Q_PROPERTY(qreal overlayWidth READ overlayWidth NOTIFY overlayGeometryChanged FINAL)
43 Q_PROPERTY(qreal overlayHeight READ overlayHeight NOTIFY overlayGeometryChanged FINAL)
44 Q_PROPERTY(QRectF presentationRect READ presentationRect NOTIFY presentationRectChanged FINAL)
45 Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
46 Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY
47 contentChildrenChanged FINAL)
48 Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
49 Q_PROPERTY(bool opened READ isOpened NOTIFY openedChanged FINAL)
50 Q_PROPERTY(bool entering READ entering NOTIFY enteringChanged FINAL)
51 Q_PROPERTY(bool closing READ closing NOTIFY closingChanged FINAL)
52 Q_PROPERTY(bool modal READ modal WRITE setModal NOTIFY modalChanged FINAL)
53 Q_PROPERTY(bool dim READ dim WRITE setDim RESET resetDim NOTIFY dimChanged FINAL)
54 Q_PROPERTY(bool focus READ focus WRITE setFocus NOTIFY focusChanged FINAL)
55 Q_PROPERTY(bool deferredCompletion READ deferredCompletion WRITE setDeferredCompletion NOTIFY
56 deferredCompletionChanged FINAL)
57 Q_PROPERTY(int hideDelay READ hideDelay WRITE setHideDelay NOTIFY hideDelayChanged FINAL)
58 Q_PROPERTY(ClosePolicy closePolicy READ closePolicy WRITE setClosePolicy NOTIFY
59 closePolicyChanged FINAL)
60 Q_PROPERTY(CollisionPolicy collisionPolicy READ collisionPolicy WRITE setCollisionPolicy NOTIFY
61 collisionPolicyChanged FINAL)
62 Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL)
63 Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL)
64 Q_PROPERTY(qreal z READ z WRITE setZ RESET resetZ NOTIFY zChanged FINAL)
65 Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged FINAL)
66 Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin RESET resetLeftMargin NOTIFY
67 marginsChanged FINAL)
68 Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin RESET resetRightMargin NOTIFY
69 marginsChanged FINAL)
70 Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin RESET resetTopMargin NOTIFY
71 marginsChanged FINAL)
72 Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin RESET resetBottomMargin
73 NOTIFY marginsChanged FINAL)
74 Q_PROPERTY(QFont font READ font WRITE setFont RESET resetFont NOTIFY fontChanged FINAL)
75 Q_PROPERTY(
76 QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged FINAL)
77 Q_PROPERTY(QQuickTransition* enter READ enter WRITE setEnter NOTIFY enterChanged FINAL)
78 Q_PROPERTY(QQuickTransition* exit READ exit WRITE setExit NOTIFY exitChanged FINAL)
79 Q_PROPERTY(QQuickItem* contentItem READ contentItem WRITE setContentItem NOTIFY
80 contentItemChanged FINAL)
81 Q_PROPERTY(
82 QQuickItem* background READ background WRITE setBackground NOTIFY backgroundChanged FINAL)
83 Q_PROPERTY(qreal width READ width WRITE setWidth RESET resetWidth NOTIFY widthChanged FINAL)
84 Q_PROPERTY(
85 qreal height READ height WRITE setHeight RESET resetHeight NOTIFY heightChanged FINAL)
86 Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY
87 implicitWidthChanged FINAL)
88 Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY
89 implicitHeightChanged FINAL)
90 Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth
91 NOTIFY contentWidthChanged FINAL)
92 Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET
93 resetContentHeight NOTIFY contentHeightChanged FINAL)
94 Q_PROPERTY(qreal padding READ padding WRITE setPadding NOTIFY paddingChanged FINAL)
95 Q_PROPERTY(qreal horizontalPadding READ horizontalPadding WRITE setHorizontalPadding NOTIFY
96 horizontalPaddingChanged FINAL)
97 Q_PROPERTY(qreal verticalPadding READ verticalPadding WRITE setVerticalPadding NOTIFY
98 verticalPaddingChanged FINAL)
99 Q_PROPERTY(
100 qreal leftPadding READ leftPadding WRITE setLeftPadding NOTIFY leftPaddingChanged FINAL)
101 Q_PROPERTY(
102 qreal rightPadding READ rightPadding WRITE setRightPadding NOTIFY rightPaddingChanged FINAL)
103 Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding NOTIFY topPaddingChanged FINAL)
104 Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding NOTIFY
105 bottomPaddingChanged FINAL)
106 Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged FINAL)
107 Q_PROPERTY(qreal leftInset READ leftInset WRITE setLeftInset NOTIFY leftInsetChanged FINAL)
108 Q_PROPERTY(qreal rightInset READ rightInset WRITE setRightInset NOTIFY rightInsetChanged FINAL)
109 Q_PROPERTY(qreal topInset READ topInset WRITE setTopInset NOTIFY topInsetChanged FINAL)
110 Q_PROPERTY(
111 qreal bottomInset READ bottomInset WRITE setBottomInset NOTIFY bottomInsetChanged FINAL)
112 Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
113 Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged FINAL)
114 Q_PROPERTY(QQuickItem::TransformOrigin transformOrigin READ transformOrigin WRITE
115 setTransformOrigin NOTIFY transformOriginChanged FINAL)
116 Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged FINAL)
117 Q_PROPERTY(qreal availableWidth READ availableWidth NOTIFY availableWidthChanged FINAL)
118 Q_PROPERTY(qreal availableHeight READ availableHeight NOTIFY availableHeightChanged FINAL)
119 Q_PROPERTY(qreal implicitContentWidth READ implicitContentWidth NOTIFY
120 implicitContentWidthChanged FINAL)
121 Q_PROPERTY(qreal implicitContentHeight READ implicitContentHeight NOTIFY
122 implicitContentHeightChanged FINAL)
123 Q_PROPERTY(qreal implicitBackgroundWidth READ implicitBackgroundWidth NOTIFY
124 implicitBackgroundWidthChanged FINAL)
125 Q_PROPERTY(qreal implicitBackgroundHeight READ implicitBackgroundHeight NOTIFY
126 implicitBackgroundHeightChanged FINAL)
127 Q_PROPERTY(bool activeFocus READ activeFocus NOTIFY activeFocusChanged FINAL)
128 Q_PROPERTY(bool visualFocus READ visualFocus NOTIFY visualFocusChanged FINAL)
129 Q_PROPERTY(bool mirrored READ mirrored NOTIFY mirroredChanged FINAL)
130public:
131 explicit Popup(QObject* parent = nullptr);
132 ~Popup() override;
133 enum ClosePolicyFlag
134 {
135 NoAutoClose = 0,
136 CloseOnPressOutside = 1,
137 CloseOnPressOutsideParent = 2,
138 CloseOnReleaseOutside = 4,
139 CloseOnReleaseOutsideParent = 8,
140 CloseOnEscape = 16
141 };
142 Q_DECLARE_FLAGS(ClosePolicy, ClosePolicyFlag)
143 Q_FLAG(ClosePolicy)
144 enum CollisionPolicy
145 {
146 Unrestricted,
147 Clamp
148 };
149 Q_ENUM(CollisionPolicy)
150 QQuickItem* parentItem() const { return m_parent; }
151 void setParentItem(QQuickItem*);
152 // Null uses the logical parent; changing the coordinate reference does not reparent the popup.
153 QQuickItem* positioningItem() const { return m_positioningItem; }
154 void setPositioningItem(QQuickItem*);
155 Panel* surfaceItem() const { return m_surface; }
156 QQuickItem* popupItem() const;
157 void setPopupItem(QQuickItem*);
158 QQuickItem* overlayItem() const;
159 qreal overlayWidth() const;
160 qreal overlayHeight() const;
161 QQmlListProperty<QObject> contentData();
162 QQmlListProperty<QQuickItem> contentChildren();
163 bool isVisible() const { return m_state != Closed; }
164 void setVisible(bool);
165 bool isOpened() const { return m_state == Open; }
166 bool entering() const { return m_state == Entering; }
167 bool closing() const { return m_state == Closing; }
168 bool modal() const { return m_modal; }
169 void setModal(bool);
170 bool dim() const { return m_dim.value_or(m_modal); }
171 void setDim(bool);
172 void resetDim();
173 bool focus() const { return m_focus; }
174 void setFocus(bool);
175 bool deferredCompletion() const { return m_deferred; }
176 void setDeferredCompletion(bool);
177 int hideDelay() const { return m_hideDelay; }
178 void setHideDelay(int);
179 ClosePolicy closePolicy() const { return m_closePolicy; }
180 void setClosePolicy(ClosePolicy);
181 CollisionPolicy collisionPolicy() const { return m_collision; }
182 void setCollisionPolicy(CollisionPolicy);
183 qreal x() const { return m_position.x(); }
184 qreal y() const { return m_position.y(); }
185 qreal z() const { return m_z.value_or(m_inheritedZ); }
186 void setX(qreal);
187 void setY(qreal);
188 void setZ(qreal);
189 void resetZ();
190 qreal margins() const { return m_margins; }
191 void setMargins(qreal);
192 qreal leftMargin() const { return m_leftMargin.value_or(m_margins); }
193 void setLeftMargin(qreal);
194 void resetLeftMargin();
195 qreal rightMargin() const { return m_rightMargin.value_or(m_margins); }
196 void setRightMargin(qreal);
197 void resetRightMargin();
198 qreal topMargin() const { return m_topMargin.value_or(m_margins); }
199 void setTopMargin(qreal);
200 void resetTopMargin();
201 qreal bottomMargin() const { return m_bottomMargin.value_or(m_margins); }
202 void setBottomMargin(qreal);
203 void resetBottomMargin();
204 QFont font() const;
205 void setFont(const QFont&);
206 void resetFont();
207 QLocale locale() const;
208 void setLocale(const QLocale&);
209 void resetLocale();
210 QQuickTransition* enter() const;
211 QQuickTransition* exit() const;
212 void setEnter(QQuickTransition*);
213 void setExit(QQuickTransition*);
214 QQuickItem* contentItem() const;
215 void setContentItem(QQuickItem* value);
216 Q_SIGNAL void contentItemChanged();
217 QQuickItem* background() const;
218 void setBackground(QQuickItem* value);
219 Q_SIGNAL void backgroundChanged();
220 qreal width() const { return m_width.value_or(implicitWidth()); }
221 void setWidth(qreal value);
222 void resetWidth();
223 Q_SIGNAL void widthChanged();
224 qreal height() const { return m_height.value_or(implicitHeight()); }
225 void setHeight(qreal value);
226 void resetHeight();
227 Q_SIGNAL void heightChanged();
228 qreal implicitWidth() const;
229 void setImplicitWidth(qreal value);
230 Q_SIGNAL void implicitWidthChanged();
231 qreal implicitHeight() const;
232 void setImplicitHeight(qreal value);
233 Q_SIGNAL void implicitHeightChanged();
234 qreal contentWidth() const;
235 void setContentWidth(qreal value);
236 void resetContentWidth();
237 Q_SIGNAL void contentWidthChanged();
238 qreal contentHeight() const;
239 void setContentHeight(qreal value);
240 void resetContentHeight();
241 Q_SIGNAL void contentHeightChanged();
242 qreal padding() const;
243 void setPadding(qreal value);
244 Q_SIGNAL void paddingChanged();
245 qreal horizontalPadding() const;
246 void setHorizontalPadding(qreal value);
247 Q_SIGNAL void horizontalPaddingChanged();
248 qreal verticalPadding() const;
249 void setVerticalPadding(qreal value);
250 Q_SIGNAL void verticalPaddingChanged();
251 qreal leftPadding() const;
252 void setLeftPadding(qreal value);
253 Q_SIGNAL void leftPaddingChanged();
254 qreal rightPadding() const;
255 void setRightPadding(qreal value);
256 Q_SIGNAL void rightPaddingChanged();
257 qreal topPadding() const;
258 void setTopPadding(qreal value);
259 Q_SIGNAL void topPaddingChanged();
260 qreal bottomPadding() const;
261 void setBottomPadding(qreal value);
262 Q_SIGNAL void bottomPaddingChanged();
263 qreal spacing() const;
264 void setSpacing(qreal value);
265 Q_SIGNAL void spacingChanged();
266 qreal leftInset() const;
267 void setLeftInset(qreal value);
268 Q_SIGNAL void leftInsetChanged();
269 qreal rightInset() const;
270 void setRightInset(qreal value);
271 Q_SIGNAL void rightInsetChanged();
272 qreal topInset() const;
273 void setTopInset(qreal value);
274 Q_SIGNAL void topInsetChanged();
275 qreal bottomInset() const;
276 void setBottomInset(qreal value);
277 Q_SIGNAL void bottomInsetChanged();
278 qreal opacity() const;
279 void setOpacity(qreal value);
280 Q_SIGNAL void opacityChanged();
281 qreal scale() const;
282 void setScale(qreal value);
283 Q_SIGNAL void scaleChanged();
284 QQuickItem::TransformOrigin transformOrigin() const;
285 void setTransformOrigin(QQuickItem::TransformOrigin value);
286 Q_SIGNAL void transformOriginChanged();
287 bool enabled() const;
288 void setEnabled(bool value);
289 Q_SIGNAL void enabledChanged();
290 qreal availableWidth() const;
291 Q_SIGNAL void availableWidthChanged();
292 qreal availableHeight() const;
293 Q_SIGNAL void availableHeightChanged();
294 qreal implicitContentWidth() const;
295 Q_SIGNAL void implicitContentWidthChanged();
296 qreal implicitContentHeight() const;
297 Q_SIGNAL void implicitContentHeightChanged();
298 qreal implicitBackgroundWidth() const;
299 Q_SIGNAL void implicitBackgroundWidthChanged();
300 qreal implicitBackgroundHeight() const;
301 Q_SIGNAL void implicitBackgroundHeightChanged();
302 bool activeFocus() const;
303 Q_SIGNAL void activeFocusChanged();
304 bool visualFocus() const;
305 Q_SIGNAL void visualFocusChanged();
306 bool mirrored() const;
307 Q_SIGNAL void mirroredChanged();
308 Q_INVOKABLE virtual void open();
309 Q_INVOKABLE virtual void close();
310 virtual void closeFromInput();
311 Q_INVOKABLE void completeEnter();
312 Q_INVOKABLE void completeExit();
313 Q_INVOKABLE void forceActiveFocus(Qt::FocusReason reason = Qt::OtherFocusReason);
314 Q_INVOKABLE virtual void dismissImmediately();
315 bool acquirePresentation(QObject* owner);
316 void releasePresentation(QObject* owner);
317 void setPresentationAllowed(QObject* owner, bool allowed);
318 void setPresentationRequestEnabled(QObject* owner, bool enabled);
319 void setPresentationCloseHandler(QObject* owner, std::function<void()>);
320 QRectF presentationRect() const;
321 Q_SIGNAL void presentationRectChanged();
322 bool requestPresentation();
323 bool canRequestPresentation() const {
324 return presentationAllowed() || m_presentationRequestEnabled;
325 }
326 QObject* presentationOwner() const { return m_presentationOwner; }
327 bool presentationAllowed() const { return ! m_presentationOwner || m_presentationAllowed; }
328 Q_SIGNAL void presentationOwnerChanged();
329 Q_SIGNAL void presentationRequested();
330 void reposition();
331 virtual void updateDimmer(QQuickItem*, qreal opacity) const;
332 bool containsScenePoint(const QPointF&) const;
333 virtual bool blocksScenePoint(const QPointF&) const { return modal(); }
334 virtual bool overlayContainsScenePoint(const QPointF&) const { return true; }
335 bool parentContainsScenePoint(const QPointF&) const;
336 Q_SIGNAL void parentChanged();
337 Q_SIGNAL void popupItemChanged();
338 Q_SIGNAL void overlayItemChanged();
339 Q_SIGNAL void overlayGeometryChanged();
340 Q_SIGNAL void contentChildrenChanged();
341 Q_SIGNAL void visibleChanged();
342 Q_SIGNAL void openedChanged();
343 Q_SIGNAL void enteringChanged();
344 Q_SIGNAL void closingChanged();
345 Q_SIGNAL void modalChanged();
346 Q_SIGNAL void dimChanged();
347 Q_SIGNAL void focusChanged();
348 Q_SIGNAL void positioningItemChanged();
349 Q_SIGNAL void deferredCompletionChanged();
350 Q_SIGNAL void hideDelayChanged();
351 Q_SIGNAL void closePolicyChanged();
352 Q_SIGNAL void collisionPolicyChanged();
353 Q_SIGNAL void xChanged();
354 Q_SIGNAL void yChanged();
355 Q_SIGNAL void zChanged();
356 Q_SIGNAL void marginsChanged();
357 Q_SIGNAL void fontChanged();
358 Q_SIGNAL void localeChanged();
359 Q_SIGNAL void enterChanged();
360 Q_SIGNAL void exitChanged();
361 Q_SIGNAL void aboutToShow();
362 Q_SIGNAL void aboutToHide();
363 Q_SIGNAL void opened();
364 Q_SIGNAL void closed();
365
366protected:
367 void beginInteractiveTransition();
368 void endInteractiveTransition(bool opening);
369 struct TransitionTarget {
370 QString property;
371 QVariant value;
372 };
373 virtual QPointF surfacePosition() const;
374 virtual QSizeF surfaceSize() const { return { width(), height() }; }
375 virtual qreal presentationScale() const { return 1; }
376 virtual QList<TransitionTarget> transitionTargets(bool) const { return {}; }
377 virtual void finalizeTransition(bool) {}
378 virtual bool inheritsHoverEnabled() const { return true; }
379 Popup(Panel* surface, QObject* parent);
380 void classBegin() override;
381 void componentComplete() override;
382
383private:
384 friend class OverlayManager;
385 void overlayPress(const QPointF&);
386 void overlayRelease(const QPointF&);
387 void cancelOverlayPress();
388 bool m_outsidePressed = false, m_outsideParentPressed = false;
389 enum State
390 {
391 Closed,
392 Entering,
393 Open,
394 Closing
395 };
396 bool changeState(State);
397 void observeParent();
398 void observePositioningItem();
399 void refreshEnvironment();
400 void resolveFont();
401 void resolveLocale();
402 void resolveLayoutDirection();
403 void resolveHoverEnabled();
404 void refreshInheritedZ();
405 void updateOverlay();
406 void finishClose();
407 void startTransition(bool);
408 Panel* m_surface;
409 QPointer<QQuickItem> m_parent, m_hitItem, m_positioningItem;
410 QPointer<Control> m_environmentParent;
411 QPointer<OverlayManager> m_overlay;
412 QList<QMetaObject::Connection> m_parentConnections, m_overlayConnections;
413 QList<QMetaObject::Connection> m_positioningConnections;
414 QPointer<QQuickTransition> m_enter, m_exit;
415 std::unique_ptr<PopupMotion> m_motion;
416 State m_state = Closed;
417 bool m_dismissing = false;
418 bool m_finishingClose = false;
419 std::function<void()> m_presentationCloseHandler;
420 QQuickTransform* m_presentationTransform = nullptr;
421 std::optional<qreal> m_width, m_height;
422 bool m_interacting = false;
423 QPointer<QObject> m_presentationOwner;
424 QMetaObject::Connection m_presentationOwnerConnection;
425 bool m_presentationAllowed = false;
426 bool m_presentationRequestEnabled = false, m_requestingPresentation = false;
427 bool m_complete = false, m_requestedVisible = false, m_modal = false, m_focus = false,
428 m_deferred = false, m_positioning = false;
429 std::optional<bool> m_dim;
430 ClosePolicy m_closePolicy { CloseOnEscape | CloseOnPressOutside };
431 CollisionPolicy m_collision = Clamp;
432 QPointF m_position;
433 std::optional<qreal> m_z;
434 qreal m_inheritedZ = 0, m_margins = 0;
435 qreal m_savedOpacity = 1, m_savedScale = 1;
436 std::optional<qreal> m_leftMargin, m_rightMargin, m_topMargin, m_bottomMargin;
437 QFont m_font;
438 std::optional<QLocale> m_locale;
439 int m_hideDelay = 0;
440 QTimer m_hideTimer;
441};
442} // namespace qml_material
443Q_DECLARE_OPERATORS_FOR_FLAGS(qml_material::Popup::ClosePolicy)