summaryrefslogtreecommitdiffstats
path: root/plotwidget.cpp
blob: 90231eca300632dba831c932914cfc880452dc9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <QtGui>

#include "plotwidget.h"
#include "qkineticscroller.h"

PlotWidget::PlotWidget(QKineticScroller *scroller)
    : QWidget(), m_scroller(scroller)
{
    setWindowTitle(QLatin1String("Plot"));
    m_scroller->registerDebugHook(debugHook, this);
    
    m_clear = new QPushButton(QLatin1String("Clear"), this);
    connect(m_clear, SIGNAL(clicked()), this, SLOT(reset()));
    m_legend = new QLabel(QLatin1String("Legend"), this);
    QString tooltip;
    QTextStream ts(&tooltip);
    ts << "<table border=\"0\">";
    ts << "<tr><td width=\"30\" bgcolor=\"" << QColor(Qt::red).dark().name() << "\" /><td>releaseVelocity X</td></tr>";
    ts << "<tr><td width=\"30\" bgcolor=\"" << QColor(Qt::red).light().name() << "\" /><td>releaseVelocity Y</td></tr>";
    ts << "<tr><td width=\"30\" bgcolor=\"" << QColor(Qt::green).dark().name() << "\" /><td>Content Position X</td></tr>";
    ts << "<tr><td width=\"30\" bgcolor=\"" << QColor(Qt::green).light().name() << "\" /><td>Content Position Y</td></tr>";
    ts << "<tr><td width=\"30\" bgcolor=\"" << QColor(Qt::blue).dark().name() << "\" /><td>Overshoot Position X</td></tr>";
    ts << "<tr><td width=\"30\" bgcolor=\"" << QColor(Qt::blue).light().name() << "\" /><td>Overshoot Position Y</td></tr>";
    ts << "</table>";
    m_legend->setToolTip(tooltip);
}

void PlotWidget::debugHook(void *user, const QPointF &releaseVelocity, const QPointF &contentPosition, const QPointF &overshootPosition)
{
    PlotItem pi = { releaseVelocity, contentPosition, overshootPosition };
    static_cast<PlotWidget *>(user)->addPlotItem(pi);
}

static inline void doMaxMin(const QPointF &v, qreal &minmaxv)
{
    minmaxv = qMax(minmaxv, qMax(qAbs(v.x()), qAbs(v.y())));
}

void PlotWidget::addPlotItem(const PlotItem &pi)
{
    m_plotitems.append(pi);
    minMaxVelocity = minMaxPosition = 0;

    while (m_plotitems.size() > 500)
        m_plotitems.removeFirst();
    
    foreach (const PlotItem &pi, m_plotitems) {
        doMaxMin(pi.releaseVelocity, minMaxVelocity);
        doMaxMin(pi.contentPosition, minMaxPosition);
        doMaxMin(pi.overshootPosition, minMaxPosition);
    } 
    update();
}

void PlotWidget::reset()
{
    m_plotitems.clear();
    minMaxVelocity = minMaxPosition = 0;
    update();
}

void PlotWidget::resizeEvent(QResizeEvent *)
{
    QSize cs = m_clear->sizeHint();
    QSize ls = m_legend->sizeHint();
    m_clear->setGeometry(4, 4, cs.width(), cs.height());
    m_legend->setGeometry(4, height() - ls.height() - 4, ls.width(), ls.height());
}

void PlotWidget::paintEvent(QPaintEvent *)
{
#define SCALE(v, mm)  ((qreal(1) - (v / mm)) * qreal(0.5) * height())

    QColor rvColor = Qt::red;
    QColor cpColor = Qt::green;
    QColor opColor = Qt::blue;


    QPainter p(this);
    p.setRenderHints(QPainter::Antialiasing);
    p.fillRect(rect(), Qt::white);

    if (m_plotitems.isEmpty())
        return;

    int x = 2;
    int offset = m_plotitems.size() - width() / 2;    
    QList<PlotItem>::const_iterator it = m_plotitems.constBegin();
    if (offset > 0)
        it += (offset - 1);
    
//     PlotItem &last = const_cast<PlotItem &>(*it++);
//     PlotItem dummy;
     const PlotItem *last = &(*it++);
//     last = *it++;
        
//    qWarning() << "lastOp[0].y = " << last.overshootPosition.y() << m_plotitems.at(1).overshootPosition.y();
        
    while (it != m_plotitems.constEnd()) {    
        p.setPen(rvColor.light());
        p.drawLine(qreal(x - 2), SCALE(last->releaseVelocity.x(), minMaxVelocity),
                   qreal(x), SCALE(it->releaseVelocity.x(), minMaxVelocity));
        p.setPen(rvColor.dark());
        p.drawLine(qreal(x - 2), SCALE(last->releaseVelocity.y(), minMaxVelocity),
                   qreal(x), SCALE(it->releaseVelocity.y(), minMaxVelocity));

        p.setPen(cpColor.light());
        p.drawLine(qreal(x - 2), SCALE(last->contentPosition.x(), minMaxPosition),
                   qreal(x), SCALE(it->contentPosition.x(), minMaxPosition));
        p.setPen(cpColor.dark());
        p.drawLine(qreal(x - 2), SCALE(last->contentPosition.y(), minMaxPosition),
                   qreal(x), SCALE(it->contentPosition.y(), minMaxPosition));

        p.setPen(opColor.light());
        p.drawLine(qreal(x - 2), SCALE(last->overshootPosition.x(), minMaxPosition),
                   qreal(x), SCALE(it->overshootPosition.x(), minMaxPosition));
        p.setPen(opColor.dark());
        p.drawLine(qreal(x - 2), SCALE(last->overshootPosition.y(), minMaxPosition),
                   qreal(x), SCALE(it->overshootPosition.y(), minMaxPosition));

        last = &(*it++);
        x += 2;
    }
#undef SCALE
}