aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates/qquickswitch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates/qquickswitch.cpp')
-rw-r--r--src/quicktemplates/qquickswitch.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/quicktemplates/qquickswitch.cpp b/src/quicktemplates/qquickswitch.cpp
new file mode 100644
index 0000000000..1b2473cbdb
--- /dev/null
+++ b/src/quicktemplates/qquickswitch.cpp
@@ -0,0 +1,210 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qquickswitch_p.h"
+#include "qquickabstractbutton_p_p.h"
+
+#include <QtGui/qstylehints.h>
+#include <QtGui/qguiapplication.h>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qquickevents_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Switch
+ \inherits AbstractButton
+//! \instantiates QQuickSwitch
+ \inqmlmodule QtQuick.Controls
+ \since 5.7
+ \ingroup qtquickcontrols-buttons
+ \brief Switch button that can be toggled on or off.
+
+ \image qtquickcontrols-switch.gif
+
+ Switch is an option button that can be dragged or toggled on (checked) or
+ off (unchecked). Switches are typically used to select between two states.
+ For larger sets of options, such as those in a list, consider using
+ \l SwitchDelegate instead.
+
+ Switch inherits its API from \l AbstractButton. For instance, the state
+ of the switch can be set with the \l {AbstractButton::}{checked} property.
+
+ \code
+ ColumnLayout {
+ Switch {
+ text: qsTr("Wi-Fi")
+ }
+ Switch {
+ text: qsTr("Bluetooth")
+ }
+ }
+ \endcode
+
+ \sa {Customizing Switch}, {Button Controls}
+*/
+
+class QQuickSwitchPrivate : public QQuickAbstractButtonPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickSwitch)
+
+public:
+ qreal positionAt(const QPointF &point) const;
+
+ bool canDrag(const QPointF &movePoint) const;
+ bool handleMove(const QPointF &point, ulong timestamp) override;
+ bool handleRelease(const QPointF &point, ulong timestamp) override;
+
+ QPalette defaultPalette() const override { return QQuickTheme::palette(QQuickTheme::Switch); }
+
+ qreal position = 0;
+};
+
+qreal QQuickSwitchPrivate::positionAt(const QPointF &point) const
+{
+ Q_Q(const QQuickSwitch);
+ qreal pos = 0.0;
+ if (indicator)
+ pos = indicator->mapFromItem(q, point).x() / indicator->width();
+ if (q->isMirrored())
+ return 1.0 - pos;
+ return pos;
+}
+
+bool QQuickSwitchPrivate::canDrag(const QPointF &movePoint) const
+{
+ // don't start dragging the handle unless the initial press was at the indicator,
+ // or the drag has reached the indicator area. this prevents unnatural jumps when
+ // dragging far outside the indicator.
+ const qreal pressPos = positionAt(pressPoint);
+ const qreal movePos = positionAt(movePoint);
+ return (pressPos >= 0.0 && pressPos <= 1.0) || (movePos >= 0.0 && movePos <= 1.0);
+}
+
+bool QQuickSwitchPrivate::handleMove(const QPointF &point, ulong timestamp)
+{
+ Q_Q(QQuickSwitch);
+ QQuickAbstractButtonPrivate::handleMove(point, timestamp);
+ if (q->keepMouseGrab() || q->keepTouchGrab())
+ q->setPosition(positionAt(point));
+ return true;
+}
+
+bool QQuickSwitchPrivate::handleRelease(const QPointF &point, ulong timestamp)
+{
+ Q_Q(QQuickSwitch);
+ QQuickAbstractButtonPrivate::handleRelease(point, timestamp);
+ q->setKeepMouseGrab(false);
+ q->setKeepTouchGrab(false);
+ return true;
+}
+
+QQuickSwitch::QQuickSwitch(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickSwitchPrivate), parent)
+{
+ Q_D(QQuickSwitch);
+ d->keepPressed = true;
+ setCheckable(true);
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::Switch::position
+ \readonly
+
+ \input includes/qquickswitch.qdocinc position
+*/
+qreal QQuickSwitch::position() const
+{
+ Q_D(const QQuickSwitch);
+ return d->position;
+}
+
+void QQuickSwitch::setPosition(qreal position)
+{
+ Q_D(QQuickSwitch);
+ position = qBound<qreal>(0.0, position, 1.0);
+ if (qFuzzyCompare(d->position, position))
+ return;
+
+ d->position = position;
+ emit positionChanged();
+ emit visualPositionChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::Switch::visualPosition
+ \readonly
+
+ \input includes/qquickswitch.qdocinc visualPosition
+*/
+qreal QQuickSwitch::visualPosition() const
+{
+ Q_D(const QQuickSwitch);
+ if (isMirrored())
+ return 1.0 - d->position;
+ return d->position;
+}
+
+void QQuickSwitch::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickSwitch);
+ if (!keepMouseGrab()) {
+ const QPointF movePoint = event->position();
+ if (d->canDrag(movePoint))
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(movePoint.x() - d->pressPoint.x(), Qt::XAxis, event));
+ }
+ QQuickAbstractButton::mouseMoveEvent(event);
+}
+
+#if QT_CONFIG(quicktemplates2_multitouch)
+void QQuickSwitch::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickSwitch);
+ if (!keepTouchGrab() && event->type() == QEvent::TouchUpdate) {
+ for (const QTouchEvent::TouchPoint &point : event->points()) {
+ if (point.id() != d->touchId || point.state() != QEventPoint::Updated)
+ continue;
+ if (d->canDrag(point.position()))
+ setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.position().x() - d->pressPoint.x(), Qt::XAxis, &point));
+ }
+ }
+ QQuickAbstractButton::touchEvent(event);
+}
+#endif
+
+void QQuickSwitch::mirrorChange()
+{
+ QQuickAbstractButton::mirrorChange();
+ emit visualPositionChanged();
+}
+
+void QQuickSwitch::nextCheckState()
+{
+ Q_D(QQuickSwitch);
+ if (keepMouseGrab() || keepTouchGrab()) {
+ d->toggle(d->position > 0.5);
+ // the checked state might not change => force a position update to
+ // avoid that the handle is left somewhere in the middle (QTBUG-57944)
+ setPosition(d->checked ? 1.0 : 0.0);
+ } else {
+ QQuickAbstractButton::nextCheckState();
+ }
+}
+
+void QQuickSwitch::buttonChange(ButtonChange change)
+{
+ Q_D(QQuickSwitch);
+ if (change == ButtonCheckedChange)
+ setPosition(d->checked ? 1.0 : 0.0);
+ else
+ QQuickAbstractButton::buttonChange(change);
+}
+
+QFont QQuickSwitch::defaultFont() const
+{
+ return QQuickTheme::font(QQuickTheme::Switch);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickswitch_p.cpp"