data/logic/ui: added aggregation edges
This change adds the creation of aggregation edges to the StorageGraph, which save the connection counts between children in their parents. Aggregation edges are displayed using a straight line, that is thicker than more connections it represents with the connection count in the middle.
This commit is contained in:
@@ -87,6 +87,8 @@ add_files(
|
||||
data/graph/token_component/TokenComponentAbstraction.h
|
||||
data/graph/token_component/TokenComponentAccess.cpp
|
||||
data/graph/token_component/TokenComponentAccess.h
|
||||
data/graph/token_component/TokenComponentAggregation.cpp
|
||||
data/graph/token_component/TokenComponentAggregation.h
|
||||
data/graph/token_component/TokenComponentConst.cpp
|
||||
data/graph/token_component/TokenComponentConst.h
|
||||
data/graph/token_component/TokenComponentName.cpp
|
||||
|
||||
@@ -168,7 +168,14 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node)
|
||||
return;
|
||||
}
|
||||
|
||||
result.connected = true;
|
||||
if (edge->isType(Edge::EDGE_AGGREGATION))
|
||||
{
|
||||
result.aggregated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.connected = true;
|
||||
}
|
||||
|
||||
for (const DummyEdge& dummy : m_dummyEdges)
|
||||
{
|
||||
@@ -189,7 +196,7 @@ void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenI
|
||||
{
|
||||
for (DummyNode& node : m_dummyNodes)
|
||||
{
|
||||
setNodeActiveAndVisibilityRecursiveBottomUp(node, activeTokenIds);
|
||||
setNodeActiveAndVisibilityRecursiveBottomUp(node, activeTokenIds, false);
|
||||
}
|
||||
|
||||
for (DummyEdge& edge : m_dummyEdges)
|
||||
@@ -203,7 +210,7 @@ void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenI
|
||||
}
|
||||
|
||||
bool GraphController::setNodeActiveAndVisibilityRecursiveBottomUp(
|
||||
DummyNode& node, const std::vector<Id>& activeTokenIds
|
||||
DummyNode& node, const std::vector<Id>& activeTokenIds, bool aggregated
|
||||
) const {
|
||||
node.visible = false;
|
||||
node.active = false;
|
||||
@@ -216,13 +223,13 @@ bool GraphController::setNodeActiveAndVisibilityRecursiveBottomUp(
|
||||
bool childVisible = false;
|
||||
for (DummyNode& subNode : node.subNodes)
|
||||
{
|
||||
if (setNodeActiveAndVisibilityRecursiveBottomUp(subNode, activeTokenIds))
|
||||
if (setNodeActiveAndVisibilityRecursiveBottomUp(subNode, activeTokenIds, aggregated | node.aggregated))
|
||||
{
|
||||
childVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.active || node.connected || childVisible)
|
||||
if (node.active || node.connected || childVisible || (!aggregated && node.aggregated))
|
||||
{
|
||||
setNodeVisibilityRecursiveTopDown(node);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,8 @@ private:
|
||||
DummyNode createDummyNodeTopDown(Node* node);
|
||||
|
||||
void setActiveAndVisibility(const std::vector<Id>& activeTokenIds);
|
||||
bool setNodeActiveAndVisibilityRecursiveBottomUp(DummyNode& node, const std::vector<Id>& activeTokenIds) const;
|
||||
bool setNodeActiveAndVisibilityRecursiveBottomUp(
|
||||
DummyNode& node, const std::vector<Id>& activeTokenIds, bool aggregated) const;
|
||||
void setNodeVisibilityRecursiveTopDown(DummyNode& node) const;
|
||||
|
||||
void layoutNesting();
|
||||
|
||||
@@ -52,6 +52,7 @@ struct DummyNode
|
||||
, accessType(TokenComponentAccess::ACCESS_NONE)
|
||||
, active(false)
|
||||
, connected(false)
|
||||
, aggregated(false)
|
||||
, expanded(false)
|
||||
, invisibleSubNodeCount(0)
|
||||
, visible(false)
|
||||
@@ -63,6 +64,7 @@ struct DummyNode
|
||||
, accessType(accessType)
|
||||
, active(false)
|
||||
, connected(false)
|
||||
, aggregated(false)
|
||||
, expanded(false)
|
||||
, invisibleSubNodeCount(0)
|
||||
, visible(false)
|
||||
@@ -77,6 +79,7 @@ struct DummyNode
|
||||
|
||||
bool active;
|
||||
bool connected;
|
||||
bool aggregated;
|
||||
|
||||
bool expanded;
|
||||
size_t invisibleSubNodeCount;
|
||||
|
||||
@@ -481,9 +481,16 @@ std::shared_ptr<Graph> Storage::getGraphForActiveTokenIds(const std::vector<Id>&
|
||||
graph->addNodeAndAllChildrenAsPlainCopy(node->getLastParentNode());
|
||||
|
||||
node->forEachEdge(
|
||||
[graph](Edge* edge)
|
||||
[graph, node](Edge* edge)
|
||||
{
|
||||
graph->addEdgeAndAllChildrenAsPlainCopy(edge);
|
||||
const Node::NodeTypeMask varFuncMask =
|
||||
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))
|
||||
{
|
||||
graph->addEdgeAndAllChildrenAsPlainCopy(edge);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "data/graph/Node.h"
|
||||
#include "data/graph/token_component/TokenComponentAggregation.h"
|
||||
#include "data/graph/token_component/TokenComponentAccess.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
@@ -76,6 +77,22 @@ bool Edge::isEdge() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Edge::addComponentAggregation(std::shared_ptr<TokenComponentAggregation> component)
|
||||
{
|
||||
if (getComponent<TokenComponentAggregation>())
|
||||
{
|
||||
LOG_ERROR("TokenComponentAggregation has been set before!");
|
||||
}
|
||||
else if (m_type != EDGE_AGGREGATION)
|
||||
{
|
||||
LOG_ERROR("TokenComponentAggregation can't be set on edge of type: " + getTypeString());
|
||||
}
|
||||
else
|
||||
{
|
||||
addComponent(component);
|
||||
}
|
||||
}
|
||||
|
||||
void Edge::addComponentAccess(std::shared_ptr<TokenComponentAccess> component)
|
||||
{
|
||||
if (getComponent<TokenComponentAccess>())
|
||||
@@ -118,6 +135,8 @@ std::string Edge::getTypeString(EdgeType type) const
|
||||
return "template parameter";
|
||||
case EDGE_TEMPLATE_SPECIALIZATION_OF:
|
||||
return "template specialization";
|
||||
case EDGE_AGGREGATION:
|
||||
return "aggregation";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -132,10 +151,16 @@ std::string Edge::getAsString() const
|
||||
std::stringstream str;
|
||||
str << "[" << getId() << "] " << getTypeString() << ": \"" << m_from->getName() << "\" -> \"" + m_to->getName() << "\"";
|
||||
|
||||
TokenComponentAccess* component = getComponent<TokenComponentAccess>();
|
||||
if (component)
|
||||
TokenComponentAccess* access = getComponent<TokenComponentAccess>();
|
||||
if (access)
|
||||
{
|
||||
str << " " << component->getAccessString();
|
||||
str << " " << access->getAccessString();
|
||||
}
|
||||
|
||||
TokenComponentAggregation* aggregation = getComponent<TokenComponentAggregation>();
|
||||
if (aggregation)
|
||||
{
|
||||
str << " " << aggregation->getAggregationCount();
|
||||
}
|
||||
|
||||
return str.str();
|
||||
@@ -222,6 +247,13 @@ bool Edge::checkType() const
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
case EDGE_AGGREGATION:
|
||||
if (!m_from->isType(typeMask | variableMask | functionMask) || !m_to->isType(typeMask | variableMask | functionMask))
|
||||
{
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_ERROR_STREAM(
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "data/graph/Token.h"
|
||||
|
||||
class Node;
|
||||
class TokenComponentAggregation;
|
||||
class TokenComponentAccess;
|
||||
class TokenComponentDataType;
|
||||
|
||||
@@ -26,7 +27,9 @@ public:
|
||||
EDGE_INHERITANCE = 0x80,
|
||||
EDGE_TYPEDEF_OF = 0x100,
|
||||
EDGE_TEMPLATE_PARAMETER_OF = 0x200,
|
||||
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x400
|
||||
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x400,
|
||||
|
||||
EDGE_AGGREGATION = 0x800
|
||||
};
|
||||
|
||||
Edge(EdgeType type, Node* from, Node* to);
|
||||
@@ -46,6 +49,7 @@ public:
|
||||
virtual bool isEdge() const;
|
||||
|
||||
// Component setters
|
||||
void addComponentAggregation(std::shared_ptr<TokenComponentAggregation> component);
|
||||
void addComponentAccess(std::shared_ptr<TokenComponentAccess> component);
|
||||
|
||||
// Logging.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "data/graph/StorageGraph.h"
|
||||
|
||||
#include "data/graph/token_component/TokenComponentAggregation.h"
|
||||
#include "data/graph/token_component/TokenComponentName.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/utilityString.h"
|
||||
@@ -87,7 +88,16 @@ Edge* StorageGraph::createEdge(Edge::EdgeType type, Node* from, Node* to)
|
||||
return edge;
|
||||
}
|
||||
|
||||
return insertEdge(type, from, to);
|
||||
edge = insertEdge(type, from, to);
|
||||
|
||||
if (from->getLastParentNode() != to->getLastParentNode())
|
||||
{
|
||||
Id edgeId = edge->getId();
|
||||
updateAggregationEdges(from->getParentNode(), to, edgeId);
|
||||
updateAggregationEdges(from, to->getParentNode(), edgeId);
|
||||
}
|
||||
|
||||
return edge;
|
||||
}
|
||||
|
||||
Node* StorageGraph::insertNodeHierarchy(Node::NodeType type, SearchNode* searchNode)
|
||||
@@ -140,3 +150,39 @@ Edge* StorageGraph::insertEdge(Edge::EdgeType type, Node* from, Node* to)
|
||||
m_edges.emplace(edgePtr->getId(), edgePtr);
|
||||
return edgePtr.get();
|
||||
}
|
||||
|
||||
void StorageGraph::updateAggregationEdges(Node* from, Node* to, Id edgeId)
|
||||
{
|
||||
if (!from || !to || from == to)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Node::NodeTypeMask mask = Node::NODE_UNDEFINED_TYPE | Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_ENUM;
|
||||
const Node::NodeTypeMask varFuncMask =
|
||||
Node::NODE_UNDEFINED_FUNCTION | Node::NODE_FUNCTION | Node::NODE_UNDEFINED_VARIABLE | Node::NODE_GLOBAL_VARIABLE;
|
||||
|
||||
if ((from->isType(mask) && to->isType(mask | varFuncMask)) ||
|
||||
(from->isType(mask | varFuncMask) && to->isType(mask)))
|
||||
{
|
||||
Edge* edge = from->findEdgeOfType(Edge::EDGE_AGGREGATION,
|
||||
[from, to](Edge* e)
|
||||
{
|
||||
const Node* f = e->getFrom();
|
||||
const Node* t = e->getTo();
|
||||
return (f == from && t == to) || (f == to && t == from);
|
||||
}
|
||||
);
|
||||
|
||||
if (!edge)
|
||||
{
|
||||
edge = insertEdge(Edge::EDGE_AGGREGATION, from, to);
|
||||
edge->addComponentAggregation(std::make_shared<TokenComponentAggregation>());
|
||||
}
|
||||
|
||||
edge->getComponent<TokenComponentAggregation>()->addAggregationId(edgeId);
|
||||
}
|
||||
|
||||
updateAggregationEdges(from->getParentNode(), to, edgeId);
|
||||
updateAggregationEdges(from, to->getParentNode(), edgeId);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ private:
|
||||
Node* insertNodeHierarchy(Node::NodeType type, SearchNode* searchNode);
|
||||
Node* insertNode(Node::NodeType type, Node* parentNode, SearchNode* searchNode);
|
||||
Edge* insertEdge(Edge::EdgeType type, Node* from, Node* to);
|
||||
|
||||
void updateAggregationEdges(Node* from, Node* to, Id edgeId);
|
||||
};
|
||||
|
||||
#endif // STORAGE_GRAPH_H
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "data/graph/token_component/TokenComponentAggregation.h"
|
||||
|
||||
TokenComponentAggregation::TokenComponentAggregation()
|
||||
{
|
||||
}
|
||||
|
||||
TokenComponentAggregation::~TokenComponentAggregation()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenComponent> TokenComponentAggregation::copy() const
|
||||
{
|
||||
return std::make_shared<TokenComponentAggregation>(*this);
|
||||
}
|
||||
|
||||
int TokenComponentAggregation::getAggregationCount() const
|
||||
{
|
||||
return m_ids.size();
|
||||
}
|
||||
|
||||
void TokenComponentAggregation::addAggregationId(Id id)
|
||||
{
|
||||
m_ids.insert(id);
|
||||
}
|
||||
|
||||
const std::set<Id>& TokenComponentAggregation::getAggregationIds() const
|
||||
{
|
||||
return m_ids;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef TOKEN_COMPONENT_AGGREGATION_H
|
||||
#define TOKEN_COMPONENT_AGGREGATION_H
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "utility/types.h"
|
||||
|
||||
#include "data/graph/token_component/TokenComponent.h"
|
||||
|
||||
class TokenComponentAggregation
|
||||
: public TokenComponent
|
||||
{
|
||||
public:
|
||||
TokenComponentAggregation();
|
||||
virtual ~TokenComponentAggregation();
|
||||
|
||||
virtual std::shared_ptr<TokenComponent> copy() const;
|
||||
|
||||
int getAggregationCount() const;
|
||||
void addAggregationId(Id id);
|
||||
const std::set<Id>& getAggregationIds() const;
|
||||
|
||||
private:
|
||||
std::set<Id> m_ids;
|
||||
};
|
||||
|
||||
#endif // TOKEN_COMPONENT_AGGREGATION_H
|
||||
@@ -39,11 +39,11 @@ public:
|
||||
void assign(const VectorBase<U, N>& other);
|
||||
|
||||
template<class U>
|
||||
VectorBase<T, N> add(const VectorBase<U, N>& other);
|
||||
VectorBase<T, N>& add(const VectorBase<U, N>& other);
|
||||
template<class U>
|
||||
VectorBase<T, N> subtract(const VectorBase<U, N>& other);
|
||||
VectorBase<T, N>& subtract(const VectorBase<U, N>& other);
|
||||
template<class U>
|
||||
VectorBase<T, N> scalarMultiplication(const U& scalar);
|
||||
VectorBase<T, N>& scalarMultiplication(const U& scalar);
|
||||
template<class U>
|
||||
T dotProduct(const VectorBase<U, N>& other);
|
||||
|
||||
@@ -71,13 +71,13 @@ public:
|
||||
VectorBase<T, N> operator/(const U& scalar) const;
|
||||
|
||||
template<class U>
|
||||
VectorBase<T, N> operator+=(const VectorBase<U, N>& other);
|
||||
VectorBase<T, N>& operator+=(const VectorBase<U, N>& other);
|
||||
template<class U>
|
||||
VectorBase<T, N> operator-=(const VectorBase<U, N>& other);
|
||||
VectorBase<T, N>& operator-=(const VectorBase<U, N>& other);
|
||||
template<class U>
|
||||
VectorBase<T, N> operator*=(const U& scalar);
|
||||
VectorBase<T, N>& operator*=(const U& scalar);
|
||||
template<class U>
|
||||
VectorBase<T, N> operator/=(const U& scalar);
|
||||
VectorBase<T, N>& operator/=(const U& scalar);
|
||||
|
||||
// Checks whether all values are the same.
|
||||
template<class U>
|
||||
@@ -238,7 +238,7 @@ void VectorBase<T, N>::assign(const VectorBase<U, N>& other)
|
||||
|
||||
template<class T, unsigned int N>
|
||||
template<class U>
|
||||
VectorBase<T, N> VectorBase<T, N>::add(const VectorBase<U, N>& other)
|
||||
VectorBase<T, N>& VectorBase<T, N>::add(const VectorBase<U, N>& other)
|
||||
{
|
||||
T tmpValues[N];
|
||||
for (unsigned int i = 0; i < N; i++)
|
||||
@@ -253,7 +253,7 @@ VectorBase<T, N> VectorBase<T, N>::add(const VectorBase<U, N>& other)
|
||||
|
||||
template<class T, unsigned int N>
|
||||
template<class U>
|
||||
VectorBase<T, N> VectorBase<T, N>::subtract(const VectorBase<U, N>& other)
|
||||
VectorBase<T, N>& VectorBase<T, N>::subtract(const VectorBase<U, N>& other)
|
||||
{
|
||||
T tmpValues[N];
|
||||
for (unsigned int i = 0; i < N; i++)
|
||||
@@ -268,7 +268,7 @@ VectorBase<T, N> VectorBase<T, N>::subtract(const VectorBase<U, N>& other)
|
||||
|
||||
template<class T, unsigned int N>
|
||||
template<class U>
|
||||
VectorBase<T, N> VectorBase<T, N>::scalarMultiplication(const U& scalar)
|
||||
VectorBase<T, N>& VectorBase<T, N>::scalarMultiplication(const U& scalar)
|
||||
{
|
||||
T tmpValues[N];
|
||||
for (unsigned int i = 0; i < N; i++)
|
||||
@@ -371,28 +371,28 @@ VectorBase<T, N> VectorBase<T, N>::operator/(const U& scalar) const
|
||||
|
||||
template<class T, unsigned int N>
|
||||
template<class U>
|
||||
VectorBase<T, N> VectorBase<T, N>::operator+=(const VectorBase<U, N>& other)
|
||||
VectorBase<T, N>& VectorBase<T, N>::operator+=(const VectorBase<U, N>& other)
|
||||
{
|
||||
return add(other);
|
||||
}
|
||||
|
||||
template<class T, unsigned int N>
|
||||
template<class U>
|
||||
VectorBase<T, N> VectorBase<T, N>::operator-=(const VectorBase<U, N>& other)
|
||||
VectorBase<T, N>& VectorBase<T, N>::operator-=(const VectorBase<U, N>& other)
|
||||
{
|
||||
return subtract(other);
|
||||
}
|
||||
|
||||
template<class T, unsigned int N>
|
||||
template<class U>
|
||||
VectorBase<T, N> VectorBase<T, N>::operator*=(const U& scalar)
|
||||
VectorBase<T, N>& VectorBase<T, N>::operator*=(const U& scalar)
|
||||
{
|
||||
return scalarMultiplication(scalar);
|
||||
}
|
||||
|
||||
template<class T, unsigned int N>
|
||||
template<class U>
|
||||
VectorBase<T, N> VectorBase<T, N>::operator/=(const U& scalar)
|
||||
VectorBase<T, N>& VectorBase<T, N>::operator/=(const U& scalar)
|
||||
{
|
||||
return scalarMultiplication(1.0f / scalar);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user