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

Gopala Krishna A krishna.ggk at gmail.com
Fri Aug 7 20:35:29 UTC 2009


SVN commit 1008558 by gopala:

AssociationWidget: Few more methods ported.



 M  +141 -8    associationwidget.cpp  
 M  +2 -0      associationwidget.h  


--- branches/work/soc-umbrello/umbrello/widgets/associationwidget.cpp #1008557:1008558
@@ -30,6 +30,8 @@
 
 #include <QPointer>
 
+#include <cmath>
+
 WidgetRole::WidgetRole()
 {
     multiplicityWidget = changeabilityWidget = roleWidget = 0;
@@ -433,8 +435,7 @@
      */
     const QPointF mid = (p0 + p1) / 2.0;
     const qreal radius = QLineF(p0, mid).length();
-    const QPointF textAbs(textCenterX, textCenterY);
-    const QPointF textRel = textAbs - mid;
+    const QPointF textRel = textCenter - mid;
 
     QPointF projected = textRel;
     QLineF line(QPointF(0, 0), textRel);
@@ -448,10 +449,36 @@
     textY = projected.y() - .5 * textHeight;
 }
 
-
 void AssociationWidget::calculateNameTextSegment()
 {
-    //TODO: Implement this
+    if (!m_nameWidget) return;
+    //changed to use the middle of the text
+    //i think this will give a better result.
+    //never know what sort of lines people come up with
+    //and text could be long to give a false reading
+    qreal xt = m_nameWidget->x();
+    qreal yt = m_nameWidget->y();
+    xt += m_nameWidget->width() / 2;
+    yt += m_nameWidget->height() / 2;
+    uint size = m_associationLine->count();
+    //sum of length(PTP1) and length(PTP2)
+    qreal total_length = 0;
+    qreal smallest_length = 0;
+    for(uint i = 0; i < size - 1; ++i) {
+        QPointF pi = m_associationLine->point(i);
+        QPointF pj = m_associationLine->point(i+1);
+        qreal xtiDiff = xt - pi.x();
+        qreal xtjDiff = xt - pj.x();
+        qreal ytiDiff = yt - pi.y();
+        qreal ytjDiff = yt - pj.y();
+        total_length =  std::sqrt( double(xtiDiff * xtiDiff + ytiDiff * ytiDiff) )
+                        + std::sqrt( double(xtjDiff * xtjDiff + ytjDiff * ytjDiff) );
+        //this gives the closest point
+        if( total_length < smallest_length || i == 0) {
+            smallest_length = total_length;
+            m_nameSegmentIndex = i;
+        }
+    }
 }
 
 
@@ -918,8 +945,7 @@
     if (m_nameWidget) {
         updateNameWidgetRole();
         m_nameWidget->activate();
-        // TODO: Check for removal of comment
-        // calculateNameTextSegment();
+        calculateNameTextSegment();
     }
 
     // Prepare the association class line if needed.
@@ -1116,6 +1142,7 @@
 
     m_nameWidget = new FloatingTextWidget(Uml::tr_Name);
     m_nameWidget->setLink(this);
+    m_nameSegmentIndex = -1;
 
     m_widgetRole[Uml::A].initFloatingWidgets(Uml::A, this);
     m_widgetRole[Uml::B].initFloatingWidgets(Uml::B, this);
@@ -1138,10 +1165,116 @@
     }
 }
 
+QPointF AssociationWidget::calculateTextPosition(Uml::Text_Role role)
+{
+    const qreal SPACE = 2;
+    QPointF p(-1, -1), q(-1, -1);
+
+    // used to find out if association end point (p)
+    // is at top or bottom edge of widget.
+    UMLWidget *pWidget = 0;
+
+    if (role == Uml::tr_MultiA || role == Uml::tr_ChangeA || role == Uml::tr_RoleAName) {
+        p = m_associationLine->point( 0 );
+        q = m_associationLine->point( 1 );
+        pWidget = widgetForRole(Uml::A);
+    } else if (role == Uml::tr_MultiB || role == Uml::tr_ChangeB || role == Uml::tr_RoleBName) {
+        const uint lastSegment = m_associationLine->count() - 1;
+        p = m_associationLine->point(lastSegment);
+        q = m_associationLine->point(lastSegment - 1);
+        pWidget = widgetForRole(Uml::B);
+    } else if (role != Uml::tr_Name) {
+        uError() << "called with unsupported Text_Role " << role;
+        return QPoint(-1, -1);
+    }
+
+    FloatingTextWidget *text = textWidgetByRole(role);
+    qreal textW = 0, textH = 0;
+    if (text) {
+        textW = text->width();
+        textH = text->height();
+    }
+
+    qreal x = 0, y = 0;
+
+    if (role == Uml::tr_MultiA || role == Uml::tr_MultiB) {
+        const bool isHorizontal = (p.y() == q.y());
+        const qreal atBottom = p.y() + SPACE;
+        const qreal atTop = p.y() - SPACE - textH;
+        const qreal atLeft = p.x() - SPACE - textW;
+        const qreal atRight = p.x() + SPACE;
+        y = (p.y() > q.y()) == isHorizontal ? atBottom : atTop;
+        x = (p.x() < q.x()) == isHorizontal ? atRight : atLeft;
+
+    } else if (role == Uml::tr_ChangeA || role == Uml::tr_ChangeB) {
+
+        if( p.y() > q.y() ) {
+            y = p.y() - SPACE - (textH * 2);
+        }
+        else {
+            y = p.y() + SPACE + textH;
+        }
+
+        if( p.x() < q.x() ) {
+            x = p.x() + SPACE;
+        }
+        else {
+            x = p.x() - SPACE - textW;
+        }
+
+    } else if (role == Uml::tr_RoleAName || role == Uml::tr_RoleBName) {
+
+        if( p.y() > q.y() ) {
+            y = p.y() - SPACE - textH;
+        }
+        else {
+            y = p.y() + SPACE;
+        }
+
+        if( p.x() < q.x() ) {
+            x = p.x() + SPACE;
+        }
+        else {
+            x = p.x() - SPACE - textW;
+        }
+
+    } else if (role == Uml::tr_Name) {
+
+        calculateNameTextSegment();
+        x = ( m_associationLine->point(m_nameSegmentIndex).x() +
+                m_associationLine->point(m_nameSegmentIndex + 1).x() ) / 2.0;
+
+        y = ( m_associationLine->point(m_nameSegmentIndex).y() +
+                m_associationLine->point(m_nameSegmentIndex + 1).y() ) / 2.0;
+    }
+
+    if (text) {
+        constrainTextPos(x, y, textW, textH, role);
+    }
+    p = QPointF( x, y );
+    return p;
+}
+
 void AssociationWidget::setTextPosition(Uml::Text_Role tr)
 {
-    Q_UNUSED(tr);
-    // TODO: Implement this stub
+    bool startMove = false;
+    //TODO: Check startMove removal
+    if (startMove) {
+        return;
+    }
+    FloatingTextWidget *ft = textWidgetByRole(tr);
+    if (!ft) {
+        return;
+    }
+    QPointF pos = calculateTextPosition(tr);
+    if ( (pos.x() < 0.0 || pos.x() > FloatingTextWidget::restrictPositionMax) ||
+            (pos.y() < 0 || pos.y() > FloatingTextWidget::restrictPositionMax) ) {
+        uDebug() << "(x=" << pos.x() << " , y=" << pos.y() << ") "
+            << "- was blocked because at least one value is out of bounds: ["
+            << "0 ... " << FloatingTextWidget::restrictPositionMax << "]";
+        return;
+    }
+    ft->setPos(pos);
 }
 
 void AssociationWidget::updateNameWidgetRole()
--- branches/work/soc-umbrello/umbrello/widgets/associationwidget.h #1008557:1008558
@@ -163,6 +163,7 @@
         void init();
         void setFloatingText(Uml::Text_Role tr, const QString& text,
                 FloatingTextWidget* &ft);
+        QPointF calculateTextPosition(Uml::Text_Role tr);
         void setTextPosition(Uml::Text_Role tr);
         void updateNameWidgetRole();
 
@@ -172,6 +173,7 @@
         ClassifierWidget *m_associationClass;
         WidgetRole m_widgetRole[2];
         FloatingTextWidget *m_nameWidget;
+        int m_nameSegmentIndex;
 
         Uml::Association_Type m_associationType;
         bool m_setCollabIDOnFirstSceneSet;




More information about the umbrello-devel mailing list