[Uml-devel] branches/work/soc-umbrello/umbrello/widgets

Gopala Krishna A krishna.ggk at gmail.com
Sat Aug 8 16:40:45 UTC 2009


SVN commit 1008913 by gopala:

* Implemented collaboration line support for AssociationLine.



 M  +188 -104  associationline.cpp  
 M  +17 -7     associationline.h  
 M  +2 -1      associationwidget.cpp  


--- branches/work/soc-umbrello/umbrello/widgets/associationline.cpp #1008912:1008913
@@ -267,8 +267,6 @@
 }
 
 
-
-
 // Initialize static variables.
 const qreal AssociationLine::Delta = 5;
 const qreal AssociationLine::SelectedPointDiameter = 8;
@@ -284,6 +282,8 @@
     m_activePointIndex = m_activeSegmentIndex = -1;
     m_startSymbol = m_endSymbol = m_subsetSymbol = 0;
     m_associationClassLine = 0;
+    m_collaborationLineHead = 0;
+    m_collaborationLineItem = 0;
     // This tracker is only for debugging and testing purpose.
     tracker = new QGraphicsLineItem;
     tracker->setPen(QPen(Qt::darkBlue, 1));
@@ -498,105 +498,6 @@
 }
 
 /**
- * Sets the Symbol to appear at the first line segment to \a
- * symbol.
- *
- * If symbol == Symbol::None , then it deletes the symbol item.
- *
- * Also this method aligns the symbols.
- */
-void AssociationLine::setStartSymbol(Symbol::SymbolType symbolType)
-{
-    Q_ASSERT(symbolType != Symbol::Count);
-    if (symbolType == Symbol::None) {
-        delete m_startSymbol;
-        m_startSymbol = 0;
-        return;
-    }
-
-    if (m_startSymbol) {
-        m_startSymbol->setSymbolType(symbolType);
-    }
-    else {
-        m_startSymbol = new Symbol(symbolType, m_associationWidget);
-    }
-    m_startSymbol->setPen(pen());
-    alignSymbols();
-}
-
-/**
- * Sets the Symbol to appear at the last line segment to \a
- * symbol.
- *
- * If symbol == Symbol::None , then it deletes the symbol item.
- *
- * Also this method aligns the symbols.
- */
-void AssociationLine::setEndSymbol(Symbol::SymbolType symbolType)
-{
-    Q_ASSERT(symbolType != Symbol::Count);
-    if (symbolType == Symbol::None) {
-        delete m_endSymbol;
-        m_endSymbol = 0;
-        return;
-    }
-
-    if (m_endSymbol) {
-        m_endSymbol->setSymbolType(symbolType);
-    }
-    else {
-        m_endSymbol = new Symbol(symbolType, m_associationWidget);
-    }
-    m_endSymbol->setPen(pen());
-    alignSymbols();
-}
-
-/**
- * Creates a subset symbol and aligns it.
- */
-void AssociationLine::createSubsetSymbol()
-{
-    if (m_subsetSymbol) {
-        return;
-    }
-    m_subsetSymbol = new Symbol(Symbol::Subset, m_associationWidget);
-    m_subsetSymbol->setPen(pen());
-    alignSymbols();
-}
-
-/**
- * This method aligns both the \b "start" and \b "end" symbols to
- * the current angles of the \b "first" and the \b "last" line
- * segment respectively.
- */
-void AssociationLine::alignSymbols()
-{
-    const int sz = m_points.size();
-    if (sz < 2) {
-        // Cannot align if there is no line (one line = 2 points)
-        return;
-    }
-
-    if (m_startSymbol) {
-        QLineF segment(m_points[1], m_points[0]);
-        m_startSymbol->alignTo(segment);
-    }
-
-    if (m_endSymbol) {
-        QLineF segment(m_points[sz-2], m_points[sz - 1]);
-        m_endSymbol->alignTo(segment);
-    }
-
-    if (m_subsetSymbol) {
-        QLineF segment(m_points.at(0), (m_points.at(0) + m_points.at(1)) * .5);
-        uDebug() << "points: " << m_points.at(0) << m_points.at(1);
-        uDebug() << "segment: " << segment;
-        m_subsetSymbol->alignTo(segment);
-    }
-}
-
-
-/**
  * Loads AssociationLine information saved in \a qElement XMI element.
  */
 bool AssociationLine::loadFromXMI(QDomElement &qElement)
@@ -1148,10 +1049,12 @@
 }
 
 /**
- * This method creates appropriate symbols based on type of
- * m_associationWidget.
+ * This method creates, deletes symbols and collaboration lines based on
+ * m_associationWidget->associationType().
+ *
+ * Call this method when associationType of m_associationWidget changes.
  */
-void AssociationLine::setupSymbols()
+void AssociationLine::reconstructSymbols()
 {
     switch( m_associationWidget->associationType() ) {
         case Uml::at_State:
@@ -1159,28 +1062,209 @@
         case Uml::at_Exception:
         case Uml::at_UniAssociation:
         case Uml::at_Dependency:
+            setStartSymbol(Symbol::None);
             setEndSymbol(Symbol::OpenArrow);
+            removeSubsetSymbol();
+            removeCollaborationLine();
             break;
 
         case Uml::at_Relationship:
+            setStartSymbol(Symbol::None);
             setEndSymbol(Symbol::CrowFeet);
+            removeSubsetSymbol();
+            removeCollaborationLine();
             break;
 
         case Uml::at_Generalization:
         case Uml::at_Realization:
+            setStartSymbol(Symbol::None);
             setEndSymbol(Symbol::ClosedArrow);
+            removeSubsetSymbol();
+            removeCollaborationLine();
             break;
 
         case Uml::at_Composition:
         case Uml::at_Aggregation:
             setStartSymbol(Symbol::Diamond);
+            setEndSymbol(Symbol::None);
+            removeSubsetSymbol();
+            removeCollaborationLine();
             break;
 
         case Uml::at_Containment:
             setStartSymbol(Symbol::Circle);
+            setEndSymbol(Symbol::None);
+            removeSubsetSymbol();
+            removeCollaborationLine();
             break;
+
+        case Uml::at_Child2Category:
+            setStartSymbol(Symbol::None);
+            setEndSymbol(Symbol::None);
+            createSubsetSymbol();
+            removeCollaborationLine();
+            break;
+
+        case Uml::at_Coll_Message:
+        case Uml::at_Coll_Message_Self:
+            setStartSymbol(Symbol::None);
+            setEndSymbol(Symbol::None);
+            removeSubsetSymbol();
+            createCollaborationLine();
+            break;
+
         default:
             break;
     }
+
+    alignSymbols();
 }
 
+/**
+ * Sets the Symbol to appear at the first line segment to \a symbol.
+ *
+ * If symbol == Symbol::None , then it deletes the symbol item.
+ */
+void AssociationLine::setStartSymbol(Symbol::SymbolType symbolType)
+{
+    Q_ASSERT(symbolType != Symbol::Count);
+    if (symbolType == Symbol::None) {
+        delete m_startSymbol;
+        m_startSymbol = 0;
+        return;
+    }
+
+    if (m_startSymbol) {
+        m_startSymbol->setSymbolType(symbolType);
+    }
+    else {
+        m_startSymbol = new Symbol(symbolType, m_associationWidget);
+    }
+    m_startSymbol->setPen(pen());
+}
+
+/**
+ * Sets the Symbol to appear at the last line segment to \a symbol.
+ *
+ * If symbol == Symbol::None , then it deletes the symbol item.
+ */
+void AssociationLine::setEndSymbol(Symbol::SymbolType symbolType)
+{
+    Q_ASSERT(symbolType != Symbol::Count);
+    if (symbolType == Symbol::None) {
+        delete m_endSymbol;
+        m_endSymbol = 0;
+        return;
+    }
+
+    if (m_endSymbol) {
+        m_endSymbol->setSymbolType(symbolType);
+    }
+    else {
+        m_endSymbol = new Symbol(symbolType, m_associationWidget);
+    }
+    m_endSymbol->setPen(pen());
+}
+
+/**
+ * Constructs a new subset symbol.
+ */
+void AssociationLine::createSubsetSymbol()
+{
+    delete m_subsetSymbol; // recreate
+    m_subsetSymbol = new Symbol(Symbol::Subset, m_associationWidget);
+    m_subsetSymbol->setPen(pen());
+}
+
+/// Removes the subset symbol if it existed by deleting appropriate items.
+void AssociationLine::removeSubsetSymbol()
+{
+    delete m_subsetSymbol;
+    m_subsetSymbol = 0;
+}
+
+/**
+ * Constructs the open arrow symbol and arrow line, that would represent Collaboration line.
+ */
+void AssociationLine::createCollaborationLine()
+{
+    const QPen p = pen();
+
+    // recreate
+    delete m_collaborationLineItem;
+    delete m_collaborationLineHead;
+
+    m_collaborationLineItem = new QGraphicsLineItem(m_associationWidget);
+    m_collaborationLineItem->setPen(p);
+
+    m_collaborationLineHead = new Symbol(Symbol::OpenArrow, m_associationWidget);
+    m_collaborationLineHead->setPen(p);
+}
+
+/// Removes collaboration line by deleting the head and line item.
+void AssociationLine::removeCollaborationLine()
+{
+    delete m_collaborationLineItem;
+    m_collaborationLineItem = 0;
+
+    delete m_collaborationLineHead;
+    m_collaborationLineHead = 0;
+}
+
+/**
+ * This method aligns both the \b "start" and \b "end" symbols to
+ * the current angles of the \b "first" and the \b "last" line
+ * segment respectively.
+ */
+void AssociationLine::alignSymbols()
+{
+    const int sz = m_points.size();
+    if (sz < 2) {
+        // Cannot align if there is no line (one line = 2 points)
+        return;
+    }
+
+    if (m_startSymbol) {
+        QLineF segment(m_points[1], m_points[0]);
+        m_startSymbol->alignTo(segment);
+    }
+
+    if (m_endSymbol) {
+        QLineF segment(m_points[sz-2], m_points[sz - 1]);
+        m_endSymbol->alignTo(segment);
+    }
+
+    if (m_subsetSymbol) {
+        QLineF segment(m_points.at(0), (m_points.at(0) + m_points.at(1)) * .5);
+        uDebug() << "points: " << m_points.at(0) << m_points.at(1);
+        uDebug() << "segment: " << segment;
+        m_subsetSymbol->alignTo(segment);
+    }
+
+    if (m_collaborationLineItem) {
+        Q_ASSERT(m_collaborationLineHead != 0);
+        const qreal distance = 10;
+        const int midSegmentIndex = (sz - 1) / 2;
+
+        const QPointF a = m_points.at(midSegmentIndex);
+        const QPointF b = m_points.at(midSegmentIndex + 1);
+
+        const QPointF p1 = (a + b) / 2.0;
+        const QPointF p2 = (p1 + b) / 2.0;
+
+        // Reversed line as we want normal in opposite direction.
+        QLineF segment(p2, p1);
+        QLineF normal = segment.normalVector().unitVector();
+        normal.setLength(distance);
+
+        QLineF actualLine;
+        actualLine.setP2(normal.p2());
+
+        normal.translate(p1 - p2);
+        actualLine.setP1(normal.p2());
+
+        m_collaborationLineItem->setLine(actualLine);
+        m_collaborationLineHead->alignTo(actualLine);
+    }
+}
+
--- branches/work/soc-umbrello/umbrello/widgets/associationline.h #1008912:1008913
@@ -96,7 +96,6 @@
         static void setupSymbolTable();
 };
 
-
 /**
  * A convenience class that encapsulates geometry management, handles
  * mouse and hover events, embeds and aligns symbols and finally draws the
@@ -135,11 +134,6 @@
 
         void setEndPoints(const QPointF &start, const QPointF &end);
 
-        void setStartSymbol(Symbol::SymbolType symbolType);
-        void setEndSymbol(Symbol::SymbolType symbolType);
-        void createSubsetSymbol();
-        void alignSymbols();
-
         bool loadFromXMI(QDomElement &qElement);
         void saveToXMI(QDomDocument &qDoc, QDomElement &qElement);
 
@@ -171,9 +165,20 @@
         void calculateInitialEndPoints();
         void calculateAssociationClassLine();
 
-        void setupSymbols();
+        void reconstructSymbols();
 
     private:
+        void setStartSymbol(Symbol::SymbolType symbolType);
+        void setEndSymbol(Symbol::SymbolType symbolType);
+
+        void createSubsetSymbol();
+        void removeSubsetSymbol();
+
+        void createCollaborationLine();
+        void removeCollaborationLine();
+
+        void alignSymbols();
+
         /// These points represents the association line.
         QVector<QPointF> m_points;
 
@@ -196,6 +201,11 @@
         /// The subset symbol.
         Symbol *m_subsetSymbol;
 
+        /// The parallel arrow line drawn in case of collaboration message.
+        QGraphicsLineItem *m_collaborationLineItem;
+        /// The arrow head drawn at end of m_collaborationLineItem
+        Symbol *m_collaborationLineHead;
+
         /// The bounding rectangle of this AssociationLine
         QRectF m_boundingRect;
         /// The shape of this AssociationLine.
--- branches/work/soc-umbrello/umbrello/widgets/associationwidget.cpp #1008912:1008913
@@ -130,7 +130,7 @@
     }
     // TODO: Probably move this calculation to slotInit.
     m_associationLine->calculateInitialEndPoints();
-    m_associationLine->setupSymbols();
+    m_associationLine->reconstructSymbols();
 
 
     Q_ASSERT(widgetA->umlScene() == widgetB->umlScene());
@@ -840,6 +840,7 @@
         setRoleDocumentation("", Uml::A);
         setRoleDocumentation("", Uml::B);
     }
+    m_associationLine->reconstructSymbols();
 }
 
 bool AssociationWidget::isCollaboration() const




More information about the umbrello-devel mailing list