/**
 * Sets the first object of the message using the specified object.
 * The temporal visual message is created and mouse tracking enabled, so
 * mouse events will be delivered.
 *
 * @param firstObject The first object of the message.
 */
void ToolBarStateMessages::setFirstWidget(ObjectWidget* firstObject)
{
    m_firstObject = firstObject;
    Uml::Sequence_Message_Type msgType = getMessageType();

    if (msgType ==  Uml::sequence_message_found && xclick!=0 && yclick!=0) {
        MessageWidget* message = new MessageWidget(m_pUMLScene, m_firstObject,xclick, yclick, msgType);
        cleanMessage();
        m_pUMLScene->getMessageList().append(message);

        xclick = 0;
        yclick = 0;

        FloatingTextWidget *ft = message->floatingTextWidget();
        //TODO cancel doesn't cancel the creation of the message, only cancels setting an operation.
        //Shouldn't it cancel also the whole creation?
        ft->showOperationDialog();
        message->setTextPosition();
        m_pUMLScene->getWidgetList().append(ft);

        UMLApp::app()->document()->setModified();
    }
    else {
        m_messageLine = new UMLSceneLine(m_pUMLScene->canvas());
        m_messageLine->setPoints(m_pMouseEvent->x(), m_pMouseEvent->y(), m_pMouseEvent->x(), m_pMouseEvent->y());
        m_messageLine->setPen(QPen(m_pUMLScene->lineColor(), m_pUMLScene->lineWidth(), Qt::DashLine));

        m_messageLine->setVisible(true);

        m_pUMLScene->viewport()->setMouseTracking(true);
    }
}
/**
 * Sets the second object of the message using the specified widget and
 * creates the message.
 * The association is created and added to the view. The dialog to select
 * the operation of the message is shown.
 *
 * @param secondObject The second object of the message.
 * @param messageType The type of the message to create.
 */
void ToolBarStateMessages::setSecondWidget(ObjectWidget* secondObject, MessageType messageType)
{
    Uml::Sequence_Message_Type msgType = getMessageType();

    //There shouldn't be second widget for a lost or a found message
    if (msgType == Uml::sequence_message_lost || msgType == Uml::sequence_message_found) {
        cleanMessage();
        xclick = 0;
        yclick = 0;
        return;
    }
    //TODO shouldn't start position in the first widget be used also for normal messages
    //and not only for creation?
    int y = m_pMouseEvent->y();
    if (messageType == CreationMessage) {
        msgType = Uml::sequence_message_creation;
        y = m_messageLine->startPoint().y();
    }

    MessageWidget* message = new MessageWidget(m_pUMLScene, m_firstObject,
                                               secondObject, y, msgType);

    cleanMessage();

    m_pUMLScene->getMessageList().append(message);

    FloatingTextWidget *ft = message->floatingTextWidget();
    //TODO cancel doesn't cancel the creation of the message, only cancels setting an operation.
    //Shouldn't it cancel also the whole creation?
    ft->showOperationDialog();
    message->setTextPosition();
    m_pUMLScene->getWidgetList().append(ft);

    UMLApp::app()->document()->setModified();
}
void ToolBarStateMessages::setupMessageWidget(MessageWidget *message)
{
    m_pUMLScene->messageList().append(message);
    m_pUMLScene->addItem(message);
    message->activate();

    FloatingTextWidget *ft = message->floatingTextWidget();
    //TODO cancel doesn't cancel the creation of the message, only cancels setting an operation.
    //Shouldn't it cancel also the whole creation?
    ft->showOperationDialog();
    message->setTextPosition();
    m_pUMLScene->widgetList().append(ft);

    UMLApp::app()->document()->setModified();
}
/**
 * Sets the second widget in the association using the current widget and
 * creates the association.
 * If the association between the two widgets using the current type of
 * association is illegitimate, an error is shown and the association cancelled.
 * Otherwise, the association is created and added to the scene, and the tool
 * is changed to the default tool.
 *
 * @todo Why change to the default tool? Shouldn't it better to stay on
 *       association and let the user change with a right click? The tool to
 *       create widgets doesn't change to default after creating a widget
 */
void ToolBarStateAssociation::setSecondWidget()
{
    Uml::AssociationType::Enum type = getAssociationType();
    UMLWidget* widgetA = m_firstWidget;
    UMLWidget* widgetB = currentWidget();
    WidgetBase::WidgetType at = widgetA->baseType();
    bool valid = true;
    if (type == Uml::AssociationType::Generalization) {
        type = AssocRules::isGeneralisationOrRealisation(widgetA, widgetB);
    }
    if (widgetA == widgetB) {
        valid = AssocRules::allowSelf(type, at);
        if (valid && type == Uml::AssociationType::Association) {
            type = Uml::AssociationType::Association_Self;
        }
    } else {
        valid = AssocRules::allowAssociation(type, widgetA, widgetB);
    }
    if (valid) {
        AssociationWidget *temp = AssociationWidget::create(m_pUMLScene, widgetA, type, widgetB);
        FloatingTextWidget *wt = temp->textWidgetByRole(Uml::TextRole::Coll_Message);
        if (wt)
            wt->showOperationDialog();
        if (addAssociationInViewAndDoc(temp)) {
            if (type == Uml::AssociationType::Containment) {
                UMLObject *newContainer = widgetA->umlObject();
                UMLObject *objToBeMoved = widgetB->umlObject();
                if (newContainer && objToBeMoved) {
                    Model_Utils::treeViewMoveObjectTo(newContainer, objToBeMoved);
                }
            }
            UMLApp::app()->document()->setModified();
        }
    } else {
        //TODO improve error feedback: tell the user what are the valid type of associations for
        //the second widget using the first widget
        KMessageBox::error(0, i18n("Incorrect use of associations."), i18n("Association Error"));
    }

    cleanAssociation();
}