QmlMaterial 0.1.0
Loading...
Searching...
No Matches
carousel_view.hpp
1#pragma once
2
3#include <QPointer>
4#include <QQuickItem>
5#include <QQmlComponent>
6#include <QQmlEngine>
7#include <QVariant>
8#include <QVector>
9
10#include <QModelIndex>
11
12#include "qml_material/carousel/carousel_attached.hpp"
13#include "qml_material/carousel/carousel_strategy.hpp"
14
15class QAbstractItemModel;
16
17namespace qml_material
18{
19
20class CarouselView : public QQuickItem
21{
22 Q_OBJECT
23 QML_ELEMENT
24 QML_ATTACHED(CarouselAttached)
25
26 Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged FINAL)
27 Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
28 Q_PROPERTY(int count READ count NOTIFY countChanged FINAL)
29 Q_PROPERTY(int layout READ layout WRITE setLayout NOTIFY layoutChanged FINAL)
30 Q_PROPERTY(int orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
31 Q_PROPERTY(qreal itemExtent READ itemExtent WRITE setItemExtent NOTIFY itemExtentChanged FINAL)
32 Q_PROPERTY(qreal minSmallItemWidth READ minSmallItemWidth WRITE setMinSmallItemWidth NOTIFY
33 minSmallItemWidthChanged FINAL)
34 Q_PROPERTY(qreal maxSmallItemWidth READ maxSmallItemWidth WRITE setMaxSmallItemWidth NOTIFY
35 maxSmallItemWidthChanged FINAL)
36 Q_PROPERTY(bool itemSnapping READ itemSnapping WRITE setItemSnapping NOTIFY itemSnappingChanged FINAL)
37 Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL)
38 Q_PROPERTY(int initialItem READ initialItem WRITE setInitialItem NOTIFY initialItemChanged FINAL)
39 Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged FINAL)
40 Q_PROPERTY(qreal contentPaddingStart READ contentPaddingStart WRITE setContentPaddingStart NOTIFY
41 contentPaddingChanged FINAL)
42 Q_PROPERTY(qreal contentPaddingEnd READ contentPaddingEnd WRITE setContentPaddingEnd NOTIFY
43 contentPaddingChanged FINAL)
44 Q_PROPERTY(qreal contentPaddingCross READ contentPaddingCross WRITE setContentPaddingCross NOTIFY
45 contentPaddingCrossChanged FINAL)
46 Q_PROPERTY(bool clipContainer READ clipContainer WRITE setClipContainer NOTIFY clipContainerChanged FINAL)
47 Q_PROPERTY(bool reduceMotion READ reduceMotion WRITE setReduceMotion NOTIFY reduceMotionChanged FINAL)
48 Q_PROPERTY(bool interactive READ interactive WRITE setInteractive NOTIFY interactiveChanged FINAL)
49 Q_PROPERTY(qreal itemCornerRadius READ itemCornerRadius WRITE setItemCornerRadius NOTIFY
50 itemCornerRadiusChanged FINAL)
51 Q_PROPERTY(qreal contentWidth READ contentWidth NOTIFY contentWidthChanged FINAL)
52 Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentHeightChanged FINAL)
53 Q_PROPERTY(QQuickItem* flickable READ flickable CONSTANT FINAL)
54
55public:
56 explicit CarouselView(QQuickItem* parent = nullptr);
57 ~CarouselView() override;
58
59 static CarouselAttached* qmlAttachedProperties(QObject* object);
60
61 QVariant model() const;
62 void setModel(const QVariant& model);
63 QQmlComponent* delegate() const;
64 void setDelegate(QQmlComponent* delegate);
65 int count() const;
66
67 int layout() const;
68 void setLayout(int layout);
69 int orientation() const;
70 void setOrientation(int orientation);
71
72 qreal itemExtent() const;
73 void setItemExtent(qreal extent);
74 qreal minSmallItemWidth() const;
75 void setMinSmallItemWidth(qreal width);
76 qreal maxSmallItemWidth() const;
77 void setMaxSmallItemWidth(qreal width);
78 bool itemSnapping() const;
79 void setItemSnapping(bool snapping);
80 int currentIndex() const;
81 void setCurrentIndex(int index);
82 int initialItem() const;
83 void setInitialItem(int item);
84 qreal spacing() const;
85 void setSpacing(qreal spacing);
86 qreal contentPaddingStart() const;
87 void setContentPaddingStart(qreal padding);
88 qreal contentPaddingEnd() const;
89 void setContentPaddingEnd(qreal padding);
90 qreal contentPaddingCross() const;
91 void setContentPaddingCross(qreal padding);
92 bool clipContainer() const;
93 void setClipContainer(bool clip);
94 bool reduceMotion() const;
95 void setReduceMotion(bool reduce);
96 qreal itemCornerRadius() const;
97 void setItemCornerRadius(qreal radius);
98 bool interactive() const;
99 void setInteractive(bool interactive);
100 qreal contentWidth() const;
101 qreal contentHeight() const;
102 QQuickItem* flickable() const;
103
104 Q_INVOKABLE void incrementCurrentIndex();
105 Q_INVOKABLE void decrementCurrentIndex();
106 Q_INVOKABLE void incrementCurrentIndexFromKeyboard();
107 Q_INVOKABLE void decrementCurrentIndexFromKeyboard();
108 Q_INVOKABLE void setCurrentIndexAnimated(int index);
109 Q_INVOKABLE void focusCurrentItem();
110 Q_INVOKABLE void claimInteractionFocus();
111 Q_INVOKABLE void engageTabFocus();
112 Q_INVOKABLE void suppressFocusRing();
113
114 Q_SIGNAL void modelChanged();
115 Q_SIGNAL void delegateChanged();
116 Q_SIGNAL void countChanged();
117 Q_SIGNAL void layoutChanged();
118 Q_SIGNAL void orientationChanged();
119 Q_SIGNAL void itemExtentChanged();
120 Q_SIGNAL void minSmallItemWidthChanged();
121 Q_SIGNAL void maxSmallItemWidthChanged();
122 Q_SIGNAL void itemSnappingChanged();
123 Q_SIGNAL void currentIndexChanged();
124 Q_SIGNAL void initialItemChanged();
125 Q_SIGNAL void spacingChanged();
126 Q_SIGNAL void contentPaddingChanged();
127 Q_SIGNAL void contentPaddingCrossChanged();
128 Q_SIGNAL void clipContainerChanged();
129 Q_SIGNAL void reduceMotionChanged();
130 Q_SIGNAL void itemCornerRadiusChanged();
131 Q_SIGNAL void interactiveChanged();
132 Q_SIGNAL void contentWidthChanged();
133 Q_SIGNAL void contentHeightChanged();
134 Q_SIGNAL void clicked(int index);
135
136protected:
137 void componentComplete() override;
138 void geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) override;
139 void itemChange(ItemChange change, const ItemChangeData& value) override;
140
141private Q_SLOTS:
142 void onDelegateClicked();
143 void onDelegateAspectRatioChanged();
144 void onSnapTick();
145 void onModelRowsChanged();
146 void onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
147 const QList<int>& roles);
148
149private:
150 void syncCurrentIndexAfterCountChange();
151 void rebuildItems();
152 void updateLayout();
153 void updateCount();
154 void clearLayout();
155 void bindItemModel(QAbstractItemModel* model);
156 void unbindItemModel();
157 void snapAfterGesture();
158 void cancelSnapAnimation();
159 void applySnapAnimation(qreal targetOffset);
160 void finishSnap(qreal targetOffset);
161 qreal snapOffsetForIndex(int index) const;
162 void syncScrollToIndex(int index);
163 qreal snapTargetForGesture(qreal offset, qreal velocity) const;
164 int snapIndexForOffset(qreal offset) const;
165 int snapIndexForFling(qreal offset, qreal velocity) const;
166 bool usesSingleAdvanceFling() const;
167 bool usesFreeScrollSnap() const;
168 QVariant modelDataAt(int index) const;
169 QVariantMap initialPropertiesForDelegate(int index) const;
170 void applyDelegateProperties(QQuickItem* item, int index) const;
171 void createDelegate(int index);
172 void destroyDelegate(int index);
173 void positionItem(QQuickItem* item, const CarouselItemGeometry& geom, bool isActive);
174 int activeIndexForLayout(const CarouselLayoutOutput& out) const;
175 void broadcastFocusRingState();
176 void completeKeyboardNavigation();
177
178 QVariant m_model;
179 QQmlComponent* m_delegate = nullptr;
180 QPointer<QAbstractItemModel> m_item_model;
181 int m_count = 0;
182 int m_layout = 0;
183 Qt::Orientation m_orientation = Qt::Horizontal;
184 qreal m_item_extent = 180;
185 qreal m_min_small_item_width = 40;
186 qreal m_max_small_item_width = 56;
187 qreal m_item_corner_radius = 28;
188 bool m_item_snapping = true;
189 int m_current_index = 0;
190 int m_initial_item = 0;
191 qreal m_spacing = 8;
192 qreal m_content_padding_start = 0;
193 qreal m_content_padding_end = 0;
194 qreal m_content_padding_cross = 0;
195 bool m_clip_container = true;
196 bool m_reduce_motion = false;
197 bool m_interactive = true;
198 bool m_snapping = false;
199 qreal m_content_width = 0;
200 qreal m_content_height = 0;
201 bool m_completed = false;
202
203 qreal m_snap_pos = 0;
204 qreal m_snap_velocity = 0;
205 qreal m_snap_target = 0;
206 class QTimer* m_snap_timer = nullptr;
207 QObject* m_snap_anim = nullptr;
208
209 QQuickItem* m_flickable = nullptr;
210 QQuickItem* m_content = nullptr;
211 QVector<QQuickItem*> m_items;
212 QVector<CarouselItemGeometry> m_geometries;
213 QVector<qreal> m_snap_offsets;
214 QVector<qreal> m_item_aspects;
215 qreal m_max_scroll_offset = 0;
216 qreal m_end_snap_offset = 0;
217 qreal m_scroll_step = 0;
218 bool m_updating = false;
219 bool m_focus_ring_suppressed = true;
220 bool m_tab_focus_engaged = false;
221 bool m_keyboard_nav_pending = false;
222 bool m_suppress_tab_engage = false;
223};
224
225} // namespace qml_material