ui: redesigned graph overview and use new list layouting within overview bundles
* overview bundles imitate style of bundled node type * removed bundle for built-in types * show contents of overview bundle in vertical list layouted with new ListLayouter * nodes starting with the same letter are grouped with the letter displayed above * pressing the letter key will scroll to the group * also use this list layouting for namespace & package contents * renamed BucketGrid to BucketLayouter * moved used functions of GraphPostProcessor to GraphViewStyle and removed GraphPostProcessor fortune cookie message = Don't be afraid to take that big step
This commit is contained in:
@@ -378,6 +378,14 @@
|
|||||||
<normal>#FFFFFF</normal>
|
<normal>#FFFFFF</normal>
|
||||||
</text>
|
</text>
|
||||||
</qualifier>
|
</qualifier>
|
||||||
|
<text>
|
||||||
|
<fill>
|
||||||
|
<normal>transparent</normal>
|
||||||
|
</fill>
|
||||||
|
<text>
|
||||||
|
<normal>white</normal>
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
</node>
|
</node>
|
||||||
<edge>
|
<edge>
|
||||||
<default>
|
<default>
|
||||||
|
|||||||
@@ -349,6 +349,14 @@
|
|||||||
<normal>black</normal>
|
<normal>black</normal>
|
||||||
</text>
|
</text>
|
||||||
</qualifier>
|
</qualifier>
|
||||||
|
<text>
|
||||||
|
<fill>
|
||||||
|
<normal>transparent</normal>
|
||||||
|
</fill>
|
||||||
|
<text>
|
||||||
|
<normal>black</normal>
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
</node>
|
</node>
|
||||||
<edge>
|
<edge>
|
||||||
<default>
|
<default>
|
||||||
|
|||||||
@@ -352,6 +352,14 @@
|
|||||||
<normal>#F7F7F7</normal>
|
<normal>#F7F7F7</normal>
|
||||||
</text>
|
</text>
|
||||||
</qualifier>
|
</qualifier>
|
||||||
|
<text>
|
||||||
|
<fill>
|
||||||
|
<normal>transparent</normal>
|
||||||
|
</fill>
|
||||||
|
<text>
|
||||||
|
<normal>white</normal>
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
</node>
|
</node>
|
||||||
<edge>
|
<edge>
|
||||||
<default>
|
<default>
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
add_files(
|
add_files(
|
||||||
LIB_FILES
|
LIB_FILES
|
||||||
|
|
||||||
component/controller/helper/BucketGrid.cpp
|
component/controller/helper/BucketLayouter.cpp
|
||||||
component/controller/helper/BucketGrid.h
|
component/controller/helper/BucketLayouter.h
|
||||||
component/controller/helper/DummyEdge.h
|
component/controller/helper/DummyEdge.h
|
||||||
component/controller/helper/DummyNode.h
|
component/controller/helper/DummyNode.h
|
||||||
component/controller/helper/GraphPostprocessor.cpp
|
component/controller/helper/ListLayouter.cpp
|
||||||
component/controller/helper/GraphPostprocessor.h
|
component/controller/helper/ListLayouter.h
|
||||||
component/controller/helper/NetworkProtocolHelper.cpp
|
component/controller/helper/NetworkProtocolHelper.cpp
|
||||||
component/controller/helper/NetworkProtocolHelper.h
|
component/controller/helper/NetworkProtocolHelper.h
|
||||||
component/controller/helper/SnippetMerger.cpp
|
component/controller/helper/SnippetMerger.cpp
|
||||||
@@ -362,7 +362,7 @@ add_files(
|
|||||||
|
|
||||||
utility/text/TextAccess.cpp
|
utility/text/TextAccess.cpp
|
||||||
utility/text/TextAccess.h
|
utility/text/TextAccess.h
|
||||||
|
|
||||||
utility/ApplicationArchitectureType.h
|
utility/ApplicationArchitectureType.h
|
||||||
utility/AppPath.cpp
|
utility/AppPath.cpp
|
||||||
utility/AppPath.h
|
utility/AppPath.h
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
#include "utility/utility.h"
|
#include "utility/utility.h"
|
||||||
#include "utility/utilityString.h"
|
#include "utility/utilityString.h"
|
||||||
|
|
||||||
#include "component/controller/helper/BucketGrid.h"
|
#include "component/controller/helper/BucketLayouter.h"
|
||||||
|
#include "component/controller/helper/ListLayouter.h"
|
||||||
#include "component/view/GraphView.h"
|
#include "component/view/GraphView.h"
|
||||||
#include "component/view/GraphViewStyle.h"
|
#include "component/view/GraphViewStyle.h"
|
||||||
#include "data/access/StorageAccess.h"
|
#include "data/access/StorageAccess.h"
|
||||||
@@ -72,20 +73,30 @@ void GraphController::handleMessage(MessageActivateTokens* message)
|
|||||||
|
|
||||||
std::vector<Id> tokenIds = utility::concat(m_activeNodeIds, m_activeEdgeIds);
|
std::vector<Id> tokenIds = utility::concat(m_activeNodeIds, m_activeEdgeIds);
|
||||||
|
|
||||||
std::shared_ptr<Graph> graph = m_storageAccess->getGraphForActiveTokenIds(tokenIds);
|
bool isNamespace = false;
|
||||||
|
std::shared_ptr<Graph> graph = m_storageAccess->getGraphForActiveTokenIds(tokenIds, &isNamespace);
|
||||||
|
|
||||||
createDummyGraphForTokenIdsAndSetActiveAndVisibility(tokenIds, graph);
|
createDummyGraphForTokenIdsAndSetActiveAndVisibility(tokenIds, graph);
|
||||||
|
|
||||||
if (m_activeNodeIds.size() == 1)
|
if (isNamespace)
|
||||||
{
|
{
|
||||||
bundleNodes();
|
addCharacterIndex();
|
||||||
|
layoutNesting();
|
||||||
|
layoutList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_activeNodeIds.size() == 1)
|
||||||
|
{
|
||||||
|
bundleNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutNesting();
|
||||||
|
layoutGraph(true);
|
||||||
|
assignBundleIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutNesting();
|
buildGraph(message, !isNamespace, true, isNamespace);
|
||||||
layoutGraph(true);
|
|
||||||
assignBundleIds();
|
|
||||||
|
|
||||||
buildGraph(message, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphController::handleMessage(MessageFlushUpdates* message)
|
void GraphController::handleMessage(MessageFlushUpdates* message)
|
||||||
@@ -115,8 +126,16 @@ void GraphController::handleMessage(MessageGraphNodeBundleSplit* message)
|
|||||||
DummyNode* node = m_dummyNodes[i].get();
|
DummyNode* node = m_dummyNodes[i].get();
|
||||||
if (node->isBundleNode() && node->tokenId == message->bundleId)
|
if (node->isBundleNode() && node->tokenId == message->bundleId)
|
||||||
{
|
{
|
||||||
m_dummyNodes.insert(m_dummyNodes.begin() + i + 1, node->bundledNodes.begin(), node->bundledNodes.end());
|
if (message->removeOtherNodes)
|
||||||
m_dummyNodes.erase(m_dummyNodes.begin() + i);
|
{
|
||||||
|
std::vector<std::shared_ptr<DummyNode>> nodes(node->bundledNodes.begin(), node->bundledNodes.end());
|
||||||
|
m_dummyNodes = nodes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_dummyNodes.insert(m_dummyNodes.begin() + i + 1, node->bundledNodes.begin(), node->bundledNodes.end());
|
||||||
|
m_dummyNodes.erase(m_dummyNodes.begin() + i);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,10 +153,19 @@ void GraphController::handleMessage(MessageGraphNodeBundleSplit* message)
|
|||||||
std::vector<Id> tokenIds = utility::concat(m_activeNodeIds, m_activeEdgeIds);
|
std::vector<Id> tokenIds = utility::concat(m_activeNodeIds, m_activeEdgeIds);
|
||||||
setActiveAndVisibility(tokenIds);
|
setActiveAndVisibility(tokenIds);
|
||||||
|
|
||||||
layoutNesting();
|
if (message->layoutToList)
|
||||||
layoutGraph();
|
{
|
||||||
|
addCharacterIndex();
|
||||||
|
layoutNesting();
|
||||||
|
layoutList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
layoutNesting();
|
||||||
|
layoutGraph();
|
||||||
|
}
|
||||||
|
|
||||||
buildGraph(message, false);
|
buildGraph(message, false, true, message->layoutToList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphController::handleMessage(MessageGraphNodeExpand* message)
|
void GraphController::handleMessage(MessageGraphNodeExpand* message)
|
||||||
@@ -942,6 +970,7 @@ void GraphController::bundleByType(
|
|||||||
|
|
||||||
if (bundleNode)
|
if (bundleNode)
|
||||||
{
|
{
|
||||||
|
bundleNode->bundledNodeType = type;
|
||||||
m_dummyNodes.push_back(bundleNode);
|
m_dummyNodes.push_back(bundleNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -959,9 +988,13 @@ void GraphController::bundleNodesByType()
|
|||||||
nodes.push_back(oldNodes[i]);
|
nodes.push_back(oldNodes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bundleByType(nodes, Node::NODE_FILE, "Files");
|
||||||
|
bundleByType(nodes, Node::NODE_MACRO, "Macros");
|
||||||
|
|
||||||
bundleByType(nodes, Node::NODE_NAMESPACE, "Namespaces");
|
bundleByType(nodes, Node::NODE_NAMESPACE, "Namespaces");
|
||||||
bundleByType(nodes, Node::NODE_PACKAGE, "Packages");
|
bundleByType(nodes, Node::NODE_PACKAGE, "Packages");
|
||||||
bundleByType(nodes, Node::NODE_BUILTIN_TYPE, "Built-in Types");
|
|
||||||
|
// bundleByType(nodes, Node::NODE_BUILTIN_TYPE, "Built-in Types");
|
||||||
bundleByType(nodes, Node::NODE_CLASS, "Classes");
|
bundleByType(nodes, Node::NODE_CLASS, "Classes");
|
||||||
bundleByType(nodes, Node::NODE_INTERFACE, "Interfaces");
|
bundleByType(nodes, Node::NODE_INTERFACE, "Interfaces");
|
||||||
bundleByType(nodes, Node::NODE_STRUCT, "Structs");
|
bundleByType(nodes, Node::NODE_STRUCT, "Structs");
|
||||||
@@ -973,9 +1006,6 @@ void GraphController::bundleNodesByType()
|
|||||||
bundleByType(nodes, Node::NODE_TYPEDEF, "Typedefs");
|
bundleByType(nodes, Node::NODE_TYPEDEF, "Typedefs");
|
||||||
bundleByType(nodes, Node::NODE_ENUM, "Enums");
|
bundleByType(nodes, Node::NODE_ENUM, "Enums");
|
||||||
|
|
||||||
bundleByType(nodes, Node::NODE_FILE, "Files");
|
|
||||||
bundleByType(nodes, Node::NODE_MACRO, "Macros");
|
|
||||||
|
|
||||||
// // should never be visible
|
// // should never be visible
|
||||||
|
|
||||||
bundleByType(nodes, Node::NODE_METHOD, "Methods");
|
bundleByType(nodes, Node::NODE_METHOD, "Methods");
|
||||||
@@ -1022,6 +1052,7 @@ void GraphController::bundleNodesByType()
|
|||||||
|
|
||||||
if (anonymousBundle)
|
if (anonymousBundle)
|
||||||
{
|
{
|
||||||
|
anonymousBundle->bundledNodeType = Node::NODE_NAMESPACE;
|
||||||
bundleNode->bundledNodeCount = bundleNode->getBundledNodeCount() + anonymousBundle->getBundledNodeCount();
|
bundleNode->bundledNodeCount = bundleNode->getBundledNodeCount() + anonymousBundle->getBundledNodeCount();
|
||||||
bundleNode->bundledNodes.insert(anonymousBundle);
|
bundleNode->bundledNodes.insert(anonymousBundle);
|
||||||
}
|
}
|
||||||
@@ -1029,6 +1060,43 @@ void GraphController::bundleNodesByType()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphController::addCharacterIndex()
|
||||||
|
{
|
||||||
|
// Remove index characters from last time
|
||||||
|
DummyNode::BundledNodesSet newNodes;
|
||||||
|
for (const std::shared_ptr<DummyNode> node : m_dummyNodes)
|
||||||
|
{
|
||||||
|
if (!node->isTextNode())
|
||||||
|
{
|
||||||
|
newNodes.insert(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_dummyNodes.clear();
|
||||||
|
m_dummyNodes.insert(m_dummyNodes.end(), newNodes.begin(), newNodes.end());
|
||||||
|
|
||||||
|
// Add index characters
|
||||||
|
char character = 0;
|
||||||
|
for (size_t i = 0; i < m_dummyNodes.size(); i++)
|
||||||
|
{
|
||||||
|
if (!m_dummyNodes[i]->name.size())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toupper(m_dummyNodes[i]->name[0]) != character)
|
||||||
|
{
|
||||||
|
character = toupper(m_dummyNodes[i]->name[0]);
|
||||||
|
|
||||||
|
std::shared_ptr<DummyNode> textNode = std::make_shared<DummyNode>();
|
||||||
|
textNode->textNode = true;
|
||||||
|
textNode->name = character;
|
||||||
|
textNode->visible = true;
|
||||||
|
|
||||||
|
m_dummyNodes.insert(m_dummyNodes.begin() + i, textNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GraphController::layoutNesting()
|
void GraphController::layoutNesting()
|
||||||
{
|
{
|
||||||
TRACE();
|
TRACE();
|
||||||
@@ -1067,12 +1135,23 @@ void GraphController::layoutNestingRecursive(DummyNode* node) const
|
|||||||
}
|
}
|
||||||
else if (node->isBundleNode())
|
else if (node->isBundleNode())
|
||||||
{
|
{
|
||||||
margins = GraphViewStyle::getMarginsOfBundleNode();
|
if (node->bundledNodeType != Node::NODE_UNDEFINED)
|
||||||
|
{
|
||||||
|
margins = GraphViewStyle::getMarginsForNodeType(node->bundledNodeType, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
margins = GraphViewStyle::getMarginsOfBundleNode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (node->isQualifierNode())
|
else if (node->isQualifierNode())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (node->isTextNode())
|
||||||
|
{
|
||||||
|
margins = GraphViewStyle::getMarginsOfTextNode();
|
||||||
|
}
|
||||||
|
|
||||||
int y = 0;
|
int y = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
@@ -1277,7 +1356,7 @@ void GraphController::layoutGraph(bool getSortedNodes)
|
|||||||
{
|
{
|
||||||
TRACE();
|
TRACE();
|
||||||
|
|
||||||
BucketGrid grid(getView()->getViewSize());
|
BucketLayouter grid(getView()->getViewSize());
|
||||||
grid.createBuckets(m_dummyNodes, m_dummyEdges);
|
grid.createBuckets(m_dummyNodes, m_dummyEdges);
|
||||||
grid.layoutBuckets();
|
grid.layoutBuckets();
|
||||||
|
|
||||||
@@ -1287,6 +1366,14 @@ void GraphController::layoutGraph(bool getSortedNodes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphController::layoutList()
|
||||||
|
{
|
||||||
|
TRACE();
|
||||||
|
|
||||||
|
ListLayouter layouter(getView()->getViewSize());
|
||||||
|
layouter.layoutList(m_dummyNodes);
|
||||||
|
}
|
||||||
|
|
||||||
void GraphController::assignBundleIds()
|
void GraphController::assignBundleIds()
|
||||||
{
|
{
|
||||||
Id bundleId = 0;
|
Id bundleId = 0;
|
||||||
@@ -1307,13 +1394,15 @@ DummyNode* GraphController::getDummyGraphNodeById(Id tokenId) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphController::buildGraph(MessageBase* message, bool centerActiveNode, bool animatedTransition)
|
void GraphController::buildGraph(MessageBase* message, bool centerActiveNode, bool animatedTransition, bool scrollToTop)
|
||||||
{
|
{
|
||||||
if (!message->isReplayed())
|
if (!message->isReplayed())
|
||||||
{
|
{
|
||||||
GraphView::GraphParams params;
|
GraphView::GraphParams params;
|
||||||
params.centerActiveNode = centerActiveNode;
|
params.centerActiveNode = centerActiveNode;
|
||||||
params.animatedTransition = animatedTransition;
|
params.animatedTransition = animatedTransition;
|
||||||
|
params.scrollToTop = scrollToTop;
|
||||||
|
params.isIndexedList = scrollToTop;
|
||||||
|
|
||||||
getView()->rebuildGraph(m_graph, m_dummyNodes, m_dummyEdges, params);
|
getView()->rebuildGraph(m_graph, m_dummyNodes, m_dummyEdges, params);
|
||||||
}
|
}
|
||||||
@@ -1591,7 +1680,7 @@ void GraphController::handleMessage(MessageColorSchemeTest* message)
|
|||||||
node->layoutBucket.y = (i / 6) + 1;
|
node->layoutBucket.y = (i / 6) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BucketGrid grid(Vec2i(0, 0));
|
BucketLayouter grid(Vec2i(0, 0));
|
||||||
grid.createBuckets(m_dummyNodes, std::vector<std::shared_ptr<DummyEdge>>());
|
grid.createBuckets(m_dummyNodes, std::vector<std::shared_ptr<DummyEdge>>());
|
||||||
grid.layoutBuckets();
|
grid.layoutBuckets();
|
||||||
|
|
||||||
|
|||||||
@@ -83,22 +83,28 @@ private:
|
|||||||
void setNodeVisibilityRecursiveTopDown(DummyNode* node, bool parentExpanded) const;
|
void setNodeVisibilityRecursiveTopDown(DummyNode* node, bool parentExpanded) const;
|
||||||
|
|
||||||
void bundleNodes();
|
void bundleNodes();
|
||||||
void bundleNodesAndEdgesMatching(std::function<bool(const DummyNode::BundleInfo&, const Node*)> matcher, size_t count, const std::string& name);
|
void bundleNodesAndEdgesMatching(
|
||||||
std::shared_ptr<DummyNode> bundleNodesMatching(std::list<std::shared_ptr<DummyNode>>& nodes, std::function<bool(const DummyNode*)> matcher, const std::string& name);
|
std::function<bool(const DummyNode::BundleInfo&, const Node*)> matcher, size_t count, const std::string& name);
|
||||||
|
std::shared_ptr<DummyNode> bundleNodesMatching(
|
||||||
|
std::list<std::shared_ptr<DummyNode>>& nodes, std::function<bool(const DummyNode*)> matcher, const std::string& name);
|
||||||
void bundleByType(std::list<std::shared_ptr<DummyNode>>& nodes, Node::NodeType type, const std::string& name);
|
void bundleByType(std::list<std::shared_ptr<DummyNode>>& nodes, Node::NodeType type, const std::string& name);
|
||||||
void bundleNodesByType();
|
void bundleNodesByType();
|
||||||
|
|
||||||
|
void addCharacterIndex();
|
||||||
|
|
||||||
void layoutNesting();
|
void layoutNesting();
|
||||||
void layoutNestingRecursive(DummyNode* node) const;
|
void layoutNestingRecursive(DummyNode* node) const;
|
||||||
void addExpandToggleNode(DummyNode* node) const;
|
void addExpandToggleNode(DummyNode* node) const;
|
||||||
void layoutToGrid(DummyNode* node) const;
|
void layoutToGrid(DummyNode* node) const;
|
||||||
|
|
||||||
void layoutGraph(bool getSortedNodes = false);
|
void layoutGraph(bool getSortedNodes = false);
|
||||||
|
void layoutList();
|
||||||
|
|
||||||
void assignBundleIds();
|
void assignBundleIds();
|
||||||
|
|
||||||
DummyNode* getDummyGraphNodeById(Id tokenId) const;
|
DummyNode* getDummyGraphNodeById(Id tokenId) const;
|
||||||
|
|
||||||
void buildGraph(MessageBase* message, bool centerActiveNode, bool animatedTransition = true);
|
void buildGraph(MessageBase* message, bool centerActiveNode, bool animatedTransition = true, bool scrollToTop = false);
|
||||||
|
|
||||||
void forEachDummyNodeRecursive(std::function<void(DummyNode*)> func);
|
void forEachDummyNodeRecursive(std::function<void(DummyNode*)> func);
|
||||||
void forEachDummyEdge(std::function<void(DummyEdge*)> func);
|
void forEachDummyEdge(std::function<void(DummyEdge*)> func);
|
||||||
|
|||||||
+10
-10
@@ -1,4 +1,4 @@
|
|||||||
#include "component/controller/helper/BucketGrid.h"
|
#include "component/controller/helper/BucketLayouter.h"
|
||||||
|
|
||||||
#include "component/controller/helper/DummyEdge.h"
|
#include "component/controller/helper/DummyEdge.h"
|
||||||
#include "component/view/GraphViewStyle.h"
|
#include "component/view/GraphViewStyle.h"
|
||||||
@@ -101,7 +101,7 @@ void Bucket::layout(int x, int y, int width, int height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BucketGrid::BucketGrid(Vec2i viewSize)
|
BucketLayouter::BucketLayouter(Vec2i viewSize)
|
||||||
: m_viewSize(viewSize)
|
: m_viewSize(viewSize)
|
||||||
, m_i1(0)
|
, m_i1(0)
|
||||||
, m_j1(0)
|
, m_j1(0)
|
||||||
@@ -111,7 +111,7 @@ BucketGrid::BucketGrid(Vec2i viewSize)
|
|||||||
m_buckets[0][0] = Bucket(0, 0);
|
m_buckets[0][0] = Bucket(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BucketGrid::createBuckets(
|
void BucketLayouter::createBuckets(
|
||||||
std::vector<std::shared_ptr<DummyNode>>& nodes, const std::vector<std::shared_ptr<DummyEdge>>& edges
|
std::vector<std::shared_ptr<DummyNode>>& nodes, const std::vector<std::shared_ptr<DummyEdge>>& edges
|
||||||
){
|
){
|
||||||
if (!nodes.size())
|
if (!nodes.size())
|
||||||
@@ -194,7 +194,7 @@ void BucketGrid::createBuckets(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BucketGrid::layoutBuckets()
|
void BucketLayouter::layoutBuckets()
|
||||||
{
|
{
|
||||||
std::map<int, int> widths;
|
std::map<int, int> widths;
|
||||||
std::map<int, int> heights;
|
std::map<int, int> heights;
|
||||||
@@ -245,7 +245,7 @@ void BucketGrid::layoutBuckets()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<DummyNode>> BucketGrid::getSortedNodes()
|
std::vector<std::shared_ptr<DummyNode>> BucketLayouter::getSortedNodes()
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<DummyNode>> sortedNodes;
|
std::vector<std::shared_ptr<DummyNode>> sortedNodes;
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ std::vector<std::shared_ptr<DummyNode>> BucketGrid::getSortedNodes()
|
|||||||
return sortedNodes;
|
return sortedNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<DummyNode> BucketGrid::findTopMostDummyNodeRecursive(
|
std::shared_ptr<DummyNode> BucketLayouter::findTopMostDummyNodeRecursive(
|
||||||
std::vector<std::shared_ptr<DummyNode>>& nodes, Id tokenId, std::shared_ptr<DummyNode> top
|
std::vector<std::shared_ptr<DummyNode>>& nodes, Id tokenId, std::shared_ptr<DummyNode> top
|
||||||
){
|
){
|
||||||
for (std::shared_ptr<DummyNode> node : nodes)
|
for (std::shared_ptr<DummyNode> node : nodes)
|
||||||
@@ -283,13 +283,13 @@ std::shared_ptr<DummyNode> BucketGrid::findTopMostDummyNodeRecursive(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BucketGrid::addNode(std::shared_ptr<DummyNode> node)
|
void BucketLayouter::addNode(std::shared_ptr<DummyNode> node)
|
||||||
{
|
{
|
||||||
Bucket* bucket = getBucket(node->layoutBucket.x, node->layoutBucket.y);
|
Bucket* bucket = getBucket(node->layoutBucket.x, node->layoutBucket.y);
|
||||||
bucket->addNode(node);
|
bucket->addNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BucketGrid::addNode(std::shared_ptr<DummyNode> owner, std::shared_ptr<DummyNode> target, bool horizontal)
|
bool BucketLayouter::addNode(std::shared_ptr<DummyNode> owner, std::shared_ptr<DummyNode> target, bool horizontal)
|
||||||
{
|
{
|
||||||
Bucket* ownerBucket = getBucket(owner);
|
Bucket* ownerBucket = getBucket(owner);
|
||||||
Bucket* targetBucket = getBucket(target);
|
Bucket* targetBucket = getBucket(target);
|
||||||
@@ -324,7 +324,7 @@ bool BucketGrid::addNode(std::shared_ptr<DummyNode> owner, std::shared_ptr<Dummy
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bucket* BucketGrid::getBucket(int i, int j)
|
Bucket* BucketLayouter::getBucket(int i, int j)
|
||||||
{
|
{
|
||||||
bool newColumn = false;
|
bool newColumn = false;
|
||||||
bool newRow = false;
|
bool newRow = false;
|
||||||
@@ -375,7 +375,7 @@ Bucket* BucketGrid::getBucket(int i, int j)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bucket* BucketGrid::getBucket(std::shared_ptr<DummyNode> node)
|
Bucket* BucketLayouter::getBucket(std::shared_ptr<DummyNode> node)
|
||||||
{
|
{
|
||||||
for (int j = m_j1; j <= m_j2; j++)
|
for (int j = m_j1; j <= m_j2; j++)
|
||||||
{
|
{
|
||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
#ifndef BUCKET_GRID_H
|
#ifndef BUCKET_LAYOUTER_H
|
||||||
#define BUCKET_GRID_H
|
#define BUCKET_LAYOUTER_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -38,10 +38,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BucketGrid
|
class BucketLayouter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BucketGrid(Vec2i viewSize);
|
BucketLayouter(Vec2i viewSize);
|
||||||
void createBuckets(
|
void createBuckets(
|
||||||
std::vector<std::shared_ptr<DummyNode>>& nodes,
|
std::vector<std::shared_ptr<DummyNode>>& nodes,
|
||||||
const std::vector<std::shared_ptr<DummyEdge>>& edges);
|
const std::vector<std::shared_ptr<DummyEdge>>& edges);
|
||||||
@@ -68,4 +68,4 @@ private:
|
|||||||
int m_j2;
|
int m_j2;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BUCKET_GRID_H
|
#endif // BUCKET_LAYOUTER_H
|
||||||
@@ -6,11 +6,10 @@
|
|||||||
#include "utility/utility.h"
|
#include "utility/utility.h"
|
||||||
#include "utility/utilityString.h"
|
#include "utility/utilityString.h"
|
||||||
|
|
||||||
|
#include "data/graph/Node.h"
|
||||||
#include "data/graph/token_component/TokenComponentAccess.h"
|
#include "data/graph/token_component/TokenComponentAccess.h"
|
||||||
#include "data/name/NameHierarchy.h"
|
#include "data/name/NameHierarchy.h"
|
||||||
|
|
||||||
class Node;
|
|
||||||
|
|
||||||
// temporary data structure for (visual) graph creation process
|
// temporary data structure for (visual) graph creation process
|
||||||
struct DummyNode
|
struct DummyNode
|
||||||
{
|
{
|
||||||
@@ -68,6 +67,8 @@ public:
|
|||||||
, bundleId(0)
|
, bundleId(0)
|
||||||
, layoutBucket(0, 0)
|
, layoutBucket(0, 0)
|
||||||
, bundledNodeCount(0)
|
, bundledNodeCount(0)
|
||||||
|
, bundledNodeType(Node::NODE_UNDEFINED)
|
||||||
|
, textNode(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ public:
|
|||||||
|
|
||||||
bool isExpandToggleNode() const
|
bool isExpandToggleNode() const
|
||||||
{
|
{
|
||||||
return !isGraphNode() && !isAccessNode() && !isBundleNode() && !isQualifierNode();
|
return !isGraphNode() && !isAccessNode() && !isBundleNode() && !isQualifierNode() && !isTextNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBundleNode() const
|
bool isBundleNode() const
|
||||||
@@ -96,6 +97,11 @@ public:
|
|||||||
return qualifierName.size();
|
return qualifierName.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isTextNode() const
|
||||||
|
{
|
||||||
|
return textNode;
|
||||||
|
}
|
||||||
|
|
||||||
bool isExpanded() const
|
bool isExpanded() const
|
||||||
{
|
{
|
||||||
return expanded;
|
return expanded;
|
||||||
@@ -269,9 +275,13 @@ public:
|
|||||||
// BundleNode
|
// BundleNode
|
||||||
BundledNodesSet bundledNodes;
|
BundledNodesSet bundledNodes;
|
||||||
size_t bundledNodeCount;
|
size_t bundledNodeCount;
|
||||||
|
Node::NodeType bundledNodeType;
|
||||||
|
|
||||||
// QualifierNode
|
// QualifierNode
|
||||||
NameHierarchy qualifierName;
|
NameHierarchy qualifierName;
|
||||||
|
|
||||||
|
// TextNode
|
||||||
|
bool textNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DUMMY_NODE_H
|
#endif // DUMMY_NODE_H
|
||||||
|
|||||||
@@ -1,467 +0,0 @@
|
|||||||
#include "component/controller/helper/GraphPostprocessor.h"
|
|
||||||
|
|
||||||
#include "component/view/GraphViewStyle.h"
|
|
||||||
|
|
||||||
unsigned int GraphPostprocessor::s_cellWidth = GraphViewStyle::s_gridCellSize;
|
|
||||||
unsigned int GraphPostprocessor::s_cellHeight = GraphViewStyle::s_gridCellSize;
|
|
||||||
unsigned int GraphPostprocessor::s_cellPadding = GraphViewStyle::s_gridCellPadding;
|
|
||||||
|
|
||||||
void GraphPostprocessor::doPostprocessing(std::vector<DummyNode>& nodes)
|
|
||||||
{
|
|
||||||
unsigned int atomarGridWidth = s_cellWidth;
|
|
||||||
unsigned int atomarGridHeight = s_cellHeight;
|
|
||||||
|
|
||||||
if (nodes.size() < 2)
|
|
||||||
{
|
|
||||||
LOG_INFO_STREAM(<< "Skipping postprocessing, need at least 2 nodes but got " << nodes.size());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine center of mass (CoD) which is used to get outliers closer to the rest of the graph
|
|
||||||
int divisorWidth = 999999;
|
|
||||||
int divisorHeight = 999999;
|
|
||||||
int maxNodeWidth = 0;
|
|
||||||
int maxNodeHeight = 0;
|
|
||||||
Vec2i centerOfMass(0, 0);
|
|
||||||
float totalMass = 0.0f;
|
|
||||||
|
|
||||||
for (const DummyNode& node : nodes)
|
|
||||||
{
|
|
||||||
if (node.size.x < divisorWidth)
|
|
||||||
{
|
|
||||||
divisorWidth = node.size.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.size.y < divisorHeight)
|
|
||||||
{
|
|
||||||
divisorHeight = node.size.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.size.x > maxNodeWidth)
|
|
||||||
{
|
|
||||||
maxNodeWidth = node.size.x;
|
|
||||||
}
|
|
||||||
else if (node.size.y > maxNodeHeight)
|
|
||||||
{
|
|
||||||
maxNodeHeight = node.size.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
float nodeMass = node.size.x * node.size.y;
|
|
||||||
centerOfMass += node.position * nodeMass;
|
|
||||||
totalMass += nodeMass;
|
|
||||||
}
|
|
||||||
|
|
||||||
centerOfMass /= totalMass;
|
|
||||||
|
|
||||||
divisorWidth = (int)atomarGridWidth + s_cellPadding; //std::min(divisor, (int)atomarGridSize);
|
|
||||||
divisorHeight = (int)atomarGridHeight + s_cellPadding;
|
|
||||||
|
|
||||||
resolveOutliers(nodes, centerOfMass);
|
|
||||||
|
|
||||||
// the nodes will be aligned everytime they move during post-processing
|
|
||||||
// align all nodes once here so that nodes that won't be moved again are aligned
|
|
||||||
for (DummyNode& node : nodes)
|
|
||||||
{
|
|
||||||
alignNodeOnRaster(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
MatrixDynamicBase<unsigned int> heatMap = buildHeatMap(nodes, divisorWidth, divisorHeight, maxNodeWidth, maxNodeHeight);
|
|
||||||
|
|
||||||
resolveOverlap(nodes, heatMap, divisorWidth, divisorHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphPostprocessor::alignNodeOnRaster(DummyNode& node)
|
|
||||||
{
|
|
||||||
node.position = alignOnRaster(node.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2i GraphPostprocessor::alignOnRaster(Vec2i position)
|
|
||||||
{
|
|
||||||
int rasterPosDivisor = s_cellWidth + s_cellPadding;
|
|
||||||
|
|
||||||
if (position.x % rasterPosDivisor != 0)
|
|
||||||
{
|
|
||||||
int t = position.x / rasterPosDivisor;
|
|
||||||
int r = position.x % rasterPosDivisor;
|
|
||||||
|
|
||||||
if (std::abs(r) > rasterPosDivisor/2)
|
|
||||||
{
|
|
||||||
if (t != 0)
|
|
||||||
{
|
|
||||||
t += (t / std::abs(t));
|
|
||||||
}
|
|
||||||
else if (r != 0)
|
|
||||||
{
|
|
||||||
t += (r / std::abs(r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
position.x = t * rasterPosDivisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position.y % rasterPosDivisor != 0)
|
|
||||||
{
|
|
||||||
int t = position.y / rasterPosDivisor;
|
|
||||||
int r = position.y % rasterPosDivisor;
|
|
||||||
|
|
||||||
if (std::abs(r) > rasterPosDivisor/2)
|
|
||||||
{
|
|
||||||
if(t != 0)
|
|
||||||
{
|
|
||||||
t += (t / std::abs(t));
|
|
||||||
}
|
|
||||||
else if(r != 0)
|
|
||||||
{
|
|
||||||
t += (r / std::abs(r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
position.y = t * rasterPosDivisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphPostprocessor::resolveOutliers(std::vector<DummyNode>& nodes, const Vec2i& centerPoint)
|
|
||||||
{
|
|
||||||
float maxDist = 0.0f;
|
|
||||||
for (const DummyNode& node : nodes)
|
|
||||||
{
|
|
||||||
Vec2i toCenterOfMass = centerPoint - node.position;
|
|
||||||
if (toCenterOfMass.getLength() > maxDist)
|
|
||||||
{
|
|
||||||
maxDist = toCenterOfMass.getLength();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxDist == 0.0f)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (DummyNode& node : nodes)
|
|
||||||
{
|
|
||||||
Vec2i toCenterOfMass = centerPoint - node.position;
|
|
||||||
float dist = toCenterOfMass.getLength();
|
|
||||||
|
|
||||||
// causes far away nodes to be effected stronger than nodes that are already close to the center
|
|
||||||
float distFactor = std::sqrt(dist / maxDist);
|
|
||||||
node.position += toCenterOfMass * distFactor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MatrixDynamicBase<unsigned int> GraphPostprocessor::buildHeatMap(
|
|
||||||
const std::vector<DummyNode>& nodes, const int atomarNodeWidth, const int atomarNodeHeight, const int maxNodeWidth, const int maxNodeHeight)
|
|
||||||
{
|
|
||||||
int heatMapWidth = (maxNodeWidth * nodes.size() / atomarNodeWidth) * 5; // theoretically the nodes could horizontally or vertically far from the center, therefore '*5' (it's kinda arbitrary, generally *2 should suffice, I use *5 to prevent problems in extrem cases)
|
|
||||||
int heatMapHeight = (maxNodeHeight * nodes.size() / atomarNodeHeight) * 5;
|
|
||||||
|
|
||||||
MatrixDynamicBase<unsigned int> heatMap(heatMapWidth, heatMapHeight);
|
|
||||||
|
|
||||||
for (const DummyNode& node : nodes)
|
|
||||||
{
|
|
||||||
int left = node.position.x / atomarNodeWidth + heatMapWidth/2;
|
|
||||||
int up = node.position.y / atomarNodeHeight + heatMapHeight/2;
|
|
||||||
Vec2i size = calculateRasterNodeSize(node);
|
|
||||||
int width = size.x;
|
|
||||||
int height = size.y;
|
|
||||||
|
|
||||||
if (left + width > heatMapWidth || left < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (up + height > heatMapHeight || up < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
unsigned int x = left + i;
|
|
||||||
unsigned int y = up + j;
|
|
||||||
unsigned int value = heatMap.getValue(x, y);
|
|
||||||
|
|
||||||
heatMap.setValue(x, y, value+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return heatMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphPostprocessor::resolveOverlap(
|
|
||||||
std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisorWidth, const int divisorHeight)
|
|
||||||
{
|
|
||||||
int heatMapWidth = heatMap.getColumnsCount();
|
|
||||||
int heatMapHeight = heatMap.getRowsCount();
|
|
||||||
|
|
||||||
bool overlap = true;
|
|
||||||
int iterationCount = 0;
|
|
||||||
int maxIterations = 15;
|
|
||||||
|
|
||||||
while (overlap && iterationCount < maxIterations)
|
|
||||||
{
|
|
||||||
LOG_INFO_STREAM(<< iterationCount);
|
|
||||||
|
|
||||||
overlap = false;
|
|
||||||
iterationCount++;
|
|
||||||
|
|
||||||
for (DummyNode& node : nodes)
|
|
||||||
{
|
|
||||||
Vec2i nodePos(0, 0);
|
|
||||||
nodePos.x = node.position.x / divisorWidth + heatMapWidth/2;
|
|
||||||
nodePos.y = node.position.y / divisorHeight + heatMapHeight/2;
|
|
||||||
Vec2i nodeSize = calculateRasterNodeSize(node);
|
|
||||||
|
|
||||||
if (nodePos.x + nodeSize.x > heatMapWidth || nodePos.x < 0)
|
|
||||||
{
|
|
||||||
LOG_WARNING("Leaving heatmap area in x");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodePos.y + nodeSize.y > heatMapHeight || nodePos.y < 0)
|
|
||||||
{
|
|
||||||
LOG_WARNING("Leaving heatmap area in y");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2f grad(0.0f, 0.0f);
|
|
||||||
if (getHeatmapGradient(grad, heatMap, nodePos, nodeSize))
|
|
||||||
{
|
|
||||||
overlap = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle overlap with no gradient
|
|
||||||
// e.g. when a node lies completely on top of another
|
|
||||||
if (grad.getLengthSquared() <= 0.000001f && overlap)
|
|
||||||
{
|
|
||||||
grad = node.position;
|
|
||||||
grad.normalize();
|
|
||||||
|
|
||||||
// catch special case of node being at position 0/0
|
|
||||||
if (grad.getLengthSquared() <= 0.000001f)
|
|
||||||
{
|
|
||||||
grad.y = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
grad *= -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove node temporarily from heat map, it will be re-added at the new position later on
|
|
||||||
modifyHeatmapArea(heatMap, nodePos, nodeSize, -1);
|
|
||||||
|
|
||||||
// move node to new position
|
|
||||||
int xOffset = grad.x * divisorWidth;
|
|
||||||
int yOffset = grad.y * divisorHeight;
|
|
||||||
|
|
||||||
int maxXOffset = 2*divisorWidth;
|
|
||||||
int maxYOffset = 2*divisorHeight;
|
|
||||||
|
|
||||||
// prevent the graph from "exploding" again...
|
|
||||||
if (xOffset > maxXOffset)
|
|
||||||
{
|
|
||||||
xOffset = maxXOffset;
|
|
||||||
}
|
|
||||||
else if (xOffset < -maxXOffset)
|
|
||||||
{
|
|
||||||
xOffset = -maxXOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yOffset > maxYOffset)
|
|
||||||
{
|
|
||||||
yOffset = maxYOffset;
|
|
||||||
}
|
|
||||||
else if (yOffset < -maxYOffset)
|
|
||||||
{
|
|
||||||
yOffset = -maxYOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
node.position += Vec2i(xOffset, yOffset);
|
|
||||||
|
|
||||||
alignNodeOnRaster(node);
|
|
||||||
|
|
||||||
// re-add node to heat map at new position
|
|
||||||
nodePos.x = node.position.x / divisorWidth + heatMapWidth/2;
|
|
||||||
nodePos.y = node.position.y / divisorHeight + heatMapHeight/2;
|
|
||||||
|
|
||||||
modifyHeatmapArea(heatMap, nodePos, nodeSize, 1);
|
|
||||||
|
|
||||||
if (getHeatmapGradient(grad, heatMap, nodePos, nodeSize))
|
|
||||||
{
|
|
||||||
overlap = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphPostprocessor::modifyHeatmapArea(
|
|
||||||
MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size, const int modifier
|
|
||||||
){
|
|
||||||
bool wentOutOfRange = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < size.x; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size.y; j++)
|
|
||||||
{
|
|
||||||
int x = leftUpperCorner.x + i;
|
|
||||||
int y = leftUpperCorner.y + j;
|
|
||||||
|
|
||||||
if (x < 0 || x > static_cast<int>(heatMap.getColumnsCount()-1))
|
|
||||||
{
|
|
||||||
wentOutOfRange = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > static_cast<int>(heatMap.getRowsCount()-1))
|
|
||||||
{
|
|
||||||
wentOutOfRange = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int value = heatMap.getValue(x, y);
|
|
||||||
heatMap.setValue(x, y, value+modifier);
|
|
||||||
|
|
||||||
if (wentOutOfRange == true)
|
|
||||||
{
|
|
||||||
LOG_WARNING("Left matrix range while trying to modify values.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphPostprocessor::getHeatmapGradient(
|
|
||||||
Vec2f& outGradient, const MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size
|
|
||||||
){
|
|
||||||
bool overlap = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < size.x; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size.y; j++)
|
|
||||||
{
|
|
||||||
int x = leftUpperCorner.x + i;
|
|
||||||
int y = leftUpperCorner.y + j;
|
|
||||||
|
|
||||||
// weight factors that emphasize gradients near the nodes center
|
|
||||||
int hMagFactor = std::max(1, (int)(size.x * 0.5 - std::abs(i + 1 - size.x * 0.5)));
|
|
||||||
int vMagFactor = std::max(1, (int)(size.y * 0.5 - std::abs(j + 1 - size.y * 0.5)));
|
|
||||||
|
|
||||||
// if x and y lie directly at the border not all 4 neighbours can be checked
|
|
||||||
if (x < 1 || x > static_cast<int>(heatMap.getColumnsCount() - 2))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 1 || y > static_cast<int>(heatMap.getRowsCount() - 2))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
float val = heatMap.getValue(x, y);
|
|
||||||
|
|
||||||
float xP1 = heatMap.getValue(x + 1, y) * hMagFactor;
|
|
||||||
float xM1 = heatMap.getValue(x - 1, y) * hMagFactor;
|
|
||||||
float yP1 = heatMap.getValue(x, y + 1) * vMagFactor;
|
|
||||||
float yM1 = heatMap.getValue(x, y - 1) * vMagFactor;
|
|
||||||
|
|
||||||
xP1 = std::sqrt(xP1);
|
|
||||||
xM1 = std::sqrt(xM1);
|
|
||||||
yP1 = std::sqrt(yP1);
|
|
||||||
yM1 = std::sqrt(yM1);
|
|
||||||
|
|
||||||
float xOffset = (xM1 - val) + (val - xP1);
|
|
||||||
float yOffset = (yM1 - val) + (val - yP1);
|
|
||||||
|
|
||||||
outGradient += Vec2f(xOffset, yOffset);
|
|
||||||
|
|
||||||
if (val > 1)
|
|
||||||
{
|
|
||||||
overlap = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return overlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2f GraphPostprocessor::heatMapRayCast(
|
|
||||||
const MatrixDynamicBase<unsigned int>& heatMap, const Vec2f& startPosition, const Vec2f& direction, unsigned int minValue
|
|
||||||
){
|
|
||||||
float xOffset = 0.0f;
|
|
||||||
float yOffset = 0.0f;
|
|
||||||
|
|
||||||
if (std::abs(direction.x) > 0.0000000001f)
|
|
||||||
{
|
|
||||||
xOffset = direction.x / std::abs(direction.x);
|
|
||||||
}
|
|
||||||
if (std::abs(direction.y) > 0.0000000001f)
|
|
||||||
{
|
|
||||||
yOffset = direction.y / std::abs(direction.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startPosition.x < 1 || startPosition.x > static_cast<int>(heatMap.getColumnsCount() - 2))
|
|
||||||
{
|
|
||||||
return Vec2f(0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
if (startPosition.y < 1 || startPosition.y > static_cast<int>(heatMap.getRowsCount() - 2))
|
|
||||||
{
|
|
||||||
return Vec2f(0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2f length(0.0f, 0.0f);
|
|
||||||
|
|
||||||
bool hit = false;
|
|
||||||
|
|
||||||
float posX = startPosition.x + xOffset;
|
|
||||||
float posY = startPosition.y + yOffset;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (heatMap.getValue(posX, posY) >= minValue)
|
|
||||||
{
|
|
||||||
hit = true;
|
|
||||||
length.x = length.x + xOffset;
|
|
||||||
length.y = length.y + yOffset;
|
|
||||||
|
|
||||||
posX += xOffset;
|
|
||||||
posY += yOffset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hit = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (hit);
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2i GraphPostprocessor::calculateRasterNodeSize(const DummyNode& node)
|
|
||||||
{
|
|
||||||
Vec2i size = node.size;
|
|
||||||
Vec2i rasterSize(0, 0);
|
|
||||||
|
|
||||||
while (size.x > 0)
|
|
||||||
{
|
|
||||||
size.x = size.x - s_cellWidth;
|
|
||||||
if(size.x > 0)
|
|
||||||
{
|
|
||||||
size.x = size.x - s_cellPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
rasterSize.x = rasterSize.x + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (size.y > 0)
|
|
||||||
{
|
|
||||||
size.y = size.y - s_cellHeight;
|
|
||||||
if(size.y > 0)
|
|
||||||
{
|
|
||||||
size.y = size.y - s_cellPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
rasterSize.y = rasterSize.y + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rasterSize;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#ifndef GRAPH_POSTPROCESSOR_H
|
|
||||||
#define GRAPH_POSTPROCESSOR_H
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include "utility/math/MatrixDynamicBase.h"
|
|
||||||
|
|
||||||
#include "component/controller/helper/DummyNode.h"
|
|
||||||
|
|
||||||
class GraphPostprocessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void doPostprocessing(std::vector<DummyNode>& nodes);
|
|
||||||
|
|
||||||
static void alignNodeOnRaster(DummyNode& node);
|
|
||||||
static Vec2i alignOnRaster(Vec2i position);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static unsigned int s_cellWidth;
|
|
||||||
static unsigned int s_cellHeight;
|
|
||||||
static unsigned int s_cellPadding;
|
|
||||||
|
|
||||||
static MatrixDynamicBase<unsigned int> buildHeatMap(const std::vector<DummyNode>& nodes, const int atomarNodeWidth, const int atomarNodeHeight, const int maxNodeWidth, const int maxNodeHeight);
|
|
||||||
static void resolveOutliers(std::vector<DummyNode>& nodes, const Vec2i& centerPoint);
|
|
||||||
static void resolveOverlap(std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisorWidth, const int divisorHeight);
|
|
||||||
|
|
||||||
static void modifyHeatmapArea(MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size, const int modifier);
|
|
||||||
static bool getHeatmapGradient(Vec2f& outGradient, const MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size);
|
|
||||||
static Vec2f heatMapRayCast(const MatrixDynamicBase<unsigned int>& heatMap, const Vec2f& startPosition, const Vec2f& direction, unsigned int minValue);
|
|
||||||
static Vec2i calculateRasterNodeSize(const DummyNode& node);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GRAPH_POSTPROCESSOR_H
|
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
#include "component/controller/helper/ListLayouter.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "component/controller/helper/DummyNode.h"
|
||||||
|
#include "component/view/GraphViewStyle.h"
|
||||||
|
|
||||||
|
ListLayouter::ListLayouter(Vec2i viewSize)
|
||||||
|
: m_viewSize(viewSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListLayouter::layoutList(std::vector<std::shared_ptr<DummyNode>>& nodes)
|
||||||
|
{
|
||||||
|
size_t colsFinal;
|
||||||
|
std::vector<int> maxWidthsFinal;
|
||||||
|
|
||||||
|
int gapX = GraphViewStyle::s_gridCellSize + 2 * GraphViewStyle::s_gridCellPadding;
|
||||||
|
int gapY = GraphViewStyle::s_gridCellPadding;
|
||||||
|
|
||||||
|
for (size_t cols = 1; cols <= 10; cols++)
|
||||||
|
{
|
||||||
|
std::vector<int> maxWidths = std::vector<int>(cols, 0);
|
||||||
|
size_t nodesPerCol = cols == 1 ? nodes.size() : std::ceil((nodes.size() + cols - 1) / double(cols));
|
||||||
|
int maxHeight = 0;
|
||||||
|
int height = -gapY;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nodes.size(); i++)
|
||||||
|
{
|
||||||
|
size_t j = i / nodesPerCol;
|
||||||
|
|
||||||
|
if (i % nodesPerCol == 0)
|
||||||
|
{
|
||||||
|
height = -gapY;
|
||||||
|
}
|
||||||
|
height += nodes[i]->size.y() + gapY;
|
||||||
|
|
||||||
|
maxWidths[j] = std::max(nodes[i]->size.x(), maxWidths[j]);
|
||||||
|
maxHeight = std::max(height, maxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = -gapX;
|
||||||
|
for (size_t j = 0; j < cols; j++)
|
||||||
|
{
|
||||||
|
width += maxWidths[j] + gapX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width > m_viewSize.x)
|
||||||
|
{
|
||||||
|
if (!maxWidthsFinal.size())
|
||||||
|
{
|
||||||
|
colsFinal = 1;
|
||||||
|
maxWidthsFinal = maxWidths;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
colsFinal = cols;
|
||||||
|
maxWidthsFinal = maxWidths;
|
||||||
|
|
||||||
|
if (height < m_viewSize.y)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
size_t nodesPerCol = colsFinal == 1 ? nodes.size() : std::ceil((nodes.size() + colsFinal - 1) / double(colsFinal));
|
||||||
|
std::shared_ptr<DummyNode> lastTextNode;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nodes.size(); i++)
|
||||||
|
{
|
||||||
|
size_t j = i / nodesPerCol;
|
||||||
|
if (j != 0 && j != colsFinal && i % nodesPerCol == 0)
|
||||||
|
{
|
||||||
|
if (lastTextNode)
|
||||||
|
{
|
||||||
|
std::shared_ptr<DummyNode> textNode = std::make_shared<DummyNode>(*lastTextNode.get());
|
||||||
|
|
||||||
|
if (nodes[i - 1] == lastTextNode)
|
||||||
|
{
|
||||||
|
lastTextNode->visible = false;
|
||||||
|
}
|
||||||
|
else if (textNode->name.size() == 1)
|
||||||
|
{
|
||||||
|
textNode->name += "..";
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.insert(nodes.begin() + i, textNode);
|
||||||
|
lastTextNode.reset();
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
y = 0;
|
||||||
|
x += maxWidthsFinal[j - 1] + gapX;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes[i]->position.x = x;
|
||||||
|
nodes[i]->position.y = y;
|
||||||
|
|
||||||
|
y += nodes[i]->size.y + gapY;
|
||||||
|
|
||||||
|
if (nodes[i]->isTextNode())
|
||||||
|
{
|
||||||
|
lastTextNode = nodes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef LIST_LAYOUTER_H
|
||||||
|
#define LIST_LAYOUTER_H
|
||||||
|
|
||||||
|
#include "utility/math/Vector2.h"
|
||||||
|
|
||||||
|
struct DummyNode;
|
||||||
|
|
||||||
|
class ListLayouter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ListLayouter(Vec2i viewSize);
|
||||||
|
|
||||||
|
void layoutList(std::vector<std::shared_ptr<DummyNode>>& nodes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vec2i m_viewSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LIST_LAYOUTER_H
|
||||||
@@ -20,6 +20,8 @@ public:
|
|||||||
{
|
{
|
||||||
bool animatedTransition;
|
bool animatedTransition;
|
||||||
bool centerActiveNode;
|
bool centerActiveNode;
|
||||||
|
bool scrollToTop;
|
||||||
|
bool isIndexedList;
|
||||||
};
|
};
|
||||||
|
|
||||||
GraphView(ViewLayout* viewLayout);
|
GraphView(ViewLayout* viewLayout);
|
||||||
|
|||||||
@@ -23,6 +23,53 @@ float GraphViewStyle::s_zoomFactor;
|
|||||||
std::map<std::string, GraphViewStyle::NodeColor> GraphViewStyle::s_nodeColors;
|
std::map<std::string, GraphViewStyle::NodeColor> GraphViewStyle::s_nodeColors;
|
||||||
std::map<std::string, std::string> GraphViewStyle::s_edgeColors;
|
std::map<std::string, std::string> GraphViewStyle::s_edgeColors;
|
||||||
|
|
||||||
|
Vec2i GraphViewStyle::alignOnRaster(Vec2i position)
|
||||||
|
{
|
||||||
|
int rasterPosDivisor = s_gridCellSize + s_gridCellPadding;
|
||||||
|
|
||||||
|
if (position.x % rasterPosDivisor != 0)
|
||||||
|
{
|
||||||
|
int t = position.x / rasterPosDivisor;
|
||||||
|
int r = position.x % rasterPosDivisor;
|
||||||
|
|
||||||
|
if (std::abs(r) > rasterPosDivisor/2)
|
||||||
|
{
|
||||||
|
if (t != 0)
|
||||||
|
{
|
||||||
|
t += (t / std::abs(t));
|
||||||
|
}
|
||||||
|
else if (r != 0)
|
||||||
|
{
|
||||||
|
t += (r / std::abs(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
position.x = t * rasterPosDivisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position.y % rasterPosDivisor != 0)
|
||||||
|
{
|
||||||
|
int t = position.y / rasterPosDivisor;
|
||||||
|
int r = position.y % rasterPosDivisor;
|
||||||
|
|
||||||
|
if (std::abs(r) > rasterPosDivisor/2)
|
||||||
|
{
|
||||||
|
if(t != 0)
|
||||||
|
{
|
||||||
|
t += (t / std::abs(t));
|
||||||
|
}
|
||||||
|
else if(r != 0)
|
||||||
|
{
|
||||||
|
t += (r / std::abs(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
position.y = t * rasterPosDivisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
GraphViewStyle::NodeMargins::NodeMargins()
|
GraphViewStyle::NodeMargins::NodeMargins()
|
||||||
: left(0)
|
: left(0)
|
||||||
, right(0)
|
, right(0)
|
||||||
@@ -176,6 +223,11 @@ size_t GraphViewStyle::getFontSizeOfQualifier()
|
|||||||
return s_fontSize - 3;
|
return s_fontSize - 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GraphViewStyle::getFontSizeOfTextNode()
|
||||||
|
{
|
||||||
|
return s_fontSize + 5;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GraphViewStyle::getFontNameForNodeType(Node::NodeType type)
|
std::string GraphViewStyle::getFontNameForNodeType(Node::NodeType type)
|
||||||
{
|
{
|
||||||
return s_fontName;
|
return s_fontName;
|
||||||
@@ -191,6 +243,11 @@ std::string GraphViewStyle::getFontNameOfExpandToggleNode()
|
|||||||
return "Fira Sans";
|
return "Fira Sans";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GraphViewStyle::getFontNameOfTextNode()
|
||||||
|
{
|
||||||
|
return "Fira Sans";
|
||||||
|
}
|
||||||
|
|
||||||
GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType type, bool hasChildren)
|
GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType type, bool hasChildren)
|
||||||
{
|
{
|
||||||
NodeMargins margins;
|
NodeMargins margins;
|
||||||
@@ -308,6 +365,17 @@ GraphViewStyle::NodeMargins GraphViewStyle::getMarginsOfBundleNode()
|
|||||||
return getMarginsForNodeType(Node::NODE_ENUM, false);
|
return getMarginsForNodeType(Node::NODE_ENUM, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphViewStyle::NodeMargins GraphViewStyle::getMarginsOfTextNode()
|
||||||
|
{
|
||||||
|
NodeMargins margins;
|
||||||
|
|
||||||
|
margins.left = margins.right = 0;
|
||||||
|
margins.top = margins.bottom = 6;
|
||||||
|
margins.minWidth = margins.charHeight = getFontSizeOfTextNode();
|
||||||
|
|
||||||
|
return margins;
|
||||||
|
}
|
||||||
|
|
||||||
GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType(
|
GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType(
|
||||||
Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren, bool hasQualifier
|
Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren, bool hasQualifier
|
||||||
){
|
){
|
||||||
@@ -463,6 +531,21 @@ GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfQualifier()
|
|||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfTextNode()
|
||||||
|
{
|
||||||
|
NodeStyle style;
|
||||||
|
|
||||||
|
style.color = getNodeColor("text", false);
|
||||||
|
|
||||||
|
style.fontName = getFontNameOfTextNode();
|
||||||
|
style.fontSize = getFontSizeOfTextNode();
|
||||||
|
style.fontBold = true;
|
||||||
|
|
||||||
|
style.textOffset.y = 10;
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused)
|
GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused)
|
||||||
{
|
{
|
||||||
EdgeStyle style;
|
EdgeStyle style;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class GraphViewStyleImpl;
|
|||||||
class GraphViewStyle
|
class GraphViewStyle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static Vec2i alignOnRaster(Vec2i position);
|
||||||
|
|
||||||
struct NodeMargins
|
struct NodeMargins
|
||||||
{
|
{
|
||||||
NodeMargins();
|
NodeMargins();
|
||||||
@@ -104,15 +106,18 @@ public:
|
|||||||
static size_t getFontSizeOfExpandToggleNode();
|
static size_t getFontSizeOfExpandToggleNode();
|
||||||
static size_t getFontSizeOfCountCircle();
|
static size_t getFontSizeOfCountCircle();
|
||||||
static size_t getFontSizeOfQualifier();
|
static size_t getFontSizeOfQualifier();
|
||||||
|
static size_t getFontSizeOfTextNode();
|
||||||
|
|
||||||
static std::string getFontNameForNodeType(Node::NodeType type);
|
static std::string getFontNameForNodeType(Node::NodeType type);
|
||||||
static std::string getFontNameOfAccessNode();
|
static std::string getFontNameOfAccessNode();
|
||||||
static std::string getFontNameOfExpandToggleNode();
|
static std::string getFontNameOfExpandToggleNode();
|
||||||
|
static std::string getFontNameOfTextNode();
|
||||||
|
|
||||||
static NodeMargins getMarginsForNodeType(Node::NodeType type, bool hasChildren);
|
static NodeMargins getMarginsForNodeType(Node::NodeType type, bool hasChildren);
|
||||||
static NodeMargins getMarginsOfAccessNode(AccessKind access);
|
static NodeMargins getMarginsOfAccessNode(AccessKind access);
|
||||||
static NodeMargins getMarginsOfExpandToggleNode();
|
static NodeMargins getMarginsOfExpandToggleNode();
|
||||||
static NodeMargins getMarginsOfBundleNode();
|
static NodeMargins getMarginsOfBundleNode();
|
||||||
|
static NodeMargins getMarginsOfTextNode();
|
||||||
|
|
||||||
static NodeStyle getStyleForNodeType(
|
static NodeStyle getStyleForNodeType(
|
||||||
Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren, bool hasQualifier);
|
Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren, bool hasQualifier);
|
||||||
@@ -121,6 +126,7 @@ public:
|
|||||||
static NodeStyle getStyleOfCountCircle();
|
static NodeStyle getStyleOfCountCircle();
|
||||||
static NodeStyle getStyleOfBundleNode(bool isFocused);
|
static NodeStyle getStyleOfBundleNode(bool isFocused);
|
||||||
static NodeStyle getStyleOfQualifier();
|
static NodeStyle getStyleOfQualifier();
|
||||||
|
static NodeStyle getStyleOfTextNode();
|
||||||
|
|
||||||
static EdgeStyle getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused);
|
static EdgeStyle getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused);
|
||||||
|
|
||||||
|
|||||||
@@ -756,7 +756,7 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForAll() const
|
|||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const
|
std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace) const
|
||||||
{
|
{
|
||||||
TRACE();
|
TRACE();
|
||||||
|
|
||||||
@@ -863,6 +863,11 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(const std::v
|
|||||||
|
|
||||||
addComponentAccessToGraph(graph);
|
addComponentAccessToGraph(graph);
|
||||||
|
|
||||||
|
if (isActiveNamespace)
|
||||||
|
{
|
||||||
|
*isActiveNamespace = isNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public:
|
|||||||
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& elementIds) const;
|
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& elementIds) const;
|
||||||
|
|
||||||
virtual std::shared_ptr<Graph> getGraphForAll() const;
|
virtual std::shared_ptr<Graph> getGraphForAll() const;
|
||||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const;
|
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace = nullptr) const;
|
||||||
|
|
||||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||||
|
|
||||||
virtual std::shared_ptr<Graph> getGraphForAll() const = 0;
|
virtual std::shared_ptr<Graph> getGraphForAll() const = 0;
|
||||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace = nullptr) const = 0;
|
||||||
|
|
||||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0;
|
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -117,11 +117,11 @@ std::shared_ptr<Graph> StorageAccessProxy::getGraphForAll() const
|
|||||||
return std::make_shared<Graph>();
|
return std::make_shared<Graph>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Graph> StorageAccessProxy::getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const
|
std::shared_ptr<Graph> StorageAccessProxy::getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace) const
|
||||||
{
|
{
|
||||||
if (hasSubject())
|
if (hasSubject())
|
||||||
{
|
{
|
||||||
return m_subject->getGraphForActiveTokenIds(tokenIds);
|
return m_subject->getGraphForActiveTokenIds(tokenIds, isActiveNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<Graph>();
|
return std::make_shared<Graph>();
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const;
|
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||||
|
|
||||||
virtual std::shared_ptr<Graph> getGraphForAll() const;
|
virtual std::shared_ptr<Graph> getGraphForAll() const;
|
||||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const;
|
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace = nullptr) const;
|
||||||
|
|
||||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public:
|
|||||||
Property<T>& operator=(const Property<T>& property);
|
Property<T>& operator=(const Property<T>& property);
|
||||||
|
|
||||||
operator const T&() const;
|
operator const T&() const;
|
||||||
|
T& operator()() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* m_valuePointer;
|
T* m_valuePointer;
|
||||||
@@ -47,4 +48,10 @@ Property<T>::operator const T&() const
|
|||||||
return *m_valuePointer;
|
return *m_valuePointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T& Property<T>::operator()() const
|
||||||
|
{
|
||||||
|
return *m_valuePointer;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // PROPERTY_H
|
#endif // PROPERTY_H
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ class MessageGraphNodeBundleSplit
|
|||||||
: public Message<MessageGraphNodeBundleSplit>
|
: public Message<MessageGraphNodeBundleSplit>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MessageGraphNodeBundleSplit(Id bundleId)
|
MessageGraphNodeBundleSplit(Id bundleId, bool removeOtherNodes = false, bool layoutToList = false)
|
||||||
: bundleId(bundleId)
|
: bundleId(bundleId)
|
||||||
|
, removeOtherNodes(removeOtherNodes)
|
||||||
|
, layoutToList(layoutToList)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,6 +26,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Id bundleId;
|
Id bundleId;
|
||||||
|
bool removeOtherNodes;
|
||||||
|
bool layoutToList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESSAGE_GRAPH_NODE_BUNDLE_SPLIT_H
|
#endif // MESSAGE_GRAPH_NODE_BUNDLE_SPLIT_H
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ add_files(
|
|||||||
qt/view/graphElements/QtGraphNodeExpandToggle.h
|
qt/view/graphElements/QtGraphNodeExpandToggle.h
|
||||||
qt/view/graphElements/QtGraphNodeQualifier.cpp
|
qt/view/graphElements/QtGraphNodeQualifier.cpp
|
||||||
qt/view/graphElements/QtGraphNodeQualifier.h
|
qt/view/graphElements/QtGraphNodeQualifier.h
|
||||||
|
qt/view/graphElements/QtGraphNodeText.cpp
|
||||||
|
qt/view/graphElements/QtGraphNodeText.h
|
||||||
|
|
||||||
qt/view/QtCodeView.cpp
|
qt/view/QtCodeView.cpp
|
||||||
qt/view/QtCodeView.h
|
qt/view/QtCodeView.h
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ QtGraphicsView::QtGraphicsView(QWidget* parent)
|
|||||||
|
|
||||||
float QtGraphicsView::getZoomFactor() const
|
float QtGraphicsView::getZoomFactor() const
|
||||||
{
|
{
|
||||||
return m_appZoomFactor;
|
return m_appZoomFactor * m_zoomFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtGraphicsView::setAppZoomFactor(float appZoomFactor)
|
void QtGraphicsView::setAppZoomFactor(float appZoomFactor)
|
||||||
@@ -181,6 +181,12 @@ void QtGraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
void QtGraphicsView::keyPressEvent(QKeyEvent* event)
|
void QtGraphicsView::keyPressEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
|
if (event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z)
|
||||||
|
{
|
||||||
|
QChar c = event->text().at(0).toUpper();
|
||||||
|
emit characterKeyPressed(c);
|
||||||
|
}
|
||||||
|
|
||||||
bool moved = moves();
|
bool moved = moves();
|
||||||
|
|
||||||
switch (event->key())
|
switch (event->key())
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ protected:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void emptySpaceClicked();
|
void emptySpaceClicked();
|
||||||
|
void characterKeyPressed(QChar c);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateTimer();
|
void updateTimer();
|
||||||
|
|||||||
@@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
#include "component/controller/helper/DummyEdge.h"
|
#include "component/controller/helper/DummyEdge.h"
|
||||||
#include "component/controller/helper/DummyNode.h"
|
#include "component/controller/helper/DummyNode.h"
|
||||||
#include "component/controller/helper/GraphPostprocessor.h"
|
|
||||||
#include "component/view/GraphViewStyle.h"
|
#include "component/view/GraphViewStyle.h"
|
||||||
#include "settings/ColorScheme.h"
|
|
||||||
#include "settings/ApplicationSettings.h"
|
#include "settings/ApplicationSettings.h"
|
||||||
#include "utility/messaging/type/MessageDeactivateEdge.h"
|
#include "utility/messaging/type/MessageDeactivateEdge.h"
|
||||||
#include "utility/ResourcePaths.h"
|
#include "utility/ResourcePaths.h"
|
||||||
@@ -29,6 +27,7 @@
|
|||||||
#include "qt/view/graphElements/QtGraphNodeData.h"
|
#include "qt/view/graphElements/QtGraphNodeData.h"
|
||||||
#include "qt/view/graphElements/QtGraphNodeExpandToggle.h"
|
#include "qt/view/graphElements/QtGraphNodeExpandToggle.h"
|
||||||
#include "qt/view/graphElements/QtGraphNodeQualifier.h"
|
#include "qt/view/graphElements/QtGraphNodeQualifier.h"
|
||||||
|
#include "qt/view/graphElements/QtGraphNodeText.h"
|
||||||
|
|
||||||
QtGraphView::QtGraphView(ViewLayout* viewLayout)
|
QtGraphView::QtGraphView(ViewLayout* viewLayout)
|
||||||
: GraphView(viewLayout)
|
: GraphView(viewLayout)
|
||||||
@@ -40,6 +39,8 @@ QtGraphView::QtGraphView(ViewLayout* viewLayout)
|
|||||||
, m_refreshFunctor(std::bind(&QtGraphView::doRefreshView, this))
|
, m_refreshFunctor(std::bind(&QtGraphView::doRefreshView, this))
|
||||||
, m_focusInFunctor(std::bind(&QtGraphView::doFocusIn, this, std::placeholders::_1))
|
, m_focusInFunctor(std::bind(&QtGraphView::doFocusIn, this, std::placeholders::_1))
|
||||||
, m_focusOutFunctor(std::bind(&QtGraphView::doFocusOut, this, std::placeholders::_1))
|
, m_focusOutFunctor(std::bind(&QtGraphView::doFocusOut, this, std::placeholders::_1))
|
||||||
|
, m_scrollToTop(false)
|
||||||
|
, m_isIndexedList(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ void QtGraphView::initView()
|
|||||||
widget->layout()->addWidget(view);
|
widget->layout()->addWidget(view);
|
||||||
|
|
||||||
connect(view, SIGNAL(emptySpaceClicked()), this, SLOT(clickedInEmptySpace()));
|
connect(view, SIGNAL(emptySpaceClicked()), this, SLOT(clickedInEmptySpace()));
|
||||||
|
connect(view, SIGNAL(characterKeyPressed(QChar)), this, SLOT(pressedCharacterKey(QChar)));
|
||||||
|
|
||||||
m_scrollSpeedChangeListenerHorizontal.setScrollBar(view->horizontalScrollBar());
|
m_scrollSpeedChangeListenerHorizontal.setScrollBar(view->horizontalScrollBar());
|
||||||
m_scrollSpeedChangeListenerVertical.setScrollBar(view->verticalScrollBar());
|
m_scrollSpeedChangeListenerVertical.setScrollBar(view->verticalScrollBar());
|
||||||
@@ -109,18 +111,25 @@ Vec2i QtGraphView::getViewSize() const
|
|||||||
QtGraphicsView* view = getView();
|
QtGraphicsView* view = getView();
|
||||||
|
|
||||||
float zoomFactor = view->getZoomFactor();
|
float zoomFactor = view->getZoomFactor();
|
||||||
return Vec2i(view->width() / zoomFactor - 80, view->height() / zoomFactor - 80);
|
return Vec2i(view->width() / zoomFactor - 60, view->height() / zoomFactor - 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtGraphView::centerScrollBars()
|
void QtGraphView::updateScrollBars()
|
||||||
{
|
{
|
||||||
QGraphicsView* view = getView();
|
QGraphicsView* view = getView();
|
||||||
|
|
||||||
QScrollBar* hb = view->horizontalScrollBar();
|
QScrollBar* hb = view->horizontalScrollBar();
|
||||||
QScrollBar* vb = view->verticalScrollBar();
|
QScrollBar* vb = view->verticalScrollBar();
|
||||||
|
|
||||||
hb->setValue((hb->minimum() + hb->maximum()) / 2);
|
if (m_scrollToTop)
|
||||||
vb->setValue((vb->minimum() + vb->maximum()) / 2);
|
{
|
||||||
|
vb->setValue(vb->minimum());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hb->setValue((hb->minimum() + hb->maximum()) / 2);
|
||||||
|
vb->setValue((vb->minimum() + vb->maximum()) / 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtGraphView::finishedTransition()
|
void QtGraphView::finishedTransition()
|
||||||
@@ -148,6 +157,50 @@ void QtGraphView::clickedInEmptySpace()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtGraphView::pressedCharacterKey(QChar c)
|
||||||
|
{
|
||||||
|
if (!m_isIndexedList)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QtGraphNode* node = nullptr;
|
||||||
|
bool hasTextNodes = false;
|
||||||
|
|
||||||
|
for (const std::shared_ptr<QtGraphNode>& n : m_oldNodes)
|
||||||
|
{
|
||||||
|
if (n->isTextNode() && n->getName().size())
|
||||||
|
{
|
||||||
|
hasTextNodes = true;
|
||||||
|
QChar start(n->getName()[0]);
|
||||||
|
if (start >= c)
|
||||||
|
{
|
||||||
|
node = n.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasTextNodes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QtGraphicsView* view = getView();
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
view->ensureVisibleAnimated(QRectF(0, view->scene()->height() - 5, view->scene()->width(), 5), 100, 100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vec2i pos = node->getPosition();
|
||||||
|
Vec2i size = node->getSize();
|
||||||
|
|
||||||
|
view->ensureVisibleAnimated(QRectF(pos.x, pos.y, size.x, size.y + view->height() / 3 * 2), 100, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QtGraphView::switchToNewGraphData()
|
void QtGraphView::switchToNewGraphData()
|
||||||
{
|
{
|
||||||
m_oldGraph = m_graph;
|
m_oldGraph = m_graph;
|
||||||
@@ -170,6 +223,11 @@ void QtGraphView::switchToNewGraphData()
|
|||||||
|
|
||||||
doResize();
|
doResize();
|
||||||
|
|
||||||
|
if (m_scrollToTop)
|
||||||
|
{
|
||||||
|
updateScrollBars();
|
||||||
|
}
|
||||||
|
|
||||||
// Manually hover the item below the mouse cursor.
|
// Manually hover the item below the mouse cursor.
|
||||||
QtGraphicsView* view = getView();
|
QtGraphicsView* view = getView();
|
||||||
QtGraphNode* node = view->getNodeAtCursorPosition();
|
QtGraphNode* node = view->getNodeAtCursorPosition();
|
||||||
@@ -244,7 +302,7 @@ void QtGraphView::doRebuildGraph(
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPointF center = itemsBoundingRect(m_nodes).center();
|
QPointF center = itemsBoundingRect(m_nodes).center();
|
||||||
Vec2i o = GraphPostprocessor::alignOnRaster(Vec2i(center.x(), center.y()));
|
Vec2i o = GraphViewStyle::alignOnRaster(Vec2i(center.x(), center.y()));
|
||||||
QPointF offset = QPointF(o.x, o.y);
|
QPointF offset = QPointF(o.x, o.y);
|
||||||
m_sceneRectOffset = offset - center;
|
m_sceneRectOffset = offset - center;
|
||||||
|
|
||||||
@@ -282,6 +340,9 @@ void QtGraphView::doRebuildGraph(
|
|||||||
m_activeNode.reset();
|
m_activeNode.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_scrollToTop = params.scrollToTop;
|
||||||
|
m_isIndexedList = params.isIndexedList;
|
||||||
|
|
||||||
if (params.animatedTransition && ApplicationSettings::getInstance()->getUseAnimations())
|
if (params.animatedTransition && ApplicationSettings::getInstance()->getUseAnimations())
|
||||||
{
|
{
|
||||||
createTransition();
|
createTransition();
|
||||||
@@ -364,12 +425,17 @@ std::shared_ptr<QtGraphNode> QtGraphView::createNodeRecursive(
|
|||||||
}
|
}
|
||||||
else if (node->isBundleNode())
|
else if (node->isBundleNode())
|
||||||
{
|
{
|
||||||
newNode = std::make_shared<QtGraphNodeBundle>(node->tokenId, node->getBundledNodeCount(), node->name);
|
newNode = std::make_shared<QtGraphNodeBundle>(
|
||||||
|
node->tokenId, node->getBundledNodeCount(), node->bundledNodeType, node->name);
|
||||||
}
|
}
|
||||||
else if (node->isQualifierNode())
|
else if (node->isQualifierNode())
|
||||||
{
|
{
|
||||||
newNode = std::make_shared<QtGraphNodeQualifier>(node->qualifierName);
|
newNode = std::make_shared<QtGraphNodeQualifier>(node->qualifierName);
|
||||||
}
|
}
|
||||||
|
else if (node->isTextNode())
|
||||||
|
{
|
||||||
|
newNode = std::make_shared<QtGraphNodeText>(node->name);
|
||||||
|
}
|
||||||
|
|
||||||
newNode->setPosition(node->position);
|
newNode->setPosition(node->position);
|
||||||
newNode->setSize(node->size);
|
newNode->setSize(node->size);
|
||||||
@@ -384,7 +450,7 @@ std::shared_ptr<QtGraphNode> QtGraphView::createNodeRecursive(
|
|||||||
{
|
{
|
||||||
newNode->setParent(parentNode);
|
newNode->setParent(parentNode);
|
||||||
}
|
}
|
||||||
else
|
else if (!node->isTextNode())
|
||||||
{
|
{
|
||||||
newNode->addComponent(std::make_shared<QtGraphNodeComponentMoveable>(newNode));
|
newNode->addComponent(std::make_shared<QtGraphNodeComponentMoveable>(newNode));
|
||||||
}
|
}
|
||||||
@@ -624,9 +690,9 @@ void QtGraphView::createTransition()
|
|||||||
|
|
||||||
anim->setDuration(300);
|
anim->setDuration(300);
|
||||||
|
|
||||||
if (!remainingNodes.size())
|
if (!remainingNodes.size() || m_scrollToTop)
|
||||||
{
|
{
|
||||||
connect(anim, SIGNAL(finished()), this, SLOT(centerScrollBars()));
|
connect(anim, SIGNAL(finished()), this, SLOT(updateScrollBars()));
|
||||||
}
|
}
|
||||||
|
|
||||||
remain->addAnimation(anim);
|
remain->addAnimation(anim);
|
||||||
|
|||||||
@@ -49,9 +49,10 @@ public:
|
|||||||
virtual Vec2i getViewSize() const;
|
virtual Vec2i getViewSize() const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void centerScrollBars();
|
void updateScrollBars();
|
||||||
void finishedTransition();
|
void finishedTransition();
|
||||||
void clickedInEmptySpace();
|
void clickedInEmptySpace();
|
||||||
|
void pressedCharacterKey(QChar c);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void switchToNewGraphData();
|
void switchToNewGraphData();
|
||||||
@@ -112,6 +113,8 @@ private:
|
|||||||
std::list<std::shared_ptr<QtGraphNode>> m_oldNodes;
|
std::list<std::shared_ptr<QtGraphNode>> m_oldNodes;
|
||||||
|
|
||||||
std::shared_ptr<QtGraphNode> m_activeNode;
|
std::shared_ptr<QtGraphNode> m_activeNode;
|
||||||
|
bool m_scrollToTop;
|
||||||
|
bool m_isIndexedList;
|
||||||
|
|
||||||
std::shared_ptr<QSequentialAnimationGroup> m_transition;
|
std::shared_ptr<QSequentialAnimationGroup> m_transition;
|
||||||
QPointF m_sceneRectOffset;
|
QPointF m_sceneRectOffset;
|
||||||
|
|||||||
@@ -5,15 +5,12 @@
|
|||||||
#include <QGraphicsSceneEvent>
|
#include <QGraphicsSceneEvent>
|
||||||
#include <QPen>
|
#include <QPen>
|
||||||
|
|
||||||
#include "utility/ResourcePaths.h"
|
|
||||||
|
|
||||||
#include "component/controller/helper/GraphPostprocessor.h"
|
|
||||||
|
|
||||||
#include "qt/graphics/QtRoundedRectItem.h"
|
#include "qt/graphics/QtRoundedRectItem.h"
|
||||||
#include "qt/utility/QtDeviceScaledPixmap.h"
|
#include "qt/utility/QtDeviceScaledPixmap.h"
|
||||||
#include "qt/utility/utilityQt.h"
|
#include "qt/utility/utilityQt.h"
|
||||||
#include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h"
|
#include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h"
|
||||||
#include "qt/view/graphElements/QtGraphEdge.h"
|
#include "qt/view/graphElements/QtGraphEdge.h"
|
||||||
|
#include "utility/ResourcePaths.h"
|
||||||
|
|
||||||
void QtGraphNode::blendIn()
|
void QtGraphNode::blendIn()
|
||||||
{
|
{
|
||||||
@@ -250,6 +247,11 @@ bool QtGraphNode::isQualifierNode() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QtGraphNode::isTextNode() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Id QtGraphNode::getTokenId() const
|
Id QtGraphNode::getTokenId() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -277,7 +279,7 @@ void QtGraphNode::addSubNode(const std::shared_ptr<QtGraphNode>& node)
|
|||||||
|
|
||||||
void QtGraphNode::moved(const Vec2i& oldPosition)
|
void QtGraphNode::moved(const Vec2i& oldPosition)
|
||||||
{
|
{
|
||||||
setPosition(GraphPostprocessor::alignOnRaster(getPosition()));
|
setPosition(GraphViewStyle::alignOnRaster(getPosition()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtGraphNode::onClick()
|
void QtGraphNode::onClick()
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ public:
|
|||||||
virtual bool isExpandToggleNode() const;
|
virtual bool isExpandToggleNode() const;
|
||||||
virtual bool isBundleNode() const;
|
virtual bool isBundleNode() const;
|
||||||
virtual bool isQualifierNode() const;
|
virtual bool isQualifierNode() const;
|
||||||
|
virtual bool isTextNode() const;
|
||||||
|
|
||||||
virtual Id getTokenId() const;
|
virtual Id getTokenId() const;
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
#include "component/view/GraphViewStyle.h"
|
#include "component/view/GraphViewStyle.h"
|
||||||
#include "qt/graphics/QtCountCircleItem.h"
|
#include "qt/graphics/QtCountCircleItem.h"
|
||||||
|
|
||||||
QtGraphNodeBundle::QtGraphNodeBundle(Id tokenId, size_t nodeCount, std::string name)
|
QtGraphNodeBundle::QtGraphNodeBundle(Id tokenId, size_t nodeCount, Node::NodeType type, std::string name)
|
||||||
: QtGraphNode()
|
: QtGraphNode()
|
||||||
, m_tokenId(tokenId)
|
, m_tokenId(tokenId)
|
||||||
|
, m_type(type)
|
||||||
{
|
{
|
||||||
this->setName(name);
|
this->setName(name);
|
||||||
|
|
||||||
@@ -38,12 +39,24 @@ Id QtGraphNodeBundle::getTokenId() const
|
|||||||
|
|
||||||
void QtGraphNodeBundle::onClick()
|
void QtGraphNodeBundle::onClick()
|
||||||
{
|
{
|
||||||
MessageGraphNodeBundleSplit(m_tokenId).dispatch();
|
MessageGraphNodeBundleSplit(
|
||||||
|
m_tokenId,
|
||||||
|
m_type != Node::NODE_UNDEFINED && getName() != "Anonymous Namespaces",
|
||||||
|
m_type != Node::NODE_UNDEFINED
|
||||||
|
).dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtGraphNodeBundle::updateStyle()
|
void QtGraphNodeBundle::updateStyle()
|
||||||
{
|
{
|
||||||
GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleOfBundleNode(m_isHovering);
|
GraphViewStyle::NodeStyle style;
|
||||||
|
if (m_type != Node::NODE_UNDEFINED)
|
||||||
|
{
|
||||||
|
style = GraphViewStyle::getStyleForNodeType(m_type, true, false, m_isHovering, false, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
style = GraphViewStyle::getStyleOfBundleNode(m_isHovering);
|
||||||
|
}
|
||||||
setStyle(style);
|
setStyle(style);
|
||||||
|
|
||||||
m_circle->setPosition(Vec2f(m_rect->rect().right() - 3, m_rect->rect().top() + 3));
|
m_circle->setPosition(Vec2f(m_rect->rect().right() - 3, m_rect->rect().top() + 3));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef QT_GRAPH_NODE_BUNDLE_H
|
#ifndef QT_GRAPH_NODE_BUNDLE_H
|
||||||
#define QT_GRAPH_NODE_BUNDLE_H
|
#define QT_GRAPH_NODE_BUNDLE_H
|
||||||
|
|
||||||
|
#include "data/graph/Node.h"
|
||||||
#include "qt/view/graphElements/QtGraphNode.h"
|
#include "qt/view/graphElements/QtGraphNode.h"
|
||||||
|
|
||||||
class QtCountCircleItem;
|
class QtCountCircleItem;
|
||||||
@@ -9,7 +10,7 @@ class QtGraphNodeBundle
|
|||||||
: public QtGraphNode
|
: public QtGraphNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QtGraphNodeBundle(Id tokenId, size_t nodeCount, std::string name);
|
QtGraphNodeBundle(Id tokenId, size_t nodeCount, Node::NodeType type, std::string name);
|
||||||
virtual ~QtGraphNodeBundle();
|
virtual ~QtGraphNodeBundle();
|
||||||
|
|
||||||
// QtGraphNode implementation
|
// QtGraphNode implementation
|
||||||
@@ -27,6 +28,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
QtCountCircleItem* m_circle;
|
QtCountCircleItem* m_circle;
|
||||||
Id m_tokenId;
|
Id m_tokenId;
|
||||||
|
Node::NodeType m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_GRAPH_NODE_BUNDLE_H
|
#endif // QT_GRAPH_NODE_BUNDLE_H
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#include "qt/view/graphElements/QtGraphNodeText.h"
|
||||||
|
|
||||||
|
QtGraphNodeText::QtGraphNodeText(const std::string& name)
|
||||||
|
{
|
||||||
|
setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QtGraphNodeText::~QtGraphNodeText()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtGraphNodeText::isTextNode() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtGraphNodeText::updateStyle()
|
||||||
|
{
|
||||||
|
setStyle(GraphViewStyle::getStyleOfTextNode());
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef QT_GRAPH_NODE_TEXT_H
|
||||||
|
#define QT_GRAPH_NODE_TEXT_H
|
||||||
|
|
||||||
|
#include "qt/view/graphElements/QtGraphNode.h"
|
||||||
|
|
||||||
|
class QtGraphNodeText
|
||||||
|
: public QtGraphNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QtGraphNodeText(const std::string& name);
|
||||||
|
virtual ~QtGraphNodeText();
|
||||||
|
|
||||||
|
// QtGraphNode implementation
|
||||||
|
virtual bool isTextNode() const;
|
||||||
|
|
||||||
|
virtual void updateStyle();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_GRAPH_NODE_TEXT_H
|
||||||
Reference in New Issue
Block a user