2
#include "arthurstyle.h"
3
#include "pathstroke.h"
4
#include "arthurwidgets.h"
6
extern void draw_round_rect(QPainter *p, const QRect &bounds, int radius);
8
PathStrokeWidget::PathStrokeWidget()
10
setWindowTitle("Primitive Stroking");
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"));
19
// Widget construction and property setting
20
m_renderer = new PathStrokeRenderer(this);
22
QGroupBox *mainGroup = new ArthurGroupBox(this);
23
// QWidget *mainGroup = new QWidget(this);
24
mainGroup->setFixedWidth(180);
25
mainGroup->setTitle("Path Stroking");
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");
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");
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");
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");
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");
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);
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");
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);
94
QCheckBox *animated = new QCheckBox(mainGroup);
95
animated->setText("Animated");
97
QPushButton *animated = new QPushButton(mainGroup);
98
animated->setText("Animate");
99
animated->setCheckable(true);
102
QPushButton *showSourceButton = new QPushButton(mainGroup);
103
showSourceButton->setText("Show Source");
105
QPushButton *whatsThisButton = new QPushButton(mainGroup);
106
whatsThisButton->setText("What's This?");
107
whatsThisButton->setCheckable(true);
110
QHBoxLayout *viewLayout = new QHBoxLayout(this);
111
viewLayout->addWidget(m_renderer);
112
viewLayout->addWidget(mainGroup);
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);
126
QVBoxLayout *capGroupLayout = new QVBoxLayout(capGroup);
127
capGroupLayout->addWidget(flatCap);
128
capGroupLayout->addWidget(squareCap);
129
capGroupLayout->addWidget(roundCap);
131
QVBoxLayout *joinGroupLayout = new QVBoxLayout(joinGroup);
132
joinGroupLayout->addWidget(bevelJoin);
133
joinGroupLayout->addWidget(miterJoin);
134
joinGroupLayout->addWidget(roundJoin);
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);
144
QVBoxLayout *pathModeGroupLayout = new QVBoxLayout(pathModeGroup);
145
pathModeGroupLayout->addWidget(curveMode);
146
pathModeGroupLayout->addWidget(lineMode);
148
QVBoxLayout *penWidthLayout = new QVBoxLayout(penWidthGroup);
149
penWidthLayout->addWidget(penWidth);
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)));
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()));
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()));
165
connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode()));
166
connect(lineMode, SIGNAL(clicked()), m_renderer, SLOT(setLineMode()));
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()));
175
connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
177
connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
178
connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
179
whatsThisButton, SLOT(setChecked(bool)));
182
animated->setChecked(true);
183
flatCap->setChecked(true);
184
bevelJoin->setChecked(true);
185
penWidth->setValue(50);
186
curveMode->setChecked(true);
187
solidLine->setChecked(true);
189
m_renderer->loadSourceFile(":res/pathstroke.cpp");
190
m_renderer->loadDescription(":res/pathstroke.html");
194
PathStrokeRenderer::PathStrokeRenderer(QWidget *parent)
195
: ArthurFrame(parent)
199
m_capStyle = Qt::FlatCap;
200
m_joinStyle = Qt::BevelJoin;
201
m_pathMode = CurveMode;
203
m_penStyle = Qt::SolidLine;
204
m_wasAnimated = true;
205
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
208
void PathStrokeRenderer::paint(QPainter *painter)
210
if (m_points.isEmpty())
213
painter->setRenderHint(QPainter::Antialiasing);
215
QPalette pal = palette();
216
painter->setPen(Qt::NoPen);
218
// Construct the path
220
path.moveTo(m_points.at(0));
222
if (m_pathMode == LineMode) {
223
for (int i=1; i<m_points.size(); ++i) {
224
path.lineTo(m_points.at(i));
228
while (i + 2 < m_points.size()) {
229
path.cubicTo(m_points.at(i), m_points.at(i+1), m_points.at(i+2));
232
while (i < m_points.size()) {
233
path.lineTo(m_points.at(i));
243
if (m_penStyle == Qt::NoPen) {
244
QPainterPathStroker stroker;
245
stroker.setWidth(m_penWidth);
246
stroker.setJoinStyle(m_joinStyle);
247
stroker.setCapStyle(m_capStyle);
249
QVector<qreal> dashes;
257
stroker.setDashPattern(dashes);
258
QPainterPath stroke = stroker.createStroke(path);
259
painter->fillPath(stroke, lg);
262
QPen pen(lg, m_penWidth, m_penStyle, m_capStyle, m_joinStyle);
263
painter->strokePath(path, pen);
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));
277
painter->setPen(QPen(Qt::lightGray, 0, Qt::SolidLine));
278
painter->setBrush(Qt::NoBrush);
279
painter->drawPolyline(m_points);
284
void PathStrokeRenderer::initializePoints()
291
double rot = 360 / count;
292
QPointF center(width() / 2, height() / 2);
297
for (int i=0; i<count; ++i) {
298
m_vectors << QPointF(.1f, .25f) * (m * vm);
299
m_points << QPointF(0, 100) * m + center;
304
void PathStrokeRenderer::updatePoints()
308
double right = width() - pad;
310
double bottom = height() - pad;
312
Q_ASSERT(m_points.size() == m_vectors.size());
313
for (int i=0; i<m_points.size(); ++i) {
315
if (i == m_activePoint)
318
QPointF pos = m_points.at(i);
319
QPointF vec = m_vectors.at(i);
321
if (pos.x() < left || pos.x() > right) {
323
pos.setX(pos.x() < left ? left : right);
324
} if (pos.y() < top || pos.y() > bottom) {
326
pos.setY(pos.y() < top ? top : bottom);
334
void PathStrokeRenderer::mousePressEvent(QMouseEvent *e)
336
setDescriptionEnabled(false);
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) {
347
if (m_activePoint != -1) {
348
m_wasAnimated = m_timer.isActive();
354
void PathStrokeRenderer::mouseMoveEvent(QMouseEvent *e)
356
if (m_activePoint >= 0 && m_activePoint < m_points.size()) {
357
m_points[m_activePoint] = e->pos();
362
void PathStrokeRenderer::mouseReleaseEvent(QMouseEvent *)
365
setAnimation(m_wasAnimated);
368
void PathStrokeRenderer::timerEvent(QTimerEvent *e)
370
if (e->timerId() == m_timer.timerId()) {
372
QApplication::syncX();
373
} // else if (e->timerId() == m_fpsTimer.timerId()) {
374
// emit frameRate(m_frameCount);
379
void PathStrokeRenderer::setAnimation(bool animation)
382
// m_fpsTimer.stop();
385
m_timer.start(25, this);
386
// m_fpsTimer.start(1000, this);