Kaynağa Gözat

Improves rightClick->printDebug info

Andreas T. Meyer-Berg 6 yıl önce
ebeveyn
işleme
3740dffb0d

+ 1009 - 997
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/view/VisualisationInteractor.java

@@ -1,997 +1,1009 @@
-package de.tu_darmstadt.tk.SmartHomeNetworkSim.view;
-
-import java.awt.Point;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseMotionListener;
-import java.util.LinkedList;
-
-import javax.swing.JMenu;
-import javax.swing.JMenuItem;
-import javax.swing.JPopupMenu;
-import javax.swing.event.MouseInputListener;
-
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.SettingsController;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.Controller;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.NetworkController;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Connection;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.ConnectionPerformance;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Port;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SmartDevice;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleLink;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleProtocol;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.util.Pair;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.popups.ConnectionCreationDialog;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.popups.LinkCreationDialog;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.popups.SmartDeviceCreationPopUp;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.util.LinkToolTip;
-import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.util.Utility;
-
-/**
- * Listener which detects User Interaction with the {@link VisualisationPanel},
- * stores interaction information, triggers the controller and helps
- * visualization of the interaction
- * 
- * @author Andreas T. Meyer-Berg
- */
-public class VisualisationInteractor implements MouseInputListener,
-		MouseMotionListener, ActionListener, KeyListener {
-	/**
-	 * Controller to notify when the model changes
-	 */
-	private Controller controller;
-	
-	/**
-	 * Configurations
-	 */
-	private SettingsController config;
-	
-	/**
-	 * Network Controller
-	 */
-	private NetworkController network;
-	
-	/**
-	 * Panel which is observed
-	 */
-	private VisualisationPanel panel;
-
-	/**
-	 * Menu which is shown on right clicks
-	 */
-	private JPopupMenu rightClickMenu;
-
-	/**
-	 * RightClick MenuItem for SmartDevice creation
-	 */
-	private JMenuItem itemCreate;
-
-	/**
-	 * RightClick MenuItem for Link creation
-	 */
-	private JMenuItem itemCreateLink;
-	
-	/**
-	 * RightClick MenuItem for Connection creation
-	 */
-	private JMenuItem itemCreateConnection;
-	/**
-	 * RightClickMenu for editing connections
-	 */
-	private JMenu itemEditConnection;
-	/**
-	 * Position of editCreate connection in the Rightclick menu 
-	 */
-	private int editCreateConnectionIndex = 2;
-
-	/**
-	 * RightClick MenuItem for SmartDevice deletion
-	 */
-	private JMenuItem itemDelete;
-	
-	/**
-	 * RightClick MenuItem for deletion of multiple selected SmartDevices
-	 */
-	private JMenuItem itemDeleteSelected;
-
-	/**
-	 * RightClick MenuItem for debug purposes
-	 */
-	private JMenuItem itemDebug;
-
-	/**
-	 * SmartDevice that is dragged on Screen
-	 */
-	public SmartDevice dragged = null;
-
-	/**
-	 * Current x Position of the dragged device
-	 */
-	public int dragged_x;
-
-	/**
-	 * Current y Position of the dragged device
-	 */
-	public int dragged_y;
-	
-	/**
-	 * x Position where the drage begun
-	 */
-	public int dragged_x_start;
-	
-	/**
-	 *  y Position where the drag begun
-	 */
-	public int dragged_y_start;
-	
-	/**
-	 * true if an selected device was dragged
-	 */
-	private boolean draggedDeviceWasSelected = false;
-	
-	/**
-	 * No interaction
-	 */
-	public static final byte NOTHING = 0;
-	
-	/**
-	 * Right-click menu is shown
-	 */
-	public static final byte RIGHTCLICK_MENU = 1; 
-	
-	/**
-	 * Drag of multiple selected devices
-	 */
-	public static final byte SELECTED_DRAG = 2;
-	
-	/**
-	 * drag to create connection
-	 */
-	public static final byte DRAG_CONNECTION = 3;
-	
-	/**
-	 * Drag to select multiple devices
-	 */
-	public static final byte DRAG_SELECT = 4; 
-	
-	/**
-	 * Devices are selected on the screen
-	 */
-	public static final byte SELECTED = 5;
-	
-	/**
-	 * Mode, which action is currently executed
-	 */
-	public byte mode = NOTHING;
-	
-	/**
-	 * SmartDevice that was clicked
-	 */
-	private SmartDevice clicked = null;
-	
-	
-	/**
-	 * Device where the current connection is dragged from
-	 */
-	public SmartDevice connectionFrom = null;
-
-	/**
-	 * True if the ControlKey is currently pressed
-	 */
-	public boolean controlDown = false;
-
-	/**
-	 * ToolTip which describes the Links
-	 */
-	private LinkToolTip toolTip;
-	
-	/**
-	 * Link which was clicked
-	 */
-	private Link clickedLink = null;
-	
-	/**
-	 * Creates a new VisualisationInteractor
-	 *
-	 * @param controller
-	 *            controller that is accessed
-	 * @param panel
-	 *            which should visualize the interactions
-	 */
-	public VisualisationInteractor(Controller controller,
-			VisualisationPanel panel) {
-		// Initialize the values
-		this.controller = controller;
-		this.panel = panel;
-		this.config = controller.getSettingsController();
-		this.network = controller.getNetworkController();
-		this.toolTip = new LinkToolTip();
-
-		initializeRightClickMenu();
-	}
-
-	@Override
-	public void mouseClicked(MouseEvent e) {
-		toolTip.setEnabled(false);
-		/*
-		 * FindSmartDevice that was clicked
-		 */
-		clicked = getSmartDeviceAtPosition(e.getX(), e.getY());
-		
-		controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection.clear();
-		if(clicked == null)
-			controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection = getConnectionsAtPosition(e.getX(), e.getY());
-		
-		
-		switch (mode) {
-		case DRAG_CONNECTION:
-			finishConnectionCreation();			
-			break;
-		case SELECTED_DRAG:
-			// Finish Drag Device operations
-			finishDrag();
-		case SELECTED:			
-		case NOTHING:
-			// If Rightclick
-			if (e.getButton() == MouseEvent.BUTTON3) {
-				// Show the RightClickMenu
-				Link linkAtPosition = getLinkVisualizationAtPosition(e.getX(), e.getY());
-				showRightClickMenu(clicked, linkAtPosition);
-				break;
-			}
-			if(!controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty()&&!controlDown){
-				controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
-				if (clicked == null) {
-					panel.repaint();					
-				}
-			}
-			if(clicked!=null){
-				if(!controlDown)
-					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.add(clicked);
-				else if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.remove(clicked)&&!draggedDeviceWasSelected){
-					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.add(clicked);
-				}
-				mode = SELECTED;
-				panel.repaint();
-			}else{
-				if(!controlDown)
-					mode = NOTHING; 
-				else if(!controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
-					mode = SELECTED;
-
-				panel.repaint();	
-			}
-			break;
-		default:
-			break;
-		}
-		
-		
-
-	}
-
-	@Override
-	public void mousePressed(MouseEvent e) {
-		toolTip.setEnabled(false);
-		// Save mouse position for right Click options
-		dragged_x = e.getX();
-		dragged_y = e.getY();
-		// Check if SmartDevice was clicked
-		SmartDevice pressedOn = getSmartDeviceAtPosition(dragged_x, dragged_y);
-		switch (mode) {
-		case SELECTED:
-			if(!controlDown)
-				mode = NOTHING;
-		case RIGHTCLICK_MENU:
-		case NOTHING:
-			if (pressedOn == null){
-				//Click drag - multi select
-				dragged_x_start = e.getX();
-				dragged_y_start = e.getY();
-				mode = DRAG_SELECT;
-				if(!controlDown)
-					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
-				break;
-			} else if (e.getButton() == MouseEvent.BUTTON1){// && connectionFrom == null) {
-				// Recognize possible drag operation
-				draggedDeviceWasSelected = controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.contains(pressedOn);
-				if(!draggedDeviceWasSelected){
-					if(!controlDown)
-						controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
-					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.add(pressedOn);
-				}
-				dragged = pressedOn;
-				dragged_x = pressedOn.getX();
-				dragged_y = pressedOn.getY();
-				mode = SELECTED_DRAG;
-			} else if (e.getButton() == MouseEvent.BUTTON3){// && dragged == null) {
-				connectionFrom = pressedOn;
-				mode = DRAG_CONNECTION;
-			}
-			break;
-		case DRAG_SELECT:
-			finishDragSelect();
-			break;
-		default:
-			mode = NOTHING;
-			break;
-		}
-		panel.repaint();
-	}
-
-	@Override
-	public void mouseReleased(MouseEvent e) {
-		// Finish operation
-		switch (mode) {
-		case DRAG_SELECT:
-			finishDragSelect();
-			panel.repaint();
-			break;
-		case SELECTED_DRAG:
-			finishDrag();
-			
-			break;
-		case DRAG_CONNECTION:
-			finishConnectionCreation();
-			break;
-		default:
-			break;
-		}
-	}
-
-	@Override
-	public void mouseDragged(MouseEvent e) {
-		toolTip.setEnabled(false);
-		// move dragged object/object selection on screen
-		switch (mode) {
-		case DRAG_SELECT:
-		case DRAG_CONNECTION:
-			//Update position
-			if (e.getX() < 0)
-				dragged_x = 0;
-			else if (e.getX() >= config.getWidth())
-				dragged_x = config.getWidth()-1;
-			else
-				dragged_x = e.getX();
-			if (e.getY() < 0)
-				dragged_y = 0;
-			else if (e.getY() >= config.getHeight())
-				dragged_y = config.getHeight()-1;
-			else
-				dragged_y = e.getY();
-			if(mode == DRAG_CONNECTION)
-				break;
-			//Update Selected objects, if DragSelect mode is active
-			int min_x = Math.min(dragged_x, dragged_x_start);
-			int min_y = Math.min(dragged_y, dragged_y_start);
-			int max_x = Math.max(dragged_x, dragged_x_start);
-			int max_y = Math.max(dragged_y, dragged_y_start);
-			//Remove unselected
-			controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.removeIf(s->(s.getX()<min_x||s.getX()>max_x||s.getY()<min_y||s.getY()>max_y));
-			//Add selected devices
-			for(SmartDevice sel:network.getVisibleSmartDevices()){
-				if(sel.getX()>=min_x&&sel.getX()<=max_x&&sel.getY()>=min_y&&sel.getY()<=max_y&&!controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.contains(sel)){
-					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.add(sel);
-				}
-			}
-			break;
-		case SELECTED_DRAG:
-			//new Position of the dragged Device
-			dragged_x = e.getX();
-			dragged_y = e.getY();
-			//offset of the new Position - old position
-			int x_offset = dragged_x - dragged.getX();
-			int y_offset = dragged_y - dragged.getY();
-			//Validate for all moved devices, that they are within the model, if not change offset
-			for(SmartDevice d:controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices){
-				if (d.getX() + x_offset <= config.getDeviceVisualizationRadius())
-					x_offset = config.getDeviceVisualizationRadius()-d.getX();
-				else if (d.getX() + x_offset >= config.getWidth() - config.getDeviceVisualizationRadius())
-					x_offset = config.getWidth() - config.getDeviceVisualizationRadius()-d.getX();
-				if (d.getY() + y_offset <= config.getDeviceVisualizationRadius())
-					y_offset = config.getDeviceVisualizationRadius()-d.getY();
-				else if (d.getY() + y_offset >= config.getHeight() - config.getDeviceVisualizationRadius())
-					y_offset = config.getHeight() - config.getDeviceVisualizationRadius()-d.getY();
-			}
-			//update the dragged position, if the offset changed
-			dragged_x =dragged.getX() + x_offset;
-			dragged_y =dragged.getY() + y_offset;
-			break;
-
-		default:
-			break;
-		}
-		
-		// repaint the dragged smartDevice or new connection
-		if (mode == SELECTED_DRAG || mode == DRAG_CONNECTION || mode == DRAG_SELECT)
-			panel.repaint();
-	}
-	
-	/**
-	 * Finishes the drag operation, if a SmartDevice was dragged, repaint the
-	 * panel and set dragged to null
-	 */
-	public void finishDrag() {
-		if (mode == SELECTED_DRAG){
-			if(dragged != null
-				&& (dragged.getX() != dragged_x || dragged.getY() != dragged_y)) {
-				int x_offset = dragged_x-dragged.getX();
-				int y_offset = dragged_y-dragged.getY();
-				for(SmartDevice d: controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices)
-					network.moveSmartDevice(d, d.getX()+x_offset, d.getY()+y_offset, d.getZ());
-			}
-			dragged = null;
-			if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
-				mode = NOTHING;
-			else
-				mode = SELECTED;
-			panel.repaint();
-			controller.notifyObservers();
-		}
-	}
-
-	private void finishDragSelect() {
-		LinkedList<SmartDevice> merged = new LinkedList<SmartDevice>();
-		//XOR of controller.getControllerConfiguration().getConfigurationManager().getSelectionModel().selectedDevices and controller.getControllerConfiguration().getConfigurationManager().getSelectionModel().selectedDevices Drag
-		merged.addAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices);
-		merged.removeAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag);
-		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.removeAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices);
-		merged.addAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag);
-		//clear sets
-		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
-		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.clear();
-		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices = merged;
-		if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
-			mode = NOTHING;
-		else
-			mode = SELECTED;
-	}
-	
-	/**
-	 * Finishes the create connection operation and open a PopUp for
-	 * Link/Connection creation
-	 */
-	private void finishConnectionCreation() {
-		/**
-		 * SmartDevice the connection was
-		 */
-		SmartDevice connectionTo = getSmartDeviceAtPosition(dragged_x,
-				dragged_y);
-		if (mode == DRAG_CONNECTION && connectionFrom != null && connectionTo != null
-				&& connectionFrom != connectionTo) {
-			// Create new Connection
-			/**
-			 * Link of the new Connection
-			 */
-			Link l = null;
-			/**
-			 * Devices of the connection -> to find common Link
-			 */
-			LinkedList<SmartDevice> devices = new LinkedList<SmartDevice>();
-			devices.add(connectionFrom);
-			devices.add(connectionTo);
-			for(Link link:network.getLinks()){
-				if(link.getDevices().containsAll(devices)){
-					l = link;
-					break;
-				}
-			}
-			/**
-			 * Create new Connection if no link was found
-			 */
-			if(l==null){
-				l= new SimpleLink("Ethernet: " + connectionFrom.getName()
-					+ " to " + connectionTo.getName());
-				l.addDevice(connectionFrom);
-				l.addDevice(connectionTo);
-			}
-			//Create ports and add to controller
-			Port p1 = new Port(connectionFrom, (short) 1,(long) (Math.random()*300+300));
-			Port p2 = new Port(connectionTo, (short) 2,(long) (Math.random()*300+300));
-			Connection c = new ConnectionPerformance(l, new SimpleProtocol(p1, p2));
-			c.addSmartDevice(p1);
-			c.addSmartDevice(p2);
-			p1.setConnection(c);
-			p2.setConnection(c);
-			connectionTo.addLink(l);
-			connectionTo.addPort(p2);
-			connectionFrom.addLink(l);
-			connectionFrom.addPort(p1);
-			network.addConnectionToLink(c, l);
-			network.addConnection(c);
-			if(!network.getLinks().contains(l))
-				network.addLink(l);
-			
-		}
-		connectionFrom = null;
-		if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
-			mode = NOTHING;
-		else
-			mode = SELECTED;
-		panel.repaint();
-		controller.notifyObservers();
-	}
-
-	/**
-	 * Returns SmartDevice which is at position (x,y) or within its
-	 * visualization radius. Returns null, if no SmartDevice is within the
-	 * range.
-	 * 
-	 * @param x
-	 *            x-position which should be checked
-	 * @param y
-	 *            y-position which should be checked
-	 * @return {@link SmartDevice} at position (x,y) or null if there is no
-	 */
-	private SmartDevice getSmartDeviceAtPosition(int x, int y) {
-		// Check is device is inside visualization radius
-		for (SmartDevice d : network.getVisibleSmartDevices()) {
-			if (Math.abs(d.getX() - x) < config.getDeviceVisualizationRadius()
-					&& Math.abs(d.getY() - y) < config.getDeviceVisualizationRadius()) {
-				/**
-				 * correct distance / radius from the smartDevice
-				 */
-				int radius = (int) Math.floor(Math.sqrt((d.getX() - x)*(d.getX() - x)+(d.getY() - y)*(d.getY() - y)));
-				if(radius <= config.getDeviceVisualizationRadius())
-					return d;
-			}
-		}
-		return null;
-	}
-	
-	/**
-	 * Returns all Connections, which cross point (x,y)
-	 * @param x xPosition of the point (x,y)
-	 * @param y yPosition of the point (x,y)
-	 * @return List of all possible clicked Connections
-	 */
-	private LinkedList<Pair<Connection, Pair<Port, Port>>> getConnectionsAtPosition(int x, int y) {
-		LinkedList<Pair<Connection,Pair<Port,Port>>> edges = new LinkedList<Pair<Connection,Pair<Port,Port>>>();
-		// Check is device is inside visualization radius
-		for(Connection c: network.getVisibleConnections()){
-			if(c.getProtocol()==null)
-				continue;
-			for(Pair<Port, Port> p: c.getProtocol().getTopology()){
-				if(pointOnConnection(x,y,p)){
-					edges.add(new Pair<Connection, Pair<Port,Port>>(c, p));
-					//break;//Connection was clicked - check for further connections
-				}
-			}
-		}
-		return edges;
-	}
-
-	/**
-	 * Returns true if the point (x,y) is on the connection part p.
-	 * 
-	 * @param x xPosition of the Point
-	 * @param y yPosition of the Point
-	 * @param p connection part, which connects to Ports with a line
-	 * @return true if point is on connection, else false
-	 */
-	private boolean pointOnConnection(int x, int y, Pair<Port, Port> p) {
-		//No valid connection part
-		if(p.getLeft()==null||p.getRight()==null||p.getLeft().getOwner()==null||p.getRight().getOwner()==null)
-			return false;
-		int lX = p.getLeft().getOwner().getX();
-		int lY = p.getLeft().getOwner().getY();
-		int rX = p.getRight().getOwner().getX();
-		int rY = p.getRight().getOwner().getY();
-		//Point out of bounds
-		if(x < Math.min(lX, rX) || x > Math.max(lX, rX) || y < Math.min(lY, rY) || y > Math.max(lY, rY))
-			return false;
-		double dLP = distance(lX,lY,x,y);
-		double dPR = distance(x,y,rX,rY);
-		double dLR = distance(lX,lY,rX,rY);
-		double diff = Math.abs(dLP+dPR-dLR);
-		return diff < 0.5;
-	}
-
-	/**
-	 * Calculates distance between (x1,y1) and (x2,y2)
-	 * 
-	 * @param x1 x Position of Point 1
-	 * @param y1 y Position of Point 1
-	 * @param x2 x Position of Point 1 
-	 * @param y2 y Position of Point 1
-	 * @return distance
-	 */
-	private double distance(int x1, int y1, int x2, int y2) {
-		return Math.sqrt(Math.pow(x1-x2, 2)+Math.pow(y1-y2, 2));
-	}
-
-	@Override
-	public void keyTyped(KeyEvent e) {
-		if(e.getKeyCode()==KeyEvent.VK_CONTROL){
-			if(controlDown!=true){
-				controlDown = true;
-				panel.repaint();
-			}
-		}
-	}
-
-	@Override
-	public void keyPressed(KeyEvent e) {
-		if(e.getKeyCode()==KeyEvent.VK_CONTROL){
-			if(controlDown!=true){
-				controlDown = true;
-				panel.repaint();
-			}
-		}
-	}
-
-	@Override
-	public void keyReleased(KeyEvent e) {
-		if(e.getKeyCode()==KeyEvent.VK_CONTROL){
-			if(controlDown==true){
-				controlDown = false;
-				panel.repaint();
-			}
-		}
-	}
-	
-	@Override
-	public void mouseMoved(MouseEvent e) {
-		/**
-		 * Link which might get a toolTip
-		 */
-		Link l = null; 
-		/**
-		 * Check Hover on Link
-		 */
-		if(config.isShowLinkToolTips())
-			l = getLinkVisualizationAtPosition(e.getX(),e.getY());
-		if(l != null){
-			if(l != toolTip.getLink() || !toolTip.isEnabled()){
-				toolTip.setText("Link "+l.getName());
-				toolTip.setLink(l);
-				toolTip.setX(e.getX());
-				toolTip.setY(e.getY());
-				toolTip.setEnabled(true);
-				panel.update(null, null);
-			}
-		}else{
-			if(toolTip.getLink()!=null || toolTip.isEnabled()){
-				toolTip.setLink(null);
-				toolTip.setEnabled(false);
-				panel.update(null, null);
-			}
-		}
-	}
-
-	/**
-	 * Return Link which is at position at the given position
-	 * @param x xPosition
-	 * @param y yPosition
-	 * @return Link at the position, else null
-	 */
-	private Link getLinkVisualizationAtPosition(int x, int y) {
-		if(!config.isShowLinks())
-			return null;
-		// Check is device is inside visualization radius
-		/**
-		 * Radius of the device
-		 */
-		int smallRadius = config.getDeviceVisualizationRadius();
-		/**
-		 * Radius of the device + link
-		 */
-		int radius =  smallRadius + config.getLinkRadius();
-		for (SmartDevice d : network.getVisibleSmartDevices()) {
-			//In DeviceRadius + Link Radius ?
-			if (Math.abs(d.getX() - x) <= radius && Math.abs(d.getY() - y) <= radius) {
-				//More detailed check
-				// On Ring ?
-				// On which part of Ring ?
-				//Outside of device ?
-				int realDistance = (int)Math.round(Math.sqrt((d.getX() - x)*(d.getX() - x)+(d.getY() - y)*(d.getY() - y)));
-				if (realDistance >= smallRadius && realDistance <= radius && !d.getLinks().isEmpty()) {
-					/**
-					 * Angle of this point. Counterclockwise, starting at 3 o' clock position
-					 */
-					float angle = Utility.getAngle(d.getX(), d.getY(), x, y);
-					/**
-					 * Number of Links in the Model
-					 */
-					int numberOfLinks = network.getVisibleLinks().size();
-					/**
-					 * Angle per Link in "linkSlice degrees"
-					 */
-					double linkSlice = Math.min(360.0 / numberOfLinks,90.0);
-					/**
-					 * calculate the number of the link
-					 */
-					int linkNumber = (int) Math.floor(angle / linkSlice);
-					/**
-					 * Return if, there are not so many link
-					 */
-					if(linkNumber>=numberOfLinks)
-						return null;
-					/**
-					 * Link, which would be at this connection
-					 */
-					Link linkAtPosition = (Link) network.getVisibleLinks().toArray()[linkNumber];
-					/**
-					 * Return link, if smartDevice contains it
-					 */
-					if(d.getLinks().contains(linkAtPosition))
-						return linkAtPosition;
-				}
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public void mouseEntered(MouseEvent e) {}
-
-	@Override
-	public void mouseExited(MouseEvent e) {
-		toolTip.setEnabled(false);
-	}
-
-	@Override
-	public void actionPerformed(ActionEvent e) {}
-	
-	/**
-	 * Shows the RightClick Menu on the Visualization Panel, with Options for
-	 * the given SmartDevice clickedOn, if clickedOn is null, the RightClick
-	 * Menu contains Options for creation of new SmartDevices. The Menu will be
-	 * shown at the Mouse position on the VisualisationPanel.
-	 * 
-	 * @param clickedOn
-	 *            Device which was clicked, otherwise null
-	 * @param clickedLink Link which was clicked, otherwise null
-	 */
-	protected void showRightClickMenu(SmartDevice clickedOn, Link clickedLink) {
-		this.clickedLink = clickedLink;
-		/**
-		 * Mouse Position on the VisualisationPanel
-		 */
-		Point mousePos = panel.getMousePosition();
-		// Just execute if Mouse Position is on the Panel
-		if (mousePos != null) {			
-			if (clickedOn == null) {
-				if(clickedLink == null){
-					itemCreateLink.setText("Create Link");
-					itemCreateLink.setEnabled(false);
-				}else{
-					itemCreateLink.setText("Edit Link");
-					itemCreateLink.setEnabled(true);
-				}
-				
-				itemCreate.setText("Create Device");
-				itemCreate.setEnabled(true);
-				itemDelete.setEnabled(false);
-				itemDeleteSelected.setEnabled(false);
-				if(controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection.size()>0){
-					/**
-					 * Update Connections which can be edited
-					 */
-					itemEditConnection.removeAll();	
-					
-					//List to prevent duplicate connection entries
-					LinkedList<Connection> editableConnections = new LinkedList<Connection>();
-					for(Pair<Connection, Pair<Port,Port>> p:controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection){
-						//Don't add the same connection multiple times
-						if(editableConnections.contains(p.getLeft())|| p == null || p.getLeft() == null)continue;
-						editableConnections.add(p.getLeft());
-						JMenuItem a = new JMenuItem(p.getLeft().getName());
-						a.addActionListener(e->new ConnectionCreationDialog(p.getLeft(), controller, panel));
-						itemEditConnection.add(a);
-					}
-					
-					if(rightClickMenu.getComponentIndex(itemCreateConnection)!=-1){
-						rightClickMenu.remove(itemCreateConnection);
-						rightClickMenu.add(itemEditConnection,editCreateConnectionIndex);
-						itemCreateConnection.setEnabled(false);				
-					}
-					itemEditConnection.setEnabled(true);
-				}else{
-					if(rightClickMenu.getComponentIndex(itemEditConnection)!=-1){
-						rightClickMenu.remove(itemEditConnection);
-						rightClickMenu.add(itemCreateConnection,editCreateConnectionIndex);
-					}
-					itemCreateConnection.setEnabled(false);
-				}
-			} else {
-				itemCreate.setText("Edit Device");
-				itemCreate.setEnabled(true);
-				itemDelete.setEnabled(true);
-				//Remove edit connection if it exist
-				if(rightClickMenu.getComponentIndex(itemEditConnection)!=-1){
-					rightClickMenu.remove(itemEditConnection);
-					rightClickMenu.add(itemCreateConnection,editCreateConnectionIndex);
-				}
-				itemCreateLink.setText("Create Link");
-				if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.contains(clickedOn)){
-					itemDeleteSelected.setEnabled(true);
-					itemCreateLink.setEnabled(true);
-					itemCreateConnection.setEnabled(true);
-				}
-				else{
-					itemDeleteSelected.setEnabled(false);
-					itemCreateLink.setEnabled(false);
-					itemCreateConnection.setEnabled(false);
-				}
-			}
-			// Show the RightClickMenu
-			rightClickMenu.show(panel, mousePos.x, mousePos.y);
-			rightClickMenu.setEnabled(true);
-			rightClickMenu.setVisible(true);
-			mode = RIGHTCLICK_MENU;
-		}
-	}
-
-	/**
-	 * Creates the RightClickMenu, adds the different Labels and functionalities to the menu and adds it to the panel.
-	 */
-	private void initializeRightClickMenu() {
-		this.rightClickMenu = new JPopupMenu();
-
-		// Create device option
-		itemCreate = new JMenuItem("Create SmartDevice");
-
-		itemCreate.addActionListener(e -> {
-			SmartDevice toEdit;
-			if(clicked == null){
-				toEdit = new SmartDevice("DeviceName");
-				toEdit.setX(dragged_x);
-				toEdit.setY(dragged_y);
-			}else{
-				toEdit = clicked;
-			}
-			SmartDeviceCreationPopUp popUp = new SmartDeviceCreationPopUp(toEdit, toEdit==clicked,controller);
-			popUp.setLocationRelativeTo(panel);
-			popUp.setEnabled(true);
-			popUp.setVisible(true);
-			mode = NOTHING;
-
-		});
-
-		rightClickMenu.add(itemCreate);
-		
-		// Create Link
-		itemCreateLink = new JMenuItem("Create Link");
-		
-		itemCreateLink.addActionListener(e -> {
-			if(clickedLink!=null){
-				new LinkCreationDialog(clickedLink, controller, panel);
-			}else{
-				new LinkCreationDialog(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices, controller, panel);
-			}
-			if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
-				mode = NOTHING;
-			else
-				mode = SELECTED;
-			
-		});
-		rightClickMenu.add(itemCreateLink);
-		
-		// Create Connection
-		itemCreateConnection = new JMenuItem("Create Connection");
-		itemCreateConnection.addActionListener(e->{
-			LinkedList<SmartDevice> selectedDevices = new LinkedList<SmartDevice>(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices);
-			LinkedList<Port> ports = new LinkedList<Port>();
-			for(SmartDevice d: selectedDevices)
-				ports.add(new Port(d, (short) 12));
-			Link link = null;
-			/**
-			 * Find common link -> else null -> create new link
-			 */
-			for(Link l:network.getLinks()){
-				if(l.getDevices().containsAll(selectedDevices)){
-					link = l;
-					break;
-				}
-			}
-			new ConnectionCreationDialog(ports,link, controller, panel);
-			if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
-				mode = NOTHING;
-			else
-				mode = SELECTED;
-		});
-		rightClickMenu.add(itemCreateConnection);
-		
-		// Edit connection
-		itemEditConnection = new JMenu("Edit Connection");
-
-		// Delete device option
-		itemDelete = new JMenuItem("Delete");
-
-		itemDelete.addActionListener(e -> {
-			// Delete the clicked object
-				network.deleteSmartDevice(clicked);
-				clicked = null;
-				controller.notifyObservers();
-				mode = NOTHING;
-			});
-
-		rightClickMenu.add(itemDelete);
-		
-		// Delete device option
-		itemDeleteSelected = new JMenuItem("Delete Selected");
-		
-		itemDeleteSelected.addActionListener(e -> {
-			// Delete the clicked object
-			for(SmartDevice c: controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices)
-				network.deleteSmartDevice(c);
-			controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
-			clicked = null;
-			controller.notifyObservers();
-			mode = NOTHING;
-		});
-		itemDeleteSelected.setEnabled(false);
-		rightClickMenu.add(itemDeleteSelected);
-				
-		/*
-		 * Add PrintDebug option
-		 */
-		itemDebug = new JMenuItem("Print NetworkState");
-		itemDebug.addActionListener(e -> {
-			// Print Links, Devices and Connections
-				for (Link l : network.getLinks())
-					System.out.println("Link: " + l.getName());
-				for (SmartDevice d : network.getSmartDevices()) {
-					System.out.println("Device: " + d.getName());
-					for (Port p : d.getPorts()) {
-						if(p==null){
-							System.out.println("Port: null");
-							continue;
-						}
-						if(p.getConnection()==null){
-							System.out.println("Connection: null");
-							continue;
-						}
-						switch (p.getConnection().getStatus()) {
-						case Connection.ACTIVE:
-							System.out.println("Connection: active");
-							break;
-						case Connection.FINISHED:
-						case Connection.TERMINATED:
-							System.out.println("Connection: terminated");
-
-							break;
-
-						case Connection.HALTED:
-						default:
-							break;
-						}
-					}
-				}
-				// Print Terminating Packages
-				LinkedList<Connection> terminated = new LinkedList<Connection>();
-
-				network.getConnections()
-						.stream()
-						.forEach(c -> {
-							if(c.getStatus() == Connection.FINISHED || c
-								.getStatus() == Connection.TERMINATED)
-								terminated.add(c);
-							for (Packet p : c.getTerminationPackages(1000))
-								System.out.println(p.getTextualRepresentation());
-						});
-				network.getConnections().removeAll(terminated);
-				if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
-					mode = NOTHING;
-				else
-					mode = SELECTED;
-				controller.notifyObservers();
-			});
-		rightClickMenu.add(itemDebug);
-
-		this.panel.add(rightClickMenu);
-	}
-
-	/**
-	 * @return the toolTip
-	 */
-	public LinkToolTip getToolTip() {
-		return toolTip;
-	}
-}
+package de.tu_darmstadt.tk.SmartHomeNetworkSim.view;
+
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.util.LinkedList;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.event.MouseInputListener;
+
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.SettingsController;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.Controller;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.NetworkController;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Connection;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.ConnectionPerformance;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Port;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SmartDevice;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleLink;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleProtocol;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.util.Pair;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.popups.ConnectionCreationDialog;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.popups.LinkCreationDialog;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.popups.SmartDeviceCreationPopUp;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.util.LinkToolTip;
+import de.tu_darmstadt.tk.SmartHomeNetworkSim.view.util.Utility;
+
+/**
+ * Listener which detects User Interaction with the {@link VisualisationPanel},
+ * stores interaction information, triggers the controller and helps
+ * visualization of the interaction
+ * 
+ * @author Andreas T. Meyer-Berg
+ */
+public class VisualisationInteractor implements MouseInputListener,
+		MouseMotionListener, ActionListener, KeyListener {
+	/**
+	 * Controller to notify when the model changes
+	 */
+	private Controller controller;
+	
+	/**
+	 * Configurations
+	 */
+	private SettingsController config;
+	
+	/**
+	 * Network Controller
+	 */
+	private NetworkController network;
+	
+	/**
+	 * Panel which is observed
+	 */
+	private VisualisationPanel panel;
+
+	/**
+	 * Menu which is shown on right clicks
+	 */
+	private JPopupMenu rightClickMenu;
+
+	/**
+	 * RightClick MenuItem for SmartDevice creation
+	 */
+	private JMenuItem itemCreate;
+
+	/**
+	 * RightClick MenuItem for Link creation
+	 */
+	private JMenuItem itemCreateLink;
+	
+	/**
+	 * RightClick MenuItem for Connection creation
+	 */
+	private JMenuItem itemCreateConnection;
+	/**
+	 * RightClickMenu for editing connections
+	 */
+	private JMenu itemEditConnection;
+	/**
+	 * Position of editCreate connection in the Rightclick menu 
+	 */
+	private int editCreateConnectionIndex = 2;
+
+	/**
+	 * RightClick MenuItem for SmartDevice deletion
+	 */
+	private JMenuItem itemDelete;
+	
+	/**
+	 * RightClick MenuItem for deletion of multiple selected SmartDevices
+	 */
+	private JMenuItem itemDeleteSelected;
+
+	/**
+	 * RightClick MenuItem for debug purposes
+	 */
+	private JMenuItem itemDebug;
+
+	/**
+	 * SmartDevice that is dragged on Screen
+	 */
+	public SmartDevice dragged = null;
+
+	/**
+	 * Current x Position of the dragged device
+	 */
+	public int dragged_x;
+
+	/**
+	 * Current y Position of the dragged device
+	 */
+	public int dragged_y;
+	
+	/**
+	 * x Position where the drage begun
+	 */
+	public int dragged_x_start;
+	
+	/**
+	 *  y Position where the drag begun
+	 */
+	public int dragged_y_start;
+	
+	/**
+	 * true if an selected device was dragged
+	 */
+	private boolean draggedDeviceWasSelected = false;
+	
+	/**
+	 * No interaction
+	 */
+	public static final byte NOTHING = 0;
+	
+	/**
+	 * Right-click menu is shown
+	 */
+	public static final byte RIGHTCLICK_MENU = 1; 
+	
+	/**
+	 * Drag of multiple selected devices
+	 */
+	public static final byte SELECTED_DRAG = 2;
+	
+	/**
+	 * drag to create connection
+	 */
+	public static final byte DRAG_CONNECTION = 3;
+	
+	/**
+	 * Drag to select multiple devices
+	 */
+	public static final byte DRAG_SELECT = 4; 
+	
+	/**
+	 * Devices are selected on the screen
+	 */
+	public static final byte SELECTED = 5;
+	
+	/**
+	 * Mode, which action is currently executed
+	 */
+	public byte mode = NOTHING;
+	
+	/**
+	 * SmartDevice that was clicked
+	 */
+	private SmartDevice clicked = null;
+	
+	
+	/**
+	 * Device where the current connection is dragged from
+	 */
+	public SmartDevice connectionFrom = null;
+
+	/**
+	 * True if the ControlKey is currently pressed
+	 */
+	public boolean controlDown = false;
+
+	/**
+	 * ToolTip which describes the Links
+	 */
+	private LinkToolTip toolTip;
+	
+	/**
+	 * Link which was clicked
+	 */
+	private Link clickedLink = null;
+	
+	/**
+	 * Creates a new VisualisationInteractor
+	 *
+	 * @param controller
+	 *            controller that is accessed
+	 * @param panel
+	 *            which should visualize the interactions
+	 */
+	public VisualisationInteractor(Controller controller,
+			VisualisationPanel panel) {
+		// Initialize the values
+		this.controller = controller;
+		this.panel = panel;
+		this.config = controller.getSettingsController();
+		this.network = controller.getNetworkController();
+		this.toolTip = new LinkToolTip();
+
+		initializeRightClickMenu();
+	}
+
+	@Override
+	public void mouseClicked(MouseEvent e) {
+		toolTip.setEnabled(false);
+		/*
+		 * FindSmartDevice that was clicked
+		 */
+		clicked = getSmartDeviceAtPosition(e.getX(), e.getY());
+		
+		controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection.clear();
+		if(clicked == null)
+			controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection = getConnectionsAtPosition(e.getX(), e.getY());
+		
+		
+		switch (mode) {
+		case DRAG_CONNECTION:
+			finishConnectionCreation();			
+			break;
+		case SELECTED_DRAG:
+			// Finish Drag Device operations
+			finishDrag();
+		case SELECTED:			
+		case NOTHING:
+			// If Rightclick
+			if (e.getButton() == MouseEvent.BUTTON3) {
+				// Show the RightClickMenu
+				Link linkAtPosition = getLinkVisualizationAtPosition(e.getX(), e.getY());
+				showRightClickMenu(clicked, linkAtPosition);
+				break;
+			}
+			if(!controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty()&&!controlDown){
+				controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
+				if (clicked == null) {
+					panel.repaint();					
+				}
+			}
+			if(clicked!=null){
+				if(!controlDown)
+					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.add(clicked);
+				else if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.remove(clicked)&&!draggedDeviceWasSelected){
+					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.add(clicked);
+				}
+				mode = SELECTED;
+				panel.repaint();
+			}else{
+				if(!controlDown)
+					mode = NOTHING; 
+				else if(!controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
+					mode = SELECTED;
+
+				panel.repaint();	
+			}
+			break;
+		default:
+			break;
+		}
+		
+		
+
+	}
+
+	@Override
+	public void mousePressed(MouseEvent e) {
+		toolTip.setEnabled(false);
+		// Save mouse position for right Click options
+		dragged_x = e.getX();
+		dragged_y = e.getY();
+		// Check if SmartDevice was clicked
+		SmartDevice pressedOn = getSmartDeviceAtPosition(dragged_x, dragged_y);
+		switch (mode) {
+		case SELECTED:
+			if(!controlDown)
+				mode = NOTHING;
+		case RIGHTCLICK_MENU:
+		case NOTHING:
+			if (pressedOn == null){
+				//Click drag - multi select
+				dragged_x_start = e.getX();
+				dragged_y_start = e.getY();
+				mode = DRAG_SELECT;
+				if(!controlDown)
+					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
+				break;
+			} else if (e.getButton() == MouseEvent.BUTTON1){// && connectionFrom == null) {
+				// Recognize possible drag operation
+				draggedDeviceWasSelected = controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.contains(pressedOn);
+				if(!draggedDeviceWasSelected){
+					if(!controlDown)
+						controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
+					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.add(pressedOn);
+				}
+				dragged = pressedOn;
+				dragged_x = pressedOn.getX();
+				dragged_y = pressedOn.getY();
+				mode = SELECTED_DRAG;
+			} else if (e.getButton() == MouseEvent.BUTTON3){// && dragged == null) {
+				connectionFrom = pressedOn;
+				mode = DRAG_CONNECTION;
+			}
+			break;
+		case DRAG_SELECT:
+			finishDragSelect();
+			break;
+		default:
+			mode = NOTHING;
+			break;
+		}
+		panel.repaint();
+	}
+
+	@Override
+	public void mouseReleased(MouseEvent e) {
+		// Finish operation
+		switch (mode) {
+		case DRAG_SELECT:
+			finishDragSelect();
+			panel.repaint();
+			break;
+		case SELECTED_DRAG:
+			finishDrag();
+			
+			break;
+		case DRAG_CONNECTION:
+			finishConnectionCreation();
+			break;
+		default:
+			break;
+		}
+	}
+
+	@Override
+	public void mouseDragged(MouseEvent e) {
+		toolTip.setEnabled(false);
+		// move dragged object/object selection on screen
+		switch (mode) {
+		case DRAG_SELECT:
+		case DRAG_CONNECTION:
+			//Update position
+			if (e.getX() < 0)
+				dragged_x = 0;
+			else if (e.getX() >= config.getWidth())
+				dragged_x = config.getWidth()-1;
+			else
+				dragged_x = e.getX();
+			if (e.getY() < 0)
+				dragged_y = 0;
+			else if (e.getY() >= config.getHeight())
+				dragged_y = config.getHeight()-1;
+			else
+				dragged_y = e.getY();
+			if(mode == DRAG_CONNECTION)
+				break;
+			//Update Selected objects, if DragSelect mode is active
+			int min_x = Math.min(dragged_x, dragged_x_start);
+			int min_y = Math.min(dragged_y, dragged_y_start);
+			int max_x = Math.max(dragged_x, dragged_x_start);
+			int max_y = Math.max(dragged_y, dragged_y_start);
+			//Remove unselected
+			controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.removeIf(s->(s.getX()<min_x||s.getX()>max_x||s.getY()<min_y||s.getY()>max_y));
+			//Add selected devices
+			for(SmartDevice sel:network.getVisibleSmartDevices()){
+				if(sel.getX()>=min_x&&sel.getX()<=max_x&&sel.getY()>=min_y&&sel.getY()<=max_y&&!controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.contains(sel)){
+					controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.add(sel);
+				}
+			}
+			break;
+		case SELECTED_DRAG:
+			//new Position of the dragged Device
+			dragged_x = e.getX();
+			dragged_y = e.getY();
+			//offset of the new Position - old position
+			int x_offset = dragged_x - dragged.getX();
+			int y_offset = dragged_y - dragged.getY();
+			//Validate for all moved devices, that they are within the model, if not change offset
+			for(SmartDevice d:controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices){
+				if (d.getX() + x_offset <= config.getDeviceVisualizationRadius())
+					x_offset = config.getDeviceVisualizationRadius()-d.getX();
+				else if (d.getX() + x_offset >= config.getWidth() - config.getDeviceVisualizationRadius())
+					x_offset = config.getWidth() - config.getDeviceVisualizationRadius()-d.getX();
+				if (d.getY() + y_offset <= config.getDeviceVisualizationRadius())
+					y_offset = config.getDeviceVisualizationRadius()-d.getY();
+				else if (d.getY() + y_offset >= config.getHeight() - config.getDeviceVisualizationRadius())
+					y_offset = config.getHeight() - config.getDeviceVisualizationRadius()-d.getY();
+			}
+			//update the dragged position, if the offset changed
+			dragged_x =dragged.getX() + x_offset;
+			dragged_y =dragged.getY() + y_offset;
+			break;
+
+		default:
+			break;
+		}
+		
+		// repaint the dragged smartDevice or new connection
+		if (mode == SELECTED_DRAG || mode == DRAG_CONNECTION || mode == DRAG_SELECT)
+			panel.repaint();
+	}
+	
+	/**
+	 * Finishes the drag operation, if a SmartDevice was dragged, repaint the
+	 * panel and set dragged to null
+	 */
+	public void finishDrag() {
+		if (mode == SELECTED_DRAG){
+			if(dragged != null
+				&& (dragged.getX() != dragged_x || dragged.getY() != dragged_y)) {
+				int x_offset = dragged_x-dragged.getX();
+				int y_offset = dragged_y-dragged.getY();
+				for(SmartDevice d: controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices)
+					network.moveSmartDevice(d, d.getX()+x_offset, d.getY()+y_offset, d.getZ());
+			}
+			dragged = null;
+			if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
+				mode = NOTHING;
+			else
+				mode = SELECTED;
+			panel.repaint();
+			controller.notifyObservers();
+		}
+	}
+
+	private void finishDragSelect() {
+		LinkedList<SmartDevice> merged = new LinkedList<SmartDevice>();
+		//XOR of controller.getControllerConfiguration().getConfigurationManager().getSelectionModel().selectedDevices and controller.getControllerConfiguration().getConfigurationManager().getSelectionModel().selectedDevices Drag
+		merged.addAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices);
+		merged.removeAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag);
+		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.removeAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices);
+		merged.addAll(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag);
+		//clear sets
+		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
+		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevicesDrag.clear();
+		controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices = merged;
+		if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
+			mode = NOTHING;
+		else
+			mode = SELECTED;
+	}
+	
+	/**
+	 * Finishes the create connection operation and open a PopUp for
+	 * Link/Connection creation
+	 */
+	private void finishConnectionCreation() {
+		/**
+		 * SmartDevice the connection was
+		 */
+		SmartDevice connectionTo = getSmartDeviceAtPosition(dragged_x,
+				dragged_y);
+		if (mode == DRAG_CONNECTION && connectionFrom != null && connectionTo != null
+				&& connectionFrom != connectionTo) {
+			// Create new Connection
+			/**
+			 * Link of the new Connection
+			 */
+			Link l = null;
+			/**
+			 * Devices of the connection -> to find common Link
+			 */
+			LinkedList<SmartDevice> devices = new LinkedList<SmartDevice>();
+			devices.add(connectionFrom);
+			devices.add(connectionTo);
+			for(Link link:network.getLinks()){
+				if(link.getDevices().containsAll(devices)){
+					l = link;
+					break;
+				}
+			}
+			/**
+			 * Create new Connection if no link was found
+			 */
+			if(l==null){
+				l= new SimpleLink("Ethernet: " + connectionFrom.getName()
+					+ " to " + connectionTo.getName());
+				l.addDevice(connectionFrom);
+				l.addDevice(connectionTo);
+			}
+			//Create ports and add to controller
+			Port p1 = new Port(connectionFrom, (short) 1,(long) (Math.random()*300+300));
+			Port p2 = new Port(connectionTo, (short) 2,(long) (Math.random()*300+300));
+			Connection c = new ConnectionPerformance(l, new SimpleProtocol(p1, p2));
+			c.addSmartDevice(p1);
+			c.addSmartDevice(p2);
+			p1.setConnection(c);
+			p2.setConnection(c);
+			connectionTo.addLink(l);
+			connectionTo.addPort(p2);
+			connectionFrom.addLink(l);
+			connectionFrom.addPort(p1);
+			network.addConnectionToLink(c, l);
+			network.addConnection(c);
+			if(!network.getLinks().contains(l))
+				network.addLink(l);
+			
+		}
+		connectionFrom = null;
+		if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
+			mode = NOTHING;
+		else
+			mode = SELECTED;
+		panel.repaint();
+		controller.notifyObservers();
+	}
+
+	/**
+	 * Returns SmartDevice which is at position (x,y) or within its
+	 * visualization radius. Returns null, if no SmartDevice is within the
+	 * range.
+	 * 
+	 * @param x
+	 *            x-position which should be checked
+	 * @param y
+	 *            y-position which should be checked
+	 * @return {@link SmartDevice} at position (x,y) or null if there is no
+	 */
+	private SmartDevice getSmartDeviceAtPosition(int x, int y) {
+		// Check is device is inside visualization radius
+		for (SmartDevice d : network.getVisibleSmartDevices()) {
+			if (Math.abs(d.getX() - x) < config.getDeviceVisualizationRadius()
+					&& Math.abs(d.getY() - y) < config.getDeviceVisualizationRadius()) {
+				/**
+				 * correct distance / radius from the smartDevice
+				 */
+				int radius = (int) Math.floor(Math.sqrt((d.getX() - x)*(d.getX() - x)+(d.getY() - y)*(d.getY() - y)));
+				if(radius <= config.getDeviceVisualizationRadius())
+					return d;
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns all Connections, which cross point (x,y)
+	 * @param x xPosition of the point (x,y)
+	 * @param y yPosition of the point (x,y)
+	 * @return List of all possible clicked Connections
+	 */
+	private LinkedList<Pair<Connection, Pair<Port, Port>>> getConnectionsAtPosition(int x, int y) {
+		LinkedList<Pair<Connection,Pair<Port,Port>>> edges = new LinkedList<Pair<Connection,Pair<Port,Port>>>();
+		// Check is device is inside visualization radius
+		for(Connection c: network.getVisibleConnections()){
+			if(c.getProtocol()==null)
+				continue;
+			for(Pair<Port, Port> p: c.getProtocol().getTopology()){
+				if(pointOnConnection(x,y,p)){
+					edges.add(new Pair<Connection, Pair<Port,Port>>(c, p));
+					//break;//Connection was clicked - check for further connections
+				}
+			}
+		}
+		return edges;
+	}
+
+	/**
+	 * Returns true if the point (x,y) is on the connection part p.
+	 * 
+	 * @param x xPosition of the Point
+	 * @param y yPosition of the Point
+	 * @param p connection part, which connects to Ports with a line
+	 * @return true if point is on connection, else false
+	 */
+	private boolean pointOnConnection(int x, int y, Pair<Port, Port> p) {
+		//No valid connection part
+		if(p.getLeft()==null||p.getRight()==null||p.getLeft().getOwner()==null||p.getRight().getOwner()==null)
+			return false;
+		int lX = p.getLeft().getOwner().getX();
+		int lY = p.getLeft().getOwner().getY();
+		int rX = p.getRight().getOwner().getX();
+		int rY = p.getRight().getOwner().getY();
+		//Point out of bounds
+		if(x < Math.min(lX, rX) || x > Math.max(lX, rX) || y < Math.min(lY, rY) || y > Math.max(lY, rY))
+			return false;
+		double dLP = distance(lX,lY,x,y);
+		double dPR = distance(x,y,rX,rY);
+		double dLR = distance(lX,lY,rX,rY);
+		double diff = Math.abs(dLP+dPR-dLR);
+		return diff < 0.5;
+	}
+
+	/**
+	 * Calculates distance between (x1,y1) and (x2,y2)
+	 * 
+	 * @param x1 x Position of Point 1
+	 * @param y1 y Position of Point 1
+	 * @param x2 x Position of Point 1 
+	 * @param y2 y Position of Point 1
+	 * @return distance
+	 */
+	private double distance(int x1, int y1, int x2, int y2) {
+		return Math.sqrt(Math.pow(x1-x2, 2)+Math.pow(y1-y2, 2));
+	}
+
+	@Override
+	public void keyTyped(KeyEvent e) {
+		if(e.getKeyCode()==KeyEvent.VK_CONTROL){
+			if(controlDown!=true){
+				controlDown = true;
+				panel.repaint();
+			}
+		}
+	}
+
+	@Override
+	public void keyPressed(KeyEvent e) {
+		if(e.getKeyCode()==KeyEvent.VK_CONTROL){
+			if(controlDown!=true){
+				controlDown = true;
+				panel.repaint();
+			}
+		}
+	}
+
+	@Override
+	public void keyReleased(KeyEvent e) {
+		if(e.getKeyCode()==KeyEvent.VK_CONTROL){
+			if(controlDown==true){
+				controlDown = false;
+				panel.repaint();
+			}
+		}
+	}
+	
+	@Override
+	public void mouseMoved(MouseEvent e) {
+		/**
+		 * Link which might get a toolTip
+		 */
+		Link l = null; 
+		/**
+		 * Check Hover on Link
+		 */
+		if(config.isShowLinkToolTips())
+			l = getLinkVisualizationAtPosition(e.getX(),e.getY());
+		if(l != null){
+			if(l != toolTip.getLink() || !toolTip.isEnabled()){
+				toolTip.setText("Link "+l.getName());
+				toolTip.setLink(l);
+				toolTip.setX(e.getX());
+				toolTip.setY(e.getY());
+				toolTip.setEnabled(true);
+				panel.update(null, null);
+			}
+		}else{
+			if(toolTip.getLink()!=null || toolTip.isEnabled()){
+				toolTip.setLink(null);
+				toolTip.setEnabled(false);
+				panel.update(null, null);
+			}
+		}
+	}
+
+	/**
+	 * Return Link which is at position at the given position
+	 * @param x xPosition
+	 * @param y yPosition
+	 * @return Link at the position, else null
+	 */
+	private Link getLinkVisualizationAtPosition(int x, int y) {
+		if(!config.isShowLinks())
+			return null;
+		// Check is device is inside visualization radius
+		/**
+		 * Radius of the device
+		 */
+		int smallRadius = config.getDeviceVisualizationRadius();
+		/**
+		 * Radius of the device + link
+		 */
+		int radius =  smallRadius + config.getLinkRadius();
+		for (SmartDevice d : network.getVisibleSmartDevices()) {
+			//In DeviceRadius + Link Radius ?
+			if (Math.abs(d.getX() - x) <= radius && Math.abs(d.getY() - y) <= radius) {
+				//More detailed check
+				// On Ring ?
+				// On which part of Ring ?
+				//Outside of device ?
+				int realDistance = (int)Math.round(Math.sqrt((d.getX() - x)*(d.getX() - x)+(d.getY() - y)*(d.getY() - y)));
+				if (realDistance >= smallRadius && realDistance <= radius && !d.getLinks().isEmpty()) {
+					/**
+					 * Angle of this point. Counterclockwise, starting at 3 o' clock position
+					 */
+					float angle = Utility.getAngle(d.getX(), d.getY(), x, y);
+					/**
+					 * Number of Links in the Model
+					 */
+					int numberOfLinks = network.getVisibleLinks().size();
+					/**
+					 * Angle per Link in "linkSlice degrees"
+					 */
+					double linkSlice = Math.min(360.0 / numberOfLinks,90.0);
+					/**
+					 * calculate the number of the link
+					 */
+					int linkNumber = (int) Math.floor(angle / linkSlice);
+					/**
+					 * Return if, there are not so many link
+					 */
+					if(linkNumber>=numberOfLinks)
+						return null;
+					/**
+					 * Link, which would be at this connection
+					 */
+					Link linkAtPosition = (Link) network.getVisibleLinks().toArray()[linkNumber];
+					/**
+					 * Return link, if smartDevice contains it
+					 */
+					if(d.getLinks().contains(linkAtPosition))
+						return linkAtPosition;
+				}
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public void mouseEntered(MouseEvent e) {}
+
+	@Override
+	public void mouseExited(MouseEvent e) {
+		toolTip.setEnabled(false);
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {}
+	
+	/**
+	 * Shows the RightClick Menu on the Visualization Panel, with Options for
+	 * the given SmartDevice clickedOn, if clickedOn is null, the RightClick
+	 * Menu contains Options for creation of new SmartDevices. The Menu will be
+	 * shown at the Mouse position on the VisualisationPanel.
+	 * 
+	 * @param clickedOn
+	 *            Device which was clicked, otherwise null
+	 * @param clickedLink Link which was clicked, otherwise null
+	 */
+	protected void showRightClickMenu(SmartDevice clickedOn, Link clickedLink) {
+		this.clickedLink = clickedLink;
+		/**
+		 * Mouse Position on the VisualisationPanel
+		 */
+		Point mousePos = panel.getMousePosition();
+		// Just execute if Mouse Position is on the Panel
+		if (mousePos != null) {			
+			if (clickedOn == null) {
+				if(clickedLink == null){
+					itemCreateLink.setText("Create Link");
+					itemCreateLink.setEnabled(false);
+				}else{
+					itemCreateLink.setText("Edit Link");
+					itemCreateLink.setEnabled(true);
+				}
+				
+				itemCreate.setText("Create Device");
+				itemCreate.setEnabled(true);
+				itemDelete.setEnabled(false);
+				itemDeleteSelected.setEnabled(false);
+				if(controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection.size()>0){
+					/**
+					 * Update Connections which can be edited
+					 */
+					itemEditConnection.removeAll();	
+					
+					//List to prevent duplicate connection entries
+					LinkedList<Connection> editableConnections = new LinkedList<Connection>();
+					for(Pair<Connection, Pair<Port,Port>> p:controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection){
+						//Don't add the same connection multiple times
+						if(editableConnections.contains(p.getLeft())|| p == null || p.getLeft() == null)continue;
+						editableConnections.add(p.getLeft());
+						JMenuItem a = new JMenuItem(p.getLeft().getName());
+						a.addActionListener(e->new ConnectionCreationDialog(p.getLeft(), controller, panel));
+						itemEditConnection.add(a);
+					}
+					
+					if(rightClickMenu.getComponentIndex(itemCreateConnection)!=-1){
+						rightClickMenu.remove(itemCreateConnection);
+						rightClickMenu.add(itemEditConnection,editCreateConnectionIndex);
+						itemCreateConnection.setEnabled(false);				
+					}
+					itemEditConnection.setEnabled(true);
+				}else{
+					if(rightClickMenu.getComponentIndex(itemEditConnection)!=-1){
+						rightClickMenu.remove(itemEditConnection);
+						rightClickMenu.add(itemCreateConnection,editCreateConnectionIndex);
+					}
+					itemCreateConnection.setEnabled(false);
+				}
+			} else {
+				itemCreate.setText("Edit Device");
+				itemCreate.setEnabled(true);
+				itemDelete.setEnabled(true);
+				//Remove edit connection if it exist
+				if(rightClickMenu.getComponentIndex(itemEditConnection)!=-1){
+					rightClickMenu.remove(itemEditConnection);
+					rightClickMenu.add(itemCreateConnection,editCreateConnectionIndex);
+				}
+				itemCreateLink.setText("Create Link");
+				if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.contains(clickedOn)){
+					itemDeleteSelected.setEnabled(true);
+					itemCreateLink.setEnabled(true);
+					itemCreateConnection.setEnabled(true);
+				}
+				else{
+					itemDeleteSelected.setEnabled(false);
+					itemCreateLink.setEnabled(false);
+					itemCreateConnection.setEnabled(false);
+				}
+			}
+			// Show the RightClickMenu
+			rightClickMenu.show(panel, mousePos.x, mousePos.y);
+			rightClickMenu.setEnabled(true);
+			rightClickMenu.setVisible(true);
+			mode = RIGHTCLICK_MENU;
+		}
+	}
+
+	/**
+	 * Creates the RightClickMenu, adds the different Labels and functionalities to the menu and adds it to the panel.
+	 */
+	private void initializeRightClickMenu() {
+		this.rightClickMenu = new JPopupMenu();
+
+		// Create device option
+		itemCreate = new JMenuItem("Create SmartDevice");
+
+		itemCreate.addActionListener(e -> {
+			SmartDevice toEdit;
+			if(clicked == null){
+				toEdit = new SmartDevice("DeviceName");
+				toEdit.setX(dragged_x);
+				toEdit.setY(dragged_y);
+			}else{
+				toEdit = clicked;
+			}
+			SmartDeviceCreationPopUp popUp = new SmartDeviceCreationPopUp(toEdit, toEdit==clicked,controller);
+			popUp.setLocationRelativeTo(panel);
+			popUp.setEnabled(true);
+			popUp.setVisible(true);
+			mode = NOTHING;
+
+		});
+
+		rightClickMenu.add(itemCreate);
+		
+		// Create Link
+		itemCreateLink = new JMenuItem("Create Link");
+		
+		itemCreateLink.addActionListener(e -> {
+			if(clickedLink!=null){
+				new LinkCreationDialog(clickedLink, controller, panel);
+			}else{
+				new LinkCreationDialog(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices, controller, panel);
+			}
+			if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
+				mode = NOTHING;
+			else
+				mode = SELECTED;
+			
+		});
+		rightClickMenu.add(itemCreateLink);
+		
+		// Create Connection
+		itemCreateConnection = new JMenuItem("Create Connection");
+		itemCreateConnection.addActionListener(e->{
+			LinkedList<SmartDevice> selectedDevices = new LinkedList<SmartDevice>(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices);
+			LinkedList<Port> ports = new LinkedList<Port>();
+			for(SmartDevice d: selectedDevices)
+				ports.add(new Port(d, (short) 12));
+			Link link = null;
+			/**
+			 * Find common link -> else null -> create new link
+			 */
+			for(Link l:network.getLinks()){
+				if(l.getDevices().containsAll(selectedDevices)){
+					link = l;
+					break;
+				}
+			}
+			new ConnectionCreationDialog(ports,link, controller, panel);
+			if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
+				mode = NOTHING;
+			else
+				mode = SELECTED;
+		});
+		rightClickMenu.add(itemCreateConnection);
+		
+		// Edit connection
+		itemEditConnection = new JMenu("Edit Connection");
+
+		// Delete device option
+		itemDelete = new JMenuItem("Delete");
+
+		itemDelete.addActionListener(e -> {
+			// Delete the clicked object
+				network.deleteSmartDevice(clicked);
+				clicked = null;
+				controller.notifyObservers();
+				mode = NOTHING;
+			});
+
+		rightClickMenu.add(itemDelete);
+		
+		// Delete device option
+		itemDeleteSelected = new JMenuItem("Delete Selected");
+		
+		itemDeleteSelected.addActionListener(e -> {
+			// Delete the clicked object
+			for(SmartDevice c: controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices)
+				network.deleteSmartDevice(c);
+			controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.clear();
+			clicked = null;
+			controller.notifyObservers();
+			mode = NOTHING;
+		});
+		itemDeleteSelected.setEnabled(false);
+		rightClickMenu.add(itemDeleteSelected);
+				
+		/*
+		 * Add PrintDebug option
+		 */
+		itemDebug = new JMenuItem("Print NetworkState");
+		itemDebug.addActionListener(e -> {
+			// Print Links, Devices and Connections
+			System.out.println("Links:");
+				for (Link l : network.getLinks()){
+					System.out.println("Link: " + l.getName());
+					System.out.print("Devices of "+l.getName()+": ");
+					for(SmartDevice d:l.getDevices())
+						System.out.print(d.getName()+", ");
+					System.out.println();
+					System.out.print("Connections of "+l.getName()+": ");
+					for(Connection c: l.getConnections())
+						System.out.print(c.getName()+", ");
+					System.out.println();
+				}
+				System.out.println();
+				System.out.println("Devices");
+				for (SmartDevice d : network.getSmartDevices()) {
+					System.out.println("Device: " + d.getName());
+					System.out.println("Ports: ");
+					for (Port p : d.getPorts()) {
+						if(p==null){
+							System.out.println("Port: null");
+							continue;
+						}
+						System.out.println("Port: "+p.getPortNumber());
+						if(p.getOwner()!=null)
+							System.out.println("Owner: "+p.getOwner().getName());
+						else
+							System.out.println("Owner: null");
+						if(p.getConnection()==null){
+							System.out.println("Connection: null");
+						}else{
+							System.out.println("Connection: "+p.getConnection().getName());							
+						}
+						System.out.println("LastTrigger: " +p.getLastTrigger());
+						System.out.println("Jitter: " +p.getJitter());
+						System.out.println("ResponseTime: " +p.getResponseTime());
+						System.out.println("TriggerInterval: " +p.getTriggerInterval());
+						System.out.println("Status: " +Port.statusToString(p.getStatus()));
+						System.out.println();
+					}
+					System.out.println("");
+				}
+				// Print Terminating Packages
+				LinkedList<Connection> terminated = new LinkedList<Connection>();
+
+				network.getConnections()
+						.stream()
+						.forEach(c -> {
+							if(c.getStatus() == Connection.FINISHED || c
+								.getStatus() == Connection.TERMINATED)
+								terminated.add(c);
+							for (Packet p : c.getTerminationPackages(1000))
+								System.out.println(p.getTextualRepresentation());
+						});
+				network.getConnections().removeAll(terminated);
+				if(controller.getSettingsController().getConfigurationManager().getSelectionModel().selectedDevices.isEmpty())
+					mode = NOTHING;
+				else
+					mode = SELECTED;
+				controller.notifyObservers();
+			});
+		rightClickMenu.add(itemDebug);
+
+		this.panel.add(rightClickMenu);
+	}
+
+	/**
+	 * @return the toolTip
+	 */
+	public LinkToolTip getToolTip() {
+		return toolTip;
+	}
+}