diff --git a/Kieker.WebGUI/src/main/webapp/css/FlowEditor.css b/Kieker.WebGUI/src/main/webapp/css/FlowEditor.css
index eb0b8e77bcc6002603699b20d9087faad23bb02a..e442b7aab89218a9db809aadfcc8a86ba734611f 100644
--- a/Kieker.WebGUI/src/main/webapp/css/FlowEditor.css
+++ b/Kieker.WebGUI/src/main/webapp/css/FlowEditor.css
@@ -1,5 +1,3 @@
-@charset "UTF-8";
-
 #inner-details {
   font-size:12px;
 }
diff --git a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js
index 36ef8a34ca2e10edd58d4f7a65c62e2da4ce987d..96fef984ae4f3f92dc9cb79bf5fe1c0d4a9516ca 100644
--- a/Kieker.WebGUI/src/main/webapp/js/flowEditor.js
+++ b/Kieker.WebGUI/src/main/webapp/js/flowEditor.js
@@ -1,3 +1,21 @@
+/**************************************************************************
+
+Copyright [2012] [Software Engineering Group - Kiel University]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+***************************************************************************/
+
 var labelType, useGradients, nativeTextSupport, animate;
 
 /**
@@ -38,7 +56,7 @@ function GraphFlow(){
 	
 	var visContainer = 'infovis';
 	
-	/** Color Palettes */
+	/** Colors */
 	var nodeFillColor = [];
 		nodeFillColor['nodeFamily']		= "#DEDEDE";
 	
@@ -62,48 +80,50 @@ function GraphFlow(){
 	/** FlowGraph Object */
 	var fd;
 
-	/** Nodes and edges where the mouse moves over */
+	/** Nodes and edges that are highlighted when the mouse moves over them */
 	var hover = null;
+	var markedNode = null;
 
 	/** This array stores all Nodes and is initialized with a dummy,
-		used for drawing edges between a node and the mousepointer.
+		used for drawing edges between a node and the mousepointer. Empty
+		elements are dynamically reserved for additional nodes.
 		*/
 	var json;
 		
-	/** Used for managing space for node creation/deletion
-		since the array is divided into to parts, adding and removing nodes
-		would cause many costly splices. We a similar approach to ArrayLists. 
+	/** Used for dynamically adding and removing space for node creation/deletion
+		resulting in better performance when manipulating the json array.
 	*/
 	var jsonCapacity = {'occupied' : 0,
 						'max'  : 10};
 
-	/** selected node:	{id : <the id of the selected node, 
-						 from : <the data.$type of the selected node>}
+	/** selected node:	{id : the id of the selected node, 
+						 from : the data.$type of the selected node,
+						 label: the label of a selected edge}
 						 
 		When clicking a node or edge, this variable will contain node
-		information, that is required for creating edges.
+		information, that is required for attaching/detaching edges.
 		*/
 	var selectedNode = null;
 	
-	/** This points to the DOM-node (not the json-array node!) that is
+	/** This points to a DOM-node (not the json-array node!) which is
 		an invisible dummy for moving an edge with the mouse
 		*/
 	var mouseNode = null;
 
-	/** true if the mouse is over a port-node/edge */
+	/** true if the mouse is over a port/edge */
 	var mouseOverNode = false;
 	var mouseOverEdge = false;
 	
-	/** A hashtable of mouse and node events to arrays of functions that
-		should happen on these events
+	/** A hashtable, mapping mouse and node events to arrays of functions that
+		are called when these events happen
 		*/
 	var listener = [];
 	
-	/** Can be changed to allow or prohibit node movement or creation */
+	/** Can be changed to allow or prohibit node movement or deletion/creation */
 	var readOnly = {'deleteCreate' 	: true,
 					'move' 			: true};
 	
-	/** Options concerning the grid. */
+	/** Grid dummy-node which is drawn over the graph if it is visible */
 		
 	var grid = { 'data': {'$dim' : vertexLabelSize*4,
 						  '$type'	 : 'grid',
@@ -116,7 +136,9 @@ function GraphFlow(){
 				 'snap'   : false
 				};
 	
-	/** Stores information about the canvas, such as its dimensions and its position
+	/** Stores information about the canvas, such as its dimensions and its position.
+		This information is needed to correctly draw the Grid and may come in handy in
+		future functions.
 		*/
 	var navi = { 'width' : document.getElementById(visContainer).clientWidth,
 				 'height': document.getElementById(visContainer).clientHeight,
@@ -131,18 +153,243 @@ function GraphFlow(){
 	/////////////////////////////////////////////
 
 	
+	/**
+		Returns a XML-String, representing the graph as KGraph
+		This function is work in progress and will be tuned
+		for efficiency in the future!
+	*/
+	this.convertToKGraph = function(){
+		// define helper strings
+		var ie = '<children incomingEdges="';
+		var pt = '<ports edges="';
+		var oe = [	'<outgoingEdges target="//@children.',
+								'" sourcePort="//@children.',
+								'/@ports.',
+								'" targetPort="//@children.',
+								'">\n<data xsi:type="klayoutdata:KEdgeLayout"/>\n</outgoingEdges>\n'					
+				 ];
+		
+		// this array will contain XMI-Strings
+		var children = [],
+			indexMap = [];		// KGraphs use indices instead of IDs
+		
+		// this loop prepares the children array
+		var child;
+		for(var n = 0, l = jsonCapacity.occupied; n < l; n++){
+			// reserve space for edges
+			child = {
+						incomingEdges : ie,
+						ports :	[],
+						outgoingEdges : ""
+					};
+			// reserve space for port strings
+			for(var p = 0, pl = json[n].data.$portCount-1; p < pl; p++){ // TODO: adjust for ReadOnly
+					child.ports.push({"text":pt, "isEast":false});
+			}
+			children.push(child);
+			
+			// add node id to index map
+			indexMap[json[n].id] = n;
+		}
+		
+		// determine port indices
+		var node,
+			indexCounter = 0;
+		for(var n = jsonCapacity.max, l = json.length; n < l; n++){
+			node = json[n];
+			if(node.data.$type == "crossBox"){
+				indexCounter = 0;
+			}
+			else{
+				indexMap[json[n].id] = indexCounter;
+				indexCounter++;
+			}
+		}
+		
+		// now prepare all strings needed
+		indexCounter = -1;
+		var edgeCounter = 0, portCounter = 0;
+		var adja, edge, edgeString, targetChild, targetPort, relativeY;
+		for(var n = jsonCapacity.max+1, l = json.length; n < l; n++){
+			node = json[n];
+			if(node.data.$type == "crossBox"){ // TODO: do not rely on crossBox, make more generic
+				indexCounter++;
+				edgeCounter = 0;
+				portCounter = 0;
+			}
+			else{
+				// is the port the first of its type within the node (e.g. the first inputPort)
+				relativeY = node.data.$relativeY;
+				if(relativeY){
+					children[indexCounter].ports[portCounter].yPos = relativeY;
+				}
+			
+				// is the port positioned on the east side of the node?
+				children[indexCounter].ports[portCounter].isEast = node.data.$type == "inputPort";
+			
+				adja = node.adjacencies;
+				for(var e = 0, el = adja.length; e < el; e++){
+					edge = adja[e];
+					edgeString = "//@children."
+								+ indexCounter 
+								+"/@outgoingEdges." 
+								+ edgeCounter + " ";
+					targetChild = indexMap[edge.data.$targetFamily];
+					targetPort = indexMap[edge.nodeTo];
+					
+					// add edge info to outgoing family
+					children[indexCounter].outgoingEdges +=
+						oe[0] + targetChild + oe[1] + indexCounter + oe[2] + portCounter 
+						+ oe[3] + targetChild + oe[2] + targetPort + oe[4];
+					children[indexCounter].ports[portCounter].text += edgeString; 
+					
+					// add edge info to target family
+					children[targetChild].ports[targetPort].text += edgeString;
+					children[targetChild].incomingEdges += edgeString;
+					
+					edgeCounter++;
+				}
+				
+				portCounter++;
+			}
+		}
+		// redefine helper strings
+		ie = '">\n<data xsi:type="klayoutdata:KShapeLayout" xpos="0.0" ypos="0.0" width="';
+		pt = '">\n<data xsi:type="klayoutdata:KShapeLayout" xpos="';
+		var ie2 = '">\n<persistentEntries key="de.cau.cs.kieler.sizeConstraint" value="FIXED"/>\n'
+					+ '<persistentEntries key="de.cau.cs.kieler.portConstraints" value="FIXED_POS"/>\n<insets/>\n</data>\n',
+			pt2 = '" width="'+(vertexLabelSize*2)+'" height="'+vertexLabelSize+'">\n</data>\n</ports>\n';
+		
+		// assemble XMI-String
+		var xmi = '<?xml version="1.0" encoding="UTF-8"?>\n'
+					+ '<kgraph:KNode xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" '
+					+ 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:kgraph="http://kieler.cs.cau.de/KGraph" '
+					+ 'xmlns:klayoutdata="http://kieler.cs.cau.de/KLayoutData">\n<data xsi:type="klayoutdata:KShapeLayout" '
+					+ 'width="348.0" height="112.0">\n<persistentEntries key="de.cau.cs.kieler.sizeConstraint" value="FIXED"/>\n'
+					+ '<insets/>\n</data>\n\n';
+		var ports, xPos, yPos, width, height;
+		for(var c = 0, l = children.length; c < l; c++){
+			child = children[c];
+			width = json[c].data.$width;
+			height = json[c].data.$height;
+			xmi += child.incomingEdges + ie + width + '" height="'+ height + ie2;
+			
+			ports = child.ports;
+			for(var p = 0, pl = ports.length; p < pl; p++){
+			
+				// determine the y-Position of the port
+				relativeY = ports[p].yPos;
+				if(relativeY){
+					yPos = relativeY + height/2;
+				}
+				else{
+					yPos += 2*vertexLabelSize;
+				}
+				
+				// determine the x-Position of the port
+				if(ports[p].isEast){
+					xPos = -vertexLabelSize;
+				}
+				else {
+					xPos = width - vertexLabelSize;
+				}
+				xmi += ports[p].text + pt + xPos + '" ypos="'+ yPos +pt2;
+			}
+			
+			xmi += child.outgoingEdges + '</children>\n';
+			
+			delete children[c];
+		}
+		xmi += '</kgraph:KNode>';
+		
+		return xmi;
+	}
+	
+	/**
+		Checks an input color-string for validation.
+		Sends an onError-event if the string is not valid.
+		@param callFunction - the function where the argument needs to be checked
+		@param color - the color argument which is checked
+		@returns - false if the string is not a well formed color string 
+	*/
+	function validArgColor(callFunction, color){
+		var valid = false;
+		
+		// is it a string at all ?
+		if(typeof color == "string"){
+			// does the string match "#RRGGBB" ?
+			var regEx = /^#[a-f\d]{6}$/i;
+			valid = color.match(regEx);
+		}
+		
+		if(!valid){
+			callListener("onError", ["Error in function "+ callFunction 
+										+ ": Invalid color '"+ color 
+										+ "'. Must be structured like '#RRGGBB'."]);
+		}
+		return valid;
+	}
+	
+	
+	/**
+		Checks an input object for validation.
+		Sends an onError-event if the Object does not have an id
+		@param callFunction - the function where the argument needs to be checked
+		@param node - the object argument which is checked
+		@returns - false if the object does not have an id
+	*/
+	function validArgNode(callFunction, node){
+		var valid = false;
+		
+		// is it an object at all ?
+		if(node && typeof node == "object"){
+			// does the object have an id
+			valid = (typeof node.id != "undefined");
+		}
+		
+		if(!valid){
+			callListener("onError", ["Error in function "+ callFunction 
+										+ ": Invalid Node '"+ node 
+										+ "'. Must have a field 'id'."]);
+		}
+		return valid;
+	}
+	
+	
+	/**
+		Checks an argument for type correctness.
+		Sends an onError-event if the argument is not valid.
+		@param callFunction - the function where the argument needs to be checked
+		@param arg - the argument which is checked
+		@param type - the type of which the argument must be
+		@returns - false if the string is not a well formed color string 
+	*/
+	function validArg(callFunction, arg, type){
+		var valid = (typeof arg == type);
+		if(!valid){
+			callListener("onError", ["Error in function "+ callFunction 
+										+ ": Invalid argument type for argument '"
+										+ arg + "'. Must be of type " + type + "."]);
+		}
+		return valid;
+	}
+	
 	/**
 		Changes the color of the grid. Requires a refresh().
 	*/
 	this.setGridColor = function(newColor){
-		grid.data.$color = newColor;
+		if(validArgColor('setGridColor()', newColor)){
+			grid.data.$color = newColor;
+		}
 	}
 	
 	/**
 		Changes the size of the grid. Requires a refresh().
 	*/
 	this.setGridSize = function(newSize){
-		grid.data.$dim = newSize;
+		if(validArg('setGridSize()', newSize, 'number')){
+			grid.data.$dim = newSize;
+		}
 	}
 	
 	/**
@@ -159,7 +406,6 @@ function GraphFlow(){
 		grid.snap = snap;
 	}
 	
-	
 	/**
 		Scales and centers the graph to fit the space provided by the container
 		in which it is drawn.
@@ -238,206 +484,82 @@ function GraphFlow(){
 				  icon will be deleted
 	*/
 	this.setNodeIcon = function(nodeType, path){
+		if(!validArg('setNodeIcon()', nodeType, 'string')){
+			return;
+		}
+	
 		if(path == null){
 			delete nodeIcons[nodeType];
 			//TODO: adjust shrink width
 		}
 		else{
-			// if nodes were already created, we need to
-			// adjust their width and iconPath
-			if(nodeIcons[nodeType] == undefined){
-				var icon = Image();
-					addSize = 6* vertexLabelSize,
-					addPortSize = addSize / 2,
-					max = jsonCapacity.max;
+			if(!validArg('setNodeIcon()', path, 'string')){
+				return;
+			}
+			var icon = Image();
+			icon.src = path;
 			
-				icon.src = path;
+			// if the image was loaded successfully, its width must be greater 0
+			if(icon.width > 0){
+				// if nodes were already created, we need to
+				// adjust their width and iconPath
+				if(nodeIcons[nodeType] == undefined){
+					var	addSize = 6* vertexLabelSize,
+						addPortSize = addSize / 2,
+						max = jsonCapacity.max;
 				
-				var data, portData, portCount, addPortSizeRel;
-				for(var n = 0, l = jsonCapacity.occupied; n < l; n++){
-					// adjust node width
-					data = json[n].data;
-					if(data.$nodeType == nodeType){
-						data.$icon = icon;
-						data.$width += addSize;
-						portCount = data.$portCount;
-						
-						// adjust port positions
-						for(var p = data.$portIndex+max, s = p+portCount; p < s; p++){
-							portData = json[p].data;
-							if(portData.$type == "inputPort"){
-								addPortSizeRel = -addPortSize;
-							}else{
-								addPortSizeRel = addPortSize;
-							}
-							if(portData.$relativeX != undefined){
-								portData.$relativeX += addPortSizeRel;
+					var data, portData, portCount, addPortSizeRel;
+					for(var n = 0, l = jsonCapacity.occupied; n < l; n++){
+						// adjust node width
+						data = json[n].data;
+						if(data.$nodeType == nodeType){
+							data.$icon = icon;
+							data.$width += addSize;
+							portCount = data.$portCount;
+							
+							// adjust port positions
+							for(var p = data.$portIndex+max, s = p+portCount; p < s; p++){
+								portData = json[p].data;
+								if(portData.$type == "inputPort"){
+									addPortSizeRel = -addPortSize;
+								}else{
+									addPortSizeRel = addPortSize;
+								}
+								if(portData.$relativeX != undefined){
+									portData.$relativeX += addPortSizeRel;
+								}
+								portData.$xPos += addPortSizeRel;
 							}
-							portData.$xPos += addPortSizeRel;
 						}
 					}
 				}
+				nodeIcons[nodeType] = icon;
+			}
+			else{
+				callListener("onError", ["Error in function setNodeIcon(): Could not load '"+ path +"'."]);
 			}
-			nodeIcons[nodeType] = icon;
 		}
 	}
 	
 	/**
-	Sets the mouseCursor to a new one. If the new cursor is null,
-	it will be reset to the default mouse cursor.
+	Changes the appearance of the mouse cursor. 
+	@param newCursor - 	a String-name of the new cursor. 
+						If null, restore the cursor.
 	*/
 	this.setMouseCursor = function(newCursor){
 		if(newCursor == null){
 			fd.canvas.getElement().style.cursor = '';
-		}else{
+			
+		}else if(validArg('setMouseCursor()', newCursor, 'string')){
 			fd.canvas.getElement().style.cursor = newCursor;
 		}
 	}
 	
-	/**
-	Converts the Graph to dot language, returning it as a string.
-	*/
-	this.graphToDot = function(filename){
-		var node;
-		var dotGraph = 'digraph structs {\nnode [shape=plaintext];\n\n'
-		for(var n=0; n < json.length; n++){
-			node = json[n];
-			if(node.data.$type == "nodeFamily"){
-				dotGraph += nodeToDot(node);
-				dotGraph += '\n';
-			}
-		}
-		dotGraph += '}';
-		console.log(dotGraph);
-	}
-	
-	/**
-		Converts a single node to a node in dot language, and returns it as a string.
-		@param nodeFamily - the node which is to be converted
-	*/
-	this.nodeToDot = function(nodeFamily){
-		var pWidth = (nodeFamily.data.$width+vertexLabelSize)/2;
-		var tableDef = '<TABLE BORDER="0" CELLSPACING="0" CELLBORDER="1" CELLPADDING="0">\n',
-			portDefA = '<TR><TD WIDTH="'+pWidth+'" FIXEDSIZE="true" HEIGHT="'+(2*vertexLabelSize)+'" PORT="',
-			portDefB = '">p</TD></TR>\n',
-			padDefA = '<TR><TD FIXEDSIZE="true" WIDTH="'+pWidth+'" HEIGHT="',
-			padDefB = '"></TD></TR>\n',
-			emptyDef = '<TD FIXEDSIZE="true" HEIGHT="1" WIDTH="'+pWidth+'"></TD>\n';
-		
-		// this variable will contain a string, representing a node in dot-code
-		var dot = nodeFamily.id,
-			dotEdges = '';
-		
-		dot+= ' [label=< '+tableDef;
-		dot+= '<TR><TD COLSPAN="2" HEIGHT="'+(2.5*vertexLabelSize)+'"></TD></TR><TR>\n';
-		
-		var portIndex = nodeFamily.data.$jsonIndex+2,
-			lastPortIndex = nodeFamily.data.$jsonIndex+ nodeFamily.data.$portCount;
-		var port = json[portIndex];
-		if(port.data.$type == "inputPort"){
-			
-			dot += '<TD>'+tableDef;
-			var dotInput = '',
-				countInput = 0;
-			
-			// write the dot representation of ports into a temporary string
-			while(portIndex <= lastPortIndex && port.data.$type == "inputPort"){
-				dotInput += portDefA+ port.id + portDefB;
-				countInput++;
-				portIndex++;
-				port = json[portIndex];
-			}
-			
-			// apply padding if there is space above and below the ports
-			var padding = nodeFamily.data.$height/2 - (1.5+countInput)*vertexLabelSize;
-			if(padding > 0){
-				dotInput = padDefA+padding+padDefB + dotInput + padDefA+padding+padDefB;
-			}
-			
-			// append temp string to result
-			dot += dotInput + '</TABLE></TD>';
-		}
-		else{
-			dot += emptyDef;
-		}
-		
-		if (portIndex <= lastPortIndex){
-			// we get here if there were no input ports OR if we handled them all
-			var dotRight = '',
-				countRight = 0,
-				adja,			// outgoing edges of port
-				adjaIter;		// used to iterate through the edges
-				
-			// add repository ports
-			if(port.data.$type == "repositoryPort"){
-				
-				dot += '<TD>'+tableDef;
-				
-				// write the dot representation of ports into a temporary string
-				while(portIndex <= lastPortIndex && port.data.$type == "repositoryPort"){
-					dotRight += portDefA+ port.id + portDefB;
-					
-					// add edges
-					adja = port.adjacencies;
-					for(a = 0; a < adja.length; a++){
-						adjaIter = adja[a];
-						dotEdges += nodeFamily.id+":"+port.id + ":e->" + adjaIter.data.$targetFamily + ":" + adjaIter.nodeTo+":w;\n";
-					}
-					
-					countRight++;
-					portIndex++;
-					port = json[portIndex];
-				}
-			}
-			// add output ports
-			if(portIndex <= lastPortIndex && port.data.$type == "outputPort"){
-				
-				// if we have preceding repo ports, insert a little gap to separate
-				// the output ports
-				if(json[portIndex-1].data.$type == "repositoryPort"){
-					dotRight += padDefA + vertexLabelSize + padDefB;
-					countRight += 0.5;
-				}
-				else{
-					dot += '<TD>'+tableDef;
-				}
-				
-				// write the dot representation of ports into a temporary string
-				while(portIndex <= lastPortIndex && port.data.$type == "outputPort"){
-					dotRight += portDefA+ port.id + portDefB;
-					
-					// add edges
-					adja = port.adjacencies;
-					for(var a = 0; a < adja.length; a++){
-						adjaIter = adja[a];
-						dotEdges += nodeFamily.id+":"+port.id + ":e->" + adjaIter.data.$targetFamily + ":" + adjaIter.nodeTo+":w;\n";
-					}
-					
-					countRight++;
-					portIndex++;
-					port = json[portIndex];
-				}
-			} 
-			// apply padding  to right sideif there is space above and below the ports
-				var padding = nodeFamily.data.$height/2 - (1.5+countRight)*vertexLabelSize;
-				if(padding > 0){
-					dotRight = padDefA+padding+padDefB + dotRight + padDefA+padding+padDefB;
-				}
-				dot += dotRight + '</TABLE></TD>';
-		}else{
-			dot += emptyDef;
-		}
-		// end of ports
-		
-		dot+= '</TR><TR><TD COLSPAN="2" HEIGHT="'+vertexLabelSize/2+'"></TD></TR></TABLE>>];\n';
-		dot+= dotEdges;
-		
-		return dot;
-	}
 	
 	/** 
-		reloads the graph, trying to restore all positions 
-		this function needs to be called whenever nodes or egdges are
+		Reloads the graph, restoring all positions and displaying all
+		changes to the graph that happened since the last refresh.
+		This function needs to be called whenever nodes or egdges are
 		added or deleted!
 	*/
 	this.refresh = function(){
@@ -467,24 +589,29 @@ function GraphFlow(){
 			onDragCancel,
 			onDragEnd
 		Or one of these events:
+			onError(errorMessage)
 			onCreateEdge(sourceNode, targetNode, sourcePort, targetPort) : boolean,
 			onCreateNode(node) : boolean,
 			onRemoveEdge(sourceNode, targetNode, sourcePort, targetPort) : boolean,
 			onRemoveNode(node) : boolean
-		When altering the graph, do not forget to refresh() it at the
-		end!
-		@param event - the name of the mouse event ( see list above)
+		@param eventName - the name of the mouse event ( see list above)
 		@param listenerFunction - a function that may alter the graph
 	*/
-	this.addListener = function(event, listenerFunction){
-		if(listener[event] == undefined){
-			listener[event] = [];
+	this.addListener = function(eventName, listenerFunction){
+		// check arguments
+		if(!validArg('addListener()', eventName, 'string') ||
+			!validArg('addListener()', listenerFunction, 'function')){
+				return;
+		}
+	
+		if(listener[eventName] == undefined){
+			listener[eventName] = [];
 		}
-		listener[event].push(listenerFunction);
+		listener[eventName].push(listenerFunction);
 	}
 	
 	/**
-		Calls all listener that are registered under the eventName.
+		Calls all listeners that are registered under the eventName.
 		@param eventName - see 'addListener()'
 		@param arguments - an array of arguments. For mouseEvents it is [node, eventInfo, e],
 						   for nodeEvents it is [node], 
@@ -497,7 +624,6 @@ function GraphFlow(){
 		if(!lArr){
 			return true;
 		}
-		
 		var permitted = true;
 		var testval;
 		
@@ -578,10 +704,15 @@ function GraphFlow(){
 	}
 	
 	/**
-	Iterates through all nodes and ports, calling a given function for each.
+	Iterates through all nodes and ports, calling a given function for each one.
 	@param nodeFunction - a single parameter function, called on a node.
 	*/
 	this.iterateAllNodes = function(nodeFunction){
+		// check arguments
+		if(validArg('iterateAllNodes()', nodeFunction, 'function')){
+			return;
+		}
+	
 		var node;
 		for(var n=0, l=jsonCapacity.occupied; n < l; n++){
 			node = json[n];
@@ -595,20 +726,45 @@ function GraphFlow(){
 	
 	/**
 	Changes the colors of the entire graph.
+	Requires a refresh().
+	@param fillColor - the fill color of nodes. If null, restore Node Color from global Array.
+	@param strokeColor - the stroke color of nodes. If null, restore Stroke Color from global Array.
+	@param portColor - the color of all ports. If null, restore Port Color from global Array.
+	@param edgeColor - the color of edges. If null, restore Edge Color from global Array.
+	@param highlightColor - the of highlighted objects. If null, restore Edge Color from global Array.
 	*/
-	this.setNodeStyle = function(fillColor, strokeColor, portColor){
-		nodeFillColor['nodeFamily'] = fillColor;
-		nodeStrokeColor['nodeFamily'] = strokeColor;
-		nodeStrokeColor['inputPort'] = portColor;
-		nodeStrokeColor['outputPort'] = portColor;
-		nodeStrokeColor['repositoryPort'] = portColor;
+	this.setNodeStyle = function(fillColor, strokeColor, portColor, edColor, fcColor){
 		
-		var data;
+		if(fillColor && validArgColor('setNodeStyle()', fillColor)){
+			nodeFillColor['nodeFamily'] = fillColor;
+		}
+		if(strokeColor && validArgColor('setNodeStyle()', strokeColor)){
+			nodeStrokeColor['nodeFamily'] = strokeColor;
+		}
+		
+		if(portColor && validArgColor('setNodeStyle()', portColor)){
+			nodeStrokeColor['inputPort'] = portColor;
+			nodeStrokeColor['outputPort'] = portColor;
+			nodeStrokeColor['repositoryPort'] = portColor;
+		}
+		if(edColor && validArgColor('setNodeStyle()', edColor)){
+			edgeColor = edColor;
+		}
+		if(fcColor && validArgColor('setNodeStyle()', fcColor)){
+			edgeColorFocus = fcColor;
+			nodeColorFocus = fcColor;
+		}
+		
+		
+		var data, a, al, adja;
 		// change family colors
 		for(var n = 0, l = jsonCapacity.occupied; n < l; n++){
 			data = json[n].data;
-			data.$fillColor = nodeFillColor["nodeFamily"];
-			data.$color = nodeStrokeColor["nodeFamily"];
+			// change only if node is not marked
+			if(json[n] != markedNode){
+				data.$fillColor = nodeFillColor["nodeFamily"];
+				data.$color = nodeStrokeColor["nodeFamily"];
+			}
 		}
 		// change port colors
 		for(var n = jsonCapacity.max+1, l = json.length; n < l; n++){
@@ -617,18 +773,24 @@ function GraphFlow(){
 			if(data.$type == "crossBox"){
 				data.$fillColor = nodeFillColor["nodeFamily"];
 			}
+			// change edge colors
+			if(edColor){
+				adja = data.adjacencies;
+				for(a = 0, al = adja.length; a < al; a++){
+					adja[a].data.$color = edgeColor;
+				}
+			}
 		}
-		refresh();
 	}
 	
 	/**
-	Permits or prohibits node and edge deletion/creation and hides the cross
+	Permits or prohibits node and edge deletion/creation and hides the deletion-cross
 	accordingly.
 	@param deleteCreate - if true, one can change the graph in any way
 	@param move - if true, one can change the graph in any way
 	*/
 	this.setReadOnly = function(deleteCreate, move){
-		
+				
 		if(deleteCreate != readOnly.deleteCreate){
 			// set crossBoxes (in)visible
 			var data;
@@ -636,6 +798,7 @@ function GraphFlow(){
 				data = json[n].data;
 				if(data.$type == "crossBox"){
 					data.$visible = deleteCreate;
+					
 				}
 			}
 			readOnly.deleteCreate = deleteCreate;
@@ -648,12 +811,60 @@ function GraphFlow(){
 		
 	/**
 	 Adds a Node to the graph.
+	 @param xPosition - the horizontal position of the added node. 0 is the center of the canvas' starting position
+	 @param xPosition - the vertical position of the added node. 0 is the center of the canvas' starting position
 	 @param nodeFamily - describes some properties of the node: (id, name, nodeClass, tooltip)
-	 @param inputPortIDs - an array of properties for the input ports (id, name, tooltip)
-	 @param outputPortIDs - an array of properties for the output ports (id, name, tooltip)
+	 @param repositoryPorts - an array of properties for the input ports (id, name, tooltip)
+	 @param inputPorts - an array of properties for the input ports (id, name, tooltip)
+	 @param outputPorts - an array of properties for the output ports (id, name, tooltip)
+	 @param nodeType - a string-identifier for a certain group of nodefamilies eg. Filter, Repository
+	 @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,
+		countOutput = 0,
+		iconSpace = 0;
+		
+	if(repositoryPorts){
+		countRepo = repositoryPorts.length;
+		// check if it is an array
+		if(!validArg(caller, repositoryPorts, 'object') || !countRepo){
+			countRepo = 0;
+		}
+	}
+	if(inputPorts){
+		countInput = inputPorts.length;
+		// check if it is an array
+		if(!validArg(caller, inputPorts, 'object') || !countInput){
+			countInput = 0;
+		}
+	}
+	if(outputPorts){
+		countOutput = outputPorts.length;
+		// check if it is an array
+		if(!validArg(caller, outputPorts, 'object') || !countOutput){
+			countOutput = 0;
+		}
+	}
+	
+	// check for other illegal arguments
+	var caller = 'addNode()';
+	if(!validArg(caller, xPosition, 'number')){
+		xPosition = 0;
+	}
+	if(!validArg(caller, yPosition, 'number')){
+		yPosition = 0;
+	}
+	if(!validArg(caller, nodeType, 'string')){
+		nodeType = 'Filter';
+	}
+	if(!validArgNode(caller, nodeFamily)){
+		return;
+	}
+	
 	// check if we have enough space reserved
 	var max = jsonCapacity.max;
 	var occ = jsonCapacity.occupied;
@@ -669,24 +880,9 @@ function GraphFlow(){
 		json = families.concat(ports);
 	}
 	
-	var countRepo = 0,
-		countInput = 0,
-		countOutput = 0,
-		iconSpace = 0;
-		
-	if(repositoryPorts != null){
-		countRepo= repositoryPorts.length;
-	}
-	if(inputPorts != null){
-		countInput= inputPorts.length;
-	}
-	if(outputPorts != null){
-		countOutput= outputPorts.length;
-	}
-	
 	var maxPorts = Math.max(countInput, countRepo+countOutput+0.5),
 		size = vertexLabelSize*2;
-	
+		
 	// insert some space between repo ports and output ports, only if both are present
 	if(maxPorts > countInput && (countRepo == 0 || countOutput == 0)){
 		maxPorts-= 0.5;
@@ -746,7 +942,7 @@ function GraphFlow(){
 				"$relativeY": -height/2,
 				"$color": strokeColor,
 				"$fillColor": nodeColor,
-				"$visible":true
+				"$visible": readOnly.deleteCreate
 			   }, 
 			  "id": nodeFamily.id+".close", 
 			  "name": "x"
@@ -802,25 +998,30 @@ function GraphFlow(){
 			
 			for(var p=0; p < loopPorts.length; p++){
 				var port = loopPorts[p];
-				var newPort ={
-					  "adjacencies": [], 
-					  "data": {
-						"$dim": size,					
-						"$type": loopType,
-						"$xPos": x,
-						"$yPos": y,
-						"$color": nodeStrokeColor[loopType],
-						"$fillColor": nodeColor,
-						"$tooltip": port.tooltip}, 
-					  "id": nodeFamily.id+"."+port.id, 
-					  "name": port.name};
-					  
-				if(p == 0){
-					newPort.data.$relativeX= relativeX;
-					newPort.data.$relativeY= relativeY;
+				
+				// only attempt to add a node if it has an id
+				if(validArgNode(caller, port)){
+				
+					var newPort ={
+						  "adjacencies": [], 
+						  "data": {
+							"$dim": size,					
+							"$type": loopType,
+							"$xPos": x,
+							"$yPos": y,
+							"$color": nodeStrokeColor[loopType],
+							"$fillColor": nodeColor,
+							"$tooltip": port.tooltip}, 
+						  "id": nodeFamily.id+"."+port.id, 
+						  "name": port.name};
+						  
+					if(p == 0){
+						newPort.data.$relativeX= relativeX;
+						newPort.data.$relativeY= relativeY;
+					}
+					json.push(newPort);
+					y += size;
 				}
-				json.push(newPort);
-				y += size;
 			}
 		}
 	}
@@ -833,16 +1034,27 @@ function GraphFlow(){
 	}
 
 	/**
-		Removes a Node and all its edges from the graph.
+		Removes a Node and all its attached edges from the graph.
 		@param nodeFamily - the node which is to be removed
+		@param forced - if true, the node will be removed unconditionally and no
+						event listeners will be called
 	*/
 	this.removeNode =  function(nodeFamily, forced){
-		//fd.graph.removeNode(node.id);
+	
+		// check for valid arguments
+		if(!validArgNode("removeNode()", nodeFamily)){
+			return;
+		}
 		// call listener
 		if(!forced && !callListener("onRemoveNode", [nodeFamily])){
 			return;
 		}
 		
+		// unmark node
+		if (markedNode && markedNode.id == nodeFamily.id){
+			markedNode = null;
+		}
+		
 		var deleteFrom = nodeFamily.data.$portIndex + jsonCapacity.max, 
 			deleteUntil = deleteFrom+ nodeFamily.data.$portCount,
 			familyIndex = nodeFamily.data.$jsonIndex,
@@ -872,16 +1084,6 @@ function GraphFlow(){
 		json.splice(deleteFrom, deletionSum);
 		selectedNode = null;
 		
-		/*
-		// update nodeFamily indices
-		for(var n = deleteUntil-deletionSum+1;  n < json.length;  n++){
-			var familyIndex = json[n].data.$jsonIndex;
-			if(familyIndex != undefined){
-				json[n].data.$jsonIndex = n;
-			}
-		}
-		*/
-		
 		// update nodeFamily indices and remove the deletion gap
 		// in the array space by shifting all following families up
 		var data;
@@ -894,7 +1096,6 @@ function GraphFlow(){
 		}
 		json[occ] = null;
 		
-		
 		// check if we should remove some space
 		var max = jsonCapacity.max;
 		if( (occ*4) < max && max > 10){
@@ -909,10 +1110,12 @@ function GraphFlow(){
 	 }
 	 
 	 /**
-		Prepares a drag opertion for a node, by memorizing all corresponding graph nodes.
+		Prepares a drag operation for a node, caching all graph nodes that need to be moved.
 		This speeds up the moveNode() function considerably.
+		@param node - the node which will be moved
 	*/
 	 function prepareNodeMove(node){
+		
 		var nodes = [];
 		var familyIndex = node.data.$jsonIndex,
 			moveFrom = node.data.$portIndex+ jsonCapacity.max, 
@@ -934,6 +1137,8 @@ function GraphFlow(){
 	 
 	 /**
 		Moves a nodeFamily and its subnodes to the specified position.
+		@param xPos - the horizontal position of the moved node. 0 is the center of the canvas' starting position
+		@param yPos - the vertical position of the moved node. 0 is the center of the canvas' starting position
 	 */
 	 function moveNode(xPos, yPos){
 		var nodes = navi.draggedNodes,
@@ -1020,7 +1225,8 @@ function GraphFlow(){
 	 
 	 /**
 		Saves the position of a node, so that it will be placed there again,
-		when the graph is altered.
+		when the graph is refreshed. This function will only be called once
+		when a node drag operation has finished.
 	 */
 	 function saveNodeMove(){
 		var node = navi.draggedNodes[0],
@@ -1047,13 +1253,27 @@ function GraphFlow(){
 
   
   /**
-   *  adds an edge to the graph
-   *  @param sourceID the id of the node from which the edge starts
-   *  @param targetID the id of the node where the edge ends
-   *  @return true if the edge was successfully added
+   *  Adds a directed edge between two nodes to the graph.
+   *  @param sourceID - the id of the node from which the edge starts
+   *  @param targetID - the id of the node where the edge ends
+   *  @param edgeLabel - the label of the edge. Can be null if no label is required
+   *  @param forced - if true, creates the edge unconditionally and does not trigger 
+					  a listener event
+   *  @return true - if the edge was successfully added
    */
 	this.addEdge = function(sourceID, targetID, edgeLabel, forced){
 		
+		// check for valid arguments
+		if(!validArg("addEdge()", sourceID, "string")){
+			return false;
+		}
+		if(!validArg("addEdge()", targetID, "string")){
+			return false;
+		}
+		if(edgeLabel && !validArg("addEdge()", edgeLabel, "string")){
+			edgeLabel = null;
+		}
+		
 		// look up the source node and the nodeFamilys of both nodes
 		var source, sourceFamily, targetFamily, target;
 		
@@ -1107,13 +1327,14 @@ function GraphFlow(){
 				  "nodeTo": targetID, 
 				  "nodeFrom": sourceID,
 				  "data": {"$direction" : [ sourceID, targetID ],
-						   "$targetFamily" : targetFamilyID},
+						   "$targetFamily" : targetFamilyID,
+						   "$color" : edgeColor},
 				  };
 		
-		if(edgeLabel != null && edgeLabel != undefined){
+		if(edgeLabel){
 			edge.data.$label = edgeLabel;
         }
-				  
+		
 		adja.push(edge);
 		
 		if(sourceID == mouseNode.id || targetID == mouseNode.id){
@@ -1124,11 +1345,21 @@ function GraphFlow(){
 	}
   
   /**
-	Removes the edge between two vertices.
-	@param source the source Node
-	@param targetID the id of the target Node
+	Removes the edge between two nodes.
+	@param sourceID - the if of the source Node
+	@param targetID - the id of the target Node
+	@param forced - if true, removes the edge unconditionally and
+					does not trigger a listener event
 	*/
   this.removeEdge = function(sourceID, targetID, forced){
+	// check for valid arguments
+	if(!validArg("removeEdge()", sourceID, "string")){
+		return;
+	}
+	if(!validArg("removeEdge()", targetID, "string")){
+		return;
+	}
+  
 	// look up the source node and the nodeFamilys of both nodes
 	var source, sourceFamily, targetFamily, target;
 	
@@ -1188,44 +1419,30 @@ function GraphFlow(){
   }
   
   /**
-	makes it so that a text label is not selectable.
-	(unfortunately, this does not prevent CTRL+A selection)
-	*/
-  function setLabelUnselectable(label){
-	// internet explorer:
-	if (typeof label.onselectstart!="undefined"){
-        label.onselectstart =
-			function(){return false};
-		}
-	// mozilla firefox:
-    else if (typeof label.style.MozUserSelect!="undefined"){
-        label.style.MozUserSelect = "none";
-	}
-	// others:
-    else{
-        label.onmousedown =
-			function(){return false};
-	}
-  }
-  
-  /**
-  returns a jsonNode by id
-  @param nodeID the id of the desired node
+  Returns a node from the json array
+  @param nodeID - the id of the desired node
+  @return - the node object or null if the node does not exist
   */
   this.getNode = function(nodeID){
-	for(var n=0; n< json.length; n++){
+	// check for valid arguments
+	if(!validArg("getNode()", nodeID, "string")){
+		return;
+	}
+	for(var n=0, l = json.length; n < l; n++){
 		var node = json[n];
-		if(node != undefined && node.id == nodeID){
+		if(node && node.id == nodeID){
 			return json[n];
 		}
 	}
 	return null;
   }
   
+  
+  
   /**
-	clears all highlights, caused by mouse-enter events
-	@param clearNodes - if true, highlighted nodes will be cleared
-	@param clearEdges - if true, highlighted edges will be cleared
+	Highlights exactly one node or edge, and un-highlights the previously highlighted
+	node or edge.
+	@param node - the node or edge object which will be highlighted
 	*/
   function setHighlight(node){
 		// animation parameters
@@ -1240,7 +1457,13 @@ function GraphFlow(){
 			}
 			else{
 				var type = hover.data.$type;
-				hover.setData('color', nodeStrokeColor[type], 'end');
+				if(markedNode != null && hover.id == markedNode.id){
+					hover.setData('color', markedNode.data.$color, 'end');
+				}
+				else{
+					hover.setData('color', nodeStrokeColor[type], 'end');
+				}
+				
 			}
 			hover = null;
 		}
@@ -1270,9 +1493,78 @@ function GraphFlow(){
 				duration: dur
 		}); 
   }
+  
+  /**
+	Highlights exactly one node, and un-highlights the previously highlighted
+	node.
+	@param node - the node or edge object which will be highlighted.
+				  Can be null if no new node shall be highlighted
+	@param strokeColor - the color of the node stroke or a port's fillcolor.
+						 Can be null for no change.
+	@param fillColor - the fill color of a nodefamily
+						Can be null for no change.
+	*/
+  this.markNode = function(node, strokeColor, fillColor){
+  
+		// check for valid arguments
+		if(node && !validArgNode("markNode()", node)){
+			return;
+		}
+		if(strokeColor && !validArgColor("markNode()", strokeColor)){
+			return;
+		}
+		if(fillColor && !validArgColor("markNode()", fillColor)){
+			return;
+		}
+		
+		// clean up the old marking
+		if(markedNode != null){
+			
+			if(markedNode.nodeFrom != undefined){
+				// ignore edges
+			}
+			else{
+				var type = markedNode.data.$type;
+				markedNode.data.$color = nodeStrokeColor[type];
+				
+				// change FillColor only if it exists
+				if(nodeFillColor[type]){
+					markedNode.data.$fillColor = nodeFillColor[type];
+				}
+			}
+			markedNode = null;
+		}
+		
+		// do we highlight something new?
+		if(node && node != null){
+			// convert dom node to json node
+		
+			if(node.nodeFrom != undefined){
+				// ignore edges
+			}else{
+				var jsonNode = getNode(node.id);
+				if(!jsonNode){
+					callListener("onError", ["Error in function markNode(): Marked Node was deleted."]);
+					return;
+				}
+				
+				if(strokeColor != null){
+					jsonNode.data.$color = strokeColor;
+				}
+				
+				// change FillColor only if it exists
+				if(fillColor != null  && nodeFillColor[node.data.$type]){
+					jsonNode.data.$fillColor = fillColor;
+				}
+			}
+			markedNode = jsonNode;
+		}
+  }
     
   /**
-	Initializes the Graph
+	Initializes the Graph, enabling canvas navigation and tooltips.
+	Also the json array is initialized with a dummy mouse node and
+	what happens on various mouse events is determined.
 	*/
   this.initGraph = function(){
 	json = [ null, null, null, null, null, null, null, null, null, null, 
@@ -1527,23 +1819,24 @@ function GraphFlow(){
 						else{
 							addEdge(node.id, mouseNode.id);
 						}
+						var pos = node.pos.getc(true);
 						refresh();
+						
+						// set mouse position
+						mouseNode.pos.setc(pos.x, pos.y);
+						fd.plot();
 						return;
 					}
 					// click outside the edge drag box
 					else{
 						// add Edge if the selectedNode differs from the clickedNode
-						var newEdgeAdded;
 						if(selectedNode.from == "inputPort"){
 							var label = selectedNode.label;
-							newEdgeAdded = addEdge(node.id, selectedNode.id, label);
+							addEdge(node.id, selectedNode.id, label);
 						}
 						else{
 							var label = selectedNode.label;
-							newEdgeAdded = addEdge(selectedNode.id, node.id, label);
-						}
-						if(newEdgeAdded){
-							refresh();
+							addEdge(selectedNode.id, node.id, label);
 						}
 					}
 					break;
@@ -1559,7 +1852,11 @@ function GraphFlow(){
 					removeEdge(selectedNode.id, node.data.$direction[1]);
 					// add edge to mouseNode
 					addEdge(selectedNode.id, mouseNode.id, label);
+					var pos = eventInfo.getPos();
 					refresh();
+					// set mouse position
+					mouseNode.pos.setc(pos.x, pos.y-2);
+					fd.plot();
 					return;
 				}
 		  }
@@ -1586,59 +1883,7 @@ function GraphFlow(){
 		iterations: 0,
 		//Edge length
 		levelDistance: 0,
-		// This method is only triggered
-		// on label creation and only for DOM labels (not native canvas ones).
-		/*onCreateLabel: function(domElement, node){
-			// do not add labels if it is a dummy element
-			// instead save pointer to domElement
-			if(node.id == "#DUMMY_MOUSE_NODE"){
-				mouseNode = node;
-				return;
-			}
-			if(node.data.$type != "nodeFamily"){
-				return;
-			}
-			
-			domElement.innerHTML = node.name;  
-			
-			// set style for name
-			var style = domElement.style;  
-			style.fontSize = 1.65* fd.canvas.scaleOffsetX* vertexLabelSize+"px";
-			style.left = 0.2*vertexLabelSize-domElement.offsetWidth/2+"px";
-			setLabelUnselectable(domElement);
-		},
-		
-		// Change node styles when DOM labels are placed
-		// or moved.
-		onPlaceLabel: function(domElement, node){
-		  if(node.data.$type != "nodeFamily"){
-			return;
-		  }
-		  
-		  var style = domElement.style;
-		  var left = parseInt(style.left);
-		  var top = parseInt(style.top);
-		  var scale = fd.canvas.scaleOffsetX;
-		  var w = scale*vertexLabelSize* node.name.length;
-		  
-		  var classWidth =  scale*(vertexLabelSize-2)* (node.data.$nodeClass.length+2);
-		  if(classWidth > w){
-			w = classWidth;
-		  }
-		  
-		  style.fontSize = scale* 1.65 * vertexLabelSize+"px";
-		  style.fontFamily = "Lucida Console";
-		  style.left = (left - w/ 2) + 'px';
-		  style.top = (top - h ) + 'px';
-		  style.color = node.data.$color;
-		  style.display = '';
-		  // add class name
-			if(node.data.$nodeClass != undefined){
-				domElement.innerHTML = node.name;  
-				var fontSize= scale*1.65*(vertexLabelSize-2);
-				domElement.innerHTML += "<div style=\"font-size:"+fontSize+"px\"> &lt"+node.data.$nodeClass+"&gt";
-			}
-		}*/
+	
 	  });
 	  
 	  
diff --git a/Kieker.WebGUI/src/main/webapp/js/jit.js b/Kieker.WebGUI/src/main/webapp/js/jit.js
index 51c63e28681c73fead7041cee5e4840dcb58dea6..15130dccc5618b77dd912ece0d4ddc93971f8358 100644
--- a/Kieker.WebGUI/src/main/webapp/js/jit.js
+++ b/Kieker.WebGUI/src/main/webapp/js/jit.js
@@ -1228,8 +1228,6 @@ Options.Node = {
   align: "center",
   angularWidth:1,
   span:1,
-  // FLOWGRAPH:
-  infoText:"info",
   //Raw canvas styles to be
   //applied to the context instance
   //before plotting a node
@@ -4008,6 +4006,12 @@ $jit.Graph = new Class({
 	var node = this.addNode(obj);
 	var x = node.data.$xPos,
 		y = node.data.$yPos;
+	if(isNaN(0-x)){
+		x = 0;
+	}
+	if(isNaN(0-y)){
+		y = 0;
+	}
 	node.pos.setc(x,y);
     return node;
   },
@@ -17148,10 +17152,9 @@ $jit.Hypertree.$extend = true;
 
 
 ///////////////////////////////////////////////////////////////////
-// FLOW GRAPH MODEL (a slightly different ForceDirected version) //
+// GRAPH FLOW MODEL (an extended ForceDirected version)          //
 ///////////////////////////////////////////////////////////////////
 
-
 /*
  * File: Layouts.FlowGraph.js
  *
@@ -17874,6 +17877,7 @@ $jit.FlowGraph.$extend = true;
 					}
 					
 					// paint class
+					
 					var nodeClass =  node.data.$nodeClass;
 					if(nodeClass != undefined){
 						nodeClass = "<"+nodeClass+">";
@@ -17891,6 +17895,7 @@ $jit.FlowGraph.$extend = true;
 					}
 					
 					// draw icon
+					
 					if(img){
 					
 					var ix = posX - textWidth - dim*1.3,
@@ -17970,40 +17975,6 @@ $jit.FlowGraph.$extend = true;
 					ctx.font = bSize +"px Arial Black";
 					ctx.fillText("R", bx, by);
 					
-					/*var grid = size/8,
-						i = by + 2*grid,
-						b = by + grid,
-						h = grid/2,
-						j = h + grid,
-						k = by + 3*grid + h,
-						xh = bx + h,
-						xmh = bx - h;
-						
-					// draw R
-					ctx.fillStyle = node.getData('fillColor');
-					ctx.beginPath();
-					ctx.moveTo(bx - j	, by + h);
-					ctx.lineTo(xh		, by + h);
-					ctx.lineTo(bx + j	, b);
-					ctx.lineTo(bx + grid, i);
-					ctx.lineTo(xh		, i);
-					ctx.lineTo(bx + j	, k);
-					ctx.lineTo(xh		, k);
-					ctx.lineTo(xmh		, i);
-					ctx.lineTo(xmh		, k);
-					ctx.lineTo(bx - j	, k);
-					ctx.closePath();
-					ctx.fill();
-					
-					ctx.fillStyle = node.getData('color');
-					ctx.beginPath();
-					ctx.moveTo(xmh	   , b);
-					ctx.lineTo(xh + h/2, b);
-					ctx.lineTo(xh	   , by + j);
-					ctx.lineTo(xmh	   , by + j);
-					ctx.closePath();
-					ctx.fill();*/
-					
 	    	      },
 	    	      'contains': function(node, pos){
 				  
@@ -18101,19 +18072,19 @@ $jit.FlowGraph.$extend = true;
 	'grid': {
 			'render': function(grid, canvas){
 				
-				var scale = canvas.scaleOffsetX,
-					centerX = - canvas.translateOffsetX/scale,
-					centerY = - canvas.translateOffsetY/scale,
+				var scale = 1/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),
+					width = grid.data.$width*scale*2,
+					height = grid.data.$height*scale*2,
 					left = centerX - width,
 					up = centerY - height,
 					right = centerX + width,
 					bottom = centerY + height,
 					ctx = canvas.getCtx();
 				
-				ctx.lineWidth = 1;
+				ctx.lineWidth = scale;
 				ctx.beginPath();
 				// draw vertical lines
 				for(var x = left - (left % size), l = centerX + width; x < l; x += size){
@@ -18169,24 +18140,35 @@ $jit.FlowGraph.$extend = true;
       'render': function(adj, canvas) {
 		
         var dim = adj.getData('dim'),
-            direction = adj.data.$direction,
-            inv = (direction && direction.length>1 && direction[0] != adj.nodeFrom.id),
+            inverse = adj.data.$direction[0] != adj.nodeFrom.id,
 			posFrom = adj.nodeFrom.pos.getc(true),
 			posTo = adj.nodeTo.pos.getc(true);
 		
 		var from = {"x": posFrom.x, "y" : posFrom.y+dim/2};
 		var to = {"x": posTo.x, "y" : posTo.y+dim/2};
 		
-		if(direction[0] == adj.nodeFrom.id){
-			to.x -= dim;
-			from.x += dim;
+		// swap points if the edge direction is "wrong"
+		if(inverse){
+			var temp = to;
+			to = from;
+			from = temp;
 		}
-		else{
-			to.x += dim;
-			from.x -= dim;
+		
+		to.x -= dim;
+		from.x += dim;
+		
+		// draw potential bend points
+		var bend = adj.data.$bendPoints,
+			toBend;
+		if(bend){
+			for(var b = 0, l = bend.length; b < l; b++){
+				toBend = bend[b];
+				this.edgeHelper.line.render(from, toBend, canvas);
+				from = bend[b];
+			}
 		}
 		
-        this.edgeHelper.flowarrow.render(from, to, dim, inv, canvas);
+        this.edgeHelper.flowarrow.render(from, to, dim, false, canvas);
 		
 		// add the label
 		var label = adj.data.$label;
@@ -18203,24 +18185,35 @@ $jit.FlowGraph.$extend = true;
       },
       'contains': function(adj, pos) {		
         var dim = adj.getData('dim'),
-			direction = adj.data.$direction,
-            inv = (direction && direction.length > 1 && direction[0] != adj.nodeFrom.id),
+			inverse = adj.data.$direction[0] != adj.nodeFrom.id,
 			posFrom = adj.nodeFrom.pos.getc(true),
 			posTo = adj.nodeTo.pos.getc(true);
 			
 		var from = {"x": posFrom.x, "y" : posFrom.y+dim/2};
 		var to = {"x": posTo.x, "y" : posTo.y+dim/2};
 		
-		if(direction[0] == adj.nodeFrom.id){
-			to.x -= dim;
-			from.x += dim;
-		}
-		else{
-			to.x += dim;
-			from.x -= dim;
+		// swap if the arrow points in inverse order
+		if(inverse){
+			var temp = to;
+			to = from;
+			from = temp;
 		}
+		to.x -= dim;
+		from.x += dim;
+		
+		// check if mouse is between bendpoints
+		var bend = adj.data.$bendPoints,
+			toBend,
+			contains = false;
+		if(bend){
+			for(var b = 0, l = bend.length; b < l; b++){
+				toBend = bend[b];
+				contains |= this.edgeHelper.flowarrow.contains(from, toBend, pos, this.edge.epsilon);
+				from = bend[b];
+			}
 			
-        return this.edgeHelper.flowarrow.contains(from, to, pos, this.edge.epsilon);
+		}
+		return contains || this.edgeHelper.flowarrow.contains(from, to, pos, this.edge.epsilon);
       }
     },
 	
@@ -18245,16 +18238,22 @@ $jit.FlowGraph.$extend = true;
         this.edgeHelper.flowarrow.render(from, to, dim, inv, canvas);
 		
 		// add the label
-		// apparently this throws an error on FireFox...
-		/*var label = adj.data.$label;
+		var label = adj.data.$label;
 		if(label != undefined){
 			var ctx = canvas.getCtx();
 			ctx.font = (1.23 * dim)+"px Arial";
 				
 			var	midX = (from.x + to.x - ctx.measureText(label).width) / 2,
 				midY = (from.y + to.y -dim) / 2;
-			ctx.fillText(label, midX, midY);
-		}*/
+			try{
+				ctx.fillText(label, midX, midY);
+			} 
+			catch(e){
+				// do nothing. This "fixes" the 
+				// "An invalid or illegal string was specified"
+				// bug in FireFox
+			}
+		}
       },
       'contains': function(adj, pos) {
 			return false;
diff --git a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml
index 1f7694466ba46a3607014971bbfa1953514ddbc5..e15d5389aba1a72a2dfeac28b84e362e31205ab0 100644
--- a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml
@@ -41,6 +41,9 @@
                 <script>            
                     nodeClickListener = function(node, info, e) {
                         nodeClickCommand([{name : 'ID', value : node.id}]);
+                        markNode(node, '#FF0000');
+                        // TODO Selektieren
+                        graph.refresh();
                     }
             
                     nodeRemoveListener = function(node) {