diff --git a/Kieker.WebGUI/bin/data/Advanced Example/meta.dat b/Kieker.WebGUI/bin/data/Advanced Example/meta.dat index ff6c9d68a8a4949714e212cffb077984127e0b85..b70565bdfe67056a7e677a4c35d65ef4489b1207 100644 --- a/Kieker.WebGUI/bin/data/Advanced Example/meta.dat +++ b/Kieker.WebGUI/bin/data/Advanced Example/meta.dat @@ -1,5 +1,5 @@ # -#Wed Apr 10 22:37:49 CEST 2013 +#Thu Apr 11 15:35:42 CEST 2013 owner=Kieker-Administrator -layout=0 -2087 -780 192 72;1 -1791 -780 312 72;2 -1433 -791 276 132;3 -1125 -779 252 108;4 -429 -791 468 96;5 429 -744 816 144;6 -497 -532 876 84;7 425 -544 840 120;8 1093 -514 288 72;9 1087 -816 360 72;10 1505 -816 348 72;\#1.2 2.6 -1604.5 -769.5 -1604.5 -744.5;1.2 2.5 -1604.5 -769.5 -1604.5 -768.5;3.12 6.20 -968.5 -780.5 -968.5 -521.5;4.0 10.R -28.5 -798.5 -28.5 -899.5 1297.5 -899.5 1297.5 -805.5;4.15 5.16 -28.5 -762.5 -28.5 -733.5;5.1 10.R 875.5 -775.5 875.5 -899.5 1297.5 -899.5 1297.5 -805.5;5.17 8.26 885.5 -739.5 885.5 -503.5;7.2 10.R 875.5 -563.5 875.5 -736.5 1297.5 -736.5 1297.5 -805.5;8.3 10.R 1297.5 -503.5 1297.5 -805.5; +layout=id0 -567 -144 192 72;id1 -271 -144 312 72;id2 87 -155 276 132;id3 395 -143 252 108;id4 1091 -155 468 96;id5 1949 -108 816 144;id6 1023 104 876 84;id7 1945 92 840 120;id8 2613 122 288 72;id9 2607 -180 360 72;id10 3025 -180 348 72;\#id1.2 id2.6 -83.5 -132.5 -83.5 -107.5;id1.2 id2.5 -83.5 -132.5 -83.5 -131.5;id3.12 id6.20 552.5 -143.5 552.5 115.5;id4.0 id10.R 1492.5 -161.5 1492.5 -262.5 2818.5 -262.5 2818.5 -168.5;id4.15 id5.16 1492.5 -125.5 1492.5 -96.5;id5.1 id10.R 2396.5 -138.5 2396.5 -262.5 2818.5 -262.5 2818.5 -168.5;id5.17 id8.26 2406.5 -102.5 2406.5 133.5;id7.2 id10.R 2396.5 73.5 2396.5 -99.5 2818.5 -99.5 2818.5 -168.5;id8.3 id10.R 2818.5 133.5 2818.5 -168.5; last\ user=Kieker-Administrator diff --git a/Kieker.WebGUI/bin/data/Bookstore-Example/meta.dat b/Kieker.WebGUI/bin/data/Bookstore-Example/meta.dat index 9bca80a1a555d57f7784932793ab401e7d207373..4f7ca6273d4fd54d971faf446f101fbe80fbebcf 100644 --- a/Kieker.WebGUI/bin/data/Bookstore-Example/meta.dat +++ b/Kieker.WebGUI/bin/data/Bookstore-Example/meta.dat @@ -1,5 +1,5 @@ # -#Wed Apr 10 22:34:45 CEST 2013 +#Thu Apr 11 15:36:17 CEST 2013 owner=Kieker-Administrator -layout=0 -675 -155 192 72;1 -59 -167 336 84;2 651 -69 276 72;3 311 -57 276 84;4 311 -197 252 84;5 -403 -155 264 84;6 639 -201 252 72;\#1.2 4.8 140.5 -167.5 140.5 -185.5;1.3 3.5 140.5 -143.5 140.5 -45.5;4.9 6.14 480.5 -197.5 480.5 -189.5; +layout=id0 -1933 -617 192 72;id1 -1317 -629 336 84;id2 -607 -531 276 72;id3 -947 -519 276 84;id4 -947 -659 252 84;id5 -1661 -617 264 84;id6 -619 -663 252 72;\#id1.2 id4.8 -1118.5 -630.5 -1118.5 -648.5;id1.3 id3.5 -1118.5 -606.5 -1118.5 -508.5;id4.9 id6.14 -778.5 -660.5 -778.5 -652.5; last\ user=Kieker-Administrator diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java index 2b089f88a27a016ffd29033f8726b784be91a3d5..1aa15ca10fd0c9ec853e40bb3490b2029a5a01e7 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java @@ -333,7 +333,7 @@ public final class CurrentAnalysisEditorGraphBean { * @return The ID for the port within the graph */ private synchronized String assembleGraphPortID(final MIPlugin plugin, final MIPort port) { - return this.componentMap.get(plugin) + "." + this.portMap.get(port); + return "id" + this.componentMap.get(plugin) + "." + this.portMap.get(port); } /** @@ -346,7 +346,7 @@ public final class CurrentAnalysisEditorGraphBean { * @return The ID for the port within the graph */ private synchronized Object assembleGraphPortID(final MIPlugin plugin, final MIRepositoryConnector port) { - return this.componentMap.get(plugin) + "." + this.repositoryPortMap.get(port); + return "id" + this.componentMap.get(plugin) + "." + this.repositoryPortMap.get(port); } /** @@ -357,7 +357,7 @@ public final class CurrentAnalysisEditorGraphBean { * @return The ID for the port within the graph */ private synchronized Object assembleGraphPortID(final MIRepository repository) { - return this.componentMap.get(repository) + "." + CurrentAnalysisEditorGraphBean.REPOSITORY_INPUT_PORT; + return "id" + this.componentMap.get(repository) + "." + CurrentAnalysisEditorGraphBean.REPOSITORY_INPUT_PORT; } /** @@ -372,7 +372,7 @@ public final class CurrentAnalysisEditorGraphBean { final String className = component.getClassname(); final String shortName = className.substring(className.lastIndexOf('.') + 1); - return String.format(CurrentAnalysisEditorGraphBean.JS_CMD_NODE, this.componentMap.get(component), + return String.format(CurrentAnalysisEditorGraphBean.JS_CMD_NODE, "id" + this.componentMap.get(component), CurrentAnalysisEditorGraphBean.simpleEscape(name), CurrentAnalysisEditorGraphBean.simpleEscape(shortName), CurrentAnalysisEditorGraphBean.simpleEscape(className)); } @@ -388,7 +388,7 @@ public final class CurrentAnalysisEditorGraphBean { // Now search the correct node try { - final MIAnalysisComponent selectedNode = this.componentMap.get(Integer.parseInt(clickedNodeID)); + final MIAnalysisComponent selectedNode = this.componentMap.get(Integer.parseInt(clickedNodeID.substring(2))); if ((selectedNode != null) && (this.currentAnalysisEditorBean != null)) { this.currentAnalysisEditorBean.nodeSelected(selectedNode); } @@ -408,7 +408,7 @@ public final class CurrentAnalysisEditorGraphBean { final String clickedNodeID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_ID); // Now search the correct node try { - final MIAnalysisComponent selectedNode = this.componentMap.get(Integer.parseInt(clickedNodeID)); + final MIAnalysisComponent selectedNode = this.componentMap.get(Integer.parseInt(clickedNodeID.substring(2))); if ((selectedNode != null) && (this.currentAnalysisEditorBean != null)) { this.currentAnalysisEditorBean.nodeRemoved(selectedNode); } @@ -435,7 +435,7 @@ public final class CurrentAnalysisEditorGraphBean { // This is a special case: An edge between a filter and a repository final MIRepositoryConnector sourcePort = this.repositoryPortMap.get(Integer.parseInt(sourcePortID)); final String targetID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_TARGET_PORT_ID).split("\\.")[0]; - final MIAnalysisComponent targetRepo = this.componentMap.get(Integer.parseInt(targetID)); + final MIAnalysisComponent targetRepo = this.componentMap.get(Integer.parseInt(targetID.substring(2))); if ((sourcePort != null) && (targetRepo instanceof MIRepository) && (this.currentAnalysisEditorBean != null)) { this.currentAnalysisEditorBean.edgeCreated(sourcePort, (MIRepository) targetRepo); @@ -472,7 +472,7 @@ public final class CurrentAnalysisEditorGraphBean { // This is a special case: An edge between a filter and a repository final MIRepositoryConnector sourcePort = this.repositoryPortMap.get(Integer.parseInt(sourcePortID)); final String targetID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_TARGET_PORT_ID).split("\\.")[0]; - final MIAnalysisComponent targetRepo = this.componentMap.get(Integer.parseInt(targetID)); + final MIAnalysisComponent targetRepo = this.componentMap.get(Integer.parseInt(targetID.substring(2))); if ((sourcePort != null) && (targetRepo instanceof MIRepository) && (this.currentAnalysisEditorBean != null)) { this.currentAnalysisEditorBean.edgeRemoved(sourcePort, (MIRepository) targetRepo); } @@ -555,7 +555,7 @@ public final class CurrentAnalysisEditorGraphBean { * The new name of the node. */ public synchronized void renameNode(final MIAnalysisComponent node, final String newName) { - final String cmd = String.format(CurrentAnalysisEditorGraphBean.JS_CMD_RENAME_NODE, this.componentMap.get(node), + final String cmd = String.format(CurrentAnalysisEditorGraphBean.JS_CMD_RENAME_NODE, "id" + this.componentMap.get(node), CurrentAnalysisEditorGraphBean.simpleEscape(newName)); RequestContext.getCurrentInstance().execute(cmd); } diff --git a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js index 0a086156a9a2a7c00ac0e5927595e307e12209fe..d54d6adff103cd2e019c6568fc4d6a5798f0ac46 100644 --- a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js +++ b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js @@ -35,6 +35,11 @@ var labelType, useGradients, nativeTextSupport, animate; nativeTextSupport = labelType == 'Native'; useGradients = nativeCanvasSupport; animate = !(iStuff || !nativeCanvasSupport); + + // fix IE script crashes + if(!window.console){ + window.console={log:function(){}}; + } })(); var Log = { @@ -151,7 +156,8 @@ function GraphFlow(){ var animation = { 'enabled' : true, - 'duration' : 1000 + 'duration' : 1000, + 'busyCanvas' : false }; ///////////////////////////////////////////// @@ -872,9 +878,6 @@ function GraphFlow(){ nodes = nodes.join(";"); edges = edges.join(";"); - console.log(nodes); - console.log(edges); - callListener("autoLayout", [nodes, edges]); } @@ -888,7 +891,6 @@ function GraphFlow(){ */ this.loadPositions = function(input){ - console.log(input); // check if animation is in progress var isAnimated = animation.enabled; @@ -1051,27 +1053,48 @@ function GraphFlow(){ } + + + // scaling values + var canvas = fd.canvas, + oldScale = canvas.scaleOffsetX, + scaleX = grid.data.$width / (right - left + 4*vertexLabelSize), + scaleY = grid.data.$height / (bottom - top + 4*vertexLabelSize) + scale = Math.min(scaleX, scaleY); + // translation values - var scale = fd.canvas.scaleOffsetX, - midX = - (left + right) / 2, - midY = - (top + bottom) / 2; + var midX = -(left + right) / 2, + midY = -(top + bottom) / 2; if(isAnimated){ - fd.canvas.translateOffsetXEnd = midX * scale; - fd.canvas.translateOffsetYEnd = midY * scale; + + // set animation parameters + canvas.translateOffsetXEnd = midX; + canvas.translateOffsetYEnd = midY; + + canvas.scaleOffsetOld = oldScale; + canvas.scaleOffsetEnd = scale; + animation.busyCanvas = true; fd.animate({ - modes: ['node-property:width:height', 'linear', 'canvas'], + modes: ['node-property:width:height', 'linear', 'canvas:zoom:translate'], transition: $jit.Trans.Cubic.easeInOut, - duration: animation.duration - }); - } - else{ - midX -= fd.canvas.translateOffsetX/scale; - midY -= fd.canvas.translateOffsetY/scale; - fd.canvas.translate(midX, midY); + duration: animation.duration, + onComplete: function(){animation.busyCanvas = false; fd.plot();} + }); + + }else{ + // translate to the center of the graph and scale + midX -= fd.canvas.translateOffsetX / oldScale; + midY -= fd.canvas.translateOffsetY / oldScale; + scale /= oldScale; + + canvas.translate(midX, midY); + canvas.scale(scale, scale); + fd.plot(); } + return; } @@ -1298,7 +1321,7 @@ function GraphFlow(){ */ this.setGridVisible = function(visibility){ - isAnimated = animation.enabled; + isAnimated = animation.enabled && !animation.busyCanvas; var setter = 'current'; if(isAnimated){ @@ -1315,9 +1338,10 @@ function GraphFlow(){ fd.animate({ modes: ['node-property:alpha'], transition: $jit.Trans.Cubic.easeInOut, - duration: animation.duration + duration: animation.duration / 2, + onComplete: function(){fd.plot();} }); - }else{ + }else if(!animation.busyCanvas){ fd.plot(); } } @@ -1332,22 +1356,19 @@ function GraphFlow(){ return; } + var isAnimated = animation.enabled && !animation.busyCanvas; + // init loop variables var data, width = 0, height = 0; + // init the outer bounds of the displayed graph var left = Number.POSITIVE_INFINITY, right = Number.NEGATIVE_INFINITY, top = Number.POSITIVE_INFINITY, bottom = Number.NEGATIVE_INFINITY; - // init the outer bounds of the displayed graph - var leftMost = left, - rightMost = right, - topMost = top, - bottomMost = bottom; - // check nodeFamilies for position iterateAllNodes(function(node){ data = node.data; @@ -1357,48 +1378,58 @@ function GraphFlow(){ width = data.$width/2; height = data.$height/2; - left = node.pos.x - width, - right = node.pos.x + width, - top = node.pos.y - height, - bottom = node.pos.y + height; + left = Math.min(left, node.pos.x - width); + right = Math.max(right, node.pos.x + width); + top = Math.min(top, node.pos.y - height); + bottom = Math.max(bottom, node.pos.y + height); - // update bounds - if(left < leftMost){ - leftMost = left; - } - if(right > rightMost){ - rightMost = right; - } - if(top < topMost){ - topMost = top; - } - if(bottom > bottomMost){ - bottomMost = bottom; - } } }); // scaling values var canvas = fd.canvas, oldScale = canvas.scaleOffsetX, - scaleX = grid.data.$width / (rightMost - leftMost + 4*vertexLabelSize), - scaleY = grid.data.$height / (bottomMost - topMost + 4*vertexLabelSize) - scale = Math.min(scaleX, scaleY) / oldScale; - + scaleX = grid.data.$width / (right - left + 4*vertexLabelSize), + scaleY = grid.data.$height / (bottom - top + 4*vertexLabelSize) + scale = Math.min(scaleX, scaleY); + // translation values - var midX = (leftMost + rightMost) / 2, - midY = (topMost + bottomMost) / 2; - + var midX = -(left + right) / 2, + midY = -(top + bottom) / 2; - // translate to origin, scale, and translate to the center of the graph - canvas.translate( -canvas.translateOffsetX/oldScale, -canvas.translateOffsetY/oldScale); - canvas.scale(scale, scale); - canvas.translate( -midX, -midY); + if(isAnimated){ + + // set animation parameters + fd.canvas.translateOffsetXEnd = midX; + fd.canvas.translateOffsetYEnd = midY; + + canvas.scaleOffsetOld = oldScale; + canvas.scaleOffsetEnd = scale; + + animation.busyCanvas = true; + fd.animate({ + modes: ['canvas:zoom:translate'], + transition: $jit.Trans.Cubic.easeInOut, + duration: animation.duration, + onComplete: function(){animation.busyCanvas = false; fd.plot();} + }); + + }else{ + // translate to the center of the graph and scale + midX -= fd.canvas.translateOffsetX / oldScale; + midY -= fd.canvas.translateOffsetY / oldScale; + scale /= oldScale; + + fd.canvas.translate(midX, midY); + canvas.scale(scale, scale); + + if(!animation.busyCanvas){ + fd.plot(); + } + } // show text only if it is big enough canvas.showLabels = (canvas.scaleOffsetX > canvas.labelThreshold); - - fd.plot(); } @@ -1736,7 +1767,6 @@ function GraphFlow(){ @param forced - if true, no event listener will be called and the node will be created no matter what */ this.addNode = function(xPosition, yPosition, nodeFamily, repositoryPorts, inputPorts, outputPorts, nodeType, forced){ - // determine array size var countRepo = 0, countInput = 0, @@ -2383,6 +2413,10 @@ function GraphFlow(){ */ function setHighlight(node, noAnim){ + if(animation.busyCanvas){ + return; + } + var setter = 'current'; var isAnimated = animation.enabled; if(isAnimated){ @@ -2450,7 +2484,8 @@ function GraphFlow(){ modes: ['edge-property:lineWidth:color', 'node-property:color:dim'], transition: trans, - duration: dur + duration: dur, + onComplete: function(){fd.plot();} }); }else{ fd.plot(); @@ -2470,12 +2505,17 @@ function GraphFlow(){ */ this.markNode = function(node, strokeColor, fillColor){ - var isAnimated = animation.enabled; + var isAnimated = animation.enabled && !animation.busyCanvas; var setter = 'current'; if(isAnimated){ setter = 'end'; } - + + // do not mark edges + if(node.nodeFrom){ + return; + } + // check for valid arguments /* if(node && !validArgNode("markNode()", node)){ @@ -2531,9 +2571,10 @@ function GraphFlow(){ modes: ['edge-property:color', 'node-property:color'], transition: $jit.Trans.Quint.easeOut, - duration: animation.duration / 2 + duration: animation.duration / 2, + onComplete: function(){fd.plot();} }); - }else{ + }else if(!animation.busyCanvas){ fd.plot(); } } @@ -2577,36 +2618,38 @@ function GraphFlow(){ } // define mouseNode - json.push({ - "adjacencies": [], - "data": { - "$type": "none" - }, - "id": "#DUMMY_MOUSE_NODE" - }, - - // define gridNode - { - 'data': { - '$dim' : vertexLabelSize*4, - '$type' : 'grid', - '$color' : '#AAAAFF', - '$width' : document.getElementById(visContainer).clientWidth, - '$height': document.getElementById(visContainer).clientHeight, - '$alpha' : 0, - '$snap' : false - }, - 'id': '#DUMMY_GRID_NODE' - }, - - // define canvas node - { - 'data': { - '$dim' : vertexLabelSize*4, - '$type' : 'none' - }, - 'id': '#DUMMY_NAV_NODE' - }); + json.push( + { + "adjacencies": [], + "data": { + "$type": "none" + }, + "id": "#DUMMY_MOUSE_NODE" + }, + + // define gridNode + { + 'data': { + '$dim' : vertexLabelSize*4, + '$type' : 'grid', + '$color' : '#AAAAFF', + '$width' : document.getElementById(visContainer).clientWidth, + '$height': document.getElementById(visContainer).clientHeight, + '$alpha' : 0, + '$snap' : false + }, + 'id': '#DUMMY_GRID_NODE' + }, + + // define canvas node + { + 'data': { + '$dim' : vertexLabelSize*4, + '$type' : 'none' + }, + 'id': '#DUMMY_NAV_NODE' + } + ); diff --git a/Kieker.WebGUI/src/main/webapp/js/jit.js b/Kieker.WebGUI/src/main/webapp/js/jit.js index f4626464f35bd6f3c73e2207400e39b61fbbb33c..23d8d636b4f55d832765cbcd7934dbdccc4acb33 100644 --- a/Kieker.WebGUI/src/main/webapp/js/jit.js +++ b/Kieker.WebGUI/src/main/webapp/js/jit.js @@ -17003,17 +17003,32 @@ $jit.GraphFlow = new Class( { var iMap = this.fx.Interpolator.map; this.fx.Interpolator.canvas = - function(c, delta){ - var scale = c.scaleOffsetX; - var fromX = c.translateOffsetX/scale, - fromY = c.translateOffsetY/scale; - var toX = c.translateOffsetXEnd/scale, - toY = c.translateOffsetYEnd/scale; - - var newX = that.fx.Interpolator.compute(fromX, toX, delta), - newY = that.fx.Interpolator.compute(fromY, toY, delta); - - c.translate(newX-fromX, newY-fromY); + function(c, delta, doZoom, doTranslate){ + var scale; + + // scale + if(doZoom){ + var oldScale = c.scaleOffsetOld; + var newScale = c.scaleOffsetEnd; + scale = c.scaleOffsetX; + + newScale = that.fx.Interpolator.compute(oldScale, newScale, delta) / scale; + c.scale(newScale, newScale); + } + + // translate + if(doTranslate){ + scale = c.scaleOffsetX; + var fromX = c.translateOffsetX / scale, + fromY = c.translateOffsetY / scale; + var toX = c.translateOffsetXEnd, + toY = c.translateOffsetYEnd; + + var newX = that.fx.Interpolator.compute(fromX, toX, delta), + newY = that.fx.Interpolator.compute(fromY, toY, delta); + + c.translate(newX - fromX, newY - fromY); + } }; iMap.fillColor = "color"; @@ -17203,7 +17218,22 @@ $jit.GraphFlow.$extend = true; //prepare graph values var m = animFix.map; + var doZoom = false; + var doTrans = false; var moveCanvas = !!m.canvas; + + // prepare canvas move parameters + if(moveCanvas){ + for(var c in m.canvas){ + c = m.canvas[c]; + if(c == "zoom"){ + doZoom = true; + }else if(c == "translate"){ + doTrans = true; + } + } + } + var iterNodes = !!Object.keys(m).length; delete m.canvas; @@ -17221,7 +17251,7 @@ $jit.GraphFlow.$extend = true; } viz.canvas.clear(); if(moveCanvas){ - interp.canvas(viz.canvas, delta); + interp.canvas(viz.canvas, delta, doZoom, doTrans); } that.plot(opt, this.$animating, delta); diff --git a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml index 094f083dba218ef2982aac9c71b6b4c1a5b91233..5d26fb252f8388529c80b412b9dba0c0443fe1f2 100644 --- a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml +++ b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml @@ -68,7 +68,7 @@ // "Overwrite" the function in the template function bodyLoaded() { - postInit(); + // postInit(); } </script> </ui:define> @@ -76,7 +76,7 @@ <ui:define name="furtherForms"> <h:form id="hidden" style="display:none"> <p:remoteCommand autoRun="true" name="init" action="#{currentAnalysisEditorBean.initializeGraph()}" /> - <p:remoteCommand name="postInit" action="#{currentAnalysisEditorGraphBean.scaleToFit()}" /> + <p:remoteCommand name="postInit" action="#{currentAnalysisEditorGraphBean.scaleToFit()}" /> </h:form> <h:form id="hiddenNodeProperties" style="display:none"> <p:remoteCommand name="nodeClickCommand" action="#{currentAnalysisEditorGraphBean.nodeClicked()}" update=":propertiesForm"/> diff --git a/Kieker.WebGUI/src/main/webapp/templates/CommonTemplate.xhtml b/Kieker.WebGUI/src/main/webapp/templates/CommonTemplate.xhtml index 62d658751a2bfcd5f4c99e25767474d2ee08b80d..aa21582fc6404e49420c76c0e4622485a1f31291 100644 --- a/Kieker.WebGUI/src/main/webapp/templates/CommonTemplate.xhtml +++ b/Kieker.WebGUI/src/main/webapp/templates/CommonTemplate.xhtml @@ -17,6 +17,7 @@ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Kieker.WebGUI</title> + <link rel="stylesheet" type="text/css" href="#{root}/css/Common.css" /> <link rel="stylesheet" type="text/css" href="#{root}/css/Icons.css" />