1
2
3
4
5
6 #include <gendoc/html/ClassInheritanceDiagramCode.hpp>
7
8 namespace gendoc { namespace html {
9
10 void GenerateClassInheritanceDiagramCode(CodeFormatter& formatter)
11 {
12 formatter.WriteLine("// JavaScript source code for drawing class inheritance diagrams");
13 formatter.WriteLine();
14
15 formatter.WriteLine("function pick(level, classes) {");
16 formatter.IncIndent();
17 formatter.WriteLine("var levelClasses = [];");
18 formatter.WriteLine("var n = classes.length;");
19 formatter.WriteLine("for (var i = 0; i < n; ++i) {");
20 formatter.IncIndent();
21 formatter.WriteLine("var c = classes[i];");
22 formatter.WriteLine("if (c.level == level) {");
23 formatter.IncIndent();
24 formatter.WriteLine("levelClasses.push(c);");
25 formatter.DecIndent();
26 formatter.WriteLine("}");
27 formatter.DecIndent();
28 formatter.WriteLine("}");
29 formatter.WriteLine("return levelClasses;");
30 formatter.DecIndent();
31 formatter.WriteLine("}");
32 formatter.WriteLine();
33
34 formatter.WriteLine("function createClassElements(levelClasses, maxTextWidth, maxTextHeight) {");
35 formatter.IncIndent();
36 formatter.WriteLine("var textDimensions = { width: maxTextWidth, height: maxTextHeight };");
37 formatter.WriteLine("var n = levelClasses.length;");
38 formatter.WriteLine("for (var i = 0; i < n; ++i) {");
39 formatter.IncIndent();
40 formatter.WriteLine("var levelClass = levelClasses[i];");
41 formatter.WriteLine("var svg = document.getElementById(\"classInheritanceDiagram\");");
42 formatter.WriteLine("var rectElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect');");
43 formatter.WriteLine("rectElement.setAttribute(\"id\", levelClass.id + \"_rect\");");
44 formatter.WriteLine("var linkElement = document.createElementNS('http://www.w3.org/2000/svg', 'a');");
45 formatter.WriteLine("linkElement.setAttribute(\"href\", levelClass.link);");
46 formatter.WriteLine("var textElement = document.createElementNS('http://www.w3.org/2000/svg', 'text');");
47 formatter.WriteLine("linkElement.appendChild(textElement);");
48 formatter.WriteLine("textElement.setAttribute(\"id\", levelClass.id + \"_text\");");
49 formatter.WriteLine("textElement.innerHTML = levelClass.name;");
50 formatter.WriteLine("svg.appendChild(rectElement);");
51 formatter.WriteLine("svg.appendChild(linkElement);");
52 formatter.WriteLine("var bb = textElement.getBBox();");
53 formatter.WriteLine("var textWidth = bb.width;");
54 formatter.WriteLine("var textHeight = bb.height;");
55 formatter.WriteLine("levelClass.textWidth = textWidth;");
56 formatter.WriteLine("levelClass.textHeight = textHeight;");
57 formatter.WriteLine("if (textWidth > textDimensions.width) {");
58 formatter.IncIndent();
59 formatter.WriteLine("textDimensions.width = textWidth;");
60 formatter.DecIndent();
61 formatter.WriteLine("}");
62 formatter.WriteLine("if (textHeight > textDimensions.height) {");
63 formatter.IncIndent();
64 formatter.WriteLine("textDimensions.height = textHeight;");
65 formatter.DecIndent();
66 formatter.WriteLine("}");
67 formatter.DecIndent();
68 formatter.WriteLine("}");
69 formatter.WriteLine("return textDimensions;");
70 formatter.DecIndent();
71 formatter.WriteLine("}");
72 formatter.WriteLine();
73
74 formatter.WriteLine("function drawDiagram(classes) {");
75 formatter.IncIndent();
76 formatter.WriteLine("var cont = true;");
77 formatter.WriteLine("var level = 0;");
78 formatter.WriteLine("var yspace = 8;");
79 formatter.WriteLine("var xspace = 8;");
80 formatter.WriteLine("var minRectWidth = 100;");
81 formatter.WriteLine("var minRectHeight = 40;");
82 formatter.WriteLine("var maxTextWidth = 0;");
83 formatter.WriteLine("var maxTextHeight = 0;");
84 formatter.WriteLine("var triangleHeight = 20;");
85 formatter.WriteLine("var triangleWidth = 20;");
86 formatter.WriteLine("var targetHandleHeight = 20;");
87 formatter.WriteLine("var sourceHandleHeight = 40;");
88 formatter.WriteLine("var rectXSpace = 20;");
89 formatter.WriteLine("var horizontalRectYSpace = triangleHeight + targetHandleHeight + sourceHandleHeight;");
90 formatter.WriteLine("var verticalRectYSpace = 20;");
91 formatter.WriteLine("var derivedTriangleHeight = 8;");
92 formatter.WriteLine("var derivedTriangleWidth = 8;");
93 formatter.WriteLine("var widthThreshold = 1800;");
94 formatter.WriteLine("var allLevelClasses = [];");
95 formatter.WriteLine("while (cont) {");
96 formatter.IncIndent();
97 formatter.WriteLine("var levelClasses = pick(level, classes);");
98 formatter.WriteLine("var n = levelClasses.length;");
99 formatter.WriteLine("cont = n > 0;");
100 formatter.WriteLine("if (cont) {");
101 formatter.IncIndent();
102 formatter.WriteLine("var textDimensions = createClassElements(levelClasses, maxTextWidth, maxTextHeight);");
103 formatter.WriteLine("if (textDimensions.width > maxTextWidth) {");
104 formatter.IncIndent();
105 formatter.WriteLine("maxTextWidth = textDimensions.width;");
106 formatter.DecIndent();
107 formatter.WriteLine("}");
108 formatter.WriteLine("if (textDimensions.height > maxTextHeight) {");
109 formatter.IncIndent();
110 formatter.WriteLine("maxTextHeight = textDimensions.height;");
111 formatter.DecIndent();
112 formatter.WriteLine("}");
113 formatter.WriteLine("allLevelClasses.push(levelClasses);");
114 formatter.WriteLine("++level;");
115 formatter.DecIndent();
116 formatter.WriteLine("}");
117 formatter.DecIndent();
118 formatter.WriteLine("}");
119 formatter.WriteLine("var maxLevel = level;");
120 formatter.WriteLine("var rectWidth = Math.max(minRectWidth, maxTextWidth + 2 * xspace);");
121 formatter.WriteLine("var rectHeight = Math.max(minRectHeight, maxTextHeight + 2 * yspace);");
122 formatter.WriteLine("var totalWidth = 0;");
123 formatter.WriteLine("var totalHeight = 0;");
124 formatter.WriteLine("var horizontalDirection = 0;");
125 formatter.WriteLine("var verticalDirection = 1;");
126 formatter.WriteLine("var levelDirection = [];");
127 formatter.WriteLine("var levelHeight = [];");
128 formatter.WriteLine("var prevW = 0;");
129 formatter.WriteLine("for (level = 0; level < maxLevel; ++level) {");
130 formatter.IncIndent();
131 formatter.WriteLine("var levelClasses = allLevelClasses[level];");
132 formatter.WriteLine("var n = levelClasses.length;");
133 formatter.WriteLine("var w = n * (rectWidth + rectXSpace);");
134 formatter.WriteLine("var h = rectHeight + horizontalRectYSpace;");
135 formatter.WriteLine("if (w < widthThreshold) {");
136 formatter.IncIndent();
137 formatter.WriteLine("levelDirection.push(horizontalDirection);");
138 formatter.WriteLine("if (w > totalWidth) {");
139 formatter.IncIndent();
140 formatter.WriteLine("totalWidth = w;");
141 formatter.DecIndent();
142 formatter.WriteLine("}");
143 formatter.DecIndent();
144 formatter.WriteLine("}");
145 formatter.WriteLine("else {");
146 formatter.IncIndent();
147 formatter.WriteLine("w = prevW + rectWidth + rectXSpace;");
148 formatter.WriteLine("h = n * (rectHeight + verticalRectYSpace);");
149 formatter.WriteLine("levelDirection.push(verticalDirection);");
150 formatter.WriteLine("totalWidth += w;");
151 formatter.DecIndent();
152 formatter.WriteLine("}");
153 formatter.WriteLine("totalHeight += h;");
154 formatter.WriteLine("levelHeight.push(h);");
155 formatter.WriteLine("prevW = w;");
156 formatter.DecIndent();
157 formatter.WriteLine("}");
158 formatter.WriteLine("var svg = document.getElementById(\"classInheritanceDiagram\");");
159 formatter.WriteLine("svg.setAttribute(\"width\", totalWidth.toString());");
160 formatter.WriteLine("svg.setAttribute(\"height\", totalHeight.toString());");
161 formatter.WriteLine("var prevRectY = 0;");
162 formatter.WriteLine("var prevRectX = 0;");
163 formatter.WriteLine("var prevHandleX2 = -1;");
164 formatter.WriteLine("var prevHandleY2 = -1;");
165 formatter.WriteLine("var prevY = 0;");
166 formatter.WriteLine("for (level = 0; level < maxLevel; ++level) {");
167 formatter.IncIndent();
168 formatter.WriteLine("var direction = levelDirection[level];");
169 formatter.WriteLine("var levelClasses = allLevelClasses[level];");
170 formatter.WriteLine("var n = levelClasses.length;");
171 formatter.WriteLine("var rectY = prevY;");
172 formatter.WriteLine("prevY += levelHeight[level];");
173 formatter.WriteLine("var rectX = (totalWidth / n - rectWidth) / 2;");
174 formatter.WriteLine("var minHandleX = Number.MAX_SAFE_INTEGER;");
175 formatter.WriteLine("var maxHandleX = 0;");
176 formatter.WriteLine("var handleY = 0;");
177 formatter.WriteLine("for (var i = 0; i < n; ++i) {");
178 formatter.IncIndent();
179 formatter.WriteLine("var levelClass = levelClasses[i];");
180 formatter.WriteLine("var textWidth = levelClass.textWidth;");
181 formatter.WriteLine("var textHeight = levelClass.textHeight;");
182 formatter.WriteLine("if (direction == horizontalDirection) {");
183 formatter.IncIndent();
184 formatter.WriteLine("rectX = (totalWidth / n - rectWidth) / 2 + i * (rectWidth + rectXSpace);");
185 formatter.DecIndent();
186 formatter.WriteLine("}");
187 formatter.WriteLine("else if (direction == verticalDirection) {");
188 formatter.IncIndent();
189 formatter.WriteLine("rectX = prevRectX + (rectWidth + rectXSpace);");
190 formatter.WriteLine("rectY = prevRectY + horizontalRectYSpace + i * (rectHeight + verticalRectYSpace);");
191 formatter.DecIndent();
192 formatter.WriteLine("}");
193 formatter.WriteLine("var textX = rectX + (rectWidth - textWidth) / 2;");
194 formatter.WriteLine("var textY = (rectY + rectHeight - yspace / 2) - (rectHeight - textHeight) / 2;");
195 formatter.WriteLine("var rectElement = document.getElementById(levelClass.id + \"_rect\");");
196 formatter.WriteLine("rectElement.setAttribute(\"x\", rectX.toString());");
197 formatter.WriteLine("rectElement.setAttribute(\"y\", rectY.toString());");
198 formatter.WriteLine("rectElement.setAttribute(\"width\", rectWidth.toString());");
199 formatter.WriteLine("rectElement.setAttribute(\"height\", rectHeight.toString());");
200 formatter.WriteLine("var fillColor = \"white\";");
201 formatter.WriteLine("if (levelClass.subject) {");
202 formatter.IncIndent();
203 formatter.WriteLine("fillColor = \"floralWhite\";");
204 formatter.DecIndent();
205 formatter.WriteLine("}");
206 formatter.WriteLine("rectElement.setAttribute(\"fill\", fillColor);");
207 formatter.WriteLine("rectElement.setAttribute(\"stroke\", \"black\");");
208 formatter.WriteLine("var textElement = document.getElementById(levelClass.id + \"_text\");");
209 formatter.WriteLine("textElement.setAttribute(\"x\", textX.toString());");
210 formatter.WriteLine("textElement.setAttribute(\"y\", textY.toString());");
211 formatter.WriteLine("if (level < maxLevel - 1) {");
212 formatter.IncIndent();
213 formatter.WriteLine("var triangleElement = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');");
214 formatter.WriteLine("var tipX = rectX + rectWidth / 2;");
215 formatter.WriteLine("var tipY = rectY + rectHeight;");
216 formatter.WriteLine("var leftX = tipX - triangleWidth / 2;");
217 formatter.WriteLine("var leftY = rectY + rectHeight + triangleHeight;");
218 formatter.WriteLine("var rightX = tipX + triangleWidth / 2;");
219 formatter.WriteLine("var rightY = rectY + rectHeight + triangleHeight;");
220 formatter.WriteLine("triangleElement.setAttribute(\"points\",");
221 formatter.IncIndent();
222 formatter.WriteLine("tipX.toString() + \",\" + tipY.toString() + \" \" +");
223 formatter.WriteLine("leftX.toString() + \",\" + leftY.toString() + \" \" +");
224 formatter.WriteLine("rightX.toString() + \",\" + rightY.toString());");
225 formatter.DecIndent();
226 formatter.WriteLine("triangleElement.setAttribute(\"fill\", \"white\");");
227 formatter.WriteLine("triangleElement.setAttribute(\"stroke\", \"black\");");
228 formatter.WriteLine("svg.appendChild(triangleElement);");
229 formatter.WriteLine("var targetHandleElement = document.createElementNS('http://www.w3.org/2000/svg', 'line');");
230 formatter.WriteLine("var handleX1 = tipX;");
231 formatter.WriteLine("var handleY1 = tipY + triangleHeight;");
232 formatter.WriteLine("var handleX2 = tipX;");
233 formatter.WriteLine("var handleY2 = tipY + triangleHeight + targetHandleHeight;");
234 formatter.WriteLine("targetHandleElement.setAttribute(\"x1\", handleX1.toString());");
235 formatter.WriteLine("targetHandleElement.setAttribute(\"y1\", handleY1.toString());");
236 formatter.WriteLine("targetHandleElement.setAttribute(\"x2\", handleX2.toString());");
237 formatter.WriteLine("targetHandleElement.setAttribute(\"y2\", handleY2.toString());");
238 formatter.WriteLine("targetHandleElement.setAttribute(\"stroke\", \"black\");");
239 formatter.WriteLine("svg.appendChild(targetHandleElement);");
240 formatter.WriteLine("prevHandleX2 = handleX1;");
241 formatter.WriteLine("prevHandleY2 = handleY1;");
242 formatter.WriteLine("if (handleX1 < minHandleX) {");
243 formatter.IncIndent();
244 formatter.WriteLine("minHandleX = handleX1;");
245 formatter.WriteLine("handleY = handleY2;");
246 formatter.DecIndent();
247 formatter.WriteLine("}");
248 formatter.WriteLine("if (handleX1 > maxHandleX) {");
249 formatter.IncIndent();
250 formatter.WriteLine("maxHandleX = handleX1;");
251 formatter.WriteLine("handleY = handleY2;");
252 formatter.DecIndent();
253 formatter.WriteLine("}");
254 formatter.DecIndent();
255 formatter.WriteLine("} else if (level == maxLevel - 1 && levelClass.hasDerivedClasses) {");
256 formatter.IncIndent();
257 formatter.WriteLine("var derivedTriangleElement = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');");
258 formatter.WriteLine("var cornerX = rectX + rectWidth;");
259 formatter.WriteLine("var cornerY = rectY + rectHeight;");
260 formatter.WriteLine("var verticalX = rectX + rectWidth;");
261 formatter.WriteLine("var verticalY = rectY + rectHeight - derivedTriangleHeight;");
262 formatter.WriteLine("var horizontalX = rectX + rectWidth - derivedTriangleWidth;");
263 formatter.WriteLine("var horizontalY = rectY + rectHeight;");
264 formatter.WriteLine("derivedTriangleElement.setAttribute(\"points\",");
265 formatter.IncIndent();
266 formatter.WriteLine("cornerX.toString() + \",\" + cornerY.toString() + \" \" +");
267 formatter.WriteLine("verticalX.toString() + \",\" + verticalY.toString() + \" \" +");
268 formatter.WriteLine("horizontalX.toString() + \",\" + horizontalY.toString());");
269 formatter.DecIndent();
270 formatter.WriteLine("derivedTriangleElement.setAttribute(\"fill\", \"black\");");
271 formatter.WriteLine("svg.appendChild(derivedTriangleElement);");
272 formatter.DecIndent();
273 formatter.WriteLine("}");
274 formatter.WriteLine("if (level > 0 && direction == horizontalDirection) {");
275 formatter.IncIndent();
276 formatter.WriteLine("var sourceHandleElement = document.createElementNS('http://www.w3.org/2000/svg', 'line');");
277 formatter.WriteLine("var handleX1 = rectX + rectWidth / 2;");
278 formatter.WriteLine("var handleY1 = rectY;");
279 formatter.WriteLine("var handleX2 = rectX + rectWidth / 2;");
280 formatter.WriteLine("var handleY2 = rectY - sourceHandleHeight;");
281 formatter.WriteLine("sourceHandleElement.setAttribute(\"x1\", handleX1.toString());");
282 formatter.WriteLine("sourceHandleElement.setAttribute(\"y1\", handleY1.toString());");
283 formatter.WriteLine("sourceHandleElement.setAttribute(\"x2\", handleX2.toString());");
284 formatter.WriteLine("sourceHandleElement.setAttribute(\"y2\", handleY2.toString());");
285 formatter.WriteLine("sourceHandleElement.setAttribute(\"stroke\", \"black\");");
286 formatter.WriteLine("svg.appendChild(sourceHandleElement);");
287 formatter.WriteLine("if (handleX1 < minHandleX) {");
288 formatter.IncIndent();
289 formatter.WriteLine("minHandleX = handleX1;");
290 formatter.WriteLine("handleY = handleY2;");
291 formatter.DecIndent();
292 formatter.WriteLine("}");
293 formatter.WriteLine("if (handleX1 > maxHandleX) {");
294 formatter.IncIndent();
295 formatter.WriteLine("maxHandleX = handleX1;");
296 formatter.WriteLine("handleY = handleY2;");
297 formatter.DecIndent();
298 formatter.WriteLine("}");
299 formatter.DecIndent();
300 formatter.WriteLine("}");
301 formatter.WriteLine("else if (level > 0 && direction == verticalDirection) {");
302 formatter.IncIndent();
303 formatter.WriteLine("var sourceHandleElement = document.createElementNS('http://www.w3.org/2000/svg', 'line');");
304 formatter.WriteLine("var handleX1 = rectX;");
305 formatter.WriteLine("var handleY1 = rectY + rectHeight / 2;");
306 formatter.WriteLine("var handleX2 = rectX - rectWidth / 2 - rectXSpace;");
307 formatter.WriteLine("var handleY2 = rectY + rectHeight / 2;");
308 formatter.WriteLine("sourceHandleElement.setAttribute(\"x1\", handleX1.toString());");
309 formatter.WriteLine("sourceHandleElement.setAttribute(\"y1\", handleY1.toString());");
310 formatter.WriteLine("sourceHandleElement.setAttribute(\"x2\", handleX2.toString());");
311 formatter.WriteLine("sourceHandleElement.setAttribute(\"y2\", handleY2.toString());");
312 formatter.WriteLine("sourceHandleElement.setAttribute(\"stroke\", \"black\");");
313 formatter.WriteLine("svg.appendChild(sourceHandleElement);");
314 formatter.WriteLine("if (prevHandleX2 != -1 && prevHandleY2 != -1) {");
315 formatter.IncIndent();
316 formatter.WriteLine("var connectorHandleElement = document.createElementNS('http://www.w3.org/2000/svg', 'line');");
317 formatter.WriteLine("connectorHandleElement.setAttribute(\"x1\", handleX2.toString());");
318 formatter.WriteLine("connectorHandleElement.setAttribute(\"y1\", handleY2.toString());");
319 formatter.WriteLine("connectorHandleElement.setAttribute(\"x2\", prevHandleX2.toString());");
320 formatter.WriteLine("connectorHandleElement.setAttribute(\"y2\", prevHandleY2.toString());");
321 formatter.WriteLine("connectorHandleElement.setAttribute(\"stroke\", \"black\");");
322 formatter.WriteLine("svg.appendChild(connectorHandleElement);");
323 formatter.DecIndent();
324 formatter.WriteLine("}");
325 formatter.WriteLine("prevHandleX2 = handleX2");
326 formatter.WriteLine("prevHandleY2 = handleY2;");
327 formatter.DecIndent();
328 formatter.WriteLine("}");
329 formatter.DecIndent();
330 formatter.WriteLine("}");
331 formatter.WriteLine("if (minHandleX < maxHandleX && direction == horizontalDirection) {");
332 formatter.IncIndent();
333 formatter.WriteLine("var hlineElement = document.createElementNS('http://www.w3.org/2000/svg', 'line');");
334 formatter.WriteLine("hlineElement.setAttribute(\"x1\", minHandleX.toString());");
335 formatter.WriteLine("hlineElement.setAttribute(\"y1\", handleY.toString());");
336 formatter.WriteLine("hlineElement.setAttribute(\"x2\", maxHandleX.toString());");
337 formatter.WriteLine("hlineElement.setAttribute(\"y2\", handleY.toString());");
338 formatter.WriteLine("hlineElement.setAttribute(\"stroke\", \"black\");");
339 formatter.WriteLine("svg.appendChild(hlineElement);");
340 formatter.DecIndent();
341 formatter.WriteLine("}");
342 formatter.WriteLine("prevRectY = rectY;");
343 formatter.WriteLine("prevRectX = rectX;");
344 formatter.DecIndent();
345 formatter.WriteLine("}");
346 formatter.DecIndent();
347 formatter.WriteLine("}");
348 formatter.WriteLine();
349 }
350
351 } }