ui: Show call graphs, inheritance trees and include trees for active symbol (issue 249 337)

* Added TrailLayouter with Sugiyama dependency layouting
* Layouter supports horizontal and vertical layouts
* Added basic ui to graph view for showing incoming and outgoing paths
* Added depth slider, with infinity at maximum
* Disable trail ui when not available
* Added trail messages to undo stack and only use last one when undoing
* Added QtGraphLineBezier for trail graphs and refactored other line types
* Disabled edge activation for trail layouts, shown only visually
* Highlight all connected edges when hovering a node in trail layout
* Use different color when highlighting call edges for better contrast
* Fixed BucketLayouter issue when edge does not leave node
* Increased click area for angled edges

bug id = 249 337

fortune cookie message = Answer just what the heart prompts to you.
This commit is contained in:
Eberhard Graether
2017-04-24 01:14:53 +02:00
parent 01bd0efefb
commit f0b7dcdcdd
40 changed files with 1892 additions and 487 deletions
@@ -9,6 +9,7 @@
#include "component/controller/helper/BucketLayouter.h"
#include "component/controller/helper/ListLayouter.h"
#include "component/controller/helper/TrailLayouter.h"
#include "component/view/GraphView.h"
#include "component/view/GraphViewStyle.h"
#include "data/access/StorageAccess.h"
@@ -42,7 +43,7 @@ void GraphController::handleMessage(MessageActivateAll* message)
assignBundleIds();
layoutGraph();
buildGraph(message, false);
buildGraph(message, false, true, false);
}
void GraphController::handleMessage(MessageActivateTokens* message)
@@ -53,7 +54,7 @@ void GraphController::handleMessage(MessageActivateTokens* message)
{
m_activeEdgeIds = message->tokenIds;
setActiveAndVisibility(utility::concat(m_activeNodeIds, m_activeEdgeIds));
buildGraph(message, false, false);
buildGraph(message, false, false, false);
return;
}
else if (message->isAggregation)
@@ -101,9 +102,55 @@ void GraphController::handleMessage(MessageActivateTokens* message)
buildGraph(message, !isNamespace, true, isNamespace);
}
void GraphController::handleMessage(MessageActivateTrail* message)
{
TRACE("trail activate");
m_activeEdgeIds.clear();
std::shared_ptr<Graph> graph = m_storageAccess->getGraphForTrail(
message->originId, message->targetId, message->trailType, message->depth);
createDummyGraphForTokenIds(m_activeNodeIds, graph);
m_graph->setTrailMode(message->horizontalLayout ? Graph::TRAIL_HORIZONTAL : Graph::TRAIL_VERTICAL);
setVisibility(setActive(m_activeNodeIds, true));
layoutNesting();
TrailLayouter::LayoutDirection direction;
if (message->horizontalLayout)
{
if (message->originId)
{
direction = TrailLayouter::LAYOUT_LEFT_RIGHT;
}
else
{
direction = TrailLayouter::LAYOUT_RIGHT_LEFT;
}
}
else
{
if (message->originId)
{
direction = TrailLayouter::LAYOUT_TOP_BOTTOM;
}
else
{
direction = TrailLayouter::LAYOUT_BOTTOM_TOP;
}
}
TrailLayouter layout(direction);
layout.layoutGraph(m_dummyNodes, m_dummyEdges, m_topLevelAncestorIds);
buildGraph(message, true, true, false);
}
void GraphController::handleMessage(MessageFlushUpdates* message)
{
buildGraph(message, true, !message->keepContent());
buildGraph(message, true, !message->keepContent(), false);
}
void GraphController::handleMessage(MessageScrollGraph* message)
@@ -228,7 +275,7 @@ void GraphController::handleMessage(MessageGraphNodeExpand* message)
layoutNesting();
layoutGraph();
buildGraph(message, false);
buildGraph(message, false, true, false);
}
}
@@ -241,7 +288,7 @@ void GraphController::handleMessage(MessageGraphNodeMove* message)
if (message->isReplayed())
{
buildGraph(message, false);
buildGraph(message, false, true, false);
}
else
{
@@ -264,7 +311,7 @@ void GraphController::handleMessage(MessageShowReference* message)
m_activeEdgeIds = std::vector<Id>(1, message->tokenId);
setActiveAndVisibility(utility::concat(m_activeNodeIds, m_activeEdgeIds));
buildGraph(message, false, false);
buildGraph(message, false, false, false);
}
GraphView* GraphController::getView() const
@@ -300,6 +347,7 @@ void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenId
m_dummyEdges.clear();
m_dummyGraphNodes.clear();
m_topLevelAncestorIds.clear();
std::set<Id> addedNodes;
std::vector<std::shared_ptr<DummyNode>> dummyNodes;
@@ -308,14 +356,14 @@ void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenId
[&addedNodes, &dummyNodes, this](Node* node)
{
Node* parent = node->getLastParentNode();
Id id = parent->getId();
if (addedNodes.find(id) != addedNodes.end())
Id parentId = parent->getId();
if (addedNodes.find(parentId) != addedNodes.end())
{
return;
}
addedNodes.insert(id);
addedNodes.insert(parentId);
utility::append(dummyNodes, createDummyNodeTopDown(parent));
utility::append(dummyNodes, createDummyNodeTopDown(parent, parentId));
}
);
@@ -370,7 +418,7 @@ void GraphController::createDummyGraphForTokenIdsAndSetActiveAndVisibility(
createDummyGraphForTokenIds(tokenIds, graph);
bool noActive = setActive(tokenIds);
bool noActive = setActive(tokenIds, false);
autoExpandActiveNode(tokenIds);
setExpandedNodeIds(expandedNodeIds);
@@ -378,24 +426,26 @@ void GraphController::createDummyGraphForTokenIdsAndSetActiveAndVisibility(
setVisibility(noActive);
}
std::vector<std::shared_ptr<DummyNode>> GraphController::createDummyNodeTopDown(Node* node)
std::vector<std::shared_ptr<DummyNode>> GraphController::createDummyNodeTopDown(Node* node, Id ancestorId)
{
std::vector<std::shared_ptr<DummyNode>> nodes;
std::shared_ptr<DummyNode> result = std::make_shared<DummyNode>();
result->data = node;
result->tokenId = node->getId();
result->name = node->getName();
result->tokenId = node->getId();
m_topLevelAncestorIds.emplace(node->getId(), ancestorId);
m_dummyGraphNodes.emplace(result->data->getId(), result);
nodes.push_back(result);
if (node->isType(Node::NODE_NAMESPACE))
{
node->forEachChildNode(
[&nodes, this](Node* child)
[&nodes, &ancestorId, this](Node* child)
{
utility::append(nodes, createDummyNodeTopDown(child));
utility::append(nodes, createDummyNodeTopDown(child, ancestorId));
}
);
@@ -403,7 +453,7 @@ std::vector<std::shared_ptr<DummyNode>> GraphController::createDummyNodeTopDown(
}
node->forEachChildNode(
[node, &result, this](Node* child)
[node, &result, &ancestorId, this](Node* child)
{
DummyNode* parent = nullptr;
AccessKind accessKind = ACCESS_NONE;
@@ -432,7 +482,7 @@ std::vector<std::shared_ptr<DummyNode>> GraphController::createDummyNodeTopDown(
parent = accessNode.get();
}
utility::append(parent->subNodes, createDummyNodeTopDown(child));
utility::append(parent->subNodes, createDummyNodeTopDown(child, ancestorId));
}
);
@@ -482,7 +532,7 @@ void GraphController::autoExpandActiveNode(const std::vector<Id>& activeTokenIds
}
}
bool GraphController::setActive(const std::vector<Id>& activeTokenIds)
bool GraphController::setActive(const std::vector<Id>& activeTokenIds, bool showAllEdges)
{
TRACE();
@@ -513,7 +563,7 @@ bool GraphController::setActive(const std::vector<Id>& activeTokenIds)
DummyNode* from = getDummyGraphNodeById(edge->ownerId);
DummyNode* to = getDummyGraphNodeById(edge->targetId);
if (from && to && (noActive || from->active || to->active || edge->active))
if (from && to && (showAllEdges || noActive || from->active || to->active || edge->active))
{
edge->visible = true;
from->connected = true;
@@ -540,7 +590,7 @@ void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenI
{
TRACE();
setVisibility(setActive(activeTokenIds));
setVisibility(setActive(activeTokenIds, false));
}
void GraphController::setNodeActiveRecursive(DummyNode* node, const std::vector<Id>& activeTokenIds, bool* noActive) const
@@ -1468,7 +1518,8 @@ DummyNode* GraphController::getDummyGraphNodeById(Id tokenId) const
return nullptr;
}
void GraphController::buildGraph(MessageBase* message, bool centerActiveNode, bool animatedTransition, bool scrollToTop)
void GraphController::buildGraph(
MessageBase* message, bool centerActiveNode, bool animatedTransition, bool scrollToTop)
{
if (!message->isReplayed())
{
@@ -1742,7 +1793,7 @@ void GraphController::handleMessage(MessageColorSchemeTest* message)
}
);
setActive(activeTokenIds);
setActive(activeTokenIds, true);
layoutNesting();
@@ -1758,7 +1809,7 @@ void GraphController::handleMessage(MessageColorSchemeTest* message)
grid.createBuckets(m_dummyNodes, std::vector<std::shared_ptr<DummyEdge>>());
grid.layoutBuckets();
buildGraph(message, false);
buildGraph(message, false, true, false);
getView()->focusTokenIds(focusedTokenIds);
}