aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2016-07-07 13:11:19 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2016-07-09 05:11:42 +0000
commit7c284809df7e8f1a2adbee1d768a07d13f0403cc (patch)
tree0ace03d4996ef2d3167f94cf36f7f5df6135b4d4 /src
parentcbfa64fd84cab95d909371a5e44146928e403c05 (diff)
Material: implement the ripple effect
Consequently, the controls that were previously using the old Ripple type have now gained hover effects (when hoverEnabled: true). The rest of the Material style controls will be adjusted to use the ripple effect in follow up commits. Task-number: QTBUG-50003 Change-Id: I436f3794411fe75de9ccbe3ecda71029130db613 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/imports/controls/material/CheckIndicator.qml14
-rw-r--r--src/imports/controls/material/RadioIndicator.qml14
-rw-r--r--src/imports/controls/material/Ripple.qml51
-rw-r--r--src/imports/controls/material/SliderHandle.qml11
-rw-r--r--src/imports/controls/material/SwitchIndicator.qml10
-rw-r--r--src/imports/controls/material/material.pri3
-rw-r--r--src/imports/controls/material/qquickmaterialripple.cpp396
-rw-r--r--src/imports/controls/material/qquickmaterialripple_p.h107
-rw-r--r--src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp2
9 files changed, 532 insertions, 76 deletions
diff --git a/src/imports/controls/material/CheckIndicator.qml b/src/imports/controls/material/CheckIndicator.qml
index 224d7dbc..3e765593 100644
--- a/src/imports/controls/material/CheckIndicator.qml
+++ b/src/imports/controls/material/CheckIndicator.qml
@@ -47,7 +47,7 @@ Rectangle {
border.width: control.checked ? width / 2 : 2
radius: 2
- property alias control: ripple.control
+ property Item control
Behavior on border.width {
NumberAnimation {
@@ -64,12 +64,12 @@ Rectangle {
}
Ripple {
- id: ripple
- width: parent.width
- height: width
- control: control
- colored: control.checked
- opacity: control.down || control.visualFocus ? 1 : 0
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: 28; height: 28
+ pressed: control.pressed
+ active: control.down || control.visualFocus || control.hovered
+ color: control.checked ? control.Material.checkBoxCheckedRippleColor : control.Material.checkBoxUncheckedRippleColor
}
// TODO: This needs to be transparent
diff --git a/src/imports/controls/material/RadioIndicator.qml b/src/imports/controls/material/RadioIndicator.qml
index 1cf5829a..304176e4 100644
--- a/src/imports/controls/material/RadioIndicator.qml
+++ b/src/imports/controls/material/RadioIndicator.qml
@@ -46,15 +46,15 @@ Rectangle {
border.color: control.checked || control.down ? control.Material.accentColor : control.Material.secondaryTextColor
color: "transparent"
- property alias control: ripple.control
+ property Item control
Ripple {
- id: ripple
- width: parent.width
- height: width
- control: control
- colored: control.checked
- opacity: control.down || control.visualFocus ? 1 : 0
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: 28; height: 28
+ pressed: control.pressed
+ active: control.down || control.visualFocus || control.hovered
+ color: control.checked ? control.Material.checkBoxCheckedRippleColor : control.Material.checkBoxUncheckedRippleColor
}
Rectangle {
diff --git a/src/imports/controls/material/Ripple.qml b/src/imports/controls/material/Ripple.qml
deleted file mode 100644
index c4209e78..00000000
--- a/src/imports/controls/material/Ripple.qml
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.6
-import QtQuick.Controls.Material 2.1
-
-Rectangle {
- property Item control
- property bool colored: false
-
- radius: width / 2
- scale: 2.5
- color: colored ? control.Material.checkBoxCheckedRippleColor : control.Material.checkBoxUncheckedRippleColor
-
- Behavior on opacity {
- NumberAnimation {}
- }
-}
diff --git a/src/imports/controls/material/SliderHandle.qml b/src/imports/controls/material/SliderHandle.qml
index 149c2c3f..d8f7ef4f 100644
--- a/src/imports/controls/material/SliderHandle.qml
+++ b/src/imports/controls/material/SliderHandle.qml
@@ -66,10 +66,11 @@ Item {
}
Ripple {
- width: parent.width
- height: width
- control: root.control
- colored: true
- opacity: root.handleHasFocus && !root.handlePressed ? 1 : 0
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: 22; height: 22
+ pressed: root.handlePressed
+ active: root.handlePressed || root.handleHasFocus || control.hovered
+ color: control.Material.checkBoxUncheckedRippleColor
}
}
diff --git a/src/imports/controls/material/SwitchIndicator.qml b/src/imports/controls/material/SwitchIndicator.qml
index e5474356..84898270 100644
--- a/src/imports/controls/material/SwitchIndicator.qml
+++ b/src/imports/controls/material/SwitchIndicator.qml
@@ -43,7 +43,7 @@ Item {
implicitWidth: 38
implicitHeight: 32
- property alias control: ripple.control
+ property Item control
Material.elevation: 1
@@ -51,10 +51,10 @@ Item {
id: ripple
x: handle.x + handle.width / 2 - width / 2
y: handle.y + handle.height / 2 - height / 2
- width: handle.width
- height: width
- colored: control.checked
- opacity: control.pressed || control.visualFocus ? 1 : 0
+ width: 28; height: 28
+ pressed: control.pressed
+ active: control.down || control.visualFocus || control.hovered
+ color: control.checked ? control.Material.checkBoxCheckedRippleColor : control.Material.checkBoxUncheckedRippleColor
}
Rectangle {
diff --git a/src/imports/controls/material/material.pri b/src/imports/controls/material/material.pri
index 89d98131..76b865e4 100644
--- a/src/imports/controls/material/material.pri
+++ b/src/imports/controls/material/material.pri
@@ -1,10 +1,12 @@
HEADERS += \
+ $$PWD/qquickmaterialripple_p.h \
$$PWD/qquickmaterialstyle_p.h \
$$PWD/qquickmaterialtheme_p.h \
$$PWD/qquickmaterialprogressring_p.h \
$$PWD/qquickmaterialprogressstrip_p.h
SOURCES += \
+ $$PWD/qquickmaterialripple.cpp \
$$PWD/qquickmaterialstyle.cpp \
$$PWD/qquickmaterialtheme.cpp \
$$PWD/qquickmaterialprogressring.cpp \
@@ -38,7 +40,6 @@ QML_FILES += \
$$PWD/RadioDelegate.qml \
$$PWD/RadioIndicator.qml \
$$PWD/RangeSlider.qml \
- $$PWD/Ripple.qml \
$$PWD/ScrollBar.qml \
$$PWD/ScrollIndicator.qml \
$$PWD/Slider.qml \
diff --git a/src/imports/controls/material/qquickmaterialripple.cpp b/src/imports/controls/material/qquickmaterialripple.cpp
new file mode 100644
index 00000000..1923d554
--- /dev/null
+++ b/src/imports/controls/material/qquickmaterialripple.cpp
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickmaterialripple_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickanimator_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qquickanimatorjob_p.h>
+#include <QtQuick/private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum WavePhase { WaveEnter, WaveExit };
+}
+
+static const int RIPPLE_ENTER_DELAY = 80;
+static const int OPACITY_ENTER_DURATION_FAST = 120;
+static const int WAVE_OPACITY_DECAY_DURATION = 333;
+static const qreal WAVE_TOUCH_UP_ACCELERATION = 3400.0;
+static const qreal WAVE_TOUCH_DOWN_ACCELERATION = 1024.0;
+
+class QQuickMaterialRippleAnimatorJob : public QQuickAnimatorJob
+{
+public:
+ QQuickMaterialRippleAnimatorJob(WavePhase phase, const QPointF &anchor, const QRectF &bounds);
+
+ void initialize(QQuickAnimatorController *controller) override;
+ void updateCurrentTime(int time) override;
+ void writeBack() override;
+ void nodeWasDestroyed() override;
+ void afterNodeSync() override;
+
+private:
+ qreal m_diameter;
+ WavePhase m_phase;
+ QRectF m_bounds;
+ QPointF m_anchor;
+ QSGTransformNode *m_itemNode;
+ QSGOpacityNode *m_opacityNode;
+ QSGInternalRectangleNode *m_rectNode;
+};
+
+QQuickMaterialRippleAnimatorJob::QQuickMaterialRippleAnimatorJob(WavePhase phase, const QPointF &anchor, const QRectF &bounds)
+ : m_diameter(qSqrt(bounds.width() * bounds.width() + bounds.height() * bounds.height())),
+ m_phase(phase),
+ m_bounds(bounds),
+ m_anchor(anchor),
+ m_itemNode(nullptr),
+ m_opacityNode(nullptr),
+ m_rectNode(nullptr)
+{
+}
+
+void QQuickMaterialRippleAnimatorJob::initialize(QQuickAnimatorController *controller)
+{
+ QQuickAnimatorJob::initialize(controller);
+ afterNodeSync();
+}
+
+void QQuickMaterialRippleAnimatorJob::updateCurrentTime(int time)
+{
+ if (!m_itemNode || !m_rectNode || (m_phase == WaveEnter && time < RIPPLE_ENTER_DELAY))
+ return;
+
+ qreal duration = 0;
+ if (m_phase == WaveEnter)
+ duration = QQuickAnimatorJob::duration();
+ else
+ duration = 1000.0 * qSqrt((m_diameter - m_from) / 2.0 / (WAVE_TOUCH_UP_ACCELERATION + WAVE_TOUCH_DOWN_ACCELERATION));
+
+ qreal p = 1.0;
+ if (!qFuzzyIsNull(duration) && time < duration)
+ p = time / duration;
+
+ m_value = m_from + (m_to - m_from) * p;
+ p = m_value / m_diameter;
+
+ const qreal dx = (1.0 - p) * (m_anchor.x() - m_bounds.width() / 2);
+ const qreal dy = (1.0 - p) * (m_anchor.y() - m_bounds.height() / 2);
+
+ m_rectNode->setRect(QRectF(0, 0, m_value, m_value));
+ m_rectNode->setRadius(m_value / 2);
+ m_rectNode->update();
+
+ QMatrix4x4 m;
+ m.translate((m_bounds.width() - m_value) / 2 + dx,
+ (m_bounds.height() - m_value) / 2 + dy);
+ m_itemNode->setMatrix(m);
+
+ if (m_opacityNode) {
+ qreal opacity = 1.0;
+ if (m_phase == WaveExit)
+ opacity -= static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION;
+ m_opacityNode->setOpacity(opacity);
+ }
+}
+
+void QQuickMaterialRippleAnimatorJob::writeBack()
+{
+ if (m_target)
+ m_target->setSize(QSizeF(m_value, m_value));
+ if (m_phase == WaveExit)
+ m_target->deleteLater();
+}
+
+void QQuickMaterialRippleAnimatorJob::nodeWasDestroyed()
+{
+ m_itemNode = nullptr;
+ m_opacityNode = nullptr;
+ m_rectNode = nullptr;
+}
+
+void QQuickMaterialRippleAnimatorJob::afterNodeSync()
+{
+ m_itemNode = QQuickItemPrivate::get(m_target)->itemNode();
+ m_opacityNode = QQuickItemPrivate::get(m_target)->opacityNode();
+ m_rectNode = static_cast<QSGInternalRectangleNode *>(QQuickItemPrivate::get(m_target)->childContainerNode()->firstChild());
+}
+
+class QQuickMaterialRippleAnimator : public QQuickAnimator
+{
+public:
+ QQuickMaterialRippleAnimator(const QPointF &anchor, const QRectF &bounds, QObject *parent = nullptr);
+
+ WavePhase phase() const;
+ void setPhase(WavePhase phase);
+
+protected:
+ QString propertyName() const override;
+ QQuickAnimatorJob *createJob() const override;
+
+private:
+ QPointF m_anchor;
+ QRectF m_bounds;
+ WavePhase m_phase;
+};
+
+QQuickMaterialRippleAnimator::QQuickMaterialRippleAnimator(const QPointF &anchor, const QRectF &bounds, QObject *parent)
+ : QQuickAnimator(parent), m_anchor(anchor), m_bounds(bounds), m_phase(WaveEnter)
+{
+}
+
+WavePhase QQuickMaterialRippleAnimator::phase() const
+{
+ return m_phase;
+}
+
+void QQuickMaterialRippleAnimator::setPhase(WavePhase phase)
+{
+ if (m_phase == phase)
+ return;
+
+ m_phase = phase;
+}
+
+QString QQuickMaterialRippleAnimator::propertyName() const
+{
+ return QString();
+}
+
+QQuickAnimatorJob *QQuickMaterialRippleAnimator::createJob() const
+{
+ return new QQuickMaterialRippleAnimatorJob(m_phase, m_anchor, m_bounds);
+}
+
+QQuickMaterialRipple::QQuickMaterialRipple(QQuickItem *parent)
+ : QQuickItem(parent), m_active(false), m_pressed(false), m_anchored(false), m_clipRadius(0.0), m_opacityAnimator(nullptr)
+{
+ setOpacity(0.0);
+ setFlag(ItemHasContents);
+}
+
+bool QQuickMaterialRipple::isActive() const
+{
+ return m_active;
+}
+
+void QQuickMaterialRipple::setActive(bool active)
+{
+ if (active == m_active)
+ return;
+
+ m_active = active;
+
+ if (!m_opacityAnimator) {
+ m_opacityAnimator = new QQuickOpacityAnimator(this);
+ m_opacityAnimator->setTargetItem(this);
+ }
+ m_opacityAnimator->setDuration(active ? OPACITY_ENTER_DURATION_FAST : WAVE_OPACITY_DECAY_DURATION);
+
+ const int time = m_opacityAnimator->currentTime();
+ m_opacityAnimator->stop();
+ m_opacityAnimator->setFrom(opacity());
+ m_opacityAnimator->setTo(active ? 1.0 : 0.0);
+ m_opacityAnimator->setCurrentTime(time);
+ m_opacityAnimator->start();
+}
+
+QColor QQuickMaterialRipple::color() const
+{
+ return m_color;
+}
+
+void QQuickMaterialRipple::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+
+ m_color = color;
+ update();
+}
+
+qreal QQuickMaterialRipple::clipRadius() const
+{
+ return m_clipRadius;
+}
+
+void QQuickMaterialRipple::setClipRadius(qreal radius)
+{
+ if (qFuzzyCompare(m_clipRadius, radius))
+ return;
+
+ m_clipRadius = radius;
+ setClip(!qFuzzyIsNull(radius));
+ update();
+}
+
+bool QQuickMaterialRipple::isPressed() const
+{
+ return m_pressed;
+}
+
+void QQuickMaterialRipple::setPressed(bool pressed)
+{
+ if (pressed == m_pressed)
+ return;
+
+ m_pressed = pressed;
+
+ if (pressed)
+ enterWave();
+ else
+ exitWave();
+}
+
+QPointF QQuickMaterialRipple::anchor() const
+{
+ const QRectF bounds = boundingRect();
+ const QPointF center = bounds.center();
+ if (!m_anchored)
+ return center;
+
+ // calculate whether the anchor point is within the ripple circle bounds,
+ // that is, whether waves should start expanding from the anchor point
+ const qreal r = qSqrt(bounds.width() * bounds.width() + bounds.height() * bounds.height()) / 2;
+ if (QLineF(center, m_anchor).length() < r)
+ return m_anchor;
+
+ // if the anchor point is outside the ripple circle bounds, start expanding
+ // from the intersection point of the ripple circle and a line from its center
+ // to the the anchor point
+ const qreal p = qAtan2(m_anchor.y() - center.y(), m_anchor.x() - center.x());
+ return QPointF(center.x() + r * qCos(p), center.y() + r * qSin(p));
+}
+
+void QQuickMaterialRipple::setAnchor(const QPointF &anchor)
+{
+ m_anchor = anchor;
+ m_anchored = true;
+}
+
+void QQuickMaterialRipple::itemChange(ItemChange change, const ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+
+ if (change == ItemChildRemovedChange) {
+ QQuickMaterialRippleAnimator *animator = data.item->findChild<QQuickMaterialRippleAnimator *>();
+ if (animator)
+ m_rippleAnimators.removeOne(animator);
+ }
+}
+
+QSGNode *QQuickMaterialRipple::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ QQuickItemPrivate *d = QQuickItemPrivate::get(this);
+ QQuickDefaultClipNode *clipNode = d->clipNode();
+ if (clipNode) {
+ // TODO: QTBUG-51894
+ // clipNode->setRadius(m_clipRadius);
+ clipNode->setRect(boundingRect());
+ clipNode->update();
+ }
+
+ const qreal w = width();
+ const qreal h = height();
+ const qreal sz = qSqrt(w * w + h * h);
+
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(oldNode);
+ if (!transformNode)
+ transformNode = new QSGTransformNode;
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(transformNode->firstChild());
+ if (!rectNode) {
+ rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ transformNode->appendChildNode(rectNode);
+ }
+
+ QMatrix4x4 matrix;
+ if (qFuzzyIsNull(m_clipRadius)) {
+ matrix.translate((w - sz) / 2, (h - sz) / 2);
+ rectNode->setRect(QRectF(0, 0, sz, sz));
+ rectNode->setRadius(sz / 2);
+ } else {
+ rectNode->setRect(QRectF(0, 0, w, h));
+ rectNode->setRadius(m_clipRadius);
+ }
+ transformNode->setMatrix(matrix);
+ rectNode->setColor(m_color);
+ rectNode->update();
+
+ return transformNode;
+}
+
+void QQuickMaterialRipple::enterWave()
+{
+ const qreal w = width();
+ const qreal h = height();
+ const qreal sz = qSqrt(w * w + h * h);
+
+ QQuickRectangle *wave = new QQuickRectangle(this);
+ wave->setPosition(QPointF((w - sz) / 2, (h - sz) / 2));
+ wave->setSize(QSizeF(sz, sz));
+ wave->setRadius(sz / 2);
+ wave->setColor(color());
+ wave->setOpacity(0.0);
+
+ QQuickMaterialRippleAnimator *animator = new QQuickMaterialRippleAnimator(anchor(), boundingRect(), wave);
+ animator->setDuration(qRound(RIPPLE_ENTER_DELAY + 1000.0 * qSqrt(sz / 2.0 / WAVE_TOUCH_DOWN_ACCELERATION)));
+ animator->setTargetItem(wave);
+ animator->setTo(sz);
+ animator->start();
+ m_rippleAnimators += animator;
+}
+
+void QQuickMaterialRipple::exitWave()
+{
+ for (QQuickMaterialRippleAnimator *animator : m_rippleAnimators) {
+ if (animator->phase() == WaveEnter) {
+ animator->stop(); // -> writeBack() -> setSize()
+ if (QQuickItem *wave = animator->targetItem())
+ animator->setFrom(wave->width());
+ animator->setDuration(WAVE_OPACITY_DECAY_DURATION);
+ animator->setPhase(WaveExit);
+ animator->restart();
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/controls/material/qquickmaterialripple_p.h b/src/imports/controls/material/qquickmaterialripple_p.h
new file mode 100644
index 00000000..bff714ea
--- /dev/null
+++ b/src/imports/controls/material/qquickmaterialripple_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKMATERIALRIPPLE_P_H
+#define QQUICKMATERIALRIPPLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/qquickitem.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickOpacityAnimator;
+class QQuickMaterialRippleAnimator;
+
+class QQuickMaterialRipple : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
+ Q_PROPERTY(qreal clipRadius READ clipRadius WRITE setClipRadius FINAL)
+ Q_PROPERTY(bool pressed READ isPressed WRITE setPressed FINAL)
+ Q_PROPERTY(bool active READ isActive WRITE setActive FINAL)
+ Q_PROPERTY(QPointF anchor READ anchor WRITE setAnchor FINAL)
+
+public:
+ QQuickMaterialRipple(QQuickItem *parent = nullptr);
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+ qreal clipRadius() const;
+ void setClipRadius(qreal radius);
+
+ bool isActive() const;
+ void setActive(bool active);
+
+ bool isPressed() const;
+ void setPressed(bool pressed);
+
+ QPointF anchor() const;
+ void setAnchor(const QPointF &anchor);
+
+protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
+
+ void enterWave();
+ void exitWave();
+
+private:
+ bool m_active;
+ bool m_pressed;
+ bool m_anchored;
+ qreal m_clipRadius;
+ QPointF m_anchor;
+ QColor m_color;
+ QQuickOpacityAnimator *m_opacityAnimator;
+ QVector<QQuickMaterialRippleAnimator *> m_rippleAnimators;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickMaterialRipple)
+
+#endif // QQUICKMATERIALRIPPLE_P_H
diff --git a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
index 30c10bc1..8214d5ac 100644
--- a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
+++ b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
@@ -40,6 +40,7 @@
#include "qquickmaterialtheme_p.h"
#include "qquickmaterialprogressring_p.h"
#include "qquickmaterialprogressstrip_p.h"
+#include "qquickmaterialripple_p.h"
#include <QtQuickControls2/private/qquickstyleselector_p.h>
#include <QtQuickControls2/private/qquickpaddedrectangle_p.h>
@@ -89,6 +90,7 @@ void QtQuickControls2MaterialStylePlugin::initializeEngine(QQmlEngine *engine, c
qmlRegisterType<QQuickMaterialProgressRing>(import, 2, 1, "ProgressRing");
qmlRegisterType<QQuickMaterialProgressStrip>(import, 2, 1, "ProgressStrip");
qmlRegisterType<QQuickMaterialRingAnimator>(import, 2, 1, "RingAnimator");
+ qmlRegisterType<QQuickMaterialRipple>(import, 2, 1, "Ripple");
qmlRegisterType<QQuickMaterialStripAnimator>(import, 2, 1, "StripAnimator");
qmlRegisterType(typeUrl(QStringLiteral("BoxShadow.qml")), import, 2, 1, "BoxShadow");
qmlRegisterType(typeUrl(QStringLiteral("CheckIndicator.qml")), import, 2, 1, "CheckIndicator");