1
+ import { ViewColumn , window } from "vscode" ;
2
+
3
+ type Styles = { [ key : string ] : string } ;
4
+
5
+ export interface Element {
6
+ data : { id : string , label : string } ,
7
+ style : Styles
8
+ }
9
+
10
+ export interface Edge {
11
+ data : { id : string , source : string , target : string }
12
+ }
13
+
14
+ interface NewNode {
15
+ label : string ,
16
+ styles ?: Styles ,
17
+ parent ?: string ,
18
+ data ?: any ;
19
+ }
20
+
21
+ const randomId = ( ) => Math . random ( ) . toString ( 36 ) . substring ( 7 ) ;
22
+
23
+ export class CytoscapeGraph {
24
+ private elementData = new Map < string , any > ( ) ;
25
+ private elements : Element [ ] = [ ] ;
26
+ private edges : Edge [ ] = [ ] ;
27
+
28
+ constructor ( ) { }
29
+
30
+ addNode ( node : NewNode ) : string {
31
+ const id = randomId ( ) ; // TODO: is this unique enough?
32
+
33
+ if ( node . data ) {
34
+ this . elementData . set ( id , node . data ) ;
35
+ }
36
+
37
+ this . elements . push ( {
38
+ data : { id, label : node . label } ,
39
+ style : node . styles || { }
40
+ } ) ;
41
+
42
+ if ( node . parent ) {
43
+ this . edges . push ( {
44
+ data : { id : randomId ( ) , source : node . parent , target : id }
45
+ } ) ;
46
+ }
47
+
48
+ return id ;
49
+ }
50
+
51
+ createView ( title : string ) {
52
+ const webview = window . createWebviewPanel ( `c` , title , { viewColumn : ViewColumn . One } , { enableScripts : true , retainContextWhenHidden : true } ) ;
53
+ webview . webview . html = this . getHtml ( ) ;
54
+
55
+ return webview ;
56
+ }
57
+
58
+ private getHtml ( ) : string {
59
+ return /*html*/ `
60
+ <!DOCTYPE html>
61
+ <html lang="en">
62
+
63
+ <head>
64
+ <meta charset="UTF-8">
65
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
66
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.23.0/cytoscape.min.js"></script>
67
+ <style>
68
+ /* html,
69
+ body {
70
+ margin: 0;
71
+ padding: 0;
72
+ height: 100%;
73
+ width: 100%;
74
+ overflow: hidden;
75
+ } */
76
+
77
+ .diagram-container {
78
+ position: absolute;
79
+ top: 0;
80
+ left: 0;
81
+ width: 100%;
82
+ height: 100%;
83
+ border: none;
84
+ margin: 0;
85
+ }
86
+ </style>
87
+ </head>
88
+
89
+ <body>
90
+ <div class="diagram-container" id="diagramContainer"></div>
91
+
92
+ <script>
93
+ document.addEventListener("DOMContentLoaded", function () {
94
+ // Initialize Cytoscape
95
+ const cy = cytoscape({
96
+ container: document.getElementById('diagramContainer'),
97
+
98
+ elements: ${ JSON . stringify ( [ ...this . elements , ...this . edges ] ) } ,
99
+
100
+ style: [
101
+ {
102
+ selector: 'node',
103
+ style: {
104
+ 'width': '120px',
105
+ 'height': '60px',
106
+ 'background-color': 'var(--vscode-list-activeSelectionBackground)',
107
+ 'color': 'var(--vscode-list-activeSelectionForeground)',
108
+ 'label': 'data(label)',
109
+ 'text-valign': 'center',
110
+ 'text-halign': 'center',
111
+ 'font-size': '14px',
112
+ 'text-wrap': 'wrap',
113
+ 'text-max-width': '100px'
114
+ }
115
+ },
116
+ {
117
+ selector: 'edge',
118
+ style: {
119
+ 'width': 2,
120
+ 'line-color': '#5c96bc',
121
+ 'target-arrow-color': '#5c96bc',
122
+ 'target-arrow-shape': 'triangle',
123
+ 'curve-style': 'bezier'
124
+ }
125
+ }
126
+ ],
127
+
128
+ // Layout options
129
+ layout: {
130
+ name: 'breadthfirst',
131
+ directed: true, // Directional tree
132
+ padding: 10, // Padding around the graph
133
+ spacingFactor: 1.5 // Spacing between nodes
134
+ }
135
+ });
136
+
137
+ // Add click event to show alert for nodes
138
+ cy.on('tap', 'node', function (evt) {
139
+ const node = evt.target;
140
+ console.log("You clicked: " + node.data('label'));
141
+ });
142
+ });
143
+ </script>
144
+ </body>
145
+
146
+ </html>
147
+ ` ;
148
+ }
149
+ }
0 commit comments