4#include <QElapsedTimer>
8#include <QQmlListProperty>
17class FlickableVisibleArea :
public QObject {
21 Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged FINAL)
22 Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged FINAL)
23 Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged FINAL)
24 Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged FINAL)
27 explicit FlickableVisibleArea(Flickable* parent =
nullptr);
29 auto xPosition() const -> qreal;
30 auto yPosition() const -> qreal;
31 auto widthRatio() const -> qreal;
32 auto heightRatio() const -> qreal;
34 auto updateVisible() ->
void;
36 Q_SIGNAL
void xPositionChanged(qreal value);
37 Q_SIGNAL
void yPositionChanged(qreal value);
38 Q_SIGNAL
void widthRatioChanged(qreal value);
39 Q_SIGNAL
void heightRatioChanged(qreal value);
42 QPointer<Flickable> m_flickable;
43 qreal m_xPosition { 0 };
44 qreal m_yPosition { 0 };
45 qreal m_widthRatio { 1 };
46 qreal m_heightRatio { 1 };
49class Flickable :
public QQuickItem {
51 QML_NAMED_ELEMENT(Flickable2)
54 qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
56 qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
57 Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
58 Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
59 Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT)
61 Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
63 qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
64 Q_PROPERTY(qreal originY READ originY NOTIFY originYChanged)
65 Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
66 Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
67 Q_PROPERTY(qreal originX READ originX NOTIFY originXChanged)
69 Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged)
70 Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
71 Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity
72 NOTIFY maximumFlickVelocityChanged)
73 Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY
74 flickDecelerationChanged)
75 Q_PROPERTY(
bool moving READ isMoving NOTIFY movingChanged)
76 Q_PROPERTY(
bool movingHorizontally READ isMovingHorizontally NOTIFY movingHorizontallyChanged)
77 Q_PROPERTY(
bool movingVertically READ isMovingVertically NOTIFY movingVerticallyChanged)
78 Q_PROPERTY(
bool flicking READ isFlicking NOTIFY flickingChanged)
80 bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged)
81 Q_PROPERTY(
bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged)
82 Q_PROPERTY(
bool dragging READ isDragging NOTIFY draggingChanged)
84 bool draggingHorizontally READ isDraggingHorizontally NOTIFY draggingHorizontallyChanged)
85 Q_PROPERTY(
bool draggingVertically READ isDraggingVertically NOTIFY draggingVerticallyChanged)
86 Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE
87 setFlickableDirection NOTIFY flickableDirectionChanged)
89 Q_PROPERTY(
bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
90 Q_PROPERTY(
int pressDelay READ pressDelay WRITE setPressDelay NOTIFY pressDelayChanged)
91 Q_PROPERTY(
bool atXEnd READ isAtXEnd NOTIFY atXEndChanged)
92 Q_PROPERTY(
bool atYEnd READ isAtYEnd NOTIFY atYEndChanged)
93 Q_PROPERTY(
bool atXBeginning READ isAtXBeginning NOTIFY atXBeginningChanged)
94 Q_PROPERTY(
bool atYBeginning READ isAtYBeginning NOTIFY atYBeginningChanged)
95 Q_PROPERTY(FlickableVisibleArea* visibleArea READ visibleArea CONSTANT)
96 Q_PROPERTY(
bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
97 Q_PROPERTY(
bool synchronousDrag READ synchronousDrag WRITE setSynchronousDrag NOTIFY
98 synchronousDragChanged)
99 Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY
100 acceptedButtonsChanged FINAL)
101 Q_PROPERTY(InputMaskMode inputMaskMode READ inputMaskMode WRITE setInputMaskMode NOTIFY
102 inputMaskModeChanged FINAL)
103 Q_PROPERTY(QQuickItem* interactionItem READ interactionItem WRITE setInteractionItem RESET
104 resetInteractionItem NOTIFY interactionItemChanged FINAL)
105 Q_PROPERTY(QQmlListProperty<QObject> flickableData READ flickableData)
106 Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren)
107 Q_CLASSINFO(
"DefaultProperty",
"flickableData")
110 explicit Flickable(QQuickItem* parent =
nullptr);
111 ~Flickable() override;
113 auto flickableData() -> QQmlListProperty<QObject>;
114 auto flickableChildren() -> QQmlListProperty<QQuickItem>;
116 enum FlickableDirection
118 AutoFlickDirection = 0x0,
119 HorizontalFlick = 0x1,
121 HorizontalAndVerticalFlick = 0x3,
122 AutoFlickIfNeeded = 0xc,
124 Q_ENUM(FlickableDirection)
132 Q_ENUM(InputMaskMode)
134 auto contentWidth() const -> qreal;
135 auto setContentWidth(qreal value) ->
void;
137 auto contentHeight() const -> qreal;
138 auto setContentHeight(qreal value) ->
void;
140 auto contentX() const -> qreal;
141 virtual auto setContentX(qreal position) ->
void;
143 auto contentY() const -> qreal;
144 virtual auto setContentY(qreal position) ->
void;
146 auto topMargin() const -> qreal;
147 auto setTopMargin(qreal value) ->
void;
149 auto bottomMargin() const -> qreal;
150 auto setBottomMargin(qreal value) ->
void;
152 auto leftMargin() const -> qreal;
153 auto setLeftMargin(qreal value) ->
void;
155 auto rightMargin() const -> qreal;
156 auto setRightMargin(qreal value) ->
void;
158 virtual auto originY() const -> qreal;
159 virtual auto originX() const -> qreal;
161 auto isMoving() const ->
bool;
162 auto isMovingHorizontally() const ->
bool;
163 auto isMovingVertically() const ->
bool;
164 auto isFlicking() const ->
bool;
165 auto isFlickingHorizontally() const ->
bool;
166 auto isFlickingVertically() const ->
bool;
167 auto isDragging() const ->
bool;
168 auto isDraggingHorizontally() const ->
bool;
169 auto isDraggingVertically() const ->
bool;
171 auto pressDelay() const ->
int;
172 auto setPressDelay(
int delay) ->
void;
174 auto maximumFlickVelocity() const -> qreal;
175 auto setMaximumFlickVelocity(qreal value) ->
void;
177 auto flickDeceleration() const -> qreal;
178 auto setFlickDeceleration(qreal value) ->
void;
180 auto isInteractive() const ->
bool;
181 auto setInteractive(
bool value) ->
void;
183 auto horizontalVelocity() const -> qreal;
184 auto verticalVelocity() const -> qreal;
186 auto isAtXEnd() const ->
bool;
187 auto isAtXBeginning() const ->
bool;
188 auto isAtYEnd() const ->
bool;
189 auto isAtYBeginning() const ->
bool;
191 auto contentItem() const -> QQuickItem*;
193 auto flickableDirection() const -> FlickableDirection;
194 auto setFlickableDirection(FlickableDirection direction) ->
void;
196 auto pixelAligned() const ->
bool;
197 auto setPixelAligned(
bool align) ->
void;
199 auto synchronousDrag() const ->
bool;
200 auto setSynchronousDrag(
bool value) ->
void;
202 auto acceptedButtons() const -> Qt::MouseButtons;
203 auto setAcceptedButtons(Qt::MouseButtons buttons) ->
void;
205 auto inputMaskMode() const -> InputMaskMode;
206 auto setInputMaskMode(InputMaskMode mode) ->
void;
208 auto interactionItem() const -> QQuickItem*;
209 auto setInteractionItem(QQuickItem* item) ->
void;
210 auto resetInteractionItem() ->
void;
212 auto visibleArea() -> FlickableVisibleArea*;
214 Q_INVOKABLE auto resizeContent(qreal width, qreal height, QPointF center) ->
void;
215 Q_INVOKABLE auto flick(qreal xVelocity, qreal yVelocity) ->
void;
216 Q_INVOKABLE auto cancelFlick() ->
void;
218 Q_SIGNAL
void contentWidthChanged();
219 Q_SIGNAL
void contentHeightChanged();
220 Q_SIGNAL
void contentXChanged();
221 Q_SIGNAL
void contentYChanged();
222 Q_SIGNAL
void topMarginChanged();
223 Q_SIGNAL
void bottomMarginChanged();
224 Q_SIGNAL
void leftMarginChanged();
225 Q_SIGNAL
void rightMarginChanged();
226 Q_SIGNAL
void originYChanged();
227 Q_SIGNAL
void originXChanged();
228 Q_SIGNAL
void movingChanged();
229 Q_SIGNAL
void movingHorizontallyChanged();
230 Q_SIGNAL
void movingVerticallyChanged();
231 Q_SIGNAL
void flickingChanged();
232 Q_SIGNAL
void flickingHorizontallyChanged();
233 Q_SIGNAL
void flickingVerticallyChanged();
234 Q_SIGNAL
void draggingChanged();
235 Q_SIGNAL
void draggingHorizontallyChanged();
236 Q_SIGNAL
void draggingVerticallyChanged();
237 Q_SIGNAL
void horizontalVelocityChanged();
238 Q_SIGNAL
void verticalVelocityChanged();
239 Q_SIGNAL
void isAtBoundaryChanged();
240 Q_SIGNAL
void flickableDirectionChanged();
241 Q_SIGNAL
void interactiveChanged();
242 Q_SIGNAL
void maximumFlickVelocityChanged();
243 Q_SIGNAL
void flickDecelerationChanged();
244 Q_SIGNAL
void pressDelayChanged();
245 Q_SIGNAL
void movementStarted();
246 Q_SIGNAL
void movementEnded();
247 Q_SIGNAL
void flickStarted();
248 Q_SIGNAL
void flickEnded();
249 Q_SIGNAL
void dragStarted();
250 Q_SIGNAL
void dragEnded();
251 Q_SIGNAL
void pixelAlignedChanged();
252 Q_SIGNAL
void synchronousDragChanged();
253 Q_SIGNAL
void atXEndChanged();
254 Q_SIGNAL
void atYEndChanged();
255 Q_SIGNAL
void atXBeginningChanged();
256 Q_SIGNAL
void atYBeginningChanged();
257 Q_SIGNAL
void acceptedButtonsChanged();
258 Q_SIGNAL
void inputMaskModeChanged();
259 Q_SIGNAL
void interactionItemChanged();
262 auto childMouseEventFilter(QQuickItem* item, QEvent* event) ->
bool override;
263 auto mousePressEvent(QMouseEvent* event) ->
void override;
264 auto mouseMoveEvent(QMouseEvent* event) ->
void override;
265 auto mouseReleaseEvent(QMouseEvent* event) ->
void override;
266 auto touchEvent(QTouchEvent* event) ->
void override;
267 auto wheelEvent(QWheelEvent* event) ->
void override;
268 auto timerEvent(QTimerEvent* event) ->
void override;
269 auto geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) ->
void override;
270 auto componentComplete() ->
void override;
271 auto mouseUngrabEvent() ->
void override;
274 virtual auto minXExtent() const -> qreal;
275 virtual auto minYExtent() const -> qreal;
276 virtual auto maxXExtent() const -> qreal;
277 virtual auto maxYExtent() const -> qreal;
278 auto vWidth() const -> qreal;
279 auto vHeight() const -> qreal;
280 virtual auto viewportMoved(Qt::Orientations orientation) ->
void;
281 auto xflick() const ->
bool;
282 auto yflick() const ->
bool;
285 friend class FlickableVisibleArea;
300 qreal viewSize { -1 };
301 qreal startMargin { 0 };
302 qreal endMargin { 0 };
303 qreal pressPos { 0 };
304 qreal pressContentPos { 0 };
306 qreal dragStartOffset { 0 };
307 qreal previousDragDelta { 0 };
308 qreal velocity { 0 };
309 qreal smoothVelocity { 0 };
310 qreal motionStart { 0 };
311 qreal motionTarget { 0 };
312 qreal motionVelocity { 0 };
313 qreal motionDuration { 0 };
314 qreal motionElapsed { 0 };
315 QVector<QPair<qint64, qreal>> velocityBuffer;
316 MotionMode motionMode { NoMotion };
317 bool atEnd {
false };
318 bool atBeginning {
true };
319 bool moving {
false };
320 bool flicking {
false };
321 bool dragging {
false };
323 auto resetDrag() -> void;
324 auto addVelocitySample(qint64 timestamp, qreal position, qreal maxVelocity) -> void;
325 auto updateVelocity() -> void;
328 static auto dataAppend(QQmlListProperty<QObject>* property, QObject*
object) -> void;
329 static auto dataCount(QQmlListProperty<QObject>* property) -> qsizetype;
330 static auto dataAt(QQmlListProperty<QObject>* property, qsizetype index) -> QObject*;
331 static auto dataClear(QQmlListProperty<QObject>* property) -> void;
332 static auto childrenAppend(QQmlListProperty<QQuickItem>* property, QQuickItem* item) -> void;
333 static auto childrenCount(QQmlListProperty<QQuickItem>* property) -> qsizetype;
334 static auto childrenAt(QQmlListProperty<QQuickItem>* property, qsizetype index) -> QQuickItem*;
335 static auto childrenClear(QQmlListProperty<QQuickItem>* property) -> void;
337 auto axisData(Axis axis) -> AxisData&;
338 auto axisData(Axis axis)
const ->
const AxisData&;
339 auto axisPosition(Axis axis)
const -> qreal;
340 auto setAxisPosition(Axis axis, qreal position) -> void;
341 auto minExtent(Axis axis)
const -> qreal;
342 auto maxExtent(Axis axis)
const -> qreal;
343 auto viewportSize(Axis axis)
const -> qreal;
344 auto axisCanFlick(Axis axis)
const -> bool;
345 auto aligned(qreal value)
const -> qreal;
346 auto boundedPosition(Axis axis, qreal position)
const -> qreal;
347 auto updateContentSize(Axis axis) -> void;
348 auto updateBeginningEnd() -> void;
349 auto updateVisibleArea() -> void;
351 auto setAxisMoving(Axis axis,
bool value) -> void;
352 auto setAxisDragging(Axis axis,
bool value) -> void;
353 auto setAxisFlicking(Axis axis,
bool value) -> void;
354 auto setAxisVelocity(Axis axis, qreal value) -> void;
355 auto movementStarting() -> void;
356 auto movementEnding() -> void;
357 auto flickingStarted(
bool horizontal,
bool vertical) -> void;
358 auto draggingStarting(
bool horizontal,
bool vertical) -> void;
359 auto draggingEnding() -> void;
361 auto startAxisFlick(Axis axis, qreal velocity) -> void;
362 auto stopAxisMotion(Axis axis) -> void;
363 auto ensureMotionTimer() -> void;
364 auto advanceAxis(Axis axis, qreal deltaSeconds) -> void;
365 auto fixup(Axis axis) -> void;
366 auto isAxisAnimating(Axis axis)
const -> bool;
368 auto handlePress(
const QPointF& position, qint64 timestamp) -> void;
369 auto handleMove(
const QPointF& position, qint64 timestamp, Qt::MouseButtons buttons) -> void;
370 auto handleRelease(
const QPointF& position, qint64 timestamp) -> void;
371 auto cancelInteraction() -> void;
372 auto buttonsAccepted(
const QSinglePointEvent* event)
const -> bool;
373 auto pointerAccepted(QQuickItem* receiver, QEvent* event)
const -> bool;
374 auto acceptsPoint(
const QPointF& point)
const -> bool;
375 auto eventPosition(QQuickItem* receiver, QEvent* event)
const -> QPointF;
376 auto ignorePointerEvent(QEvent* event)
const -> void;
379 QQuickItem* m_contentItem {
nullptr };
380 QList<QObject*> m_data;
383 FlickableVisibleArea* m_visibleArea {
nullptr };
384 QPointer<QQuickItem> m_interactionItem;
385 QBasicTimer m_motionTimer;
386 QElapsedTimer m_motionClock;
387 QBasicTimer m_pressDelayTimer;
390 qint64 m_lastPosTime { -1 };
391 qint64 m_lastPressTime { -1 };
392 FlickableDirection m_flickableDirection { AutoFlickDirection };
393 InputMaskMode m_inputMaskMode { Viewport };
394 qreal m_deceleration { 5000 };
395 qreal m_wheelDeceleration { 15000 };
396 qreal m_maxVelocity { 2500 };
397 int m_pressDelay { 0 };
398 bool m_pressed {
false };
399 bool m_stealMouse {
false };
400 bool m_interactive {
true };
401 bool m_pixelAligned {
false };
402 bool m_syncDrag {
false };
403 Qt::MouseButtons m_acceptedButtons { Qt::LeftButton };