29 #include <boost/lexical_cast.hpp>
31 #include <QGraphicsPolygonItem>
36 #include "StateChartGraphEdge.h"
42 QGraphicsPathItem(0, 0), m_startControlPoint(), m_endControlPoint()
47 QGraphicsPathItem(0, scene), m_startControlPoint(), m_endControlPoint()
52 const QString& transitionName,
53 QGraphicsScene* scene,
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,
81 controlPoints[
int(controlPoints.size()) - 2].second),
87 m_pTransitionLabel =
new QGraphicsSimpleTextItem(transitionName,
this);
88 QRectF transitionLabelRect = m_pTransitionLabel->boundingRect();
98 labelAngle = -labelAngle;
104 labelAngle =
pi + labelAngle;
109 m_pTransitionLabel->setPos(
111 (0.5 * (transitionLength - arg * transitionLabelRect.width()) *
114 (0.5 * (transitionLength - arg * transitionLabelRect.width()) *
116 m_pTransitionLabel->setPos(
117 m_Path.pointAtPercent(0.5).x() - arg * transitionLabelRect.width() * 0.5 *
120 m_Path.pointAtPercent(0.5).y() -
121 arg * transitionLabelRect.width() * 0.5 *
123 m_pTransitionLabel->rotate(labelAngle * 180 /
pi);
125 setInfoPointPosition(
126 QPointF(m_pTransitionLabel->pos().x() + transitionLabelRect.width() * cos(labelAngle),
127 m_pTransitionLabel->pos().y() + transitionLabelRect.width() * sin(labelAngle)),
132 m_pTransitionInfoPoint =
new QGraphicsEllipseItem(
134 m_Cross =
new QGraphicsPathItem(m_pTransitionInfoPoint, scene);
137 m_InfoBox =
new QGraphicsRectItem(
this);
138 m_InfoBox->setBrush(QBrush(Qt::white));
139 m_InfoText =
new QGraphicsSimpleTextItem(QString(
"test1\ntest2"), m_InfoBox);
151 delete m_pTransitionLabel;
152 delete m_pTransitionInfoPoint;
158 m_transitionName = name;
159 m_pTransitionLabel->setText(name);
166 m_Path = QPainterPath(startPoint);
167 m_Path.lineTo(newEndPoint);
173 QRectF transitionRect = m_pTransitionLabel->boundingRect();
174 m_pTransitionLabel->resetTransform();
183 labelAngle = -labelAngle;
188 labelAngle =
pi + labelAngle;
192 m_pTransitionLabel->setPos(
194 (0.5 * (transitionLength - arg * transitionRect.width()) *
197 (0.5 * (transitionLength - arg * transitionRect.width()) *
199 m_pTransitionLabel->rotate(labelAngle * 180 /
pi);
201 setInfoPointPosition(
202 QPointF(m_pTransitionLabel->pos().x() + transitionRect.width() * cos(labelAngle),
203 m_pTransitionLabel->pos().y() + transitionRect.width() * sin(labelAngle)),
212 m_Path = QPainterPath(newStartPoint);
218 QRectF transitionRect = m_pTransitionLabel->boundingRect();
219 m_pTransitionLabel->resetTransform();
228 labelAngle = -labelAngle;
233 labelAngle =
pi + labelAngle;
237 m_pTransitionLabel->setPos(
239 (0.5 * (transitionLength - arg * transitionRect.width()) *
242 (0.5 * (transitionLength - arg * transitionRect.width()) *
244 m_pTransitionLabel->rotate(labelAngle * 180 /
pi);
245 setInfoPointPosition(
246 QPointF(m_pTransitionLabel->pos().x() + transitionRect.width() * cos(labelAngle),
247 m_pTransitionLabel->pos().y() + transitionRect.width() * sin(labelAngle)),
253 StateChartGraphEdge::setInfoPointPosition(QPointF newPosition,
double labelAngle)
255 QPointF startPoint(0, -m_InfoPointRadius / 3);
256 QPointF endPoint(0, m_InfoPointRadius / 3);
257 QPointF startPoint2(-m_InfoPointRadius / 3, 0);
258 QPointF endPoint2(m_InfoPointRadius / 3, 0);
262 m_CrossPainter = QPainterPath(startPoint);
263 m_CrossPainter.lineTo(endPoint);
264 m_CrossPainter.moveTo(startPoint2);
265 m_CrossPainter.lineTo(endPoint2);
266 m_Cross->setPath(m_CrossPainter);
270 m_CrossPainter = QPainterPath(startPoint2);
271 m_CrossPainter.lineTo(endPoint2);
272 m_Cross->setPath(m_CrossPainter);
275 m_pTransitionInfoPoint->setRect(
276 newPosition.x(), newPosition.y() - m_InfoPointRadius, m_InfoPointRadius, m_InfoPointRadius);
277 m_Cross->resetTransform();
278 m_Cross->setPos(newPosition.x() + m_InfoPointRadius / 2,
279 newPosition.y() - m_InfoPointRadius / 2);
280 m_Cross->rotate(labelAngle * 180 /
pi);
281 m_InfoText->setPos(newPosition.x() + m_InfoPointRadius, newPosition.y() - m_InfoPointRadius);
282 m_InfoBox->setRect(newPosition.x() + m_InfoPointRadius,
283 newPosition.y() - m_InfoPointRadius,
284 m_InfoText->boundingRect().width(),
285 m_InfoText->boundingRect().height());
289 StateChartGraphEdge::setArrowHeadPosition(QPointF headLineSegmentStart, QPointF headLineSegmentEnd)
293 QPointF arrowVector = headLineSegmentEnd - headLineSegmentStart;
295 double lengthLastSegment = calcLengthOfLine(headLineSegmentStart, headLineSegmentStart);
296 arrowVector.setX(arrowVector.x() / lengthLastSegment);
297 arrowVector.setY(arrowVector.y() / lengthLastSegment);
301 arrowHead << headLineSegmentEnd;
302 arrowHead << QPointF(
303 headLineSegmentEnd.x() - m_ArrowScale * (arrowVector.x() - arrowVector.y()),
304 headLineSegmentEnd.y() - m_ArrowScale * (arrowVector.y() + arrowVector.x()));
305 arrowHead << QPointF(
306 headLineSegmentEnd.x() - m_ArrowScale * (arrowVector.x() + arrowVector.y()),
307 headLineSegmentEnd.y() - m_ArrowScale * (arrowVector.y() - arrowVector.x()));
310 m_Arrow->setPolygon(arrowHead);
316 float xDiff = end.first - start.first;
317 float yDiff = end.second - start.second;
318 return sqrt(pow(xDiff, 2) + pow(yDiff, 2));
322 StateChartGraphEdge::calcLengthOfLine(QPointF start, QPointF end)
324 return calcLengthOfLine(
floatPair(start.x(), start.y()),
floatPair(end.x(), end.y()));
327 std::vector<floatPair>
328 StateChartGraphEdge::calcControlPoints(Agedge_t* gvGraphEdge)
330 std::vector<floatPair> controlPoints;
333 std::string position(agget(gvGraphEdge,
const_cast<char*
>(
"pos")));
334 size_t oldDividerPos;
338 dividerPos = position.find_first_of(
",");
339 assert(dividerPos != std::string::npos);
340 oldDividerPos = dividerPos;
344 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
345 assert(dividerPos != std::string::npos);
346 std::string stringEndX = position.substr(oldDividerPos + 1, dividerPos);
347 oldDividerPos = dividerPos;
352 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
353 assert(dividerPos != std::string::npos);
354 std::string stringEndY = position.substr(oldDividerPos + 1, dividerPos);
355 oldDividerPos = dividerPos;
360 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
361 assert(dividerPos != std::string::npos);
362 std::string stringStartX = position.substr(oldDividerPos + 1, dividerPos);
363 oldDividerPos = dividerPos;
368 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
369 std::string stringStartY = position.substr(oldDividerPos + 1, dividerPos);
370 oldDividerPos = dividerPos;
376 while (oldDividerPos != std::string::npos)
380 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
383 std::string posX = position.substr(oldDividerPos + 1, dividerPos);
384 oldDividerPos = dividerPos;
386 dividerPos = position.find_first_of(
",", oldDividerPos + 1);
387 std::string posY = position.substr(oldDividerPos + 1, dividerPos);
388 oldDividerPos = dividerPos;
390 controlPoint.first = boost::lexical_cast<float>(posX);
391 controlPoint.second = boost::lexical_cast<float>(posY);
392 controlPoints.push_back(controlPoint);
397 return controlPoints;
401 StateChartGraphEdge::calcPath(std::vector<floatPair> controlPoints)
404 m_Path.moveTo(controlPoints[0].first, controlPoints[0].second);
406 if (
int(controlPoints.size()) > 2)
409 for (
int i = 1; i < int(controlPoints.size()) - 1; i += 1)
411 m_Path.quadTo(controlPoints[i].first,
412 controlPoints[i].second,
413 controlPoints[i + 1].first,
414 controlPoints[i + 1].second);
421 m_Path.lineTo(controlPoints[controlPoints.size() - 1].first,
422 controlPoints[controlPoints.size() - 1].second);
456 labelAngle = -labelAngle;
461 labelAngle =
pi + labelAngle;
464 QRectF transitionRect = m_pTransitionLabel->boundingRect();
465 setInfoPointPosition(
466 QPointF(m_pTransitionLabel->pos().x() + transitionRect.width() * cos(labelAngle),
467 m_pTransitionLabel->pos().y() + transitionRect.width() * sin(labelAngle)),
483 labelAngle = -labelAngle;
488 labelAngle =
pi + labelAngle;
491 QRectF transitionRect = m_pTransitionLabel->boundingRect();
492 setInfoPointPosition(
493 QPointF(m_pTransitionLabel->pos().x() + transitionRect.width() * cos(labelAngle),
494 m_pTransitionLabel->pos().y() + transitionRect.width() * sin(labelAngle)),