diff --git a/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar b/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar index ce5c3fec4b7d7afd9df08081d70171ea142193e6..3e3f56ed47646c6fe7c628362c8def97ee54533e 100644 Binary files a/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar and b/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar differ diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorBean.java index 307beb5f317cf3f38c8b2197fadd54ed7e5ad06e..46546c7d184a90eef105792ce802f0b3cc95a24d 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorBean.java @@ -454,6 +454,27 @@ public final class CurrentAnalysisEditorBean { } } + public String getDependencies(final Class<?> clazz) { + // Get the two potential annotations + final Annotation annotationPlugin = clazz.getAnnotation(this.classAndMethodContainer.getPluginAnnotationClass()); + final Annotation annotationRepository = clazz.getAnnotation(this.classAndMethodContainer.getRepositoryAnnotationClass()); + + final Method pluginDepMethod = this.classAndMethodContainer.getPluginDependenciesMethod(); + final Method repoDepMethod = this.classAndMethodContainer.getRepositoryDependenciesMethod(); + + // Now check which one of them is available + if ((annotationPlugin == null)) { + if ((annotationRepository == null)) { + // None. Deliver a human readable substitute. + return "No dependency information available"; + } else { + return (String) ClassAndMethodContainer.invokeMethod(repoDepMethod, annotationRepository, "No dependency information available"); + } + } else { + return (String) ClassAndMethodContainer.invokeMethod(pluginDepMethod, annotationPlugin, "No dependency information available"); + } + } + /** * Delivers the description of the property of the given component (plugin or repository). * diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorGraphBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorGraphBean.java index 68f95456f8ebf8648cce97ba9e44c454824f4ff8..b8bcff5c6c2b1273534dce411e76c9e64860f41e 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorGraphBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentAnalysisEditorGraphBean.java @@ -121,10 +121,10 @@ public class CurrentAnalysisEditorGraphBean { private static final String JS_CMD_RENAME_NODE = "graph.getNode(%s).name = '%s';"; private static final Object REPOSITORY_INPUT_PORT = "R"; - private static final String JS_CMD_ENABLE_GRID = ""; - private static final String JS_CMD_DISABLE_GRID = ""; - private static final String JS_CMD_ENABLE_SNAP = ""; - private static final String JS_CMD_DISABLE_SNAP = ""; + private static final String JS_CMD_ENABLE_GRID = "graph.setGridVisible(true);"; + private static final String JS_CMD_DISABLE_GRID = "graph.setGridVisible(false);"; + private static final String JS_CMD_ENABLE_SNAP = "graph.setGridSnap(true);"; + private static final String JS_CMD_DISABLE_SNAP = "graph.setGridSnap(false);"; private static final String JS_CMD_SCALE_TO_FIT = "graph.scaleToFit();"; private boolean gridEnabled = false; @@ -496,6 +496,9 @@ public class CurrentAnalysisEditorGraphBean { } } + /** + * This method scales the graph to fit the current view. After this method-call, all components of the graph should be visible. + */ public void scaleToFit() { RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_SCALE_TO_FIT); } @@ -508,6 +511,8 @@ public class CurrentAnalysisEditorGraphBean { } this.gridEnabled = !this.gridEnabled; + + this.refreshGraph(); } public void switchSnap() { diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java index ed6d3840495e6b1d5337c89e4c41198b278e0332..5abfdc65c93357d3ef06c1c2a697f4b9dc598d64 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java @@ -223,7 +223,9 @@ public final class ClassAndMethodContainer { * This is the loadFromFile(File)-method of the class equivalence of {@link AnalysisController}. */ private final Method analysisControllerLoadFromFile; - private Method displayDescriptionMethod; + private final Method displayDescriptionMethod; + private final Method pluginDependenciesMethod; + private final Method repositoryDependenciesMethod; /** * This is the constructor for {@link AnalysisControllerThread}, which gets an instance of {@link AnalysisController}. */ @@ -280,7 +282,8 @@ public final class ClassAndMethodContainer { this.analysisControllerGetState = this.analysisControllerClass.getMethod("getState", new Class<?>[0]); this.propertyDescriptionMethod = this.propertyAnnotationClass.getMethod("description", new Class<?>[0]); this.displayDescriptionMethod = this.displayAnnotationClass.getMethod("description", new Class<?>[0]); - + this.pluginDependenciesMethod = this.pluginAnnotationClass.getMethod("dependencies", new Class<?>[0]); + this.repositoryDependenciesMethod = this.repositoryAnnotationClass.getMethod("dependencies", new Class<?>[0]); // This is a special case as we need to load some additional classes to search for the correct method final Class<?> miProjectClass = classLoader.loadClass(MIProject.class.getName()); this.analysisControllerLoadFromFile = this.analysisControllerClass.getMethod("loadFromFile", File.class); @@ -673,6 +676,10 @@ public final class ClassAndMethodContainer { return this.analysisControllerLoadFromFile; } + public Method getPluginDependenciesMethod() { + return pluginDependenciesMethod; + } + /** * The getter-method for the field {@link ClassAndMethodContainer#displayDescriptionMethod}. * @@ -682,6 +689,10 @@ public final class ClassAndMethodContainer { return this.displayDescriptionMethod; } + public Method getRepositoryDependenciesMethod() { + return repositoryDependenciesMethod; + } + /** * This method can be used to invoke a given method with given parameters, without having to mind about the exceptions. If an exception occurs, the given default * value will be returned. diff --git a/Kieker.WebGUI/src/main/resources/kieker-1.6-SNAPSHOT_emf.jar b/Kieker.WebGUI/src/main/resources/kieker-1.6-SNAPSHOT_emf.jar index ce5c3fec4b7d7afd9df08081d70171ea142193e6..3e3f56ed47646c6fe7c628362c8def97ee54533e 100644 Binary files a/Kieker.WebGUI/src/main/resources/kieker-1.6-SNAPSHOT_emf.jar and b/Kieker.WebGUI/src/main/resources/kieker-1.6-SNAPSHOT_emf.jar differ diff --git a/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml b/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml index d7033c9d2d74f4688b8e799905cfae0313591d0a..935666ce457bcd7528af936e07a6976b6ebee37e 100644 --- a/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml +++ b/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml @@ -97,8 +97,8 @@ <p:submenu label="Graph"> <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-search" value=" Scale To Fit" ajax="true" action="#{currentAnalysisEditorGraphBean.scaleToFit()}" /> <p:separator/> - <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-grip-dotted-horizontal" value=" Enable/Disable Grid" ajax="true" /> - <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-link" value=" Enable/Disable Snap" ajax="true" /> + <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-grip-dotted-horizontal" value=" #{currentAnalysisEditorGraphBean.gridEnabled ? 'Disable' : 'Enable'} Grid" ajax="true" action="#{currentAnalysisEditorGraphBean.switchGrid()}" update=":menuForm"/> + <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-link" value=" #{currentAnalysisEditorGraphBean.snapEnabled ? 'Disable' : 'Enable'} Snap" ajax="true" action="#{currentAnalysisEditorGraphBean.switchSnap()}" update=":menuForm"/> <p:separator/> <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-shuffle" value=" Auto-Layout" ajax="true" /> </p:submenu> @@ -114,10 +114,10 @@ <p:spacer height="5"/> <p:menubar> <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-search" value=" Scale To Fit" ajax="true" action="#{currentAnalysisEditorGraphBean.scaleToFit()}" /> - <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-grip-dotted-horizontal" value=" #{currentAnalysisEditorGraphBean.gridEnabled ? 'Disable' : 'Enable'} Grid" ajax="true" action="#{currentAnalysisEditorGraphBean.switchGrid()}" update=":menuForm"/> + <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-grip-dotted-horizontal" value=" #{currentAnalysisEditorGraphBean.gridEnabled ? 'Disable' : 'Enable'} Grid" ajax="true" action="#{currentAnalysisEditorGraphBean.switchGrid()}" update=":menuForm"/> <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-link" value=" #{currentAnalysisEditorGraphBean.snapEnabled ? 'Disable' : 'Enable'} Snap" ajax="true" action="#{currentAnalysisEditorGraphBean.switchSnap()}" update=":menuForm"/> <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-shuffle" value=" Auto-Layout" ajax="true" /> - </p:menubar> + </p:menubar> </h:form> </p:layoutUnit> @@ -163,7 +163,7 @@ <!-- The following is the toolpalette, presenting the available plugins etc. --> <p:layoutUnit position="east" size="300" header="Available Plugins" resizable="true" collapsible="true"> <h:form id="toolpalette"> - <p:accordionPanel multiple="true" activeIndex=""> + <p:accordionPanel multiple="true" activeIndex="0,1,2"> <p:tab title="Reader"> <ui:repeat value="#{currentAnalysisEditorBean.availableReaders}" var="reader"> <p:commandLink id="readerLink" value="#{reader.simpleName}" action="#{currentAnalysisEditorBean.addPlugin(reader)}" update=":messages" /><br/> @@ -172,18 +172,29 @@ <br/> <h:outputText value="#{currentAnalysisEditorBean.getDescription(reader)}"/> <br/><br/> - <b><h:outputText value="Output Ports:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getOutputPorts(reader)}" var="port"> - #{port.name()} - </p:dataList> - <b><h:outputText value="Repository Ports:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getRepositoryPorts(reader)}" var="port"> - #{port.name()} - </p:dataList> - <b><h:outputText value="Configuration:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getProperties(reader)}" var="property"> - #{property.name()} - </p:dataList> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getOutputPorts(reader)}"> + <b><h:outputText value="Output Ports:"/></b> + <p:dataList value="#{currentAnalysisEditorBean.getOutputPorts(reader)}" var="port"> + #{port.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getRepositoryPorts(reader)}"> + <b><h:outputText value="Repository Ports:" /></b> + <p:dataList value="#{currentAnalysisEditorBean.getRepositoryPorts(reader)}" var="port"> + #{port.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getProperties(reader)}"> + <b><h:outputText value="Configuration:"/></b> + <p:dataList value="#{currentAnalysisEditorBean.getProperties(reader)}" var="property"> + #{property.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getDependencies(reader)}"> + <b><h:outputText value="Dependencies:"/></b> + <br/> + <h:outputText value="#{currentAnalysisEditorBean.getDependencies(reader)}"/> + </ui:fragment> </p:tooltip> </ui:repeat> </p:tab> @@ -195,22 +206,35 @@ <br/> <h:outputText value="#{currentAnalysisEditorBean.getDescription(filter)}"/> <br/><br/> - <b><h:outputText value="Input Ports:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getInputPorts(filter)}" var="port"> - #{port.name()} - </p:dataList> - <b><h:outputText value="Output Ports:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getOutputPorts(filter)}" var="port"> - #{port.name()} - </p:dataList> - <b><h:outputText value="Repository Ports:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getRepositoryPorts(filter)}" var="port"> - #{port.name()} - </p:dataList> - <b><h:outputText value="Configuration:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getProperties(filter)}" var="property"> - #{property.name()} - </p:dataList> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getInputPorts(filter)}"> + <b><h:outputText value="Input Ports:"/></b> + <p:dataList value="#{currentAnalysisEditorBean.getInputPorts(filter)}" var="port"> + #{port.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getOutputPorts(filter)}"> + <b><h:outputText value="Output Ports:"/></b> + <p:dataList value="#{currentAnalysisEditorBean.getOutputPorts(filter)}" var="port"> + #{port.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getRepositoryPorts(filter)}"> + <b><h:outputText value="Repository Ports:"/></b> + <p:dataList value="#{currentAnalysisEditorBean.getRepositoryPorts(filter)}" var="port"> + #{port.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getProperties(filter)}"> + <b><h:outputText value="Configuration:"/></b> + <p:dataList value="#{currentAnalysisEditorBean.getProperties(filter)}" var="property"> + #{property.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getDependencies(filter)}"> + <b><h:outputText value="Dependencies:"/></b> + <br/> + <h:outputText value="#{currentAnalysisEditorBean.getDependencies(filter)}"/> + </ui:fragment> </p:tooltip> </ui:repeat> </p:tab> @@ -222,10 +246,17 @@ <br/> <h:outputText value="#{currentAnalysisEditorBean.getDescription(repository)}"/> <br/><br/> - <b><h:outputText value="Configuration:"/></b> - <p:dataList value="#{currentAnalysisEditorBean.getProperties(repository)}" var="property"> - #{property.name()} - </p:dataList> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getProperties(repository)}"> + <b><h:outputText value="Configuration:"/></b> + <p:dataList value="#{currentAnalysisEditorBean.getProperties(repository)}" var="property"> + #{property.name()} + </p:dataList> + </ui:fragment> + <ui:fragment rendered="#{not empty currentAnalysisEditorBean.getDependencies(repository)}"> + <b><h:outputText value="Dependencies:"/></b> + <br/> + <h:outputText value="#{currentAnalysisEditorBean.getDependencies(repository)}"/> + </ui:fragment> </p:tooltip> </ui:repeat> </p:tab> diff --git a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js index 4497d1583918c9086fb754e8f7fa16ef18c07bd6..36ef8a34ca2e10edd58d4f7a65c62e2da4ce987d 100644 --- a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js +++ b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js @@ -103,12 +103,18 @@ function GraphFlow(){ var readOnly = {'deleteCreate' : true, 'move' : true}; - /** Options concerning the grid. + /** Options concerning the grid. */ - var grid = {'size' : 32, - 'visible': true, - 'snap' : false, - 'color' : '#0000FF'};*/ + var grid = { 'data': {'$dim' : vertexLabelSize*4, + '$type' : 'grid', + '$color' : '#AAAAFF', + '$width' : document.getElementById(visContainer).clientWidth, + '$height': document.getElementById(visContainer).clientHeight + }, + 'id': '#DUMMY_GRID_NODE', + 'visible': false, + 'snap' : false + }; /** Stores information about the canvas, such as its dimensions and its position */ @@ -124,6 +130,36 @@ function GraphFlow(){ // FUNCTIONS // ///////////////////////////////////////////// + + /** + Changes the color of the grid. Requires a refresh(). + */ + this.setGridColor = function(newColor){ + grid.data.$color = newColor; + } + + /** + Changes the size of the grid. Requires a refresh(). + */ + this.setGridSize = function(newSize){ + grid.data.$dim = newSize; + } + + /** + Changes the visibility of the grid. Requires a refresh(). + */ + this.setGridVisible = function(visibility){ + grid.visible = visibility; + } + + /** + Changes whether Nodes should snap to grid. Requires a refresh(). + */ + this.setGridSnap = function(snap){ + grid.snap = snap; + } + + /** Scales and centers the graph to fit the space provided by the container in which it is drawn. @@ -409,6 +445,10 @@ function GraphFlow(){ var mouseIndex = jsonCapacity.max; fd.loadGraphFlowJSON(json, mouseIndex); + + if(grid.visible){ + fd.graph.addNode(grid); + } fd.plot(); // set the mouseNode to the freshly created graph node @@ -895,12 +935,73 @@ function GraphFlow(){ /** Moves a nodeFamily and its subnodes to the specified position. */ - function moveNode(x, y){ - var nodes = navi.draggedNodes; + function moveNode(xPos, yPos){ + var nodes = navi.draggedNodes, + node = nodes[0], + dim = node.data.$dim; + var x = xPos, + y = yPos; + + // snap to grid + if(grid.snap){ + var gridDim = grid.data.$dim, + left = (xPos - node.data.$width/2), + top = (yPos - node.data.$height/2), + right = (xPos + node.data.$width/2), + bottom = (yPos + node.data.$height/2), + + offLeft = Math.abs(left % gridDim), + offTop = Math.abs(top % gridDim), + offRight = Math.abs(right % gridDim), + offBottom = Math.abs(bottom % gridDim), + threshold = gridDim/6; + if(top > 0){ + offTop = gridDim - offTop; + } + if(bottom > 0){ + offBottom = gridDim - offBottom; + } + if(left > 0){ + offLeft = gridDim - offLeft; + } + if(right > 0){ + offRight = gridDim - offRight; + } + + // snap to closest gridline + if(offLeft < threshold) { + x += offLeft; + } + if(offRight < threshold) { + x += offRight; + } + else if(offLeft > gridDim - threshold){ + x -= gridDim-offLeft; + } + else if(offRight > gridDim - threshold){ + x -= gridDim-offRight; + } + + if(offTop < threshold) { + y += offTop; + } + + else if(offTop > gridDim - threshold){ + y -= gridDim-offTop; + } + + else if(offBottom < threshold) { + y += offBottom; + } + + else if(offBottom > gridDim - threshold){ + y -= gridDim-offBottom; + } + } + + // set position of nodeFamily - var node = nodes[0], - dim = node.data.$dim; node.pos.setc(x, y); // set position of ports and crossbox @@ -999,7 +1100,6 @@ function GraphFlow(){ var adja = source.adjacencies; // source node does not exist? if(adja == undefined){ - Log.write("Error: "+sourceID+" does not exist!"); return false; } @@ -1200,7 +1300,7 @@ function GraphFlow(){ //Enable panning events only if we're dragging the empty //canvas (and not a node). panning: 'avoid nodes', - zooming: 10 //zoom speed. higher is more sensible + zooming: 40 //zoom speed. higher is more sensible }, // Change node and edge styles such as // color and width. @@ -1257,17 +1357,6 @@ function GraphFlow(){ callListener("onRightClick", [node, eventInfo, e]); }, - /** - * EVENT: OnDragEnd - */ - onDragEnd: function(node, eventInfo, e) { - if(node.data.$type == "nodeFamily"){ - saveNodeMove(); - } - fd.plot(); - callListener("onDragEnd", [node, eventInfo, e]); - }, - /** * EVENT: OnDragCancel */ @@ -1382,6 +1471,17 @@ function GraphFlow(){ }, + /** + * EVENT: OnDragEnd + */ + onDragEnd: function(node, eventInfo, e) { + if(node.data.$type == "nodeFamily"){ + saveNodeMove(); + } + fd.plot(); + callListener("onDragEnd", [node, eventInfo, e]); + }, + /** * EVENT: OnTouchMove */ @@ -1400,7 +1500,6 @@ function GraphFlow(){ deltaY = e.pageY - navi.dragY; navi.centerX -= deltaX; navi.centerY -= deltaY; - Log.write(" Offset:"+fd.canvas.translateOffsetX+","+fd.canvas.translateOffsetY); //fd.canvas.translate(deltaX, deltaY); } else if(mouseOverNode && readOnly.deleteCreate){ @@ -1542,7 +1641,6 @@ function GraphFlow(){ }*/ }); - fd.setNavi(navi); // load JSON data. fd.loadGraphFlowJSON(json,jsonCapacity.max); diff --git a/Kieker.WebGUI/src/main/webapp/js/jit.js b/Kieker.WebGUI/src/main/webapp/js/jit.js index d27fb5bdd72ce7941f0ad2dd93bd46b604652135..51c63e28681c73fead7041cee5e4840dcb58dea6 100644 --- a/Kieker.WebGUI/src/main/webapp/js/jit.js +++ b/Kieker.WebGUI/src/main/webapp/js/jit.js @@ -17387,13 +17387,6 @@ $jit.FlowGraph = new Class( { // initialize extras this.initializeExtras(); - // set grid and navi - this.grid = {'size' : 32, - 'visible': true, - 'snap' : false, - 'color' : '#0000FF'}; - this.navi = false; - }, /* @@ -17493,7 +17486,6 @@ $jit.FlowGraph = new Class( { */ plot: function() { this.canvas.clear(); - //this.drawGrid(); this.fx.plotGraphFlow(); }, @@ -17506,60 +17498,7 @@ $jit.FlowGraph = new Class( { this.fx.animate($.merge( { modes: [ 'linear' ] }, opt || {})); - }, - - /* - Merhod: drawGrid - - Draws a grid onto the canvas. - */ - drawGrid: function(){ - var grid = this.grid, - navi = this.navi; - - if(!grid || !grid.visible || !navi){ - return; - } - - var centerX = - this.canvas.translateOffsetX, - centerY = - this.canvas.translateOffsetY, - size = grid.size, - width = navi.width/2, - height = navi.height/2, - left = centerX - width, - up = centerY - height, - ctx = this.canvas.getCtx(); - - ctx.strokeStyle = grid.color; - ctx.beginPath(); - - // draw vertical lines - for(var x = left - centerX % size, l = left + navi.width; x < l; x += size){ - ctx.moveTo(x, up); - ctx.lineTo(x, height); - } - // draw horizontal lines - for(var y = up - centerY % size, l = up + navi.height; y < l; y += size){ - ctx.moveTo(left, y); - ctx.lineTo(width, y); - } - - ctx.stroke(); - }, - -/* - Method: setNavi - - Performs the Force Directed algorithm incrementally. - - Parameters: - - grid - (object) An Object which contains grid properties such as size and color. - navi - (object) An Object which contains the screen dimensions and position. -*/ - setNavi: function(navi){ - this.navi = navi; - } + } }); @@ -18158,7 +18097,44 @@ $jit.FlowGraph.$extend = true; return Math.abs(pos.x - npos.x) <= size && Math.abs(pos.y - npos.y-size) <= size; } }, - + + 'grid': { + 'render': function(grid, canvas){ + + var scale = canvas.scaleOffsetX, + centerX = - canvas.translateOffsetX/scale, + centerY = - canvas.translateOffsetY/scale, + size = grid.data.$dim, + width = grid.data.$width/(2*scale), + height = grid.data.$height/(2*scale), + left = centerX - width, + up = centerY - height, + right = centerX + width, + bottom = centerY + height, + ctx = canvas.getCtx(); + + ctx.lineWidth = 1; + ctx.beginPath(); + // draw vertical lines + for(var x = left - (left % size), l = centerX + width; x < l; x += size){ + ctx.moveTo(x, up); + ctx.lineTo(x, bottom); + + } + + // draw horizontal lines + for(var y = up - (up % size), l = centerY + height; y < l; y += size){ + ctx.moveTo(left, y); + ctx.lineTo(right, y); + } + + ctx.stroke(); + }, + + 'contains': function(node, pos){ + return false; + } + } }); /*