broadfield-dev commited on
Commit
ccd3bcf
·
verified ·
1 Parent(s): ba7e5cb

Update static/canvas.js

Browse files
Files changed (1) hide show
  1. static/canvas.js +47 -83
static/canvas.js CHANGED
@@ -60,13 +60,15 @@ document.getElementById('btnVisualize').addEventListener('click', () => {
60
  if(data.error) {
61
  log(data.error, 'error');
62
  } else {
63
- drawGraph(data);
64
- log(`Graph generated: ${data.nodes.length} nodes, ${data.connections.length} edges.`);
 
65
  }
66
  })
67
  .catch(err => log('Network error', 'error'));
68
  });
69
 
 
70
  document.getElementById('btnDataset').addEventListener('click', () => {
71
  const code = document.getElementById('codeInput').value;
72
  log('Generating vector dataset entry...');
@@ -87,130 +89,93 @@ document.getElementById('btnDataset').addEventListener('click', () => {
87
  });
88
 
89
  // Drawing Logic
90
- function drawGraph(data) {
91
  layer.destroyChildren();
92
 
93
  if (data.nodes.length === 0) return;
94
 
 
 
 
95
  const nodeMap = {};
96
  const X_OFFSET = 100;
97
  const Y_START = 50;
98
  const INDENT_WIDTH = 60;
99
  const ROW_HEIGHT = 80;
100
 
101
- // Node Colors based on Category
102
  const colors = {
103
- 'function': '#a29bfe', // Purple
104
- 'class': '#e84393', // Pink
105
- 'if': '#fab1a0', // Peach
106
- 'for': '#fdcb6e', // Yellow
107
- 'while': '#fdcb6e',
108
- 'return': '#55efc4', // Green
109
- 'assigned_variable': '#74b9ff', // Blue
110
- 'import': '#b2bec3' // Grey
111
  };
112
 
113
- // Draw Nodes
114
  data.nodes.forEach((node, index) => {
115
- // Layout: Simple Waterfall with Indentation
116
- const x = X_OFFSET + (node.level * INDENT_WIDTH);
117
  const y = Y_START + (index * ROW_HEIGHT);
118
 
119
- const group = new Konva.Group({
120
- x: x,
121
- y: y,
122
- draggable: false // Keep rigid for structure visualization
123
- });
124
 
125
- // Box
126
  const rect = new Konva.Rect({
127
- width: 200,
128
- height: 50,
129
  fill: '#2d3436',
130
  stroke: colors[node.type] || '#636e72',
131
- strokeWidth: 2,
132
- cornerRadius: 8,
133
- shadowColor: 'black',
134
- shadowBlur: 10,
135
- shadowOpacity: 0.3
136
  });
137
 
138
- // Label
139
  const text = new Konva.Text({
140
- x: 10,
141
- y: 10,
142
- text: node.label,
143
- fontSize: 14,
144
- fontFamily: 'JetBrains Mono',
145
- fill: '#fff',
146
- width: 180,
147
- ellipsis: true
148
  });
149
 
150
- // Vector Info (Mini UI)
151
  const vecText = new Konva.Text({
152
- x: 10,
153
- y: 32,
154
- text: `V:[${node.vector[0]}, ${node.vector[1]}...]`,
155
- fontSize: 10,
156
- fontFamily: 'JetBrains Mono',
157
- fill: '#636e72'
158
  });
159
 
160
  group.add(rect);
161
  group.add(text);
162
  group.add(vecText);
163
 
164
- // Interaction: Hover to see Source
165
- group.on('mouseover', () => {
166
- document.body.style.cursor = 'pointer';
167
- rect.fill('#353b48');
168
- layer.draw();
169
- });
170
- group.on('mouseout', () => {
171
- document.body.style.cursor = 'default';
172
- rect.fill('#2d3436');
173
- layer.draw();
174
- });
175
-
176
- // Click to log source code
177
  group.on('click', () => {
178
- log(`Node Source:\n${node.source}`);
 
 
 
 
 
 
179
  });
180
 
 
 
 
 
181
  layer.add(group);
182
- nodeMap[node.id] = { group, x, y };
183
  });
184
 
185
- // Draw Connections (Parent -> Child)
186
  data.connections.forEach(conn => {
187
- const fromNode = nodeMap[conn.from];
188
- const toNode = nodeMap[conn.to];
 
189
 
190
  if (fromNode && toNode) {
191
- // Bezier Connector
192
- const startX = fromNode.x + 20; // Start from left side for tree-like feel
193
- const startY = fromNode.y + 50; // Bottom of parent
194
- const endX = toNode.x + 20; // Top of child
195
  const endY = toNode.y;
196
 
197
- // Draw clean elbow lines for code structure
198
- const points = [
199
- startX, startY,
200
- startX, endY - 10,
201
- endX, endY - 10,
202
- endX, endY
203
- ];
204
-
205
  const line = new Konva.Line({
206
- points: points,
207
- stroke: '#636e72',
208
- strokeWidth: 2,
209
- tension: 0.2,
210
- opacity: 0.6
211
  });
212
-
213
- // Move lines to bottom so nodes are on top
214
  layer.add(line);
215
  line.moveToBottom();
216
  }
@@ -218,13 +183,12 @@ function drawGraph(data) {
218
 
219
  layer.batchDraw();
220
 
221
- // Auto-center camera if nodes exist
222
  if (data.nodes.length > 0) {
223
- const firstNode = nodeMap[data.nodes[0].id];
224
  stage.x(50);
225
  stage.y(50);
226
  }
227
  }
228
 
 
229
  // Initial Call
230
  setTimeout(() => document.getElementById('btnVisualize').click(), 500);
 
60
  if(data.error) {
61
  log(data.error, 'error');
62
  } else {
63
+ // PASS 'code' HERE so we can slice it later
64
+ drawGraph(data, code);
65
+ log(`Graph generated: ${data.nodes.length} nodes.`);
66
  }
67
  })
68
  .catch(err => log('Network error', 'error'));
69
  });
70
 
71
+
72
  document.getElementById('btnDataset').addEventListener('click', () => {
73
  const code = document.getElementById('codeInput').value;
74
  log('Generating vector dataset entry...');
 
89
  });
90
 
91
  // Drawing Logic
92
+ function drawGraph(data, fullSourceCode) {
93
  layer.destroyChildren();
94
 
95
  if (data.nodes.length === 0) return;
96
 
97
+ // OPTIMIZATION: Split code once into lines for O(1) access
98
+ const sourceLines = fullSourceCode.split('\n');
99
+
100
  const nodeMap = {};
101
  const X_OFFSET = 100;
102
  const Y_START = 50;
103
  const INDENT_WIDTH = 60;
104
  const ROW_HEIGHT = 80;
105
 
 
106
  const colors = {
107
+ 'function': '#a29bfe', 'class': '#e84393', 'if': '#fab1a0',
108
+ 'for': '#fdcb6e', 'while': '#fdcb6e', 'return': '#55efc4',
109
+ 'assigned_variable': '#74b9ff', 'import': '#b2bec3'
 
 
 
 
 
110
  };
111
 
 
112
  data.nodes.forEach((node, index) => {
113
+ // Use short keys: node.lvl instead of node.level
114
+ const x = X_OFFSET + (node.lvl * INDENT_WIDTH);
115
  const y = Y_START + (index * ROW_HEIGHT);
116
 
117
+ const group = new Konva.Group({ x: x, y: y, draggable: false });
 
 
 
 
118
 
 
119
  const rect = new Konva.Rect({
120
+ width: 200, height: 50,
 
121
  fill: '#2d3436',
122
  stroke: colors[node.type] || '#636e72',
123
+ strokeWidth: 2, cornerRadius: 8,
124
+ shadowColor: 'black', shadowBlur: 10, shadowOpacity: 0.3
 
 
 
125
  });
126
 
 
127
  const text = new Konva.Text({
128
+ x: 10, y: 10,
129
+ text: node.lbl, // Use short key: lbl
130
+ fontSize: 14, fontFamily: 'JetBrains Mono', fill: '#fff',
131
+ width: 180, ellipsis: true
 
 
 
 
132
  });
133
 
 
134
  const vecText = new Konva.Text({
135
+ x: 10, y: 32,
136
+ text: `V:[${node.vec[0]}, ${node.vec[2]}...]`, // Use short key: vec
137
+ fontSize: 10, fontFamily: 'JetBrains Mono', fill: '#636e72'
 
 
 
138
  });
139
 
140
  group.add(rect);
141
  group.add(text);
142
  group.add(vecText);
143
 
144
+ // OPTIMIZATION: Reconstruct source on click
 
 
 
 
 
 
 
 
 
 
 
 
145
  group.on('click', () => {
146
+ // AST line numbers are 1-based, array is 0-based
147
+ const startLine = node.loc[0] - 1;
148
+ const endLine = node.loc[1];
149
+
150
+ // Slice the specific lines from the main array
151
+ const snippet = sourceLines.slice(startLine, endLine).join('\n');
152
+ log(`Node Source:\n${snippet}`);
153
  });
154
 
155
+ // Hover effects
156
+ group.on('mouseover', () => { document.body.style.cursor = 'pointer'; rect.fill('#353b48'); layer.draw(); });
157
+ group.on('mouseout', () => { document.body.style.cursor = 'default'; rect.fill('#2d3436'); layer.draw(); });
158
+
159
  layer.add(group);
160
+ nodeMap[node.id] = { x, y };
161
  });
162
 
163
+ // Draw Connections
164
  data.connections.forEach(conn => {
165
+ // Use short keys: f (from), t (to)
166
+ const fromNode = nodeMap[conn.f];
167
+ const toNode = nodeMap[conn.t];
168
 
169
  if (fromNode && toNode) {
170
+ const startX = fromNode.x + 20;
171
+ const startY = fromNode.y + 50;
172
+ const endX = toNode.x + 20;
 
173
  const endY = toNode.y;
174
 
 
 
 
 
 
 
 
 
175
  const line = new Konva.Line({
176
+ points: [startX, startY, startX, endY - 10, endX, endY - 10, endX, endY],
177
+ stroke: '#636e72', strokeWidth: 2, tension: 0.2, opacity: 0.6
 
 
 
178
  });
 
 
179
  layer.add(line);
180
  line.moveToBottom();
181
  }
 
183
 
184
  layer.batchDraw();
185
 
 
186
  if (data.nodes.length > 0) {
 
187
  stage.x(50);
188
  stage.y(50);
189
  }
190
  }
191
 
192
+
193
  // Initial Call
194
  setTimeout(() => document.getElementById('btnVisualize').click(), 500);