TransitionGraphic::TransitionGraphic(StateBoxGraphic *parentGraphic, StateBoxGraphic *targetGraphic, SCTransition * t) : QGraphicsObject(NULL), _transitionDM(t), _lineSegments(), _parentStateGraphic(parentGraphic), _targetStateGraphic(targetGraphic) { this->setFlag(QGraphicsItem::ItemIsMovable, false); TransitionAttributes::TransitionPathAttribute * p = dynamic_cast<TransitionAttributes::TransitionPathAttribute *> ( t->attributes.value("path")); QList<QPointF> pointList = p->asQPointFList(); if ( pointList.count() < 2 && targetGraphic != NULL ) { // this path is new, anchor each end to the source and target states // find the orientation of the parent and target graphics to determine which sides to anchor to. int sourceSide=0; int targetSide=0; getClosestSides( & sourceSide, & targetSide); QPointF sourceAnchor = _parentStateGraphic->mapFromScene( _parentStateGraphic->getSideCenterPointInSceneCoord(sourceSide)); QPointF targetAnchor = _parentStateGraphic->mapFromScene( _targetStateGraphic->getSideCenterPointInSceneCoord(targetSide)); SelectableLineSegmentGraphic * segment = new SelectableLineSegmentGraphic(sourceAnchor,sourceAnchor, targetAnchor, t); segment->setParentItem(_parentStateGraphic); _lineSegments.append(segment); connect ( segment, SIGNAL(startEndMoved(QPointF)), parentGraphic, SLOT(handleTransitionLineStartMoved(QPointF))); connect(segment, SIGNAL(updateModel()), this, SLOT(updateModel())); segment->setTerminator(true); } else if ( pointList.count() == 2 ) { SelectableLineSegmentGraphic * segment = new SelectableLineSegmentGraphic(pointList[0], pointList[0], pointList[1], t); segment->setParentItem(parentGraphic); _lineSegments.append(segment); // connect the parent state-graphic's slots to the new transition graphic's signals connect ( segment, SIGNAL(startEndMoved(QPointF)), parentGraphic, SLOT(handleTransitionLineStartMoved(QPointF))); connect(segment, SIGNAL(updateModel()), this, SLOT(updateModel())); segment->setTerminator(true); } else { SelectableLineSegmentGraphic * lastSegment=NULL; for (int i = 0 ; i < pointList.count() - 1 ; i ++) { SelectableLineSegmentGraphic * segment = new SelectableLineSegmentGraphic( pointList[i+0], pointList[i+0], pointList[i+1], t); segment->setParentItem(parentGraphic); _lineSegments.append(segment); connect ( segment, SIGNAL(startEndMoved(QPointF)), parentGraphic, SLOT(handleTransitionLineStartMoved(QPointF))); connect(segment, SIGNAL(updateModel()), this, SLOT(updateModel())); lastSegment = segment; } lastSegment->setTerminator(true); } }
/** * @brief SCGraphicsView::connectTransition * @param trans * * calls all graphics related connects for transition graphics, their elbows, and the transition deconstructors * calls all data model/attribute connects for sctransition to transitiongraphics * calls all data model/attribute connects for sctextblock of the transition to the selectable text block of the transition * additionally, repositions the anchors to their target states * */ void SCGraphicsView::connectTransition(SCTransition* trans) { SCState* parentState = trans->parentSCState(); SCState* targetState = trans->targetState(); StateBoxGraphic* parentGraphic = _hashStateToGraphic.value(parentState); StateBoxGraphic* targetGraphic = _hashStateToGraphic.value(targetState); TransitionGraphic* transGraphic = _hashTransitionToGraphic.value(trans); // set the connects for the transition graphic connect(trans, SIGNAL(markedForDeletion(QObject*)), this, SLOT(handleTransitionDeleted(QObject*))); connect(transGraphic, SIGNAL(destroyed(QObject*)), this, SLOT(handleTransitionGraphicDeleted(QObject*))); // create the connection to automatically move anchor elbows when state graphics are moved. connect(parentGraphic, SIGNAL(stateBoxMoved(QPointF)), transGraphic, SLOT(handleParentStateGraphicMoved(QPointF))); connect(targetGraphic, SIGNAL(stateBoxMoved(QPointF)), transGraphic, SLOT(handleTargetStateGraphicMoved(QPointF))); // additionally snap the anchors when done moving the source and sink connect(parentGraphic, SIGNAL(stateBoxReleased()), transGraphic, SLOT(handleParentStateGraphicReleased())); connect(targetGraphic, SIGNAL(stateBoxReleased()), transGraphic, SLOT(handleTargetStateGraphicReleased())); // snap the anchors when done RESIZING connect(parentGraphic, SIGNAL(cornerReleased()), transGraphic, SLOT(handleParentStateGraphicResizedReleased())); connect(targetGraphic, SIGNAL(cornerReleased()), transGraphic, SLOT(handleTargetStateGraphicResizedReleased())); connect(transGraphic->getSourceAnchor(),SIGNAL(anchorMoved(QPointF)),parentGraphic,SLOT(handleTransitionLineStartMoved(QPointF))); // state box will handle snapping the source elbow/anchor to its border instead of standard movement connect(transGraphic->getSinkAnchor(),SIGNAL(anchorMoved(QPointF)),targetGraphic,SLOT(handleTransitionLineEndMoved(QPointF))); // state box will handle snapping the source elbow/anchor to its border instead of standard movement //qDebug() << "hooking anchor to state graphic: " << _targetStateGraphic->objectName(); // do this to set closest wall from default emit transGraphic->getSourceAnchor()->anchorMoved(parentGraphic->mapToScene(transGraphic->getSourceAnchor()->pos())); emit transGraphic->getSinkAnchor()->anchorMoved(parentGraphic->mapToScene(transGraphic->getSinkAnchor()->pos())); // create the connect to automatically move anchor elbows when state graphics are moved. connect(parentGraphic, SIGNAL(stateBoxResized(QRectF, QRectF, int)),transGraphic, SLOT(handleParentStateGraphicResized(QRectF, QRectF, int))); connect(targetGraphic, SIGNAL(stateBoxResized(QRectF, QRectF, int)),transGraphic, SLOT(handleTargetStateGraphicResized(QRectF, QRectF, int))); // connect this state box's grand parents update anchors when they are resized StateBoxGraphic* grandParentGraphic = parentGraphic->parentItemAsStateBoxGraphic(); bool isSibling = false; while(grandParentGraphic) { connect(grandParentGraphic, SIGNAL(stateBoxResized(QRectF, QRectF, int)),transGraphic, SLOT(handleGrandParentStateGraphicResized(QRectF, QRectF, int))); connect(grandParentGraphic, SIGNAL(stateBoxReleased()), transGraphic, SLOT(handleParentStateGraphicReleased())); // this is a special case of connect for the transition // we connect a sink anchor to stay in place, unless the target graphic is a sibling of the source graphic // if the two are siblings, the anchor is already updated because the source and target are moving together if(grandParentGraphic->childItems().contains(transGraphic->getTargetStateGraphic()) && !isSibling) { isSibling = true; } if(!isSibling) { connect(grandParentGraphic, SIGNAL(stateBoxMoved(QPointF)), transGraphic, SLOT(handleParentStateGraphicMoved(QPointF))); } grandParentGraphic = grandParentGraphic->parentItemAsStateBoxGraphic(); } // connect the target state box's grand parents to update the target anchors when they are resized StateBoxGraphic* grandParentTargetGraphic = targetGraphic->parentItemAsStateBoxGraphic(); while(grandParentTargetGraphic) { connect(grandParentTargetGraphic, SIGNAL(stateBoxResized(QRectF, QRectF, int)),transGraphic, SLOT(handleGrandParentTargetStateGraphicResized(QRectF, QRectF, int))); grandParentTargetGraphic = grandParentTargetGraphic->parentItemAsStateBoxGraphic(); } // connect the event name data model to the text block TransitionStringAttribute* eventName = trans->getTransStringAttr("event"); connect(eventName, SIGNAL(changed(TransitionStringAttribute*)), transGraphic, SLOT(handleAttributeChanged(TransitionStringAttribute*))); // when the transition graphic emits clicked, also emit it for the sctransition connect(transGraphic, SIGNAL(clicked(SCTransition*)), trans, SIGNAL(clicked(SCTransition*))); // connect the text block graphic of this transition to the data model connect(trans->getEventTextBlock()->getFontFamilyAttr(), SIGNAL(changed(FontFamilyAttribute*)), transGraphic->getEventTextGraphic(), SLOT(handleFontChanged(FontFamilyAttribute*))); connect(trans->getEventTextBlock()->getFontSizeAttr(), SIGNAL(changed(FontSizeAttribute*)), transGraphic->getEventTextGraphic(), SLOT(handleFontChanged(FontSizeAttribute*))); connect(trans->getEventTextBlock()->getFontBoldAttr(), SIGNAL(changed(FontBoldAttribute*)), transGraphic->getEventTextGraphic(), SLOT(handleFontChanged(FontBoldAttribute*))); }