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 7d616f5b9dfc62d3a94af8a22a272cc8ca04d5aa..67603b6c5af2ea7d65d912987d77f13aed856d4a 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
@@ -85,9 +85,9 @@ public class CurrentAnalysisEditorGraphBean {
 
 	private static final String JS_CMD_PORT_TYPE_INPUT = "inputPort";
 	private static final String JS_CMD_ADD_EDGE = "graph.addEdge('%s', '%s', '%s', false, false)";
-	private static final String JS_CMD_ADD_FILTER = "graph.addNode(%d, %d, %s,[%s],[%s],[%s],'Filter', false)";
-	private static final String JS_CMD_ADD_READER = "graph.addNode(%d, %d, %s,[%s],null,[%s], 'Reader', false)";
-	private static final String JS_CMD_ADD_REPOSITORY = "graph.addNode(%d, %d, %s, null, [%s], null, 'Repository',false)";
+	private static final String JS_CMD_ADD_FILTER = "var center = graph.getScreenCenter(); graph.addNode(center.x, center.y, %s,[%s],[%s],[%s],'Filter', false)";
+	private static final String JS_CMD_ADD_READER = "var center = graph.getScreenCenter(); graph.addNode(center.x, center.y, %s,[%s],null,[%s], 'Reader', false)";
+	private static final String JS_CMD_ADD_REPOSITORY = "var center = graph.getScreenCenter(); graph.addNode(center.x, center.y, %s, null, [%s], null, 'Repository',false)";
 
 	private static final String JS_CMD_ENABLE_GRID = "graph.setGridVisible(true, false)";
 	private static final String JS_CMD_DISABLE_GRID = "graph.setGridVisible(false, false)";
@@ -190,10 +190,9 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The filter which should be added to the graph.
 	 */
 	public void addFilter(final MIFilter filter) {
-		RequestContext.getCurrentInstance().execute(
-				String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_FILTER, 0, 0, this.assembleGraphString(filter),
-						this.assembleGraphRepositoryPortString(filter.getRepositories()), this.assembleGraphInputPortString(filter),
-						this.assembleGraphOutputPortString(filter)));
+		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_FILTER, this.assembleGraphString(filter),
+				this.assembleGraphRepositoryPortString(filter.getRepositories()), this.assembleGraphInputPortString(filter),
+				this.assembleGraphOutputPortString(filter)));
 	}
 
 	/**
@@ -203,7 +202,7 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The reader which should be added to the graph.
 	 */
 	public void addReader(final MIReader reader) {
-		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_READER, 0, 0, this.assembleGraphString(reader),
+		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_READER, this.assembleGraphString(reader),
 				this.assembleGraphRepositoryPortString(reader.getRepositories()), this.assembleGraphOutputPortString(reader)));
 	}
 
@@ -216,8 +215,8 @@ public class CurrentAnalysisEditorGraphBean {
 	public void addRepository(final MIRepository repository) {
 		final String repoPort = String.format(CurrentAnalysisEditorGraphBean.JS_CMD_PORT, CurrentAnalysisEditorGraphBean.JS_CMD_PORT_TYPE_INPUT,
 				CurrentAnalysisEditorGraphBean.REPOSITORY_INPUT_PORT, "N/A");
-		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_REPOSITORY, 0, 0,
-				this.assembleGraphString(repository), repoPort));
+		RequestContext.getCurrentInstance().execute(
+				String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_REPOSITORY, this.assembleGraphString(repository), repoPort));
 	}
 
 	/**
diff --git a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js
index d54d6adff103cd2e019c6568fc4d6a5798f0ac46..90afa0eec4be6291cd335a4c386c34b035f72c09 100644
--- a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js
+++ b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js
@@ -144,12 +144,8 @@ function GraphFlow(){
 		 // screen position
 		 'centerX' : 0,
 		 'centerY' : 0,
-		 // these determine when the screen should move with a dragged node
-		/* 'borderLeft' : 0,
-		 'borderRight' : 0,
-		 'borderTop' : 0,
-		 'borderBottom' : 0,
-		 */
+		 'isDragging' : false,
+		 'isDraggingEdge' : false,
 		 // how far a the screen is dragged / where a dragged node is touched
 		 'dragX' : null,
 		 'dragY' : null};
@@ -924,11 +920,6 @@ function GraphFlow(){
 		// prepare loop variables
 		var node, data, adja, x, y;
 		
-		var left  	= Number.POSITIVE_INFINITY,
-			right 	= Number.NEGATIVE_INFINITY, 
-			top		= Number.POSITIVE_INFINITY, 
-			bottom	= Number.NEGATIVE_INFINITY;
-		
 		var id, width, height;
 		var xOffset = -grid.data.$width/2,
 			yOffset = -grid.data.$height/2;
@@ -959,12 +950,6 @@ function GraphFlow(){
 				width = parseFloat(nodeProps[p++]);
 				height = parseFloat(nodeProps[p]);
 				
-				// calculate new center of graph
-				left = Math.min(left, x - width / 2);
-				right = Math.max(right, x + width / 2);
-				top = Math.min(top, y - height / 2);
-				bottom = Math.max(bottom, y + height / 2);
-				
 				// is custom node
 				if(node.data.$custom){
 					
@@ -1053,27 +1038,11 @@ function GraphFlow(){
 			
 		}
 		
+		// scale to fit the new graph
+		scaleToFit(true);
 		
-		
-		// 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 midX = -(left + right) / 2,
-			midY = -(top + bottom) / 2;
-		
+		// animate if necessary
 		if(isAnimated){
-			
-			// set animation parameters
-			canvas.translateOffsetXEnd = midX;
-		  	canvas.translateOffsetYEnd = midY;
-		  	
-		  	canvas.scaleOffsetOld = oldScale;
-		  	canvas.scaleOffsetEnd = scale;
 		  	
 		  	animation.busyCanvas = true;
 			fd.animate({  
@@ -1082,17 +1051,6 @@ function GraphFlow(){
 				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;
@@ -1346,56 +1304,147 @@ function GraphFlow(){
 		}
 	}
 	
+	
 	/**
-		Scales and centers the graph to fit the space provided by the container
-		in which it is drawn.
-	*/
-	this.scaleToFit = function(){
-		// do nothing if the graph is empty
-		if(fd.graph.nodes.length == 2){
-			return;
-		}
-		
-		var isAnimated = animation.enabled && !animation.busyCanvas;
+	 *  Returns the bounds and the exact center of the graph as an 
+	 *  {x, y, left, right, top, bottom}-Object
+	 *  @param checkEndPos - if true, checks the endPos instead of pos
+	 *  					 of the node. This is used by autoLayout.
+	 */
+	this.getGraphBounds = function(checkEndPos){
 		
 		// init loop variables
-		var data,
+		var data, 
 			width  = 0,
 			height = 0;
 		
+		// the position of the node which is checked
+		var pos = 'pos';
+		if(checkEndPos){
+			pos = 'endPos';
+		}
+		
+		var x, y;
+		var b, bendPoints;
+		
 		// 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;
 		
+		// this function checks the position of bendPoints
+		var checkBendPoints = function(node){
+			node.eachAdjacency(function(adja){
+				
+				data = adja.data;
+				
+				// is the first node the source node?
+				if(adja.nodeFrom.id == data.$direction[0]){
+					bendPoints = data.$bendPoints;
+					for(b in bendPoints){
+						b = bendPoints[b];
+						
+						x = b.x;
+						y = b.y;
+						
+						left = Math.min(left, x);
+						right = Math.max(right, x);
+						top = Math.min(top, y);
+						bottom = Math.max(bottom, y);
+					}
+					
+				}
+			});
+		};
+		
 		// check nodeFamilies for position
 		iterateAllNodes(function(node){
 			data = node.data;
 			
 			if(data.$custom || data.$type == "nodeFamily"){
 			
+				x = node[pos].x;
+				y = node[pos].y;
+				
 				width  = data.$width/2;
 				height = data.$height/2;
-			
-				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);
 				
+				left = Math.min(left, x - width);
+				right = Math.max(right, x + width);
+				top = Math.min(top, y - height);
+				bottom = Math.max(bottom, y + height);
+				
+				if(data.$custom){
+					checkBendPoints(node);
+				}
+			}
+			// is a port
+			else{
+				checkBendPoints(node);
 			}
 		});
 		
+		var midX = (left + right) / 2,
+			midY = (top + bottom) / 2;
+		
+		var bounds = 
+			{
+				'x' : midX,
+				'y' : midY,
+				'left' : left,
+				'right' : right,
+				'top' : top,
+				'bottom' : bottom
+			};
+		
+		return bounds;
+	}
+	
+	
+	/**
+	 *  Returns the exact center of the canvas where the screen is currently located
+	 *  as an {x, y}-Object
+	 */
+	this.getScreenCenter = function(){
+		var canvas = fd.canvas,
+			scale = canvas.scaleOffsetX,
+			centerX = -canvas.translateOffsetX / scale,
+			centerY = -canvas.translateOffsetX / scale;
+		
+		return {'x' : centerX, 'y' : centerY};
+	}
+	
+	/**
+		Scales and centers the graph to fit the space provided by the container
+		in which it is drawn.
+		@param forLoadPositions - if exists and true, the animation won't be called,
+				   and the endPos of nodes will be checked. These are
+				   the positions where the nodes will be after the 
+				   animation.
+	*/
+	this.scaleToFit = function(forLoadPositions){
+		// do nothing if the graph is empty
+		if(fd.graph.nodes.length == 2){
+			return;
+		}
+		
+		var isAnimated = animation.enabled && !animation.busyCanvas;
+		
+		// get graph bounds
+		var bounds = getGraphBounds(forLoadPositions && isAnimated);
+		
 		// 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)
+			scaleX = grid.data.$width / (bounds.right - bounds.left + 4*vertexLabelSize),
+			scaleY = grid.data.$height / (bounds.bottom - bounds.top + 4*vertexLabelSize)
 			scale = Math.min(scaleX, scaleY);
 		
 		// translation values
-		var midX = -(left + right) / 2,
-			midY = -(top + bottom) / 2;
+		var midX = - bounds.x,
+			midY = - bounds.y;
+		
 		
 		if(isAnimated){
 			
@@ -1406,13 +1455,15 @@ function GraphFlow(){
 		  	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();}
-			});
+		  	if(!forLoadPositions){
+		  		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
@@ -2037,15 +2088,15 @@ function GraphFlow(){
 	 */
 	 function moveNode(node, x, y, smoothMove){
 	
-		var isAnimated = smoothMove;
+		var data = node.data;
 		 
 		// snap to grid
-		if(grid.data.$snap){
+		if(!smoothMove && grid.data.$snap && data.$movable){
 			var gridDim = grid.data.$dim,
-				left = (x - node.data.$width/2),
-				top = (y - node.data.$height/2),
-				right = (x + node.data.$width/2),
-				bottom = (y + node.data.$height/2),
+				left = (x - data.$width/2),
+				top = (y - data.$height/2),
+				right = (x + data.$width/2),
+				bottom = (y + data.$height/2),
 				
 				offLeft = Math.abs(left % gridDim),
 				offTop = Math.abs(top % gridDim),
@@ -2104,7 +2155,7 @@ function GraphFlow(){
 			deltaY = y - pos.y;
 		
 		// move parent
-		if(isAnimated){
+		if(smoothMove){
 			node.setPos(new $jit.Complex(x, y), "end");
 		}else{
 			node.pos.setc(x, y);
@@ -2119,7 +2170,7 @@ function GraphFlow(){
 				 
 				 child = children[c];
 				 pos = child.pos.getc(true);
-				 moveNode(child, pos.x + deltaX, pos.y + deltaY, isAnimated);
+				 moveNode(child, pos.x + deltaX, pos.y + deltaY, smoothMove);
 			 }
 		}
 	 }
@@ -2283,12 +2334,14 @@ function GraphFlow(){
 			}
 			
 			selectedNode = null;
+			
 			return newEdge;
 		}
 		// first node clicked
 		else{
 			selectedNode = {"id": nodeID, "isIncoming" : isIncoming, "label" : label};
 			
+			navi.isDraggingEdge = true;
 			// determine direction of mouse edge
 			if(isIncoming){
 				return addEdge(mouseNode.id, nodeID, label, data);
@@ -2583,7 +2636,7 @@ function GraphFlow(){
    * @returns true if a mouse edge exists
    */
   this.isEdgeDragged = function(){
-	  return !!selectedNode;
+	  return navi.isDraggingEdge;
   }
   
   /**
@@ -2639,15 +2692,6 @@ function GraphFlow(){
 			'$snap'   : false
 		},
 		'id':	'#DUMMY_GRID_NODE'
-		},
-		
-		// define canvas node
-		{ 
-		'data': {
-			'$dim' 	 : vertexLabelSize*4,
-			'$type'	 : 'none'
-		},
-		'id':	'#DUMMY_NAV_NODE'
 		}
 	);
 	
@@ -2797,7 +2841,6 @@ function GraphFlow(){
 				
 			    navi.dragX = e.layerX; //e.pageX;
 				navi.dragY = e.layerY; //e.pageY;
-				navi.isDragging = true;
 				return;
 			}
 			
@@ -2811,6 +2854,9 @@ function GraphFlow(){
 				navi.dragX = nodePos.x - mousePos.x;
 				navi.dragY = nodePos.y - mousePos.y;
 				
+				// is dragging a node
+				navi.isDragging = true;
+				
 				/*
 				// memorize the node position before node movement
 				navi.dragX = nodePos.x;
@@ -2830,7 +2876,6 @@ function GraphFlow(){
 		   */
 		  onDragMove: function(node, eventInfo, e) {
 			if(!node || !node.data.$movable || selectedNode || !readOnly.move){
-				// || node.id == mouseNode.id){
 					return;
 			}
 			
@@ -2840,25 +2885,6 @@ function GraphFlow(){
 				y = pos.y + navi.dragY;
 			moveNode(node, x, y);
 			
-			// move screen if near edge
-			/*
-			var screenX = e.layerX,
-				screenY = e.layerY;
-				
-			if(screenX < navi.borderLeft && x < navi.dragX){
-				fd.canvas.translate(20,0);
-			}
-			else if(screenX > navi.borderRight && x > navi.dragX){
-				fd.canvas.translate(-20,0);
-			}
-			
-			if(screenY < navi.borderTop && y < navi.dragY){
-				fd.canvas.translate(0,20);
-			}
-			else if(screenY > navi.borderBottom && y > navi.dragY){
-				fd.canvas.translate(0,-20);
-			}
-			*/
 			callListener("onDragMove", [node, eventInfo, e]);
 			fd.plot();
 			
@@ -2902,6 +2928,7 @@ function GraphFlow(){
 				for(var c in children){
 					updateOffset(children[c]);
 				}
+				
 			}
 			
 			fd.plot();
@@ -2921,6 +2948,7 @@ function GraphFlow(){
 		  onClick: function(node, eventInfo, e){
 		  
 		  var isNotDragging = true;
+		  var wasDraggingEdge = navi.isDraggingEdge;
 		  
 		  // set mouse position (required for dragging edges)
 		  var pos = eventInfo.getPos();
@@ -2986,6 +3014,11 @@ function GraphFlow(){
 		  }
 		  
 		  navi.isDragging = false;
+		  
+		  if(wasDraggingEdge){
+			  navi.isDraggingEdge = false;
+		  }
+		  
 		  },
 		  
 		  /**