/** * Sets the first widget in the association using the current widget. * If the widget can't be associated using the current type of association, * an error is shown and the widget isn't set. * Otherwise, the temporal visual association is created and the mouse * tracking is enabled, so move events will be delivered. */ void ToolBarStateAssociation::setFirstWidget() { UMLWidget* widget = currentWidget(); Uml::AssociationType::Enum type = getAssociationType(); if (!AssocRules::allowAssociation(type, widget)) { //TODO improve error feedback: tell the user what are the valid type of associations for //that widget KMessageBox::error(0, i18n("Incorrect use of associations."), i18n("Association Error")); return; } //set up position QPoint pos; pos.setX(widget->x() + (widget->width() / 2)); pos.setY(widget->y() + (widget->height() / 2)); //TODO why is this needed? m_pUMLScene->setPos(pos); m_firstWidget = widget; m_associationLine = new QGraphicsLineItem(); m_pUMLScene->addItem(m_associationLine); m_associationLine->setLine(pos.x(), pos.y(), pos.x(), pos.y()); m_associationLine->setPen(QPen(m_pUMLScene->lineColor(), m_pUMLScene->lineWidth(), Qt::DashLine)); m_associationLine->setVisible(true); m_pUMLScene->activeView()->viewport()->setMouseTracking(true); }
/** * Moves the point or line if active. */ void AssociationLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { UMLScene* scene = m_associationWidget->umlScene(); QPointF oldPos = event->scenePos(); QPointF newPos( scene->snappedX(oldPos.x()), scene->snappedY(oldPos.y()) ); // Prevent the moving vertex from disappearing underneath a widget // (else there's no way to get it back.) UMLWidget *onW = scene->widgetAt(newPos); if (onW && onW->baseType() != WidgetBase::wt_Box) { // boxes are transparent const qreal pX = newPos.x(); const qreal pY = newPos.y(); const qreal wX = onW->x(); const qreal wY = onW->y(); const qreal wWidth = onW->width(); const qreal wHeight = onW->height(); if (pX > wX && pX < wX + wWidth) { const qreal midX = wX + wWidth / 2.0; if (pX <= midX) newPos.setX(wX); else newPos.setX(wX + wWidth); } if (pY > wY && pY < wY + wHeight) { const qreal midY = wY + wHeight / 2.0; if (pY <= midY) newPos.setY(wY); else newPos.setY(wY + wHeight); } } if (m_activePointIndex != -1) { // Move a single point (snap behaviour) setPoint(m_activePointIndex, newPos); } else if (m_activeSegmentIndex != -1 && !isEndSegmentIndex(m_activeSegmentIndex)) { // Move a segment (between two points, snap behaviour not implemented) QPointF delta = event->scenePos() - event->lastScenePos(); setPoint(m_activeSegmentIndex, m_points[m_activeSegmentIndex] + delta); setPoint(m_activeSegmentIndex + 1, m_points[m_activeSegmentIndex + 1] + delta); } }