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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Id>& 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;
|
||||
|
||||
@@ -104,6 +104,7 @@ GraphViewStyle::EdgeStyle::EdgeStyle()
|
||||
, arrowClosed(false)
|
||||
, cornerRadius(0)
|
||||
, verticalOffset(0)
|
||||
, dashed(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ public:
|
||||
|
||||
Vec2i originOffset;
|
||||
Vec2i targetOffset;
|
||||
|
||||
bool dashed;
|
||||
};
|
||||
|
||||
static std::shared_ptr<GraphViewStyleImpl> getImpl();
|
||||
|
||||
@@ -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<Id> inheritanceEdgeIds,
|
||||
const std::set<Id>& nodeIds, std::vector<std::tuple<Id, Id, std::vector<Id>>>* inheritanceEdges)
|
||||
{
|
||||
for (size_t i = 0; i < m_bases.size(); i++)
|
||||
{
|
||||
HierarchyNode* base = m_bases[i];
|
||||
Id baseId = base->getNodeId();
|
||||
|
||||
std::vector<Id> inheritanceEdgeIds2 = inheritanceEdgeIds;
|
||||
inheritanceEdgeIds2.push_back(m_baseEdgeIds[i]);
|
||||
|
||||
if (nodeIds.find(baseId) != nodeIds.end())
|
||||
{
|
||||
std::vector<Id> inheritanceEdgeIds3 = inheritanceEdgeIds2;
|
||||
|
||||
inheritanceEdges->push_back(std::make_tuple<Id, Id, std::vector<Id>>(
|
||||
std::forward<Id>(startId), std::forward<Id>(baseId), std::forward<std::vector<Id>>(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<std::tuple<Id, Id, std::vector<Id>>> HierarchyCache::getInheritanceEdgesForNodeId(
|
||||
Id nodeId, const std::set<Id>& nodeIds) const
|
||||
{
|
||||
std::vector<std::tuple<Id, Id, std::vector<Id>>> inheritanceEdges;
|
||||
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (node)
|
||||
{
|
||||
std::vector<Id> inheritanceEdgeIds;
|
||||
node->addInheritanceEdgesRecursive(node->getNodeId(), inheritanceEdgeIds, nodeIds, & inheritanceEdges);
|
||||
}
|
||||
|
||||
return inheritanceEdges;
|
||||
}
|
||||
|
||||
HierarchyCache::HierarchyNode* HierarchyCache::getNode(Id nodeId) const
|
||||
{
|
||||
std::map<Id, std::shared_ptr<HierarchyNode>>::const_iterator it = m_nodes.find(nodeId);
|
||||
|
||||
@@ -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<std::tuple<Id, Id, std::vector<Id>>> getInheritanceEdgesForNodeId(Id nodeId, const std::set<Id>& 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<Id> inheritanceEdgeIds,
|
||||
const std::set<Id>& nodeIds, std::vector<std::tuple<Id, Id, std::vector<Id>>>* inheritanceEdges);
|
||||
|
||||
private:
|
||||
const Id m_nodeId;
|
||||
Id m_edgeId;
|
||||
|
||||
HierarchyNode* m_parent;
|
||||
|
||||
std::vector<HierarchyNode*> m_bases;
|
||||
std::vector<Id> m_baseEdgeIds;
|
||||
|
||||
std::vector<HierarchyNode*> m_children;
|
||||
|
||||
bool m_isVisible;
|
||||
|
||||
@@ -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<Graph> 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<Id>& activeNodeIds, Graph* graph) const
|
||||
{
|
||||
TRACE();
|
||||
|
||||
std::set<Id> activeNodeIdsSet;
|
||||
for (Id activeNodeId : activeNodeIds)
|
||||
{
|
||||
std::set<Id> 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<Id> 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<std::set<Id>*> 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<Id, Id, std::vector<Id>>& edge :
|
||||
m_hierarchyCache.getInheritanceEdgesForNodeId(nodeId, *nodeIdSets[(i + 1) % 2]))
|
||||
{
|
||||
Id sourceId = std::get<0>(edge);
|
||||
Id targetId = std::get<1>(edge);
|
||||
std::vector<Id> 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<TokenComponentInheritanceChain>(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<StorageEdge> inheritanceEdges = m_sqliteIndexStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_INHERITANCE));
|
||||
for (const StorageEdge& edge : inheritanceEdges)
|
||||
{
|
||||
m_hierarchyCache.createInheritance(edge.id, edge.sourceNodeId, edge.targetNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ private:
|
||||
void addComponentAccessToGraph(Graph* graph) const;
|
||||
|
||||
void addCompleteFlagsToSourceLocationCollection(SourceLocationCollection* collection) const;
|
||||
void addInheritanceChainsToGraph(const std::vector<Id>& nodeIds, Graph* graph) const;
|
||||
|
||||
void buildFilePathMaps();
|
||||
void buildSearchIndex();
|
||||
|
||||
@@ -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<TokenComponentAggregation> co
|
||||
}
|
||||
}
|
||||
|
||||
void Edge::addComponentInheritanceChain(std::shared_ptr<TokenComponentInheritanceChain> component)
|
||||
{
|
||||
if (getComponent<TokenComponentInheritanceChain>())
|
||||
{
|
||||
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), "-", "_"), " ", "_");
|
||||
|
||||
@@ -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<TokenComponentAggregation> component);
|
||||
void addComponentInheritanceChain(std::shared_ptr<TokenComponentInheritanceChain> component);
|
||||
|
||||
static std::string getUnderscoredTypeString(EdgeType type);
|
||||
static std::string getReadableTypeString(EdgeType type);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Id>& inheritanceEdgeIds)
|
||||
: inheritanceEdgeIds(inheritanceEdgeIds)
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<TokenComponent> copy() const
|
||||
{
|
||||
return std::make_shared<TokenComponentInheritanceChain>(*this);
|
||||
}
|
||||
|
||||
const std::vector<Id> inheritanceEdgeIds;
|
||||
};
|
||||
|
||||
#endif // TOKEN_COMPONENT_INHERITANCE_CHAIN_H
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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<TokenComponentInheritanceChain>();
|
||||
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<TokenComponentInheritanceChain>();
|
||||
|
||||
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<Id>(getData()->getComponent<TokenComponentAggregation>()->getAggregationIds());
|
||||
}
|
||||
else if (componentInheritance)
|
||||
{
|
||||
msg.aggregationIds = componentInheritance->inheritanceEdgeIds;
|
||||
}
|
||||
|
||||
msg.dispatch();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user