예제 #1
0
/**
 * 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);
    }
}