/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Quick Templates 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 "qquickswipedelegate_p.h"
#include "qquickswipedelegate_p_p.h"
#include "qquickcontrol_p_p.h"
#include "qquickitemdelegate_p_p.h"
#include "qquickvelocitycalculator_p_p.h"

#include <QtGui/qstylehints.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/qqmlinfo.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtQuick/private/qquicktransition_p.h>
#include <QtQuick/private/qquicktransitionmanager_p_p.h>

QT_BEGIN_NAMESPACE

/*!
    \qmltype SwipeDelegate
    \inherits ItemDelegate
//!     \instantiates QQuickSwipeDelegate
    \inqmlmodule QtQuick.Controls
    \since 5.7
    \ingroup qtquickcontrols2-delegates
    \brief Swipable item delegate.

    SwipeDelegate presents a view item that can be swiped left or right to
    expose more options or information. It is used as a delegate in views such
    as \l ListView.

    In the following example, SwipeDelegate is used in a \l ListView to allow
    items to be removed from it by swiping to the left:

    \snippet qtquickcontrols2-swipedelegate.qml 1

    SwipeDelegate inherits its API from \l ItemDelegate, which is inherited
    from AbstractButton. For instance, you can set \l {AbstractButton::text}{text},
    and react to \l {AbstractButton::clicked}{clicks} using the AbstractButton
    API.

    Information regarding the progress of a swipe, as well as the components
    that should be shown upon swiping, are both available through the
    \l {SwipeDelegate::}{swipe} grouped property object. For example,
    \c swipe.position holds the position of the
    swipe within the range \c -1.0 to \c 1.0. The \c swipe.left
    property determines which item will be displayed when the control is swiped
    to the right, and vice versa for \c swipe.right. The positioning of these
    components is left to applications to decide. For example, without specifying
    any position for \c swipe.left or \c swipe.right, the following will
    occur:

    \image qtquickcontrols2-swipedelegate.gif

    If \c swipe.left and \c swipe.right are anchored to the left and
    right of the \l {Control::}{background} item (respectively), they'll behave like this:

    \image qtquickcontrols2-swipedelegate-leading-trailing.gif

    When using \c swipe.left and \c swipe.right, the control cannot be
    swiped past the left and right edges. To achieve this type of "wrapping"
    behavior, set \c swipe.behind instead. This will result in the same
    item being shown regardless of which direction the control is swiped. For
    example, in the image below, we set \c swipe.behind and then swipe the
    control repeatedly in both directions:

    \image qtquickcontrols2-swipedelegate-behind.gif

    \sa {Customizing SwipeDelegate}, {Delegate Controls}, {Qt Quick Controls 2 - Swipe to Remove}{Swipe to Remove Example}
*/

namespace {
    typedef QQuickSwipeDelegateAttached Attached;

    Attached *attachedObject(QQuickItem *item) {
        return qobject_cast<Attached*>(qmlAttachedPropertiesObject<QQuickSwipeDelegate>(item, false));
    }

    enum PositionAnimation {
        DontAnimatePosition,
        AnimatePosition
    };
}

class QQuickSwipeTransitionManager : public QQuickTransitionManager
{
public:
    QQuickSwipeTransitionManager(QQuickSwipe *swipe);

    void transition(QQuickTransition *transition, qreal position);

protected:
    void finished() override;

private:
    QQuickSwipe *m_swipe = nullptr;
};

class QQuickSwipePrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QQuickSwipe)

public:
    QQuickSwipePrivate(QQuickSwipeDelegate *control) : control(control) { }

    static QQuickSwipePrivate *get(QQuickSwipe *swipe);

    QQuickItem *createDelegateItem(QQmlComponent *component);
    QQuickItem *showRelevantItemForPosition(qreal position);
    QQuickItem *createRelevantItemForDistance(qreal distance);
    void reposition(PositionAnimation animationPolicy);
    void createLeftItem();
    void createBehindItem();
    void createRightItem();
    void createAndShowLeftItem();
    void createAndShowBehindItem();
    void createAndShowRightItem();

    void warnAboutMixingDelegates();
    void warnAboutSettingDelegatesWhileVisible();

    bool hasDelegates() const;

    bool isTransitioning() const;
    void beginTransition(qreal position);
    void finishTransition();

    QQuickSwipeDelegate *control = nullptr;
    // Same range as position, but is set before press events so that we can
    // keep track of which direction the user must swipe when using left and right delegates.
    qreal positionBeforePress = 0;
    qreal position = 0;
    // A "less strict" version of complete that is true if complete was true
    // before the last press event.
    bool wasComplete = false;
    bool complete = false;
    bool enabled = true;
    QQuickVelocityCalculator velocityCalculator;
    QQmlComponent *left = nullptr;
    QQmlComponent *behind = nullptr;
    QQmlComponent *right = nullptr;
    QQuickItem *leftItem = nullptr;
    QQuickItem *behindItem = nullptr;
    QQuickItem *rightItem = nullptr;
    QQuickTransition *transition = nullptr;
    QScopedPointer<QQuickSwipeTransitionManager> transitionManager;
};

QQuickSwipeTransitionManager::QQuickSwipeTransitionManager(QQuickSwipe *swipe)
    : m_swipe(swipe)
{
}

void QQuickSwipeTransitionManager::transition(QQuickTransition *transition, qreal position)
{
    qmlExecuteDeferred(transition);

    QQmlProperty defaultTarget(m_swipe, QLatin1String("position"));
    QQmlListProperty<QQuickAbstractAnimation> animations = transition->animations();
    const int count = animations.count(&animations);
    for (int i = 0; i < count; ++i) {
        QQuickAbstractAnimation *anim = animations.at(&animations, i);
        anim->setDefaultTarget(defaultTarget);
    }

    QList<QQuickStateAction> actions;
    actions << QQuickStateAction(m_swipe, QLatin1String("position"), position);
    QQuickTransitionManager::transition(actions, transition, m_swipe);
}

void QQuickSwipeTransitionManager::finished()
{
    QQuickSwipePrivate::get(m_swipe)->finishTransition();
}

QQuickSwipePrivate *QQuickSwipePrivate::get(QQuickSwipe *swipe)
{
    return swipe->d_func();
}

QQuickItem *QQuickSwipePrivate::createDelegateItem(QQmlComponent *component)
{
    // If we don't use the correct context, it won't be possible to refer to
    // the control's id from within the delegates.
    QQmlContext *creationContext = component->creationContext();
    // The component might not have been created in QML, in which case
    // the creation context will be null and we have to create it ourselves.
    if (!creationContext)
        creationContext = qmlContext(control);
    QQmlContext *context = new QQmlContext(creationContext, control);
    context->setContextObject(control);
    QQuickItem *item = qobject_cast<QQuickItem*>(component->beginCreate(context));
    if (item) {
        item->setParentItem(control);
        component->completeCreate();
    }
    return item;
}

QQuickItem *QQuickSwipePrivate::showRelevantItemForPosition(qreal position)
{
    if (qFuzzyIsNull(position))
        return nullptr;

    if (behind) {
        createAndShowBehindItem();
        return behindItem;
    }

    if (right && position < 0.0) {
        createAndShowRightItem();
        return rightItem;
    }

    if (left && position > 0.0) {
        createAndShowLeftItem();
        return leftItem;
    }

    return nullptr;
}

QQuickItem *QQuickSwipePrivate::createRelevantItemForDistance(qreal distance)
{
    if (qFuzzyIsNull(distance))
        return nullptr;

    if (behind) {
        createBehindItem();
        return behindItem;
    }

    // a) If the position before the press was 0.0, we know that *any* movement
    // whose distance is negative will result in the right item being shown and
    // vice versa.
    // b) Once the control has been exposed (that is, swiped to the left or right,
    // and hence the position is either -1.0 or 1.0), we must use the width of the
    // relevant item to determine if the distance is larger than that item,
    // in order to know whether or not to display it.
    // c) If the control has been exposed, and the swipe is larger than the width
    // of the relevant item from which the swipe started from, we must show the
    // item on the other side (if any).

    if (right) {
        if ((distance < 0.0 && positionBeforePress == 0.0) /* a) */
            || (rightItem && positionBeforePress == -1.0 && distance < rightItem->width()) /* b) */
            || (leftItem && positionBeforePress == 1.0 && qAbs(distance) > leftItem->width())) /* c) */ {
            createRightItem();
            return rightItem;
        }
    }

    if (left) {
        if ((distance > 0.0 && positionBeforePress == 0.0) /* a) */
            || (leftItem && positionBeforePress == 1.0 && qAbs(distance) < leftItem->width()) /* b) */
            || (rightItem && positionBeforePress == -1.0 && qAbs(distance) > rightItem->width())) /* c) */ {
            createLeftItem();
            return leftItem;
        }
    }

    return nullptr;
}

void QQuickSwipePrivate::reposition(PositionAnimation animationPolicy)
{
    QQuickItem *relevantItem = showRelevantItemForPosition(position);
    const qreal relevantWidth = relevantItem ? relevantItem->width() : 0.0;
    const qreal contentItemX = position * relevantWidth + control->leftPadding();

    // "Behavior on x" relies on the property system to know when it should update,
    // so we can prevent it from animating by setting the x position directly.
    if (animationPolicy == AnimatePosition) {
        if (QQuickItem *contentItem = control->contentItem())
            contentItem->setProperty("x", contentItemX);
        if (QQuickItem *background = control->background())
            background->setProperty("x", position * relevantWidth);
    } else {
        if (QQuickItem *contentItem = control->contentItem())
            contentItem->setX(contentItemX);
        if (QQuickItem *background = control->background())
            background->setX(position * relevantWidth);
    }
}

void QQuickSwipePrivate::createLeftItem()
{
    if (!leftItem) {
        Q_Q(QQuickSwipe);
        q->setLeftItem(createDelegateItem(left));
        if (!leftItem)
            qmlWarning(control) << "Failed to create left item:" << left->errors();
    }
}

void QQuickSwipePrivate::createBehindItem()
{
    if (!behindItem) {
        Q_Q(QQuickSwipe);
        q->setBehindItem(createDelegateItem(behind));
        if (!behindItem)
            qmlWarning(control) << "Failed to create behind item:" << behind->errors();
    }
}

void QQuickSwipePrivate::createRightItem()
{
    if (!rightItem) {
        Q_Q(QQuickSwipe);
        q->setRightItem(createDelegateItem(right));
        if (!rightItem)
            qmlWarning(control) << "Failed to create right item:" << right->errors();
    }
}

void QQuickSwipePrivate::createAndShowLeftItem()
{
    createLeftItem();

    if (leftItem)
        leftItem->setVisible(true);

    if (rightItem)
        rightItem->setVisible(false);
}

void QQuickSwipePrivate::createAndShowBehindItem()
{
    createBehindItem();

    if (behindItem)
        behindItem->setVisible(true);
}

void QQuickSwipePrivate::createAndShowRightItem()
{
    createRightItem();

    // This item may have already existed but was hidden.
    if (rightItem)
        rightItem->setVisible(true);

    // The left item isn't visible when the right item is visible, so save rendering effort by hiding it.
    if (leftItem)
        leftItem->setVisible(false);
}

void QQuickSwipePrivate::warnAboutMixingDelegates()
{
    qmlWarning(control) << "cannot set both behind and left/right properties";
}

void QQuickSwipePrivate::warnAboutSettingDelegatesWhileVisible()
{
    qmlWarning(control) << "left/right/behind properties may only be set when swipe.position is 0";
}

bool QQuickSwipePrivate::hasDelegates() const
{
    return left || right || behind;
}

bool QQuickSwipePrivate::isTransitioning() const
{
    return transitionManager && transitionManager->isRunning();
}

void QQuickSwipePrivate::beginTransition(qreal newPosition)
{
    Q_Q(QQuickSwipe);
    if (!transition) {
        q->setPosition(newPosition);
        finishTransition();
        return;
    }

    if (!transitionManager)
        transitionManager.reset(new QQuickSwipeTransitionManager(q));

    transitionManager->transition(transition, newPosition);
}

void QQuickSwipePrivate::finishTransition()
{
    Q_Q(QQuickSwipe);
    q->setComplete(qFuzzyCompare(qAbs(position), qreal(1.0)));
    if (complete)
        emit q->opened();
    else
        emit q->closed();
}

QQuickSwipe::QQuickSwipe(QQuickSwipeDelegate *control)
    : QObject(*(new QQuickSwipePrivate(control)))
{
}

QQmlComponent *QQuickSwipe::left() const
{
    Q_D(const QQuickSwipe);
    return d->left;
}

void QQuickSwipe::setLeft(QQmlComponent *left)
{
    Q_D(QQuickSwipe);
    if (left == d->left)
        return;

    if (d->behind) {
        d->warnAboutMixingDelegates();
        return;
    }

    if (!qFuzzyIsNull(d->position)) {
        d->warnAboutSettingDelegatesWhileVisible();
        return;
    }

    d->left = left;

    if (!d->left) {
        delete d->leftItem;
        d->leftItem = nullptr;
    }

    d->control->setFiltersChildMouseEvents(d->hasDelegates());

    emit leftChanged();
}

QQmlComponent *QQuickSwipe::behind() const
{
    Q_D(const QQuickSwipe);
    return d->behind;
}

void QQuickSwipe::setBehind(QQmlComponent *behind)
{
    Q_D(QQuickSwipe);
    if (behind == d->behind)
        return;

    if (d->left || d->right) {
        d->warnAboutMixingDelegates();
        return;
    }

    if (!qFuzzyIsNull(d->position)) {
        d->warnAboutSettingDelegatesWhileVisible();
        return;
    }

    d->behind = behind;

    if (!d->behind) {
        delete d->behindItem;
        d->behindItem = nullptr;
    }

    d->control->setFiltersChildMouseEvents(d->hasDelegates());

    emit behindChanged();
}

QQmlComponent *QQuickSwipe::right() const
{
    Q_D(const QQuickSwipe);
    return d->right;
}

void QQuickSwipe::setRight(QQmlComponent *right)
{
    Q_D(QQuickSwipe);
    if (right == d->right)
        return;

    if (d->behind) {
        d->warnAboutMixingDelegates();
        return;
    }

    if (!qFuzzyIsNull(d->position)) {
        d->warnAboutSettingDelegatesWhileVisible();
        return;
    }

    d->right = right;

    if (!d->right) {
        delete d->rightItem;
        d->rightItem = nullptr;
    }

    d->control->setFiltersChildMouseEvents(d->hasDelegates());

    emit rightChanged();
}

QQuickItem *QQuickSwipe::leftItem() const
{
    Q_D(const QQuickSwipe);
    return d->leftItem;
}

void QQuickSwipe::setLeftItem(QQuickItem *item)
{
    Q_D(QQuickSwipe);
    if (item == d->leftItem)
        return;

    delete d->leftItem;
    d->leftItem = item;

    if (d->leftItem) {
        d->leftItem->setParentItem(d->control);

        if (qFuzzyIsNull(d->leftItem->z()))
            d->leftItem->setZ(-2);
    }

    emit leftItemChanged();
}

QQuickItem *QQuickSwipe::behindItem() const
{
    Q_D(const QQuickSwipe);
    return d->behindItem;
}

void QQuickSwipe::setBehindItem(QQuickItem *item)
{
    Q_D(QQuickSwipe);
    if (item == d->behindItem)
        return;

    delete d->behindItem;
    d->behindItem = item;

    if (d->behindItem) {
        d->behindItem->setParentItem(d->control);

        if (qFuzzyIsNull(d->behindItem->z()))
            d->behindItem->setZ(-2);
    }

    emit behindItemChanged();
}

QQuickItem *QQuickSwipe::rightItem() const
{
    Q_D(const QQuickSwipe);
    return d->rightItem;
}

void QQuickSwipe::setRightItem(QQuickItem *item)
{
    Q_D(QQuickSwipe);
    if (item == d->rightItem)
        return;

    delete d->rightItem;
    d->rightItem = item;

    if (d->rightItem) {
        d->rightItem->setParentItem(d->control);

        if (qFuzzyIsNull(d->rightItem->z()))
            d->rightItem->setZ(-2);
    }

    emit rightItemChanged();
}

qreal QQuickSwipe::position() const
{
    Q_D(const QQuickSwipe);
    return d->position;
}

void QQuickSwipe::setPosition(qreal position)
{
    Q_D(QQuickSwipe);
    const qreal adjustedPosition = qBound<qreal>(-1.0, position, 1.0);
    if (adjustedPosition == d->position)
        return;

    d->position = adjustedPosition;
    d->reposition(AnimatePosition);
    emit positionChanged();
}

bool QQuickSwipe::isComplete() const
{
    Q_D(const QQuickSwipe);
    return d->complete;
}

void QQuickSwipe::setComplete(bool complete)
{
    Q_D(QQuickSwipe);
    if (complete == d->complete)
        return;

    d->complete = complete;
    emit completeChanged();
    if (d->complete)
        emit completed();
}

bool QQuickSwipe::isEnabled() const
{
    Q_D(const QQuickSwipe);
    return d->enabled;
}

void QQuickSwipe::setEnabled(bool enabled)
{
    Q_D(QQuickSwipe);
    if (enabled == d->enabled)
        return;

    d->enabled = enabled;
    emit enabledChanged();
}

QQuickTransition *QQuickSwipe::transition() const
{
    Q_D(const QQuickSwipe);
    return d->transition;
}

void QQuickSwipe::setTransition(QQuickTransition *transition)
{
    Q_D(QQuickSwipe);
    if (transition == d->transition)
        return;

    d->transition = transition;
    emit transitionChanged();
}

void QQuickSwipe::open(QQuickSwipeDelegate::Side side)
{
    Q_D(QQuickSwipe);
    if (qFuzzyCompare(qAbs(d->position), qreal(1.0)))
        return;

    if ((side != QQuickSwipeDelegate::Left && side != QQuickSwipeDelegate::Right)
            || (!d->left && !d->behind && side == QQuickSwipeDelegate::Left)
            || (!d->right && !d->behind && side == QQuickSwipeDelegate::Right))
        return;

    d->beginTransition(side);
    d->wasComplete = true;
    d->velocityCalculator.reset();
    d->positionBeforePress = d->position;
}

void QQuickSwipe::close()
{
    Q_D(QQuickSwipe);
    if (qFuzzyIsNull(d->position))
        return;

    d->beginTransition(0.0);
    d->wasComplete = false;
    d->positionBeforePress = 0.0;
    d->velocityCalculator.reset();
}

QQuickSwipeDelegatePrivate::QQuickSwipeDelegatePrivate(QQuickSwipeDelegate *control)
    : swipe(control)
{
}

bool QQuickSwipeDelegatePrivate::handleMousePressEvent(QQuickItem *item, QMouseEvent *event)
{
    Q_Q(QQuickSwipeDelegate);
    QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe);
    // If the position is 0, we want to handle events ourselves - we don't want child items to steal them.
    // This code will only get called when a child item has been created;
    // events will go through the regular channels (mousePressEvent()) until then.
    if (qFuzzyIsNull(swipePrivate->position)) {
        q->mousePressEvent(event);
        // The press point could be incorrect if the press happened over a child item,
        // so we correct it after calling the base class' mousePressEvent(), rather
        // than having to duplicate its code just so we can set the pressPoint.
        setPressPoint(item->mapToItem(q, event->pos()));
        return true;
    }

    // The position is non-zero, this press could be either for a delegate or the control itself
    // (the control can be clicked to e.g. close the swipe). Either way, we must begin measuring
    // mouse movement in case it turns into a swipe, in which case we grab the mouse.
    swipePrivate->positionBeforePress = swipePrivate->position;
    swipePrivate->velocityCalculator.startMeasuring(event->pos(), event->timestamp());
    setPressPoint(item->mapToItem(q, event->pos()));

    // When a delegate uses the attached properties and signals, it declares that it wants mouse events.
    Attached *attached = attachedObject(item);
    if (attached) {
        attached->setPressed(true);
        // Stop the event from propagating, as QQuickItem explicitly ignores events.
        event->accept();
        return true;
    }

    return false;
}

bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEvent *event)
{
    Q_Q(QQuickSwipeDelegate);

    if (holdTimer > 0) {
        if (QLineF(pressPoint, event->localPos()).length() > QGuiApplication::styleHints()->startDragDistance())
            stopPressAndHold();
    }

    // The delegate can still be pressed when swipe.enabled is false,
    // but the mouse moving shouldn't have any effect on swipe.position.
    QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe);
    if (!swipePrivate->enabled)
        return false;

    // Protect against division by zero.
    if (width == 0)
        return false;

    // Don't bother reacting to events if we don't have any delegates.
    if (!swipePrivate->left && !swipePrivate->right && !swipePrivate->behind)
        return false;

    // Don't handle move events for the control if it wasn't pressed.
    if (item == q && !pressed)
        return false;

    const QPointF mappedEventPos = item->mapToItem(q, event->pos());
    const qreal distance = (mappedEventPos - pressPoint).x();
    if (!q->keepMouseGrab()) {
        // Taken from QQuickDrawerPrivate::grabMouse; see comments there.
        int threshold = qMax(20, QGuiApplication::styleHints()->startDragDistance() + 5);
        const bool overThreshold = QQuickWindowPrivate::dragOverThreshold(distance, Qt::XAxis, event, threshold);
        if (window && overThreshold) {
            QQuickItem *grabber = q->window()->mouseGrabberItem();
            if (!grabber || !grabber->keepMouseGrab()) {
                q->grabMouse();
                q->setKeepMouseGrab(true);
                q->setPressed(true);
                swipe.setComplete(false);

                if (Attached *attached = attachedObject(item))
                    attached->setPressed(false);
            }
        }
    }

    if (q->keepMouseGrab()) {
        // Ensure we don't try to calculate a position when the user tried to drag
        // to the left when the left item is already exposed, and vice versa.
        // The code below assumes that the drag is valid, so if we don't have this check,
        // the wrong items are visible and the swiping wraps.
        if (swipePrivate->behind
            || ((swipePrivate->left || swipePrivate->right)
                && (qFuzzyIsNull(swipePrivate->positionBeforePress)
                    || (swipePrivate->positionBeforePress == -1.0 && distance >= 0.0)
                    || (swipePrivate->positionBeforePress == 1.0 && distance <= 0.0)))) {

            // We must instantiate the items here so that we can calculate the
            // position against the width of the relevant item.
            QQuickItem *relevantItem = swipePrivate->createRelevantItemForDistance(distance);
            // If there isn't any relevant item, the user may have swiped back to the 0 position,
            // or they swiped back to a position that is equal to positionBeforePress.
            const qreal normalizedDistance = relevantItem ? distance / relevantItem->width() : 0.0;
            qreal position = 0;

            // If the control was exposed before the drag begun, the distance should be inverted.
            // For example, if the control had been swiped to the right, the position would be 1.0.
            // If the control was then swiped to the left by a distance of -20 pixels, the normalized
            // distance might be -0.2, for example, which cannot be used as the position; the swipe
            // started from the right, so we account for that by adding the position.
            if (qFuzzyIsNull(normalizedDistance)) {
                // There are two cases when the normalizedDistance can be 0,
                // and we must distinguish between them:
                //
                // a) The swipe returns to the position that it was at before the press event.
                // In this case, the distance will be 0.
                // There would have been many position changes in the meantime, so we can't just
                // ignore the move event; we have to set position to what it was before the press.
                //
                // b) If the position was at, 1.0, for example, and the control was then swiped
                // to the left by the exact width of the left item, there won't be any relevant item
                // (because the swipe's position would be at 0.0). In turn, the normalizedDistance
                // would be 0 (because of the lack of a relevant item), but the distance will be non-zero.
                position = qFuzzyIsNull(distance) ? swipePrivate->positionBeforePress : 0;
            } else if (!swipePrivate->wasComplete) {
                position = normalizedDistance;
            } else {
                position = distance > 0 ? normalizedDistance - 1.0 : normalizedDistance + 1.0;
            }

            if (swipePrivate->isTransitioning())
                swipePrivate->transitionManager->cancel();
            swipe.setPosition(position);
        }
    } else {
        // The swipe wasn't initiated.
        if (event->pos().y() < 0 || event->pos().y() > height) {
            // The mouse went outside the vertical bounds of the control, so
            // we should no longer consider it pressed.
            q->setPressed(false);
        }
    }

    event->accept();

    return q->keepMouseGrab();
}

static const qreal exposeVelocityThreshold = 300.0;

bool QQuickSwipeDelegatePrivate::handleMouseReleaseEvent(QQuickItem *item, QMouseEvent *event)
{
    Q_Q(QQuickSwipeDelegate);
    QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe);
    swipePrivate->velocityCalculator.stopMeasuring(event->pos(), event->timestamp());

    const bool hadGrabbedMouse = q->keepMouseGrab();
    q->setKeepMouseGrab(false);

    // Animations for the background and contentItem delegates are typically
    // only enabled when !control.down, so that the animations aren't running
    // when the user is swiping. To ensure that the animations are enabled
    // *before* the positions of these delegates change (via the swipe.setPosition() calls below),
    // we must cancel the press. QQuickAbstractButton::mouseUngrabEvent() does this
    // for us, but by then it's too late.
    if (hadGrabbedMouse) {
        // TODO: this is copied from QQuickAbstractButton::mouseUngrabEvent().
        // Eventually it should be moved into a private helper so that we don't have to duplicate it.
        q->setPressed(false);
        stopPressRepeat();
        stopPressAndHold();
        emit q->canceled();
    }

    // The control can be exposed by either swiping past the halfway mark, or swiping fast enough.
    const qreal swipeVelocity = swipePrivate->velocityCalculator.velocity().x();
    if (swipePrivate->position > 0.5 ||
        (swipePrivate->position > 0.0 && swipeVelocity > exposeVelocityThreshold)) {
        swipePrivate->beginTransition(1.0);
        swipePrivate->wasComplete = true;
    } else if (swipePrivate->position < -0.5 ||
        (swipePrivate->position < 0.0 && swipeVelocity < -exposeVelocityThreshold)) {
        swipePrivate->beginTransition(-1.0);
        swipePrivate->wasComplete = true;
    } else if (!swipePrivate->isTransitioning()) {
        swipePrivate->beginTransition(0.0);
        swipePrivate->wasComplete = false;
    }

    if (Attached *attached = attachedObject(item)) {
        const bool wasPressed = attached->isPressed();
        if (wasPressed) {
            attached->setPressed(false);
            emit attached->clicked();
        }
    }

    // Only consume child events if we had grabbed the mouse.
    return hadGrabbedMouse;
}

static void warnIfHorizontallyAnchored(QQuickItem *item, const QString &itemName)
{
    if (!item)
        return;

    QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors;
    if (anchors && (anchors->fill() || anchors->centerIn() || anchors->left().item || anchors->right().item)
            && !item->property("_q_QQuickSwipeDelegate_warned").toBool()) {
        qmlWarning(item) << QString::fromLatin1("SwipeDelegate: cannot use horizontal anchors with %1; unable to layout the item.").arg(itemName);
        item->setProperty("_q_QQuickSwipeDelegate_warned", true);
    }
}

void QQuickSwipeDelegatePrivate::resizeContent()
{
    warnIfHorizontallyAnchored(background, QStringLiteral("background"));
    warnIfHorizontallyAnchored(contentItem, QStringLiteral("contentItem"));

    // If the background and contentItem are repositioned due to a swipe,
    // we don't want to call QQuickControlPrivate's implementation of this function,
    // as it repositions the contentItem to be visible.
    // However, we still want to resize the control vertically.
    QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe);
    if (!swipePrivate->complete) {
        QQuickItemDelegatePrivate::resizeContent();
    } else if (contentItem) {
        Q_Q(QQuickSwipeDelegate);
        contentItem->setY(q->topPadding());
        contentItem->setHeight(q->availableHeight());
    }
}

QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent)
    : QQuickItemDelegate(*(new QQuickSwipeDelegatePrivate(this)), parent)
{
}

/*!
    \since QtQuick.Controls 2.2 (Qt 5.9)
    \qmlmethod void QtQuick.Controls::SwipeDelegate::swipe.open(enumeration side)

    This method sets the \c position of the swipe so that it opens
    from the specified \a side.

    Available values:
    \value SwipeDelegate.Left  The \c position is set to \c 1, which makes the swipe open
                               from the left. Either \c swipe.left or \c swipe.behind must
                               have been specified; otherwise the call is ignored.
    \value SwipeDelegate.Right The \c position is set to \c -1, which makes the swipe open
                               from the right. Either \c swipe.right or \c swipe.behind must
                               have been specified; otherwise the call is ignored.

    Any animations defined for the \l {Item::}{x} position of \l {Control::}{contentItem}
    and \l {Control::}{background} will be triggered.

    \sa swipe, swipe.close()
*/

/*!
    \since QtQuick.Controls 2.1 (Qt 5.8)
    \qmlmethod void QtQuick.Controls::SwipeDelegate::swipe.close()

    This method sets the \c position of the swipe to \c 0. Any animations
    defined for the \l {Item::}{x} position of \l {Control::}{contentItem}
    and \l {Control::}{background} will be triggered.

    \sa swipe, swipe.open()
*/

/*!
    \since QtQuick.Controls 2.2 (Qt 5.9)
    \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.opened()

    This signal is emitted when the delegate has been swiped open
    and the transition has finished.

    It is useful for performing some action upon completion of a swipe.
    For example, it can be used to remove the delegate from the list
    that it is in.

    \sa swipe, swipe.closed()
*/

/*!
    \since QtQuick.Controls 2.2 (Qt 5.9)
    \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.closed()

    This signal is emitted when the delegate has been swiped to closed
    and the transition has finished.

    It is useful for performing some action upon cancellation of a swipe.
    For example, it can be used to cancel the removal of the delegate from
    the list that it is in.

    \sa swipe, swipe.opened()
*/

/*!
    \since QtQuick.Controls 2.1 (Qt 5.8)
    \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.completed()

    This signal is emitted when \c swipe.complete becomes \c true.

    It is useful for performing some action upon completion of a swipe.
    For example, it can be used to remove the delegate from the list
    that it is in.

    \sa swipe
*/

/*!
    \qmlpropertygroup QtQuick.Controls::SwipeDelegate::swipe
    \qmlproperty real QtQuick.Controls::SwipeDelegate::swipe.position
    \qmlproperty bool QtQuick.Controls::SwipeDelegate::swipe.complete
    \qmlproperty bool QtQuick.Controls::SwipeDelegate::swipe.enabled
    \qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.left
    \qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.behind
    \qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.right
    \qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.leftItem
    \qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.behindItem
    \qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.rightItem
    \qmlproperty Transition QtQuick.Controls::SwipeDelegate::swipe.transition

    \table
    \header
        \li Name
        \li Description
    \row
        \li position
        \li This read-only property holds the position of the swipe relative to either
            side of the control. When this value reaches either
            \c -1.0 (left side) or \c 1.0 (right side) and the mouse button is
            released, \c complete will be \c true.
    \row
        \li complete
        \li This read-only property holds whether the control is fully exposed after
            having been swiped to the left or right.

            When complete is \c true, any interactive items declared in \c left,
            \c right, or \c behind will receive mouse events.
    \row
        \li enabled
        \li This property determines whether or not the control can be swiped.

            This property was added in QtQuick.Controls 2.2.
    \row
        \li left
        \li This property holds the left delegate.

            The left delegate sits behind both \l {Control::}{contentItem} and
            \l {Control::}{background}. When the SwipeDelegate is swiped to the right,
            this item will be gradually revealed.

            \include qquickswipedelegate-interaction.qdocinc
    \row
        \li behind
        \li This property holds the delegate that is shown when the
            SwipeDelegate is swiped to both the left and right.

            As with the \c left and \c right delegates, it sits behind both
            \l {Control::}{contentItem} and \l {Control::}{background}. However, a
            SwipeDelegate whose \c behind has been set can be continuously swiped
            from either side, and will always show the same item.

            \include qquickswipedelegate-interaction.qdocinc
    \row
        \li right
        \li This property holds the right delegate.

            The right delegate sits behind both \l {Control::}{contentItem} and
            \l {Control::}{background}. When the SwipeDelegate is swiped to the left,
            this item will be gradually revealed.

            \include qquickswipedelegate-interaction.qdocinc
    \row
        \li leftItem
        \li This read-only property holds the item instantiated from the \c left component.

            If \c left has not been set, or the position hasn't changed since
            creation of the SwipeDelegate, this property will be \c null.
    \row
        \li behindItem
        \li This read-only property holds the item instantiated from the \c behind component.

            If \c behind has not been set, or the position hasn't changed since
            creation of the SwipeDelegate, this property will be \c null.
    \row
        \li rightItem
        \li This read-only property holds the item instantiated from the \c right component.

            If \c right has not been set, or the position hasn't changed since
            creation of the SwipeDelegate, this property will be \c null.
    \row
        \li transition
        \li This property holds the transition that is applied when a swipe is released,
            or \l swipe.open() or \l swipe.close() is called.

            \snippet qtquickcontrols2-swipedelegate-transition.qml 1

            This property was added in Qt Quick Controls 2.2.
    \endtable

    \sa {Control::}{contentItem}, {Control::}{background}, swipe.open(), swipe.close()
*/
QQuickSwipe *QQuickSwipeDelegate::swipe() const
{
    Q_D(const QQuickSwipeDelegate);
    return const_cast<QQuickSwipe*>(&d->swipe);
}

QQuickSwipeDelegateAttached *QQuickSwipeDelegate::qmlAttachedProperties(QObject *object)
{
    return new QQuickSwipeDelegateAttached(object);
}

static bool isChildOrGrandchildOf(QQuickItem *child, QQuickItem *item)
{
    return item && (child == item || item->isAncestorOf(child));
}

bool QQuickSwipeDelegate::childMouseEventFilter(QQuickItem *child, QEvent *event)
{
    Q_D(QQuickSwipeDelegate);
    // The contentItem is, by default, usually a non-interactive item like Text, and
    // the same applies to the background. This means that simply stacking the left/right/behind
    // items before these items won't allow us to get mouse events when the control is not currently exposed
    // but has been previously. Therefore, we instead call setFiltersChildMouseEvents(true) in the constructor
    // and filter out child events only when the child is the left/right/behind item.
    const QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe);
    if (!isChildOrGrandchildOf(child, swipePrivate->leftItem) && !isChildOrGrandchildOf(child, swipePrivate->behindItem)
        && !isChildOrGrandchildOf(child, swipePrivate->rightItem)) {
        return false;
    }

    switch (event->type()) {
    case QEvent::MouseButtonPress: {
        return d->handleMousePressEvent(child, static_cast<QMouseEvent *>(event));
    } case QEvent::MouseMove: {
        return d->handleMouseMoveEvent(child, static_cast<QMouseEvent *>(event));
    } case QEvent::MouseButtonRelease: {
        // Make sure that the control gets release events if it has created child
        // items that are stealing events from it.
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        QQuickItemDelegate::mouseReleaseEvent(mouseEvent);
        return d->handleMouseReleaseEvent(child, mouseEvent);
    } case QEvent::UngrabMouse: {
        // If the mouse was pressed over e.g. rightItem and then dragged down,
        // the ListView would eventually grab the mouse, at which point we must
        // clear the pressed flag so that it doesn't stay pressed after the release.
        Attached *attached = attachedObject(child);
        if (attached)
            attached->setPressed(false);
        return false;
    } default:
        return false;
    }
}

// We only override this to set positionBeforePress;
// otherwise, it's the same as the base class implementation.
void QQuickSwipeDelegate::mousePressEvent(QMouseEvent *event)
{
    Q_D(QQuickSwipeDelegate);
    QQuickItemDelegate::mousePressEvent(event);

    QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe);
    if (!swipePrivate->enabled)
        return;

    swipePrivate->positionBeforePress = swipePrivate->position;
    swipePrivate->velocityCalculator.startMeasuring(event->pos(), event->timestamp());
}

void QQuickSwipeDelegate::mouseMoveEvent(QMouseEvent *event)
{
    Q_D(QQuickSwipeDelegate);
    if (filtersChildMouseEvents())
        d->handleMouseMoveEvent(this, event);
    else
        QQuickItemDelegate::mouseMoveEvent(event);
}

void QQuickSwipeDelegate::mouseReleaseEvent(QMouseEvent *event)
{
    Q_D(QQuickSwipeDelegate);
    if (!filtersChildMouseEvents() || !d->handleMouseReleaseEvent(this, event))
        QQuickItemDelegate::mouseReleaseEvent(event);
}

void QQuickSwipeDelegate::touchEvent(QTouchEvent *event)
{
    // Don't allow QQuickControl accept the touch event, because QQuickSwipeDelegate
    // is still based on synthesized mouse events
    event->ignore();
}

void QQuickSwipeDelegate::componentComplete()
{
    Q_D(QQuickSwipeDelegate);
    QQuickItemDelegate::componentComplete();
    QQuickSwipePrivate::get(&d->swipe)->reposition(DontAnimatePosition);
}

void QQuickSwipeDelegate::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    Q_D(QQuickSwipeDelegate);
    QQuickControl::geometryChanged(newGeometry, oldGeometry);

    if (isComponentComplete() && !qFuzzyCompare(newGeometry.width(), oldGeometry.width())) {
        QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe);
        swipePrivate->reposition(DontAnimatePosition);
    }
}

QFont QQuickSwipeDelegate::defaultFont() const
{
    return QQuickTheme::font(QQuickTheme::ListView);
}

QPalette QQuickSwipeDelegate::defaultPalette() const
{
    return QQuickTheme::palette(QQuickTheme::ListView);
}

#if QT_CONFIG(accessibility)
QAccessible::Role QQuickSwipeDelegate::accessibleRole() const
{
    return QAccessible::ListItem;
}
#endif

class QQuickSwipeDelegateAttachedPrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QQuickSwipeDelegateAttached)

public:
    // True when left/right/behind is non-interactive and is pressed.
    bool pressed = false;
};

/*!
    \since QtQuick.Controls 2.1 (Qt 5.8)
    \qmlattachedsignal QtQuick.Controls::SwipeDelegate::clicked()

    This signal can be attached to a non-interactive item declared in
    \c swipe.left, \c swipe.right, or \c swipe.behind, in order to react to
    clicks. Items can only be clicked when \c swipe.complete is \c true.

    For interactive controls (such as \l Button) declared in these
    items, use their respective \c clicked() signal instead.

    To respond to clicks on the SwipeDelegate itself, use its
    \l {AbstractButton::}{clicked()} signal.

    \note See the documentation for \l pressed for information on
    how to use the event-related properties correctly.

    \sa pressed
*/

QQuickSwipeDelegateAttached::QQuickSwipeDelegateAttached(QObject *object)
    : QObject(*(new QQuickSwipeDelegateAttachedPrivate), object)
{
    QQuickItem *item = qobject_cast<QQuickItem *>(object);
    if (item) {
        // This allows us to be notified when an otherwise non-interactive item
        // is pressed and clicked. The alternative is much more more complex:
        // iterating through children that contain the event pos and finding
        // the first one with an attached object.
        item->setAcceptedMouseButtons(Qt::AllButtons);
    } else {
        qWarning() << "Attached properties of SwipeDelegate must be accessed through an Item";
    }
}

/*!
    \since QtQuick.Controls 2.1 (Qt 5.8)
    \qmlattachedproperty bool QtQuick.Controls::SwipeDelegate::pressed
    \readonly

    This property can be attached to a non-interactive item declared in
    \c swipe.left, \c swipe.right, or \c swipe.behind, in order to detect if it
    is pressed. Items can only be pressed when \c swipe.complete is \c true.

    For example:

    \code
    swipe.right: Label {
        anchors.right: parent.right
        height: parent.height
        text: "Action"
        color: "white"
        padding: 12
        background: Rectangle {
            color: SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato"
        }
    }
    \endcode

    It is possible to have multiple items which individually receive mouse and
    touch events. For example, to have two actions in the \c swipe.right item,
    use the following code:

    \code
    swipe.right: Row {
        anchors.right: parent.right
        height: parent.height

        Label {
            id: moveLabel
            text: qsTr("Move")
            color: "white"
            verticalAlignment: Label.AlignVCenter
            padding: 12
            height: parent.height

            SwipeDelegate.onClicked: console.log("Moving...")

            background: Rectangle {
                color: moveLabel.SwipeDelegate.pressed ? Qt.darker("#ffbf47", 1.1) : "#ffbf47"
            }
        }
        Label {
            id: deleteLabel
            text: qsTr("Delete")
            color: "white"
            verticalAlignment: Label.AlignVCenter
            padding: 12
            height: parent.height

            SwipeDelegate.onClicked: console.log("Deleting...")

            background: Rectangle {
                color: deleteLabel.SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato"
            }
        }
    }
    \endcode

    Note how the \c color assignment in each \l {Control::}{background} item
    qualifies the attached property with the \c id of the label. This
    is important; using the attached properties on an item causes that item
    to accept events. Suppose we had left out the \c id in the previous example:

    \code
    color: SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato"
    \endcode

    The \l Rectangle background item is a child of the label, so it naturally
    receives events before it. In practice, this means that the background
    color will change, but the \c onClicked handler in the label will never
    get called.

    For interactive controls (such as \l Button) declared in these
    items, use their respective \c pressed property instead.

    For presses on the SwipeDelegate itself, use its
    \l {AbstractButton::}{pressed} property.

    \sa clicked()
*/
bool QQuickSwipeDelegateAttached::isPressed() const
{
    Q_D(const QQuickSwipeDelegateAttached);
    return d->pressed;
}

void QQuickSwipeDelegateAttached::setPressed(bool pressed)
{
    Q_D(QQuickSwipeDelegateAttached);
    if (pressed == d->pressed)
        return;

    d->pressed = pressed;
    emit pressedChanged();
}

QT_END_NAMESPACE
