1
+ import { Component } from "@src" ;
2
+
3
+ export class DGMLManager {
4
+
5
+ public createNewDirectedGraph ( domImpl : DOMImplementation , direction : string , layout : string , zoomLevel : string ) {
6
+ let xmlDoc : Document = domImpl . createDocument ( '' , null , null ) ;
7
+ const root = xmlDoc . createElement ( "DirectedGraph" ) ;
8
+ root . setAttribute ( "GraphDirection" , direction ) ;
9
+ root . setAttribute ( "Layout" , layout ) ;
10
+ root . setAttribute ( "ZoomLevel" , zoomLevel ) ;
11
+ root . setAttribute ( "xmlns" , "http://schemas.microsoft.com/vs/2009/dgml" ) ;
12
+ xmlDoc . appendChild ( root ) ;
13
+ return xmlDoc ;
14
+ }
15
+
16
+ private addNodeToRoot ( xmlDoc : Document , tagName : string ) : Element | null {
17
+ const root = xmlDoc . documentElement ;
18
+ const elements = root . getElementsByTagName ( tagName ) ;
19
+ let nodeElement : Element ;
20
+ if ( elements . length === 0 ) {
21
+ nodeElement = xmlDoc . createElement ( tagName ) ;
22
+ root . appendChild ( nodeElement ) ;
23
+ return nodeElement ;
24
+ }
25
+ else {
26
+ const exitingNode = elements . item ( 0 ) ;
27
+ return exitingNode ;
28
+ }
29
+ }
30
+
31
+ private addNode ( element : Element | null , nodeElement : Element , attribute : string = 'Id' ) {
32
+ if ( element !== null ) {
33
+ let nodeAlreadyAdded = false ;
34
+ if ( element . childNodes . length > 0 ) {
35
+ for ( let i = 0 ; i < element . childNodes . length ; i ++ ) {
36
+ let node = element . childNodes [ i ] ;
37
+ if ( node . nodeType === 1 && ( node as Element ) . hasAttribute ( attribute ) &&
38
+ ( node as Element ) . getAttribute ( attribute ) ?. toLowerCase ( ) === nodeElement . getAttribute ( attribute ) ?. toLowerCase ( ) ) {
39
+ nodeAlreadyAdded = true ;
40
+ }
41
+ } ;
42
+ }
43
+ if ( ! nodeAlreadyAdded ) {
44
+ element . appendChild ( nodeElement ) ;
45
+ }
46
+ }
47
+ }
48
+
49
+ private addLinkNode ( xmlDoc : Document , element : Element | null , source : string , target : string ) {
50
+ if ( element !== null ) {
51
+ let nodeAlreadyAdded = false ;
52
+ if ( element . childNodes . length > 0 ) {
53
+ for ( let i = 0 ; i < element . childNodes . length ; i ++ ) {
54
+ let node = element . childNodes [ i ] ;
55
+ if ( node . nodeType === 1 &&
56
+ ( node as Element ) . hasAttribute ( "Source" ) &&
57
+ ( node as Element ) . hasAttribute ( "Target" ) &&
58
+ ( node as Element ) . getAttribute ( "Source" ) ?. toLowerCase ( ) === source . toLowerCase ( ) &&
59
+ ( node as Element ) . getAttribute ( "Target" ) ?. toLowerCase ( ) === target . toLowerCase ( ) ) {
60
+ nodeAlreadyAdded = true ;
61
+ }
62
+ }
63
+ }
64
+ if ( ! nodeAlreadyAdded ) {
65
+ const linkElement = xmlDoc . createElement ( "Link" ) ;
66
+ linkElement . setAttribute ( "Source" , source ) ;
67
+ linkElement . setAttribute ( "Target" , target ) ;
68
+ element . appendChild ( linkElement ) ;
69
+ }
70
+ }
71
+ }
72
+
73
+ public addNodesAndLinks ( xmlDoc : Document , componentHash : { [ selector : string ] : Component ; } ) {
74
+ const nodesElement = this . addNodeToRoot ( xmlDoc , "Nodes" ) ;
75
+ const linksElement = this . addNodeToRoot ( xmlDoc , "Links" ) ;
76
+ for ( let selector in componentHash ) {
77
+ const component = componentHash [ selector ] ;
78
+ if ( component . isRoot ) {
79
+ this . generateDirectedGraphNodesXml ( xmlDoc , component . subComponents , component , true , nodesElement ) ;
80
+ this . generateDirectedGraphLinksXml ( xmlDoc , component . subComponents , selector , "" , linksElement ) ;
81
+ }
82
+ }
83
+ }
84
+
85
+ private generateDirectedGraphNodesXml ( xmlDoc : Document , components : Component [ ] , component : Component , isRoot : boolean , nodesElement : Element | null ) {
86
+ const nodeElement = xmlDoc . createElement ( "Node" ) ;
87
+ nodeElement . setAttribute ( "ComponentFilename" , component . tsFilename ) ;
88
+ nodeElement . setAttribute ( "Label" , component . selector ) ;
89
+ nodeElement . setAttribute ( "Id" , component . selector ) ;
90
+ if ( isRoot ) {
91
+ nodeElement . setAttribute ( "Category" , "RootComponent" ) ;
92
+ }
93
+ this . addNode ( nodesElement , nodeElement ) ;
94
+ if ( components . length > 0 ) {
95
+ components . forEach ( ( subComponent ) => {
96
+ this . generateDirectedGraphNodesXml ( xmlDoc , subComponent . subComponents , subComponent , subComponent . isRoot , nodesElement ) ;
97
+ } ) ;
98
+ }
99
+ }
100
+
101
+ private generateDirectedGraphLinksXml ( xmlDoc : Document , subComponents : Component [ ] , displayName : string , parentDisplayName : string , linksElement : Element | null ) {
102
+ if ( parentDisplayName . length > 0 ) {
103
+ this . addLinkNode ( xmlDoc , linksElement , parentDisplayName , displayName ) ;
104
+ }
105
+ if ( subComponents . length > 0 ) {
106
+ subComponents . forEach ( ( subComponent ) => {
107
+ this . generateDirectedGraphLinksXml ( xmlDoc , subComponent . subComponents , subComponent . selector , displayName , linksElement ) ;
108
+ } ) ;
109
+ }
110
+ }
111
+
112
+ public addCategory ( xmlDoc : Document , id : string , label : string , backgroundColor : string ) {
113
+ const categoriesElement = this . addNodeToRoot ( xmlDoc , "Categories" ) ;
114
+ const categoryElement = xmlDoc . createElement ( "Category" ) ;
115
+ categoryElement . setAttribute ( "Id" , id ) ;
116
+ categoryElement . setAttribute ( "Label" , label ) ;
117
+ categoryElement . setAttribute ( "Background" , backgroundColor ) ;
118
+ categoryElement . setAttribute ( "IsTag" , "True" ) ;
119
+ this . addNode ( categoriesElement , categoryElement ) ;
120
+ }
121
+
122
+ public addProperties ( xmlDoc : Document ) {
123
+ const propertiesElement = this . addNodeToRoot ( xmlDoc , "Properties" ) ;
124
+ this . addProperty ( xmlDoc , propertiesElement , "ComponentFilename" , "System.String" ) ;
125
+ this . addProperty ( xmlDoc , propertiesElement , "Background" , "System.Windows.Media.Brush" ) ;
126
+ this . addProperty ( xmlDoc , propertiesElement , "GraphDirection" , "Microsoft.VisualStudio.Diagrams.Layout.LayoutOrientation" ) ;
127
+ this . addProperty ( xmlDoc , propertiesElement , "GroupLabel" , "System.String" ) ;
128
+ this . addProperty ( xmlDoc , propertiesElement , "IsTag" , "System.Boolean" ) ;
129
+ this . addProperty ( xmlDoc , propertiesElement , "Label" , "System.String" ) ;
130
+ this . addProperty ( xmlDoc , propertiesElement , "Layout" , "System.String" ) ;
131
+ this . addProperty ( xmlDoc , propertiesElement , "TargetType" , "System.String" ) ;
132
+ this . addProperty ( xmlDoc , propertiesElement , "ValueLabel" , "System.String" ) ;
133
+ this . addProperty ( xmlDoc , propertiesElement , "ZoomLevel" , "System.String" ) ;
134
+ this . addProperty ( xmlDoc , propertiesElement , "Expression" , "System.String" ) ;
135
+ }
136
+
137
+ private addProperty ( xmlDoc : Document , propertiesElement : Element | null , idValue : string , datatypeValue : string ) {
138
+ const propertyElement = xmlDoc . createElement ( "Property" ) ;
139
+ propertyElement . setAttribute ( "Id" , idValue ) ;
140
+ propertyElement . setAttribute ( "DataType" , datatypeValue ) ;
141
+ this . addNode ( propertiesElement , propertyElement ) ;
142
+ }
143
+
144
+ public addStyles ( xmlDoc : Document ) {
145
+ const stylesElement = this . addNodeToRoot ( xmlDoc , "Styles" ) ;
146
+ const styleElement = xmlDoc . createElement ( "Style" ) ;
147
+ styleElement . setAttribute ( "TargetType" , "Node" ) ;
148
+ styleElement . setAttribute ( "GroupLabel" , "Root component" ) ;
149
+ styleElement . setAttribute ( "ValueLabel" , "Has category" ) ;
150
+ const conditionElement = xmlDoc . createElement ( "Condition" ) ;
151
+ conditionElement . setAttribute ( "Expression" , "HasCategory('RootComponent')" ) ;
152
+ styleElement . appendChild ( conditionElement ) ;
153
+ const setterElement = xmlDoc . createElement ( "Setter" ) ;
154
+ setterElement . setAttribute ( "Property" , "Background" ) ;
155
+ setterElement . setAttribute ( "Property" , "#FF00AA00" ) ;
156
+ styleElement . appendChild ( setterElement ) ;
157
+ this . addNode ( stylesElement , styleElement , "GroupLabel" ) ;
158
+ }
159
+ }
0 commit comments