4#include <QElapsedTimer>
8#include <QQmlListProperty>
11#include <QPointerEvent>
14#include "qml_material/scrollable/scroll_motion.hpp"
15#include "qml_material/export.hpp"
22class QML_MATERIAL_API FlickableVisibleArea :
public QObject {
26 Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged FINAL)
27 Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged FINAL)
28 Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged FINAL)
29 Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged FINAL)
32 explicit FlickableVisibleArea(Flickable* parent =
nullptr);
34 qreal xPosition()
const;
35 qreal yPosition()
const;
36 qreal widthRatio()
const;
37 qreal heightRatio()
const;
39 auto updateVisible() -> void;
41 Q_SIGNAL
void xPositionChanged(qreal value);
42 Q_SIGNAL
void yPositionChanged(qreal value);
43 Q_SIGNAL
void widthRatioChanged(qreal value);
44 Q_SIGNAL
void heightRatioChanged(qreal value);
47 QPointer<Flickable> m_flickable;
48 qreal m_xPosition { 0 };
49 qreal m_yPosition { 0 };
50 qreal m_widthRatio { 1 };
51 qreal m_heightRatio { 1 };
54class QML_MATERIAL_API Flickable :
public QQuickItem {
56 QML_NAMED_ELEMENT(Scrollable)
59 qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
61 qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
62 Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
63 Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
64 Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT)
66 Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
68 qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
69 Q_PROPERTY(qreal originY READ originY NOTIFY originYChanged)
70 Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
71 Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
72 Q_PROPERTY(qreal originX READ originX NOTIFY originXChanged)
74 Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged)
75 Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
76 Q_PROPERTY(QPointF dragVelocity READ dragVelocity NOTIFY dragVelocityChanged)
77 Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity
78 NOTIFY maximumFlickVelocityChanged)
79 Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY
80 flickDecelerationChanged)
81 Q_PROPERTY(
bool moving READ isMoving NOTIFY movingChanged)
82 Q_PROPERTY(
bool movingHorizontally READ isMovingHorizontally NOTIFY movingHorizontallyChanged)
83 Q_PROPERTY(
bool movingVertically READ isMovingVertically NOTIFY movingVerticallyChanged)
84 Q_PROPERTY(
bool flicking READ isFlicking NOTIFY flickingChanged)
86 bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged)
87 Q_PROPERTY(
bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged)
88 Q_PROPERTY(
bool dragging READ isDragging NOTIFY draggingChanged)
90 bool draggingHorizontally READ isDraggingHorizontally NOTIFY draggingHorizontallyChanged)
91 Q_PROPERTY(
bool draggingVertically READ isDraggingVertically NOTIFY draggingVerticallyChanged)
92 Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE
93 setFlickableDirection NOTIFY flickableDirectionChanged)
95 Q_PROPERTY(
bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
96 Q_PROPERTY(
int pressDelay READ pressDelay WRITE setPressDelay NOTIFY pressDelayChanged)
97 Q_PROPERTY(
bool atXEnd READ isAtXEnd NOTIFY atXEndChanged)
98 Q_PROPERTY(
bool atYEnd READ isAtYEnd NOTIFY atYEndChanged)
99 Q_PROPERTY(
bool atXBeginning READ isAtXBeginning NOTIFY atXBeginningChanged)
100 Q_PROPERTY(
bool atYBeginning READ isAtYBeginning NOTIFY atYBeginningChanged)
101 Q_PROPERTY(FlickableVisibleArea* visibleArea READ visibleArea CONSTANT)
102 Q_PROPERTY(
bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
103 Q_PROPERTY(
bool synchronousDrag READ synchronousDrag WRITE setSynchronousDrag NOTIFY
104 synchronousDragChanged)
105 Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY
106 acceptedButtonsChanged FINAL)
107 Q_PROPERTY(InputMaskMode inputMaskMode READ inputMaskMode WRITE setInputMaskMode NOTIFY
108 inputMaskModeChanged FINAL)
109 Q_PROPERTY(QQuickItem* interactionItem READ interactionItem WRITE setInteractionItem RESET
110 resetInteractionItem NOTIFY interactionItemChanged FINAL)
111 Q_PROPERTY(QQmlListProperty<QObject> flickableData READ flickableData)
112 Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren)
113 Q_CLASSINFO(
"DefaultProperty",
"flickableData")
116 explicit Flickable(QQuickItem* parent =
nullptr);
117 ~Flickable() override;
119 QQmlListProperty<QObject> flickableData();
120 QQmlListProperty<QQuickItem> flickableChildren();
122 enum FlickableDirection
124 AutoFlickDirection = 0x0,
125 HorizontalFlick = 0x1,
127 HorizontalAndVerticalFlick = 0x3,
128 AutoFlickIfNeeded = 0xc,
130 Q_ENUM(FlickableDirection)
138 Q_ENUM(InputMaskMode)
140 qreal contentWidth()
const;
141 void setContentWidth(qreal value);
143 qreal contentHeight()
const;
144 void setContentHeight(qreal value);
146 qreal contentX()
const;
147 virtual void setContentX(qreal position);
149 qreal contentY()
const;
150 virtual void setContentY(qreal position);
152 qreal topMargin()
const;
153 void setTopMargin(qreal value);
155 qreal bottomMargin()
const;
156 void setBottomMargin(qreal value);
158 qreal leftMargin()
const;
159 void setLeftMargin(qreal value);
161 qreal rightMargin()
const;
162 void setRightMargin(qreal value);
164 virtual qreal originY()
const;
165 virtual qreal originX()
const;
167 bool isMoving()
const;
168 bool isMovingHorizontally()
const;
169 bool isMovingVertically()
const;
170 bool isFlicking()
const;
171 bool isFlickingHorizontally()
const;
172 bool isFlickingVertically()
const;
173 bool isDragging()
const;
174 bool isDraggingHorizontally()
const;
175 bool isDraggingVertically()
const;
177 int pressDelay()
const;
178 void setPressDelay(
int delay);
180 qreal maximumFlickVelocity()
const;
181 void setMaximumFlickVelocity(qreal value);
183 qreal flickDeceleration()
const;
184 void setFlickDeceleration(qreal value);
186 bool isInteractive()
const;
187 void setInteractive(
bool value);
189 qreal horizontalVelocity()
const;
190 qreal verticalVelocity()
const;
192 QPointF dragVelocity()
const {
return m_dragVelocity; }
194 bool isAtXEnd()
const;
195 bool isAtXBeginning()
const;
196 bool isAtYEnd()
const;
197 bool isAtYBeginning()
const;
199 QQuickItem* contentItem()
const;
201 FlickableDirection flickableDirection()
const;
202 void setFlickableDirection(FlickableDirection direction);
204 bool pixelAligned()
const;
205 void setPixelAligned(
bool align);
207 bool synchronousDrag()
const;
208 void setSynchronousDrag(
bool value);
210 Qt::MouseButtons acceptedButtons()
const;
211 void setAcceptedButtons(Qt::MouseButtons buttons);
213 InputMaskMode inputMaskMode()
const;
214 void setInputMaskMode(InputMaskMode mode);
216 QQuickItem* interactionItem()
const;
217 void setInteractionItem(QQuickItem* item);
218 void resetInteractionItem();
220 FlickableVisibleArea* visibleArea();
222 Q_INVOKABLE
void resizeContent(qreal width, qreal height, QPointF center);
223 Q_INVOKABLE
void flick(qreal xVelocity, qreal yVelocity);
224 Q_INVOKABLE
void cancelFlick();
226 enum class ScrollInput
231 struct ScrollConsumption {
236 ScrollConsumption consumeScroll(QPointF delta, ScrollInput input,
237 Qt::ScrollPhase phase = Qt::NoScrollPhase);
239 Q_SIGNAL
void contentWidthChanged();
240 Q_SIGNAL
void contentHeightChanged();
241 Q_SIGNAL
void contentXChanged();
242 Q_SIGNAL
void contentYChanged();
243 Q_SIGNAL
void topMarginChanged();
244 Q_SIGNAL
void bottomMarginChanged();
245 Q_SIGNAL
void leftMarginChanged();
246 Q_SIGNAL
void rightMarginChanged();
247 Q_SIGNAL
void originYChanged();
248 Q_SIGNAL
void originXChanged();
249 Q_SIGNAL
void movingChanged();
250 Q_SIGNAL
void movingHorizontallyChanged();
251 Q_SIGNAL
void movingVerticallyChanged();
252 Q_SIGNAL
void flickingChanged();
253 Q_SIGNAL
void flickingHorizontallyChanged();
254 Q_SIGNAL
void flickingVerticallyChanged();
255 Q_SIGNAL
void draggingChanged();
256 Q_SIGNAL
void draggingHorizontallyChanged();
257 Q_SIGNAL
void draggingVerticallyChanged();
258 Q_SIGNAL
void horizontalVelocityChanged();
259 Q_SIGNAL
void verticalVelocityChanged();
260 Q_SIGNAL
void isAtBoundaryChanged();
261 Q_SIGNAL
void flickableDirectionChanged();
262 Q_SIGNAL
void interactiveChanged();
263 Q_SIGNAL
void maximumFlickVelocityChanged();
264 Q_SIGNAL
void flickDecelerationChanged();
265 Q_SIGNAL
void pressDelayChanged();
266 Q_SIGNAL
void movementStarted();
267 Q_SIGNAL
void movementEnded();
268 Q_SIGNAL
void flickStarted();
269 Q_SIGNAL
void flickEnded();
270 Q_SIGNAL
void dragStarted();
271 Q_SIGNAL
void dragEnded();
272 Q_SIGNAL
void dragVelocityChanged();
273 Q_SIGNAL
void dragReleased(QPointF velocity);
274 Q_SIGNAL
void pixelAlignedChanged();
275 Q_SIGNAL
void synchronousDragChanged();
276 Q_SIGNAL
void atXEndChanged();
277 Q_SIGNAL
void atYEndChanged();
278 Q_SIGNAL
void atXBeginningChanged();
279 Q_SIGNAL
void atYBeginningChanged();
280 Q_SIGNAL
void acceptedButtonsChanged();
281 Q_SIGNAL
void inputMaskModeChanged();
282 Q_SIGNAL
void interactionItemChanged();
286 void updateContentGeometry(QSizeF extent, QPointF anchorDelta = {});
287 virtual void scrollInputStarted();
288 virtual void scrollActivityCancelled();
289 void setVerticalScrollTarget(qreal position);
290 auto childMouseEventFilter(QQuickItem* item, QEvent* event) ->
bool override;
291 auto mousePressEvent(QMouseEvent* event) ->
void override;
292 auto mouseMoveEvent(QMouseEvent* event) ->
void override;
293 auto mouseReleaseEvent(QMouseEvent* event) ->
void override;
294 auto touchEvent(QTouchEvent* event) ->
void override;
295 auto wheelEvent(QWheelEvent* event) ->
void override;
296 auto timerEvent(QTimerEvent* event) ->
void override;
297 auto updatePolish() ->
void override;
298 auto geometryChange(
const QRectF& newGeometry,
const QRectF& oldGeometry) ->
void override;
299 auto componentComplete() ->
void override;
300 auto mouseUngrabEvent() ->
void override;
301 auto touchUngrabEvent() ->
void override;
304 virtual auto minXExtent() const -> qreal;
305 virtual auto minYExtent() const -> qreal;
306 virtual auto maxXExtent() const -> qreal;
307 virtual auto maxYExtent() const -> qreal;
308 auto vWidth() const -> qreal;
309 auto vHeight() const -> qreal;
310 virtual auto viewportMoved(Qt::Orientations orientation) ->
void;
311 auto xflick() const ->
bool;
312 auto yflick() const ->
bool;
315 friend class FlickableVisibleArea;
316 friend class ScrollParticipant;
325 qreal position { 0 };
326 qreal viewSize { -1 };
327 qreal startMargin { 0 };
328 qreal endMargin { 0 };
329 qreal pressPos { 0 };
330 qreal pressContentPos { 0 };
332 qreal dragStartOffset { 0 };
333 qreal previousDragDelta { 0 };
334 qreal velocity { 0 };
335 qreal smoothVelocity { 0 };
337 QVector<QPair<qint64, qreal>> velocityBuffer;
338 bool atEnd {
false };
339 bool atBeginning {
true };
340 bool moving {
false };
341 bool flicking {
false };
342 bool dragging {
false };
343 bool platformScrolling {
false };
345 auto resetDrag() -> void;
346 auto addVelocitySample(qint64 timestamp, qreal position, qreal maxVelocity) -> void;
347 auto updateVelocity() -> void;
350 static auto dataAppend(QQmlListProperty<QObject>* property, QObject*
object) -> void;
351 static auto dataCount(QQmlListProperty<QObject>* property) -> qsizetype;
352 static auto dataAt(QQmlListProperty<QObject>* property, qsizetype index) -> QObject*;
353 static auto dataClear(QQmlListProperty<QObject>* property) -> void;
354 static auto childrenAppend(QQmlListProperty<QQuickItem>* property, QQuickItem* item) -> void;
355 static auto childrenCount(QQmlListProperty<QQuickItem>* property) -> qsizetype;
356 static auto childrenAt(QQmlListProperty<QQuickItem>* property, qsizetype index) -> QQuickItem*;
357 static auto childrenClear(QQmlListProperty<QQuickItem>* property) -> void;
359 auto axisData(Axis axis) -> AxisData&;
360 auto axisData(Axis axis)
const ->
const AxisData&;
361 auto axisPosition(Axis axis)
const -> qreal;
362 auto setAxisPosition(Axis axis, qreal position) -> void;
363 void setContentPosition(Axis axis, qreal position);
364 auto minExtent(Axis axis)
const -> qreal;
365 auto maxExtent(Axis axis)
const -> qreal;
366 auto viewportSize(Axis axis)
const -> qreal;
367 auto axisCanFlick(Axis axis)
const -> bool;
368 auto aligned(qreal value)
const -> qreal;
369 auto boundedPosition(Axis axis, qreal position)
const -> qreal;
370 auto updateContentSize(Axis axis) -> void;
371 auto updateBeginningEnd() -> void;
372 auto updateVisibleArea() -> void;
373 void flushContentGeometry();
375 auto setAxisMoving(Axis axis,
bool value) -> void;
376 auto setAxisDragging(Axis axis,
bool value) -> void;
377 auto setAxisFlicking(Axis axis,
bool value) -> void;
378 auto setAxisVelocity(Axis axis, qreal value) -> void;
379 auto movementStarting() -> void;
380 auto movementEnding() -> void;
381 auto flickingStarted(
bool horizontal,
bool vertical) -> void;
382 auto draggingStarting(
bool horizontal,
bool vertical) -> void;
383 auto setDragVelocity(QPointF velocity) -> void;
384 auto draggingEnding(std::optional<QPointF> releaseVelocity = std::nullopt) -> void;
386 auto startAxisFlick(Axis axis, qreal velocity) -> void;
387 auto stopAxisMotion(Axis axis) -> void;
388 auto requestMotionFrame() -> void;
389 auto attachMotionWindow(QQuickWindow* window) -> void;
390 void cancelScrollActivity();
391 auto advanceAxis(Axis axis, qreal now) -> void;
392 auto fixup(Axis axis) -> void;
393 auto isAxisAnimating(Axis axis)
const -> bool;
395 auto handlePress(
const QPointF& position, qint64 timestamp) -> void;
396 auto handleMove(
const QPointF& position, qint64 timestamp, Qt::MouseButtons buttons) -> void;
397 auto handleRelease(
const QPointF& position, qint64 timestamp) -> void;
398 auto cancelInteraction() -> void;
399 bool captureDelayedPress(QQuickItem*, QPointerEvent*);
400 void clearDelayedPress();
401 void replayDelayedPress(QPointerEvent* release =
nullptr);
402 auto buttonsAccepted(
const QSinglePointEvent* event)
const -> bool;
403 auto pointerAccepted(QQuickItem* receiver, QEvent* event)
const -> bool;
404 auto acceptsPoint(
const QPointF& point)
const -> bool;
405 auto eventPosition(QQuickItem* receiver, QEvent* event)
const -> QPointF;
406 auto ignorePointerEvent(QEvent* event)
const -> void;
409 QQuickItem* m_contentItem {
nullptr };
410 quint64 m_geometryRevision { 0 };
411 unsigned m_geometryNotifications { 0 };
412 bool m_syncingGeometry {
false };
413 QList<QObject*> m_data;
416 QPointF m_dragVelocity;
417 FlickableVisibleArea* m_visibleArea {
nullptr };
418 QPointer<QQuickItem> m_interactionItem;
419 QMetaObject::Connection m_frameConnection;
420 QMetaObject::Connection m_windowVisibilityConnection;
421 bool m_motionWindowAttached =
false;
422 QElapsedTimer m_motionClock;
423 QBasicTimer m_pressDelayTimer;
424 QBasicTimer m_dragVelocityTimer;
425 std::unique_ptr<QPointerEvent> m_delayedPress;
426 QPointer<QQuickItem> m_delayedReceiver;
427 QPointer<QQuickWindow> m_delayedWindow;
428 bool m_replayingPress =
false;
431 qint64 m_lastPosTime { -1 };
432 qint64 m_lastPressTime { -1 };
433 FlickableDirection m_flickableDirection { AutoFlickDirection };
434 InputMaskMode m_inputMaskMode { Viewport };
435 qreal m_deceleration { 5000 };
436 qreal m_maxVelocity { 2500 };
437 int m_pressDelay { 0 };
438 bool m_pressed {
false };
439 bool m_stealMouse {
false };
440 bool m_interactive {
true };
441 bool m_pixelAligned {
false };
442 bool m_syncDrag {
false };
443 Qt::MouseButtons m_acceptedButtons { Qt::LeftButton };