void LinePath::setLineColor( const QColor &color ) { QCanvasLine * line = 0; uint linewidth = 0; LineListIt it( m_LineList ); while( ( line = it.current() ) ) { linewidth = line->pen().width(); line -> setPen( QPen( color, linewidth ) ); ++it; } LineListIt hit( m_HeadList ); while( ( line = hit.current() ) ) { linewidth = line->pen().width(); line -> setPen( QPen( color, linewidth ) ); ++hit; } LineListIt pit( m_ParallelList ); while( ( line = pit.current() ) ) { linewidth = line->pen().width(); line -> setPen( QPen( color, linewidth ) ); ++pit; } if( getAssocType() == Uml::at_Aggregation ) if (m_pClearPoly) m_pClearPoly -> setBrush( QBrush( Qt::white ) ); else if( getAssocType() == Uml::at_Composition ) if (m_pClearPoly) m_pClearPoly -> setBrush( QBrush( color ) ); if( m_pCircle ) { linewidth = m_pCircle->pen().width(); m_pCircle->setPen( QPen(color, linewidth) ); } }
void LinePath::createHeadLines() { m_HeadList.clear(); QCanvas * canvas = getCanvas(); switch( getAssocType() ) { case Uml::at_Activity: case Uml::at_State: case Uml::at_Dependency: case Uml::at_UniAssociation: case Uml::at_Relationship: growList(m_HeadList, 2); break; case Uml::at_Generalization: case Uml::at_Realization: growList(m_HeadList, 3); m_pClearPoly = new QCanvasPolygon( canvas ); m_pClearPoly -> setVisible( true ); m_pClearPoly -> setBrush( QBrush( Qt::white ) ); m_pClearPoly -> setZ( -1 ); break; case Uml::at_Composition: case Uml::at_Aggregation: growList(m_HeadList, 4); m_pClearPoly = new QCanvasPolygon( canvas ); m_pClearPoly -> setVisible( true ); if( getAssocType() == Uml::at_Aggregation ) m_pClearPoly -> setBrush( QBrush( Qt::white ) ); else m_pClearPoly -> setBrush( QBrush( getLineColor() ) ); m_pClearPoly -> setZ( -1 ); break; case Uml::at_Containment: growList(m_HeadList, 1); if (!m_pCircle) { m_pCircle = new Circle( canvas, 6 ); m_pCircle->show(); m_pCircle->setPen( QPen( getLineColor(), getLineWidth() ) ); } break; default: break; } m_bHeadCreated = true; }
void LinePath::setAssociation(AssociationWidget * association ) { if( !association ) return; cleanup(); m_pAssociation = association; createHeadLines(); if( getAssocType() == Uml::at_Coll_Message ) setupParallelLine(); UMLView * view = (UMLView *)m_pAssociation -> parent(); connect( view, SIGNAL( sigColorChanged( Uml::IDType ) ), this, SLOT( slotLineColorChanged( Uml::IDType ) ) ); connect( view, SIGNAL( sigLineWidthChanged( Uml::IDType ) ), this, SLOT( slotLineWidthChanged( Uml::IDType ) ) ); }
void LinePath::update() { if (getAssocType() == Uml::at_Coll_Message) { if (m_bParallelLineCreated) { calculateParallelLine(); updateParallelLine(); } else setupParallelLine(); } else if (m_bHeadCreated) { calculateHead(); updateHead(); } else { createHeadLines(); } }
/** * This will setup the class ready to display the line correctly. * This MUST be called before you can use this class. */ void AssociationLine::setAssociation(AssociationWidget * association) { if( !association ) return; cleanup(); m_pAssociation = association; createHeadLines(); createSubsetSymbol(); if( getAssocType() == Uml::AssociationType::Coll_Message ) setupParallelLine(); UMLView * view = (UMLView *)m_pAssociation->parent(); if (view) { connect(view, SIGNAL(sigColorChanged(Uml::IDType)), this, SLOT(slotLineColorChanged(Uml::IDType))); connect(view, SIGNAL(sigLineWidthChanged(Uml::IDType)), this, SLOT(slotLineWidthChanged(Uml::IDType))); } else { uWarning() << "Parent is null. Can not connect SIGNAL/SLOT."; } }
/** * Calls a group of methods to update the line. Used to save you calling multiple methods. */ void AssociationLine::update() { if (getAssocType() == Uml::AssociationType::Coll_Message) { if (m_bParallelLineCreated) { calculateParallelLine(); updateParallelLine(); } else setupParallelLine(); } else if (m_bHeadCreated) { calculateHead(); updateHead(); } else { createHeadLines(); } if ( m_bSubsetSymbolCreated ) { updateSubsetSymbol(); } else { createSubsetSymbol(); } }
void LinePath::updateHead() { int count = m_HeadList.count(); QCanvasLine * line = 0; switch( getAssocType() ) { case Uml::at_State: case Uml::at_Activity: case Uml::at_UniAssociation: case Uml::at_Dependency: if( count < 2) return; line = m_HeadList.at( 0 ); line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointA.x(), m_ArrowPointA.y() ); line = m_HeadList.at( 1 ); line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointB.x(), m_ArrowPointB.y() ); break; case Uml::at_Relationship: if (count < 2) { return; } { int xoffset = 0; int yoffset = 0; if( m_DockRegion == TopBottom ) xoffset = 8; else yoffset = 8; line = m_HeadList.at( 0 ); line->setPoints( m_PointArray[2].x(), m_PointArray[2].y(), m_PointArray[0].x()-xoffset, m_PointArray[0].y()-yoffset ); line = m_HeadList.at( 1 ); line->setPoints( m_PointArray[2].x(), m_PointArray[2].y(), m_PointArray[0].x()+xoffset, m_PointArray[0].y()+yoffset ); } case Uml::at_Generalization: case Uml::at_Realization: if( count < 3) return; line = m_HeadList.at( 0 ); line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointA.x(), m_ArrowPointA.y() ); line = m_HeadList.at( 1 ); line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointB.x(), m_ArrowPointB.y() ); line = m_HeadList.at( 2 ); line -> setPoints( m_ArrowPointA.x(), m_ArrowPointA.y(), m_ArrowPointB.x(), m_ArrowPointB.y() ); m_pClearPoly -> setPoints( m_PointArray ); break; case Uml::at_Composition: case Uml::at_Aggregation: if( count < 4) return; line = m_HeadList.at( 0 ); line -> setPoints( m_PointArray[ 0 ].x(), m_PointArray[ 0 ].y(), m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y() ); line = m_HeadList.at( 1 ); line -> setPoints( m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y(), m_PointArray[ 2 ].x(), m_PointArray[ 2 ].y() ); line = m_HeadList.at( 2 ); line -> setPoints( m_PointArray[ 2 ].x(), m_PointArray[ 2 ].y(), m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y() ); line = m_HeadList.at( 3 ); line -> setPoints( m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y(), m_PointArray[ 0 ].x(), m_PointArray[ 0 ].y() ); m_pClearPoly -> setPoints( m_PointArray ); break; case Uml::at_Containment: if (count < 1) return; line = m_HeadList.at( 0 ); line->setPoints( m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y(), m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y() ); m_pCircle -> setX( m_MidPoint.x() ); m_pCircle -> setY( m_MidPoint.y() ); break; default: break; } }
void LinePath::calculateHead() { uint size = m_LineList.count(); QPoint farPoint; int halfLength = 10; double arrowAngle = 0.2618; // 0.5 * atan(sqrt(3.0) / 3.0) = 0.2618 Uml::Association_Type at = getAssocType(); bool diamond = (at == Uml::at_Aggregation || at == Uml::at_Composition); if (diamond || at == Uml::at_Containment) { farPoint = getPoint(1); m_EgdePoint = getPoint(0); if (diamond) { arrowAngle *= 1.5; // wider halfLength += 1; // longer } else { // Containment has a circle-plus symbol at the // containing object. What we are tweaking here // is the perpendicular line through the circle // (i.e. the horizontal line of the plus sign if // the objects are oriented north/south) arrowAngle *= 2.5; // wider halfLength -= 4; // shorter } } else { farPoint = getPoint(size - 1); m_EgdePoint = getPoint(size); // We have an arrow. arrowAngle *= 2.0; // wider halfLength += 3; // longer } int xa = farPoint.x(); int ya = farPoint.y(); int xb = m_EgdePoint.x(); int yb = m_EgdePoint.y(); double deltaX = xb - xa; double deltaY = yb - ya; double hypotenuse = sqrt(deltaX*deltaX + deltaY*deltaY); // the length double slope = atan2(deltaY, deltaX); //slope of line double arrowSlope = slope + arrowAngle; double cosx, siny; if (hypotenuse < 1.0e-6) { cosx = 1.0; siny = 0.0; } else { cosx = halfLength * deltaX/hypotenuse; siny = halfLength * deltaY/hypotenuse; } m_ArrowPointA.setX( (int)rint(xb - halfLength * cos(arrowSlope)) ); m_ArrowPointA.setY( (int)rint(yb - halfLength * sin(arrowSlope)) ); arrowSlope = slope - arrowAngle; m_ArrowPointB.setX( (int)rint(xb - halfLength * cos(arrowSlope)) ); m_ArrowPointB.setY( (int)rint(yb - halfLength * sin(arrowSlope)) ); if(xa > xb) cosx = cosx > 0 ? cosx : cosx * -1; else cosx = cosx > 0 ? cosx * -1: cosx; if(ya > yb) siny = siny > 0 ? siny : siny * -1; else siny = siny > 0 ? siny * -1 : siny; m_MidPoint.setX( (int)rint(xb + cosx) ); m_MidPoint.setY( (int)rint(yb + siny) ); m_PointArray.setPoint(0, m_EgdePoint); m_PointArray.setPoint(1, m_ArrowPointA); if( getAssocType() == Uml::at_Realization || getAssocType() == Uml::at_Generalization ) { m_PointArray.setPoint( 2, m_ArrowPointB ); m_PointArray.setPoint( 3, m_EgdePoint ); } else { QPoint diamondFarPoint; diamondFarPoint.setX( (int)rint(xb + cosx * 2) ); diamondFarPoint.setY( (int)rint(yb + siny * 2) ); m_PointArray.setPoint(2, diamondFarPoint); m_PointArray.setPoint(3, m_ArrowPointB); } }
QPen LinePath::getPen() { Uml::Association_Type type = getAssocType(); if( type == Uml::at_Dependency || type == Uml::at_Realization || type == Uml::at_Anchor ) return QPen( getLineColor(), getLineWidth(), Qt::DashLine ); return QPen( getLineColor(), getLineWidth() ); }