Skip to content

Commit a6d0e71

Browse files
committed
enhance TreeVisualiser to compute node positions using BFS; simplify drawTree method; improve rendering logic for better visual representation
1 parent 13cb919 commit a6d0e71

File tree

2 files changed

+90
-42
lines changed

2 files changed

+90
-42
lines changed

parser_gui/Widgets/include/TreeVisualiser.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#include <QVBoxLayout>
66
#include <QLabel>
77
#include <QPainter>
8+
#include <QQueue>
9+
#include <QMap>
10+
811

912
#include "Node.h"
1013

@@ -17,6 +20,7 @@ namespace Tiny::Widgets {
1720
void paintEvent(QPaintEvent *event) override;
1821
public:
1922
TreeVisualiser(QWidget *parent = nullptr);
23+
void drawTree(QPainter *painter, Node *root);
2024
void drawTree(QPainter *painter, Node *node, int x, int y, int availableWidth, int currentLevel);
2125

2226
int calculateTreeWidth(Node* node) {
@@ -57,9 +61,50 @@ namespace Tiny::Widgets {
5761
return false;
5862
}
5963
}
64+
65+
void computePositions() {
66+
positions.clear();
67+
if (!root) return;
68+
69+
// BFS to gather nodes by level
70+
QQueue<Node*> queue;
71+
queue.enqueue(root);
72+
73+
QMap<int, QList<Node*>> levelMap;
74+
int maxLevel = 0;
75+
76+
while (!queue.isEmpty()) {
77+
Node* current = queue.dequeue();
78+
int lvl = current->getLevel();
79+
maxLevel = qMax(maxLevel, lvl);
80+
levelMap[lvl].append(current);
81+
82+
for (Node* child : current->getChildren()) {
83+
queue.enqueue(child);
84+
}
85+
}
86+
87+
// Now assign positions level by level
88+
int W = width(); // widget width
89+
for (int lvl = 0; lvl <= maxLevel; lvl++) {
90+
QList<Node*>& nodesAtLevel = levelMap[lvl];
91+
int N = nodesAtLevel.size();
92+
if (N == 0) continue;
93+
94+
int spacing = W / (N + 1);
95+
int yPos = 50 + lvl * 100; // each level 100px apart vertically
96+
for (int i = 0; i < N; i++) {
97+
Node* n = nodesAtLevel[i];
98+
int xPos = spacing * (i + 1);
99+
positions[n] = QPoint(xPos, yPos);
100+
}
101+
}
102+
}
60103
private:
61104
Node *root = nullptr;
62105
qreal zoomFactor = 1.0;
106+
QMap<Node*, QPoint> positions;
107+
63108
}; // class TreeVisualiser
64109
} // namespace Tiny::Widgets
65110

parser_gui/Widgets/src/TreeVisualiser.cpp

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,86 +11,89 @@ void TreeVisualiser::paintEvent(QPaintEvent *event) {
1111
QPainter painter(this);
1212
painter.setRenderHint(QPainter::Antialiasing);
1313

14-
// Clear background
1514
painter.fillRect(rect(), QColor(240, 240, 240));
1615
painter.scale(zoomFactor, zoomFactor);
1716

18-
// Calculate the total width needed for the tree
19-
int treeWidth = calculateTreeWidth(root);
17+
// Compute positions before drawing
18+
computePositions();
2019

21-
// Draw the entire tree
22-
drawTree(&painter, root, width() / 2, 50, treeWidth, root->getLevel());
20+
// Draw the entire tree now
21+
drawTree(&painter, root);
2322
}
2423

2524
TreeVisualiser::TreeVisualiser(QWidget *parent) : QWidget(parent) {
2625

2726
}
2827

29-
void TreeVisualiser::drawTree(QPainter *painter, Node *node, int x, int y, int availableWidth, int level) {
28+
void TreeVisualiser::drawTree(QPainter *painter, Node *node)
29+
{
3030
if (!node) return;
3131

32-
// Draw the current node
32+
QPoint pos = positions[node];
33+
34+
// Draw this node
3335
painter->setPen(QPen(Qt::black, 2));
3436
painter->setBrush(QColor(70, 130, 180)); // Steel Blue
3537

3638
if (isOval(node->getType())) {
37-
painter->drawEllipse(x - 20, y - 20, 40, 40); // Node as an oval
39+
painter->drawEllipse(pos.x() - 20, pos.y() - 20, 40, 40);
3840
} else {
39-
painter->drawRect(x - 40, y - 20, 80, 40); // Node as a rectangle
41+
painter->drawRect(pos.x() - 40, pos.y() - 20, 80, 40);
4042
}
4143

42-
// Draw node value
4344
painter->setPen(Qt::white);
4445
QString nodeText;
4546
if (!hasValue(node->getType())) {
4647
nodeText = node->getNodeTypeString().toString() + "\n(" + node->getValue() + ")";
4748
} else {
4849
nodeText = node->getNodeTypeString().toString();
4950
}
50-
painter->drawText(QRect(x - 40, y - 20, 80, 40),
51-
Qt::AlignCenter | Qt::TextWordWrap, nodeText);
5251

53-
if (node->getChildren().empty()) return;
54-
55-
// Calculate the total width and starting positions for children
56-
int childCount = node->getChildren().size();
57-
std::vector<int> childWidths;
58-
int totalChildWidth = 0;
52+
painter->drawText(QRect(pos.x() - 40, pos.y() - 20, 80, 40),
53+
Qt::AlignCenter | Qt::TextWordWrap, nodeText);
5954

60-
// Calculate width for each child's subtree
55+
// Draw lines to children
56+
painter->setPen(QPen(Qt::black, 2));
6157
for (Node* child : node->getChildren()) {
62-
int childWidth = calculateTreeWidth(child);
63-
childWidths.push_back(childWidth);
64-
totalChildWidth += childWidth;
58+
QPoint childPos = positions[child];
59+
painter->drawLine(pos.x(), pos.y() + 20, childPos.x(), childPos.y() - 20);
60+
drawTree(painter, child); // Recursively draw children
6561
}
6662

67-
// Vertical and horizontal spacing between nodes
68-
int verticalSpacing = 100;
69-
int horizontalSpacing = 100;
63+
}
7064

71-
// Starting X position for the first child node
72-
int startX = x - totalChildWidth / 2;
65+
void TreeVisualiser::drawTree(QPainter *painter, Node *node, int x, int y, int availableWidth, int level) {
66+
if (!node) return;
7367

74-
// Draw children and their subtrees
75-
for (size_t i = 0; i < node->getChildren().size(); ++i) {
76-
Node* child = node->getChildren()[i];
77-
int childWidth = childWidths[i];
68+
QPoint pos = positions[node];
7869

79-
// Calculate position for each child
80-
int childX = startX + childWidth / 2 - 20;
81-
int childY = y + verticalSpacing;
70+
// Draw this node
71+
painter->setPen(QPen(Qt::black, 2));
72+
painter->setBrush(QColor(70, 130, 180)); // Steel Blue
8273

83-
// Draw connection line to child node
84-
painter->setPen(QPen(Qt::black, 2));
85-
int yLineOffset = (child->getLevel() == node->getLevel())? 0 : 20;
74+
if (isOval(node->getType())) {
75+
painter->drawEllipse(pos.x() - 20, pos.y() - 20, 40, 40);
76+
} else {
77+
painter->drawRect(pos.x() - 40, pos.y() - 20, 80, 40);
78+
}
8679

87-
painter->drawLine(x, y + 20, childX, childY);
80+
painter->setPen(Qt::white);
81+
QString nodeText;
82+
if (!hasValue(node->getType())) {
83+
nodeText = node->getNodeTypeString().toString() + "\n(" + node->getValue() + ")";
84+
} else {
85+
nodeText = node->getNodeTypeString().toString();
86+
}
8887

89-
// Recursively draw the child node
90-
drawTree(painter, child, childX, childY, childWidth, child->getLevel());
88+
painter->drawText(QRect(pos.x() - 40, pos.y() - 20, 80, 40),
89+
Qt::AlignCenter | Qt::TextWordWrap, nodeText);
9190

92-
// Update the starting position for the next child
93-
startX += childWidth + horizontalSpacing;
91+
// Draw lines to children
92+
painter->setPen(QPen(Qt::black, 2));
93+
for (Node* child : node->getChildren()) {
94+
QPoint childPos = positions[child];
95+
painter->drawLine(pos.x(), pos.y() + 20, childPos.x(), childPos.y() - 20);
96+
drawTree(painter, child); // Recursively draw children
9497
}
9598
}
9699

0 commit comments

Comments
 (0)