ui: bundling nodes in the graph view
This change bundles similar nodes in the graph view together. When the bundled node or it's aggregation edge are clicked, then the bundle is split. This change also adds an arrow to the aggregation edge based on the direction of it's edges.
This commit is contained in:
@@ -811,10 +811,15 @@ std::shared_ptr<Graph> Storage::getGraphForActiveTokenIds(const std::vector<Id>&
|
||||
Node::NODE_UNDEFINED_FUNCTION | Node::NODE_FUNCTION | Node::NODE_METHOD |
|
||||
Node::NODE_UNDEFINED_VARIABLE | Node::NODE_GLOBAL_VARIABLE | Node::NODE_FIELD;
|
||||
|
||||
if (!node->isType(varFuncMask) || !edge->isType(Edge::EDGE_AGGREGATION))
|
||||
const Node::NodeTypeMask typeMask = Node::NODE_STRUCT | Node::NODE_CLASS;
|
||||
|
||||
if ((node->isType(varFuncMask) && edge->isType(Edge::EDGE_AGGREGATION)) ||
|
||||
(node->isType(typeMask) && edge->isType(Edge::EDGE_TYPE_USAGE | Edge::EDGE_TYPE_OF)))
|
||||
{
|
||||
graph->addEdgeAndAllChildrenAsPlainCopy(edge);
|
||||
return;
|
||||
}
|
||||
|
||||
graph->addEdgeAndAllChildrenAsPlainCopy(edge);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -128,17 +128,17 @@ Edge* Node::findEdge(std::function<bool(Edge*)> func) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Edge* Node::findEdgeOfType(Edge::EdgeType type) const
|
||||
Edge* Node::findEdgeOfType(Edge::EdgeTypeMask mask) const
|
||||
{
|
||||
return findEdgeOfType(type, [](Edge* e){ return true; });
|
||||
return findEdgeOfType(mask, [](Edge* e){ return true; });
|
||||
}
|
||||
|
||||
Edge* Node::findEdgeOfType(Edge::EdgeType type, std::function<bool(Edge*)> func) const
|
||||
Edge* Node::findEdgeOfType(Edge::EdgeTypeMask mask, std::function<bool(Edge*)> func) const
|
||||
{
|
||||
std::vector<Edge*>::const_iterator it = find_if(m_edges.begin(), m_edges.end(),
|
||||
[type, func](Edge* e)
|
||||
[mask, func](Edge* e)
|
||||
{
|
||||
if (e->getType() == type)
|
||||
if (e->isType(mask))
|
||||
{
|
||||
return func(e);
|
||||
}
|
||||
@@ -180,12 +180,12 @@ void Node::forEachEdge(std::function<void(Edge*)> func) const
|
||||
for_each(m_edges.begin(), m_edges.end(), func);
|
||||
}
|
||||
|
||||
void Node::forEachEdgeOfType(Edge::EdgeType type, std::function<void(Edge*)> func) const
|
||||
void Node::forEachEdgeOfType(Edge::EdgeTypeMask mask, std::function<void(Edge*)> func) const
|
||||
{
|
||||
for_each(m_edges.begin(), m_edges.end(),
|
||||
[type, func](Edge* e)
|
||||
[mask, func](Edge* e)
|
||||
{
|
||||
if (e->getType() == type)
|
||||
if (e->isType(mask))
|
||||
{
|
||||
func(e);
|
||||
}
|
||||
|
||||
@@ -67,12 +67,12 @@ public:
|
||||
Edge* getMemberEdge() const;
|
||||
|
||||
Edge* findEdge(std::function<bool(Edge*)> func) const;
|
||||
Edge* findEdgeOfType(Edge::EdgeType type) const;
|
||||
Edge* findEdgeOfType(Edge::EdgeType type, std::function<bool(Edge*)> func) const;
|
||||
Edge* findEdgeOfType(Edge::EdgeTypeMask mask) const;
|
||||
Edge* findEdgeOfType(Edge::EdgeTypeMask mask, std::function<bool(Edge*)> func) const;
|
||||
Node* findChildNode(std::function<bool(Node*)> func) const;
|
||||
|
||||
void forEachEdge(std::function<void(Edge*)> func) const;
|
||||
void forEachEdgeOfType(Edge::EdgeType type, std::function<void(Edge*)> func) const;
|
||||
void forEachEdgeOfType(Edge::EdgeTypeMask mask, std::function<void(Edge*)> func) const;
|
||||
void forEachChildNode(std::function<void(Node*)> func) const;
|
||||
|
||||
bool hasReferences() const;
|
||||
|
||||
@@ -197,7 +197,8 @@ void StorageGraph::updateAggregationEdges(Node* from, Node* to, Id addEdgeId, Id
|
||||
|
||||
if (addEdgeId)
|
||||
{
|
||||
edge->getComponent<TokenComponentAggregation>()->addAggregationId(addEdgeId);
|
||||
bool forward = (edge->getFrom() == from);
|
||||
edge->getComponent<TokenComponentAggregation>()->addAggregationId(addEdgeId, forward);
|
||||
}
|
||||
|
||||
if (edge && removeEdgeId)
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
#include "data/graph/token_component/TokenComponentAggregation.h"
|
||||
|
||||
TokenComponentAggregation::Direction TokenComponentAggregation::opposite(Direction direction)
|
||||
{
|
||||
if (direction == DIRECTION_FORWARD)
|
||||
{
|
||||
return DIRECTION_BACKWARD;
|
||||
}
|
||||
else if (direction == DIRECTION_BACKWARD)
|
||||
{
|
||||
return DIRECTION_FORWARD;
|
||||
}
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
TokenComponentAggregation::TokenComponentAggregation()
|
||||
: m_direction(DIRECTION_INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -18,17 +33,53 @@ int TokenComponentAggregation::getAggregationCount() const
|
||||
return m_ids.size();
|
||||
}
|
||||
|
||||
const std::set<Id>& TokenComponentAggregation::getAggregationIds() const
|
||||
std::set<Id> TokenComponentAggregation::getAggregationIds() const
|
||||
{
|
||||
return m_ids;
|
||||
std::set<Id> ids;
|
||||
|
||||
for (const std::pair<Id, Direction>& p : m_ids)
|
||||
{
|
||||
ids.insert(p.first);
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
void TokenComponentAggregation::addAggregationId(Id id)
|
||||
void TokenComponentAggregation::addAggregationId(Id id, bool forward)
|
||||
{
|
||||
m_ids.insert(id);
|
||||
m_ids.emplace(id, forward ? DIRECTION_FORWARD : DIRECTION_BACKWARD);
|
||||
|
||||
m_direction = DIRECTION_INVALID;
|
||||
}
|
||||
|
||||
void TokenComponentAggregation::removeAggregationId(Id id)
|
||||
{
|
||||
m_ids.erase(id);
|
||||
|
||||
m_direction = DIRECTION_INVALID;
|
||||
}
|
||||
|
||||
TokenComponentAggregation::Direction TokenComponentAggregation::getDirection()
|
||||
{
|
||||
if (m_direction != DIRECTION_INVALID)
|
||||
{
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
m_direction = DIRECTION_NONE;
|
||||
|
||||
for (const std::pair<Id, Direction>& p : m_ids)
|
||||
{
|
||||
if (m_direction == DIRECTION_NONE)
|
||||
{
|
||||
m_direction = p.second;
|
||||
}
|
||||
else if (m_direction != p.second)
|
||||
{
|
||||
m_direction = DIRECTION_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef TOKEN_COMPONENT_AGGREGATION_H
|
||||
#define TOKEN_COMPONENT_AGGREGATION_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "utility/types.h"
|
||||
@@ -11,19 +12,32 @@ class TokenComponentAggregation
|
||||
: public TokenComponent
|
||||
{
|
||||
public:
|
||||
enum Direction
|
||||
{
|
||||
DIRECTION_NONE,
|
||||
DIRECTION_FORWARD,
|
||||
DIRECTION_BACKWARD,
|
||||
DIRECTION_INVALID
|
||||
};
|
||||
|
||||
static Direction opposite(Direction direction);
|
||||
|
||||
TokenComponentAggregation();
|
||||
virtual ~TokenComponentAggregation();
|
||||
|
||||
virtual std::shared_ptr<TokenComponent> copy() const;
|
||||
|
||||
int getAggregationCount() const;
|
||||
const std::set<Id>& getAggregationIds() const;
|
||||
std::set<Id> getAggregationIds() const;
|
||||
|
||||
void addAggregationId(Id id);
|
||||
void addAggregationId(Id id, bool forward);
|
||||
void removeAggregationId(Id id);
|
||||
|
||||
Direction getDirection();
|
||||
|
||||
private:
|
||||
std::set<Id> m_ids;
|
||||
std::map<Id, Direction> m_ids;
|
||||
Direction m_direction;
|
||||
};
|
||||
|
||||
#endif // TOKEN_COMPONENT_AGGREGATION_H
|
||||
|
||||
Reference in New Issue
Block a user