[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