~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to demos/pathstroke/pathstroke.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "arthurstyle.h"
 
3
#include "pathstroke.h"
 
4
#include "arthurwidgets.h"
 
5
 
 
6
extern void draw_round_rect(QPainter *p, const QRect &bounds, int radius);
 
7
 
 
8
PathStrokeWidget::PathStrokeWidget()
 
9
{
 
10
    setWindowTitle("Primitive Stroking");
 
11
 
 
12
    // Setting up palette.
 
13
    QPalette pal = palette();
 
14
//     pal.setBrush(QPalette::Background, Qt::white);
 
15
//     pal.setBrush(QPalette::Foreground, QColor("aquamarine"));
 
16
//     pal.setBrush(QPalette::Background, QPixmap("background.png"));
 
17
    setPalette(pal);
 
18
 
 
19
    // Widget construction and property setting
 
20
    m_renderer = new PathStrokeRenderer(this);
 
21
 
 
22
    QGroupBox *mainGroup = new ArthurGroupBox(this);
 
23
//     QWidget *mainGroup = new QWidget(this);
 
24
    mainGroup->setFixedWidth(180);
 
25
    mainGroup->setTitle("Path Stroking");
 
26
 
 
27
    QGroupBox *capGroup = new ArthurGroupBox(mainGroup);
 
28
    capGroup->setAttribute(Qt::WA_ContentsPropagated);
 
29
    QRadioButton *flatCap = new QRadioButton(capGroup);
 
30
    QRadioButton *squareCap = new QRadioButton(capGroup);
 
31
    QRadioButton *roundCap = new QRadioButton(capGroup);
 
32
    capGroup->setTitle("Cap Style");
 
33
    flatCap->setText("Flat Cap");
 
34
    squareCap->setText("Square Cap");
 
35
    roundCap->setText("Round Cap");
 
36
 
 
37
    QGroupBox *joinGroup = new ArthurGroupBox(mainGroup);
 
38
    joinGroup->setAttribute(Qt::WA_ContentsPropagated);
 
39
    QRadioButton *bevelJoin = new QRadioButton(joinGroup);
 
40
    QRadioButton *miterJoin = new QRadioButton(joinGroup);
 
41
    QRadioButton *roundJoin = new QRadioButton(joinGroup);
 
42
    joinGroup->setTitle("Join Style");
 
43
    bevelJoin->setText("Bevel Join");
 
44
    miterJoin->setText("Miter Join");
 
45
    roundJoin->setText("Round Join");
 
46
 
 
47
    QGroupBox *styleGroup = new ArthurGroupBox(mainGroup);
 
48
    styleGroup->setAttribute(Qt::WA_ContentsPropagated);
 
49
    QRadioButton *solidLine = new QRadioButton(styleGroup);
 
50
    QRadioButton *dashLine = new QRadioButton(styleGroup);
 
51
    QRadioButton *dotLine = new QRadioButton(styleGroup);
 
52
    QRadioButton *dashDotLine = new QRadioButton(styleGroup);
 
53
    QRadioButton *dashDotDotLine = new QRadioButton(styleGroup);
 
54
    QRadioButton *customDashLine = new QRadioButton(styleGroup);
 
55
    styleGroup->setTitle("Pen Style");
 
56
#if 0
 
57
    solidLine->setText("Solid Line");
 
58
    dashLine->setText("Dash Line");
 
59
    dotLine->setText("Dot Line");
 
60
    dashDotLine->setText("Dash Dot Line");
 
61
    dashDotDotLine->setText("Dash Dot Dot Line");
 
62
#else
 
63
    solidLine->setIcon(QPixmap(":res/images/line_solid.png"));
 
64
    dashLine->setIcon(QPixmap(":res/images/line_dashed.png"));
 
65
    dotLine->setIcon(QPixmap(":res/images/line_dotted.png"));
 
66
    dashDotLine->setIcon(QPixmap(":res/images/line_dash_dot.png"));
 
67
    dashDotDotLine->setIcon(QPixmap(":res/images/line_dash_dot_dot.png"));
 
68
    customDashLine->setText("Custom Style");
 
69
 
 
70
    int fixedHeight = bevelJoin->sizeHint().height();
 
71
    solidLine->setFixedHeight(fixedHeight);
 
72
    dashLine->setFixedHeight(fixedHeight);
 
73
    dotLine->setFixedHeight(fixedHeight);
 
74
    dashDotLine->setFixedHeight(fixedHeight);
 
75
    dashDotDotLine->setFixedHeight(fixedHeight);
 
76
#endif
 
77
 
 
78
    QGroupBox *pathModeGroup = new ArthurGroupBox(mainGroup);
 
79
    pathModeGroup->setAttribute(Qt::WA_ContentsPropagated);
 
80
    QRadioButton *curveMode = new QRadioButton(pathModeGroup);
 
81
    QRadioButton *lineMode = new QRadioButton(pathModeGroup);
 
82
    pathModeGroup->setTitle("Path composed of");
 
83
    curveMode->setText("Curves");
 
84
    lineMode->setText("Lines");
 
85
 
 
86
    QGroupBox *penWidthGroup = new ArthurGroupBox(mainGroup);
 
87
    penWidthGroup->setAttribute(Qt::WA_ContentsPropagated);
 
88
    QSlider *penWidth = new QSlider(Qt::Horizontal, penWidthGroup);
 
89
    penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
 
90
    penWidthGroup->setTitle("Pen Width");
 
91
    penWidth->setRange(0, 500);
 
92
 
 
93
#if 0
 
94
    QCheckBox *animated = new QCheckBox(mainGroup);
 
95
    animated->setText("Animated");
 
96
#else
 
97
    QPushButton *animated = new QPushButton(mainGroup);
 
98
    animated->setText("Animate");
 
99
    animated->setCheckable(true);
 
100
#endif
 
101
 
 
102
    QPushButton *showSourceButton = new QPushButton(mainGroup);
 
103
    showSourceButton->setText("Show Source");
 
104
 
 
105
    QPushButton *whatsThisButton = new QPushButton(mainGroup);
 
106
    whatsThisButton->setText("What's This?");
 
107
    whatsThisButton->setCheckable(true);
 
108
 
 
109
    // Layouting
 
110
    QHBoxLayout *viewLayout = new QHBoxLayout(this);
 
111
    viewLayout->addWidget(m_renderer);
 
112
    viewLayout->addWidget(mainGroup);
 
113
 
 
114
    QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
 
115
    mainGroupLayout->setMargin(3);
 
116
    mainGroupLayout->addWidget(capGroup);
 
117
    mainGroupLayout->addWidget(joinGroup);
 
118
    mainGroupLayout->addWidget(styleGroup);
 
119
    mainGroupLayout->addWidget(penWidthGroup);
 
120
    mainGroupLayout->addWidget(pathModeGroup);
 
121
    mainGroupLayout->addWidget(animated);
 
122
    mainGroupLayout->addStretch(1);
 
123
    mainGroupLayout->addWidget(showSourceButton);
 
124
    mainGroupLayout->addWidget(whatsThisButton);
 
125
 
 
126
    QVBoxLayout *capGroupLayout = new QVBoxLayout(capGroup);
 
127
    capGroupLayout->addWidget(flatCap);
 
128
    capGroupLayout->addWidget(squareCap);
 
129
    capGroupLayout->addWidget(roundCap);
 
130
 
 
131
    QVBoxLayout *joinGroupLayout = new QVBoxLayout(joinGroup);
 
132
    joinGroupLayout->addWidget(bevelJoin);
 
133
    joinGroupLayout->addWidget(miterJoin);
 
134
    joinGroupLayout->addWidget(roundJoin);
 
135
 
 
136
    QVBoxLayout *styleGroupLayout = new QVBoxLayout(styleGroup);
 
137
    styleGroupLayout->addWidget(solidLine);
 
138
    styleGroupLayout->addWidget(dashLine);
 
139
    styleGroupLayout->addWidget(dotLine);
 
140
    styleGroupLayout->addWidget(dashDotLine);
 
141
    styleGroupLayout->addWidget(dashDotDotLine);
 
142
    styleGroupLayout->addWidget(customDashLine);
 
143
 
 
144
    QVBoxLayout *pathModeGroupLayout = new QVBoxLayout(pathModeGroup);
 
145
    pathModeGroupLayout->addWidget(curveMode);
 
146
    pathModeGroupLayout->addWidget(lineMode);
 
147
 
 
148
    QVBoxLayout *penWidthLayout = new QVBoxLayout(penWidthGroup);
 
149
    penWidthLayout->addWidget(penWidth);
 
150
 
 
151
    // Set up connections
 
152
    connect(penWidth, SIGNAL(valueChanged(int)),
 
153
            m_renderer, SLOT(setPenWidth(int)));
 
154
    connect(animated, SIGNAL(toggled(bool)),
 
155
            m_renderer, SLOT(setAnimation(bool)));
 
156
 
 
157
    connect(flatCap, SIGNAL(clicked()), m_renderer, SLOT(setFlatCap()));
 
158
    connect(squareCap, SIGNAL(clicked()), m_renderer, SLOT(setSquareCap()));
 
159
    connect(roundCap, SIGNAL(clicked()), m_renderer, SLOT(setRoundCap()));
 
160
 
 
161
    connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin()));
 
162
    connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin()));
 
163
    connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin()));
 
164
 
 
165
    connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode()));
 
166
    connect(lineMode, SIGNAL(clicked()), m_renderer, SLOT(setLineMode()));
 
167
 
 
168
    connect(solidLine, SIGNAL(clicked()), m_renderer, SLOT(setSolidLine()));
 
169
    connect(dashLine, SIGNAL(clicked()), m_renderer, SLOT(setDashLine()));
 
170
    connect(dotLine, SIGNAL(clicked()), m_renderer, SLOT(setDotLine()));
 
171
    connect(dashDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotLine()));
 
172
    connect(dashDotDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotDotLine()));
 
173
    connect(customDashLine, SIGNAL(clicked()), m_renderer, SLOT(setCustomDashLine()));
 
174
 
 
175
    connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
 
176
 
 
177
    connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
 
178
    connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
 
179
            whatsThisButton, SLOT(setChecked(bool)));
 
180
 
 
181
    // Set the defaults
 
182
    animated->setChecked(true);
 
183
    flatCap->setChecked(true);
 
184
    bevelJoin->setChecked(true);
 
185
    penWidth->setValue(50);
 
186
    curveMode->setChecked(true);
 
187
    solidLine->setChecked(true);
 
188
 
 
189
    m_renderer->loadSourceFile(":res/pathstroke.cpp");
 
190
    m_renderer->loadDescription(":res/pathstroke.html");
 
191
}
 
192
 
 
193
 
 
194
PathStrokeRenderer::PathStrokeRenderer(QWidget *parent)
 
195
    : ArthurFrame(parent)
 
196
{
 
197
    m_pointSize = 10;
 
198
    m_activePoint = -1;
 
199
    m_capStyle = Qt::FlatCap;
 
200
    m_joinStyle = Qt::BevelJoin;
 
201
    m_pathMode = CurveMode;
 
202
    m_penWidth = 1;
 
203
    m_penStyle = Qt::SolidLine;
 
204
    m_wasAnimated = true;
 
205
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
206
}
 
207
 
 
208
void PathStrokeRenderer::paint(QPainter *painter)
 
209
{
 
210
    if (m_points.isEmpty())
 
211
        initializePoints();
 
212
 
 
213
    painter->setRenderHint(QPainter::Antialiasing);
 
214
 
 
215
    QPalette pal = palette();
 
216
    painter->setPen(Qt::NoPen);
 
217
 
 
218
    // Construct the path
 
219
    QPainterPath path;
 
220
    path.moveTo(m_points.at(0));
 
221
 
 
222
    if (m_pathMode == LineMode) {
 
223
        for (int i=1; i<m_points.size(); ++i) {
 
224
            path.lineTo(m_points.at(i));
 
225
        }
 
226
    } else {
 
227
        int i=1;
 
228
        while (i + 2 < m_points.size()) {
 
229
            path.cubicTo(m_points.at(i), m_points.at(i+1), m_points.at(i+2));
 
230
            i += 3;
 
231
        }
 
232
        while (i < m_points.size()) {
 
233
            path.lineTo(m_points.at(i));
 
234
            ++i;
 
235
        }
 
236
    }
 
237
 
 
238
    // Draw the path
 
239
    {
 
240
        QColor lg = Qt::red;
 
241
 
 
242
        // The "custom" pen
 
243
        if (m_penStyle == Qt::NoPen) {
 
244
            QPainterPathStroker stroker;
 
245
            stroker.setWidth(m_penWidth);
 
246
            stroker.setJoinStyle(m_joinStyle);
 
247
            stroker.setCapStyle(m_capStyle);
 
248
 
 
249
            QVector<qreal> dashes;
 
250
            qreal space = 4;
 
251
            dashes << 1 << space
 
252
                   << 3 << space
 
253
                   << 9 << space
 
254
                   << 27 << space
 
255
                   << 9 << space
 
256
                   << 3 << space;
 
257
            stroker.setDashPattern(dashes);
 
258
            QPainterPath stroke = stroker.createStroke(path);
 
259
            painter->fillPath(stroke, lg);
 
260
 
 
261
        } else {
 
262
            QPen pen(lg, m_penWidth, m_penStyle, m_capStyle, m_joinStyle);
 
263
            painter->strokePath(path, pen);
 
264
        }
 
265
    }
 
266
 
 
267
    if (1) {
 
268
        // Draw the control points
 
269
        painter->setPen(QColor(50, 100, 120, 200));
 
270
        painter->setBrush(QColor(200, 200, 210, 120));
 
271
        for (int i=0; i<m_points.size(); ++i) {
 
272
            QPointF pos = m_points.at(i);
 
273
            painter->drawEllipse(QRectF(pos.x() - m_pointSize,
 
274
                                       pos.y() - m_pointSize,
 
275
                                       m_pointSize*2, m_pointSize*2));
 
276
        }
 
277
        painter->setPen(QPen(Qt::lightGray, 0, Qt::SolidLine));
 
278
        painter->setBrush(Qt::NoBrush);
 
279
        painter->drawPolyline(m_points);
 
280
    }
 
281
 
 
282
}
 
283
 
 
284
void PathStrokeRenderer::initializePoints()
 
285
{
 
286
    const int count = 7;
 
287
    m_points.clear();
 
288
    m_vectors.clear();
 
289
 
 
290
    QMatrix m;
 
291
    double rot = 360 / count;
 
292
    QPointF center(width() / 2, height() / 2);
 
293
    QMatrix vm;
 
294
    vm.shear(2, -1);
 
295
    vm.scale(3, 3);
 
296
 
 
297
    for (int i=0; i<count; ++i) {
 
298
        m_vectors << QPointF(.1f, .25f) * (m * vm);
 
299
        m_points << QPointF(0, 100) * m + center;
 
300
        m.rotate(rot);
 
301
    }
 
302
}
 
303
 
 
304
void PathStrokeRenderer::updatePoints()
 
305
{
 
306
    double pad = 10;
 
307
    double left = pad;
 
308
    double right = width() - pad;
 
309
    double top = pad;
 
310
    double bottom = height() - pad;
 
311
 
 
312
    Q_ASSERT(m_points.size() == m_vectors.size());
 
313
    for (int i=0; i<m_points.size(); ++i) {
 
314
 
 
315
        if (i == m_activePoint)
 
316
            continue;
 
317
 
 
318
        QPointF pos = m_points.at(i);
 
319
        QPointF vec = m_vectors.at(i);
 
320
        pos += vec;
 
321
        if (pos.x() < left || pos.x() > right) {
 
322
            vec.setX(-vec.x());
 
323
            pos.setX(pos.x() < left ? left : right);
 
324
        } if (pos.y() < top || pos.y() > bottom) {
 
325
            vec.setY(-vec.y());
 
326
            pos.setY(pos.y() < top ? top : bottom);
 
327
        }
 
328
        m_points[i] = pos;
 
329
        m_vectors[i] = vec;
 
330
    }
 
331
    update();
 
332
}
 
333
 
 
334
void PathStrokeRenderer::mousePressEvent(QMouseEvent *e)
 
335
{
 
336
    setDescriptionEnabled(false);
 
337
    m_activePoint = -1;
 
338
    qreal distance = -1;
 
339
    for (int i=0; i<m_points.size(); ++i) {
 
340
        qreal d = QLineF(e->pos(), m_points.at(i)).length();
 
341
        if ((distance < 0 && d < 8 * m_pointSize) || d < distance) {
 
342
            distance = d;
 
343
            m_activePoint = i;
 
344
        }
 
345
    }
 
346
 
 
347
    if (m_activePoint != -1) {
 
348
        m_wasAnimated = m_timer.isActive();
 
349
        setAnimation(false);
 
350
        mouseMoveEvent(e);
 
351
    }
 
352
}
 
353
 
 
354
void PathStrokeRenderer::mouseMoveEvent(QMouseEvent *e)
 
355
{
 
356
    if (m_activePoint >= 0 && m_activePoint < m_points.size()) {
 
357
        m_points[m_activePoint] = e->pos();
 
358
        update();
 
359
    }
 
360
}
 
361
 
 
362
void PathStrokeRenderer::mouseReleaseEvent(QMouseEvent *)
 
363
{
 
364
    m_activePoint = -1;
 
365
    setAnimation(m_wasAnimated);
 
366
}
 
367
 
 
368
void PathStrokeRenderer::timerEvent(QTimerEvent *e)
 
369
{
 
370
    if (e->timerId() == m_timer.timerId()) {
 
371
        updatePoints();
 
372
        QApplication::syncX();
 
373
    } // else if (e->timerId() == m_fpsTimer.timerId()) {
 
374
//         emit frameRate(m_frameCount);
 
375
//         m_frameCount = 0;
 
376
//     }
 
377
}
 
378
 
 
379
void PathStrokeRenderer::setAnimation(bool animation)
 
380
{
 
381
    m_timer.stop();
 
382
//     m_fpsTimer.stop();
 
383
 
 
384
    if (animation) {
 
385
        m_timer.start(25, this);
 
386
//         m_fpsTimer.start(1000, this);
 
387
//         m_frameCount = 0;
 
388
    }
 
389
}
 
390
 
 
391