From 9d0b86ad9860ccc1a87caed1f6a2b6f82a24ccec Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Sun, 16 Jul 2017 18:40:59 +0200 Subject: [PATCH] logic: Show inheritance edges between parents of active symbol and other visible symbols (issue #167) * add inheritance edges between parents of active symbol and other visible symbols * add dashed inheritance edges when symbols are no direct decendants * inheritance edges are also respected in layouting, putting base/derived classes in the correct top/bottom spot now bug id = 167 --- src/lib/CMakeLists.txt | 1 + .../controller/ActivationController.cpp | 2 - .../component/controller/GraphController.cpp | 30 ++++++-- src/lib/component/view/GraphViewStyle.cpp | 1 + src/lib/component/view/GraphViewStyle.h | 2 + src/lib/data/HierarchyCache.cpp | 53 +++++++++++++ src/lib/data/HierarchyCache.h | 13 ++++ src/lib/data/PersistentStorage.cpp | 75 +++++++++++++++++++ src/lib/data/PersistentStorage.h | 1 + src/lib/data/graph/Edge.cpp | 17 +++++ src/lib/data/graph/Edge.h | 4 +- src/lib/data/graph/Node.cpp | 4 +- src/lib/data/graph/Node.h | 1 + .../TokenComponentInheritanceChain.h | 23 ++++++ src/lib_gui/qt/graphics/QtLineItemAngled.cpp | 21 +++++- src/lib_gui/qt/graphics/QtLineItemBase.cpp | 9 ++- src/lib_gui/qt/graphics/QtLineItemBase.h | 2 +- src/lib_gui/qt/view/QtGraphView.cpp | 1 + .../qt/view/graphElements/QtGraphEdge.cpp | 18 ++++- 19 files changed, 261 insertions(+), 17 deletions(-) create mode 100644 src/lib/data/graph/token_component/TokenComponentInheritanceChain.h diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 60ff87d2..c679ac96 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -124,6 +124,7 @@ add_files( data/graph/token_component/TokenComponentConst.h data/graph/token_component/TokenComponentFilePath.cpp data/graph/token_component/TokenComponentFilePath.h + data/graph/token_component/TokenComponentInheritanceChain.h data/graph/token_component/TokenComponentSignature.cpp data/graph/token_component/TokenComponentSignature.h data/graph/token_component/TokenComponentStatic.cpp diff --git a/src/lib/component/controller/ActivationController.cpp b/src/lib/component/controller/ActivationController.cpp index 84c73886..82799c3f 100644 --- a/src/lib/component/controller/ActivationController.cpp +++ b/src/lib/component/controller/ActivationController.cpp @@ -34,7 +34,6 @@ void ActivationController::handleMessage(MessageActivateEdge* message) m.tokenIds = message->aggregationIds; m.setKeepContent(false); m.isAggregation = true; - m.tokenNames.push_back(NameHierarchy(message->getFullName(), message->sourceNameHierarchy.getDelimiter())); m.dispatchImmediately(); } else @@ -42,7 +41,6 @@ void ActivationController::handleMessage(MessageActivateEdge* message) MessageActivateTokens m(message); m.tokenIds.push_back(message->tokenId); m.isEdge = true; - m.tokenNames.push_back(NameHierarchy(message->getFullName(), message->sourceNameHierarchy.getDelimiter())); m.dispatchImmediately(); } } diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index bed96215..516dc5f6 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -103,17 +103,34 @@ void GraphController::handleMessage(MessageActivateTokens* message) { bundleNodes(); } + else if (message->isAggregation) + { + bool isInheritanceChain = true; + for (auto edge : m_dummyEdges) + { + if (!edge->data->isType(Edge::EDGE_INHERITANCE)) + { + isInheritanceChain = false; + break; + } + } + + if (isInheritanceChain) + { + for (auto node : m_dummyNodes) + { + node->bundleInfo.layoutVertical = true; + } + } + + m_useBezierEdges = !isInheritanceChain; + } layoutNesting(); layoutGraph(true); assignBundleIds(); } - if (message->isAggregation) - { - m_useBezierEdges = true; - } - buildGraph(message, !isNamespace, true, isNamespace); } @@ -640,7 +657,8 @@ bool GraphController::setActive(const std::vector& activeTokenIds, bool show DummyNode* from = getDummyGraphNodeById(edge->ownerId); DummyNode* to = getDummyGraphNodeById(edge->targetId); - if (from && to && (showAllEdges || noActive || from->active || to->active || edge->active)) + bool isInheritance = edge->data->isType(Edge::EDGE_INHERITANCE); + if (from && to && (showAllEdges || noActive || from->active || to->active || edge->active || isInheritance)) { edge->visible = true; from->connected = true; diff --git a/src/lib/component/view/GraphViewStyle.cpp b/src/lib/component/view/GraphViewStyle.cpp index 5156f674..99049f34 100644 --- a/src/lib/component/view/GraphViewStyle.cpp +++ b/src/lib/component/view/GraphViewStyle.cpp @@ -104,6 +104,7 @@ GraphViewStyle::EdgeStyle::EdgeStyle() , arrowClosed(false) , cornerRadius(0) , verticalOffset(0) + , dashed(false) { } diff --git a/src/lib/component/view/GraphViewStyle.h b/src/lib/component/view/GraphViewStyle.h index d7abf04f..e86e4108 100644 --- a/src/lib/component/view/GraphViewStyle.h +++ b/src/lib/component/view/GraphViewStyle.h @@ -89,6 +89,8 @@ public: Vec2i originOffset; Vec2i targetOffset; + + bool dashed; }; static std::shared_ptr getImpl(); diff --git a/src/lib/data/HierarchyCache.cpp b/src/lib/data/HierarchyCache.cpp index b52f39e3..02f62ca4 100644 --- a/src/lib/data/HierarchyCache.cpp +++ b/src/lib/data/HierarchyCache.cpp @@ -34,6 +34,12 @@ void HierarchyCache::HierarchyNode::setParent(HierarchyNode* parent) m_parent = parent; } +void HierarchyCache::HierarchyNode::addBase(HierarchyNode* base, Id edgeId) +{ + m_bases.push_back(base); + m_baseEdgeIds.push_back(edgeId); +} + void HierarchyCache::HierarchyNode::addChild(HierarchyNode* child) { m_children.push_back(child); @@ -100,6 +106,30 @@ void HierarchyCache::HierarchyNode::setIsImplicit(bool isImplicit) m_isImplicit = isImplicit; } +void HierarchyCache::HierarchyNode::addInheritanceEdgesRecursive( + Id startId, std::vector inheritanceEdgeIds, + const std::set& nodeIds, std::vector>>* inheritanceEdges) +{ + for (size_t i = 0; i < m_bases.size(); i++) + { + HierarchyNode* base = m_bases[i]; + Id baseId = base->getNodeId(); + + std::vector inheritanceEdgeIds2 = inheritanceEdgeIds; + inheritanceEdgeIds2.push_back(m_baseEdgeIds[i]); + + if (nodeIds.find(baseId) != nodeIds.end()) + { + std::vector inheritanceEdgeIds3 = inheritanceEdgeIds2; + + inheritanceEdges->push_back(std::make_tuple>( + std::forward(startId), std::forward(baseId), std::forward>(inheritanceEdgeIds3))); + } + + base->addInheritanceEdgesRecursive(startId, inheritanceEdgeIds2, nodeIds, inheritanceEdges); + } +} + void HierarchyCache::clear() { @@ -120,6 +150,14 @@ void HierarchyCache::createConnection(Id edgeId, Id fromId, Id toId, bool source to->setIsImplicit(targetImplicit); } +void HierarchyCache::createInheritance(Id edgeId, Id fromId, Id toId) +{ + HierarchyNode* from = createNode(fromId); + HierarchyNode* to = createNode(toId); + + from->addBase(to, edgeId); +} + Id HierarchyCache::getLastVisibleParentNodeId(Id nodeId) const { HierarchyNode* node = nullptr; @@ -240,6 +278,21 @@ bool HierarchyCache::nodeHasChildren(Id nodeId) const return false; } +std::vector>> HierarchyCache::getInheritanceEdgesForNodeId( + Id nodeId, const std::set& nodeIds) const +{ + std::vector>> inheritanceEdges; + + HierarchyNode* node = getNode(nodeId); + if (node) + { + std::vector inheritanceEdgeIds; + node->addInheritanceEdgesRecursive(node->getNodeId(), inheritanceEdgeIds, nodeIds, & inheritanceEdges); + } + + return inheritanceEdges; +} + HierarchyCache::HierarchyNode* HierarchyCache::getNode(Id nodeId) const { std::map>::const_iterator it = m_nodes.find(nodeId); diff --git a/src/lib/data/HierarchyCache.h b/src/lib/data/HierarchyCache.h index 25fdcaf2..6e611a21 100644 --- a/src/lib/data/HierarchyCache.h +++ b/src/lib/data/HierarchyCache.h @@ -14,6 +14,7 @@ public: void clear(); void createConnection(Id edgeId, Id fromId, Id toId, bool sourceVisible, bool targetImplicit); + void createInheritance(Id edgeId, Id fromId, Id toId); Id getLastVisibleParentNodeId(Id nodeId) const; size_t getIndexOfLastVisibleParentNode(Id nodeId) const; @@ -29,6 +30,8 @@ public: bool nodeHasChildren(Id nodeId) const; + std::vector>> getInheritanceEdgesForNodeId(Id nodeId, const std::set& nodeIds) const; + private: class HierarchyNode { @@ -43,6 +46,8 @@ private: HierarchyNode* getParent() const; void setParent(HierarchyNode* parent); + void addBase(HierarchyNode* base, Id edgeId); + void addChild(HierarchyNode* child); size_t getChildrenCount() const; @@ -57,11 +62,19 @@ private: bool isImplicit() const; void setIsImplicit(bool isImplicit); + void addInheritanceEdgesRecursive( + Id startId, std::vector inheritanceEdgeIds, + const std::set& nodeIds, std::vector>>* inheritanceEdges); + private: const Id m_nodeId; Id m_edgeId; HierarchyNode* m_parent; + + std::vector m_bases; + std::vector m_baseEdgeIds; + std::vector m_children; bool m_isVisible; diff --git a/src/lib/data/PersistentStorage.cpp b/src/lib/data/PersistentStorage.cpp index 6034f777..339cbbf4 100644 --- a/src/lib/data/PersistentStorage.cpp +++ b/src/lib/data/PersistentStorage.cpp @@ -17,6 +17,7 @@ #include "data/graph/token_component/TokenComponentAccess.h" #include "data/graph/token_component/TokenComponentAggregation.h" #include "data/graph/token_component/TokenComponentFilePath.h" +#include "data/graph/token_component/TokenComponentInheritanceChain.h" #include "data/graph/token_component/TokenComponentSignature.h" #include "data/graph/Graph.h" #include "data/location/SourceLocationCollection.h" @@ -1117,6 +1118,8 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds( addNodesToGraph(expandedChildIds, graph); addEdgesToGraph(expandedChildEdgeIds, graph); } + + addInheritanceChainsToGraph(nodeIds, graph); } addComponentAccessToGraph(graph); @@ -2078,6 +2081,72 @@ void PersistentStorage::addCompleteFlagsToSourceLocationCollection(SourceLocatio ); } +void PersistentStorage::addInheritanceChainsToGraph(const std::vector& activeNodeIds, Graph* graph) const +{ + TRACE(); + + std::set activeNodeIdsSet; + for (Id activeNodeId : activeNodeIds) + { + std::set visibleParentIds, edgeIds; + visibleParentIds.insert(activeNodeId); + m_hierarchyCache.addAllVisibleParentIdsForNodeId(activeNodeId, &visibleParentIds, &edgeIds); + + for (Id nodeId : visibleParentIds) + { + Node* node = graph->getNodeById(nodeId); + if (node && node->isType(Node::NODE_INHERITABLE_TYPE)) + { + activeNodeIdsSet.insert(node->getId()); + } + } + } + + std::set nodeIdsSet; + graph->forEachNode( + [&nodeIdsSet, &activeNodeIdsSet](Node* node) + { + if (node->isType(Node::NODE_INHERITABLE_TYPE) && activeNodeIdsSet.find(node->getId()) == activeNodeIdsSet.end()) + { + nodeIdsSet.insert(node->getId()); + } + } + ); + + std::vector*> nodeIdSets; + nodeIdSets.push_back(&activeNodeIdsSet); + nodeIdSets.push_back(&nodeIdsSet); + + size_t inheritanceEdgeCount = 1; + + for (size_t i = 0; i < nodeIdSets.size(); i++) + { + for (const Id nodeId : *nodeIdSets[i]) + { + for (const std::tuple>& edge : + m_hierarchyCache.getInheritanceEdgesForNodeId(nodeId, *nodeIdSets[(i + 1) % 2])) + { + Id sourceId = std::get<0>(edge); + Id targetId = std::get<1>(edge); + std::vector edgeIds = std::get<2>(edge); + + if (!edgeIds.size() || (edgeIds.size() == 1 && graph->getEdgeById(edgeIds[0]))) + { + continue; + } + + // Set first 2 bits to 1 to avoid collisions + Id inheritanceEdgeId = ~(~size_t(0) >> 2) + inheritanceEdgeCount++; + + Edge* inheritanceEdge = graph->createEdge( + inheritanceEdgeId, Edge::EDGE_INHERITANCE, graph->getNodeById(sourceId), graph->getNodeById(targetId)); + + inheritanceEdge->addComponentInheritanceChain(std::make_shared(edgeIds)); + } + } + } +} + void PersistentStorage::buildFilePathMaps() { TRACE(); @@ -2177,4 +2246,10 @@ void PersistentStorage::buildHierarchyCache() m_hierarchyCache.createConnection( edge.id, edge.sourceNodeId, edge.targetNodeId, sourceIsVisible, targetIsImplicit); } + + std::vector inheritanceEdges = m_sqliteIndexStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_INHERITANCE)); + for (const StorageEdge& edge : inheritanceEdges) + { + m_hierarchyCache.createInheritance(edge.id, edge.sourceNodeId, edge.targetNodeId); + } } diff --git a/src/lib/data/PersistentStorage.h b/src/lib/data/PersistentStorage.h index 9d2f9887..ce387c91 100644 --- a/src/lib/data/PersistentStorage.h +++ b/src/lib/data/PersistentStorage.h @@ -165,6 +165,7 @@ private: void addComponentAccessToGraph(Graph* graph) const; void addCompleteFlagsToSourceLocationCollection(SourceLocationCollection* collection) const; + void addInheritanceChainsToGraph(const std::vector& nodeIds, Graph* graph) const; void buildFilePathMaps(); void buildSearchIndex(); diff --git a/src/lib/data/graph/Edge.cpp b/src/lib/data/graph/Edge.cpp index 88de48ea..a903f68d 100644 --- a/src/lib/data/graph/Edge.cpp +++ b/src/lib/data/graph/Edge.cpp @@ -4,6 +4,7 @@ #include "data/graph/Node.h" #include "data/graph/token_component/TokenComponentAggregation.h" +#include "data/graph/token_component/TokenComponentInheritanceChain.h" #include "utility/logging/logging.h" #include "utility/utilityString.h" @@ -134,6 +135,22 @@ void Edge::addComponentAggregation(std::shared_ptr co } } +void Edge::addComponentInheritanceChain(std::shared_ptr component) +{ + if (getComponent()) + { + LOG_ERROR("TokenComponentInheritanceChain has been set before!"); + } + else if (m_type != EDGE_INHERITANCE) + { + LOG_ERROR("TokenComponentInheritanceChain can't be set on edge of type: " + getReadableTypeString()); + } + else + { + addComponent(component); + } +} + std::string Edge::getUnderscoredTypeString(EdgeType type) { return utility::replace(utility::replace(getReadableTypeString(type), "-", "_"), " ", "_"); diff --git a/src/lib/data/graph/Edge.h b/src/lib/data/graph/Edge.h index 8dab4f0a..db123941 100644 --- a/src/lib/data/graph/Edge.h +++ b/src/lib/data/graph/Edge.h @@ -8,8 +8,7 @@ class Node; class TokenComponentAggregation; -class TokenComponentAccess; -class TokenComponentDataType; +class TokenComponentInheritanceChain; class Edge : public Token @@ -57,6 +56,7 @@ public: // Component setters void addComponentAggregation(std::shared_ptr component); + void addComponentInheritanceChain(std::shared_ptr component); static std::string getUnderscoredTypeString(EdgeType type); static std::string getReadableTypeString(EdgeType type); diff --git a/src/lib/data/graph/Node.cpp b/src/lib/data/graph/Node.cpp index 26a604b0..6ee79ee9 100644 --- a/src/lib/data/graph/Node.cpp +++ b/src/lib/data/graph/Node.cpp @@ -14,7 +14,9 @@ const Node::NodeTypeMask Node::NODE_NOT_VISIBLE = Node::NODE_NAMESPACE | Node::NODE_PACKAGE; const Node::NodeTypeMask Node::NODE_USEABLE_TYPE = Node::NODE_NON_INDEXED | Node::NODE_BUILTIN_TYPE | - Node::NODE_BUILTIN_TYPE | Node::NODE_STRUCT | Node::NODE_CLASS | Node::NODE_INTERFACE | Node::NODE_TYPEDEF; + Node::NODE_STRUCT | Node::NODE_CLASS | Node::NODE_INTERFACE | Node::NODE_TYPEDEF; +const Node::NodeTypeMask Node::NODE_INHERITABLE_TYPE = Node::NODE_NON_INDEXED | Node::NODE_BUILTIN_TYPE | + NODE_TYPE | Node::NODE_STRUCT | Node::NODE_CLASS | Node::NODE_INTERFACE; std::string Node::getUnderscoredTypeString(NodeType type) { diff --git a/src/lib/data/graph/Node.h b/src/lib/data/graph/Node.h index 724a9319..965fb0c0 100644 --- a/src/lib/data/graph/Node.h +++ b/src/lib/data/graph/Node.h @@ -56,6 +56,7 @@ public: static const NodeTypeMask NODE_NOT_VISIBLE; static const NodeTypeMask NODE_USEABLE_TYPE; + static const NodeTypeMask NODE_INHERITABLE_TYPE; Node(Id id, NodeType type, NameHierarchy nameHierarchy, bool defined); Node(const Node& other); diff --git a/src/lib/data/graph/token_component/TokenComponentInheritanceChain.h b/src/lib/data/graph/token_component/TokenComponentInheritanceChain.h new file mode 100644 index 00000000..29183aaa --- /dev/null +++ b/src/lib/data/graph/token_component/TokenComponentInheritanceChain.h @@ -0,0 +1,23 @@ +#ifndef TOKEN_COMPONENT_INHERITANCE_CHAIN_H +#define TOKEN_COMPONENT_INHERITANCE_CHAIN_H + +#include "data/graph/token_component/TokenComponent.h" + +class TokenComponentInheritanceChain + : public TokenComponent +{ +public: + TokenComponentInheritanceChain(const std::vector& inheritanceEdgeIds) + : inheritanceEdgeIds(inheritanceEdgeIds) + { + } + + virtual std::shared_ptr copy() const + { + return std::make_shared(*this); + } + + const std::vector inheritanceEdgeIds; +}; + +#endif // TOKEN_COMPONENT_INHERITANCE_CHAIN_H diff --git a/src/lib_gui/qt/graphics/QtLineItemAngled.cpp b/src/lib_gui/qt/graphics/QtLineItemAngled.cpp index 84614ade..bd79004d 100644 --- a/src/lib_gui/qt/graphics/QtLineItemAngled.cpp +++ b/src/lib_gui/qt/graphics/QtLineItemAngled.cpp @@ -32,7 +32,8 @@ QPainterPath QtLineItemAngled::shape() const void QtLineItemAngled::paint(QPainter* painter, const QStyleOptionGraphicsItem* options, QWidget* widget) { - painter->setPen(pen()); + QPen p = pen(); + painter->setPen(p); QPainterPath path; @@ -169,7 +170,17 @@ void QtLineItemAngled::paint(QPainter* painter, const QStyleOptionGraphicsItem* partRect = getArrowBoundingRect(poly); if (drawRect.intersects(partRect) && m_showArrow) { - drawArrow(poly, &path); + if (m_style.dashed) + { + QPainterPath arrowPath; + drawArrow(poly, &path, &arrowPath); + + painter->drawPath(arrowPath); + } + else + { + drawArrow(poly, &path); + } } else { @@ -177,5 +188,11 @@ void QtLineItemAngled::paint(QPainter* painter, const QStyleOptionGraphicsItem* } } + if (m_style.dashed) + { + p.setStyle(Qt::DashLine); + painter->setPen(p); + } + painter->drawPath(path); } diff --git a/src/lib_gui/qt/graphics/QtLineItemBase.cpp b/src/lib_gui/qt/graphics/QtLineItemBase.cpp index b6bfed35..71897de6 100644 --- a/src/lib_gui/qt/graphics/QtLineItemBase.cpp +++ b/src/lib_gui/qt/graphics/QtLineItemBase.cpp @@ -336,7 +336,7 @@ QRectF QtLineItemBase::getArrowBoundingRect(const QPolygon& poly) const return rect; } -void QtLineItemBase::drawArrow(const QPolygon& poly, QPainterPath* path) const +void QtLineItemBase::drawArrow(const QPolygon& poly, QPainterPath* path, QPainterPath* arrowPath) const { int dir = getDirection(poly.at(1), poly.at(0)); @@ -364,7 +364,6 @@ void QtLineItemBase::drawArrow(const QPolygon& poly, QPainterPath* path) const break; } - if (m_style.arrowClosed) { path->lineTo(tip + toBack); @@ -375,6 +374,12 @@ void QtLineItemBase::drawArrow(const QPolygon& poly, QPainterPath* path) const path->lineTo(tip); } + if (arrowPath) + { + path = arrowPath; + path->moveTo(tip); + } + path->lineTo(tip + toBack + toLeft); if (m_style.arrowClosed) diff --git a/src/lib_gui/qt/graphics/QtLineItemBase.h b/src/lib_gui/qt/graphics/QtLineItemBase.h index d1105295..fe65d6eb 100644 --- a/src/lib_gui/qt/graphics/QtLineItemBase.h +++ b/src/lib_gui/qt/graphics/QtLineItemBase.h @@ -45,7 +45,7 @@ protected: int getDirection(const QPointF& a, const QPointF& b) const; QRectF getArrowBoundingRect(const QPolygon& poly) const; - void drawArrow(const QPolygon& poly, QPainterPath* path) const; + void drawArrow(const QPolygon& poly, QPainterPath* path, QPainterPath* arrowPath = nullptr) const; void getPivotPoints(Vec2f* p, const Vec4i& in, const Vec4i& out, int offset, bool target) const; diff --git a/src/lib_gui/qt/view/QtGraphView.cpp b/src/lib_gui/qt/view/QtGraphView.cpp index deca1787..0c59f001 100644 --- a/src/lib_gui/qt/view/QtGraphView.cpp +++ b/src/lib_gui/qt/view/QtGraphView.cpp @@ -398,6 +398,7 @@ MessageActivateTrail QtGraphView::getMessageActivateTrail(bool forward) switch (node->getData()->getType()) { + case Node::NODE_NON_INDEXED: case Node::NODE_CLASS: case Node::NODE_STRUCT: case Node::NODE_INTERFACE: diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp index 79f1715a..e181bfb9 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp @@ -6,6 +6,7 @@ #include "component/view/GraphViewStyle.h" #include "data/graph/Edge.h" #include "data/graph/token_component/TokenComponentAggregation.h" +#include "data/graph/token_component/TokenComponentInheritanceChain.h" #include "qt/graphics/QtLineItemAngled.h" #include "qt/graphics/QtLineItemBezier.h" #include "qt/graphics/QtLineItemStraight.h" @@ -207,6 +208,15 @@ void QtGraphEdge::updateLine() showArrow = m_direction != TokenComponentAggregation::DIRECTION_NONE; } + if (getData()) + { + TokenComponentInheritanceChain* componentInheritance = getData()->getComponent(); + if (componentInheritance && componentInheritance->inheritanceEdgeIds.size() > 1) + { + style.dashed = true; + } + } + child->updateLine( owner->getBoundingRect(), target->getBoundingRect(), owner->getParentBoundingRect(), target->getParentBoundingRect(), @@ -262,9 +272,11 @@ void QtGraphEdge::onClick() } else { + TokenComponentInheritanceChain* componentInheritance = getData()->getComponent(); + MessageActivateEdge msg( getData()->getId(), - getData()->getType(), + componentInheritance ? Edge::EDGE_AGGREGATION : getData()->getType(), getData()->getFrom()->getNameHierarchy(), getData()->getTo()->getNameHierarchy() ); @@ -274,6 +286,10 @@ void QtGraphEdge::onClick() msg.aggregationIds = utility::toVector(getData()->getComponent()->getAggregationIds()); } + else if (componentInheritance) + { + msg.aggregationIds = componentInheritance->inheritanceEdgeIds; + } msg.dispatch(); }