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:
@@ -11,18 +11,35 @@ class Edge;
|
||||
// temporary data structure for (visual) graph creation process
|
||||
struct DummyEdge
|
||||
{
|
||||
DummyEdge()
|
||||
: ownerId(0)
|
||||
, targetId(0)
|
||||
, data(nullptr)
|
||||
, visible(false)
|
||||
, active(false)
|
||||
, weight(0)
|
||||
, direction(TokenComponentAggregation::DIRECTION_INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
DummyEdge(const Id ownerId, const Id targetId, const Edge* data)
|
||||
: ownerId(ownerId)
|
||||
, targetId(targetId)
|
||||
, data(data)
|
||||
, visible(false)
|
||||
, active(false)
|
||||
, weight(0)
|
||||
, direction(TokenComponentAggregation::DIRECTION_INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
int getWeight() const
|
||||
{
|
||||
if (data->isType(Edge::EDGE_AGGREGATION))
|
||||
if (!data)
|
||||
{
|
||||
return weight;
|
||||
}
|
||||
else if (data->isType(Edge::EDGE_AGGREGATION))
|
||||
{
|
||||
return data->getComponent<TokenComponentAggregation>()->getAggregationCount();
|
||||
}
|
||||
@@ -30,6 +47,37 @@ struct DummyEdge
|
||||
return 1;
|
||||
}
|
||||
|
||||
void updateDirection(TokenComponentAggregation::Direction dir, bool invert)
|
||||
{
|
||||
if (invert)
|
||||
{
|
||||
dir = TokenComponentAggregation::opposite(dir);
|
||||
}
|
||||
|
||||
if (direction == TokenComponentAggregation::DIRECTION_INVALID)
|
||||
{
|
||||
direction = dir;
|
||||
}
|
||||
else if (direction != dir)
|
||||
{
|
||||
direction = TokenComponentAggregation::DIRECTION_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
TokenComponentAggregation::Direction getDirection() const
|
||||
{
|
||||
if (!data)
|
||||
{
|
||||
return direction;
|
||||
}
|
||||
else if (data->isType(Edge::EDGE_AGGREGATION))
|
||||
{
|
||||
return data->getComponent<TokenComponentAggregation>()->getDirection();
|
||||
}
|
||||
|
||||
return TokenComponentAggregation::DIRECTION_FORWARD;
|
||||
}
|
||||
|
||||
Id ownerId;
|
||||
Id targetId;
|
||||
|
||||
@@ -37,6 +85,10 @@ struct DummyEdge
|
||||
|
||||
bool visible;
|
||||
bool active;
|
||||
|
||||
// BundleEdge
|
||||
int weight;
|
||||
TokenComponentAggregation::Direction direction;
|
||||
};
|
||||
|
||||
#endif // DUMMY_EDGE_H
|
||||
|
||||
@@ -40,7 +40,12 @@ public:
|
||||
|
||||
bool isExpandToggleNode() const
|
||||
{
|
||||
return !data && !isAccessNode();
|
||||
return !isGraphNode() && !isAccessNode() && !isBundleNode();
|
||||
}
|
||||
|
||||
bool isBundleNode() const
|
||||
{
|
||||
return bundledNodes.size() > 0;
|
||||
}
|
||||
|
||||
bool isExpanded() const
|
||||
@@ -48,6 +53,55 @@ public:
|
||||
return expanded || autoExpanded;
|
||||
}
|
||||
|
||||
bool hasVisibleSubNode() const
|
||||
{
|
||||
for (const DummyNode& node : subNodes)
|
||||
{
|
||||
if (node.visible)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasActiveSubNode() const
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const DummyNode& node : subNodes)
|
||||
{
|
||||
if (node.hasActiveSubNode())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasConnectedSubNode() const
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const DummyNode& node : subNodes)
|
||||
{
|
||||
if (node.hasConnectedSubNode())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Vec2i position;
|
||||
Vec2i size;
|
||||
|
||||
@@ -72,6 +126,10 @@ public:
|
||||
|
||||
// ExpandToggleNode
|
||||
size_t invisibleSubNodeCount;
|
||||
|
||||
// BundleNode
|
||||
std::vector<DummyNode> bundledNodes;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
#endif // DUMMY_NODE_H
|
||||
|
||||
Reference in New Issue
Block a user