7#include <QtCore/qmath.h>
8#include <QtQuick/private/qquickitem_p.h>
9#include <QtQuick/private/qsgadaptationlayer_p.h>
10#include <QtQuickControls2Impl/private/qquickanimatednode_p.h>
11#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
12#include <QtQuickTemplates2/private/qquickabstractbutton_p_p.h>
30 void sync(QQuickItem *item)
override;
33 void updateWaveNode();
44 qreal m_opacity = -1.0;
45 qreal m_newOpacity = 1.0;
51 start(qRound(1000.0 * qSqrt(ripple->diameter() / 2.0 / WAVE_TOUCH_DOWN_ACCELERATION)));
53 QSGOpacityNode *opacityNode =
new QSGOpacityNode;
54 appendChildNode(opacityNode);
56 QQuickItemPrivate *d = QQuickItemPrivate::get(ripple);
57 QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
58 rectNode->setAntialiasing(
true);
59 opacityNode->appendChildNode(rectNode);
61 auto window = ripple->window();
62 connect(window, &QQuickWindow::beforeFrameBegin,
this, &QQuickMaterialRippleWaveNode::updateWaveNode, Qt::DirectConnection);
71 connect(
this, &QQuickAnimatedNode::stopped,
this, &QObject::deleteLater);
78 p = time /
static_cast<qreal>(duration());
80 m_newValue = m_from + (m_to - m_from) * p;
82 if (m_phase == WaveExit)
83 m_newOpacity = 1.0 -
static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION;
88 QQuickMaterialRipple *ripple =
static_cast<QQuickMaterialRipple *>(item);
89 m_to = ripple->diameter();
90 m_anchor = ripple->anchorPoint();
91 m_bounds = ripple->boundingRect();
93 QSGOpacityNode *opacityNode =
static_cast<QSGOpacityNode *>(firstChild());
94 Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
96 QSGInternalRectangleNode *rectNode =
static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
97 Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
98 rectNode->setColor(ripple->color());
103 QSGOpacityNode *opacityNode =
static_cast<QSGOpacityNode *>(firstChild());
104 Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
105 if (!qFuzzyCompare(m_opacity, m_newOpacity)) {
106 m_opacity = m_newOpacity;
107 opacityNode->setOpacity(m_opacity);
110 if (qFuzzyCompare(m_value, m_newValue))
113 m_value = m_newValue;
115 qreal p = m_value / m_to;
117 const qreal dx = (1.0 - p) * (m_anchor.x() - m_bounds.width() / 2);
118 const qreal dy = (1.0 - p) * (m_anchor.y() - m_bounds.height() / 2);
121 m.translate(qRound((m_bounds.width() - m_value) / 2 + dx),
122 qRound((m_bounds.height() - m_value) / 2 + dy));
125 QSGInternalRectangleNode *rectNode =
static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
126 Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
127 rectNode->setRect(QRectF(0, 0, m_value, m_value));
128 rectNode->setRadius(m_value / 2);
140 void sync(QQuickItem *item)
override;
143 void updateBackgroundNode();
145 bool m_active =
false;
147 qreal m_opacity = -1.0;
148 qreal m_newOpacity = 0.0;
152 : QQuickAnimatedNode(ripple)
156 QSGOpacityNode *opacityNode =
new QSGOpacityNode;
157 appendChildNode(opacityNode);
159 QQuickItemPrivate *d = QQuickItemPrivate::get(ripple);
160 QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
161 rectNode->setAntialiasing(
true);
162 opacityNode->appendChildNode(rectNode);
164 auto window = ripple->window();
165 connect(window, &QQuickWindow::beforeFrameBegin,
this, &QQuickMaterialRippleBackgroundNode::updateBackgroundNode, Qt::DirectConnection);
170 qreal opacity = time /
static_cast<qreal>(duration());
172 opacity = 1.0 - opacity;
174 QSGOpacityNode *opacityNode =
static_cast<QSGOpacityNode *>(firstChild());
175 Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
176 m_newOpacity = opacity;
181 QQuickMaterialRipple *ripple =
static_cast<QQuickMaterialRipple *>(item);
182 if (m_active != ripple->isActive()) {
183 m_active = ripple->isActive();
188 QSGOpacityNode *opacityNode =
static_cast<QSGOpacityNode *>(firstChild());
189 Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
191 QSGInternalRectangleNode *rectNode =
static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
192 Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
194 const qreal w = ripple->width();
195 const qreal h = ripple->height();
196 const qreal sz = qSqrt(w * w + h * h);
199 if (qFuzzyIsNull(ripple->clipRadius())) {
200 matrix.translate(qRound((w - sz) / 2), qRound((h - sz) / 2));
201 rectNode->setRect(QRectF(0, 0, sz, sz));
202 rectNode->setRadius(sz / 2);
204 rectNode->setRect(QRectF(0, 0, w, h));
205 rectNode->setRadius(ripple->clipRadius());
209 rectNode->setColor(ripple->color());
215 if (m_opacity == m_newOpacity)
218 m_opacity = m_newOpacity;
219 QSGOpacityNode *opacityNode =
static_cast<QSGOpacityNode *>(firstChild());
220 Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
221 opacityNode->setOpacity(m_opacity);
224QQuickMaterialRipple::QQuickMaterialRipple(QQuickItem *parent)
227 setFlag(ItemHasContents);
230bool QQuickMaterialRipple::isActive()
const
235void QQuickMaterialRipple::setActive(
bool active)
237 if (active == m_active)
244QColor QQuickMaterialRipple::color()
const
249void QQuickMaterialRipple::setColor(
const QColor &color)
251 if (m_color == color)
258qreal QQuickMaterialRipple::clipRadius()
const
263void QQuickMaterialRipple::setClipRadius(qreal radius)
265 if (qFuzzyCompare(m_clipRadius, radius))
268 m_clipRadius = radius;
272bool QQuickMaterialRipple::isPressed()
const
277void QQuickMaterialRipple::setPressed(
bool pressed)
279 if (pressed == m_pressed)
290 if (m_trigger == Press)
295 if (m_trigger == Release)
302QQuickMaterialRipple::Trigger QQuickMaterialRipple::trigger()
const
307void QQuickMaterialRipple::setTrigger(Trigger trigger)
312QPointF QQuickMaterialRipple::anchorPoint()
const
314 const QRectF bounds = boundingRect();
315 const QPointF center = bounds.center();
319 QPointF anchorPoint = bounds.center();
320 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(m_anchor))
321 anchorPoint = QQuickAbstractButtonPrivate::get(button)->pressPoint;
322 anchorPoint = mapFromItem(m_anchor, anchorPoint);
326 const qreal r = qSqrt(bounds.width() * bounds.width() + bounds.height() * bounds.height()) / 2;
327 if (QLineF(center, anchorPoint).length() < r)
333 const qreal p = qAtan2(anchorPoint.y() - center.y(), anchorPoint.x() - center.x());
334 return QPointF(center.x() + r * qCos(p), center.y() + r * qSin(p));
337QQuickItem *QQuickMaterialRipple::anchor()
const
342void QQuickMaterialRipple::setAnchor(QQuickItem *item)
347qreal QQuickMaterialRipple::diameter()
const
349 const qreal w = width();
350 const qreal h = height();
351 return qSqrt(w * w + h * h);
354void QQuickMaterialRipple::itemChange(ItemChange change,
const ItemChangeData &data)
356 QQuickItem::itemChange(change, data);
359QSGNode *QQuickMaterialRipple::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
361 QQuickItemPrivate *d = QQuickItemPrivate::get(
this);
362 QQuickDefaultClipNode *clipNode = d->clipNode();
364 clipNode->setRadius(m_clipRadius);
365 clipNode->setRect(boundingRect());
369 QSGNode *container = oldNode;
371 container =
new QSGNode;
374 if (!backgroundNode) {
375 backgroundNode =
new QQuickMaterialRippleBackgroundNode(
this);
376 backgroundNode->setObjectName(objectName());
377 container->appendChildNode(backgroundNode);
379 backgroundNode->sync(
this);
387 container->appendChildNode(enterNode);
389 enterNode->sync(
this);
394 int j = container->childCount() - 1 - m_waves;
399 exitNode->sync(
this);
406void QQuickMaterialRipple::timerEvent(QTimerEvent *event)
408 QQuickItem::timerEvent(event);
410 if (event->timerId() == m_enterDelay)
414void QQuickMaterialRipple::prepareWave()
416 if (m_enterDelay <= 0)
420void QQuickMaterialRipple::enterWave()
422 if (m_enterDelay > 0) {
423 killTimer(m_enterDelay);
431void QQuickMaterialRipple::exitWave()
433 if (m_enterDelay > 0) {
434 killTimer(m_enterDelay);
446#include "moc_qquickmaterialripple_p.cpp"
448#include "qquickmaterialripple.moc"
void updateCurrentTime(int time) override
void sync(QQuickItem *item) override
void updateCurrentTime(int time) override
void sync(QQuickItem *item) override
QQuickMaterialRippleWaveNode(QQuickMaterialRipple *ripple)
Combined button and popup list for selecting options.
static const int WAVE_OPACITY_DECAY_DURATION
static const int RIPPLE_ENTER_DELAY
static const int OPACITY_ENTER_DURATION_FAST
static const qreal WAVE_TOUCH_DOWN_ACCELERATION