Browse Source

Merge branch 'master' of https://git.tk.informatik.tu-darmstadt.de/carlos.garcia/praktikum-holons

# Conflicts:
#	src/ui/model/Model.java
dominik.rieder 7 years ago
parent
commit
7dcf1c8dd0

+ 18 - 2
src/ui/controller/Control.java

@@ -733,10 +733,26 @@ public class Control {
 	 */
 
 	public void addUpperNode(String nodeName, CpsUpperNode upperNode) {
-		nodeController.addNode(nodeName, upperNode);
+		nodeController.doUpperNode(nodeName, upperNode);
 	}
 	
-	public void addObjectInUpperNode(AbstractCpsObject object, CpsUpperNode upperNode) {
+	public void delUpperNode(CpsUpperNode node, CpsUpperNode upperNode) {
+		nodeController.undoUpperNode(node, upperNode);
+	}
+	
+	public void addObjUpperNode(AbstractCpsObject object, CpsUpperNode upperNode) {
 		nodeController.addObjectInUpperNode(object, upperNode);
 	}
+	
+	public void delObjUpperNode(AbstractCpsObject object, CpsUpperNode upperNode) {
+		nodeController.deleteObjectInUpperNode(object, upperNode);
+	}
+	
+	public void addEdgeUpperNode(CpsEdge edge, CpsUpperNode upperNode) {
+		nodeController.addEdge(edge, upperNode);
+	}
+	
+	public void delEdgeUpperNode(CpsEdge edge, CpsUpperNode upperNode) {
+		nodeController.deleteEdge(edge, upperNode);
+	}
 }

+ 17 - 0
src/ui/controller/MultiPurposeController.java

@@ -5,6 +5,7 @@ import java.util.Map.Entry;
 
 import classes.Category;
 import classes.CpsEdge;
+import classes.CpsUpperNode;
 import classes.AbstractCpsObject;
 import classes.HolonElement;
 import classes.HolonObject;
@@ -114,6 +115,22 @@ public class MultiPurposeController {
 	public HolonElement searchEleById(HolonObject object, int idEle) {
 		return object.searchElementById(idEle);
 	}
+	
+	/**
+	 * 
+	 * @param upperNode
+	 * @param id
+	 * @return
+	 */
+	public AbstractCpsObject searchIDUpperNode(CpsUpperNode upperNode, int id) {
+		
+		Integer idx;
+
+		if ((idx = upperNode.getNodesIdx().get(id)) == null || upperNode.getNodesIdx().size() < 1)
+			return null;
+		else
+			return upperNode.getNodes().get(idx);
+	}
 
 	/**
 	 * Search Edge between 2 Objects.

+ 205 - 36
src/ui/controller/NodeController.java

@@ -9,6 +9,7 @@ import classes.CpsEdge;
 import classes.CpsUpperNode;
 import classes.Position;
 import ui.model.Model;
+import ui.view.UpperNodeCanvas;
 
 public class NodeController {
 
@@ -28,11 +29,13 @@ public class NodeController {
 	 * 
 	 * @param nodeName
 	 */
-	public void addNode(String nodeName, CpsUpperNode upperNode) {
+	public void doUpperNode(String nodeName, CpsUpperNode upperNode) {
+
 		CpsUpperNode node = new CpsUpperNode(nodeName);
 		node.setPosition(calculatePos());
-		connectAdjacent(node, upperNode);
+		makeAdjacent(node, upperNode);
 		makeNodeOfNodes(node, upperNode);
+		backupOldEdges(node, upperNode);
 		if (upperNode == null)
 			cvs.addNewObject(node);
 		else
@@ -40,25 +43,19 @@ public class NodeController {
 
 	}
 
-	/**
-	 * Add a Object into a CpsUpperNode
-	 * 
-	 * @param object
-	 * @param upperNode
-	 */
-	public void addObjectInUpperNode(AbstractCpsObject object, CpsUpperNode upperNode) {
-		object.setSav("UPPER" + upperNode.getID());
-		upperNode.getNodesIdx().put(object.getID(), upperNode.getNodes().size());
-		upperNode.getNodes().add(object);
-	}
-
 	/**
 	 * Delete a CpsUpperNode from the Canvas
 	 * 
 	 * @param node
 	 */
-	public void deleteNode(CpsUpperNode node) {
-
+	public void undoUpperNode(CpsUpperNode node, CpsUpperNode upperNode) {
+		restoreOldEdges(node, upperNode);
+		unmakeNodesOfNodes(node, upperNode);
+		unmakeAdjacent(node, upperNode);
+		if (upperNode == null)
+			cvs.deleteObjectOnCanvas(node);
+		else
+			deleteObjectInUpperNode(node, upperNode);
 	}
 
 	/**
@@ -69,45 +66,53 @@ public class NodeController {
 	private void makeNodeOfNodes(CpsUpperNode node, CpsUpperNode upperNode) {
 
 		ArrayList<AbstractCpsObject> nodes = node.getNodes();
-		ArrayList<CpsEdge> nodeEdges = node.getNodeEdges();
-		HashMap<Integer, Integer> nodeIdx = node.getNodesIdx();
+		//ArrayList<CpsEdge> nodeEdges = node.getNodeEdges();
 
 		// Put all selected Nodes into the Upper Node
 		for (Iterator<AbstractCpsObject> it = model.getSelectedCpsObjects().iterator(); it.hasNext();) {
 
+			// füge Neue Objecte in Neuen Node hinzu
 			AbstractCpsObject obj = it.next();
-			nodeIdx.put(obj.getID(), nodes.size());
-			nodes.add(obj);
+			// POSITION MUSS NEU GEMACHT WERDEN FÜR OBJECTS IN NODE OF NODE
+			// obj.setPosition((obj.getPosition().x + node.getPosition().x) / 2,
+			// (obj.getPosition().y + node.getPosition().y) / 2);
+			addObjectInUpperNode(obj, node);
 		}
 
-		// remove selected nodes
-
+		// Füge die Edges die Alle Objekte vorher verbunden hat in neuen Node
 		for (Iterator<CpsEdge> it = (upperNode == null ? model.getEdgesOnCanvas() : upperNode.getNodeEdges())
 				.iterator(); it.hasNext();) {
 
 			CpsEdge edge = it.next();
-			if (nodes.contains(edge.getA()) && nodes.contains(edge.getB())) {
 
-				nodeEdges.add(edge);
+			// kopiere edge in UpperNode
+			if (nodes.contains(edge.getA()) && nodes.contains(edge.getB())) {
+				addEdge(edge, node);
 			}
 
 		}
-
+		// Lösche dann die Edges aus der nächst höheren schicht
 		for (AbstractCpsObject abs : model.getSelectedCpsObjects()) {
 			if (upperNode == null)
 				cvs.deleteObjectOnCanvas(abs);
 			else
-				// MUSS GEÄNDERT WERDEN!!!!!!!!!!!!!!!!!
-				upperNode.getNodes().remove(abs);
+				deleteObjectInUpperNode(abs, upperNode);
 		}
 
 	}
 
+	private void unmakeNodesOfNodes(CpsUpperNode node, CpsUpperNode upperNode) {
+		// TODO Auto-generated method stub
+		(upperNode == null ? model.getObjectsOnCanvas() : upperNode.getNodes()).addAll(node.getNodes());
+		(upperNode == null ? model.getCvsObjIdx() : upperNode.getNodesIdx()).putAll(node.getNodesIdx());
+		(upperNode == null ? model.getEdgesOnCanvas() : upperNode.getNodeEdges()).addAll(node.getNodeEdges());
+	}
+
 	/**
 	 * 
 	 * @return
 	 */
-	private void connectAdjacent(CpsUpperNode node, CpsUpperNode upperNode) {
+	private void makeAdjacent(CpsUpperNode node, CpsUpperNode upperNode) {
 
 		ArrayList<AbstractCpsObject> adj = new ArrayList<>();
 		ArrayList<Float> maxCapacity = new ArrayList<>();
@@ -115,16 +120,12 @@ public class NodeController {
 
 		ArrayList<CpsEdge> toDelete = new ArrayList<>();
 
-		// float maxCapacity = 0;
-
 		// für alle Edges auf dem Canvas
-		for (Iterator<CpsEdge> it = model.getEdgesOnCanvas().iterator(); it.hasNext();) {
+		for (Iterator<CpsEdge> it = (upperNode == null ? model.getEdgesOnCanvas() : upperNode.getNodeEdges())
+				.iterator(); it.hasNext();) {
 
 			CpsEdge edge = it.next();
 
-			// if (edge.getCapacity() > maxCapacity)
-			// maxCapacity = edge.getCapacity();
-
 			// wenn ausgewählte Objekte in edge und andere auserhalb
 			if (model.getSelectedCpsObjects().contains(edge.getA())
 					&& !model.getSelectedCpsObjects().contains(edge.getB())) {
@@ -158,20 +159,128 @@ public class NodeController {
 			}
 		}
 
-		model.getEdgesOnCanvas().removeAll(toDelete);
+		(upperNode == null ? model.getEdgesOnCanvas() : upperNode.getNodeEdges()).removeAll(toDelete);
 
 		// für alle objekte in adjazenzliste mach
 		for (AbstractCpsObject cps : adj) {
 			CpsEdge newEdge = new CpsEdge(cps, node, maxCapacity.get(adj.indexOf(cps)));
 			// !! Eventuell noch bei getConnections() hinzufügem
+			// node.getConnections().add(newEdge);
 			if (upperNode == null)
 				cvs.addEdgeOnCanvas(newEdge);
 			else
 				upperNode.getNodeEdges().add(newEdge);
-			node.getConnections().add(newEdge);
+
 		}
 	}
 
+	/**
+	 * 
+	 * @param node
+	 * @param upperNode
+	 */
+	private void unmakeAdjacent(CpsUpperNode node, CpsUpperNode upperNode) {
+		// TODO Auto-generated method stub
+		ArrayList<CpsEdge> toDelete = new ArrayList<>();
+
+		for (Iterator<CpsEdge> it = (upperNode == null ? model.getEdgesOnCanvas() : upperNode.getNodeEdges())
+				.iterator(); it.hasNext();) {
+
+			CpsEdge edge = it.next();
+			if (edge.getA().equals(node) || edge.getB().equals(node))
+				toDelete.add(edge);
+
+		}
+		(upperNode == null ? model.getEdgesOnCanvas() : upperNode.getNodeEdges()).removeAll(toDelete);
+		(upperNode == null ? model.getEdgesOnCanvas() : upperNode.getNodeEdges()).addAll(node.getOldEdges());
+	}
+
+	/**
+	 * Backups Old Edges into next lower layer in Current UpperNode anymore
+	 * 
+	 * @param node
+	 * @param upperNode
+	 */
+	private void backupOldEdges(CpsUpperNode node, CpsUpperNode upperNode) {
+
+		ArrayList<CpsEdge> backup = new ArrayList<>();
+		ArrayList<AbstractCpsObject> adj = new ArrayList<>();
+		ArrayList<Float> maxCapacity = new ArrayList<>();
+
+		// wenn upperNode in UpperNode erzeugt wird
+		if (upperNode != null) {
+			// für alle oldEdges die die zu gruppierenden nodes enthält werden
+			// in die neuen upperNOde verschoben
+			for (CpsEdge edge : upperNode.getOldEdges()) {
+				if (!upperNode.getNodes().contains(edge.getA()) && !upperNode.getNodes().contains(edge.getB()))
+					backup.add(edge);
+			}
+			// hier wird verschoben
+			node.getOldEdges().addAll(backup);
+
+			// neue adjazent muss hergestellt werden in den alten oldEdges
+			for (CpsEdge edge : upperNode.getOldEdges()) {
+
+				if (node.getNodes().contains(edge.getA()))
+					if (!adj.contains(edge.getB())) {
+						adj.add(edge.getB());
+						maxCapacity.add(edge.getCapacity());
+					} else if (maxCapacity.get(adj.indexOf(edge.getB())) < edge.getCapacity()) {
+						maxCapacity.set(adj.indexOf(edge.getB()), edge.getCapacity());
+
+					}
+				if (node.getNodes().contains(edge.getB()))
+					if (!adj.contains(edge.getA())) {
+						adj.add(edge.getA());
+						maxCapacity.add(edge.getCapacity());
+					} else if (maxCapacity.get(adj.indexOf(edge.getA())) < edge.getCapacity()) {
+						maxCapacity.set(adj.indexOf(edge.getA()), edge.getCapacity());
+
+					}
+			}
+			// alle übertragenen Edges werden gelöscht
+			upperNode.getOldEdges().removeAll(backup);
+			// neue edges werden erzeugt
+			for (AbstractCpsObject cps : adj)
+				upperNode.getOldEdges().add(new CpsEdge(cps, node, maxCapacity.get(adj.indexOf(cps))));
+
+		}
+	}
+
+	/**
+	 * Restore Old Edges into next higher layer of UpperNode
+	 * 
+	 * @param node
+	 * @param upperNode
+	 */
+	private void restoreOldEdges(CpsUpperNode node, CpsUpperNode upperNode) {
+
+		ArrayList<CpsEdge> toDelete = new ArrayList<>();
+
+		if (upperNode != null) {
+			for (CpsEdge edge : node.getOldEdges()) {
+				// wenn upperNode weder A oder B von von den OldEdges enthält
+				if (!upperNode.getNodes().contains(edge.getA()) && !upperNode.getNodes().contains(edge.getB()))
+					// Übertrage die OldEdges eine Schicht höher
+					toDelete.add(edge);
+			}
+			// übertrage sie hier
+			upperNode.getOldEdges().addAll(toDelete);
+			// lösch sie aus den zu löschenden node, da sonst durch unmake
+			// Adjacent probleme auftauchen
+			node.getOldEdges().removeAll(toDelete);
+			toDelete.clear();
+			// lösche alle OldEdges aus der höheren schicht die zu den zu
+			// löschenden Node vorher führten
+			for (CpsEdge edge : upperNode.getOldEdges()) {
+				if (edge.getA().equals(node) || edge.getB().equals(node))
+					toDelete.add(edge);
+			}
+			upperNode.getOldEdges().removeAll(toDelete);
+		}
+
+	}
+
 	/**
 	 * Calculate new Position of the Upper Node
 	 * 
@@ -192,4 +301,64 @@ public class NodeController {
 		return pos;
 	}
 
+	/**
+	 * Add a Object into a CpsUpperNode
+	 * 
+	 * @param object
+	 * @param upperNode
+	 */
+	public void addObjectInUpperNode(AbstractCpsObject object, CpsUpperNode upperNode) {
+		object.setSav("UPPER" + upperNode.getID());
+		upperNode.getNodesIdx().put(object.getID(), upperNode.getNodes().size());
+		upperNode.getNodes().add(object);
+	}
+
+	/**
+	 * Delete a AbstactCpsObject from CPSUpperNode
+	 * 
+	 * @param object
+	 * @param upperNode
+	 */
+	public void deleteObjectInUpperNode(AbstractCpsObject object, CpsUpperNode upperNode) {
+		CpsEdge e = null;
+		for (AbstractCpsObject cps : upperNode.getNodes()) {
+			for (CpsEdge p : cps.getConnections()) {
+				if (p.getA() == object || p.getB() == object) {
+					e = p;
+				}
+			}
+			if (!model.getClipboradObjects().contains(cps)) {
+				cps.getConnectedTo().remove(e);
+			}
+			upperNode.getNodeEdges().remove(e);
+		}
+		mpC.decIdx(object.getID(), upperNode.getNodesIdx());
+		upperNode.getNodesIdx().remove(object.getID());
+		upperNode.getNodes().remove(object);
+	}
+
+	/**
+	 * Add Edge in UpperNode
+	 * 
+	 * @param edge
+	 * @param upperNode
+	 */
+	public void addEdge(CpsEdge edge, CpsUpperNode upperNode) {
+		edge.getA().getConnections().add(edge);
+		edge.getB().getConnections().add(edge);
+		upperNode.getNodeEdges().add(edge);
+	}
+
+	/**
+	 * Delete Edge in UpperNode
+	 * 
+	 * @param edge
+	 * @param upperNode
+	 */
+	public void deleteEdge(CpsEdge edge, CpsUpperNode upperNode) {
+		edge.getA().getConnections().remove(edge);
+		edge.getB().getConnections().remove(edge);
+		upperNode.getNodeEdges().remove(edge);
+	}
+
 }

+ 122 - 0
src/ui/controller/UpdateController.java

@@ -0,0 +1,122 @@
+package ui.controller;
+
+import java.util.ArrayList;
+
+import classes.AbstractCpsObject;
+import classes.HolonElement;
+import classes.HolonObject;
+import ui.view.DefaulTable;
+import ui.view.Languages;
+import ui.view.PropertyTable;
+import ui.model.*;
+import ui.controller.*;
+
+/**
+ * This class is for all update methods and more ;)
+ * 
+ * @author Edgardo
+ *
+ */
+public class UpdateController {
+
+	Model model;
+	Control controller;
+
+	public UpdateController(Model model, Control control) {
+		this.model = model;
+		this.controller = control;
+	}
+
+	/**
+	 * Update the information concerning properties of the selected CpsObject.
+	 */
+	public void refreshTableProperties(DefaulTable table) {
+		if (model.getSelectedCpsObjects().size() == 1) {
+			AbstractCpsObject tempCps = model.getSelectedCpsObject();
+			if (tempCps != null && tempCps.getClass() == HolonObject.class) {
+				table.removeRow(2);
+				Object[] tempEnergy = { Languages.getLanguage()[73], ((HolonObject) tempCps).getCurrentEnergy() };
+				table.insertRow(2, tempEnergy);
+			}
+		}
+	}
+
+	/**
+	 * Add the Information of the given ArrayList in the HolonElement Model as
+	 * Name,Energy and Amount.
+	 * 
+	 * @param objects
+	 *            ArrayList to be displayed
+	 */
+	public void fillElementTable(ArrayList<AbstractCpsObject> objects, PropertyTable table) {
+		if (objects.size() > 1) {
+			for (AbstractCpsObject o : objects) {
+				if (o instanceof HolonObject) {
+					for (HolonElement he : ((HolonObject) o).getElements()) {
+						Object[] temp = { o.getName() + ", " + o.getID(), he.getId(), he.getEleName(), he.getEnergy(),
+								he.getAmount(), he.getActive() };
+						table.addRow(temp);
+					}
+				}
+			}
+		} else if (objects.size() == 1) {
+			AbstractCpsObject o = objects.get(0);
+			if (o instanceof HolonObject) {
+				for (HolonElement he : ((HolonObject) o).getElements()) {
+					Object[] temp = { he.getId(), he.getEleName(), he.getEnergy(), he.getAmount(), he.getActive() };
+					table.addRow(temp);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Update the HolonElement Table, that means erase all rows and add the new
+	 * rows with new data.
+	 */
+	public void refreshTableHolonElement(PropertyTable multiTable, PropertyTable singleTable) {
+		// Update of the Information about the HolonElements - only for
+		// HolonObjects
+
+		if (model.getSelectedCpsObjects().size() > 1) {
+			deleteRows(multiTable);
+			fillElementTable(model.getSelectedCpsObjects(), multiTable);
+			multiTable.fireTableDataChanged();
+		} else if (model.getSelectedCpsObjects().size() == 1) {
+			deleteRows(singleTable);
+			fillElementTable(model.getSelectedCpsObjects(), singleTable);
+			singleTable.fireTableDataChanged();
+		}
+	}
+
+	/**
+	 * Erase all information of the HolonElement Model.
+	 * 
+	 * @param t
+	 *            the Table
+	 */
+	public void deleteRows(PropertyTable t) {
+		if (t.getRowCount() > 0) {
+			for (int i = t.getRowCount() - 1; i > -1; i--) {
+				t.removeRow(i);
+			}
+		}
+	}
+
+	/**
+	 * Search for clicked HolonObject through the mouse's y-Coord.
+	 * 
+	 * @param yValue
+	 *            the Y Coordination
+	 * @return clicked HolonObject
+	 */
+	public HolonObject getHolonObj(int yValue, PropertyTable table) {
+		final int yTemp = (int) Math.floor(yValue / 16);
+		HolonObject obtTemp = null;
+		String temp = table.getValueAt(yTemp, 0).toString();
+		int idTemp = Integer.parseInt(temp.split(", ")[1]);
+		obtTemp = (HolonObject) controller.searchByID(idTemp);
+		return obtTemp;
+	}
+
+}

+ 15 - 17
src/ui/model/Model.java

@@ -290,6 +290,15 @@ public class Model {
 		return selectedObjects;
 	}
 
+	/**
+	 * Returns all selected Objects on the Canvas.
+	 * 
+	 * @return The selected Objects
+	 */
+	public void setSelectedCpsObjects(ArrayList<AbstractCpsObject> arr) {
+		this.selectedObjects = arr;
+	}
+
 	/**
 	 * Returns the Selected Holon Element.
 	 * 
@@ -355,14 +364,14 @@ public class Model {
 	 */
 	public void setCurIteration(int curIT) {
 		this.curIteration = curIT;
-		repaintGraphListeners();
+		notifyGraphListeners();
 	}
 
-	private void repaintGraphListeners() {
-		for(GraphListener gl: graphListeners){
+	private void notifyGraphListeners() {
+		for (GraphListener gl : graphListeners) {
 			gl.repaintGraph();
 		}
-		
+
 	}
 
 	/**
@@ -625,25 +634,14 @@ public class Model {
 
 	public void setTrackingObj(ArrayList<HolonObject> toTrack) {
 		trackingObj = toTrack;
-		addObjectsToGraphListeners();
-	}
-	
-	public void addObjectsToGraphListeners(){
-		for(GraphListener gl : graphListeners){
-			gl.addTrackedObject(trackingObj);
-		}
 	}
 
 	public ArrayList<HolonObject> getTrackingObj() {
 		return trackingObj;
 	}
-	
-	public void addGraphListener(GraphListener gl){
+
+	public void addGraphListener(GraphListener gl) {
 		graphListeners.add(gl);
 	}
-	
-	public ArrayList<GraphListener> getGraphListener(){
-		return graphListeners;
-	}
 
 }

+ 159 - 148
src/ui/view/GUI.java

@@ -24,6 +24,8 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import javax.swing.AbstractAction;
 import javax.swing.ActionMap;
@@ -78,6 +80,7 @@ import classes.IdCounter;
 import classes.IdCounterElem;
 import interfaces.CategoryListener;
 import ui.controller.Control;
+import ui.controller.UpdateController;
 import ui.model.Model;
 
 /**
@@ -90,6 +93,9 @@ import ui.model.Model;
  */
 public class GUI<E> implements CategoryListener {
 
+	// for doubleclick
+	private boolean click = false;
+
 	private JFrame frmCyberPhysical;
 
 	private final SimulationMenu simMenu;
@@ -262,6 +268,8 @@ public class GUI<E> implements CategoryListener {
 	private String eraseCategory = "Do you really want to delete the Category ";
 	private String selectObjBeforeErase = "Please select a Category or an Object in order to delete something.";
 
+	UpdateController updCon;
+
 	/**
 	 * Create the application.
 	 * 
@@ -283,7 +291,7 @@ public class GUI<E> implements CategoryListener {
 		simMenu = new SimulationMenu(model, control);
 		initialize();
 		updateCategories(model.getCategories());
-
+		updCon = new UpdateController(model, controller);
 	}
 
 	/**
@@ -680,8 +688,8 @@ public class GUI<E> implements CategoryListener {
 							controller.addElementCanvasObject(tempCpsObject.getID(), ele.getEleName(), ele.getAmount(),
 									ele.getEnergy());
 						}
-						refreshTableHolonElement();
-						refreshTableProperties();
+						updCon.refreshTableHolonElement(tableModelHolonElementMulti, tableModelHolonElementSingle);
+						updCon.refreshTableProperties(tableModelProperties);
 						controller.calculateStateForTimeStep(model.getCurIteration());
 					}
 				}
@@ -699,8 +707,8 @@ public class GUI<E> implements CategoryListener {
 						HolonObject obj = (HolonObject) getActualCps();
 						for (HolonElement e : selectedElements) {
 							controller.deleteElementCanvas(obj.getID(), e.getId());
-							refreshTableHolonElement();
-							refreshTableProperties();
+							updCon.refreshTableHolonElement(tableModelHolonElementMulti, tableModelHolonElementSingle);
+							updCon.refreshTableProperties(tableModelProperties);
 							controller.calculateStateForTimeStep(model.getCurIteration());
 							// Names displayed in graph are not updated
 						}
@@ -714,8 +722,8 @@ public class GUI<E> implements CategoryListener {
 							controller.deleteElementCanvas(i, e.getId());
 						}
 					}
-					refreshTableHolonElement();
-					refreshTableProperties();
+					updCon.refreshTableHolonElement(tableModelHolonElementMulti, tableModelHolonElementSingle);
+					updCon.refreshTableProperties(tableModelProperties);
 					eleToDelete.clear();
 					selectedElements.clear();
 				}
@@ -796,7 +804,7 @@ public class GUI<E> implements CategoryListener {
 					if (model.getSelectedCpsObjects().size() > 1) {
 						int selectedValueX = (int) Math.floor(xThis / (tableHolonElement.getWidth() / 6));
 						int selectedValueBX = (int) Math.floor(xBThis / (tableHolonElement.getWidth() / 6));
-						if (getHolonObj(yMouse) != null) {
+						if (updCon.getHolonObj(yMouse, tableModelHolonElementMulti) != null) {
 							// For last column (boolean with a checkbox)
 							if (selectedValueBX == 5) {
 								HolonElement eleBTemp = getActualHolonElement(null, yBMouse, 0);
@@ -857,7 +865,7 @@ public class GUI<E> implements CategoryListener {
 							}
 						}
 					}
-					refreshTableProperties();
+					updCon.refreshTableProperties(tableModelProperties);
 					tableModelHolonElementSingle.fireTableDataChanged();
 					controller.calculateStateForTimeStep(model.getCurIteration());
 					unitGraph.repaint();
@@ -917,9 +925,10 @@ public class GUI<E> implements CategoryListener {
 									((HolonSwitch) getActualCps()).setManualState(bTemp);
 								}
 							}
-						} else if (getActualCps() instanceof HolonObject) {
-							getActualCps().setName(temp.toString());
-						}
+						} // else if (getActualCps() instanceof
+							// AbstractCpsObject) {
+						getActualCps().setName(temp.toString());
+						// }
 					} else {
 						temp = tableModelProperties.getValueAt(selValueY, selValueX);
 						btemp = tableModelProperties.getValueAt(mousePos.y / tableProperties.getRowHeight(),
@@ -1010,24 +1019,51 @@ public class GUI<E> implements CategoryListener {
 			public void mouseReleased(MouseEvent e) {
 				try {
 					if (dragging) {
-						int x = (int) canvas.getMousePosition().getX();
-						int y = (int) canvas.getMousePosition().getY();
-						AbstractCpsObject h = null;
-						if (tempCps.getClass() == HolonObject.class) {
-							h = new HolonObject(tempCps);
-						}
-						if (tempCps.getClass() == HolonSwitch.class) {
-							h = new HolonSwitch(tempCps);
-						}
-						if (tempCps.getClass() == HolonTransformer.class) {
-							h = new HolonTransformer(tempCps);
-						}
+						if (((JScrollPane) tabbedPane.getSelectedComponent()).getViewport()
+								.getComponent(0) instanceof UpperNodeCanvas) {
+							UpperNodeCanvas unc = ((UpperNodeCanvas) ((JScrollPane) tabbedPane.getSelectedComponent())
+									.getViewport().getComponent(0));
 
-						h.setPosition(x, y);
-						controller.addObjectCanvas(h);
-						canvas.invalidate();
-						canvas.repaint();
+							int x = (int) unc.getMousePosition().getX();
+							int y = (int) unc.getMousePosition().getY();
+
+							AbstractCpsObject h = null;
+							if (tempCps instanceof HolonObject) {
+								h = new HolonObject(tempCps);
+							}
+							if (tempCps instanceof HolonSwitch) {
+								h = new HolonSwitch(tempCps);
+							}
+							if (tempCps instanceof HolonTransformer) {
+								h = new HolonTransformer(tempCps);
+							}
+
+							h.setPosition(x, y);
+
+							controller.addObjUpperNode(h, unc.upperNode);
+							unc.invalidate();
+							unc.repaint();
+						} else {
+							int x = (int) canvas.getMousePosition().getX();
+							int y = (int) canvas.getMousePosition().getY();
+
+							AbstractCpsObject h = null;
+							if (tempCps instanceof HolonObject) {
+								h = new HolonObject(tempCps);
+							}
+							if (tempCps instanceof HolonSwitch) {
+								h = new HolonSwitch(tempCps);
+							}
+							if (tempCps instanceof HolonTransformer) {
+								h = new HolonTransformer(tempCps);
+							}
+
+							h.setPosition(x, y);
 
+							controller.addObjectCanvas(h);
+							canvas.invalidate();
+							canvas.repaint();
+						}
 						dragging = false;
 					}
 				} catch (Exception eex) {
@@ -1053,8 +1089,8 @@ public class GUI<E> implements CategoryListener {
 							.getPathForLocation(e.getX(), e.getY()).getLastPathComponent();
 					if (selectedNode.getLevel() == 2) {
 						controller.searchCategoryObject(selectedNode.getParent().toString(), selectedNode.toString());
-						deleteRows(tableModelHolonElementSingle);
-						deleteRows(tableModelHolonElementMulti);
+						updCon.deleteRows(tableModelHolonElementSingle);
+						updCon.deleteRows(tableModelHolonElementMulti);
 						// if (selected instanceof HolonObject && selected !=
 						// null) {
 						// selected = (HolonObject) selected;
@@ -1212,7 +1248,7 @@ public class GUI<E> implements CategoryListener {
 					// For HolonObjects the Total Energy (production or
 					// consumption) is calculated
 					if (temp instanceof HolonObject) {
-						refreshTableHolonElement();
+						updCon.refreshTableHolonElement(tableModelHolonElementMulti, tableModelHolonElementSingle);
 						Object[] tempEnergy = { Languages.getLanguage()[73], ((HolonObject) temp).getCurrentEnergy() };
 						tableModelProperties.addRow(tempEnergy);
 						tableModelProperties.setCellEditable(0, 1, true);
@@ -1221,8 +1257,8 @@ public class GUI<E> implements CategoryListener {
 					} // For HolonSwitches is showed the actual status (active
 						// or inactive)
 					else if (temp instanceof HolonSwitch) {
-						deleteRows(tableModelHolonElementSingle);
-						deleteRows(tableModelHolonElementMulti);
+						updCon.deleteRows(tableModelHolonElementSingle);
+						updCon.deleteRows(tableModelHolonElementMulti);
 						Object[] tempMode = { Languages.getLanguage()[74], ((HolonSwitch) temp).getManualMode() };
 						tableModelProperties.addRow(tempMode);
 						if (((HolonSwitch) temp).getManualMode()) {
@@ -1241,8 +1277,8 @@ public class GUI<E> implements CategoryListener {
 						tableModelProperties.setCellEditable(0, 1, true);
 						tableModelProperties.setCellEditable(2, 1, true);
 					} else {
-						deleteRows(tableModelHolonElementSingle);
-						deleteRows(tableModelHolonElementMulti);
+						updCon.deleteRows(tableModelHolonElementSingle);
+						updCon.deleteRows(tableModelHolonElementMulti);
 					}
 					// For Objects the only editable cell is the name
 					ArrayList<CpsEdge> tempArray = temp.getConnections();
@@ -1298,8 +1334,8 @@ public class GUI<E> implements CategoryListener {
 					tableModelProperties.setCellEditable(2, 1, true);
 					tableModelProperties.setCellEditable(3, 1, true);
 				} else if (getActualCps() == null) {
-					deleteRows(tableModelHolonElementSingle);
-					deleteRows(tableModelHolonElementMulti);
+					updCon.deleteRows(tableModelHolonElementSingle);
+					updCon.deleteRows(tableModelHolonElementMulti);
 				} // Update of the HolonElementTable (Single- or
 					// Multi-Selection)
 				if (model.getSelectedCpsObjects().size() > 1) {
@@ -1308,21 +1344,15 @@ public class GUI<E> implements CategoryListener {
 					tableHolonElement.setModel(tableModelHolonElementSingle);
 				}
 				// New Tab with NodeOfNode
-				if (canvas.click && temp instanceof CpsUpperNode) {
-					UpperNodeCanvas unc = new UpperNodeCanvas(model, controller, (CpsUpperNode) temp);
-					unc.setBorder(null);
-					unc.setBackground(Color.WHITE);
-					unc.setPreferredSize(new Dimension(model.getCanvasX(), model.getCanvasY()));
-					JScrollPane sp = new JScrollPane(unc);
-					sp.setBorder(null);
-					tabbedPane.add(temp.getName(), sp);
+				if (doubleClick() && temp instanceof CpsUpperNode) {
+					openNewUpperNodeTab();
 				}
 			}
 
 			@Override
 			public void mouseReleased(MouseEvent e) {
-				refreshTableHolonElement();
-				refreshTableProperties();
+				updCon.refreshTableHolonElement(tableModelHolonElementMulti, tableModelHolonElementSingle);
+				updCon.refreshTableProperties(tableModelProperties);
 				if (model.getSelectedCpsObjects().size() > 1) {
 					tableHolonElement.setModel(tableModelHolonElementMulti);
 				} else if (model.getSelectedCpsObjects().size() == 1) {
@@ -1473,7 +1503,7 @@ public class GUI<E> implements CategoryListener {
 			public void actionPerformed(ActionEvent e) {
 				Languages.setLanguage(0);
 				refreshLanguages();
-				refreshTableProperties();
+				updCon.refreshTableProperties(tableModelProperties);
 			}
 		});
 		spanishBtn.addActionListener(new ActionListener() {
@@ -1482,7 +1512,7 @@ public class GUI<E> implements CategoryListener {
 			public void actionPerformed(ActionEvent e) {
 				Languages.setLanguage(1);
 				refreshLanguages();
-				refreshTableProperties();
+				updCon.refreshTableProperties(tableModelProperties);
 			}
 		});
 		germanBtn.addActionListener(new ActionListener() {
@@ -1491,7 +1521,7 @@ public class GUI<E> implements CategoryListener {
 			public void actionPerformed(ActionEvent e) {
 				Languages.setLanguage(2);
 				refreshLanguages();
-				refreshTableProperties();
+				updCon.refreshTableProperties(tableModelProperties);
 			}
 		});
 		czechBtn.addActionListener(new ActionListener() {
@@ -1500,7 +1530,7 @@ public class GUI<E> implements CategoryListener {
 			public void actionPerformed(ActionEvent e) {
 				Languages.setLanguage(3);
 				refreshLanguages();
-				refreshTableProperties();
+				updCon.refreshTableProperties(tableModelProperties);
 			}
 		});
 		chineseBtn.addActionListener(new ActionListener() {
@@ -1509,7 +1539,8 @@ public class GUI<E> implements CategoryListener {
 			public void actionPerformed(ActionEvent e) {
 				Languages.setLanguage(4);
 				refreshLanguages();
-				refreshTableProperties();
+				updCon.refreshTableProperties(tableModelProperties);
+				;
 			}
 		});
 
@@ -1605,10 +1636,8 @@ public class GUI<E> implements CategoryListener {
 		splitPane.setLeftComponent(scrollPane1);
 		splitPaneCanvasConsole.setLeftComponent(panelTapped_SimMenu);
 		tabbedPane.addTab("View", canvasSP);
-		tabbedPane.setTabComponentAt(0, new ButtonTabComponent(tabbedPane));
-		tabbedPane.addTab("Statistics", statScrollPane);
-		tabbedPane.setTabComponentAt(1, new ButtonTabComponent(tabbedPane));
-		
+		tabbedPane.addTab("Statistics", statScrollPane);
+
 		splitPaneCanvasConsole.setRightComponent(console);
 		splitPane1.setLeftComponent(splitPaneCanvasConsole);
 		splitPane1.setRightComponent(splitHolonElPro);
@@ -1828,98 +1857,6 @@ public class GUI<E> implements CategoryListener {
 		}
 	}
 
-	/**
-	 * Search for clicked HolonObject through the mouse's y-Coord.
-	 * 
-	 * @param yValue
-	 *            the Y Coordination
-	 * @return clicked HolonObject
-	 */
-	private HolonObject getHolonObj(int yValue) {
-		final int yTemp = (int) Math.floor(yValue / 16);
-		HolonObject obtTemp = null;
-		String temp = tableModelHolonElementMulti.getValueAt(yTemp, 0).toString();
-		int idTemp = Integer.parseInt(temp.split(", ")[1]);
-		obtTemp = (HolonObject) controller.searchByID(idTemp);
-		return obtTemp;
-	}
-
-	/**
-	 * Update the HolonElement Table, that means erase all rows and add the new
-	 * rows with new data.
-	 */
-	private void refreshTableHolonElement() {
-		// Update of the Information about the HolonElements - only for
-		// HolonObjects
-
-		if (model.getSelectedCpsObjects().size() > 1) {
-			deleteRows(tableModelHolonElementMulti);
-			fillElementTable(model.getSelectedCpsObjects());
-			tableModelHolonElementMulti.fireTableDataChanged();
-		} else if (model.getSelectedCpsObjects().size() == 1) {
-			deleteRows(tableModelHolonElementSingle);
-			fillElementTable(model.getSelectedCpsObjects());
-			tableModelHolonElementSingle.fireTableDataChanged();
-		}
-	}
-
-	/**
-	 * Erase all information of the HolonElement Model.
-	 * 
-	 * @param t
-	 *            the Table
-	 */
-	private void deleteRows(PropertyTable t) {
-		if (t.getRowCount() > 0) {
-			for (int i = t.getRowCount() - 1; i > -1; i--) {
-				t.removeRow(i);
-			}
-		}
-	}
-
-	/**
-	 * Add the Information of the given ArrayList in the HolonElement Model as
-	 * Name,Energy and Amount.
-	 * 
-	 * @param objects
-	 *            ArrayList to be displayed
-	 */
-	private void fillElementTable(ArrayList<AbstractCpsObject> objects) {
-		if (objects.size() > 1) {
-			for (AbstractCpsObject o : objects) {
-				if (o instanceof HolonObject) {
-					for (HolonElement he : ((HolonObject) o).getElements()) {
-						Object[] temp = { o.getName() + ", " + o.getID(), he.getId(), he.getEleName(), he.getEnergy(),
-								he.getAmount(), he.getActive() };
-						tableModelHolonElementMulti.addRow(temp);
-					}
-				}
-			}
-		} else if (objects.size() == 1) {
-			AbstractCpsObject o = objects.get(0);
-			if (o instanceof HolonObject) {
-				for (HolonElement he : ((HolonObject) o).getElements()) {
-					Object[] temp = { he.getId(), he.getEleName(), he.getEnergy(), he.getAmount(), he.getActive() };
-					tableModelHolonElementSingle.addRow(temp);
-				}
-			}
-		}
-	}
-
-	/**
-	 * Update the information concerning properties of the selected CpsObject.
-	 */
-	private void refreshTableProperties() {
-		if (model.getSelectedCpsObjects().size() == 1) {
-			AbstractCpsObject tempCps = getActualCps();
-			if (tempCps != null && tempCps.getClass() == HolonObject.class) {
-				tableModelProperties.removeRow(2);
-				Object[] tempEnergy = { Languages.getLanguage()[73], ((HolonObject) tempCps).getCurrentEnergy() };
-				tableModelProperties.insertRow(2, tempEnergy);
-			}
-		}
-	}
-
 	/**
 	 * Adds a Popup.
 	 * 
@@ -2004,4 +1941,78 @@ public class GUI<E> implements CategoryListener {
 		// Image Size Slider
 		lblImageSize.setText(Languages.getLanguage()[94]);
 	}
+
+	/**
+	 * Checks if a double click was made.
+	 * 
+	 * @return
+	 * 
+	 * @return true if doublecklick, false if not
+	 */
+	private boolean doubleClick() {
+		if (click) {
+			click = false;
+			return true;
+		} else {
+			click = true;
+			Timer t = new Timer("doubleclickTimer", false);
+			t.schedule(new TimerTask() {
+				@Override
+				public void run() {
+					click = false;
+				}
+			}, 350);
+		}
+		return false;
+	}
+
+	/*
+	 * Open a new Tab with an UpperNodeCanvas
+	 */
+	private void openNewUpperNodeTab() {
+
+		UpperNodeCanvas unc;
+		if (((JScrollPane) tabbedPane.getSelectedComponent()).getViewport().getComponent(0) instanceof MyCanvas) {
+			unc = new UpperNodeCanvas(model, controller, (CpsUpperNode) temp, "");
+		} else {
+			unc = new UpperNodeCanvas(model, controller, (CpsUpperNode) temp,
+					((UpperNodeCanvas) ((JScrollPane) tabbedPane.getSelectedComponent()).getViewport()
+							.getComponent(0)).path + " -> ");
+		}
+
+		// check if tab already open for clicked NodeOfNode
+		boolean dupl = false;
+		for (int i = 2; i < tabbedPane.getTabCount() && dupl == false; i++) {
+			if (((UpperNodeCanvas) ((JScrollPane) tabbedPane.getComponentAt(i)).getViewport().getComponent(0)).upperNode
+					.getID() == temp.getID()) {
+				dupl = true;
+				tabbedPane.setSelectedComponent(tabbedPane.getComponentAt(i));
+			}
+		}
+		if (!dupl) {
+
+			unc.setBorder(null);
+			unc.setBackground(Color.WHITE);
+			unc.setPreferredSize(new Dimension(model.getCanvasX(), model.getCanvasY()));
+
+			unc.addMouseListener(new MouseAdapter() {
+				@Override
+				public void mousePressed(MouseEvent e) {
+					temp = unc.tempCps;
+					if (doubleClick() && temp instanceof CpsUpperNode) {
+						openNewUpperNodeTab();
+					}
+				}
+			});
+
+			JScrollPane sp = new JScrollPane(unc);
+			sp.setBorder(null);
+			tabbedPane.add(temp.getName(), sp);
+			tabbedPane.setSelectedComponent(sp);
+			tabbedPane.setTabComponentAt(tabbedPane.getTabCount() - 1, new ButtonTabComponent(tabbedPane));
+			temp = null;
+
+		}
+	}
+
 }

+ 27 - 13
src/ui/view/MyCanvas.java

@@ -73,7 +73,8 @@ public class MyCanvas extends JPanel implements MouseListener, MouseMotionListen
 	private JMenuItem itemCut = new JMenuItem("Cut");
 	private JMenuItem itemCopy = new JMenuItem("Copy");
 	public JMenuItem itemPaste = new JMenuItem("Paste");
-	public JMenuItem itemCollapse = new JMenuItem("Colapse Nodes");
+	public JMenuItem itemGroup = new JMenuItem("Group");
+	public JMenuItem itemUngroup = new JMenuItem("Ungroup");
 	public JMenuItem itemTrack = new JMenuItem("Track");
 	public JMenuItem itemUntrack = new JMenuItem("Untrack");
 	private JToolTip objectTT = new JToolTip();
@@ -108,7 +109,8 @@ public class MyCanvas extends JPanel implements MouseListener, MouseMotionListen
 		popmenu.add(itemPaste);
 		popmenu.add(itemDelete);
 		popmenu.addSeparator();
-		popmenu.add(itemCollapse);
+		popmenu.add(itemGroup);
+		popmenu.add(itemUngroup);
 		popmenu.add(itemTrack);
 		popmenu.add(itemUntrack);
 
@@ -116,11 +118,12 @@ public class MyCanvas extends JPanel implements MouseListener, MouseMotionListen
 		itemCut.setEnabled(false);
 		itemCopy.setEnabled(false);
 		itemPaste.setEnabled(false);
-		itemCollapse.setEnabled(false);
+		itemGroup.setEnabled(false);
+		itemUngroup.setEnabled(false);
 		itemTrack.setEnabled(false);
 		itemUntrack.setEnabled(false);
 
-		itemCollapse.addActionListener(new ActionListener() {
+		itemGroup.addActionListener(new ActionListener() {
 			@Override
 			public void actionPerformed(ActionEvent e) {
 				controller.addUpperNode("NodeOfNode", null);
@@ -128,6 +131,14 @@ public class MyCanvas extends JPanel implements MouseListener, MouseMotionListen
 			}
 		});
 
+		itemUngroup.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				controller.delUpperNode((CpsUpperNode) tempCps, null);
+				repaint();
+			}
+		});
+
 		itemTrack.addActionListener(new ActionListener() {
 			@Override
 			public void actionPerformed(ActionEvent e) {
@@ -403,13 +414,9 @@ public class MyCanvas extends JPanel implements MouseListener, MouseMotionListen
 					img = new ImageIcon(this.getClass().getResource(cps.getImage())).getImage();
 				}
 			}
-			if (cps instanceof CpsUpperNode) {
-				g2.drawImage(img, cps.getPosition().x, cps.getPosition().y, (int)(controller.getScale()*1.5),
-						(int)(controller.getScale()*1.5), null);
-			} else {
-				g2.drawImage(img, cps.getPosition().x, cps.getPosition().y, controller.getScale(),
-						controller.getScale(), null);
-			}
+			g2.drawImage(img, cps.getPosition().x, cps.getPosition().y, controller.getScale(), controller.getScale(),
+					null);
+
 		}
 
 		// Dragg Highlighting
@@ -521,7 +528,13 @@ public class MyCanvas extends JPanel implements MouseListener, MouseMotionListen
 				itemDelete.setEnabled(true);
 				itemCut.setEnabled(true);
 				itemCopy.setEnabled(true);
-				itemCollapse.setEnabled(true);
+				if (tempCps != null)
+					itemGroup.setEnabled(true);
+				if (tempCps instanceof CpsUpperNode)
+					itemUngroup.setEnabled(true);
+				else
+					itemUngroup.setEnabled(false);
+
 				if (!(tempCps instanceof HolonSwitch)) {
 					itemTrack.setEnabled(true);
 					itemUntrack.setEnabled(true);
@@ -536,7 +549,8 @@ public class MyCanvas extends JPanel implements MouseListener, MouseMotionListen
 				itemCut.setEnabled(false);
 				itemCopy.setEnabled(false);
 				itemDelete.setEnabled(false);
-				itemCollapse.setEnabled(false);
+				itemGroup.setEnabled(false);
+				itemUngroup.setEnabled(false);
 				itemTrack.setEnabled(false);
 				itemUntrack.setEnabled(false);
 			}

+ 52 - 27
src/ui/view/UpperNodeCanvas.java

@@ -6,7 +6,6 @@ import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Image;
 import java.awt.Point;
-import java.awt.Rectangle;
 import java.awt.RenderingHints;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -21,12 +20,13 @@ import java.util.Timer;
 import java.util.TimerTask;
 
 import javax.swing.ImageIcon;
+import javax.swing.JLabel;
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
 import javax.swing.JToolTip;
 
-import api.CpsAPI;
 import classes.CpsEdge;
 import classes.CpsNode;
 import classes.CpsUpperNode;
@@ -57,12 +57,16 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 	private int sx, sy; // Mark Coords
 	private float scalediv20;
 
+	// Path
+	public String path;
+	private JLabel breadCrumb;
+
 	ArrayList<HolonElement> dataSelected = new ArrayList<HolonElement>();
 	ArrayList<AbstractCpsObject> tempSelected = new ArrayList<AbstractCpsObject>();
-	
-	//The UpperNode
-	CpsUpperNode upperNode;
-	
+
+	// The UpperNode
+	public CpsUpperNode upperNode;
+
 	private boolean[] showedInformation = new boolean[3];
 	private boolean dragging = false; // for dragging
 	private boolean dragged = false; // if an object/objects was/were dragged
@@ -78,7 +82,8 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 	private JMenuItem itemCut = new JMenuItem("Cut");
 	private JMenuItem itemCopy = new JMenuItem("Copy");
 	public JMenuItem itemPaste = new JMenuItem("Paste");
-	public JMenuItem itemCollapse = new JMenuItem("Colapse Nodes");
+	public JMenuItem itemGroup = new JMenuItem("Group");
+	public JMenuItem itemUngroup = new JMenuItem("Ungroup");
 	public JMenuItem itemTrack = new JMenuItem("Track");
 	public JMenuItem itemUntrack = new JMenuItem("Untrack");
 	private JToolTip objectTT = new JToolTip();
@@ -97,13 +102,14 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 	 * @param control
 	 *            the Controller
 	 */
-	public UpperNodeCanvas(Model mod, Control control, CpsUpperNode UpperNode) {
+	public UpperNodeCanvas(Model mod, Control control, CpsUpperNode UpperNode, String parentPath) {
 		this.add(objectTT);
 		this.controller = control;
 		this.model = mod;
-
 		this.upperNode = UpperNode;
-		
+		this.path = parentPath + upperNode.getName();
+		this.breadCrumb = new JLabel(path);
+		// this.add(breadCrumb);
 		scalediv20 = model.getScale() / 20;
 
 		showedInformation[0] = true;
@@ -115,7 +121,8 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 		popmenu.add(itemPaste);
 		popmenu.add(itemDelete);
 		popmenu.addSeparator();
-		popmenu.add(itemCollapse);
+		popmenu.add(itemGroup);
+		popmenu.add(itemUngroup);
 		popmenu.add(itemTrack);
 		popmenu.add(itemUntrack);
 
@@ -123,14 +130,23 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 		itemCut.setEnabled(false);
 		itemCopy.setEnabled(false);
 		itemPaste.setEnabled(false);
-		itemCollapse.setEnabled(false);
+		itemGroup.setEnabled(false);
+		itemUngroup.setEnabled(false);
 		itemTrack.setEnabled(false);
 		itemUntrack.setEnabled(false);
 
-		itemCollapse.addActionListener(new ActionListener() {
+		itemGroup.addActionListener(new ActionListener() {
 			@Override
 			public void actionPerformed(ActionEvent e) {
-				controller.addUpperNode("NodeOfNode", null);
+				controller.addUpperNode("NodeOfNode", UpperNode);
+				repaint();
+			}
+		});
+		
+		itemUngroup.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				controller.delUpperNode((CpsUpperNode) tempCps, UpperNode);
 				repaint();
 			}
 		});
@@ -191,7 +207,7 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 			public void actionPerformed(ActionEvent e) {
 				// Remove the selected Object objects
 				for (AbstractCpsObject cps : model.getSelectedCpsObjects()) {
-					controller.delCanvasObject(cps);
+					controller.delObjUpperNode(cps, UpperNode);
 				}
 				model.getSelectedCpsObjects().clear();
 				tempCps = null;
@@ -238,6 +254,7 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 	public void paintComponent(Graphics g) {
 		String maxCap;
 		super.paintComponent(g);
+		((JScrollPane) this.getParent().getParent()).setColumnHeaderView(breadCrumb);
 		// Rendering
 		g2 = (Graphics2D) g;
 		RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
@@ -472,7 +489,9 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 				}
 			}
 		}
-
+		// Selection of CpsObject
+		model.setSelectedCpsObject(tempCps);
+		
 		// Edge Selection
 		if (tempCps == null) {
 			edgeHighlight = mousePositionOnEdge(x, y);
@@ -523,7 +542,12 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 				itemDelete.setEnabled(true);
 				itemCut.setEnabled(true);
 				itemCopy.setEnabled(true);
-				itemCollapse.setEnabled(true);
+				if (tempCps != null)
+					itemGroup.setEnabled(true);
+				if (tempCps instanceof CpsUpperNode)
+					itemUngroup.setEnabled(true);
+				else
+					itemUngroup.setEnabled(false);
 				if (!(tempCps instanceof HolonSwitch)) {
 					itemTrack.setEnabled(true);
 					itemUntrack.setEnabled(true);
@@ -538,7 +562,8 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 				itemCut.setEnabled(false);
 				itemCopy.setEnabled(false);
 				itemDelete.setEnabled(false);
-				itemCollapse.setEnabled(false);
+				itemGroup.setEnabled(false);
+				itemUngroup.setEnabled(false);
 				itemTrack.setEnabled(false);
 				itemUntrack.setEnabled(false);
 			}
@@ -704,7 +729,7 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 					}
 				}
 				if (!newEdge) {
-					controller.removeEdgesOnCanvas(e);
+					controller.delEdgeUpperNode(e, upperNode);
 					// Node ohne Edge?
 					if (e.getA().getClass() == CpsNode.class && e.getA().getConnections().isEmpty()) {
 						tempCps = e.getA();
@@ -717,7 +742,7 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 				}
 				if (newEdge) {
 					e = new CpsEdge(cps, tempCps, edgeCapacity);
-					controller.addEdgeOnCanvas(e);
+					controller.addEdgeUpperNode(e, upperNode);
 				}
 			}
 		}
@@ -733,7 +758,7 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 				CpsNode n = new CpsNode("Node");
 
 				n.setPosition(x - model.getScaleDiv2(), y - model.getScaleDiv2());
-				controller.addObjectCanvas(n);
+				controller.addObjUpperNode(n, upperNode);
 
 				AbstractCpsObject r, k;
 				r = p.getA();
@@ -745,10 +770,10 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 
 				e2 = new CpsEdge(n, k, edgeCapacity);
 
-				controller.removeEdgesOnCanvas(p);
-				controller.addEdgeOnCanvas(e);
-				controller.addEdgeOnCanvas(e1);
-				controller.addEdgeOnCanvas(e2);
+				controller.delEdgeUpperNode(p, upperNode);
+				controller.addEdgeUpperNode(e, upperNode);
+				controller.addEdgeUpperNode(e1, upperNode);
+				controller.addEdgeUpperNode(e2, upperNode);
 			}
 		}
 
@@ -757,11 +782,11 @@ public class UpperNodeCanvas extends JPanel implements MouseListener, MouseMotio
 			CpsNode n = new CpsNode("Node");
 
 			n.setPosition(x - model.getScaleDiv2(), y - model.getScaleDiv2());
-			controller.addObjectCanvas(n);
+			controller.addObjUpperNode(n, upperNode);
 
 			e = new CpsEdge(n, tempCps, edgeCapacity);
 
-			controller.addEdgeOnCanvas(e);
+			controller.addEdgeUpperNode(e, upperNode);
 		}
 
 		// Wenn ein Node ohne Connections da ist