25 #include <QGraphicsPolygonItem>
27 #include <boost/lexical_cast.hpp>
35 #include "StateChartGraphEdge.h"
41 QGraphicsPathItem(0, 0),
42 m_startControlPoint(),
48 QGraphicsPathItem(0, scene),
49 m_startControlPoint(),
55 QGraphicsPathItem(0, scene),
56 m_headNode(gvGraphEdge->head->name),
57 m_tailNode(gvGraphEdge->tail->name),
58 m_startControlPoint(),
60 m_bInfoBoxUnfolded(false),
61 m_transitionName(transitionName)
63 m_InfoPointRadius = dpi / 6;
64 m_ArrowScale = dpi / 10;
66 std::vector<floatPair> controlPoints = calcControlPoints(gvGraphEdge);
67 calcPath(controlPoints);
74 pen.setColor(Qt::black);
77 m_Arrow =
new QGraphicsPolygonItem(
this, scene);
78 m_Arrow->setBrush(QBrush(Qt::black));
80 setArrowHeadPosition(QPointF(controlPoints[
int(controlPoints.size()) - 2].first, controlPoints[
int(controlPoints.size()) - 2].second),
86 m_pTransitionLabel =
new QGraphicsSimpleTextItem(transitionName,
this);
87 QRectF transitionLabelRect = m_pTransitionLabel->boundingRect();
96 labelAngle = -labelAngle;
102 labelAngle =
pi + labelAngle;
111 m_pTransitionLabel->rotate(labelAngle * 180 /
pi);
113 setInfoPointPosition(QPointF(m_pTransitionLabel->pos().x() + transitionLabelRect.width()*cos(labelAngle),
114 m_pTransitionLabel->pos().y() + transitionLabelRect.width()*sin(labelAngle)), labelAngle);
118 m_pTransitionInfoPoint =
new QGraphicsEllipseItem(
this, scene);
119 m_Cross =
new QGraphicsPathItem(m_pTransitionInfoPoint, scene);
122 m_InfoBox =
new QGraphicsRectItem(
this);
123 m_InfoBox->setBrush(QBrush(Qt::white));
124 m_InfoText =
new QGraphicsSimpleTextItem(QString(
"test1\ntest2"), m_InfoBox);
136 delete m_pTransitionLabel;
137 delete m_pTransitionInfoPoint;
142 m_transitionName = name;
143 m_pTransitionLabel->setText(name);
149 m_Path = QPainterPath(startPoint);
150 m_Path.lineTo(newEndPoint);
156 QRectF transitionRect = m_pTransitionLabel->boundingRect();
157 m_pTransitionLabel->resetTransform();
164 labelAngle = -labelAngle;
169 labelAngle =
pi + labelAngle;
175 m_pTransitionLabel->rotate(labelAngle * 180 /
pi);
177 setInfoPointPosition(QPointF(m_pTransitionLabel->pos().x() + transitionRect.width()*cos(labelAngle),
178 m_pTransitionLabel->pos().y() + transitionRect.width()*sin(labelAngle)), labelAngle);
186 m_Path = QPainterPath(newStartPoint);
192 QRectF transitionRect = m_pTransitionLabel->boundingRect();
193 m_pTransitionLabel->resetTransform();
200 labelAngle = -labelAngle;
205 labelAngle =
pi + labelAngle;
211 m_pTransitionLabel->rotate(labelAngle * 180 /
pi);
212 setInfoPointPosition(QPointF(m_pTransitionLabel->pos().x() + transitionRect.width()*cos(labelAngle),
213 m_pTransitionLabel->pos().y() + transitionRect.width()*sin(labelAngle)), labelAngle);
217 void StateChartGraphEdge::setInfoPointPosition(QPointF newPosition,
double labelAngle)
219 QPointF startPoint(0, -m_InfoPointRadius / 3);
220 QPointF endPoint(0, m_InfoPointRadius / 3);
221 QPointF startPoint2(-m_InfoPointRadius / 3, 0);
222 QPointF endPoint2(m_InfoPointRadius / 3, 0);
226 m_CrossPainter = QPainterPath(startPoint);
227 m_CrossPainter.lineTo(endPoint);
228 m_CrossPainter.moveTo(startPoint2);
229 m_CrossPainter.lineTo(endPoint2);
230 m_Cross->setPath(m_CrossPainter);
234 m_CrossPainter = QPainterPath(startPoint2);
235 m_CrossPainter.lineTo(endPoint2);
236 m_Cross->setPath(m_CrossPainter);
239 m_pTransitionInfoPoint->setRect(newPosition.x(), newPosition.y() - m_InfoPointRadius, m_InfoPointRadius, m_InfoPointRadius);
240 m_Cross->resetTransform();
241 m_Cross->setPos(newPosition.x() + m_InfoPointRadius / 2, newPosition.y() - m_InfoPointRadius / 2);
242 m_Cross->rotate(labelAngle * 180 /
pi);
243 m_InfoText->setPos(newPosition.x() + m_InfoPointRadius, newPosition.y() - m_InfoPointRadius);
244 m_InfoBox->setRect(newPosition.x() + m_InfoPointRadius, newPosition.y() - m_InfoPointRadius,
245 m_InfoText->boundingRect().width(), m_InfoText->boundingRect().height());
248 void StateChartGraphEdge::setArrowHeadPosition(QPointF headLineSegmentStart, QPointF headLineSegmentEnd)
252 QPointF arrowVector = headLineSegmentEnd - headLineSegmentStart;
254 double lengthLastSegment = calcLengthOfLine(headLineSegmentStart, headLineSegmentStart);
255 arrowVector.setX(arrowVector.x() / lengthLastSegment);
256 arrowVector.setY(arrowVector.y() / lengthLastSegment);
260 arrowHead << headLineSegmentEnd;
261 arrowHead << QPointF(headLineSegmentEnd.x() - m_ArrowScale * (arrowVector.x() - arrowVector.y()), headLineSegmentEnd.y() - m_ArrowScale * (arrowVector.y() + arrowVector.x()));
262 arrowHead << QPointF(headLineSegmentEnd.x() - m_ArrowScale * (arrowVector.x() + arrowVector.y()), headLineSegmentEnd.y() - m_ArrowScale * (arrowVector.y() - arrowVector.x()));
265 m_Arrow->setPolygon(arrowHead);
270 float xDiff = end.first - start.first;
271 float yDiff = end.second - start.second;
272 return sqrt(pow(xDiff, 2) + pow(yDiff, 2));
275 float StateChartGraphEdge::calcLengthOfLine(QPointF start, QPointF end)
277 return calcLengthOfLine(
floatPair(start.x(), start.y()),
floatPair(end.x(), end.y()));
280 std::vector<floatPair> StateChartGraphEdge::calcControlPoints(Agedge_t* gvGraphEdge)
282 std::vector<floatPair> controlPoints;
285 std::string position(agget(gvGraphEdge,
const_cast<char*
>(
"pos")));
286 size_t oldDividerPos;
290 dividerPos = position.find_first_of(
",");
291 assert(dividerPos != std::string::npos);
292 oldDividerPos = dividerPos;
296 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
297 assert(dividerPos != std::string::npos);
298 std::string stringEndX = position.substr(oldDividerPos + 1, dividerPos);
299 oldDividerPos = dividerPos;
304 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
305 assert(dividerPos != std::string::npos);
306 std::string stringEndY = position.substr(oldDividerPos + 1, dividerPos);
307 oldDividerPos = dividerPos;
312 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
313 assert(dividerPos != std::string::npos);
314 std::string stringStartX = position.substr(oldDividerPos + 1, dividerPos);
315 oldDividerPos = dividerPos;
320 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
321 std::string stringStartY = position.substr(oldDividerPos + 1, dividerPos);
322 oldDividerPos = dividerPos;
328 while (oldDividerPos != std::string::npos)
332 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
333 assert(dividerPos != std::string::npos);
334 std::string posX = position.substr(oldDividerPos + 1, dividerPos);
335 oldDividerPos = dividerPos;
337 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
338 std::string posY = position.substr(oldDividerPos + 1, dividerPos);
339 oldDividerPos = dividerPos;
341 controlPoint.first = boost::lexical_cast<float>(posX);
342 controlPoint.second = boost::lexical_cast<float>(posY);
343 controlPoints.push_back(controlPoint);
348 return controlPoints;
351 void StateChartGraphEdge::calcPath(std::vector<floatPair> controlPoints)
354 m_Path.moveTo(controlPoints[0].first, controlPoints[0].second);
356 if (
int(controlPoints.size()) > 2)
359 for (
int i = 1; i < int(controlPoints.size()) - 1; i += 1)
361 m_Path.quadTo(controlPoints[i].first, controlPoints[i].second, controlPoints[i + 1].first, controlPoints[i + 1].second);
368 m_Path.lineTo(controlPoints[controlPoints.size() - 1].first, controlPoints[controlPoints.size() - 1].second);
395 labelAngle = -labelAngle;
400 labelAngle =
pi + labelAngle;
403 QRectF transitionRect = m_pTransitionLabel->boundingRect();
404 setInfoPointPosition(QPointF(m_pTransitionLabel->pos().x() + transitionRect.width()*cos(labelAngle),
405 m_pTransitionLabel->pos().y() + transitionRect.width()*sin(labelAngle)), labelAngle);
417 labelAngle = -labelAngle;
422 labelAngle =
pi + labelAngle;
425 QRectF transitionRect = m_pTransitionLabel->boundingRect();
426 setInfoPointPosition(QPointF(m_pTransitionLabel->pos().x() + transitionRect.width()*cos(labelAngle),
427 m_pTransitionLabel->pos().y() + transitionRect.width()*sin(labelAngle)), labelAngle);