umbrello API Documentation

toolbarstateassociation.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *   copyright (C) 2004-2006                                               *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "toolbarstateassociation.h"
00014 
00015 // kde includes
00016 #include <kdebug.h>
00017 #include <klocale.h>
00018 #include <kmessagebox.h>
00019 
00020 // app includes
00021 #include "assocrules.h"
00022 #include "association.h"
00023 #include "associationwidget.h"
00024 #include "classifierwidget.h"
00025 #include "folder.h"
00026 #include "model_utils.h"
00027 #include "uml.h"
00028 #include "umlobject.h"
00029 #include "umlview.h"
00030 #include "umllistview.h"
00031 #include "umldoc.h"
00032 #include "umlwidget.h"
00033 
00034 using namespace Uml;
00035 
00036 ToolBarStateAssociation::ToolBarStateAssociation(UMLView *umlView) : ToolBarStatePool(umlView) {
00037     m_firstWidget = 0;
00038     m_associationLine = 0;
00039 }
00040 
00041 ToolBarStateAssociation::~ToolBarStateAssociation() {
00042     delete m_associationLine;
00043 }
00044 
00045 void ToolBarStateAssociation::init() {
00046     ToolBarStatePool::init();
00047 
00048     cleanAssociation();
00049 }
00050 
00051 void ToolBarStateAssociation::cleanBeforeChange() {
00052     ToolBarStatePool::cleanBeforeChange();
00053 
00054     cleanAssociation();
00055 }
00056 
00057 void ToolBarStateAssociation::mouseMove(QMouseEvent* ome) {
00058     ToolBarStatePool::mouseMove(ome);
00059 
00060     if (m_associationLine) {
00061         QPoint sp = m_associationLine->startPoint();
00062         m_associationLine->setPoints(sp.x(), sp.y(), m_pMouseEvent->x(), m_pMouseEvent->y());
00063     }
00064 }
00065 
00066 void ToolBarStateAssociation::slotWidgetRemoved(UMLWidget* widget) {
00067     ToolBarState::slotWidgetRemoved(widget);
00068 
00069     if (widget == m_firstWidget) {
00070         cleanAssociation();
00071     }
00072 }
00073 
00074 void ToolBarStateAssociation::mouseReleaseAssociation() {
00075     if (m_pMouseEvent->button() != Qt::LeftButton ||
00076             !m_firstWidget || m_firstWidget->getBaseType() != Uml::wt_Class) {
00077         cleanAssociation();
00078         return;
00079     }
00080 
00081     getCurrentAssociation()->createAssocClassLine(
00082             static_cast<ClassifierWidget*>(m_firstWidget),
00083             getCurrentAssociation()->getLinePath()->onLinePath(m_pMouseEvent->pos()));
00084     cleanAssociation();
00085 }
00086 
00087 void ToolBarStateAssociation::mouseReleaseWidget() {
00088     if (m_pMouseEvent->button() != Qt::LeftButton) {
00089         cleanAssociation();
00090         return;
00091     }
00092 
00093     // TODO In old code in ToolBarState there was a TODO that said: Should not
00094     //be called by a Sequence message Association. Here's the check for that,
00095     //although I don't know why it is needed, but it seems that it's not needed,
00096     //as the old code worked fine without it...
00097     if (getAssociationType() == at_Seq_Message) {
00098         return;
00099     }
00100 
00101     if (!m_firstWidget) {
00102         setFirstWidget();
00103     } else {
00104         setSecondWidget();
00105     }
00106 }
00107 
00108 void ToolBarStateAssociation::mouseReleaseEmpty() {
00109     cleanAssociation();
00110 }
00111 
00112 void ToolBarStateAssociation::setFirstWidget() {
00113     UMLWidget* widget = getCurrentWidget();
00114     Association_Type type = getAssociationType();
00115 
00116     if (!AssocRules::allowAssociation(type, widget)) {
00117         //TODO improve error feedback: tell the user what are the valid type of associations for
00118         //that widget
00119         KMessageBox::error(0, i18n("Incorrect use of associations."), i18n("Association Error"));
00120         return;
00121     }
00122     //set up position
00123     QPoint pos;
00124     pos.setX(widget->getX() + (widget->getWidth() / 2));
00125     pos.setY(widget->getY() + (widget->getHeight() / 2));
00126     //TODO why is this needed?
00127     m_pUMLView->setPos(pos);
00128 
00129     m_firstWidget = widget;
00130 
00131     m_associationLine = new QCanvasLine(m_pUMLView->canvas());
00132     m_associationLine->setPoints(pos.x(), pos.y(), pos.x(), pos.y());
00133     m_associationLine->setPen(QPen(m_pUMLView->getLineColor(), m_pUMLView->getLineWidth(), Qt::DashLine));
00134 
00135     m_associationLine->setVisible(true);
00136 
00137     m_pUMLView->viewport()->setMouseTracking(true);
00138 }
00139 
00140 void ToolBarStateAssociation::setSecondWidget() {
00141     Association_Type type = getAssociationType();
00142     UMLWidget* widgetA = m_firstWidget;
00143     UMLWidget* widgetB = getCurrentWidget();
00144     Widget_Type at = widgetA->getBaseType();
00145     bool valid = true;
00146     if (type == at_Generalization) {
00147         type = AssocRules::isGeneralisationOrRealisation(widgetA, widgetB);
00148     }
00149     if (widgetA == widgetB) {
00150         valid = AssocRules::allowSelf(type, at);
00151         if (valid && type == at_Association) {
00152             type = at_Association_Self;
00153         }
00154     } else {
00155         valid = AssocRules::allowAssociation(type, widgetA, widgetB);
00156     }
00157     if (valid) {
00158         AssociationWidget *temp = new AssociationWidget(m_pUMLView, widgetA, type, widgetB);
00159         addAssociationInViewAndDoc(temp);
00160         if (type == at_Containment) {
00161             UMLListView *lv = UMLApp::app()->getListView();
00162             UMLObject *newContainer = widgetA->getUMLObject();
00163             UMLObject *objToBeMoved = widgetB->getUMLObject();
00164             if (newContainer && objToBeMoved) {
00165                 UMLListViewItem *newLVParent = lv->findUMLObject(newContainer);
00166                 lv->moveObject(objToBeMoved->getID(),
00167                                Model_Utils::convert_OT_LVT(objToBeMoved),
00168                                newLVParent);
00169             }
00170         }
00171         UMLApp::app()->getDocument()->setModified();
00172     } else {
00173         //TODO improve error feedback: tell the user what are the valid type of associations for
00174         //the second widget using the first widget
00175         KMessageBox::error(0, i18n("Incorrect use of associations."), i18n("Association Error"));
00176     }
00177 
00178     cleanAssociation();
00179 }
00180 
00181 Association_Type ToolBarStateAssociation::getAssociationType() {
00182     Association_Type at;
00183 
00184     switch(getButton()) {
00185         case WorkToolBar::tbb_Anchor:                   at = at_Anchor;            break;
00186         case WorkToolBar::tbb_Association:              at = at_Association;       break;
00187         case WorkToolBar::tbb_UniAssociation:           at = at_UniAssociation;    break;
00188         case WorkToolBar::tbb_Generalization:           at = at_Generalization;    break;
00189         case WorkToolBar::tbb_Composition:              at = at_Composition;       break;
00190         case WorkToolBar::tbb_Aggregation:              at = at_Aggregation;       break;
00191         case WorkToolBar::tbb_Relationship:             at = at_Relationship;      break;
00192         case WorkToolBar::tbb_Dependency:               at = at_Dependency;        break;
00193         case WorkToolBar::tbb_Containment:              at = at_Containment;       break;
00194         case WorkToolBar::tbb_Seq_Message_Synchronous:
00195         case WorkToolBar::tbb_Seq_Message_Asynchronous: at = at_Seq_Message;       break;
00196         case WorkToolBar::tbb_Coll_Message:             at = at_Coll_Message;      break;
00197         case WorkToolBar::tbb_State_Transition:         at = at_State;             break;
00198         case WorkToolBar::tbb_Activity_Transition:      at = at_Activity;          break;
00199 
00200         default:                                        at = at_Unknown;           break;
00201     }
00202 
00203     return at;
00204 }
00205 
00206 void ToolBarStateAssociation::addAssociationInViewAndDoc(AssociationWidget* a) {
00207     // append in view
00208     if (m_pUMLView->addAssociation(a, false)) {
00209         // if view went ok, then append in document
00210         UMLAssociation *umla = a->getAssociation();
00211         if (umla == NULL) {
00212             // association without model representation in UMLDoc
00213             return;
00214         }
00215         Uml::Model_Type m = Model_Utils::convert_DT_MT(m_pUMLView->getType());
00216         UMLDoc *umldoc = UMLApp::app()->getDocument();
00217         umla->setUMLPackage(umldoc->getRootFolder(m));
00218         UMLApp::app()->getDocument()->addAssociation(umla);
00219     } else {
00220         kError() << "cannot addAssocInViewAndDoc(), deleting" << endl;
00221         delete a;
00222     }
00223 }
00224 
00225 void ToolBarStateAssociation::cleanAssociation() {
00226     m_firstWidget = 0;
00227 
00228     delete m_associationLine;
00229     m_associationLine = 0;
00230 }
00231 
00232 #include "toolbarstateassociation.moc"
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:08:00 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003