00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "messagewidget.h"
00014
00015
00016 #include <qpainter.h>
00017
00018 #include <kdebug.h>
00019 #include <kcursor.h>
00020
00021 #include "messagewidgetcontroller.h"
00022 #include "floatingtextwidget.h"
00023 #include "objectwidget.h"
00024 #include "classifier.h"
00025 #include "operation.h"
00026 #include "umlview.h"
00027 #include "umldoc.h"
00028 #include "uml.h"
00029 #include "uniqueid.h"
00030 #include "listpopupmenu.h"
00031
00032 MessageWidget::MessageWidget(UMLView * view, ObjectWidget* a, ObjectWidget* b,
00033 int y, Uml::Sequence_Message_Type sequenceMessageType,
00034 Uml::IDType id )
00035 : UMLWidget(view, id, new MessageWidgetController(this)) {
00036 init();
00037 m_pOw[Uml::A] = a;
00038 m_pOw[Uml::B] = b;
00039 m_nY = y;
00040 m_sequenceMessageType = sequenceMessageType;
00041 if (m_sequenceMessageType == Uml::sequence_message_creation) {
00042 y -= m_pOw[Uml::B]->getHeight() / 2;
00043 m_pOw[Uml::B]->setY(y);
00044 }
00045 updateResizability();
00046 calculateWidget();
00047 y = y < getMinY() ? getMinY() : y;
00048 y = y > getMaxY() ? getMaxY() : y;
00049 m_nY = y;
00050
00051 this->activate();
00052 }
00053
00054 MessageWidget::MessageWidget(UMLView * view, Uml::Sequence_Message_Type seqMsgType, Uml::IDType id)
00055 : UMLWidget(view, id, new MessageWidgetController(this)) {
00056 init();
00057 m_sequenceMessageType = seqMsgType;
00058 }
00059
00060 void MessageWidget::init() {
00061 UMLWidget::setBaseType(Uml::wt_Message);
00062 m_bIgnoreSnapToGrid = true;
00063 m_bIgnoreSnapComponentSizeToGrid = true;
00064 m_pOw[Uml::A] = m_pOw[Uml::B] = NULL;
00065 m_pFText = NULL;
00066 m_nY = 0;
00067 setVisible(true);
00068 }
00069
00070 MessageWidget::~MessageWidget() {
00071 }
00072
00073 void MessageWidget::updateResizability() {
00074 if (m_sequenceMessageType == Uml::sequence_message_synchronous ||
00075 m_pOw[Uml::A] == m_pOw[Uml::B])
00076 UMLWidget::m_bResizable = true;
00077 else
00078 UMLWidget::m_bResizable = false;
00079 }
00080
00081 void MessageWidget::draw(QPainter& p, int offsetX, int offsetY) {
00082 if(!m_pOw[Uml::A] || !m_pOw[Uml::B]) {
00083 return;
00084 }
00085 UMLWidget::setPen(p);
00086 if (m_sequenceMessageType == Uml::sequence_message_synchronous) {
00087 drawSynchronous(p, offsetX, offsetY);
00088 } else if (m_sequenceMessageType == Uml::sequence_message_asynchronous) {
00089 drawAsynchronous(p, offsetX, offsetY);
00090 } else if (m_sequenceMessageType == Uml::sequence_message_creation) {
00091 drawCreation(p, offsetX, offsetY);
00092 } else {
00093 kWarning() << "Unknown message type" << endl;
00094 }
00095 }
00096
00097 void MessageWidget::drawSolidArrowhead(QPainter& p, int x, int y, Qt::ArrowType direction) {
00098 int arrowheadExtentX = 4;
00099 if (direction == Qt::RightArrow) {
00100 arrowheadExtentX = -arrowheadExtentX;
00101 }
00102 QPointArray points;
00103 points.putPoints(0, 3, x, y, x + arrowheadExtentX, y - 3, x + arrowheadExtentX, y + 3);
00104 p.setBrush( QBrush(p.pen().color()) );
00105 p.drawPolygon(points);
00106 }
00107
00108 void MessageWidget::drawArrow(QPainter& p, int x, int y, int w,
00109 Qt::ArrowType direction, bool useDottedLine ) {
00110 int arrowheadStartX = x;
00111 int arrowheadExtentX = 4;
00112 if (direction == Qt::RightArrow) {
00113 arrowheadStartX += w;
00114 arrowheadExtentX = -arrowheadExtentX;
00115 }
00116
00117 p.drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y - 3);
00118
00119 p.drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y + 3);
00120
00121 if (useDottedLine) {
00122 QPen pen = p.pen();
00123 pen.setStyle(Qt::DotLine);
00124 p.setPen(pen);
00125 }
00126 p.drawLine(x, y, x + w, y);
00127 }
00128
00129 void MessageWidget::drawSynchronous(QPainter& p, int offsetX, int offsetY) {
00130 int x1 = m_pOw[Uml::A]->getX();
00131 int x2 = m_pOw[Uml::B]->getX();
00132 int w = getWidth() - 1;
00133 int h = getHeight();
00134
00135 bool messageOverlaps = m_pOw[Uml::A] -> messageOverlap( getY(), this );
00136
00137 if(m_pOw[Uml::A] == m_pOw[Uml::B]) {
00138 p.fillRect( offsetX, offsetY, 17, h, QBrush(Qt::white) );
00139 p.drawRect(offsetX, offsetY, 17, h);
00140 offsetX += 17;
00141 w -= 17;
00142 offsetY += 3;
00143 const int lowerLineY = offsetY + h - 6;
00144
00145 p.drawLine(offsetX, offsetY, offsetX + w, offsetY);
00146
00147 p.drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
00148
00149 drawArrow(p, offsetX, lowerLineY, w, Qt::LeftArrow);
00150 offsetX -= 17;
00151 offsetY -= 3;
00152 } else if(x1 < x2) {
00153 if (messageOverlaps) {
00154 offsetX += 8;
00155 w -= 8;
00156 }
00157 QPen pen = p.pen();
00158 int startX = offsetX + w - 16;
00159 p.fillRect(startX, offsetY, 17, h, QBrush(Qt::white));
00160 p.drawRect(startX, offsetY, 17, h);
00161 p.drawLine(offsetX, offsetY + 4, startX, offsetY + 4);
00162 drawSolidArrowhead(p, startX - 1, offsetY + 4, Qt::RightArrow);
00163 drawArrow(p, offsetX, offsetY + h - 3, w - 16, Qt::LeftArrow, true);
00164 if (messageOverlaps) {
00165 offsetX -= 8;
00166 }
00167 } else {
00168 if (messageOverlaps) {
00169 w -=8;
00170 }
00171 QPen pen = p.pen();
00172 p.fillRect( offsetX, offsetY, 17, h, QBrush(Qt::white) );
00173 p.drawRect(offsetX, offsetY, 17, h);
00174 p.drawLine(offsetX + 18, offsetY + 4, offsetX + w, offsetY + 4);
00175 drawSolidArrowhead(p, offsetX + 17, offsetY + 4, Qt::LeftArrow);
00176 drawArrow(p, offsetX + 18, offsetY + h - 3, w - 18, Qt::RightArrow, true);
00177 }
00178
00179 if(m_bSelected) {
00180 drawSelected(&p, offsetX, offsetY);
00181 }
00182 }
00183
00184 void MessageWidget::drawAsynchronous(QPainter& p, int offsetX, int offsetY) {
00185 int x1 = m_pOw[Uml::A]->getX();
00186 int x2 = m_pOw[Uml::B]->getX();
00187 int w = getWidth() - 1;
00188 int h = getHeight() - 1;
00189 bool messageOverlapsA = m_pOw[Uml::A] -> messageOverlap( getY(), this );
00190
00191
00192 if(m_pOw[Uml::A] == m_pOw[Uml::B]) {
00193 if (messageOverlapsA) {
00194 offsetX += 7;
00195 w -= 7;
00196 }
00197 const int lowerLineY = offsetY + h - 3;
00198
00199 p.drawLine(offsetX, offsetY, offsetX + w, offsetY);
00200
00201 p.drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
00202
00203 drawArrow(p, offsetX, lowerLineY, w, Qt::LeftArrow);
00204 if (messageOverlapsA) {
00205 offsetX -= 7;
00206 }
00207 } else if(x1 < x2) {
00208 if (messageOverlapsA) {
00209 offsetX += 7;
00210 w -= 7;
00211 }
00212 drawArrow(p, offsetX, offsetY + 4, w, Qt::RightArrow);
00213 if (messageOverlapsA) {
00214 offsetX -= 7;
00215 }
00216 } else {
00217 if (messageOverlapsA) {
00218 w -= 7;
00219 }
00220 drawArrow(p, offsetX, offsetY + 4, w, Qt::LeftArrow);
00221 }
00222
00223 if (m_bSelected)
00224 drawSelected(&p, offsetX, offsetY);
00225 }
00226
00227 void MessageWidget::drawCreation(QPainter& p, int offsetX, int offsetY) {
00228 int x1 = m_pOw[Uml::A]->getX();
00229 int x2 = m_pOw[Uml::B]->getX();
00230 int w = getWidth() - 1;
00231
00232 bool messageOverlapsA = m_pOw[Uml::A] -> messageOverlap( getY(), this );
00233
00234
00235 const int lineY = offsetY + 4;
00236 if (x1 < x2) {
00237 if (messageOverlapsA) {
00238 offsetX += 7;
00239 w -= 7;
00240 }
00241 drawArrow(p, offsetX, lineY, w, Qt::RightArrow);
00242 if (messageOverlapsA) {
00243 offsetX -= 7;
00244 }
00245 } else {
00246 if (messageOverlapsA) {
00247 w -= 7;
00248 }
00249 drawArrow(p, offsetX, lineY, w, Qt::LeftArrow);
00250 }
00251
00252 if (m_bSelected)
00253 drawSelected(&p, offsetX, offsetY);
00254 }
00255
00256 int MessageWidget::onWidget(const QPoint & p) {
00257 if (m_sequenceMessageType != Uml::sequence_message_synchronous) {
00258 return UMLWidget::onWidget(p);
00259 }
00260
00261
00262 if (p.x() < getX() || p.x() > getX() + getWidth())
00263 return 0;
00264 const int tolerance = 5;
00265 const int pY = p.y();
00266 const int topArrowY = getY() + 3;
00267 const int bottomArrowY = getY() + getHeight() - 3;
00268 if (pY < topArrowY - tolerance || pY > bottomArrowY + tolerance)
00269 return 0;
00270 if (getHeight() <= 2 * tolerance)
00271 return 1;
00272 if (pY > topArrowY + tolerance && pY < bottomArrowY - tolerance)
00273 return 0;
00274 return 1;
00275 }
00276
00277 void MessageWidget::setTextPosition() {
00278 if (m_pFText == NULL) {
00279 kDebug() << "MessageWidget::setTextPosition: m_pFText is NULL"
00280 << endl;
00281 return;
00282 }
00283 if (m_pFText->getDisplayText().isEmpty()) {
00284 return;
00285 }
00286 m_pFText->updateComponentSize();
00287 int ftX = constrainX(m_pFText->getX(), m_pFText->getWidth(), m_pFText->getRole());
00288 int ftY = getY() - m_pFText->getHeight();
00289 m_pFText->setX( ftX );
00290 m_pFText->setY( ftY );
00291 }
00292
00293 int MessageWidget::constrainX(int textX, int textWidth, Uml::Text_Role tr) {
00294 int result = textX;
00295 const int minTextX = getX() + 5;
00296 if (textX < minTextX || tr == Uml::tr_Seq_Message_Self) {
00297 result = minTextX;
00298 } else {
00299 ObjectWidget *objectAtRight = NULL;
00300 if (m_pOw[Uml::B]->getX() > m_pOw[Uml::A]->getX())
00301 objectAtRight = m_pOw[Uml::B];
00302 else
00303 objectAtRight = m_pOw[Uml::A];
00304 const int objRight_seqLineX = objectAtRight->getX() + objectAtRight->getWidth() / 2;
00305 const int maxTextX = objRight_seqLineX - textWidth - 5;
00306 if (maxTextX <= minTextX)
00307 result = minTextX;
00308 else if (textX > maxTextX)
00309 result = maxTextX;
00310 }
00311 return result;
00312 }
00313
00314 void MessageWidget::constrainTextPos(int &textX, int &textY, int textWidth, int textHeight,
00315 Uml::Text_Role tr) {
00316 textX = constrainX(textX, textWidth, tr);
00317
00318 const int minTextY = getMinY();
00319 const int maxTextY = getMaxY() - textHeight - 5;
00320 if (textY < minTextY)
00321 textY = minTextY;
00322 else if (textY > maxTextY)
00323 textY = maxTextY;
00324
00325 }
00326
00327 void MessageWidget::setLinkAndTextPos() {
00328 if (m_pFText == NULL)
00329 return;
00330 m_pFText->setLink(this);
00331 setTextPosition();
00332 }
00333
00334 void MessageWidget::moveEvent(QMoveEvent* ) {
00335
00336 if (!m_pFText) {
00337 return;
00338 }
00339
00340
00341
00342
00343
00344 setTextPosition();
00345
00346 emit sigMessageMoved();
00347 }
00348
00349 void MessageWidget::resizeEvent(QResizeEvent* ) {
00350 }
00351
00352 void MessageWidget::calculateWidget() {
00353 setMessageText(m_pFText);
00354 calculateDimensions();
00355
00356 setVisible(true);
00357
00358 setX(m_nPosX);
00359 setY(m_nY);
00360 }
00361
00362 void MessageWidget::slotWidgetMoved(Uml::IDType id) {
00363 const Uml::IDType idA = m_pOw[Uml::A]->getLocalID();
00364 const Uml::IDType idB = m_pOw[Uml::B]->getLocalID();
00365 if (idA != id && idB != id) {
00366 kDebug() << "MessageWidget::slotWidgetMoved(" << ID2STR(id)
00367 << "): ignoring for idA=" << ID2STR(idA)
00368 << ", idB=" << ID2STR(idB) << endl;
00369 return;
00370 }
00371 m_nY = getY();
00372 if (m_nY < getMinY())
00373 m_nY = getMinY();
00374 if (m_nY > getMaxY())
00375 m_nY = getMaxY();
00376 calculateWidget();
00377 if( !m_pFText )
00378 return;
00379 if (m_pView->getSelectCount(true) > 1)
00380 return;
00381 setTextPosition();
00382 }
00383
00384 bool MessageWidget::contains(ObjectWidget * w) {
00385 if(m_pOw[Uml::A] == w || m_pOw[Uml::B] == w)
00386 return true;
00387 else
00388 return false;
00389 }
00390
00391 void MessageWidget::slotMenuSelection(int sel) {
00392 if(sel == ListPopupMenu::mt_Delete) {
00393
00394 m_pView -> removeWidget(this);
00395 } else {
00396 if (m_pFText == NULL) {
00397 Uml::Text_Role tr = Uml::tr_Seq_Message;
00398 if (m_pOw[Uml::A] == m_pOw[Uml::B])
00399 tr = Uml::tr_Seq_Message_Self;
00400 m_pFText = new FloatingTextWidget( m_pView, tr );
00401 m_pFText->setFont(UMLWidget::getFont());
00402 setLinkAndTextPos();
00403 m_pView->getWidgetList().append(m_pFText);
00404 }
00405 m_pFText -> slotMenuSelection(sel);
00406 }
00407 }
00408
00409 bool MessageWidget::activate(IDChangeLog * Log ) {
00410 m_pView->resetPastePoint();
00411
00412 if (m_pOw[Uml::A] == NULL) {
00413 UMLWidget *pWA = m_pView->findWidget(m_widgetAId);
00414 if (pWA == NULL) {
00415 kDebug() << "MessageWidget::activate: role A object "
00416 << ID2STR(m_widgetAId) << " not found" << endl;
00417 return false;
00418 }
00419 m_pOw[Uml::A] = dynamic_cast<ObjectWidget*>(pWA);
00420 if (m_pOw[Uml::A] == NULL) {
00421 kDebug() << "MessageWidget::activate: role A widget "
00422 << ID2STR(m_widgetAId) << " is not an ObjectWidget" << endl;
00423 return false;
00424 }
00425 }
00426 if (m_pOw[Uml::B] == NULL) {
00427 UMLWidget *pWB = m_pView->findWidget(m_widgetBId);
00428 if (pWB == NULL) {
00429 kDebug() << "MessageWidget::activate: role B object "
00430 << ID2STR(m_widgetBId) << " not found" << endl;
00431 return false;
00432 }
00433 m_pOw[Uml::B] = dynamic_cast<ObjectWidget*>(pWB);
00434 if (m_pOw[Uml::B] == NULL) {
00435 kDebug() << "MessageWidget::activate: role B widget "
00436 << ID2STR(m_widgetBId) << " is not an ObjectWidget" << endl;
00437 return false;
00438 }
00439 }
00440 updateResizability();
00441
00442 UMLClassifier *c = dynamic_cast<UMLClassifier*>(m_pOw[Uml::B]->getUMLObject());
00443 UMLOperation *op = NULL;
00444 if (c && !m_CustomOp.isEmpty()) {
00445 Uml::IDType opId = STR2ID(m_CustomOp);
00446 op = dynamic_cast<UMLOperation*>( c->findChildObjectById(opId, true) );
00447 if (op) {
00448
00449
00450 m_CustomOp = QString::null;
00451 }
00452 }
00453
00454 if( !m_pFText ) {
00455 Uml::Text_Role tr = Uml::tr_Seq_Message;
00456 if (m_pOw[Uml::A] == m_pOw[Uml::B])
00457 tr = Uml::tr_Seq_Message_Self;
00458 m_pFText = new FloatingTextWidget( m_pView, tr, "" );
00459 m_pFText->setFont(UMLWidget::getFont());
00460 }
00461 if (op)
00462 setOperation(op);
00463 setLinkAndTextPos();
00464 m_pFText -> setText("");
00465 m_pFText->setActivated();
00466 QString messageText = m_pFText->getText();
00467 m_pFText->setVisible( messageText.length() > 1 );
00468
00469 connect(m_pOw[Uml::A], SIGNAL(sigWidgetMoved(Uml::IDType)), this, SLOT(slotWidgetMoved(Uml::IDType)));
00470 connect(m_pOw[Uml::B], SIGNAL(sigWidgetMoved(Uml::IDType)), this, SLOT(slotWidgetMoved(Uml::IDType)));
00471
00472 connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::A], SLOT(slotMessageMoved()) );
00473 connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::B], SLOT(slotMessageMoved()) );
00474 m_pOw[Uml::A] -> messageAdded(this);
00475 m_pOw[Uml::B] -> messageAdded(this);
00476 calculateDimensions();
00477
00478 emit sigMessageMoved();
00479 return true;
00480 }
00481
00482 void MessageWidget::setMessageText(FloatingTextWidget *ft) {
00483 if (ft == NULL)
00484 return;
00485 QString displayText = m_SequenceNumber + ": " + getOperationText(m_pView);
00486 ft->setText(displayText);
00487 setTextPosition();
00488 }
00489
00490 void MessageWidget::setText(FloatingTextWidget *ft, const QString &newText) {
00491 ft->setText(newText);
00492 UMLApp::app()->getDocument()->setModified(true);
00493 }
00494
00495 void MessageWidget::setSeqNumAndOp(const QString &seqNum, const QString &op) {
00496 setSequenceNumber( seqNum );
00497 m_CustomOp = op;
00498 }
00499
00500 void MessageWidget::setSequenceNumber( const QString &sequenceNumber ) {
00501 m_SequenceNumber = sequenceNumber;
00502 }
00503
00504 QString MessageWidget::getSequenceNumber() const {
00505 return m_SequenceNumber;
00506 }
00507
00508 void MessageWidget::lwSetFont (QFont font) {
00509 UMLWidget::setFont( font );
00510 }
00511
00512 UMLClassifier *MessageWidget::getOperationOwner() {
00513 UMLObject *pObject = m_pOw[Uml::B]->getUMLObject();
00514 if (pObject == NULL)
00515 return NULL;
00516 UMLClassifier *c = dynamic_cast<UMLClassifier*>(pObject);
00517 return c;
00518 }
00519
00520 UMLOperation *MessageWidget::getOperation() {
00521 return static_cast<UMLOperation*>(m_pObject);
00522 }
00523
00524 void MessageWidget::setOperation(UMLOperation *op) {
00525 if (m_pObject && m_pFText)
00526 disconnect(m_pObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
00527 m_pObject = op;
00528 if (m_pObject && m_pFText)
00529 connect(m_pObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
00530 }
00531
00532 QString MessageWidget::getCustomOpText() {
00533 return m_CustomOp;
00534 }
00535
00536 void MessageWidget::setCustomOpText(const QString &opText) {
00537 m_CustomOp = opText;
00538 m_pFText->setMessageText();
00539 }
00540
00541 UMLClassifier * MessageWidget::getSeqNumAndOp(QString& seqNum, QString& op) {
00542 seqNum = m_SequenceNumber;
00543 UMLOperation *pOperation = getOperation();
00544 if (pOperation != NULL) {
00545 op = pOperation->toString(Uml::st_SigNoVis);
00546 } else {
00547 op = m_CustomOp;
00548 }
00549 UMLObject *o = m_pOw[Uml::B]->getUMLObject();
00550 UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
00551 return c;
00552 }
00553
00554 void MessageWidget::calculateDimensions() {
00555 if (m_sequenceMessageType == Uml::sequence_message_synchronous) {
00556 calculateDimensionsSynchronous();
00557 } else if (m_sequenceMessageType == Uml::sequence_message_asynchronous) {
00558 calculateDimensionsAsynchronous();
00559 } else if (m_sequenceMessageType == Uml::sequence_message_creation) {
00560 calculateDimensionsCreation();
00561 } else {
00562 kWarning() << "Unknown message type" << endl;
00563 }
00564 if (! UMLApp::app()->getDocument()->loading()) {
00565 adjustAssocs( getX(), getY() );
00566 }
00567 }
00568
00569 void MessageWidget::calculateDimensionsSynchronous() {
00570 int x = 0;
00571
00572 int x1 = m_pOw[Uml::A]->getX();
00573 int x2 = m_pOw[Uml::B]->getX();
00574 int w1 = m_pOw[Uml::A]->getWidth() / 2;
00575 int w2 = m_pOw[Uml::B]->getWidth() / 2;
00576 x1 += w1;
00577 x2 += w2;
00578
00579 int widgetWidth = 0;
00580 int widgetHeight = 0;
00581 if( m_pOw[Uml::A] == m_pOw[Uml::B] ) {
00582 widgetWidth = 50;
00583 x = x1 - 2;
00584 } else if( x1 < x2 ) {
00585 x = x1;
00586 widgetWidth = x2 - x1 + 8;
00587 } else {
00588 x = x2 - 8;
00589 widgetWidth = x1 - x2 + 8;
00590 }
00591
00592 if ( height() < 20 ) {
00593 widgetHeight = 20;
00594 } else {
00595 widgetHeight = height();
00596 }
00597
00598 m_nPosX = x;
00599 setSize(widgetWidth, widgetHeight);
00600 }
00601
00602 void MessageWidget::calculateDimensionsAsynchronous() {
00603 int x = 0;
00604
00605 int x1 = m_pOw[Uml::A]->getX();
00606 int x2 = m_pOw[Uml::B]->getX();
00607 int w1 = m_pOw[Uml::A]->getWidth() / 2;
00608 int w2 = m_pOw[Uml::B]->getWidth() / 2;
00609 x1 += w1;
00610 x2 += w2;
00611
00612 int widgetWidth = 0;
00613 int widgetHeight = 8;
00614 if( m_pOw[Uml::A] == m_pOw[Uml::B] ) {
00615 widgetWidth = 50;
00616 x = x1;
00617 if( height() < 20 ) {
00618 widgetHeight = 20;
00619 } else {
00620 widgetHeight = height();
00621 }
00622 } else if( x1 < x2 ) {
00623 x = x1;
00624 widgetWidth = x2 - x1;
00625 } else {
00626 x = x2;
00627 widgetWidth = x1 - x2;
00628 }
00629 x += 1;
00630 widgetWidth -= 2;
00631 m_nPosX = x;
00632 setSize(widgetWidth, widgetHeight);
00633 }
00634
00635 void MessageWidget::calculateDimensionsCreation() {
00636 int x = 0;
00637
00638 int x1 = m_pOw[Uml::A]->getX();
00639 int x2 = m_pOw[Uml::B]->getX();
00640 int w1 = m_pOw[Uml::A]->getWidth() / 2;
00641 int w2 = m_pOw[Uml::B]->getWidth();
00642 x1 += w1;
00643 if (x1 > x2)
00644 x2 += w2;
00645
00646 int widgetWidth = 0;
00647 int widgetHeight = 8;
00648 if ( x1 < x2 ) {
00649 x = x1;
00650 widgetWidth = x2 - x1;
00651 } else {
00652 x = x2;
00653 widgetWidth = x1 - x2;
00654 }
00655 x += 1;
00656 widgetWidth -= 2;
00657 m_nPosX = x;
00658 m_nY = m_pOw[Uml::B]->getY() + m_pOw[Uml::B]->getHeight() / 2;
00659 setSize(widgetWidth, widgetHeight);
00660 }
00661
00662 void MessageWidget::cleanup() {
00663 if (m_pOw[Uml::A]) {
00664 disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::A], SLOT(slotMessageMoved()) );
00665 m_pOw[Uml::A]->messageRemoved(this);
00666 }
00667 if (m_pOw[Uml::B]) {
00668 disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::B], SLOT(slotMessageMoved()) );
00669 m_pOw[Uml::B]->messageRemoved(this);
00670 }
00671
00672 UMLWidget::cleanup();
00673 if (m_pFText) {
00674 m_pView->removeWidget(m_pFText);
00675 m_pFText = NULL;
00676 }
00677 }
00678
00679 void MessageWidget::setSelected(bool _select) {
00680 UMLWidget::setSelected( _select );
00681 if( !m_pFText || m_pFText->getDisplayText().isEmpty())
00682 return;
00683 if( m_bSelected && m_pFText -> getSelected() )
00684 return;
00685 if( !m_bSelected && !m_pFText -> getSelected() )
00686 return;
00687
00688 m_pView -> setSelected( m_pFText, 0 );
00689 m_pFText -> setSelected( m_bSelected );
00690 }
00691
00692 int MessageWidget::getMinY() {
00693 if (!m_pOw[Uml::A] || !m_pOw[Uml::B]) {
00694 return 0;
00695 }
00696 if (m_sequenceMessageType == Uml::sequence_message_creation) {
00697 return m_pOw[Uml::A]->getY() + m_pOw[Uml::A]->getHeight();
00698 }
00699 int heightA = m_pOw[Uml::A]->getY() + m_pOw[Uml::A]->getHeight();
00700 int heightB = m_pOw[Uml::B]->getY() + m_pOw[Uml::B]->getHeight();
00701 int height = heightA;
00702 if( heightA < heightB ) {
00703 height = heightB;
00704 }
00705 return height;
00706 }
00707
00708 int MessageWidget::getMaxY() {
00709 if( !m_pOw[Uml::A] || !m_pOw[Uml::B] ) {
00710 return 0;
00711 }
00712 int heightA = (int)((ObjectWidget*)m_pOw[Uml::A])->getEndLineY();
00713 int heightB = (int)((ObjectWidget*)m_pOw[Uml::B])->getEndLineY();
00714 int height = heightA;
00715 if( heightA > heightB ) {
00716 height = heightB;
00717 }
00718 return (height - this->height());
00719 }
00720
00721 void MessageWidget::setWidget(ObjectWidget * ow, Uml::Role_Type role) {
00722 m_pOw[role] = ow;
00723 updateResizability();
00724 }
00725
00726 ObjectWidget* MessageWidget::getWidget(Uml::Role_Type role) {
00727 return m_pOw[role];
00728 }
00729
00730 void MessageWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
00731 QDomElement messageElement = qDoc.createElement( "messagewidget" );
00732 UMLWidget::saveToXMI( qDoc, messageElement );
00733 messageElement.setAttribute( "widgetaid", ID2STR(m_pOw[Uml::A]->getLocalID()) );
00734 messageElement.setAttribute( "widgetbid", ID2STR(m_pOw[Uml::B]->getLocalID()) );
00735 UMLOperation *pOperation = getOperation();
00736 if (pOperation)
00737 messageElement.setAttribute( "operation", ID2STR(pOperation->getID()) );
00738 else
00739 messageElement.setAttribute( "operation", m_CustomOp );
00740 messageElement.setAttribute( "seqnum", m_SequenceNumber );
00741 messageElement.setAttribute( "sequencemessagetype", m_sequenceMessageType );
00742
00743
00744 if (m_pFText && !m_pFText->getText().isEmpty()) {
00745 messageElement.setAttribute( "textid", ID2STR(m_pFText->getID()) );
00746 m_pFText -> saveToXMI( qDoc, messageElement );
00747 }
00748
00749 qElement.appendChild( messageElement );
00750 }
00751
00752 bool MessageWidget::loadFromXMI(QDomElement& qElement) {
00753 if ( !UMLWidget::loadFromXMI(qElement) ) {
00754 return false;
00755 }
00756 QString textid = qElement.attribute( "textid", "-1" );
00757 QString widgetaid = qElement.attribute( "widgetaid", "-1" );
00758 QString widgetbid = qElement.attribute( "widgetbid", "-1" );
00759 m_CustomOp = qElement.attribute( "operation", "" );
00760 m_SequenceNumber = qElement.attribute( "seqnum", "" );
00761 QString sequenceMessageType = qElement.attribute( "sequencemessagetype", "1001" );
00762 m_sequenceMessageType = (Uml::Sequence_Message_Type)sequenceMessageType.toInt();
00763
00764 m_widgetAId = STR2ID(widgetaid);
00765 m_widgetBId = STR2ID(widgetbid);
00766 m_textId = STR2ID(textid);
00767
00768 Uml::Text_Role tr = Uml::tr_Seq_Message;
00769 if (m_widgetAId == m_widgetBId)
00770 tr = Uml::tr_Seq_Message_Self;
00771
00772
00773 QDomNode node = qElement.firstChild();
00774 QDomElement element = node.toElement();
00775 if ( !element.isNull() ) {
00776 QString tag = element.tagName();
00777 if (tag == "floatingtext") {
00778 m_pFText = new FloatingTextWidget( m_pView, tr, getOperationText(m_pView), m_textId );
00779 if( ! m_pFText->loadFromXMI(element) ) {
00780
00781 delete m_pFText;
00782 m_pFText = NULL;
00783 }
00784 } else {
00785 kError() << "MessageWidget::loadFromXMI: unknown tag "
00786 << tag << endl;
00787 }
00788 }
00789 return true;
00790 }
00791
00792 #include "messagewidget.moc"