00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "linepath.h"
00014
00015
00016 #include <cstdlib>
00017 #include <cmath>
00018
00019
00020 #include <qcanvas.h>
00021 #include <qdatastream.h>
00022 #include <qdom.h>
00023
00024
00025 #include <kdebug.h>
00026
00027
00028 #include "associationwidget.h"
00029 #include "activitywidget.h"
00030 #include "widget_utils.h"
00031 #include "umlview.h"
00032 #include "umldoc.h"
00033 #include "uml.h"
00034
00035 LinePath::Circle::Circle(QCanvas * canvas, int radius )
00036 : QCanvasEllipse(radius * 2, radius * 2, canvas) {
00037 }
00038
00039 void LinePath::Circle::setX(int x) {
00040 QCanvasItem::setX( (double) x );
00041 }
00042
00043 void LinePath::Circle::setY(int y) {
00044 QCanvasItem::setY( (double) y );
00045 }
00046
00047 void LinePath::Circle::setRadius(int radius) {
00048 QCanvasEllipse::setSize(radius * 2, radius * 2);
00049 }
00050
00051 int LinePath::Circle::getRadius() const {
00052 return (QCanvasEllipse::height() / 2);
00053 }
00054
00055 void LinePath::Circle::drawShape(QPainter& p) {
00056 int diameter = height();
00057 int radius = diameter / 2;
00058 p.drawEllipse( (int)x() - radius, (int)y() - radius, diameter, diameter);
00059 }
00060
00061 LinePath::LinePath() {
00062 m_RectList.setAutoDelete( true );
00063 m_LineList.setAutoDelete( true );
00064 m_HeadList.setAutoDelete( true );
00065 m_ParallelList.setAutoDelete( true );
00066 m_bSelected = false;
00067 m_pClearPoly = 0;
00068 m_pCircle = 0;
00069 m_PointArray.resize( 4 );
00070 m_ParallelLines.resize( 4 );
00071 m_pAssociation = 0;
00072 m_bHeadCreated = false;
00073 m_bParallelLineCreated = false;
00074 m_DockRegion = TopBottom;
00075 }
00076
00077 LinePath::~LinePath() {}
00078
00079 void LinePath::setAssociation(AssociationWidget * association ) {
00080 if( !association )
00081 return;
00082 cleanup();
00083 m_pAssociation = association;
00084 createHeadLines();
00085 if( getAssocType() == Uml::at_Coll_Message )
00086 setupParallelLine();
00087 UMLView * view = (UMLView *)m_pAssociation -> parent();
00088 connect( view, SIGNAL( sigColorChanged( Uml::IDType ) ), this, SLOT( slotLineColorChanged( Uml::IDType ) ) );
00089 connect( view, SIGNAL( sigLineWidthChanged( Uml::IDType ) ), this, SLOT( slotLineWidthChanged( Uml::IDType ) ) );
00090 }
00091
00092 QPoint LinePath::getPoint( int pointIndex ) {
00093 int count = m_LineList.count();
00094 if( count == 0 || pointIndex > count || pointIndex < 0)
00095 return QPoint( -1, -1 );
00096
00097 if( pointIndex == count ) {
00098 QCanvasLine * line = m_LineList.last();
00099 return line -> endPoint();
00100 }
00101 QCanvasLine * line = m_LineList.at( pointIndex );
00102 return line -> startPoint();
00103 }
00104
00105 bool LinePath::setPoint( int pointIndex, const QPoint &point ) {
00106 int count = m_LineList.count();
00107 if( count == 0 || pointIndex > count || pointIndex < 0)
00108 return false;
00109
00110 if( pointIndex == count) {
00111 QCanvasLine * line = m_LineList.last();
00112 QPoint p = line -> startPoint();
00113 line -> setPoints( p.x(), p.y(), point.x(), point.y() );
00114 moveSelected( pointIndex );
00115 update();
00116 return true;
00117 }
00118 if( pointIndex == 0 ) {
00119 QCanvasLine * line = m_LineList.first();
00120 QPoint p = line -> endPoint();
00121 line -> setPoints( point.x(), point.y(), p.x(), p.y() );
00122 moveSelected( pointIndex );
00123 update();
00124 return true;
00125 }
00126 QCanvasLine * line = m_LineList.at( pointIndex );
00127 QPoint p = line -> endPoint();
00128 line -> setPoints( point.x(), point.y(), p.x(), p.y() );
00129 line = m_LineList.at( pointIndex - 1 );
00130 p = line -> startPoint();
00131 line -> setPoints( p.x(), p.y(), point.x(), point.y() );
00132 moveSelected( pointIndex );
00133 update();
00134 return true;
00135 }
00136
00137 bool LinePath::isPoint( int pointIndex, const QPoint &point, unsigned short delta) {
00138 int count = m_LineList.count();
00139 if ( pointIndex >= count )
00140 return false;
00141
00142 QCanvasLine * line = m_LineList.at( pointIndex );
00143
00144
00145 if ( (
00146 abs( line -> endPoint().x() - point.x() ) <= delta
00147 &&
00148 abs( line -> endPoint().y() - point.y() ) <= delta
00149 ) || (
00150 abs( line -> startPoint().x() - point.x() ) <= delta
00151 &&
00152 abs( line -> startPoint().y() - point.y() ) <= delta
00153 ) )
00154 return true;
00155
00156
00157 return false;
00158 }
00159
00160 bool LinePath::insertPoint( int pointIndex, const QPoint &point ) {
00161 int count = m_LineList.count();
00162 if( count == 0 )
00163 return false;
00164 const bool bLoading = UMLApp::app()->getDocument()->loading();
00165
00166 if( count == 1 || pointIndex == 1) {
00167 QCanvasLine * first = m_LineList.first();
00168 QPoint sp = first -> startPoint();
00169 QPoint ep = first -> endPoint();
00170 first -> setPoints( sp.x(), sp.y(), point.x(), point.y() );
00171 QCanvasLine * line = new QCanvasLine( getCanvas() );
00172 line -> setZ( -2 );
00173 line -> setPoints( point.x(), point.y(), ep.x(), ep.y() );
00174 line -> setPen( getPen() );
00175 line -> setVisible( true );
00176 m_LineList.insert( 1, line );
00177 if (!bLoading)
00178 setupSelected();
00179 return true;
00180 }
00181 if( count + 1 == pointIndex ) {
00182 QCanvasLine * before = m_LineList.last();
00183 QPoint sp = before -> startPoint();
00184 QPoint ep = before -> endPoint();
00185 before -> setPoints( sp.x(), sp.y(), point.x(), point.y() );
00186 QCanvasLine * line = new QCanvasLine( getCanvas() );
00187 line -> setPoints( point.x(), point.y(), ep.x(), ep.y() );
00188 line -> setZ( -2 );
00189 line -> setPen( getPen() );
00190 line -> setVisible( true );
00191 m_LineList.append( line );
00192 if (!bLoading)
00193 setupSelected();
00194 return true;
00195 }
00196 QCanvasLine * before = m_LineList.at( pointIndex - 1 );
00197 QPoint sp = before -> startPoint();
00198 QPoint ep = before -> endPoint();
00199 before -> setPoints( sp.x(), sp.y(), point.x(), point.y() );
00200 QCanvasLine * line = new QCanvasLine(getCanvas() );
00201 line -> setPoints( point.x(), point.y(), ep.x(), ep.y() );
00202 line -> setZ( -2 );
00203 line -> setPen( getPen() );
00204 line -> setVisible( true );
00205 m_LineList.insert( pointIndex, line );
00206 if (!bLoading)
00207 setupSelected();
00208 return true;
00209 }
00210
00211 bool LinePath::removePoint( int pointIndex, const QPoint &point, unsigned short delta )
00212 {
00213
00214 int count = m_LineList.count();
00215 if ( pointIndex >= count )
00216 return false;
00217
00218
00219
00220 QCanvasLine * current_line = m_LineList.at( pointIndex );
00221 if (abs( current_line -> endPoint().x() - point.x() ) <= delta
00222 &&
00223 abs( current_line -> endPoint().y() - point.y() ) <= delta)
00224 {
00225
00226
00227 if (pointIndex >= count - 1)
00228 return false;
00229
00230
00231
00232 QCanvasLine * next_line = m_LineList.at( pointIndex + 1 );
00233 QPoint startPoint = current_line -> startPoint();
00234 QPoint endPoint = next_line -> endPoint();
00235 next_line -> setPoints(startPoint.x(), startPoint.y(),
00236 endPoint.x(), endPoint.y());
00237
00238 } else
00239 if (abs( current_line -> startPoint().x() - point.x() ) <= delta
00240 &&
00241 abs( current_line -> startPoint().y() - point.y() ) <= delta)
00242 {
00243
00244
00245 if (pointIndex < 1)
00246 return false;
00247
00248
00249
00250 QCanvasLine * previous_line = m_LineList.at( pointIndex - 1 );
00251 QPoint startPoint = previous_line -> startPoint();
00252 QPoint endPoint = current_line -> endPoint();
00253 previous_line -> setPoints(startPoint.x(), startPoint.y(),
00254 endPoint.x(), endPoint.y());
00255 } else {
00256
00257
00258 return false;
00259 }
00260
00261
00262
00263 m_LineList.remove( pointIndex );
00264
00265 return true;
00266 }
00267
00268 bool LinePath::setStartEndPoints( const QPoint &start, const QPoint &end ) {
00269 int count = m_LineList.count();
00270
00271 if( count == 0 ) {
00272 QCanvasLine * line = new QCanvasLine(getCanvas() );
00273 line -> setPoints( start.x(), start.y(), end.x(), end.y() );
00274 line -> setZ( -2 );
00275 line -> setPen( getPen() );
00276 line -> setVisible( true );
00277 m_LineList.append( line );
00278 return true;
00279 }
00280 bool status = setPoint( 0, start );
00281 if( status)
00282 return setPoint( count , end );
00283 return false;
00284 }
00285
00286 int LinePath::count() {
00287 return m_LineList.count() + 1;
00288 }
00289
00290 int LinePath::onLinePath( const QPoint &position ) {
00291 QCanvasItemList list = getCanvas() -> collisions( position );
00292 int index = -1;
00293
00294 QCanvasItemList::iterator end(list.end());
00295 for(QCanvasItemList::iterator item_it(list.begin()); item_it != end; ++item_it ) {
00296 if( ( index = m_LineList.findRef( (QCanvasLine*)*item_it ) ) != -1 )
00297 break;
00298 }
00299 return index;
00300 }
00301
00302 void LinePath::setSelected( bool select ) {
00303 if(select)
00304 setupSelected();
00305 else if( m_RectList.count() > 0 )
00306 m_RectList.clear();
00307 }
00308
00309 void LinePath::setAssocType( Uml::Association_Type type ) {
00310 LineListIt it( m_LineList );
00311 QCanvasLine * line = 0;
00312 while( ( line = it.current() ) ) {
00313 line -> setPen( getPen() );
00314 ++it;
00315 }
00316 if( m_pClearPoly ) {
00317 delete m_pClearPoly;
00318 m_pClearPoly = 0;
00319 }
00320 if( type == Uml::at_Coll_Message )
00321 setupParallelLine();
00322 else
00323 createHeadLines();
00324 update();
00325 }
00326
00327 void LinePath::update() {
00328 if (getAssocType() == Uml::at_Coll_Message) {
00329 if (m_bParallelLineCreated) {
00330 calculateParallelLine();
00331 updateParallelLine();
00332 } else
00333 setupParallelLine();
00334 } else if (m_bHeadCreated) {
00335 calculateHead();
00336 updateHead();
00337 } else {
00338 createHeadLines();
00339 }
00340 }
00341
00342 void LinePath::slotLineColorChanged( Uml::IDType viewID ) {
00343 if(m_pAssociation->getUMLView()->getID() != viewID) {
00344 return;
00345 }
00346 setLineColor( m_pAssociation->getUMLView()->getLineColor() );
00347 }
00348
00349
00350 void LinePath::setLineColor( const QColor &color ) {
00351 QCanvasLine * line = 0;
00352 uint linewidth = 0;
00353 LineListIt it( m_LineList );
00354 while( ( line = it.current() ) ) {
00355 linewidth = line->pen().width();
00356 line -> setPen( QPen( color, linewidth ) );
00357 ++it;
00358 }
00359 LineListIt hit( m_HeadList );
00360 while( ( line = hit.current() ) ) {
00361 linewidth = line->pen().width();
00362 line -> setPen( QPen( color, linewidth ) );
00363 ++hit;
00364 }
00365 LineListIt pit( m_ParallelList );
00366 while( ( line = pit.current() ) ) {
00367 linewidth = line->pen().width();
00368 line -> setPen( QPen( color, linewidth ) );
00369 ++pit;
00370 }
00371
00372 if( getAssocType() == Uml::at_Aggregation )
00373 if (m_pClearPoly) m_pClearPoly -> setBrush( QBrush( Qt::white ) );
00374 else if( getAssocType() == Uml::at_Composition )
00375 if (m_pClearPoly) m_pClearPoly -> setBrush( QBrush( color ) );
00376
00377 if( m_pCircle ) {
00378 linewidth = m_pCircle->pen().width();
00379 m_pCircle->setPen( QPen(color, linewidth) );
00380 }
00381 }
00382
00383 void LinePath::slotLineWidthChanged( Uml::IDType viewID ) {
00384 if(m_pAssociation->getUMLView()->getID() != viewID) {
00385 return;
00386 }
00387 setLineWidth( m_pAssociation->getUMLView()->getLineWidth() );
00388 }
00389
00390 void LinePath::setLineWidth( uint width ) {
00391 QCanvasLine * line = 0;
00392 QColor linecolor;
00393 LineListIt it( m_LineList );
00394 while( ( line = it.current() ) ) {
00395 linecolor = line->pen().color();
00396 line -> setPen( QPen( linecolor, width ) );
00397 ++it;
00398 }
00399 LineListIt hit( m_HeadList );
00400 while( ( line = hit.current() ) ) {
00401 linecolor = line->pen().color();
00402 line -> setPen( QPen( linecolor, width ) );
00403 ++hit;
00404 }
00405 LineListIt pit( m_ParallelList );
00406 while( ( line = pit.current() ) ) {
00407 linecolor = line->pen().color();
00408 line -> setPen( QPen( linecolor, width ) );
00409 ++pit;
00410 }
00411
00412 if( m_pCircle ) {
00413 linecolor = m_pCircle->pen().color();
00414 m_pCircle->setPen( QPen(linecolor, width) );
00415 }
00416 }
00417
00418 void LinePath::moveSelected( int pointIndex ) {
00419 int lineCount = m_LineList.count();
00420 if( !m_bSelected ) {
00421 m_RectList.clear();
00422 return;
00423 }
00424 if( (int)m_RectList.count() + 1 != lineCount )
00425 setupSelected();
00426 QCanvasRectangle * rect = 0;
00427 QCanvasLine * line = 0;
00428 if( pointIndex == lineCount || lineCount == 1) {
00429 line = m_LineList.last();
00430 QPoint p = line -> endPoint();
00431 rect = m_RectList.last();
00432 rect -> setX( p.x() );
00433 rect -> setY( p.y() );
00434 rect -> setZ( 4 );
00435 return;
00436 }
00437 line = m_LineList.at( pointIndex );
00438 QPoint p = line -> startPoint();
00439 rect = m_RectList.at( pointIndex );
00440 rect -> setX( p.x() );
00441 rect -> setY( p.y() );
00442 rect -> setZ( 4 );
00443 }
00444
00445 void LinePath::setupSelected() {
00446 m_RectList.clear();
00447 QCanvasLine * line = 0;
00448 LineListIt it( m_LineList );
00449 while( ( line = it.current() ) ) {
00450 QPoint sp = line -> startPoint();
00451 QCanvasRectangle *rect = Widget_Utils::decoratePoint(sp);
00452 m_RectList.append( rect );
00453 ++it;
00454 }
00455
00456 line = m_LineList.last();
00457 QPoint p = line -> endPoint();
00458 QCanvasRectangle *rect = Widget_Utils::decoratePoint(p);
00459 m_RectList.append( rect );
00460 update();
00461 }
00462
00463 QPen LinePath::getPen() {
00464 Uml::Association_Type type = getAssocType();
00465 if( type == Uml::at_Dependency || type == Uml::at_Realization || type == Uml::at_Anchor )
00466 return QPen( getLineColor(), getLineWidth(), Qt::DashLine );
00467 return QPen( getLineColor(), getLineWidth() );
00468 }
00469
00470 void LinePath::calculateHead() {
00471 uint size = m_LineList.count();
00472 QPoint farPoint;
00473 int halfLength = 10;
00474 double arrowAngle = 0.2618;
00475 Uml::Association_Type at = getAssocType();
00476 bool diamond = (at == Uml::at_Aggregation || at == Uml::at_Composition);
00477 if (diamond || at == Uml::at_Containment) {
00478 farPoint = getPoint(1);
00479 m_EgdePoint = getPoint(0);
00480 if (diamond) {
00481 arrowAngle *= 1.5;
00482 halfLength += 1;
00483 } else {
00484
00485
00486
00487
00488
00489 arrowAngle *= 2.5;
00490 halfLength -= 4;
00491 }
00492 } else {
00493 farPoint = getPoint(size - 1);
00494 m_EgdePoint = getPoint(size);
00495
00496 arrowAngle *= 2.0;
00497 halfLength += 3;
00498 }
00499 int xa = farPoint.x();
00500 int ya = farPoint.y();
00501 int xb = m_EgdePoint.x();
00502 int yb = m_EgdePoint.y();
00503 double deltaX = xb - xa;
00504 double deltaY = yb - ya;
00505 double hypotenuse = sqrt(deltaX*deltaX + deltaY*deltaY);
00506 double slope = atan2(deltaY, deltaX);
00507 double arrowSlope = slope + arrowAngle;
00508 double cosx, siny;
00509 if (hypotenuse < 1.0e-6) {
00510 cosx = 1.0;
00511 siny = 0.0;
00512 } else {
00513 cosx = halfLength * deltaX/hypotenuse;
00514 siny = halfLength * deltaY/hypotenuse;
00515 }
00516
00517 m_ArrowPointA.setX( (int)rint(xb - halfLength * cos(arrowSlope)) );
00518 m_ArrowPointA.setY( (int)rint(yb - halfLength * sin(arrowSlope)) );
00519 arrowSlope = slope - arrowAngle;
00520 m_ArrowPointB.setX( (int)rint(xb - halfLength * cos(arrowSlope)) );
00521 m_ArrowPointB.setY( (int)rint(yb - halfLength * sin(arrowSlope)) );
00522
00523 if(xa > xb)
00524 cosx = cosx > 0 ? cosx : cosx * -1;
00525 else
00526 cosx = cosx > 0 ? cosx * -1: cosx;
00527
00528 if(ya > yb)
00529 siny = siny > 0 ? siny : siny * -1;
00530 else
00531 siny = siny > 0 ? siny * -1 : siny;
00532
00533 m_MidPoint.setX( (int)rint(xb + cosx) );
00534 m_MidPoint.setY( (int)rint(yb + siny) );
00535
00536 m_PointArray.setPoint(0, m_EgdePoint);
00537 m_PointArray.setPoint(1, m_ArrowPointA);
00538 if( getAssocType() == Uml::at_Realization ||
00539 getAssocType() == Uml::at_Generalization ) {
00540 m_PointArray.setPoint( 2, m_ArrowPointB );
00541 m_PointArray.setPoint( 3, m_EgdePoint );
00542 } else {
00543 QPoint diamondFarPoint;
00544 diamondFarPoint.setX( (int)rint(xb + cosx * 2) );
00545 diamondFarPoint.setY( (int)rint(yb + siny * 2) );
00546 m_PointArray.setPoint(2, diamondFarPoint);
00547 m_PointArray.setPoint(3, m_ArrowPointB);
00548 }
00549
00550 }
00551
00552 void LinePath::updateHead() {
00553 int count = m_HeadList.count();
00554 QCanvasLine * line = 0;
00555
00556 switch( getAssocType() ) {
00557 case Uml::at_State:
00558 case Uml::at_Activity:
00559 case Uml::at_UniAssociation:
00560 case Uml::at_Dependency:
00561 if( count < 2)
00562 return;
00563 line = m_HeadList.at( 0 );
00564 line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointA.x(), m_ArrowPointA.y() );
00565
00566 line = m_HeadList.at( 1 );
00567 line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointB.x(), m_ArrowPointB.y() );
00568 break;
00569
00570 case Uml::at_Relationship:
00571 if (count < 2) {
00572 return;
00573 }
00574 {
00575 int xoffset = 0;
00576 int yoffset = 0;
00577 if( m_DockRegion == TopBottom )
00578 xoffset = 8;
00579 else
00580 yoffset = 8;
00581 line = m_HeadList.at( 0 );
00582 line->setPoints( m_PointArray[2].x(), m_PointArray[2].y(),
00583 m_PointArray[0].x()-xoffset, m_PointArray[0].y()-yoffset );
00584
00585 line = m_HeadList.at( 1 );
00586 line->setPoints( m_PointArray[2].x(), m_PointArray[2].y(),
00587 m_PointArray[0].x()+xoffset, m_PointArray[0].y()+yoffset );
00588 }
00589
00590 case Uml::at_Generalization:
00591 case Uml::at_Realization:
00592 if( count < 3)
00593 return;
00594 line = m_HeadList.at( 0 );
00595 line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointA.x(), m_ArrowPointA.y() );
00596
00597 line = m_HeadList.at( 1 );
00598 line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointB.x(), m_ArrowPointB.y() );
00599
00600 line = m_HeadList.at( 2 );
00601 line -> setPoints( m_ArrowPointA.x(), m_ArrowPointA.y(), m_ArrowPointB.x(), m_ArrowPointB.y() );
00602 m_pClearPoly -> setPoints( m_PointArray );
00603 break;
00604
00605 case Uml::at_Composition:
00606 case Uml::at_Aggregation:
00607 if( count < 4)
00608 return;
00609 line = m_HeadList.at( 0 );
00610 line -> setPoints( m_PointArray[ 0 ].x(), m_PointArray[ 0 ].y(), m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y() );
00611
00612 line = m_HeadList.at( 1 );
00613 line -> setPoints( m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y(), m_PointArray[ 2 ].x(), m_PointArray[ 2 ].y() );
00614
00615 line = m_HeadList.at( 2 );
00616 line -> setPoints( m_PointArray[ 2 ].x(), m_PointArray[ 2 ].y(), m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y() );
00617
00618 line = m_HeadList.at( 3 );
00619 line -> setPoints( m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y(), m_PointArray[ 0 ].x(), m_PointArray[ 0 ].y() );
00620 m_pClearPoly -> setPoints( m_PointArray );
00621 break;
00622
00623 case Uml::at_Containment:
00624 if (count < 1)
00625 return;
00626 line = m_HeadList.at( 0 );
00627 line->setPoints( m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y(),
00628 m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y() );
00629 m_pCircle -> setX( m_MidPoint.x() );
00630 m_pCircle -> setY( m_MidPoint.y() );
00631 break;
00632 default:
00633 break;
00634 }
00635 }
00636
00637 void LinePath::growList(LineList &list, int by) {
00638 QPen pen( getLineColor(), getLineWidth() );
00639 for (int i = 0; i < by; i++) {
00640 QCanvasLine * line = new QCanvasLine( getCanvas() );
00641 line -> setZ( 0 );
00642 line -> setPen( pen );
00643 line -> setVisible( true );
00644 list.append( line );
00645 }
00646 }
00647
00648 void LinePath::createHeadLines() {
00649 m_HeadList.clear();
00650 QCanvas * canvas = getCanvas();
00651 switch( getAssocType() ) {
00652 case Uml::at_Activity:
00653 case Uml::at_State:
00654 case Uml::at_Dependency:
00655 case Uml::at_UniAssociation:
00656 case Uml::at_Relationship:
00657 growList(m_HeadList, 2);
00658 break;
00659
00660 case Uml::at_Generalization:
00661 case Uml::at_Realization:
00662 growList(m_HeadList, 3);
00663 m_pClearPoly = new QCanvasPolygon( canvas );
00664 m_pClearPoly -> setVisible( true );
00665 m_pClearPoly -> setBrush( QBrush( Qt::white ) );
00666 m_pClearPoly -> setZ( -1 );
00667 break;
00668
00669 case Uml::at_Composition:
00670 case Uml::at_Aggregation:
00671 growList(m_HeadList, 4);
00672 m_pClearPoly = new QCanvasPolygon( canvas );
00673 m_pClearPoly -> setVisible( true );
00674 if( getAssocType() == Uml::at_Aggregation )
00675 m_pClearPoly -> setBrush( QBrush( Qt::white ) );
00676 else
00677 m_pClearPoly -> setBrush( QBrush( getLineColor() ) );
00678 m_pClearPoly -> setZ( -1 );
00679 break;
00680
00681 case Uml::at_Containment:
00682 growList(m_HeadList, 1);
00683 if (!m_pCircle) {
00684 m_pCircle = new Circle( canvas, 6 );
00685 m_pCircle->show();
00686 m_pCircle->setPen( QPen( getLineColor(), getLineWidth() ) );
00687 }
00688 break;
00689 default:
00690 break;
00691 }
00692 m_bHeadCreated = true;
00693 }
00694
00695 void LinePath::calculateParallelLine() {
00696 int midCount = count() / 2;
00697 double ATAN = atan(1.0);
00698 int lineDist = 10;
00699
00700 QPoint a = getPoint( midCount - 1 );
00701 QPoint b = getPoint( midCount );
00702 int mx = ( a.x() + b.x() ) / 2;
00703 int my = ( a.y() + b.y() ) / 2;
00704 int tx = ( mx + b.x() ) / 2;
00705 int ty = ( my + b.y() ) / 2;
00706
00707 int distX = ( mx - tx );
00708 distX *= distX;
00709 int distY = ( my - ty );
00710 distY *= distY;
00711 double dist = sqrt( double(distX + distY) );
00712 double angle = atan2( double(ty - my), double(tx - mx) ) + ( ATAN * 2 );
00713
00714 double cosx = cos( angle ) * lineDist;
00715 double siny = sin( angle ) * lineDist;
00716 QPoint pointM( mx + (int)cosx, my + (int)siny );
00717
00718 distX = ( tx - b.x() );
00719 distX *= distX;
00720 distY = ( ty - b.y() );
00721 distY *= distY;
00722 dist = sqrt( double(distX + distY) );
00723
00724 cosx = cos( angle ) * lineDist;
00725 siny = sin( angle ) * lineDist;
00726 QPoint pointT( tx + (int)cosx, ty + (int)siny );
00727 m_ParallelLines[ 1 ] = pointM;
00728 m_ParallelLines[ 0 ] = pointT;
00729
00730 int arrowDist = 5;
00731 angle = atan2( double(pointT.y() - pointM.y()),
00732 double(pointT.x() - pointM.x()) );
00733 double arrowSlope = angle + ATAN;
00734 cosx = ( cos( arrowSlope ) ) * arrowDist;
00735 siny = ( sin( arrowSlope ) ) * arrowDist;
00736 m_ParallelLines[ 2 ] = QPoint( pointT.x() - (int)cosx, pointT.y() - (int)siny );
00737 arrowSlope = angle - ATAN;
00738 cosx = ( cos( arrowSlope ) ) * arrowDist;
00739 siny = ( sin( arrowSlope ) ) * arrowDist;
00740 m_ParallelLines[ 3 ] = QPoint( pointT.x() - (int)cosx, pointT.y() - (int)siny );
00741 }
00742
00743 void LinePath::setupParallelLine() {
00744 m_ParallelList.clear();
00745 growList(m_ParallelList, 3);
00746 m_bParallelLineCreated = true;
00747 }
00748
00749 void LinePath::updateParallelLine() {
00750 if( !m_bParallelLineCreated )
00751 return;
00752 QCanvasLine * line = 0;
00753 QPoint common = m_ParallelLines.at( 0 );
00754 QPoint p = m_ParallelLines.at( 1 );
00755 line = m_ParallelList.at( 0 );
00756 line -> setPoints( common.x(), common.y(), p.x(), p.y() );
00757
00758 p = m_ParallelLines.at( 2 );
00759 line = m_ParallelList.at( 1 );
00760 line -> setPoints( common.x(), common.y(), p.x(), p.y() );
00761
00762 p = m_ParallelLines.at( 3 );
00763 line = m_ParallelList.at( 2 );
00764 line -> setPoints( common.x(), common.y(), p.x(), p.y() );
00765 }
00766
00767 bool LinePath::operator==( LinePath & rhs ) {
00768 if( this -> m_LineList.count() != rhs.m_LineList.count() )
00769 return false;
00770
00771
00772 for( int i = 0; i< rhs.count() ; i++ ) {
00773 if( this -> getPoint( i ) != rhs.getPoint( i ) )
00774 return false;
00775 }
00776 return true;
00777 }
00778
00779 LinePath & LinePath::operator=( LinePath & rhs ) {
00780 if( this == &rhs )
00781 return *this;
00782
00783 this -> m_LineList.clear();
00784 this -> m_ParallelList.clear();
00785 this -> m_RectList.clear();
00786 this -> m_HeadList.clear();
00787 int count = rhs.m_LineList.count();
00788
00789 this -> setStartEndPoints( rhs.getPoint( 0 ), rhs.getPoint( count) );
00790
00791 for( int i = 1; i < count ; i++ ) {
00792 this -> insertPoint( i, rhs.getPoint ( i ) );
00793 }
00794 this -> setAssocType( rhs.getAssocType() );
00795
00796 return *this;
00797 }
00798
00799 QCanvas * LinePath::getCanvas() {
00800 if( !m_pAssociation )
00801 return 0;
00802 const UMLView * view = m_pAssociation->getUMLView();
00803 return view -> canvas();
00804 }
00805
00806 Uml::Association_Type LinePath::getAssocType() {
00807 if( m_pAssociation )
00808 return m_pAssociation -> getAssocType();
00809 return Uml::at_Association;
00810 }
00811
00812 QColor LinePath::getLineColor() {
00813 if( !m_pAssociation )
00814 return Qt::black;
00815 return m_pAssociation -> getLineColor();
00816 }
00817
00818 uint LinePath::getLineWidth() {
00819 if( !m_pAssociation )
00820 return 0;
00821 int viewLineWidth = m_pAssociation -> getLineWidth();
00822 if ( viewLineWidth >= 0 && viewLineWidth <= 10 )
00823 return viewLineWidth;
00824 else {
00825 kWarning() << "Ignore wrong LineWidth of " << viewLineWidth
00826 << " in LinePath::getLineWidth" << endl;
00827 return 0;
00828 }
00829 }
00830
00831 void LinePath::cleanup() {
00832 if (m_pAssociation)
00833 m_LineList.clear();
00834 m_HeadList.clear();
00835 m_RectList.clear();
00836 m_ParallelList.clear();
00837
00838 if( m_pClearPoly )
00839 delete m_pClearPoly;
00840 if( m_pCircle )
00841 delete m_pCircle;
00842 m_pCircle = 0;
00843 m_pClearPoly = 0;
00844 m_bHeadCreated = m_bParallelLineCreated = false;
00845 if( m_pAssociation ) {
00846 UMLView * view = (UMLView *)m_pAssociation -> parent();
00847 if(view) {
00848 disconnect( view, SIGNAL( sigColorChanged( Uml::IDType ) ), this, SLOT( slotLineColorChanged( Uml::IDType ) ) );
00849 disconnect( view, SIGNAL( sigLineWidthChanged( Uml::IDType ) ), this, SLOT( slotLineWidthChanged( Uml::IDType ) ) );
00850 }
00851 m_pAssociation = NULL;
00852 }
00853 }
00854
00855 void LinePath::setDockRegion( Region region ) {
00856 m_DockRegion = region;
00857 }
00858
00859 bool LinePath::hasPoints () {
00860 int count = m_LineList.count();
00861 if (count>1)
00862 return true;
00863 return false;
00864 }
00865 void LinePath::dumpPoints () {
00866 int count = m_LineList.count();
00867 for( int i = 1; i < count; i++ ) {
00868 QPoint point = getPoint( i );
00869 kDebug()<<" * point x:"<<point.x()<<" y:"<<point.y()<<endl;
00870 }
00871 }
00872
00873 void LinePath::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
00874 int count = m_LineList.count();
00875 QPoint point = getPoint( 0 );
00876 QDomElement lineElement = qDoc.createElement( "linepath" );
00877 QDomElement startElement = qDoc.createElement( "startpoint" );
00878 startElement.setAttribute( "startx", point.x() );
00879 startElement.setAttribute( "starty", point.y() );
00880 lineElement.appendChild( startElement );
00881 QDomElement endElement = qDoc.createElement( "endpoint" );
00882 point = getPoint( count );
00883 endElement.setAttribute( "endx", point.x() );
00884 endElement.setAttribute( "endy", point.y() );
00885 lineElement.appendChild( endElement );
00886 for( int i = 1; i < count; i++ ) {
00887 QDomElement pointElement = qDoc.createElement( "point" );
00888 point = getPoint( i );
00889 pointElement.setAttribute( "x", point.x() );
00890 pointElement.setAttribute( "y", point.y() );
00891 lineElement.appendChild( pointElement );
00892 }
00893 qElement.appendChild( lineElement );
00894 }
00895
00896 bool LinePath::loadFromXMI( QDomElement & qElement ) {
00897 QDomNode node = qElement.firstChild();
00898 QDomElement startElement = node.toElement();
00899 if( startElement.isNull() || startElement.tagName() != "startpoint" )
00900 return false;
00901 QString x = startElement.attribute( "startx", "0" );
00902 int nX = x.toInt();
00903 QString y = startElement.attribute( "starty", "0" );
00904 int nY = y.toInt();
00905 QPoint startPoint( nX, nY );
00906
00907 node = startElement.nextSibling();
00908 QDomElement endElement = node.toElement();
00909 if( endElement.isNull() || endElement.tagName() != "endpoint" )
00910 return false;
00911 x = endElement.attribute( "endx", "0" );
00912 nX = x.toInt();
00913 y = endElement.attribute( "endy", "0" );
00914 nY = y.toInt();
00915 QPoint endPoint( nX, nY );
00916 setStartEndPoints( startPoint, endPoint );
00917 QPoint point;
00918 node = endElement.nextSibling();
00919 QDomElement element = node.toElement();
00920 int i = 1;
00921 while( !element.isNull() ) {
00922 if( element.tagName() == "point" ) {
00923 x = element.attribute( "x", "0" );
00924 y = element.attribute( "y", "0" );
00925 point.setX( x.toInt() );
00926 point.setY( y.toInt() );
00927 insertPoint( i++, point );
00928 }
00929 node = element.nextSibling();
00930 element = node.toElement();
00931 }
00932
00933 return true;
00934 }
00935
00936
00937 void LinePath::activate() {
00938 int count = m_LineList.count();
00939 if (count == 0)
00940 return;
00941 QCanvas * canvas = getCanvas();
00942 if (canvas == NULL)
00943 return;
00944 for (int i = 0; i < count ; i++) {
00945 QCanvasLine *line = m_LineList.at(i);
00946 line -> setCanvas( canvas );
00947 line -> setPen( getPen() );
00948 }
00949 }
00950
00951
00952
00953 #include "linepath.moc"