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

Gopala Krishna A krishna.ggk at gmail.com
Fri May 29 18:25:42 UTC 2009


SVN commit 974891 by gopala:

Implemented more functionality in AssociationSpaceManager class.
This class implmentation is almost done.


 M  +179 -5    associationspacemanager.cpp  
 M  +13 -3     associationspacemanager.h  


--- branches/work/soc-umbrello/umbrello/associationspacemanager.cpp #974890:974891
@@ -22,24 +22,77 @@
 #include "newlinepath.h"
 #include "umlwidget.h"
 
+/**
+ * Constructs a new space manager object for given widget.
+ */
 AssociationSpaceManager::AssociationSpaceManager(UMLWidget *widget)
 {
     m_umlWidget = widget;
     Q_ASSERT(widget);
 }
 
-void AssociationSpaceManager::addAssociationWidget(New::AssociationWidget *assoc)
+/**
+ * This method is used to register the AssociationWidget associatied with this UMLWidget along
+ * specified region passed.
+ *
+ * @param  assoc The AssociationWidget to be registered.
+ * @param region The region with which the AssociationWidget has to be registered. If region =
+ *               Uml::Error, then region is computed using @ref nearestRegion() function.
+ *
+ * @note region should neither be Uml::Error nor Uml::Center.
+ */
+Uml::Region AssociationSpaceManager::add(New::AssociationWidget *assoc,
+        Uml::Region region)
 {
+    Q_ASSERT(region != Uml::Center);
+
+    if (registered(assoc)) {
+        uDebug() << assoc->name() << " is already registered!";
+        return Uml::Error;
+    }
+
+    if (region == Uml::Error) {
+        region = nearestRegion(assoc);
+        Q_ASSERT(region != Uml::Error);
+    }
+
+    QList<New::AssociationWidget*> &listRef = m_regionAssociationsMap[region];
+    listRef << assoc;
+    m_registeredAssociationSet << assoc;
+
+    return region;
 }
 
-void AssociationSpaceManager::addAssociationWidget(New::AssociationWidget *assoc, Uml::Region region)
+/**
+ * This method unregisters the AssociationWidget by removing it from region specific list.
+ * @note The AssociationWidget is however @b not deleted.
+ */
+void AssociationSpaceManager::remove(New::AssociationWidget *assoc)
 {
-}
+    if (!registered(assoc)) {
+        uDebug() << assoc->name() << " is not registered!";
+        return;
+    }
 
-void AssociationSpaceManager::removeAssociatinWidget(New::AssociationWidget *assoc)
-{
+    Uml::Region reg = region(assoc);
+    Q_ASSERT(reg != Uml::Error);
+    Q_ASSERT(reg != Uml::Center);
+
+    QList<New::AssociationWidget*> &listRef = m_regionAssociationsMap[reg];
+    listRef.removeOne(assoc);
+    m_registeredAssociationSet.remove(assoc);
 }
 
+/**
+ * This method returns the appropriate end point location in scene coordinates based on whether the
+ * association is pointing to widget or pointing away from it (that is whether it is Uml::A or
+ * Uml::B respectively).
+ *
+ * @param assoc The AssociationWidget for which end point should be returned.
+ * @return The end point of assoc in scene coordinates which is associated to m_umlWidget.
+ *
+ * @see AssociationSpaceManager::penultimateEndPoint()
+ */
 QPointF AssociationSpaceManager::endPoint(New::AssociationWidget *assoc) const
 {
     UMLWidget *widA = assoc->widgetForRole(Uml::A);
@@ -60,6 +113,15 @@
     return retVal;
 }
 
+/**
+ * This method returns the appropriate penultimate end point location in scene coordinates based on
+ * whether the association is pointing to widget or pointing away from it (that is whether it is
+ * Uml::A or Uml::B respectively).
+ *
+ * @param assoc The AssociationWidget for which penultimate end point should be returned.
+ * @return The penultimate end point of assoc in scene coordinates which is associated to
+ *         m_umlWidget.
+ */
 QPointF AssociationSpaceManager::penultimateEndPoint(New::AssociationWidget *assoc) const
 {
     UMLWidget *widA = assoc->widgetForRole(Uml::A);
@@ -80,6 +142,11 @@
     return retVal;
 }
 
+/**
+ * This method calculates the region which is closest for the AssociationWidget based on distance
+ * of penultimate point from m_umlWidget.
+ * The distance calculation happens in scene coordinates.
+ */
 Uml::Region AssociationSpaceManager::nearestRegion(New::AssociationWidget *assoc) const
 {
     QPointF penultimate = penultimateEndPoint(assoc);
@@ -119,10 +186,117 @@
     }
 }
 
+
+void sortAssociationPointList(QList<QPair<New::AssociationWidget*, QPointF> > &list,
+        qreal other, bool xCoordBasis)
+{
+    for (int i = 0; i < list.size()-1; ++i) {
+        qreal minVal = qAbs(other - (xCoordBasis ? list[i].second.x() : list[i].second.y()));
+        int minInd = i;
+
+        for (int j = i + 1; j < list.size(); ++j) {
+            qreal dist = qAbs(other - (xCoordBasis ? list[j].second.x() : list[j].second.y()));
+        }
+    }
+}
+/**
+ * This method arranges the AssociationWidget line end points for a given region based on its
+ * distance of penultimate point from edge.
+ */
 void AssociationSpaceManager::arrange(Uml::Region region)
 {
+    //TODO: Yet to complete.
+#if 0
+    Q_ASSERT(region != Uml::Error);
+    Q_ASSERT(region != Uml::Center);
+
+    QList<New::AssociationWidget*> &listRef = m_regionAssociationsMap[region];
+    QList<QPair<New::AssociationWidget*, QPointF> > assocPenuls;
+    foreach (New::AssociationWidget* assoc, listRef) {
+        QPointF p = penultimateEndPoint(assoc);
+        assocPenuls.append(qMakePair(assoc, p));
+    }
+
+    QRectF rect = m_umlWidget->mapToScene(m_umlWidget->rect()).boundingRect();
+    QPointF other;
+    bool xBasis = false;
+    switch (region) {
+        case Uml::North:
+        case Uml::NorthWest:
+            other = rect.topLeft(); xBasis = true; break;
+
+        case Uml::NorthEast:
+            other = rect.topRight(); break;
+
+        case Uml::East:
+        case Uml::SouthEast:
+            other = rect.bottomRight(); break;
+
+        case Uml::South:
+        case Uml::SouthWest:
+            xBasis = true;
+            // intended fall through
+        case Uml::West:
+            other = rect.bottomLeft(); break;
+    }
+
+    for (int i = 0; i < assocPenuls.size() - 1; ++i) {
+        qreal minVal = xBasis ? assocPenuls[i].second.x() : assocPenuls[i].second.y();
+        qreal minInd = i;
+        for (int j = 0; j < assocPenuls.size(); ++j) {
+            qreal val = xBasis ? assocPenuls[i].second.x() : assocPenuls[i].second.y();
+            if (val < minVal) {
+                minVal = val;
+                minInd = j;
+            }
+        }
+
+        if (minInd == i) continue;
+        qSwap(assocPenuls[i], assocPenuls[minInd]);
+        qSwap(listRef[i], listRef[minInd]);
+    }
+#endif
 }
 
+/**
+ * This utility method arranges the AssociationWidget line end points for a all regions based on
+ * its distance of penultimate point from edge.
+ */
 void AssociationSpaceManager::arrangeAllRegions()
 {
+    arrange(Uml::North);
+    arrange(Uml::East);
+    arrange(Uml::South);
+    arrange(Uml::West);
+    arrange(Uml::NorthEast);
+    arrange(Uml::SouthEast);
+    arrange(Uml::SouthWest);
+    arrange(Uml::NorthWest);
 }
+
+/**
+ * @return The Uml::Region where assoc's end point resides.
+ */
+Uml::Region AssociationSpaceManager::region(New::AssociationWidget *assoc) const
+{
+    if (!registered(assoc)) {
+        return Uml::Error;
+    }
+    QMapIterator<Uml::Region, QList<New::AssociationWidget*> > it(m_regionAssociationsMap);
+    while (it.hasNext()) {
+        it.next();
+        if (it.value().contains(assoc)) {
+            return it.key();
+        }
+    }
+    return Uml::Error;
+}
+
+/**
+ * @return Registration status of assoc.
+ */
+bool AssociationSpaceManager::registered(New::AssociationWidget* assoc) const
+{
+    return m_registeredAssociationSet.contains(assoc);
+}
+
--- branches/work/soc-umbrello/umbrello/associationspacemanager.h #974890:974891
@@ -28,14 +28,20 @@
     class AssociationWidget;
 }
 
+/**
+ * @short A class to manage distribution of AssociationWidget around UMLWidget.
+ *
+ * This class mainly includes functionality required to move around the AssociationWidget endings
+ * along the 8 sides around the UMLWidget, based on simple distance based algorithms.
+ * The object of this class resides in a UMLWidget.
+ */
 class AssociationSpaceManager
 {
 public:
     AssociationSpaceManager(UMLWidget *widget);
 
-    void addAssociationWidget(New::AssociationWidget *assoc);
-    void addAssociationWidget(New::AssociationWidget *assoc, Uml::Region region);
-    void removeAssociatinWidget(New::AssociationWidget *assoc);
+    Uml::Region add(New::AssociationWidget *assoc, Uml::Region region = Uml::Error);
+    void remove(New::AssociationWidget *assoc);
 
     QPointF endPoint(New::AssociationWidget *assoc) const;
     QPointF penultimateEndPoint(New::AssociationWidget *assoc) const;
@@ -45,8 +51,12 @@
     void arrange(Uml::Region region);
     void arrangeAllRegions();
 
+    Uml::Region region(New::AssociationWidget *assoc) const;
+    bool registered(New::AssociationWidget* assoc) const;
+
 private:
     QMap<Uml::Region, QList<New::AssociationWidget*> > m_regionAssociationsMap;
+    QSet<New::AssociationWidget*> m_registeredAssociationSet;
     UMLWidget *m_umlWidget;
 };
 




More information about the umbrello-devel mailing list