From 5825fe77abeb3d6213b6a53069e73a07f78faf38 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Thu, 24 Sep 2015 03:12:42 +0200 Subject: [PATCH] ui: switch Graph to bucket grid layouting This change introduces bucket grid layouting, which sorts the nodes into buckets based on how they are connected. Each bucket is then layouted individually before they are arranged next to each other. Edges go from left to right, except for inheritance edges that go from bottom to top. --- src/app/qt/graphics/QtAngledLineItem.cpp | 52 ++- src/app/qt/graphics/QtAngledLineItem.h | 6 + src/app/qt/view/graphElements/QtGraphEdge.cpp | 25 +- src/app/qt/view/graphElements/QtGraphEdge.h | 3 + src/app/qt/view/graphElements/QtGraphNode.cpp | 28 +- src/app/qt/view/graphElements/QtGraphNode.h | 3 + src/lib/CMakeLists.txt | 6 +- .../component/controller/GraphController.cpp | 19 +- .../component/controller/GraphController.h | 3 +- .../controller/helper/BucketGrid.cpp | 352 ++++++++++++++++++ .../component/controller/helper/BucketGrid.h | 66 ++++ .../controller/{ => helper}/GraphLayouter.cpp | 14 +- .../controller/{ => helper}/GraphLayouter.h | 12 +- src/lib/component/view/GraphViewStyle.cpp | 33 +- src/lib/component/view/GraphViewStyle.h | 9 +- 15 files changed, 575 insertions(+), 56 deletions(-) create mode 100644 src/lib/component/controller/helper/BucketGrid.cpp create mode 100644 src/lib/component/controller/helper/BucketGrid.h rename src/lib/component/controller/{ => helper}/GraphLayouter.cpp (93%) rename src/lib/component/controller/{ => helper}/GraphLayouter.h (54%) diff --git a/src/app/qt/graphics/QtAngledLineItem.cpp b/src/app/qt/graphics/QtAngledLineItem.cpp index aeddfd1e..e1ca0735 100644 --- a/src/app/qt/graphics/QtAngledLineItem.cpp +++ b/src/app/qt/graphics/QtAngledLineItem.cpp @@ -8,6 +8,8 @@ QtAngledLineItem::QtAngledLineItem(QGraphicsItem* parent) : QGraphicsLineItem(parent) + , m_onBack(false) + , m_horizontalIn(false) { this->setAcceptHoverEvents(true); } @@ -38,6 +40,16 @@ void QtAngledLineItem::updateLine( this->setPen(QPen(QBrush(style.color.c_str()), style.width, Qt::SolidLine, Qt::RoundCap)); } +void QtAngledLineItem::setOnBack(bool back) +{ + m_onBack = back; +} + +void QtAngledLineItem::setHorizontalIn(bool horizontal) +{ + m_horizontalIn = horizontal; +} + QPainterPath QtAngledLineItem::shape() const { int w = m_style.arrowWidth / 2 + 1; @@ -185,23 +197,31 @@ QPolygon QtAngledLineItem::getPath() const const Vec4i& oR = m_ownerRect; const Vec4i& tR = m_targetRect; - Vec2f o[2] = { Vec2f(m_ownerParentRect.x, (oR.y + 2 * oR.w) / 3), Vec2f(m_ownerParentRect.z, (oR.y + 2 * oR.w) / 3) }; - Vec2f t[2] = { Vec2f(m_targetParentRect.x, (2 * tR.y + tR.w) / 3), Vec2f(m_targetParentRect.z, (2 * tR.y + tR.w) / 3) }; + Vec2f o[2] = { Vec2f(m_ownerParentRect.x, (2 * oR.y + oR.w) / 3), Vec2f(m_ownerParentRect.z, (2 * oR.y + oR.w) / 3) }; + Vec2f t[2] = { Vec2f(m_targetParentRect.x, (tR.y + 2 * tR.w) / 3), Vec2f(m_targetParentRect.z, (tR.y + 2 * tR.w) / 3) }; int io = -1; int it = -1; float dist = -1; - for (int i = 0; i < 2; i++) + if (m_onBack) { - for (int j = 0; j < 2; j++) + io = 1; + it = 1; + } + else + { + for (int i = 0; i < 2; i++) { - Vec2f diff = o[i] - t[j]; - if (dist < 0 || diff.getLength() < dist) + for (int j = 0; j < 2; j++) { - dist = diff.getLength(); - io = i; - it = j; + Vec2f diff = o[i] - t[j]; + if (dist < 0 || diff.getLength() < dist) + { + dist = diff.getLength(); + io = i; + it = j; + } } } } @@ -233,7 +253,11 @@ QPolygon QtAngledLineItem::getPath() const } } - if (it == io && ((it && tp.x() < op.x()) || (!it && tp.x() > op.x())) ) + if (it == io && ((it && tp.x() < op.x()) || (!it && tp.x() > op.x()))) + { + tp.setX(op.x()); + } + else if (it != io && m_horizontalIn) { tp.setX(op.x()); } @@ -242,10 +266,10 @@ QPolygon QtAngledLineItem::getPath() const op.setX(tp.x()); } - o[0] = Vec2f(oR.x, (oR.y + 2 * oR.w) / 3); - o[1] = Vec2f(oR.z, (oR.y + 2 * oR.w) / 3); - t[0] = Vec2f(tR.x, (2 * tR.y + tR.w) / 3); - t[1] = Vec2f(tR.z, (2 * tR.y + tR.w) / 3); + o[0] = Vec2f(oR.x, (2 * oR.y + oR.w) / 3); + o[1] = Vec2f(oR.z, (2 * oR.y + oR.w) / 3); + t[0] = Vec2f(tR.x, (tR.y + 2 * tR.w) / 3); + t[1] = Vec2f(tR.z, (tR.y + 2 * tR.w) / 3); if (o[io].y < t[it].y) { diff --git a/src/app/qt/graphics/QtAngledLineItem.h b/src/app/qt/graphics/QtAngledLineItem.h index 46ab6ddd..d98ff0bb 100644 --- a/src/app/qt/graphics/QtAngledLineItem.h +++ b/src/app/qt/graphics/QtAngledLineItem.h @@ -19,6 +19,9 @@ public: Vec4i ownerParentRect, Vec4i targetParentRect, GraphViewStyle::EdgeStyle style); + void setOnBack(bool back); + void setHorizontalIn(bool horizontal); + virtual QPainterPath shape() const; virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget); @@ -33,6 +36,9 @@ private: Vec4i m_targetParentRect; GraphViewStyle::EdgeStyle m_style; + + bool m_onBack; + bool m_horizontalIn; }; #endif // QT_ANGLED_LINE_ITEM_H diff --git a/src/app/qt/view/graphElements/QtGraphEdge.cpp b/src/app/qt/view/graphElements/QtGraphEdge.cpp index 64d5581b..4909fc1e 100644 --- a/src/app/qt/view/graphElements/QtGraphEdge.cpp +++ b/src/app/qt/view/graphElements/QtGraphEdge.cpp @@ -22,11 +22,16 @@ QtGraphEdge::QtGraphEdge( , m_target(target) , m_child(nullptr) , m_isActive(false) + , m_fromActive(false) + , m_toActive(false) , m_weight(weight) , m_direction(TokenComponentAggregation::DIRECTION_NONE) , m_mousePos(0.0f, 0.0f) , m_mouseMoved(false) { + m_fromActive = m_owner.lock()->getIsActive(); + m_toActive = m_target.lock()->getIsActive(); + this->updateLine(); } @@ -100,6 +105,16 @@ void QtGraphEdge::updateLine() owner->getBoundingRect(), target->getBoundingRect(), owner->getParentBoundingRect(), target->getParentBoundingRect(), style); + + if (m_fromActive && owner->getLastParent() == target->getLastParent()) + { + dynamic_cast(m_child)->setOnBack(true); + } + + if (m_toActive) + { + dynamic_cast(m_child)->setHorizontalIn(true); + } } this->setZValue(style.zValue); // Used to draw edges always on top of nodes. @@ -112,9 +127,11 @@ bool QtGraphEdge::getIsActive() const void QtGraphEdge::setIsActive(bool isActive) { - m_isActive = isActive; - - updateLine(); + if (m_isActive != isActive) + { + m_isActive = isActive; + updateLine(); + } } void QtGraphEdge::onClick() @@ -138,7 +155,7 @@ void QtGraphEdge::focusIn() void QtGraphEdge::focusOut() { - this->setIsActive(m_isActive); + updateLine(); } void QtGraphEdge::mousePressEvent(QGraphicsSceneMouseEvent* event) diff --git a/src/app/qt/view/graphElements/QtGraphEdge.h b/src/app/qt/view/graphElements/QtGraphEdge.h index 855bb5da..13282936 100644 --- a/src/app/qt/view/graphElements/QtGraphEdge.h +++ b/src/app/qt/view/graphElements/QtGraphEdge.h @@ -32,6 +32,7 @@ public: bool getIsActive() const; void setIsActive(bool isActive); + void setFromAndToActive(bool fromActive, bool toActive); void onClick(); @@ -57,6 +58,8 @@ private: QGraphicsLineItem* m_child; bool m_isActive; + bool m_fromActive; + bool m_toActive; size_t m_weight; TokenComponentAggregation::Direction m_direction; diff --git a/src/app/qt/view/graphElements/QtGraphNode.cpp b/src/app/qt/view/graphElements/QtGraphNode.cpp index 50bfce87..94229477 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.cpp +++ b/src/app/qt/view/graphElements/QtGraphNode.cpp @@ -61,6 +61,21 @@ QtGraphNode* QtGraphNode::getParent() const return m_parentNode.lock().get(); } +QtGraphNode* QtGraphNode::getLastParent() const +{ + QtGraphNode* node = const_cast(this); + while (true) + { + QtGraphNode* parent = dynamic_cast(node->parentItem()); + if (!parent) + { + break; + } + node = parent; + } + return node; +} + void QtGraphNode::setParent(std::weak_ptr parentNode) { m_parentNode = parentNode; @@ -134,18 +149,7 @@ Vec4i QtGraphNode::getBoundingRect() const Vec4i QtGraphNode::getParentBoundingRect() const { - const QtGraphNode* node = this; - while (true) - { - const QtGraphNode* parent = dynamic_cast(node->parentItem()); - if (!parent) - { - break; - } - node = parent; - - } - return node->getBoundingRect(); + return getLastParent()->getBoundingRect(); } void QtGraphNode::addOutEdge(const std::shared_ptr& edge) diff --git a/src/app/qt/view/graphElements/QtGraphNode.h b/src/app/qt/view/graphElements/QtGraphNode.h index 46feac21..b6e14a9e 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.h +++ b/src/app/qt/view/graphElements/QtGraphNode.h @@ -3,6 +3,8 @@ #include +#include "utility/math/Vector4.h" + #include "component/view/GraphViewStyle.h" class QFont; @@ -33,6 +35,7 @@ public: virtual ~QtGraphNode(); QtGraphNode* getParent() const; + QtGraphNode* getLastParent() const; void setParent(std::weak_ptr parentNode); std::list> getSubNodes() const; diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 5707b0c8..11a45b7b 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -35,8 +35,12 @@ add_files( add_files( LIB_FILES + component/controller/helper/BucketGrid.cpp + component/controller/helper/BucketGrid.h component/controller/helper/DummyEdge.h component/controller/helper/DummyNode.h + component/controller/helper/GraphLayouter.cpp + component/controller/helper/GraphLayouter.h component/controller/helper/GraphPostprocessor.cpp component/controller/helper/GraphPostprocessor.h component/controller/helper/SnippetMerger.cpp @@ -50,8 +54,6 @@ add_files( component/controller/FeatureController.h component/controller/GraphController.cpp component/controller/GraphController.h - component/controller/GraphLayouter.cpp - component/controller/GraphLayouter.h component/controller/RefreshController.cpp component/controller/RefreshController.h component/controller/SearchController.cpp diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 26dd2728..c1159d70 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -7,6 +7,7 @@ #include "component/controller/helper/DummyEdge.h" #include "component/controller/helper/DummyNode.h" +#include "component/controller/helper/GraphLayouter.h" #include "component/controller/helper/GraphPostprocessor.h" #include "component/view/GraphView.h" #include "component/view/GraphViewStyle.h" @@ -88,8 +89,7 @@ void GraphController::handleMessage(MessageGraphNodeBundleSplit* message) setActiveAndVisibility(utility::concat(m_activeNodeIds, m_activeEdgeIds)); layoutNesting(); - GraphLayouter::layoutSpectralPrototype(m_dummyNodes, m_dummyEdges); - GraphPostprocessor::doPostprocessing(m_dummyNodes); + layoutGraph(); buildGraph(message); } @@ -102,9 +102,9 @@ void GraphController::handleMessage(MessageGraphNodeExpand* message) node->expanded = message->expand; setActiveAndVisibility(utility::concat(m_activeNodeIds, m_activeEdgeIds)); - layoutNesting(); - GraphPostprocessor::doPostprocessing(m_dummyNodes); + layoutNesting(); + layoutGraph(); buildGraph(message); } @@ -179,8 +179,7 @@ void GraphController::createDummyGraphForTokenIds(const std::vector& tokenId bundleNodes(); layoutNesting(); - GraphLayouter::layoutSpectralPrototype(m_dummyNodes, m_dummyEdges); - GraphPostprocessor::doPostprocessing(m_dummyNodes); + layoutGraph(); m_graph = graph; } @@ -867,6 +866,14 @@ void GraphController::layoutToGrid(DummyNode& node) const } } +void GraphController::layoutGraph() +{ + // GraphLayouter::layoutSpectralPrototype(m_dummyNodes, m_dummyEdges); + // GraphPostprocessor::doPostprocessing(m_dummyNodes); + + GraphLayouter::layoutBucket(m_dummyNodes, m_dummyEdges, getView()->getViewSize()); +} + DummyNode* GraphController::findDummyNodeRecursive(std::vector& nodes, Id tokenId) const { for (DummyNode& node : nodes) diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 7c9f5a66..49062ea4 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -13,7 +13,6 @@ #include "utility/messaging/type/MessageGraphNodeMove.h" #include "component/controller/Controller.h" -#include "component/controller/GraphLayouter.h" #include "component/view/GraphView.h" #include "data/graph/token_component/TokenComponentAccess.h" #include "data/graph/token_component/TokenComponentAggregation.h" @@ -72,6 +71,8 @@ private: void addExpandToggleNode(DummyNode& node) const; void layoutToGrid(DummyNode& node) const; + void layoutGraph(); + DummyNode* findDummyNodeRecursive(std::vector& nodes, Id tokenId) const; DummyNode* findTopLevelDummyNodeRecursive(std::vector& nodes, Id tokenId) const; DummyNode* findDummyNodeAccessRecursive(std::vector& nodes, Id parentId, TokenComponentAccess::AccessType type) const; diff --git a/src/lib/component/controller/helper/BucketGrid.cpp b/src/lib/component/controller/helper/BucketGrid.cpp new file mode 100644 index 00000000..16e389b6 --- /dev/null +++ b/src/lib/component/controller/helper/BucketGrid.cpp @@ -0,0 +1,352 @@ +#include "component/controller/helper/BucketGrid.h" + +#include "component/controller/helper/DummyEdge.h" +#include "component/controller/helper/DummyNode.h" +#include "component/view/GraphViewStyle.h" + +Bucket::Bucket() + : i(0) + , j(0) + , m_width(0) + , m_height(0) +{ +} + +Bucket::Bucket(int i, int j) + : i(i) + , j(j) + , m_width(0) + , m_height(0) +{ +} + +int Bucket::getWidth() const +{ + return m_width; +} + +int Bucket::getHeight() const +{ + return m_height; +} + +bool Bucket::hasNode(DummyNode* node) const +{ + for (DummyNode* n : m_nodes) + { + if (node == n) + { + return true; + } + } + + return false; +} + +void Bucket::addNode(DummyNode* node) +{ + m_nodes.push_back(node); + + m_width = (node->size.x > m_width ? node->size.x : m_width); + m_height += node->size.y + GraphViewStyle::toGridGap(10); +} + +void Bucket::preLayout(Vec2i viewSize) +{ + int cols = m_height / viewSize.y + 1; + + int x = 0; + int y = 0; + int height = m_height / cols; + int width = 0; + + m_height = 0; + + for (DummyNode* node : m_nodes) + { + node->position.x = x; + node->position.y = y; + + y += node->size.y + GraphViewStyle::toGridGap(10); + + width = (node->size.x > width ? node->size.x : width); + m_height = (y > m_height ? y : m_height); + + if (y > height) + { + y = 0; + + x += width + GraphViewStyle::toGridGap(25); + width = 0; + } + } + + m_width = x + width; +} + +void Bucket::layout(int x, int y, int width, int height) +{ + int cx = GraphViewStyle::toGridOffset(x + (width - m_width) / 2); + int cy = GraphViewStyle::toGridOffset(y + (height - m_height) / 2); + + for (DummyNode* node : m_nodes) + { + node->position.x = node->position.x + cx; + node->position.y = node->position.y + cy; + } +} + + +void BucketGrid::layout(std::vector& nodes, const std::vector& edges, Vec2i viewSize) +{ + BucketGrid grid(viewSize); + grid.createBuckets(nodes, edges); + grid.layoutBuckets(); +} + +BucketGrid::BucketGrid(Vec2i viewSize) + : m_viewSize(viewSize) + , m_i1(0) + , m_j1(0) + , m_i2(0) + , m_j2(0) +{ + m_buckets[0][0] = Bucket(0, 0); +} + +void BucketGrid::createBuckets(std::vector& nodes, const std::vector& edges) +{ + if (!nodes.size()) + { + return; + } + + bool activeNodeAdded = false; + for (DummyNode& node : nodes) + { + if (node.hasActiveSubNode()) + { + addNode(&node); + activeNodeAdded = true; + } + } + + if (!activeNodeAdded) + { + addNode(&nodes[0]); + } + + std::vector remainingEdges; + for (const DummyEdge& edge : edges) + { + remainingEdges.push_back(&edge); + } + + size_t i = 0; + while (remainingEdges.size()) + { + const DummyEdge* edge = remainingEdges[i]; + + DummyNode* owner = findTopMostDummyNodeRecursive(nodes, edge->ownerId); + DummyNode* target = findTopMostDummyNodeRecursive(nodes, edge->targetId); + + bool removeEdge = false; + if (!owner || !target) + { + removeEdge = true; + } + else + { + bool horizontal = edge->data ? !edge->data->isType(Edge::EDGE_INHERITANCE) : true; + removeEdge = addNode(owner, target, horizontal); + } + + if (removeEdge) + { + remainingEdges.erase(remainingEdges.begin() + i); + } + else + { + i++; + } + + if (i == remainingEdges.size()) + { + i = 0; + } + } +} + +void BucketGrid::layoutBuckets() +{ + std::map widths; + std::map heights; + + for (int j = m_j1; j <= m_j2; j++) + { + for (int i = m_i1; i <= m_i2; i++) + { + Bucket* bucket = &m_buckets[j][i]; + + bucket->preLayout(m_viewSize); + + std::map::iterator wt = widths.find(i); + if (wt == widths.end() || wt->second < bucket->getWidth()) + { + widths[i] = bucket->getWidth(); + } + + std::map::iterator ht = heights.find(j); + if (ht == heights.end() || ht->second < bucket->getHeight()) + { + heights[j] = bucket->getHeight(); + } + } + } + + int y = 0; + for (int j = m_j1; j <= m_j2; j++) + { + int x = 0; + for (int i = m_i1; i <= m_i2; i++) + { + Bucket* bucket = &m_buckets[j][i]; + + bucket->layout(x, y, widths[i], heights[j]); + + x += widths[i] + GraphViewStyle::toGridGap(85); + } + + y += heights[j] + GraphViewStyle::toGridGap(45); + } +} + +DummyNode* BucketGrid::findTopMostDummyNodeRecursive(std::vector& nodes, Id tokenId, DummyNode* top) +{ + for (DummyNode& node : nodes) + { + DummyNode* t = (top ? top : &node); + + if (node.visible && node.tokenId == tokenId) + { + return t; + } + + DummyNode* result = findTopMostDummyNodeRecursive(node.subNodes, tokenId, t); + if (result != nullptr) + { + return result; + } + } + + return nullptr; +} + +void BucketGrid::addNode(DummyNode* node) +{ + Bucket* bucket = getBucket(0, 0); + bucket->addNode(node); +} + +bool BucketGrid::addNode(DummyNode* owner, DummyNode* target, bool horizontal) +{ + Bucket* ownerBucket = getBucket(owner); + Bucket* targetBucket = getBucket(target); + + if (!ownerBucket && !targetBucket) + { + return false; + } + else if (ownerBucket && targetBucket) + { + return true; + } + + if (ownerBucket) + { + int i = horizontal ? ownerBucket->i + 1 : ownerBucket->i; + int j = horizontal ? ownerBucket->j : ownerBucket->j - 1; + + Bucket* bucket = getBucket(i, j); + bucket->addNode(target); + } + else + { + int i = horizontal ? targetBucket->i - 1 : targetBucket->i; + int j = horizontal ? targetBucket->j : targetBucket->j + 1; + + Bucket* bucket = getBucket(i, j); + bucket->addNode(owner); + } + + return true; +} + +Bucket* BucketGrid::getBucket(int i, int j) +{ + bool newColumn = false; + bool newRow = false; + + if (i == m_i1 - 1) + { + m_i1 = i; + newColumn = true; + } + else if (i == m_i2 + 1) + { + m_i2 = i; + newColumn = true; + } + + if (newColumn) + { + for (int cj = m_j1; cj <= m_j2; cj++) + { + m_buckets[cj][i] = Bucket(i, cj); + } + } + + if (j == m_j1 - 1) + { + m_j1 = j; + newRow = true; + } + else if (j == m_j2 + 1) + { + m_j2 = j; + newRow = true; + } + + if (newRow) + { + for (int ci = m_i1; ci <= m_i2; ci++) + { + m_buckets[j][ci] = Bucket(ci, j); + } + } + + if (i >= m_i1 && i <= m_i2 && j >= m_j1 && j <= m_j2) + { + return &m_buckets[j][i]; + } + + return nullptr; +} + +Bucket* BucketGrid::getBucket(DummyNode* node) +{ + for (int j = m_j1; j <= m_j2; j++) + { + for (int i = m_i1; i <= m_i2; i++) + { + Bucket* bucket = &m_buckets[j][i]; + + if (bucket->hasNode(node)) + { + return bucket; + } + } + } + + return nullptr; +} diff --git a/src/lib/component/controller/helper/BucketGrid.h b/src/lib/component/controller/helper/BucketGrid.h new file mode 100644 index 00000000..b0e706df --- /dev/null +++ b/src/lib/component/controller/helper/BucketGrid.h @@ -0,0 +1,66 @@ +#ifndef BUCKET_GRID_H +#define BUCKET_GRID_H + +#include + +#include "utility/math/Vector2.h" +#include "utility/types.h" + +struct DummyEdge; +struct DummyNode; + +class Bucket +{ +public: + Bucket(); + Bucket(int i, int j); + + int getWidth() const; + int getHeight() const; + + bool hasNode(DummyNode* node) const; + void addNode(DummyNode* node); + + void preLayout(Vec2i viewSize); + void layout(int x, int y, int width, int height); + + int i; + int j; + +private: + int m_width; + int m_height; + + std::vector m_nodes; +}; + + +class BucketGrid +{ +public: + static void layout(std::vector& nodes, const std::vector& edges, Vec2i viewSize); + +private: + BucketGrid(Vec2i viewSize); + + void createBuckets(std::vector& nodes, const std::vector& edges); + void layoutBuckets(); + + DummyNode* findTopMostDummyNodeRecursive(std::vector& nodes, Id tokenId, DummyNode* top = nullptr); + + void addNode(DummyNode* node); + bool addNode(DummyNode* owner, DummyNode* target, bool horizontal); + + Bucket* getBucket(int i, int j); + Bucket* getBucket(DummyNode* node); + + Vec2i m_viewSize; + std::map> m_buckets; + + int m_i1; + int m_j1; + int m_i2; + int m_j2; +}; + +#endif // BUCKET_GRID_H diff --git a/src/lib/component/controller/GraphLayouter.cpp b/src/lib/component/controller/helper/GraphLayouter.cpp similarity index 93% rename from src/lib/component/controller/GraphLayouter.cpp rename to src/lib/component/controller/helper/GraphLayouter.cpp index a15926b7..be9ba675 100644 --- a/src/lib/component/controller/GraphLayouter.cpp +++ b/src/lib/component/controller/helper/GraphLayouter.cpp @@ -1,13 +1,13 @@ -#include "component/controller/GraphLayouter.h" +#include "component/controller/helper/GraphLayouter.h" #include #include #include -#include "utility/math/MatrixDynamicBase.h" - +#include "component/controller/helper/BucketGrid.h" #include "component/controller/helper/DummyEdge.h" #include "component/controller/helper/DummyNode.h" +#include "data/graph/Node.h" // for prototyping, remove when done #include "Eigen/Dense" @@ -64,6 +64,11 @@ void GraphLayouter::layoutSimpleRing(std::vector& nodes) } } +void GraphLayouter::layoutBucket(std::vector& nodes, const std::vector& edges, Vec2i viewSize) +{ + BucketGrid::layout(nodes, edges, viewSize); +} + void GraphLayouter::layoutSpectralPrototype(std::vector& nodes, const std::vector& edges) { if (nodes.size() < 2) @@ -153,7 +158,8 @@ void GraphLayouter::layoutSpectralPrototype(std::vector& nodes, const } } -MatrixDynamicBase GraphLayouter::buildLaplacianMatrix(const std::vector& nodes, const std::vector& edges) +MatrixDynamicBase GraphLayouter::buildLaplacianMatrix( + const std::vector& nodes, const std::vector& edges) { MatrixDynamicBase matrix(nodes.size(), nodes.size()); diff --git a/src/lib/component/controller/GraphLayouter.h b/src/lib/component/controller/helper/GraphLayouter.h similarity index 54% rename from src/lib/component/controller/GraphLayouter.h rename to src/lib/component/controller/helper/GraphLayouter.h index 2e3deeb9..45bb0cea 100644 --- a/src/lib/component/controller/GraphLayouter.h +++ b/src/lib/component/controller/helper/GraphLayouter.h @@ -3,8 +3,9 @@ #include -template -class MatrixDynamicBase; +#include "utility/math/MatrixDynamicBase.h" +#include "utility/math/Vector2.h" +#include "utility/types.h" struct DummyEdge; struct DummyNode; @@ -12,15 +13,16 @@ struct DummyNode; class GraphLayouter { public: - typedef void (*LayoutFunction)(std::vector&); - static void layoutSimpleRaster(std::vector& nodes); static void layoutSimpleRing(std::vector& nodes); + static void layoutBucket(std::vector& nodes, const std::vector& edges, Vec2i viewSize); + static void layoutSpectralPrototype(std::vector& nodes, const std::vector& edges); private: - static MatrixDynamicBase buildLaplacianMatrix(const std::vector& nodes, const std::vector& edges); + static MatrixDynamicBase buildLaplacianMatrix( + const std::vector& nodes, const std::vector& edges); }; #endif // GRAPH_LAYOUTER_H diff --git a/src/lib/component/view/GraphViewStyle.cpp b/src/lib/component/view/GraphViewStyle.cpp index 54c3f11e..91e59768 100644 --- a/src/lib/component/view/GraphViewStyle.cpp +++ b/src/lib/component/view/GraphViewStyle.cpp @@ -484,9 +484,14 @@ GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType typ return style; } -size_t GraphViewStyle::toGridSize(size_t x) +int GraphViewStyle::toGridOffset(int x) { - size_t r = s_gridCellSize; + if (x < 1) + { + return 0; + } + + int r = 0; while (r < x - 1) { @@ -496,8 +501,28 @@ size_t GraphViewStyle::toGridSize(size_t x) return r; } -size_t GraphViewStyle::s_gridCellSize = 5; -size_t GraphViewStyle::s_gridCellPadding = 10; +int GraphViewStyle::toGridSize(int x) +{ + if (x < 1) + { + return 0; + } + + return s_gridCellSize + toGridOffset(x - s_gridCellSize); +} + +int GraphViewStyle::toGridGap(int x) +{ + if (x < 1) + { + return 0; + } + + return s_gridCellPadding + toGridOffset(x - s_gridCellPadding); +} + +int GraphViewStyle::s_gridCellSize = 5; +int GraphViewStyle::s_gridCellPadding = 10; std::map GraphViewStyle::s_charWidths; std::map GraphViewStyle::s_charHeights; diff --git a/src/lib/component/view/GraphViewStyle.h b/src/lib/component/view/GraphViewStyle.h index bc221f92..02e0f0d7 100644 --- a/src/lib/component/view/GraphViewStyle.h +++ b/src/lib/component/view/GraphViewStyle.h @@ -5,7 +5,6 @@ #include #include "utility/math/Vector2.h" -#include "utility/math/Vector4.h" #include "data/graph/Node.h" #include "data/graph/token_component/TokenComponentAccess.h" @@ -116,10 +115,12 @@ public: static EdgeStyle getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused); - static size_t toGridSize(size_t x); + static int toGridOffset(int x); + static int toGridSize(int x); + static int toGridGap(int x); - static size_t s_gridCellSize; - static size_t s_gridCellPadding; + static int s_gridCellSize; + static int s_gridCellPadding; private: static std::map s_charWidths;