1 | // Copyright (C) 2017 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qquickscrollindicator_p.h" |
5 | #include "qquickcontrol_p_p.h" |
6 | |
7 | #include <QtQml/qqmlinfo.h> |
8 | #include <QtQuick/private/qquickflickable_p.h> |
9 | #include <QtQuick/private/qquickitemchangelistener_p.h> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | /*! |
14 | \qmltype ScrollIndicator |
15 | \inherits Control |
16 | //! \nativetype QQuickScrollIndicator |
17 | \inqmlmodule QtQuick.Controls |
18 | \since 5.7 |
19 | \ingroup qtquickcontrols-indicators |
20 | \brief Vertical or horizontal non-interactive scroll indicator. |
21 | |
22 | \image qtquickcontrols-scrollindicator.gif |
23 | |
24 | ScrollIndicator is a non-interactive indicator that indicates the current scroll |
25 | position. A scroll indicator can be either \l vertical or \l horizontal, and can |
26 | be attached to any \l Flickable, such as \l ListView and \l GridView. |
27 | |
28 | \code |
29 | Flickable { |
30 | // ... |
31 | ScrollIndicator.vertical: ScrollIndicator { } |
32 | } |
33 | \endcode |
34 | |
35 | \section1 Attaching ScrollIndicator to a Flickable |
36 | |
37 | \note When ScrollIndicator is attached \l {ScrollIndicator::vertical}{vertically} |
38 | or \l {ScrollIndicator::horizontal}{horizontally} to a Flickable, its geometry and |
39 | the following properties are automatically set and updated as appropriate: |
40 | |
41 | \list |
42 | \li \l orientation |
43 | \li \l position |
44 | \li \l size |
45 | \li \l active |
46 | \endlist |
47 | |
48 | An attached ScrollIndicator re-parents itself to the target Flickable. A vertically |
49 | attached ScrollIndicator resizes itself to the height of the Flickable, and positions |
50 | itself to either side of it based on the \l {Control::mirrored}{layout direction}. |
51 | A horizontally attached ScrollIndicator resizes itself to the width of the Flickable, |
52 | and positions itself to the bottom. The automatic geometry management can be disabled |
53 | by specifying another parent for the attached ScrollIndicator. This can be useful, for |
54 | example, if the ScrollIndicator should be placed outside a clipping Flickable. This is |
55 | demonstrated by the following example: |
56 | |
57 | \code |
58 | Flickable { |
59 | id: flickable |
60 | clip: true |
61 | // ... |
62 | ScrollIndicator.vertical: ScrollIndicator { |
63 | parent: flickable.parent |
64 | anchors.top: flickable.top |
65 | anchors.left: flickable.right |
66 | anchors.bottom: flickable.bottom |
67 | } |
68 | } |
69 | \endcode |
70 | |
71 | \section1 Binding the Active State of Horizontal and Vertical Scroll Indicators |
72 | |
73 | Horizontal and vertical scroll indicators do not share the \l active state with |
74 | each other by default. In order to keep both indicators visible whilst scrolling |
75 | to either direction, establish a two-way binding between the active states as |
76 | presented by the following example: |
77 | |
78 | \snippet qtquickcontrols-scrollindicator-active.qml 1 |
79 | |
80 | \section1 Non-attached Scroll Indicators |
81 | |
82 | It is possible to create an instance of ScrollIndicator without using the |
83 | attached property API. This is useful when the behavior of the attached |
84 | scoll indicator is not sufficient or a \l Flickable is not in use. In the |
85 | following example, horizontal and vertical scroll indicators are used to |
86 | indicate how far the user has scrolled over the text (using \l MouseArea |
87 | instead of \l Flickable): |
88 | |
89 | \snippet qtquickcontrols-scrollindicator-non-attached.qml 1 |
90 | |
91 | \image qtquickcontrols-scrollindicator-non-attached.png |
92 | |
93 | \sa ScrollBar, {Customizing ScrollIndicator}, {Indicator Controls} |
94 | */ |
95 | |
96 | static const QQuickItemPrivate::ChangeTypes QsiChangeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed; |
97 | static const QQuickItemPrivate::ChangeTypes QsiHorizontalChangeTypes = QsiChangeTypes | QQuickItemPrivate::ImplicitHeight; |
98 | static const QQuickItemPrivate::ChangeTypes QsiVerticalChangeTypes = QsiChangeTypes | QQuickItemPrivate::ImplicitWidth; |
99 | |
100 | class QQuickScrollIndicatorPrivate : public QQuickControlPrivate |
101 | { |
102 | Q_DECLARE_PUBLIC(QQuickScrollIndicator) |
103 | |
104 | public: |
105 | struct VisualArea |
106 | { |
107 | VisualArea(qreal pos, qreal sz) |
108 | : position(pos), size(sz) { } |
109 | qreal position = 0; |
110 | qreal size = 0; |
111 | }; |
112 | VisualArea visualArea() const; |
113 | void visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea); |
114 | |
115 | void resizeContent() override; |
116 | |
117 | qreal size = 0; |
118 | qreal minimumSize = 0; |
119 | qreal position = 0; |
120 | bool active = false; |
121 | Qt::Orientation orientation = Qt::Vertical; |
122 | }; |
123 | |
124 | QQuickScrollIndicatorPrivate::VisualArea QQuickScrollIndicatorPrivate::visualArea() const |
125 | { |
126 | qreal visualPos = position; |
127 | if (minimumSize > size) |
128 | visualPos = position / (1.0 - size) * (1.0 - minimumSize); |
129 | |
130 | qreal maximumSize = qMax<qreal>(a: 0.0, b: 1.0 - visualPos); |
131 | qreal visualSize = qMax<qreal>(a: minimumSize, |
132 | b: qMin<qreal>(a: qMax(a: size, b: minimumSize) + qMin<qreal>(a: 0, b: visualPos), |
133 | b: maximumSize)); |
134 | |
135 | visualPos = qMax<qreal>(a: 0,b: qMin<qreal>(a: visualPos,b: qMax<qreal>(a: 0, b: 1.0 - visualSize))); |
136 | |
137 | return VisualArea(visualPos, visualSize); |
138 | } |
139 | |
140 | void QQuickScrollIndicatorPrivate::visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea) |
141 | { |
142 | Q_Q(QQuickScrollIndicator); |
143 | if (!qFuzzyCompare(p1: newVisualArea.size, p2: oldVisualArea.size)) |
144 | emit q->visualSizeChanged(); |
145 | if (!qFuzzyCompare(p1: newVisualArea.position, p2: oldVisualArea.position)) |
146 | emit q->visualPositionChanged(); |
147 | } |
148 | |
149 | void QQuickScrollIndicatorPrivate::resizeContent() |
150 | { |
151 | Q_Q(QQuickScrollIndicator); |
152 | if (!contentItem) |
153 | return; |
154 | |
155 | // - negative overshoot (pos < 0): clamp the pos to 0, and deduct the overshoot from the size |
156 | // - positive overshoot (pos + size > 1): clamp the size to 1-pos |
157 | const VisualArea visual = visualArea(); |
158 | |
159 | if (orientation == Qt::Horizontal) { |
160 | contentItem->setPosition(QPointF(q->leftPadding() + visual.position * q->availableWidth(), q->topPadding())); |
161 | contentItem->setSize(QSizeF(q->availableWidth() * visual.size, q->availableHeight())); |
162 | } else { |
163 | contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding() + visual.position * q->availableHeight())); |
164 | contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * visual.size)); |
165 | } |
166 | } |
167 | |
168 | QQuickScrollIndicator::QQuickScrollIndicator(QQuickItem *parent) |
169 | : QQuickControl(*(new QQuickScrollIndicatorPrivate), parent) |
170 | { |
171 | Q_D(QQuickScrollIndicator); |
172 | d->setSizePolicy(horizontalPolicy: QLayoutPolicy::Preferred, verticalPolicy: QLayoutPolicy::Fixed); |
173 | } |
174 | |
175 | QQuickScrollIndicatorAttached *QQuickScrollIndicator::qmlAttachedProperties(QObject *object) |
176 | { |
177 | return new QQuickScrollIndicatorAttached(object); |
178 | } |
179 | |
180 | /*! |
181 | \qmlproperty real QtQuick.Controls::ScrollIndicator::size |
182 | |
183 | This property holds the size of the indicator, scaled to \c {0.0 - 1.0}. |
184 | |
185 | \sa {Flickable::visibleArea.heightRatio}{Flickable::visibleArea} |
186 | |
187 | This property is automatically set when the scroll indicator is |
188 | \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}. |
189 | |
190 | \sa minimumSize, visualSize |
191 | */ |
192 | qreal QQuickScrollIndicator::size() const |
193 | { |
194 | Q_D(const QQuickScrollIndicator); |
195 | return d->size; |
196 | } |
197 | |
198 | void QQuickScrollIndicator::setSize(qreal size) |
199 | { |
200 | Q_D(QQuickScrollIndicator); |
201 | if (qFuzzyCompare(p1: d->size, p2: size)) |
202 | return; |
203 | |
204 | auto oldVisualArea = d->visualArea(); |
205 | d->size = size; |
206 | if (d->size + d->position > 1.0) { |
207 | setPosition(1.0 - d->size); |
208 | oldVisualArea = d->visualArea(); |
209 | } |
210 | if (isComponentComplete()) |
211 | d->resizeContent(); |
212 | emit sizeChanged(); |
213 | d->visualAreaChange(newVisualArea: d->visualArea(), oldVisualArea); |
214 | } |
215 | |
216 | /*! |
217 | \qmlproperty real QtQuick.Controls::ScrollIndicator::position |
218 | |
219 | This property holds the position of the indicator, scaled to \c {0.0 - 1.0}. |
220 | |
221 | This property is automatically set when the scroll indicator is |
222 | \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}. |
223 | |
224 | \sa {Flickable::visibleArea.yPosition}{Flickable::visibleArea}, visualPosition |
225 | */ |
226 | qreal QQuickScrollIndicator::position() const |
227 | { |
228 | Q_D(const QQuickScrollIndicator); |
229 | return d->position; |
230 | } |
231 | |
232 | void QQuickScrollIndicator::setPosition(qreal position) |
233 | { |
234 | Q_D(QQuickScrollIndicator); |
235 | if (qFuzzyCompare(p1: d->position, p2: position)) |
236 | return; |
237 | |
238 | auto oldVisualArea = d->visualArea(); |
239 | d->position = position; |
240 | if (isComponentComplete()) |
241 | d->resizeContent(); |
242 | emit positionChanged(); |
243 | d->visualAreaChange(newVisualArea: d->visualArea(), oldVisualArea); |
244 | } |
245 | |
246 | /*! |
247 | \qmlproperty bool QtQuick.Controls::ScrollIndicator::active |
248 | |
249 | This property holds whether the indicator is active, that is, when the |
250 | attached Flickable is \l {Flickable::moving}{moving}. |
251 | |
252 | It is possible to keep \l {Binding the Active State of Horizontal and Vertical Scroll Indicators} |
253 | {both horizontal and vertical indicators visible} while scrolling in either direction. |
254 | |
255 | This property is automatically set when the scroll indicator is |
256 | \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}. |
257 | */ |
258 | bool QQuickScrollIndicator::isActive() const |
259 | { |
260 | Q_D(const QQuickScrollIndicator); |
261 | return d->active; |
262 | } |
263 | |
264 | void QQuickScrollIndicator::setActive(bool active) |
265 | { |
266 | Q_D(QQuickScrollIndicator); |
267 | if (d->active == active) |
268 | return; |
269 | |
270 | d->active = active; |
271 | emit activeChanged(); |
272 | } |
273 | |
274 | /*! |
275 | \qmlproperty enumeration QtQuick.Controls::ScrollIndicator::orientation |
276 | |
277 | This property holds the orientation of the indicator. |
278 | |
279 | Possible values: |
280 | \value Qt.Horizontal Horizontal |
281 | \value Qt.Vertical Vertical (default) |
282 | |
283 | This property is automatically set when the scroll indicator is |
284 | \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}. |
285 | |
286 | \sa horizontal, vertical |
287 | */ |
288 | Qt::Orientation QQuickScrollIndicator::orientation() const |
289 | { |
290 | Q_D(const QQuickScrollIndicator); |
291 | return d->orientation; |
292 | } |
293 | |
294 | void QQuickScrollIndicator::setOrientation(Qt::Orientation orientation) |
295 | { |
296 | Q_D(QQuickScrollIndicator); |
297 | if (d->orientation == orientation) |
298 | return; |
299 | |
300 | if (orientation == Qt::Horizontal) |
301 | d->setSizePolicy(horizontalPolicy: QLayoutPolicy::Preferred, verticalPolicy: QLayoutPolicy::Fixed); |
302 | else |
303 | d->setSizePolicy(horizontalPolicy: QLayoutPolicy::Fixed, verticalPolicy: QLayoutPolicy::Preferred); |
304 | |
305 | d->orientation = orientation; |
306 | if (isComponentComplete()) |
307 | d->resizeContent(); |
308 | emit orientationChanged(); |
309 | } |
310 | |
311 | /*! |
312 | \since QtQuick.Controls 2.3 (Qt 5.10) |
313 | \qmlproperty bool QtQuick.Controls::ScrollIndicator::horizontal |
314 | \readonly |
315 | |
316 | This property holds whether the scroll indicator is horizontal. |
317 | |
318 | \sa orientation |
319 | */ |
320 | bool QQuickScrollIndicator::isHorizontal() const |
321 | { |
322 | Q_D(const QQuickScrollIndicator); |
323 | return d->orientation == Qt::Horizontal; |
324 | } |
325 | |
326 | /*! |
327 | \since QtQuick.Controls 2.3 (Qt 5.10) |
328 | \qmlproperty bool QtQuick.Controls::ScrollIndicator::vertical |
329 | \readonly |
330 | |
331 | This property holds whether the scroll indicator is vertical. |
332 | |
333 | \sa orientation |
334 | */ |
335 | bool QQuickScrollIndicator::isVertical() const |
336 | { |
337 | Q_D(const QQuickScrollIndicator); |
338 | return d->orientation == Qt::Vertical; |
339 | } |
340 | |
341 | /*! |
342 | \since QtQuick.Controls 2.4 (Qt 5.11) |
343 | \qmlproperty real QtQuick.Controls::ScrollIndicator::minimumSize |
344 | |
345 | This property holds the minimum size of the indicator, scaled to \c {0.0 - 1.0}. |
346 | |
347 | \sa size, visualSize, visualPosition |
348 | */ |
349 | qreal QQuickScrollIndicator::minimumSize() const |
350 | { |
351 | Q_D(const QQuickScrollIndicator); |
352 | return d->minimumSize; |
353 | } |
354 | |
355 | void QQuickScrollIndicator::setMinimumSize(qreal minimumSize) |
356 | { |
357 | Q_D(QQuickScrollIndicator); |
358 | if (qFuzzyCompare(p1: d->minimumSize, p2: minimumSize)) |
359 | return; |
360 | |
361 | auto oldVisualArea = d->visualArea(); |
362 | d->minimumSize = minimumSize; |
363 | if (isComponentComplete()) |
364 | d->resizeContent(); |
365 | emit minimumSizeChanged(); |
366 | d->visualAreaChange(newVisualArea: d->visualArea(), oldVisualArea); |
367 | } |
368 | |
369 | /*! |
370 | \since QtQuick.Controls 2.4 (Qt 5.11) |
371 | \qmlproperty real QtQuick.Controls::ScrollIndicator::visualSize |
372 | |
373 | This property holds the effective visual size of the indicator, |
374 | which may be limited by the \l {minimumSize}{minimum size}. |
375 | |
376 | \sa size, minimumSize |
377 | */ |
378 | qreal QQuickScrollIndicator::visualSize() const |
379 | { |
380 | Q_D(const QQuickScrollIndicator); |
381 | return d->visualArea().size; |
382 | } |
383 | |
384 | /*! |
385 | \since QtQuick.Controls 2.4 (Qt 5.11) |
386 | \qmlproperty real QtQuick.Controls::ScrollIndicator::visualPosition |
387 | |
388 | This property holds the effective visual position of the indicator, |
389 | which may be limited by the \l {minimumSize}{minimum size}. |
390 | |
391 | \sa position, minimumSize |
392 | */ |
393 | qreal QQuickScrollIndicator::visualPosition() const |
394 | { |
395 | Q_D(const QQuickScrollIndicator); |
396 | return d->visualArea().position; |
397 | } |
398 | |
399 | class QQuickScrollIndicatorAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener |
400 | { |
401 | public: |
402 | void activateHorizontal(); |
403 | void activateVertical(); |
404 | |
405 | void layoutHorizontal(bool move = true); |
406 | void layoutVertical(bool move = true); |
407 | |
408 | void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; |
409 | void itemImplicitWidthChanged(QQuickItem *item) override; |
410 | void itemImplicitHeightChanged(QQuickItem *item) override; |
411 | void itemDestroyed(QQuickItem *item) override; |
412 | |
413 | QQuickFlickable *flickable = nullptr; |
414 | QQuickScrollIndicator *horizontal = nullptr; |
415 | QQuickScrollIndicator *vertical = nullptr; |
416 | }; |
417 | |
418 | void QQuickScrollIndicatorAttachedPrivate::activateHorizontal() |
419 | { |
420 | horizontal->setActive(flickable->isMovingHorizontally()); |
421 | } |
422 | |
423 | void QQuickScrollIndicatorAttachedPrivate::activateVertical() |
424 | { |
425 | vertical->setActive(flickable->isMovingVertically()); |
426 | } |
427 | |
428 | void QQuickScrollIndicatorAttachedPrivate::layoutHorizontal(bool move) |
429 | { |
430 | Q_ASSERT(horizontal && flickable); |
431 | if (horizontal->parentItem() != flickable) |
432 | return; |
433 | horizontal->setWidth(flickable->width()); |
434 | if (move) |
435 | horizontal->setY(flickable->height() - horizontal->height()); |
436 | } |
437 | |
438 | void QQuickScrollIndicatorAttachedPrivate::layoutVertical(bool move) |
439 | { |
440 | Q_ASSERT(vertical && flickable); |
441 | if (vertical->parentItem() != flickable) |
442 | return; |
443 | vertical->setHeight(flickable->height()); |
444 | if (move && !QQuickItemPrivate::get(item: vertical)->isMirrored()) |
445 | vertical->setX(flickable->width() - vertical->width()); |
446 | } |
447 | |
448 | void QQuickScrollIndicatorAttachedPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) |
449 | { |
450 | Q_UNUSED(item); |
451 | Q_UNUSED(change); |
452 | if (horizontal && horizontal->height() > 0) { |
453 | #ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry |
454 | bool move = qFuzzyIsNull(d: horizontal->y()) || qFuzzyCompare(p1: horizontal->y(), p2: diff.height() - horizontal->height()); |
455 | #else |
456 | bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), item->height() - diff.height() - horizontal->height()); |
457 | #endif |
458 | layoutHorizontal(move); |
459 | } |
460 | if (vertical && vertical->width() > 0) { |
461 | #ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry |
462 | bool move = qFuzzyIsNull(d: vertical->x()) || qFuzzyCompare(p1: vertical->x(), p2: diff.width() - vertical->width()); |
463 | #else |
464 | bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), item->width() - diff.width() - vertical->width()); |
465 | #endif |
466 | layoutVertical(move); |
467 | } |
468 | } |
469 | |
470 | void QQuickScrollIndicatorAttachedPrivate::itemImplicitWidthChanged(QQuickItem *item) |
471 | { |
472 | if (item == vertical) |
473 | layoutVertical(move: true); |
474 | } |
475 | |
476 | void QQuickScrollIndicatorAttachedPrivate::itemImplicitHeightChanged(QQuickItem *item) |
477 | { |
478 | if (item == horizontal) |
479 | layoutHorizontal(move: true); |
480 | } |
481 | |
482 | void QQuickScrollIndicatorAttachedPrivate::itemDestroyed(QQuickItem *item) |
483 | { |
484 | if (item == horizontal) |
485 | horizontal = nullptr; |
486 | if (item == vertical) |
487 | vertical = nullptr; |
488 | } |
489 | |
490 | QQuickScrollIndicatorAttached::QQuickScrollIndicatorAttached(QObject *parent) |
491 | : QObject(*(new QQuickScrollIndicatorAttachedPrivate), parent) |
492 | { |
493 | Q_D(QQuickScrollIndicatorAttached); |
494 | d->flickable = qobject_cast<QQuickFlickable *>(object: parent); |
495 | if (d->flickable) |
496 | QQuickItemPrivate::get(item: d->flickable)->updateOrAddGeometryChangeListener(listener: d, types: QQuickGeometryChange::Size); |
497 | else if (parent) |
498 | qmlWarning(me: parent) << "ScrollIndicator must be attached to a Flickable"; |
499 | } |
500 | |
501 | QQuickScrollIndicatorAttached::~QQuickScrollIndicatorAttached() |
502 | { |
503 | Q_D(QQuickScrollIndicatorAttached); |
504 | if (d->flickable) { |
505 | if (d->horizontal) |
506 | QQuickItemPrivate::get(item: d->horizontal)->removeItemChangeListener(d, types: QsiHorizontalChangeTypes); |
507 | if (d->vertical) |
508 | QQuickItemPrivate::get(item: d->vertical)->removeItemChangeListener(d, types: QsiVerticalChangeTypes); |
509 | // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size). |
510 | // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling |
511 | // pointer on destruction. |
512 | QQuickItemPrivate::get(item: d->flickable)->removeItemChangeListener(d, types: QQuickItemPrivate::Geometry); |
513 | } |
514 | } |
515 | |
516 | /*! |
517 | \qmlattachedproperty ScrollIndicator QtQuick.Controls::ScrollIndicator::horizontal |
518 | |
519 | This property attaches a horizontal scroll indicator to a \l Flickable. |
520 | |
521 | \code |
522 | Flickable { |
523 | contentWidth: 2000 |
524 | ScrollIndicator.horizontal: ScrollIndicator { } |
525 | } |
526 | \endcode |
527 | |
528 | \sa {Attaching ScrollIndicator to a Flickable} |
529 | */ |
530 | QQuickScrollIndicator *QQuickScrollIndicatorAttached::horizontal() const |
531 | { |
532 | Q_D(const QQuickScrollIndicatorAttached); |
533 | return d->horizontal; |
534 | } |
535 | |
536 | void QQuickScrollIndicatorAttached::setHorizontal(QQuickScrollIndicator *horizontal) |
537 | { |
538 | Q_D(QQuickScrollIndicatorAttached); |
539 | if (d->horizontal == horizontal) |
540 | return; |
541 | |
542 | if (d->horizontal && d->flickable) { |
543 | QQuickItemPrivate::get(item: d->horizontal)->removeItemChangeListener(d, types: QsiHorizontalChangeTypes); |
544 | QObjectPrivate::disconnect(sender: d->flickable, signal: &QQuickFlickable::movingHorizontallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateHorizontal); |
545 | |
546 | // TODO: export QQuickFlickableVisibleArea |
547 | QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>(); |
548 | disconnect(sender: area, SIGNAL(widthRatioChanged(qreal)), receiver: d->horizontal, SLOT(setSize(qreal))); |
549 | disconnect(sender: area, SIGNAL(xPositionChanged(qreal)), receiver: d->horizontal, SLOT(setPosition(qreal))); |
550 | } |
551 | |
552 | d->horizontal = horizontal; |
553 | |
554 | if (horizontal && d->flickable) { |
555 | if (!horizontal->parentItem()) |
556 | horizontal->setParentItem(d->flickable); |
557 | horizontal->setOrientation(Qt::Horizontal); |
558 | |
559 | QQuickItemPrivate::get(item: horizontal)->addItemChangeListener(listener: d, types: QsiHorizontalChangeTypes); |
560 | QObjectPrivate::connect(sender: d->flickable, signal: &QQuickFlickable::movingHorizontallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateHorizontal); |
561 | |
562 | // TODO: export QQuickFlickableVisibleArea |
563 | QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>(); |
564 | connect(sender: area, SIGNAL(widthRatioChanged(qreal)), receiver: horizontal, SLOT(setSize(qreal))); |
565 | connect(sender: area, SIGNAL(xPositionChanged(qreal)), receiver: horizontal, SLOT(setPosition(qreal))); |
566 | |
567 | d->layoutHorizontal(); |
568 | horizontal->setSize(area->property(name: "widthRatio").toReal()); |
569 | horizontal->setPosition(area->property(name: "xPosition").toReal()); |
570 | } |
571 | emit horizontalChanged(); |
572 | } |
573 | |
574 | /*! |
575 | \qmlattachedproperty ScrollIndicator QtQuick.Controls::ScrollIndicator::vertical |
576 | |
577 | This property attaches a vertical scroll indicator to a \l Flickable. |
578 | |
579 | \code |
580 | Flickable { |
581 | contentHeight: 2000 |
582 | ScrollIndicator.vertical: ScrollIndicator { } |
583 | } |
584 | \endcode |
585 | |
586 | \sa {Attaching ScrollIndicator to a Flickable} |
587 | */ |
588 | QQuickScrollIndicator *QQuickScrollIndicatorAttached::vertical() const |
589 | { |
590 | Q_D(const QQuickScrollIndicatorAttached); |
591 | return d->vertical; |
592 | } |
593 | |
594 | void QQuickScrollIndicatorAttached::setVertical(QQuickScrollIndicator *vertical) |
595 | { |
596 | Q_D(QQuickScrollIndicatorAttached); |
597 | if (d->vertical == vertical) |
598 | return; |
599 | |
600 | if (d->vertical && d->flickable) { |
601 | QQuickItemPrivate::get(item: d->vertical)->removeItemChangeListener(d, types: QsiVerticalChangeTypes); |
602 | QObjectPrivate::disconnect(sender: d->flickable, signal: &QQuickFlickable::movingVerticallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateVertical); |
603 | |
604 | // TODO: export QQuickFlickableVisibleArea |
605 | QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>(); |
606 | disconnect(sender: area, SIGNAL(heightRatioChanged(qreal)), receiver: d->vertical, SLOT(setSize(qreal))); |
607 | disconnect(sender: area, SIGNAL(yPositionChanged(qreal)), receiver: d->vertical, SLOT(setPosition(qreal))); |
608 | } |
609 | |
610 | d->vertical = vertical; |
611 | |
612 | if (vertical && d->flickable) { |
613 | if (!vertical->parentItem()) |
614 | vertical->setParentItem(d->flickable); |
615 | vertical->setOrientation(Qt::Vertical); |
616 | |
617 | QQuickItemPrivate::get(item: vertical)->addItemChangeListener(listener: d, types: QsiVerticalChangeTypes); |
618 | QObjectPrivate::connect(sender: d->flickable, signal: &QQuickFlickable::movingVerticallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateVertical); |
619 | |
620 | // TODO: export QQuickFlickableVisibleArea |
621 | QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>(); |
622 | connect(sender: area, SIGNAL(heightRatioChanged(qreal)), receiver: vertical, SLOT(setSize(qreal))); |
623 | connect(sender: area, SIGNAL(yPositionChanged(qreal)), receiver: vertical, SLOT(setPosition(qreal))); |
624 | |
625 | d->layoutVertical(); |
626 | vertical->setSize(area->property(name: "heightRatio").toReal()); |
627 | vertical->setPosition(area->property(name: "yPosition").toReal()); |
628 | } |
629 | emit verticalChanged(); |
630 | } |
631 | |
632 | #if QT_CONFIG(quicktemplates2_multitouch) |
633 | void QQuickScrollIndicator::touchEvent(QTouchEvent *event) |
634 | { |
635 | event->ignore(); // QTBUG-61785 |
636 | } |
637 | #endif |
638 | |
639 | #if QT_CONFIG(accessibility) |
640 | QAccessible::Role QQuickScrollIndicator::accessibleRole() const |
641 | { |
642 | return QAccessible::Indicator; |
643 | } |
644 | #endif |
645 | |
646 | QT_END_NAMESPACE |
647 | |
648 | #include "moc_qquickscrollindicator_p.cpp" |
649 |
Definitions
- QsiChangeTypes
- QsiHorizontalChangeTypes
- QsiVerticalChangeTypes
- QQuickScrollIndicatorPrivate
- VisualArea
- VisualArea
- visualArea
- visualAreaChange
- resizeContent
- QQuickScrollIndicator
- qmlAttachedProperties
- size
- setSize
- position
- setPosition
- isActive
- setActive
- orientation
- setOrientation
- isHorizontal
- isVertical
- minimumSize
- setMinimumSize
- visualSize
- visualPosition
- QQuickScrollIndicatorAttachedPrivate
- activateHorizontal
- activateVertical
- layoutHorizontal
- layoutVertical
- itemGeometryChanged
- itemImplicitWidthChanged
- itemImplicitHeightChanged
- itemDestroyed
- QQuickScrollIndicatorAttached
- ~QQuickScrollIndicatorAttached
- horizontal
- setHorizontal
- vertical
- setVertical
- touchEvent
Start learning QML with our Intro Training
Find out more