/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "pathstroke.h"
#include "arthurstyle.h"
#include "arthurwidgets.h"

extern void draw_round_rect(QPainter *p, const QRect &bounds, int radius);


PathStrokeControls::PathStrokeControls(QWidget* parent, PathStrokeRenderer* renderer, bool smallScreen)
      : QWidget(parent)
{
    m_renderer = renderer;

    if (smallScreen)
        layoutForSmallScreens();
    else
        layoutForDesktop();
}

void PathStrokeControls::createCommonControls(QWidget* parent)
{
    m_capGroup = new QGroupBox(parent);
    m_capGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    QRadioButton *flatCap = new QRadioButton(m_capGroup);
    QRadioButton *squareCap = new QRadioButton(m_capGroup);
    QRadioButton *roundCap = new QRadioButton(m_capGroup);
    m_capGroup->setTitle(tr("Cap Style"));
    flatCap->setText(tr("Flat"));
    squareCap->setText(tr("Square"));
    roundCap->setText(tr("Round"));
    flatCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    squareCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    roundCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    m_joinGroup = new QGroupBox(parent);
    m_joinGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    QRadioButton *bevelJoin = new QRadioButton(m_joinGroup);
    QRadioButton *miterJoin = new QRadioButton(m_joinGroup);
    QRadioButton *svgMiterJoin = new QRadioButton(m_joinGroup);
    QRadioButton *roundJoin = new QRadioButton(m_joinGroup);
    m_joinGroup->setTitle(tr("Join Style"));
    bevelJoin->setText(tr("Bevel"));
    miterJoin->setText(tr("Miter"));
    svgMiterJoin->setText(tr("SvgMiter"));
    roundJoin->setText(tr("Round"));

    m_styleGroup = new QGroupBox(parent);
    m_styleGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    QRadioButton *solidLine = new QRadioButton(m_styleGroup);
    QRadioButton *dashLine = new QRadioButton(m_styleGroup);
    QRadioButton *dotLine = new QRadioButton(m_styleGroup);
    QRadioButton *dashDotLine = new QRadioButton(m_styleGroup);
    QRadioButton *dashDotDotLine = new QRadioButton(m_styleGroup);
    QRadioButton *customDashLine = new QRadioButton(m_styleGroup);
    m_styleGroup->setTitle(tr("Pen Style"));

    QPixmap line_solid(":res/images/line_solid.png");
    solidLine->setIcon(line_solid);
    solidLine->setIconSize(line_solid.size());
    QPixmap line_dashed(":res/images/line_dashed.png");
    dashLine->setIcon(line_dashed);
    dashLine->setIconSize(line_dashed.size());
    QPixmap line_dotted(":res/images/line_dotted.png");
    dotLine->setIcon(line_dotted);
    dotLine->setIconSize(line_dotted.size());
    QPixmap line_dash_dot(":res/images/line_dash_dot.png");
    dashDotLine->setIcon(line_dash_dot);
    dashDotLine->setIconSize(line_dash_dot.size());
    QPixmap line_dash_dot_dot(":res/images/line_dash_dot_dot.png");
    dashDotDotLine->setIcon(line_dash_dot_dot);
    dashDotDotLine->setIconSize(line_dash_dot_dot.size());
    customDashLine->setText(tr("Custom"));

    int fixedHeight = bevelJoin->sizeHint().height();
    solidLine->setFixedHeight(fixedHeight);
    dashLine->setFixedHeight(fixedHeight);
    dotLine->setFixedHeight(fixedHeight);
    dashDotLine->setFixedHeight(fixedHeight);
    dashDotDotLine->setFixedHeight(fixedHeight);

    m_pathModeGroup = new QGroupBox(parent);
    m_pathModeGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    QRadioButton *curveMode = new QRadioButton(m_pathModeGroup);
    QRadioButton *lineMode = new QRadioButton(m_pathModeGroup);
    m_pathModeGroup->setTitle(tr("Line Style"));
    curveMode->setText(tr("Curves"));
    lineMode->setText(tr("Lines"));


    // Layouts
    QVBoxLayout *capGroupLayout = new QVBoxLayout(m_capGroup);
    capGroupLayout->addWidget(flatCap);
    capGroupLayout->addWidget(squareCap);
    capGroupLayout->addWidget(roundCap);

    QVBoxLayout *joinGroupLayout = new QVBoxLayout(m_joinGroup);
    joinGroupLayout->addWidget(bevelJoin);
    joinGroupLayout->addWidget(miterJoin);
    joinGroupLayout->addWidget(svgMiterJoin);
    joinGroupLayout->addWidget(roundJoin);

    QVBoxLayout *styleGroupLayout = new QVBoxLayout(m_styleGroup);
    styleGroupLayout->addWidget(solidLine);
    styleGroupLayout->addWidget(dashLine);
    styleGroupLayout->addWidget(dotLine);
    styleGroupLayout->addWidget(dashDotLine);
    styleGroupLayout->addWidget(dashDotDotLine);
    styleGroupLayout->addWidget(customDashLine);

    QVBoxLayout *pathModeGroupLayout = new QVBoxLayout(m_pathModeGroup);
    pathModeGroupLayout->addWidget(curveMode);
    pathModeGroupLayout->addWidget(lineMode);


    // Connections
    connect(flatCap, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setFlatCap);
    connect(squareCap, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setSquareCap);
    connect(roundCap, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setRoundCap);

    connect(bevelJoin, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setBevelJoin);
    connect(miterJoin, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setMiterJoin);
    connect(svgMiterJoin, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setSvgMiterJoin);
    connect(roundJoin, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setRoundJoin);

    connect(curveMode, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setCurveMode);
    connect(lineMode, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setLineMode);

    connect(solidLine, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setSolidLine);
    connect(dashLine, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setDashLine);
    connect(dotLine, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setDotLine);
    connect(dashDotLine, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setDashDotLine);
    connect(dashDotDotLine, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setDashDotDotLine);
    connect(customDashLine, &QAbstractButton::clicked,
            m_renderer, &PathStrokeRenderer::setCustomDashLine);

    // Set the defaults:
    flatCap->setChecked(true);
    bevelJoin->setChecked(true);
    curveMode->setChecked(true);
    solidLine->setChecked(true);
}


void PathStrokeControls::layoutForDesktop()
{
    QGroupBox *mainGroup = new QGroupBox(this);
    mainGroup->setFixedWidth(180);
    mainGroup->setTitle(tr("Path Stroking"));

    createCommonControls(mainGroup);

    QGroupBox* penWidthGroup = new QGroupBox(mainGroup);
    QSlider *penWidth = new QSlider(Qt::Horizontal, penWidthGroup);
    penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    penWidthGroup->setTitle(tr("Pen Width"));
    penWidth->setRange(0, 500);

    QPushButton *animated = new QPushButton(mainGroup);
    animated->setText(tr("Animate"));
    animated->setCheckable(true);

    QPushButton *showSourceButton = new QPushButton(mainGroup);
    showSourceButton->setText(tr("Show Source"));
#if QT_CONFIG(opengl)
    QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
    enableOpenGLButton->setText(tr("Use OpenGL"));
    enableOpenGLButton->setCheckable(true);
    enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
#endif
    QPushButton *whatsThisButton = new QPushButton(mainGroup);
    whatsThisButton->setText(tr("What's This?"));
    whatsThisButton->setCheckable(true);


    // Layouts:
    QVBoxLayout *penWidthLayout = new QVBoxLayout(penWidthGroup);
    penWidthLayout->addWidget(penWidth);

    QVBoxLayout * mainLayout = new QVBoxLayout(this);
    mainLayout->setContentsMargins(QMargins());
    mainLayout->addWidget(mainGroup);

    QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
    mainGroupLayout->setContentsMargins(3, 3, 3, 3);
    mainGroupLayout->addWidget(m_capGroup);
    mainGroupLayout->addWidget(m_joinGroup);
    mainGroupLayout->addWidget(m_styleGroup);
    mainGroupLayout->addWidget(penWidthGroup);
    mainGroupLayout->addWidget(m_pathModeGroup);
    mainGroupLayout->addWidget(animated);
    mainGroupLayout->addStretch(1);
    mainGroupLayout->addWidget(showSourceButton);
#if QT_CONFIG(opengl)
    mainGroupLayout->addWidget(enableOpenGLButton);
#endif
    mainGroupLayout->addWidget(whatsThisButton);


    // Set up connections
    connect(animated, &QAbstractButton::toggled,
            m_renderer, &PathStrokeRenderer::setAnimation);

    connect(penWidth, &QAbstractSlider::valueChanged,
            m_renderer, &PathStrokeRenderer::setPenWidth);

    connect(showSourceButton, &QAbstractButton::clicked,
            m_renderer, &ArthurFrame::showSource);
#if QT_CONFIG(opengl)
    connect(enableOpenGLButton, &QAbstractButton::clicked,
            m_renderer, &ArthurFrame::enableOpenGL);
#endif
    connect(whatsThisButton, &QAbstractButton::clicked,
            m_renderer, &ArthurFrame::setDescriptionEnabled);
    connect(m_renderer, &ArthurFrame::descriptionEnabledChanged,
            whatsThisButton, &QAbstractButton::setChecked);


    // Set the defaults
    animated->setChecked(true);
    penWidth->setValue(50);

}

void PathStrokeControls::layoutForSmallScreens()
{
    createCommonControls(this);

    m_capGroup->layout()->setContentsMargins(QMargins());
    m_joinGroup->layout()->setContentsMargins(QMargins());
    m_styleGroup->layout()->setContentsMargins(QMargins());
    m_pathModeGroup->layout()->setContentsMargins(QMargins());

    QPushButton* okBtn = new QPushButton(tr("OK"), this);
    okBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    okBtn->setMinimumSize(100,okBtn->minimumSize().height());

    QPushButton* quitBtn = new QPushButton(tr("Quit"), this);
    quitBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    quitBtn->setMinimumSize(100, okBtn->minimumSize().height());

    QLabel *penWidthLabel = new QLabel(tr(" Width:"));
    QSlider *penWidth = new QSlider(Qt::Horizontal, this);
    penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    penWidth->setRange(0, 500);

#if QT_CONFIG(opengl)
    QPushButton *enableOpenGLButton = new QPushButton(this);
    enableOpenGLButton->setText(tr("Use OpenGL"));
    enableOpenGLButton->setCheckable(true);
    enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
#endif

    // Layouts:
    QHBoxLayout *penWidthLayout = new QHBoxLayout;
    penWidthLayout->addWidget(penWidthLabel, 0, Qt::AlignRight);
    penWidthLayout->addWidget(penWidth);

    QVBoxLayout *leftLayout = new QVBoxLayout;
    leftLayout->addWidget(m_capGroup);
    leftLayout->addWidget(m_joinGroup);
#if QT_CONFIG(opengl)
    leftLayout->addWidget(enableOpenGLButton);
#endif
    leftLayout->addLayout(penWidthLayout);

    QVBoxLayout *rightLayout = new QVBoxLayout;
    rightLayout->addWidget(m_styleGroup);
    rightLayout->addWidget(m_pathModeGroup);

    QGridLayout *mainLayout = new QGridLayout(this);
    mainLayout->setContentsMargins(QMargins());

    // Add spacers around the form items so we don't look stupid at higher resolutions
    mainLayout->addItem(new QSpacerItem(0,0), 0, 0, 1, 4);
    mainLayout->addItem(new QSpacerItem(0,0), 1, 0, 2, 1);
    mainLayout->addItem(new QSpacerItem(0,0), 1, 3, 2, 1);
    mainLayout->addItem(new QSpacerItem(0,0), 3, 0, 1, 4);

    mainLayout->addLayout(leftLayout, 1, 1);
    mainLayout->addLayout(rightLayout, 1, 2);
    mainLayout->addWidget(quitBtn, 2, 1, Qt::AlignHCenter | Qt::AlignTop);
    mainLayout->addWidget(okBtn, 2, 2, Qt::AlignHCenter | Qt::AlignTop);

#if QT_CONFIG(opengl)
    connect(enableOpenGLButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::enableOpenGL);
#endif

    connect(penWidth, &QAbstractSlider::valueChanged, m_renderer, &PathStrokeRenderer::setPenWidth);
    connect(quitBtn, &QAbstractButton::clicked, this, &PathStrokeControls::emitQuitSignal);
    connect(okBtn, &QAbstractButton::clicked, this, &PathStrokeControls::emitOkSignal);

    m_renderer->setAnimation(true);
    penWidth->setValue(50);
}

void PathStrokeControls::emitQuitSignal()
{
    emit quitPressed();
}

void PathStrokeControls::emitOkSignal()
{
    emit okPressed();
}


PathStrokeWidget::PathStrokeWidget(bool smallScreen)
{
    setWindowTitle(tr("Path Stroking"));

    // Widget construction and property setting
    m_renderer = new PathStrokeRenderer(this, smallScreen);

    m_controls = new PathStrokeControls(nullptr, m_renderer, smallScreen);

    // Layouting
    QHBoxLayout *viewLayout = new QHBoxLayout(this);
    viewLayout->addWidget(m_renderer);

    if (!smallScreen)
        viewLayout->addWidget(m_controls);

    m_renderer->loadSourceFile(":res/pathstroke/pathstroke.cpp");
    m_renderer->loadDescription(":res/pathstroke/pathstroke.html");

    connect(m_renderer, &PathStrokeRenderer::clicked, this, &PathStrokeWidget::showControls);
    connect(m_controls, &PathStrokeControls::okPressed, this, &PathStrokeWidget::hideControls);
    connect(m_controls, SIGNAL(quitPressed()), QApplication::instance(), SLOT(quit()));
}

void PathStrokeWidget::showControls()
{
    m_controls->showFullScreen();
}

void PathStrokeWidget::hideControls()
{
    m_controls->hide();
}

void PathStrokeWidget::setStyle(QStyle *style)
{
    QWidget::setStyle(style);
    if (m_controls != nullptr)
    {
        m_controls->setStyle(style);

        const QList<QWidget *> widgets = m_controls->findChildren<QWidget *>();
        for (QWidget *w : widgets)
            w->setStyle(style);
    }
}

PathStrokeRenderer::PathStrokeRenderer(QWidget *parent, bool smallScreen)
    : ArthurFrame(parent)
{
    m_smallScreen = smallScreen;
    m_pointSize = 10;
    m_activePoint = -1;
    m_capStyle = Qt::FlatCap;
    m_joinStyle = Qt::BevelJoin;
    m_pathMode = CurveMode;
    m_penWidth = 1;
    m_penStyle = Qt::SolidLine;
    m_wasAnimated = true;
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    setAttribute(Qt::WA_AcceptTouchEvents);
}

void PathStrokeRenderer::paint(QPainter *painter)
{
    if (m_points.isEmpty())
        initializePoints();

    painter->setRenderHint(QPainter::Antialiasing);

    QPalette pal = palette();
    painter->setPen(Qt::NoPen);

    // Construct the path
    QPainterPath path;
    path.moveTo(m_points.at(0));

    if (m_pathMode == LineMode) {
        for (int i=1; i<m_points.size(); ++i)
            path.lineTo(m_points.at(i));
    } else {
        int i=1;
        while (i + 2 < m_points.size()) {
            path.cubicTo(m_points.at(i), m_points.at(i+1), m_points.at(i+2));
            i += 3;
        }
        while (i < m_points.size()) {
            path.lineTo(m_points.at(i));
            ++i;
        }
    }

    // Draw the path
    {
        QColor lg = Qt::red;

        // The "custom" pen
        if (m_penStyle == Qt::NoPen) {
            QPainterPathStroker stroker;
            stroker.setWidth(m_penWidth);
            stroker.setJoinStyle(m_joinStyle);
            stroker.setCapStyle(m_capStyle);

            QVector<qreal> dashes;
            qreal space = 4;
            dashes << 1 << space
                   << 3 << space
                   << 9 << space
                   << 27 << space
                   << 9 << space
                   << 3 << space;
            stroker.setDashPattern(dashes);
            QPainterPath stroke = stroker.createStroke(path);
            painter->fillPath(stroke, lg);

        } else {
            QPen pen(lg, m_penWidth, m_penStyle, m_capStyle, m_joinStyle);
            painter->strokePath(path, pen);
        }
    }

    if (1) {
        // Draw the control points
        painter->setPen(QColor(50, 100, 120, 200));
        painter->setBrush(QColor(200, 200, 210, 120));
        for (int i=0; i<m_points.size(); ++i) {
            QPointF pos = m_points.at(i);
            painter->drawEllipse(QRectF(pos.x() - m_pointSize,
                                       pos.y() - m_pointSize,
                                       m_pointSize*2, m_pointSize*2));
        }
        painter->setPen(QPen(Qt::lightGray, 0, Qt::SolidLine));
        painter->setBrush(Qt::NoBrush);
        painter->drawPolyline(m_points);
    }

}

void PathStrokeRenderer::initializePoints()
{
    const int count = 7;
    m_points.clear();
    m_vectors.clear();

    QMatrix m;
    qreal rot = 360.0 / count;
    QPointF center(width() / 2, height() / 2);
    QMatrix vm;
    vm.shear(2, -1);
    vm.scale(3, 3);

    for (int i=0; i<count; ++i) {
        m_vectors << QPointF(.1f, .25f) * (m * vm);
        m_points << QPointF(0, 100) * m + center;
        m.rotate(rot);
    }
}

void PathStrokeRenderer::updatePoints()
{
    qreal pad = 10;
    qreal left = pad;
    qreal right = width() - pad;
    qreal top = pad;
    qreal bottom = height() - pad;

    Q_ASSERT(m_points.size() == m_vectors.size());
    for (int i = 0; i < m_points.size(); ++i) {
        QPointF pos = m_points.at(i);
        QPointF vec = m_vectors.at(i);
        pos += vec;
        if (pos.x() < left || pos.x() > right) {
            vec.setX(-vec.x());
            pos.setX(pos.x() < left ? left : right);
        } if (pos.y() < top || pos.y() > bottom) {
            vec.setY(-vec.y());
            pos.setY(pos.y() < top ? top : bottom);
        }
        m_points[i] = pos;
        m_vectors[i] = vec;
    }
    update();
}

void PathStrokeRenderer::mousePressEvent(QMouseEvent *e)
{
    if (!m_fingerPointMapping.isEmpty())
        return;
    setDescriptionEnabled(false);
    m_activePoint = -1;
    qreal distance = -1;
    for (int i = 0; i < m_points.size(); ++i) {
        qreal d = QLineF(e->pos(), m_points.at(i)).length();
        if ((distance < 0 && d < 8 * m_pointSize) || d < distance) {
            distance = d;
            m_activePoint = i;
        }
    }

    if (m_activePoint != -1) {
        m_wasAnimated = m_timer.isActive();
        setAnimation(false);
        mouseMoveEvent(e);
    }

    // If we're not running in small screen mode, always assume we're dragging
    m_mouseDrag = !m_smallScreen;
    m_mousePress = e->pos();
}

void PathStrokeRenderer::mouseMoveEvent(QMouseEvent *e)
{
    if (!m_fingerPointMapping.isEmpty())
        return;
    // If we've moved more then 25 pixels, assume user is dragging
    if (!m_mouseDrag && QPoint(m_mousePress - e->pos()).manhattanLength() > 25)
        m_mouseDrag = true;

    if (m_mouseDrag && m_activePoint >= 0 && m_activePoint < m_points.size()) {
        m_points[m_activePoint] = e->pos();
        update();
    }
}

void PathStrokeRenderer::mouseReleaseEvent(QMouseEvent *)
{
    if (!m_fingerPointMapping.isEmpty())
        return;
    m_activePoint = -1;
    setAnimation(m_wasAnimated);

    if (!m_mouseDrag && m_smallScreen)
        emit clicked();
}

void PathStrokeRenderer::timerEvent(QTimerEvent *e)
{
    if (e->timerId() == m_timer.timerId()) {
        updatePoints();
    } // else if (e->timerId() == m_fpsTimer.timerId()) {
//         emit frameRate(m_frameCount);
//         m_frameCount = 0;
//     }
}

bool PathStrokeRenderer::event(QEvent *e)
{
    bool touchBegin = false;
    switch (e->type()) {
    case QEvent::TouchBegin:
        touchBegin = true;
        Q_FALLTHROUGH();
    case QEvent::TouchUpdate:
    {
        const QTouchEvent *const event = static_cast<const QTouchEvent*>(e);
        const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
        for (const QTouchEvent::TouchPoint &touchPoint : points) {
            const int id = touchPoint.id();
            switch (touchPoint.state()) {
            case Qt::TouchPointPressed:
            {
                // find the point, move it
                const auto mappedPoints = m_fingerPointMapping.values();
                QSet<int> activePoints = QSet<int>(mappedPoints.begin(), mappedPoints.end());
                int activePoint = -1;
                qreal distance = -1;
                const int pointsCount = m_points.size();
                for (int i=0; i<pointsCount; ++i) {
                    if (activePoints.contains(i))
                        continue;

                    qreal d = QLineF(touchPoint.pos(), m_points.at(i)).length();
                    if ((distance < 0 && d < 12 * m_pointSize) || d < distance) {
                        distance = d;
                        activePoint = i;
                    }
                }
                if (activePoint != -1) {
                    m_fingerPointMapping.insert(touchPoint.id(), activePoint);
                    m_points[activePoint] = touchPoint.pos();
                }
                break;
            }
            case Qt::TouchPointReleased:
            {
                // move the point and release
                QHash<int,int>::iterator it = m_fingerPointMapping.find(id);
                m_points[it.value()] = touchPoint.pos();
                m_fingerPointMapping.erase(it);
                break;
            }
            case Qt::TouchPointMoved:
            {
                // move the point
                const int pointIdx = m_fingerPointMapping.value(id, -1);
                if (pointIdx >= 0)
                    m_points[pointIdx] = touchPoint.pos();
                break;
            }
            default:
                break;
            }
        }
        if (m_fingerPointMapping.isEmpty()) {
            e->ignore();
            return false;
        } else {
            if (touchBegin) {
                m_wasAnimated = m_timer.isActive();
                setAnimation(false);
            }
            update();
            return true;
        }
    }
        break;
    case QEvent::TouchEnd:
        if (m_fingerPointMapping.isEmpty()) {
            e->ignore();
            return false;
        }
        m_fingerPointMapping.clear();
        setAnimation(m_wasAnimated);
        return true;
    default:
        break;
    }
    return QWidget::event(e);
}

void PathStrokeRenderer::setAnimation(bool animation)
{
    m_timer.stop();
//     m_fpsTimer.stop();

    if (animation) {
        m_timer.start(25, this);
//         m_fpsTimer.start(1000, this);
//         m_frameCount = 0;
    }
}
