00001 #include "constants.h"
00002
00003 #include "mainwindow.h"
00004 #include "editor.h"
00005 #include "transition.h"
00006 #include "state.h"
00007 #include "label.h"
00008 #include "commands.h"
00009 #include "dialogs.h"
00010 #include "transforms.h"
00011 #include "stringProcessor.h"
00012 #include "automataCreator.h"
00013
00014 #include <QGraphicsScene>
00015 #include <QEvent>
00016 #include <QGraphicsSceneMouseEvent>
00017 #include <QFontMetrics>
00018 #include <QLineF>
00019 #include <QPolygonF>
00020 #include <QPointF>
00021 #include <QPainterPath>
00022
00023 #include <QTextStream>
00024
00025 #include <math.h>
00026
00027 #include <QtDebug>
00028
00029 #ifdef PERFORMANCE_MEASUREMENT
00030 # include <QTime>
00031 float g_TimeSum = 0;
00032 int g_TimeIterations = 0;
00033 const int g_TimeIterationsCount = 100;
00034 #endif
00035
00036
00037
00038 Transition::Transition(Editor *parent, State *ss, State *es,
00039 bool d)
00040 : editor(parent), startState(ss), endState(es), startPoint(ss->pos()),
00041 dimmed(d), checked(false),
00042 checkedColor(QColor(CheckedColor::r, CheckedColor::g,
00043 CheckedColor::b, CheckedColor::a))
00044 {
00045 setFlag(QGraphicsItem::ItemIsMovable, false);
00046 setFlag(QGraphicsItem::ItemIsSelectable, true);
00047
00048 if (endState)
00049 {
00050 endPoint = endState->pos();
00051 }
00052
00053
00054 edgeLineStyle = editor->edgeLineStyle;
00055 edgeLineWidth = 1;
00056 edgeLineColor = editor->edgeLineColor;
00057 edgeLabelColor = editor->edgeLabelColor;
00058 edgeLabelScale = 1;
00059 edgeLineDblStatus = editor->edgeLineDblStatus;
00060
00061
00062 edgeLineBorderCoef = editor->edgeLineBorderCoef;
00063 edgeLineBorderColor = editor->edgeLineBorderColor;
00064
00065 edgeLineDblCoef = editor->edgeLineDblCoef;
00066 edgeLineDblSep = editor->edgeLineDblSep;
00067
00068
00069 dimEdgeLineStyle = editor->dimEdgeLineStyle;
00070 dimEdgeLineColor = editor->dimEdgeLineColor;
00071 dimEdgeLineCoef = editor->dimEdgeLineCoef;
00072 dimEdgeLabelColor = editor->dimEdgeLabelColor;
00073
00074 m_labelFontSize = (int) (EDGE_LABEL_SIZE * edgeLabelScale * editor->edgeLabelScale);
00075 m_lineWidth = editor->edgeLineWidth * TR_LINE_VIEW_COEF;
00076 if (dimmed)
00077 m_lineWidth *= dimEdgeLineCoef;
00078 else
00079 m_lineWidth *= edgeLineWidth;
00080
00081
00082 m_arrowPoints << QPointF(0,0);
00083
00084 QLineF arrowLine(QPointF(0,0), QPointF(ARROW_LEN, 0));
00085 QLineF normArrowLine = arrowLine.normalVector();
00086 normArrowLine.translate(ARROW_LEN,0);
00087
00088 normArrowLine.setLength(ARROW_WIDTH/2);
00089 m_arrowPoints << normArrowLine.p2();
00090
00091 arrowLine.setLength(ARROW_LEN - 2);
00092 m_arrowPoints << arrowLine.p2();
00093
00094 normArrowLine.setLength(-ARROW_WIDTH/2);
00095 m_arrowPoints << normArrowLine.p2();
00096 }
00097
00098 Transition::~Transition()
00099 {
00100 if (label) delete label;
00101
00102 qDeleteAll(nextLabels.begin(), nextLabels.end());
00103 nextLabels.clear();
00104
00105 DBGLOG("Transition::~Transition");
00106 }
00107
00108 QString Transition::getStartStateName() const
00109 {
00110 Q_ASSERT(startState && "invalid startState!");
00111 return startState->getName();
00112 }
00113
00114 QString Transition::getEndStateName() const
00115 {
00116 Q_ASSERT(getEndState() && "invalid endState!");
00117 return getEndState()->getName();
00118 }
00119
00120 LabelX *Transition::getLabel() const
00121 {
00122 return (label) ? label : NULL;
00123 }
00124
00125 QString Transition::getLabelText() const
00126 {
00127 if (label)
00128 return label->text();
00129 else
00130 return QString("");
00131 }
00132
00133 void Transition::setLabelText(const QString &labelText)
00134 {
00135 prepareGeometryChange();
00136 if (!label)
00137 {
00138 RELLOG("trying to set label text to nonexistent label");
00139 return;
00140 }
00141
00142 label->setText(labelText);
00143 setLabelPosition();
00144 }
00145
00146 void Transition::setLabelPosition(LabelX *pLabel, float pos, bool isLeft, int width, int height)
00147 {
00148 Q_ASSERT(pLabel);
00149
00150 prepareGeometryChange();
00151
00152 QLineF text_v = QLineF(mapToScene(p.pointAtPercent(pos)),mapToScene(p.pointAtPercent(pos+0.1)));
00153 text_v = text_v.normalVector();
00154
00155 text_v.setLength(isLeft ? TEXT_DISTANCE : -TEXT_DISTANCE);
00156
00157 float label_x, label_y;
00158 float correct_x, correct_y;
00159 correct_x = -width/2 +
00160 (text_v.x2() - text_v.x1()) / TEXT_DISTANCE *
00161 width/2;
00162 correct_y = -height/2 +
00163 (text_v.y2() - text_v.y1()) / TEXT_DISTANCE *
00164 height/2;
00165 label_x = text_v.x2() + correct_x;
00166 label_y = text_v.y2() + correct_y;
00167
00168 pLabel->setPos(label_x, label_y);
00169 }
00170
00171 void Transition::setLabelPosition()
00172 {
00173 for (TLabelXList::Iterator labelIt = nextLabels.begin();
00174 labelIt != nextLabels.end();
00175 ++labelIt)
00176 {
00177 setLabelPosition(*labelIt, (*labelIt)->posParam(), (*labelIt)->left(),
00178 (*labelIt)->getWidth(), (*labelIt)->getHeight());
00179 }
00180 }
00181
00182 void Transition::setLabelPos(float pos)
00183 {
00184 if (label) label->setPosParam(pos);
00185 }
00186
00187 float Transition::getLabelPos() const
00188 {
00189 if (label) return label->posParam();
00190 else return DEF_EDGE_LAB_POS;
00191 }
00192
00193 void Transition::addNextLabel(LabelX *pLabel)
00194 {
00195 if (dimmed)
00196 pLabel->setColor(QColor(dimEdgeLabelColor));
00197 else
00198 pLabel->setColor(QColor(edgeLabelColor));
00199 nextLabels << pLabel;
00200 }
00201
00202 void Transition::removeNextLabel(LabelX *pLabel)
00203 {
00204 if (!nextLabels.removeOne(pLabel))
00205 RELLOG("required label was not found!");
00206 }
00207
00208 QPainterPath Transition::createShape(const QPainterPath &path, int bounds) const
00209 {
00210 QPainterPathStroker pathStroker;
00211 pathStroker.setWidth(bounds);
00212
00213 QPainterPath strokePath = pathStroker.createStroke(path);
00214
00215 strokePath.addPolygon(pa);
00216 strokePath.closeSubpath();
00217
00218 if (label && label->text() != "")
00219 {
00220 strokePath.addPolygon(mapFromItem(label, label->boundingRect()));
00221 strokePath.closeSubpath();
00222 }
00223
00224 for (TLabelXList::ConstIterator labelIt = nextLabels.begin();
00225 labelIt != nextLabels.end();
00226 ++labelIt)
00227 {
00228 if ((*labelIt)->text() == "") continue;
00229 strokePath.addPolygon(mapFromItem((*labelIt), (*labelIt)->boundingRect()));
00230 strokePath.closeSubpath();
00231 }
00232
00233 strokePath.setFillRule(Qt::WindingFill);
00234
00235 return strokePath;
00236 }
00237
00238 QPainterPath Transition::shape() const
00239 {
00240 return getClickPath();
00241 }
00242
00243 QRectF Transition::boundingRect() const
00244 {
00245 QRectF rect = getClickPath().boundingRect();
00246
00247 if (label)
00248 rect |= (mapFromItem(label, label->boundingRect())).boundingRect();
00249
00250 for (TLabelXList::ConstIterator labelIt = nextLabels.begin();
00251 labelIt != nextLabels.end();
00252 ++labelIt)
00253 {
00254 rect |= (mapFromItem((*labelIt), (*labelIt)->boundingRect())).boundingRect();
00255 }
00256
00257 rect |= pa.boundingRect();
00258
00259 return rect.adjusted(-5,-5,5,5);
00260 }
00261
00262 void Transition::paintSelectionDecoration(QPainter *painter)
00263 {
00264 if (isSelected())
00265 {
00266 const QColor selectedColor(SelectedColor::r,SelectedColor::g,
00267 SelectedColor::b, SelectedColor::a);
00268 painter->setPen(QPen(selectedColor,1,Qt::DashLine));
00269
00270 painter->strokePath(getSelectionPath(), painter->pen());
00271 }
00272 }
00273
00274 void Transition::paint (QPainter *painter, const QStyleOptionGraphicsItem * , QWidget * )
00275 {
00276 QColor lineC;
00277 Qt::PenStyle lineS;
00278
00279 if (dimmed)
00280 {
00281 lineS = dimEdgeLineStyle;
00282 lineC = dimEdgeLineColor;
00283 }
00284 else
00285 {
00286 lineS = edgeLineStyle;
00287 lineC = edgeLineColor;
00288 }
00289
00290 if (checked)
00291 {
00292 painter->setPen(QPen(checkedColor, m_lineWidth, lineS));
00293 }
00294 else
00295 {
00296 painter->setPen(QPen(lineC, m_lineWidth, lineS));
00297 }
00298
00299 painter->setBrush(Qt::NoBrush);
00300 painter->strokePath(p, painter->pen());
00301
00302
00303 if (checked)
00304 painter->setBrush(checkedColor);
00305 else
00306 painter->setBrush(lineC);
00307
00308 painter->drawPolygon(pa);
00309
00310 paintSelectionDecoration(painter);
00311
00312 #ifdef TESTING_PAINTING
00313 # ifdef TESTING_BOUNDING_RECT_PAINTING
00314 painter->setBrush(QBrush(QColor(50,255,0,100)));
00315 painter->fillRect(boundingRect(), painter->brush());
00316 # endif
00317
00318 painter->setBrush(QBrush(QColor(0,0,255,150)));
00319 painter->fillPath(shape(), painter->brush());
00320 #endif
00321 }
00322
00323 void Transition::setDimmed(bool dim)
00324 {
00325 if (dimmed == dim) return;
00326
00327 dimmed = dim;
00328
00329 if (dimmed)
00330 m_lineWidth = m_lineWidth * dimEdgeLineCoef/edgeLineWidth;
00331 else
00332 m_lineWidth = m_lineWidth * edgeLineWidth/dimEdgeLineCoef;
00333
00334 QColor color = QColor(dimmed ? dimEdgeLabelColor : edgeLabelColor);
00335
00336 if (label) label->setColor(color);
00337
00338 for (TLabelXList::ConstIterator labelIt = nextLabels.begin();
00339 labelIt != nextLabels.end();
00340 ++labelIt)
00341 {
00342 (*labelIt)->setColor(color);
00343 }
00344
00345 createStrokes(p);
00346 }
00347
00348 bool Transition::isDimmed()
00349 {
00350 return dimmed;
00351 }
00352
00353 void Transition::setChecked(bool ch)
00354 {
00355 checked = ch;
00356
00357 QColor color = (ch) ? checkedColor :
00358 dimmed ? QColor(dimEdgeLabelColor) : QColor(edgeLabelColor);
00359
00360 if (label) label->setColor(color);
00361
00362 for (TLabelXList::ConstIterator labelIt = nextLabels.begin();
00363 labelIt != nextLabels.end();
00364 ++labelIt)
00365 {
00366 (*labelIt)->setColor(color);
00367 }
00368
00369 update();
00370 }
00371
00372 void Transition::setSelected(bool sel)
00373 {
00374 if (label && label->text() != "")
00375 {
00376 label->setSelected(sel);
00377 }
00378
00379 foreach(LabelX *label, nextLabels)
00380 {
00381 label->setSelected(sel);
00382 }
00383
00384 QGraphicsItem::setSelected(sel);
00385 }
00386
00387 void Transition::mousePressEvent(QGraphicsSceneMouseEvent *event)
00388 {
00389 DBGLOG_ME("called");
00390 m_lastMouseClickType = eMouseNoClick;
00391 setChecked();
00392 if (event->button() == Qt::RightButton)
00393 {
00394 m_lastMouseClickType = eMouseRightClick;
00395 }
00396 }
00397
00398 void Transition::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
00399 {
00400 DBGLOG_ME("Transition::mouseDoubleClickEvent");
00401 if (event->button() == Qt::LeftButton && editor->getAction() == Editor::eSelection)
00402 {
00403 m_lastMouseClickType = eMouseDoubleClick;
00404 setChecked();
00405 }
00406 }
00407
00408 void Transition::setStartState(State *state)
00409 {
00410 startState = state;
00411 adjust();
00412 }
00413
00414 void Transition::setEndState(State *state)
00415 {
00416 if (endState)
00417 endState = state;
00418 else RELLOG("No endState available!");
00419 adjust();
00420 }
00421
00422
00423 bool Transition::getVCParams(QTextStream &out, EdgePrevParams &prevParams) const
00424 {
00425 bool stChanged = false;
00426 if (!dimmed){
00427 if (edgeLineStyle != prevParams.edgeLineStyle){
00428 prevParams.edgeLineStyle = edgeLineStyle;
00429 stChanged = true;
00430 if (edgeLineStyle != editor->edgeLineStyle){
00431 out << endl << "\\ChgEdgeLineStyle{";
00432 out << trLineStyle(edgeLineStyle);
00433 out << "}" << endl;
00434 }
00435 else{
00436 out << endl << "\\RstEdgeLineStyle";
00437 }
00438 }
00439
00440 if (edgeLineWidth != prevParams.edgeLineWidth){
00441 stChanged = true;
00442 prevParams.edgeLineWidth = edgeLineWidth;
00443 if (edgeLineWidth != 1)
00444 out << endl << "\\ChgEdgeLineWidth{" << edgeLineWidth << "}";
00445 else
00446 out << endl << "\\RstEdgeLineWidth";
00447 }
00448
00449 if (edgeLineColor != prevParams.edgeLineColor){
00450 stChanged = true;
00451 prevParams.edgeLineColor = edgeLineColor;
00452 if (edgeLineColor != editor->edgeLineColor)
00453 out << endl << "\\ChgEdgeLineColor{" << edgeLineColor.toLower() << "}";
00454 else
00455 out << endl << "\\RstEdgeLineColor";
00456 }
00457
00458 if (edgeLabelColor != prevParams.edgeLabelColor){
00459 stChanged = true;
00460 prevParams.edgeLabelColor = edgeLabelColor;
00461 if (edgeLabelColor != editor->edgeLabelColor)
00462 out << endl << "\\ChgEdgeLabelColor{" << edgeLabelColor.toLower() << "}";
00463 else
00464 out << endl << "\\RstEdgeLabelColor";
00465 }
00466
00467 if (edgeLabelScale != prevParams.edgeLabelScale){
00468 stChanged = true;
00469 prevParams.edgeLabelScale = edgeLabelScale;
00470 if (edgeLabelScale != 1)
00471 out << endl << "\\ChgEdgeLabelScale{" << edgeLabelScale << "}";
00472 else
00473 out << endl << "\\RstEdgeLabelScale";
00474 }
00475
00476 if (edgeLineDblStatus != prevParams.edgeLineDblStatus){
00477 stChanged = true;
00478 prevParams.edgeLineDblStatus = edgeLineDblStatus;
00479 out << endl << (edgeLineDblStatus ? "\\EdgeLineDouble" : "\\EdgeLineSimple");
00480 }
00481 }
00482 else{
00483 if (dimEdgeLineStyle != prevParams.dimEdgeLineStyle ||
00484 dimEdgeLineColor != prevParams.dimEdgeLineColor ||
00485 dimEdgeLineCoef != prevParams.dimEdgeLineCoef ||
00486 dimEdgeLabelColor != prevParams.dimEdgeLabelColor ){
00487 stChanged = true;
00488 prevParams.dimEdgeLineStyle = dimEdgeLineStyle;
00489 prevParams.dimEdgeLineColor = dimEdgeLineColor;
00490 prevParams.dimEdgeLineCoef = dimEdgeLineCoef;
00491 prevParams.dimEdgeLabelColor = dimEdgeLabelColor;
00492 out << endl <<"\\FixDimEdge{" << trLineStyle(dimEdgeLineStyle) << "}"
00493 "{" << dimEdgeLineCoef << "}"
00494 "{" << dimEdgeLineColor.toLower() << "}"
00495 "{" << dimEdgeLabelColor.toLower() << "}";
00496 }
00497 }
00498 if (edgeLineDblStatus){
00499 if (edgeLineBorderCoef != prevParams.edgeLineBorderCoef ||
00500 edgeLineBorderColor != prevParams.edgeLineBorderColor){
00501 stChanged = true;
00502 prevParams.edgeLineBorderCoef = edgeLineBorderCoef;
00503 prevParams.edgeLineBorderColor = edgeLineBorderColor;
00504 out << endl << "\\FixEdgeBorder{" << edgeLineBorderCoef << "}"
00505 "{" << edgeLineBorderColor.toLower() << "}";
00506 }
00507
00508 if (edgeLineDblCoef != prevParams.edgeLineDblCoef ||
00509 edgeLineDblSep != prevParams.edgeLineDblSep){
00510 stChanged = true;
00511 prevParams.edgeLineDblCoef = edgeLineDblCoef;
00512 prevParams.edgeLineDblSep = edgeLineDblSep;
00513 out << endl << "\\FixEdgeLineDouble{" << edgeLineDblCoef << "}"
00514 "{" << edgeLineDblSep << "}";
00515 }
00516 }
00517
00518 if (stChanged) out << endl;
00519
00520 return stChanged;
00521 }
00522
00523 QString Transition::getNextLabelsVCCommand() const
00524 {
00525 QString command = "";
00526
00527
00528 int sbs_counter = 0;
00529 for(TLabelXList::ConstIterator labelIt = nextLabels.begin();
00530 labelIt != nextLabels.end();
00531 ++labelIt)
00532 {
00533 command += (sbs_counter % SBS_LABELS) ? " " : "\n";
00534 command += "\\Label";
00535 command += (*labelIt)->left() ? "L" : "R";
00536
00537 if ((*labelIt)->posParam() != DEF_EDGE_LAB_POS)
00538 command += "[" + QString("%1").arg((*labelIt)->posParam()) + "]";
00539
00540 command += "{" + (*labelIt)->text() + "}";
00541 sbs_counter++;
00542 }
00543 if (!nextLabels.isEmpty()) command += "\n";
00544 return command;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 QPainterPath pClick1(p.translated(CLICK_BOUNDS*sin(angle), CLICK_BOUNDS*cos(angle)));
00605 QPainterPath pClick2(p.translated(-CLICK_BOUNDS*sin(angle), -CLICK_BOUNDS*cos(angle)));
00606
00607 QPainterPath pSel1(p.translated(SELECTION_BOUNDS*sin(angle), SELECTION_BOUNDS*cos(angle)));
00608 QPainterPath pSel2(p.translated(-SELECTION_BOUNDS*sin(angle), -SELECTION_BOUNDS*cos(angle)));
00609
00610
00611 pClick1.connectPath(pClick2.toReversed());
00612 m_clickArea = pClick1.toFillPolygon();
00613
00614 pSel1.connectPath(pSel2.toReversed());
00615 m_selectionArea = pSel1.toFillPolygon();
00616 #endif
00617 }*/
00618
00619 void Transition::createStrokes(const QPainterPath &path)
00620 {
00621 #ifdef MEASURE_CREATE_STROKES
00622 QTime timer;
00623 timer.start();
00624 #endif
00625
00626 #if 1
00627 m_clickPath = createShape(path, ((int)m_lineWidth < CLICK_BOUNDS*2) ? CLICK_BOUNDS*2 : (int)m_lineWidth);
00628 m_selectionPath = createShape(path, (int) m_lineWidth + SELECTION_BOUNDS);
00629 #else
00630 if (p.elementCount() < 2)
00631 return;
00632
00633 QPointF startP = p.pointAtPercent(0);
00634 QPointF endP = p.pointAtPercent(1);
00635
00636 QLineF angleLine(startP, endP);
00637 qreal angle = angleLine.angle() * M_PI/180;
00638
00639
00640
00641 QPainterPath pClick1(p.translated(CLICK_BOUNDS*sin(angle), CLICK_BOUNDS*cos(angle)));
00642 QPainterPath pClick2(p.translated(-CLICK_BOUNDS*sin(angle), -CLICK_BOUNDS*cos(angle)));
00643
00644 QPainterPath pSel1(p.translated(SELECTION_BOUNDS*sin(angle), SELECTION_BOUNDS*cos(angle)));
00645 QPainterPath pSel2(p.translated(-SELECTION_BOUNDS*sin(angle), -SELECTION_BOUNDS*cos(angle)));
00646
00647
00648 pClick1.connectPath(pClick2.toReversed());
00649 m_clickPath = pClick1;
00650
00651 pSel1.connectPath(pSel2.toReversed());
00652 m_selectionPath = pSel1;
00653 #endif
00654
00655 #ifdef MEASURE_CREATE_STROKES
00656 g_TimeSum += timer.elapsed();
00657 g_TimeIterations++;
00658 if (g_TimeIterations == g_TimeIterationsCount)
00659 {
00660 RELLOG("PM:" << "takes" << g_TimeSum << "ms on" << g_TimeIterationsCount << "iterations");
00661 g_TimeIterations = 0;
00662 g_TimeSum = 0;
00663 }
00664 #endif
00665 }
00666
00667 const QPainterPath& Transition::getClickPath() const
00668 {
00669 return m_clickPath;
00670 }
00671
00672 const QPainterPath& Transition::getSelectionPath() const
00673 {
00674 return m_selectionPath;
00675 }
00676
00677 QPolygonF Transition::getArrowPolygon(const QPainterPath &path)
00678 {
00679 QPointF p1 = path.pointAtPercent(1);
00680 QPointF p2 = path.pointAtPercent(path.percentAtLength(path.length()-ARROW_LEN));
00681 QLineF arrowAngleLine(p1, p2);
00682 qreal angle = arrowAngleLine.angle();
00683
00684 QMatrix matrix;
00685 matrix.rotate(-angle);
00686 QPolygonF arrowPoints = matrix.map(m_arrowPoints);
00687
00688 arrowPoints.translate(path.pointAtPercent(1));
00689
00690 return arrowPoints;
00691 }
00692
00693 QPolygonF Transition::findIntersectedPoints(const QPolygonF &curve, const QPolygonF &polygon,
00694 const Transition::EIntersectionFindMethod method)
00695 {
00696 QPolygonF intersectedPoints;
00697
00698 if (curve.size() < 2 || polygon.size() < 2)
00699 {
00700 Q_ASSERT(0 && "bad polygon given");
00701 RELLOG("bad polygons given (small size) !!!");
00702 return intersectedPoints;
00703 }
00704
00705 QLineF curveLine, polyLine;
00706 QPointF intersectedPoint, tmpPoint;
00707 QPolygonF::ConstIterator curveIt1 = curve.end()-1;
00708 QPolygonF::ConstIterator curveIt2 = curve.end()-2;
00709 QPolygonF::ConstIterator polyIt;
00710
00711 int found = 0;
00712
00713 while (curveIt2 >= curve.begin())
00714 {
00715 curveLine.setPoints(*curveIt1, *curveIt2);
00716
00717 polyIt = polygon.begin();
00718 polyLine.setP2(*polyIt++);
00719
00720 while (polyIt < polygon.end())
00721 {
00722 polyLine.setP1(polyLine.p2());
00723 polyLine.setP2(*polyIt++);
00724
00725 if (polyLine.intersect(curveLine, &intersectedPoint) == QLineF::BoundedIntersection)
00726 {
00727 tmpPoint = intersectedPoint;
00728 curveIt1--;
00729
00730 while (curveIt1 > curveIt2)
00731 {
00732 curveLine.setPoints(*curveIt1--, *curveIt2);
00733 if (polyLine.intersect(curveLine, &intersectedPoint) == QLineF::BoundedIntersection)
00734 {
00735 tmpPoint = intersectedPoint;
00736 }
00737 }
00738
00739
00740 if (intersectedPoints.empty() || intersectedPoints.last() != tmpPoint)
00741 {
00742 intersectedPoints << tmpPoint;
00743 found++;
00744
00745 if (method == eFIND_FIRST ||
00746 (method == eFIND_TWO && found == 2))
00747 break;
00748 }
00749 }
00750 }
00751
00752 if ((method == eFIND_FIRST && found == 1) ||
00753 (method == eFIND_TWO && found == 2))
00754 break;
00755
00756 curveIt2--;
00757 }
00758
00759 if (found == 0)
00760 DBGLOG("no intersected point found");
00761
00762 #ifdef TESTING_ARROW_POINTS
00763 DBGLOG(DBGPAR(intersectedPoints));
00764 #endif
00765
00766 return intersectedPoints;
00767 }
00768
00769 void Transition::setEdgeLabelScale(float labelScale)
00770 {
00771 if (edgeLabelScale == labelScale) return;
00772
00773 prepareGeometryChange();
00774
00775 m_labelFontSize = (int) (m_labelFontSize * labelScale/edgeLabelScale);
00776 edgeLabelScale = labelScale;
00777 if (label)
00778 {
00779 label->setFontSize(m_labelFontSize);
00780 }
00781 for (TLabelXList::Iterator labelIt = nextLabels.begin();
00782 labelIt != nextLabels.end();
00783 ++labelIt)
00784 {
00785 (*labelIt)->setFontSize(m_labelFontSize);
00786 }
00787
00788 setLabelPosition();
00789 }
00790
00791 void Transition::setEdgeLineWidth(float lineWidth)
00792 {
00793 if (edgeLineWidth == lineWidth) return;
00794
00795 prepareGeometryChange();
00796
00797 if (!dimmed)
00798 m_lineWidth = m_lineWidth * lineWidth/edgeLineWidth;
00799 edgeLineWidth = lineWidth;
00800
00801 if (!dimmed)
00802 createStrokes(p);
00803
00804 }
00805
00806 void Transition::setDimEdgeLineCoef(float lineCoef)
00807 {
00808 if (dimEdgeLineCoef == lineCoef) return;
00809
00810 prepareGeometryChange();
00811
00812 if (dimmed)
00813 m_lineWidth = m_lineWidth * lineCoef/dimEdgeLineCoef;
00814 dimEdgeLineCoef = lineCoef;
00815
00816 if (dimmed)
00817 createStrokes(p);
00818 }
00819
00820
00821
00822 QString Transition::getSourceState() const
00823 {
00824 return getStartStateName();
00825 }
00826
00827 QString Transition::getDestinationState() const
00828 {
00829
00830 return getEndStateName();
00831 }
00832
00833 void Transition::showErrorReport(const QString &reportText) const
00834 {
00835 QString report = "Incorrect transition definition (transition between states \""
00836 + getSourceState() + "\" and \"" + getDestinationState() + "\")<br>"
00837 + reportText;
00838 ReportDialog rd(report, editor);
00839 rd.exec();
00840 }
00841
00842 bool Transition::getCharacters(ITransition::TCharSet &characters,
00843 const ITransition::TCharSet &alphabet,
00844 const QString &alphabetSymbol,
00845 const QString &epsilonSymbol) const
00846 {
00847 LabelSyntaxChecker syntaxChecker(alphabet, alphabetSymbol, epsilonSymbol);
00848 bool empty = true;
00849
00850 if (label)
00851 {
00852 if (!syntaxChecker.checkSyntax(label->getCharacterList()))
00853 {
00854 showErrorReport(syntaxChecker.getReport());
00855 return false;
00856 }
00857
00858 characters |= syntaxChecker.getCharacters();
00859 empty = empty && (syntaxChecker.getPattern() == LabelSyntaxChecker::eEmptyPattern);
00860 }
00861
00862 for(TLabelXList::ConstIterator labelIt = nextLabels.begin();
00863 labelIt != nextLabels.end();
00864 ++labelIt)
00865 {
00866 if (!syntaxChecker.checkSyntax((*labelIt)->getCharacterList()))
00867 {
00868 showErrorReport(syntaxChecker.getReport());
00869 return false;
00870 }
00871
00872 characters |= syntaxChecker.getCharacters();
00873 empty = empty || (syntaxChecker.getPattern() == LabelSyntaxChecker::eEmptyPattern);
00874 }
00875
00876 if (empty)
00877 {
00878 showErrorReport("No symbols for transition.");
00879 return false;
00880 }
00881
00882 return true;
00883 }
00884
00885 void Transition::getCharactersOccurences(ITransition::TCharSet &characters) const
00886 {
00887 QStringList occurences;
00888
00889 if (label)
00890 {
00891 occurences = label->getCharacters();
00892 dismemberCharacters(occurences, characters);
00893 }
00894
00895 for(TLabelXList::ConstIterator labelIt = nextLabels.begin();
00896 labelIt != nextLabels.end();
00897 ++labelIt)
00898 {
00899 occurences = (*labelIt)->getCharacters();
00900 dismemberCharacters(occurences, characters);
00901 }
00902 }
00903
00904 void Transition::dismemberCharacters(const QStringList &occurences,
00905 ITransition::TCharSet &characters) const
00906 {
00907 foreach(const QString &character, occurences)
00908 {
00909
00910 if (character == "," || character == "-" || character == "\\{" || character == "\\}") continue;
00911
00912 characters << character;
00913 }
00914 }
00915
00916