-
Notifications
You must be signed in to change notification settings - Fork 1
/
graphicsitem.cpp
174 lines (153 loc) · 5.27 KB
/
graphicsitem.cpp
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*!
* \file graphicsitem.cpp
* \author Simon Coakley
* \date 2012
* \copyright Copyright (c) 2012 University of Sheffield
* \brief Implementation of graphics item for stategraphs
*/
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>
#include <QDebug>
#include "./graphicsitem.h"
GraphicsItem::GraphicsItem(QGraphicsItem *parent, QGraphicsScene *scene)
: QGraphicsItem(parent, scene) {
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemIsSelectable, true);
sansFont = new QFont("Helvetica", 12);
foreign = false;
}
void GraphicsItem::setState(State *s) {
myState = s;
mytype = 0;
setName(s->name());
}
void GraphicsItem::setTransition(Transition *t) {
transition = t;
mytype = 1;
setName(t->name());
setCondition(t->condition());
preState = t->currentState()->name();
postState = t->nextState()->name();
}
void GraphicsItem::setMessage(MessageComm *m) {
message = m;
mytype = 2;
setName(m->messageType);
}
QString GraphicsItem::getName() {
return name;
}
void GraphicsItem::nameChanged() {
if (mytype == 0) setName(myState->name());
else if (mytype == 1) setName(transition->name());
else if (mytype == 2) setName(message->messageType);
}
void GraphicsItem::setName(QString n) {
name = n;
QFontMetrics fm(*sansFont);
nameWidth = fm.width(name) + 10;
nameHeight = fm.height();
// prepareGeometryChange();
if (mytype == 2) { // message
myNameRect = QRectF(-(nameWidth/2.0)-5.0,
static_cast<float>(-nameHeight),
static_cast<float>(nameWidth+10.0), nameHeight*2.0);
myPath = QPainterPath();
myPath.moveTo(myNameRect.bottomLeft());
myPath.lineTo(myNameRect.bottomRight().x()-10,
myNameRect.bottomRight().y());
myPath.lineTo(myNameRect.topRight());
myPath.lineTo(myNameRect.topLeft().x()+10, myNameRect.topLeft().y());
myPath.lineTo(myNameRect.bottomLeft());
} else {
myNameRect = QRectF(-nameWidth/2.0, static_cast<float>(-nameHeight),
static_cast<float>(nameWidth), nameHeight*2.0);
}
setBoundingRect();
}
void GraphicsItem::setCondition(Condition c) {
condition = c;
QString cond = c.toString();
QFontMetrics fm(*sansFont);
condWidth = fm.width(cond) + 10;
condHeight = fm.height();
myConditionRect = QRectF(-condWidth/2.0,
static_cast<float>(-(condHeight*2)-nameHeight),
static_cast<float>(condWidth), condHeight*2.0);
setBoundingRect();
}
void GraphicsItem::addTransitionArrow(Arrow *arrow) {
transitionArrows.append(arrow);
}
void GraphicsItem::addMessageArrow(Arrow *arrow) {
messageArrows.append(arrow);
}
void GraphicsItem::removeMessageArrow(Arrow *arrow) {
messageArrows.removeOne(arrow);
}
void GraphicsItem::removeTransitionArrow(Arrow *arrow) {
transitionArrows.removeOne(arrow);
}
void GraphicsItem::setBoundingRect() {
prepareGeometryChange();
if (condition.enabled) {
myBoundingRect = QRectF(qMin(myNameRect.x(),
myConditionRect.x()), myConditionRect.y(),
qMax(myNameRect.width(), myConditionRect.width()),
myNameRect.height()+myConditionRect.height());
} else {
myBoundingRect = myNameRect;
}
}
/** \fn GraphicsItem::boundingRect() const
* \brief The bounding rect where all painting must be restricted to. Used to determine if the item needs redrawing.
* \return The bounding rect.
*/
QRectF GraphicsItem::boundingRect() const {
qreal adjust = 0.5;
// return QRectF(-20 - adjust, -10 - adjust, 40 + adjust, 20 + adjust);
return myBoundingRect.adjusted(-adjust, -adjust, adjust, adjust);
}
/** \fn GraphicsItem::shape() const
* \brief The shape of the object used for collision detection, hit tests etc.
* \return The shape.
*/
QPainterPath GraphicsItem::shape() const {
QPainterPath path;
// path.addRect(-20, -10, 40, 20);
// path.addRect(myRect);
if (mytype == 0) path.addEllipse(myNameRect);
if (mytype == 1) path.addRect(myNameRect);
if (mytype == 2) return myPath;
return path;
}
int GraphicsItem::width() {
return myBoundingRect.width();
}
void GraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *) {
// Body
// painter->setBrush(Qt::black);
painter->setRenderHint(QPainter::Antialiasing);
// if(startState) painter->setBrush(Qt::black);
// else
painter->setBrush(Qt::white);
if (foreign) painter->setPen(Qt::gray);
else
painter->setPen(isSelected() ? Qt::red : Qt::black);
if (mytype == 2) painter->setPen(isSelected() ? Qt::darkGreen : Qt::green);
// painter->drawEllipse(-20, -10, 40, 20);
if (mytype == 0) painter->drawEllipse(myNameRect);
if (mytype == 1) painter->drawRect(myNameRect);
if (mytype == 2) painter->drawPath(myPath);
// QFont sansFont("Helvetica", fontSize);
painter->setFont(*sansFont);
painter->drawText(-(nameWidth/2)+5, (nameHeight/2)-2, getName());
if (condition.enabled) painter->drawText(-(condWidth/2)+5,
(condHeight/2)-2 - nameHeight - condHeight, condition.toString());
// Draw bounding box (for development)
/*painter->setPen(Qt::DashLine);
painter->setBrush(Qt::NoBrush);
painter->drawRect(myBoundingRect);*/
}