Summary: | Association labels aren't moved correctly when moving the corresponding classes (class diagram) | ||
---|---|---|---|
Product: | [Applications] umbrello | Reporter: | Tassilo Horn <tassilo> |
Component: | general | Assignee: | Umbrello Development Group <umbrello-devel> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | justacec |
Priority: | NOR | ||
Version: | 1.4.2 | ||
Target Milestone: | --- | ||
Platform: | unspecified | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Attachments: |
The diagram where this bug is reproducible
A very simple class diagram I mentioned in my second posting. |
Description
Tassilo Horn
2005-08-05 13:53:54 UTC
Created attachment 12097 [details]
The diagram where this bug is reproducible
I investigated a little further and it seems to apply to assiciation which weren't moved manually, too. Have a look at the very simple class diagram I below this message. I created 3 classes and 2 associations. I never moved labels manually. Now take class b and move it in circles arround class c and all labels get messed up. Created attachment 12098 [details]
A very simple class diagram I mentioned in my second posting.
Here you can see that it applies to labels not moved manually, too.
A well known bug. Alas, nobody has mustered the spunk to fix it :) 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(). SVN commit 443930 by okellogg: calculateTextPosition(tr_Name): Add missing assignment of `text'. Also, apply the constrained coordinates to the FloatingText. BUG:110231 M +12 -5 associationwidget.cpp --- branches/KDE/3.5/kdesdk/umbrello/umbrello/associationwidget.cpp #443929:443930 @@ -1699,7 +1699,7 @@ int textW = 0, textH = 0; int slope = 0, divisor = 1; const int SPACE = 2; - FloatingText const * text = 0; + FloatingText *text = 0; if(role == tr_MultiA) { text = getMultiWidget(A); @@ -1778,6 +1778,8 @@ } else if(role == tr_Name) { + calculateNameTextSegment(); + text = m_pName; x = (int)( ( m_LinePath.getPoint(m_unNameLineSegment).x() + m_LinePath.getPoint(m_unNameLineSegment + 1).x() ) / 2 ); @@ -1868,9 +1870,14 @@ } if (text) { constrainTextPos(x, y, textW, textH, role); - // kdDebug() << "AssociationWidget::calculateTextPosition(" - // << p.x() << "," << p.y() << "): newPoint=(" - // << x << "," << y << ")" << endl; + if (x != p.x() || y != p.y()) { + // kdDebug() << "AssociationWidget::calculateTextPosition(" + // << text->getName() << ") textrole " << role + // << ": oldpoint=(" << p.x() << "," << p.y() << ")" + // << ", newPoint=(" << x << "," << y << ")" << endl; + text->setX(x); + text->setY(y); + } } p = QPoint( x, y ); return p; @@ -1973,7 +1980,7 @@ if (p0.y() == p1.y()) { // horizontal line // CAUTION: This is calculated in Qt coordinates! - ////////////////////////// constrain verticallly /////////////////////////// + ////////////////////////// constrain vertically ///////////////////////////// const int lineY = p0.y(); if (textY + textHeight < lineY - CORRIDOR_HALFWIDTH) // constrain at top textY = lineY - CORRIDOR_HALFWIDTH - textHeight; *** Bug 107171 has been marked as a duplicate of this bug. *** |