| 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 First Reported In: | 1.4.2 | ||
| Target Milestone: | --- | ||
| Platform: | unspecified | ||
| OS: | Linux | ||
| Latest Commit: | Version Fixed/Implemented In: | ||
| Sentry Crash Report: | |||
| 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. *** |