ui: Improvements and fixes in graph layouting

* put nodes with bidirectional aggregations on the left
* layout aggregations either horizontal or vertical based on buckets
* exceed bucket height if only one element and vertical split
* fixed hiding nodes in sublayout showed empty spot
This commit is contained in:
Eberhard Graether
2018-04-19 18:54:34 +02:00
parent 1ee4f829a4
commit 5edaedfd37
7 changed files with 67 additions and 64 deletions
@@ -1493,7 +1493,6 @@ void GraphController::groupNodesByParents(GroupType groupType)
m_dummyNodes.push_back(groupNode);
}
std::vector<DummyNode::BundleInfo> bundleInfos;
for (std::shared_ptr<DummyNode> dummyNode : p.second)
{
if (dummyNode->hasActiveSubNode())
@@ -1501,10 +1500,6 @@ void GraphController::groupNodesByParents(GroupType groupType)
groupNode->bundleInfo = dummyNode->bundleInfo;
groupNode->bundleId = dummyNode->bundleId;
}
else
{
bundleInfos.push_back(dummyNode->bundleInfo);
}
groupNode->subNodes.push_back(dummyNode);
m_topLevelAncestorIds[dummyNode->tokenId] = groupNode->tokenId;
@@ -1514,9 +1509,9 @@ void GraphController::groupNodesByParents(GroupType groupType)
if (!groupNode->bundleId)
{
groupNode->bundleId = groupNode->subNodes[0]->bundleId;
groupNode->bundleInfo = DummyNode::BundleInfo::averageBundleInfo(bundleInfos);
}
groupNode->bundleInfo = DummyNode::BundleInfo::averageBundleInfo(groupNode->getBundleInfos());
groupNode->sortSubNodesByName();
}
@@ -71,18 +71,29 @@ void Bucket::preLayout(Vec2i viewSize, bool addVerticalSplit, bool forceVertical
std::vector<std::vector<DummyNode*>> nodesInCol;
nodesInCol.push_back({ });
int heightDiff = 0;
for (const std::shared_ptr<DummyNode>& node : m_nodes)
{
if (y > height)
if (y > height + heightDiff)
{
colHeights.push_back(y - GraphViewStyle::s_gridCellPadding);
colWidths.push_back(width);
// keep adding to the same columns if it only contains 1 element, which will end up above the middle split
if (nodesInCol.back().size() == 1 && m_nodes.size() > 1 && addVerticalSplit | forceVerticalSplit)
{
heightDiff = y;
}
else
{
colHeights.push_back(y - GraphViewStyle::s_gridCellPadding);
colWidths.push_back(width);
y = 0;
x += GraphViewStyle::toGridOffset(width + 45);
width = 0;
y = 0;
x += GraphViewStyle::toGridOffset(width + 45);
width = 0;
nodesInCol.push_back({ });
nodesInCol.push_back({ });
heightDiff = 0;
}
}
node->position.x = x;
@@ -92,8 +103,8 @@ void Bucket::preLayout(Vec2i viewSize, bool addVerticalSplit, bool forceVertical
y += GraphViewStyle::toGridSize(node->size.y) + GraphViewStyle::s_gridCellPadding;
width = (node->size.x > width ? node->size.x : width);
m_height = (y > m_height ? y : m_height);
width = std::max(width, node->size.x());
m_height = std::max(m_height, y);
}
colHeights.push_back(y - GraphViewStyle::s_gridCellPadding);
@@ -242,28 +253,16 @@ void BucketLayouter::createBuckets(
addNode(nodes[0]);
}
std::vector<const DummyEdge*> remainingEdges;
for (const std::shared_ptr<DummyEdge>& edge : edges)
for (std::shared_ptr<DummyEdge> edge : edges)
{
remainingEdges.push_back(edge.get());
}
size_t i = 0;
while (remainingEdges.size())
{
const DummyEdge* edge = remainingEdges[i];
std::shared_ptr<DummyNode> owner = findTopMostDummyNodeRecursive(nodes, edge->ownerId, nullptr);
std::shared_ptr<DummyNode> target = findTopMostDummyNodeRecursive(nodes, edge->targetId, nullptr);
bool removeEdge = false;
if (!owner || !target || owner == target)
bool horizontal = true;
if (owner && target && owner != target && owner->getsLayouted() && target->getsLayouted())
{
removeEdge = true;
}
else
{
bool horizontal = !owner->bundleInfo.layoutVertical && !target->bundleInfo.layoutVertical;
horizontal = !owner->bundleInfo.layoutVertical && !target->bundleInfo.layoutVertical;
if (!horizontal)
{
@@ -273,27 +272,18 @@ void BucketLayouter::createBuckets(
std::swap(owner, target);
}
}
else if (edge->getDirection() == TokenComponentAggregation::DIRECTION_BACKWARD)
else if (edge->getDirection() == TokenComponentAggregation::DIRECTION_BACKWARD ||
// put nodes with bidirectional edges on the left
(edge->getDirection() == TokenComponentAggregation::DIRECTION_NONE &&
!target->bundleInfo.isReferencing && !target->bundleInfo.isReferenced))
{
std::swap(owner, target);
}
removeEdge = addNode(owner, target, horizontal);
horizontal = addNode(owner, target, horizontal);
}
if (removeEdge)
{
remainingEdges.erase(remainingEdges.begin() + i);
}
else
{
i++;
}
if (i == remainingEdges.size())
{
i = 0;
}
edge->layoutHorizontal = horizontal;
}
}
@@ -416,7 +406,7 @@ bool BucketLayouter::addNode(std::shared_ptr<DummyNode> owner, std::shared_ptr<D
}
else if (ownerBucket && targetBucket)
{
return true;
return ownerBucket->j == targetBucket->j;
}
if (ownerBucket)
@@ -436,7 +426,7 @@ bool BucketLayouter::addNode(std::shared_ptr<DummyNode> owner, std::shared_ptr<D
bucket->addNode(owner);
}
return true;
return horizontal;
}
Bucket* BucketLayouter::getBucket(int i, int j)
@@ -19,6 +19,7 @@ struct DummyEdge
, visible(false)
, hidden(false)
, active(false)
, layoutHorizontal(true)
, weight(0)
, direction(TokenComponentAggregation::DIRECTION_INVALID)
{
@@ -31,6 +32,7 @@ struct DummyEdge
, visible(false)
, hidden(false)
, active(false)
, layoutHorizontal(true)
, weight(0)
, direction(TokenComponentAggregation::DIRECTION_INVALID)
{
@@ -92,6 +94,8 @@ struct DummyEdge
std::vector<Vec4i> path;
bool layoutHorizontal;
// BundleEdge
int weight;
TokenComponentAggregation::Direction direction;
@@ -74,11 +74,11 @@ public:
}
BundleInfo info;
if (activeCount > bundleInfos.size() / 2) info.isActive = true;
if (definedCount > bundleInfos.size() / 2) info.isDefined = true;
if (verticalLayoutCount > bundleInfos.size() / 2) info.layoutVertical = true;
if (referencedCount > bundleInfos.size() / 2) info.isReferenced = true;
if (referencingCount > bundleInfos.size() / 2) info.isReferencing = true;
if (activeCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isActive = true;
if (definedCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isDefined = true;
if (verticalLayoutCount >= std::ceil(bundleInfos.size() / 2.0f)) info.layoutVertical = true;
if (referencedCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isReferenced = true;
if (referencingCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isReferencing = true;
return info;
}
@@ -431,6 +431,16 @@ public:
return nullptr;
}
std::vector<BundleInfo> getBundleInfos() const
{
std::vector<BundleInfo> bundleInfos;
for (const std::shared_ptr<DummyNode>& subNode : subNodes)
{
bundleInfos.push_back(subNode->bundleInfo);
}
return bundleInfos;
}
Type type;
Vec2i position;