[Uml-devel] [Bug 110231] Association labels aren't moved correctly when moving the corresponding classes (class diagram)

Oliver Kellogg okellogg at users.sourceforge.net
Sun Aug 7 06:04:20 UTC 2005


------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
         
http://bugs.kde.org/show_bug.cgi?id=110231         




------- Additional Comments From okellogg users sourceforge net  2005-08-07 15:03 -------
SVN commit 443800 by okellogg:

CCBUG:110231 - First stab at constraining the text positions.
Only works for exactly vertical and horizontal association lines.
Only works when actively dragging around a FloatingText, i.e. does
not yet work as a side effect of moving one of the role objects.
In other words, all the hard stuff is still To Be Done :)


 M  +107 -0    associationwidget.cpp  
 M  +13 -0     associationwidget.h  
 M  +1 -4      floatingtext.cpp  
 M  +0 -5      linkwidget.cpp  
 M  +4 -3      linkwidget.h  


--- branches/KDE/3.5/kdesdk/umbrello/umbrello/associationwidget.cpp #443799:443800
 @ -1870,6 +1870,113  @
     return p;
 }
 
+void AssociationWidget::constrainTextPos(int &textX, int &textY,
+                                         int textWidth, int textHeight,
+                                         Uml::Text_Role tr) {
+    const int CORRIDOR_HALFWIDTH = 30;
+    const int textHalfWidth = textWidth / 2;
+    const int textHalfHeight = textHeight / 2;
+    const int textCenterX = textX + textHalfWidth;
+    const int textCenterY = textY + textHalfHeight;
+    const uint lastSegment = m_LinePath.count() - 1;
+    QPoint p0, p1;
+    bool atBSide = false;
+    switch (tr) {
+        case tr_RoleAName:
+        case tr_MultiA:
+        case tr_ChangeA:
+            p0 = m_LinePath.getPoint(0);
+            p1 = m_LinePath.getPoint(1);
+            break;
+        case tr_RoleBName:
+        case tr_MultiB:
+        case tr_ChangeB:
+            p0 = m_LinePath.getPoint(lastSegment - 1);
+            p1 = m_LinePath.getPoint(lastSegment);
+            atBSide = true;
+            break;
+        case tr_Name:
+            //  todo Find the linepath segment to which the (textX,textY) is closest
+            //       and constrain to the corridor of that segment.
+            return;
+            break;
+        default:
+            kdError() << "AssociationWidget::constrainTextPos(): unexpected Text_Role "
+                      << tr << endl;
+            return;
+            break;
+    }
+    if (p0.x() == p1.x()) {
+        // vertical line
+        // CAUTION: This is calculated in Qt coordinates!
+        ////////////////////////// constrain horizontally /////////////////////////
+        const int lineX = p0.x();
+        if (textX + textWidth < lineX - CORRIDOR_HALFWIDTH)  // constrain at left
+            textX = lineX - CORRIDOR_HALFWIDTH - textWidth;
+        else if (textX > lineX + CORRIDOR_HALFWIDTH)         // constrain at right
+            textX = lineX + CORRIDOR_HALFWIDTH;
+        ////////////////////////// constrain vertically ///////////////////////////
+        // pre-constrain the corridor to the appropriate half:
+        if (atBSide) {
+            if (p0.y() > p1.y())
+                p0.setY(p1.y() + (p0.y() - p1.y()) / 2);
+            else
+                p0.setY(p1.y() - (p1.y() - p0.y()) / 2);
+        } else {
+            if (p0.y() < p1.y())
+                p1.setY(p0.y() + (p1.y() - p0.y()) / 2);
+            else
+                p1.setY(p0.y() - (p0.y() - p1.y()) / 2);
+        }
+        // swap points so that p0 contains the one with the smaller Y
+        if (p0.y() > p1.y()) {
+            QPoint tmp = p0;
+            p0 = p1;
+            p1 = tmp;
+        }
+        if (textY + textHeight < p0.y())  // constrain at top
+            textY = p0.y() - textHeight;
+        else if (textY > p1.y())          // constrain at bottom
+            textY = p1.y();
+        return;
+    }
+    if (p0.y() == p1.y()) {
+        // horizontal line
+        // CAUTION: This is calculated in Qt coordinates!
+        ////////////////////////// constrain verticallly ///////////////////////////
+        const int lineY = p0.y();
+        if (textY + textHeight < lineY - CORRIDOR_HALFWIDTH)  // constrain at top
+            textY = lineY - CORRIDOR_HALFWIDTH - textHeight;
+        else if (textY > lineY + CORRIDOR_HALFWIDTH)          // constrain at bottom
+            textY = lineY + CORRIDOR_HALFWIDTH;
+        ////////////////////////// constrain horizontally //////////////////////////
+        // pre-constrain the corridor to the appropriate half:
+        if (atBSide) {
+            if (p0.x() < p1.x())
+                p0.setX(p1.x() - (p1.x() - p0.x()) / 2);
+            else
+                p0.setX(p1.x() + (p0.x() - p1.x()) / 2);
+        } else {
+            if (p0.x() < p1.x())
+                p1.setX(p0.x() + (p1.x() - p0.x()) / 2);
+            else
+                p1.setX(p0.x() - (p0.x() - p1.x()) / 2);
+        }
+        // swap points so that p0 contains the one with the smaller X
+        if (p0.x() > p1.x()) {
+            QPoint tmp = p0;
+            p0 = p1;
+            p1 = tmp;
+        }
+        if (textX + textWidth < p0.x())   // constrain at left
+            textX = p0.x() - textWidth;
+        else if (textX > p1.x())          // constrain at right
+            textX = p1.x();
+        return;
+    }
+    //  todo: deal with slopes
+}
+
 void AssociationWidget::calculateNameTextSegment() {
     if(!m_pName) {
         return;
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/associationwidget.h #443799:443800
 @ -490,6 +490,19  @
     void resetTextPositions();
 
     /**
+     * Constrains the FloatingText X and Y values supplied.
+     * Implements the abstract operation from LinkWidget.
+     *
+     *  param textX       Candidate X value (may be modified by the constraint.)
+     *  param textY       Candidate Y value (may be modified by the constraint.)
+     *  param textWidth   Width of the text.
+     *  param textHeight  Height of the text.
+     *  param tr          Uml::Text_Role of the text.
+     */
+    void constrainTextPos(int &textX, int &textY, int textWidth, int textHeight,
+                          Uml::Text_Role tr);
+
+    /**
      * Shows the association properties dialog and updates the
      * corresponding texts if its execution is successful.
      * Returns true for success.
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/floatingtext.cpp #443799:443800
 @ -304,10 +304,7  @
     int newX = newPosition.x();
     int newY = newPosition.y();
 
-    //implement specific rules for a sequence diagram
-    if (m_Role == Uml::tr_Seq_Message || m_Role == Uml::tr_Seq_Message_Self) {
-        m_pLink->constrainTextPos(newX, newY, width(), height(), m_Role);
-    }
+    m_pLink->constrainTextPos(newX, newY, width(), height(), m_Role);
     m_nOldX = newX;
     m_nOldY = newY;
     setX( newX );
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/linkwidget.cpp #443799:443800
 @ -55,11 +55,6  @
     return true;
 }
 
-void LinkWidget::constrainTextPos(int & /*textX*/, int & /*textY*/,
-                                  int /*textWidth*/, int /*textHeight*/,
-                                  Uml::Text_Role /*tr*/) {
-}
-
 void LinkWidget::calculateNameTextSegment() {
 }
 
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/linkwidget.h #443799:443800
 @ -113,11 +113,12  @
     virtual void setSeqNumAndOp(const QString &seqNum, const QString &op) = 0;
 
     /**
+     * Abstract operation implemented by inheriting classes.
      * Motivated by FloatingText::mouseMoveEvent()
-     * Only applies to MessageWidget.
      */
-    virtual void constrainTextPos(int &textX, int &textY, int textWidth, int textHeight,
-                                  Uml::Text_Role tr);
+    virtual void constrainTextPos(int &textX, int &textY,
+                                  int textWidth, int textHeight,
+                                  Uml::Text_Role tr) = 0;
 
     /**
      * Motivated by FloatingText::setLink().




More information about the umbrello-devel mailing list