Pārlūkot izejas kodu

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

Merge till newest update
tolatesry 6 gadi atpakaļ
vecāks
revīzija
5a0f49458c

+ 25 - 0
src/ui/controller/CanvasController.java

@@ -105,6 +105,31 @@ public class CanvasController {
 		notifyObjListeners();
 	}
 
+	/**
+     * Replaces {@code toBeReplaced} by {@code by} on the canvas
+     * @param toBeReplaced the object that will be replaced
+     * @param by the object that will replace it
+     */
+	public void replaceObjectOnCanvas(AbstractCpsObject toBeReplaced, AbstractCpsObject by) {
+		/** let all edges of 'toBeReplaced' connect to 'by' */
+		for(CpsEdge e: toBeReplaced.getConnections()){
+			if(e.getA() == toBeReplaced){
+				e.setA(by);
+			}else if(e.getB() == toBeReplaced){
+				e.setB(by);
+			}
+			
+			/** if edge from an object to itself -> remove it */
+			if(e.getA() == e.getB())
+				removeEdgesOnCanvas(e);
+			else/** else add edge to 'by' */
+				by.addConnection(e);
+		}
+		/** delete 'toBeReplaced' new empty connections, to prevent Nullpointer*/
+		toBeReplaced.setConnections(new ArrayList<CpsEdge>(1));
+		deleteObjectOnCanvas(toBeReplaced);
+	}
+	
 	/**
 	 * Add an edge to the Canvas.
 	 * 

+ 10 - 1
src/ui/controller/CategoryController.java

@@ -9,6 +9,7 @@ import classes.HolonElement;
 import classes.HolonObject;
 import classes.HolonSwitch;
 import classes.HolonTransformer;
+import classes.Pair;
 import interfaces.CategoryListener;
 import ui.model.Model;
 
@@ -120,14 +121,22 @@ public class CategoryController {
 	 */
 	public void addObject(Category category, AbstractCpsObject object) {
 		int i = 0;
+		boolean updateElementSaves = false;
+		String name = "";
 		while (mpC.searchCatObj(category, object.getObjName()) != null) {
+			updateElementSaves = true;
 			if (object.getObjName().contains("_"))
 				object.setObjName(object.getObjName().substring(0, object.getObjName().indexOf('_')));
-			String name = object.getObjName() + "_" + i;
+			name = object.getObjName() + "_" + i;
 			object.setObjName(name);
 			object.setName(name);
 			i++;
 		}
+		if(updateElementSaves && object instanceof HolonObject){
+			for(HolonElement e: ((HolonObject)object).getElements()){
+				e.setSaving(new Pair<String,String>(e.getSaving().getKey(), name));
+			}
+		}
 		category.getObjIdx().put(object.getObjName(), category.getObjects().size());
 		category.getObjects().add(object);
 		notifyCatListeners();

+ 38 - 1
src/ui/controller/Control.java

@@ -2,10 +2,15 @@ package ui.controller;
 
 import api.CpsAlgorithm;
 import classes.*;
+
 import com.google.gson.JsonParseException;
+
 import interfaces.CategoryListener;
+
 import org.apache.commons.compress.archivers.ArchiveException;
+
 import ui.model.Model;
+import ui.view.CreateTemplatePopUp;
 import ui.view.FlexiblePane;
 import ui.view.MyCanvas;
 import ui.view.StatisticGraphPanel;
@@ -17,6 +22,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Hashtable;
 
+import javax.swing.JFrame;
+
 /**
  * The Class represents the controller in the model, controller view Pattern.
  *
@@ -316,6 +323,16 @@ public class Control {
             }
     }
 
+    /**
+     * Replaces {@code toBeReplaced} by {@code by} on the canvas
+     * @param toBeReplaced the object that will be replaced
+     * @param by the object that will replace it
+     */
+    public void replaceCanvasObject(AbstractCpsObject toBeReplaced, AbstractCpsObject by) {
+    	canvasController.replaceObjectOnCanvas(toBeReplaced, by);
+    	
+    }
+    
     /**
      * Add an edge to the Canvas.
      *
@@ -809,6 +826,17 @@ public class Control {
 
     }
 
+    /**
+     * Replaces {@code toBePlaced} by {@code by} in {@code upperNode}
+     * @param toBeReplaced
+     * @param by
+     * @param upperNode
+     */
+	public void replaceObjUpperNode(AbstractCpsObject toBeReplaced,
+			AbstractCpsObject by, CpsUpperNode upperNode) {
+		nodeController.replaceObjectInUpperNode(toBeReplaced, by, upperNode);
+	}
+
     public void addEdgeUpperNode(CpsEdge edge, CpsUpperNode upperNode) {
         nodeController.addEdge(edge, upperNode);
         try {
@@ -916,6 +944,16 @@ public class Control {
             e.printStackTrace();
         }
     }
+    
+    /**
+     * creates a new Template for the given cps Object
+     * @param cps Object, which should become a template
+     * @param parentFrame 
+     */
+    public void createTemplate(HolonObject cps, JFrame parentFrame) {
+        CreateTemplatePopUp t = new CreateTemplatePopUp(cps,model,parentFrame,this);
+        t.setVisible(true);
+    }
 
     public void getObjectsInDepth() {
         clipboardController.getObjectsInDepth();
@@ -996,5 +1034,4 @@ public class Control {
 	public void setFairnessModel(short fairnessModel) {
 		globalController.setFairnessModel(fairnessModel);
 	}
-
 }

+ 8 - 3
src/ui/controller/LoadController.java

@@ -1,14 +1,17 @@
 package ui.controller;
 
 import classes.*;
+
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
+
 import org.apache.commons.compress.archivers.ArchiveEntry;
 import org.apache.commons.compress.archivers.ArchiveException;
 import org.apache.commons.compress.archivers.ArchiveInputStream;
 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
 import org.apache.commons.compress.utils.IOUtils;
+
 import ui.model.Model;
 
 import java.awt.*;
@@ -164,7 +167,7 @@ public class LoadController {
             if (key.contains("CGOBJECT"))
                 loadCategoryObject(json.get(key));
             if (key.contains("CGELEMENT"))
-                loadCategoryElements(json.get(key));
+                loadCategoryElements(json.get(key), eleDispatch);//TODO
             if (key.contains("CVSOBJECT"))
                 loadCanvasObject(json.get(key), objDispatch);
             if (key.contains("CVSELEMENT"))
@@ -242,10 +245,12 @@ public class LoadController {
 
     /**
      * Load a given Element in Category by Deserialization
+     * @param eleDispatch 
      */
-    private void loadCategoryElements(JsonElement jsonElement) {
+    private void loadCategoryElements(JsonElement jsonElement, HashMap<Integer, HolonElement> eleDispatch) {
         HolonElement temp = model.getGson().fromJson(jsonElement.getAsJsonObject().get("properties").getAsJsonObject(),
                 HolonElement.class);
+        eleDispatch.put(temp.getId(), temp);
         initElements(temp);
         objC.addElementIntoCategoryObject(temp.getSaving().getKey(), temp.getSaving().getValue(), temp);
     }
@@ -375,7 +380,7 @@ public class LoadController {
                 break;
             case ELEMENT:
                 HolonElement ele = eleDispatch.get(sav);
-                ele.setGraphPoints(graphpoint);
+                ele.setGraphPoints(graphpoint);//TODO?
                 break;
             default:
                 break;

+ 27 - 1
src/ui/controller/NodeController.java

@@ -468,6 +468,33 @@ class NodeController {
 		upperNode.getNodes().remove(object);
 	}
 
+    /**
+     * Replaces {@code toBePlaced} by {@code by} in {@code upperNode}
+     * @param toBeReplaced
+     * @param by
+     * @param upperNode
+     */
+	public void replaceObjectInUpperNode(AbstractCpsObject toBeReplaced,
+			AbstractCpsObject by, CpsUpperNode upperNode) {
+		/** let all edges of 'toBeReplaced' connect to 'by' */
+		for(CpsEdge e: toBeReplaced.getConnections()){
+			if(e.getA() == toBeReplaced){
+				e.setA(by);
+			}else if(e.getB() == toBeReplaced){
+				e.setB(by);
+			}
+			
+			/** if edge from an object to itself -> remove it */
+			if(e.getA() == e.getB())
+				deleteEdge(e, upperNode);
+			else/** else add edge to 'by' */
+				by.addConnection(e);
+		}
+		/** delete 'toBeReplaced' new empty connections, to prevent Nullpointer*/
+		toBeReplaced.setConnections(new ArrayList<CpsEdge>(1));
+		deleteObjectInUpperNode(toBeReplaced, upperNode);
+	}
+
 	/**
 	 * Add Edge in UpperNode
 	 */
@@ -527,5 +554,4 @@ class NodeController {
 		temp.setPosition(new Position(x, y));
 
 	}
-
 }

+ 9 - 0
src/ui/view/AbstractCanvas.java

@@ -29,6 +29,7 @@ public abstract class AbstractCanvas extends JPanel {
     final JMenuItem itemUngroup = new JMenuItem(Languages.getLanguage()[100]);
     final JMenuItem itemTrack = new JMenuItem(Languages.getLanguage()[101]);
     final JMenuItem itemUntrack = new JMenuItem(Languages.getLanguage()[102]);
+    final JMenuItem itemCreateTemplate = new JMenuItem(Languages.getLanguage()[Languages.right_click_create_template]);
     final int ANIMTIME = 500; // animation Time
     private final int animFPS = 60;
     final int animDelay = 1000 / animFPS; // animation Delay
@@ -324,11 +325,13 @@ public abstract class AbstractCanvas extends JPanel {
                 itemDelete.setEnabled(true);
                 itemCut.setEnabled(true);
                 itemCopy.setEnabled(true);
+                //tracking
                 if (tempCps != null) {
                     itemGroup.setEnabled(true);
                     itemTrack.setEnabled(true);
                     itemUntrack.setEnabled(true);
                 }
+                //ungrouping
                 if (tempCps instanceof CpsUpperNode)
                     itemUngroup.setEnabled(true);
                 else
@@ -336,6 +339,11 @@ public abstract class AbstractCanvas extends JPanel {
                 if (model.getSelectedCpsObjects().size() == 0) {
                     controller.addSelectedObject(tempCps);
                 }
+                if(tempCps instanceof HolonObject){
+                	itemCreateTemplate.setEnabled(true);
+                }else{
+                	itemCreateTemplate.setEnabled(false);                	
+                }
             }else{
                 itemCut.setEnabled(false);
                 itemCopy.setEnabled(false);
@@ -343,6 +351,7 @@ public abstract class AbstractCanvas extends JPanel {
                 itemUngroup.setEnabled(false);
                 itemTrack.setEnabled(false);
                 itemUntrack.setEnabled(false);
+                itemCreateTemplate.setEnabled(false);
         		if(edgeHighlight != null)
         		{
                     itemDelete.setEnabled(true);

+ 75 - 70
src/ui/view/AddElementPopUp.java

@@ -28,29 +28,29 @@ public class AddElementPopUp extends JDialog {
 	private HolonElement hl;
 	private AbstractCpsObject tempCps;
 
-//	/**
-//	 * Launch the application.
-//	 *
-//	 * @param args
-//	 *            standard
-//	 */
-//	public static void main(String[] args) {
-//		try {
-//
-//			AddElementPopUp dialog = new AddElementPopUp();
-//			dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
-//			dialog.setVisible(true);
-//		} catch (Exception e) {
-//			e.printStackTrace();
-//		}
-//	}
+	// /**
+	// * Launch the application.
+	// *
+	// * @param args
+	// * standard
+	// */
+	// public static void main(String[] args) {
+	// try {
+	//
+	// AddElementPopUp dialog = new AddElementPopUp();
+	// dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+	// dialog.setVisible(true);
+	// } catch (Exception e) {
+	// e.printStackTrace();
+	// }
+	// }
 
 	/**
 	 * Create the dialog.
 	 */
 	AddElementPopUp(JFrame parentFrame) {
 		super((java.awt.Frame) null, true);
-		this.setIconImage(Util.loadImage(this,"/Images/Dummy_House.png",30,30));
+		this.setIconImage(Util.loadImage(this, "/Images/Dummy_House.png", 30, 30));
 		setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
 		setBounds(100, 100, 400, 190);
 		setLocationRelativeTo(parentFrame);
@@ -102,57 +102,21 @@ public class AddElementPopUp extends JDialog {
 		contentPanel.add(amount);
 		amount.setColumns(10);
 		amount.setText("1");
-		{
-			JPanel buttonPane = new JPanel();
-			buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
-			getContentPane().add(buttonPane, BorderLayout.SOUTH);
-			{
-				JButton okButton = new JButton("OK");
-                okButton.addActionListener(arg0 -> {
-                    boolean repeated = false;
-                    for (HolonElement e : ((HolonObject) tempCps).getElements()) {
-                        if (elementName.getText().equals(e.getEleName())) {
-                            repeated = true;
-                            break;
-                        }
-                    }
-                    if (elementName.getText().length() != 0 && !repeated) {
-                        try {
-                            float energy = Float.parseFloat(providedEnergy.getText());
-                            int elementAmount = Integer.parseInt(amount.getText());
-                            hl = new HolonElement(elementName.getText(), elementAmount, energy);
-
-                            dispose();
-                        } catch (NumberFormatException e) {
-                            JOptionPane.showMessageDialog(new JFrame(), Languages.getLanguage()[68]);
-                        }
-                    } else {
-                        // JOptionPane.showMessageDialog(new JFrame(),
-                        // "Please enter a Name");
-
-                        if (elementName.getText().length() == 0) {
-                            JLabel errorString = new JLabel(Languages.getLanguage()[69]);
-                            errorString.setBounds(240, 8, 100, 20);
-                            contentPanel.add(errorString);
-                        } else if (repeated) {
-                            JLabel errorString = new JLabel(Languages.getLanguage()[70]);
-                            errorString.setBounds(250, 8, 100, 20);
-                            contentPanel.add(errorString);
-                        }
-                        elementName.setBackground(new Color(255, 50, 50));
-                    }
-                });
-                okButton.setActionCommand("OK");
-				buttonPane.add(okButton);
-				getRootPane().setDefaultButton(okButton);
-			}
-			{
-				JButton cancelButton = new JButton(Languages.getLanguage()[71]);
-				cancelButton.setActionCommand("Cancel");
-				buttonPane.add(cancelButton);
-                cancelButton.addActionListener(e -> dispose());
-            }
-		}
+
+		JPanel buttonPane = new JPanel();
+		buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
+		getContentPane().add(buttonPane, BorderLayout.SOUTH);
+
+		JButton okButton = new JButton("OK");
+		okButton.addActionListener(arg0 -> okAction());
+		okButton.setActionCommand("OK");
+		buttonPane.add(okButton);
+		getRootPane().setDefaultButton(okButton);
+
+		JButton cancelButton = new JButton(Languages.getLanguage()[71]);
+		cancelButton.setActionCommand("Cancel");
+		buttonPane.add(cancelButton);
+		cancelButton.addActionListener(e -> dispose());
 
 	}
 
@@ -162,8 +126,8 @@ public class AddElementPopUp extends JDialog {
 	 * @param cps
 	 *            actual Cps
 	 */
-    void setActualCps(AbstractCpsObject cps) {
-        this.tempCps = cps;
+	void setActualCps(AbstractCpsObject cps) {
+		this.tempCps = cps;
 	}
 
 	/**
@@ -174,4 +138,45 @@ public class AddElementPopUp extends JDialog {
 	public HolonElement getElement() {
 		return hl;
 	}
+
+	public void setElement(HolonElement holonElement) {
+		hl = new HolonElement(hl);
+
+	}
+
+	private void okAction() {
+		boolean repeated = false;
+		for (HolonElement e : ((HolonObject) tempCps).getElements()) {
+			if (elementName.getText().equals(e.getEleName())) {
+				repeated = true;
+				break;
+			}
+		}
+		if (elementName.getText().length() != 0 && !repeated) {
+			try {
+				float energy = Float.parseFloat(providedEnergy.getText());
+				int elementAmount = Integer.parseInt(amount.getText());
+				hl = new HolonElement(elementName.getText(), elementAmount, energy);
+
+				dispose();
+			} catch (NumberFormatException e) {
+				JOptionPane.showMessageDialog(new JFrame(), Languages.getLanguage()[68]);
+			}
+		} else {
+			// JOptionPane.showMessageDialog(new JFrame(),
+			// "Please enter a Name");
+
+			if (elementName.getText().length() == 0) {
+				JLabel errorString = new JLabel(Languages.getLanguage()[69]);
+				errorString.setBounds(240, 8, 100, 20);
+				contentPanel.add(errorString);
+			} else if (repeated) {
+				JLabel errorString = new JLabel(Languages.getLanguage()[70]);
+				errorString.setBounds(250, 8, 100, 20);
+				contentPanel.add(errorString);
+			}
+			elementName.setBackground(new Color(255, 50, 50));
+		}
+
+	}
 }

+ 1 - 1
src/ui/view/AddObjectPopUp.java

@@ -236,7 +236,7 @@ public class AddObjectPopUp extends JDialog {
 								// theObject = new
 								// HolonObject(objectName.getText());
 								// theObject.setElements(hElements);
-								// theObject.setImage(imagePath);
+								// theObject.setImage(imagePath);// TODO Auto-generated catch block
 								try {
 									if (editState) {
 										controller.delObjectCategory(givenCategory, toEdit.getName());

+ 362 - 0
src/ui/view/CreateTemplatePopUp.java

@@ -0,0 +1,362 @@
+package ui.view;
+
+import classes.AbstractCpsObject;
+import classes.Category;
+import classes.HolonElement;
+import classes.HolonObject;
+import classes.Pair;
+import ui.controller.Control;
+import ui.model.Model;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.filechooser.FileNameExtensionFilter;
+
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.*;
+import java.util.ArrayList;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+/**
+ * PopUp for creating Holon Object Template.
+ * 
+ * @author Gruppe 07 (A.T.M-B)
+ */
+public class CreateTemplatePopUp extends JDialog {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Template HolonObject
+	 */
+	private HolonObject template;
+
+	/**
+	 * HolonElementList
+	 */
+	DefaultListModel<String> listModel;
+
+	/**
+	 * HolonElement List
+	 */
+	JList<String> list;
+
+	/**
+	 * Category the Template should be inserted into
+	 */
+	private String category;
+
+	// Template Attributes
+
+	// PopUp Parts
+	private Control controller;
+
+	/**
+	 * Category Selection
+	 */
+	Choice choice;
+
+	/**
+	 * name textfield
+	 */
+	private JTextField textField_name;
+
+	/**
+	 * textField for path
+	 */
+	private JTextField textField_imagePath;
+
+	/**
+	 * Image Preview
+	 */
+	JLabel lblImagePreview;
+
+	/**
+	 * parent Frame
+	 */
+	JFrame parent;
+
+	/**
+	 * Create the dialog.
+	 * 
+	 * @param edit
+	 *            true if edit
+	 * @param obj
+	 *            the object
+	 * @param model
+	 * @param cat
+	 *            the categorie
+	 */
+	public CreateTemplatePopUp(HolonObject obj, Model model,
+			JFrame parentFrame, Control controller) {
+		setResizable(false);
+		/*
+		 * use Category Controller an stuff lul
+		 */
+
+		/*
+		 * initialize Data
+		 */
+		template = new HolonObject(obj);
+		this.parent = parentFrame;
+		this.controller = controller;
+		/*
+		 * create Frame and GUI
+		 */
+		setIconImage(Util.loadImage(this, "/Images/Dummy_House.png", 30, 30));
+		setBounds(100, 100, 476, 344);
+		setLocationRelativeTo(parentFrame);
+		getContentPane().setLayout(new BorderLayout());
+
+		/**
+		 * Content Panel
+		 */
+		JPanel contentPanel = new JPanel();
+		contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
+		getContentPane().add(contentPanel, BorderLayout.CENTER);
+		contentPanel.setLayout(null);
+
+		/**
+		 * Category Label
+		 */
+		JLabel lblCategory = new JLabel("Category:");
+		lblCategory.setBounds(12, 13, 68, 22);
+		contentPanel.add(lblCategory);
+
+		/**
+		 * Category Choice
+		 */
+		choice = new Choice();
+		choice.setBounds(86, 13, 172, 22);
+		contentPanel.add(choice);
+		// add categories
+		if (model.getCategories().size() == 0)// if no categorie exist: create
+												// new Template Category
+			try {
+				this.controller.addCategory("Template");
+			} catch (IOException e1) {
+				e1.printStackTrace();
+			}
+		// add Categories to the choice
+		for (Category c : model.getCategories())
+			choice.add(c.getName());
+
+		/**
+		 * Name Label
+		 */
+		JLabel lblName = new JLabel("Name:");
+		lblName.setBounds(12, 48, 56, 16);
+		contentPanel.add(lblName);
+
+		/**
+		 * Name Textfield
+		 */
+		textField_name = new JTextField();
+		textField_name.setBounds(86, 48, 172, 22);
+		contentPanel.add(textField_name);
+		textField_name.setColumns(10);
+		textField_name.setText(template.getName());
+
+		/**
+		 * Image Path Lable
+		 */
+		JLabel lblImage = new JLabel("Image:");
+		lblImage.setBounds(12, 89, 56, 16);
+		contentPanel.add(lblImage);
+
+		/**
+		 * Image Path Text Field
+		 */
+		textField_imagePath = new JTextField();
+		textField_imagePath.setBounds(86, 86, 172, 22);
+		contentPanel.add(textField_imagePath);
+		textField_imagePath.setColumns(10);
+		textField_imagePath.setText(template.getImage());
+
+		/**
+		 * Browse Image Button
+		 */
+		JButton btnBrowseImage = new JButton("BrowseImage");
+		btnBrowseImage.setBounds(268, 85, 117, 25);
+		contentPanel.add(btnBrowseImage);
+		btnBrowseImage.addActionListener(actionevent -> {
+			fileChooser();
+		});
+
+		/**
+		 * Image Preview
+		 */
+		lblImagePreview = new JLabel("Image Preview");
+		lblImagePreview.setIcon(new ImageIcon(Util.loadImage(this,
+				template.getImage(), 62, 62)));
+		lblImagePreview.setBounds(298, 13, 62, 62);
+		contentPanel.add(lblImagePreview);
+
+		/**
+		 * Holon Element List
+		 */
+		listModel = new DefaultListModel<String>();
+
+		/**
+		 * Add Elements to List
+		 */
+		for (HolonElement he : template.getElements())
+			listModel.addElement(he.getAmount() + " * " + he.getEleName()
+					+ ": " + he.getOverallEnergy() + "U");
+
+		/**
+		 * Add ScrollPane to List
+		 */
+		JScrollPane scrollPane = new JScrollPane();
+		scrollPane.setBounds(22, 118, 236, 150);
+		contentPanel.add(scrollPane);
+		list = new JList<String>(listModel);
+		scrollPane.setViewportView(list);
+
+		/**
+		 * Delete Element Button
+		 */
+		JButton btnDeleteElement = new JButton("Delete Element");
+		btnDeleteElement.setBounds(268, 228, 140, 25);
+		contentPanel.add(btnDeleteElement);
+		btnDeleteElement.addActionListener(e -> removeElement());
+
+		/**
+		 * Edit Element Button
+		 */
+		JButton btnEditElement = new JButton("Edit Element");
+		btnEditElement.setBounds(268, 190, 140, 25);
+		contentPanel.add(btnEditElement);
+		btnEditElement.addActionListener(e -> editElement());
+
+		/**
+		 * Add Element Button
+		 */
+		JButton btnAddElement = new JButton("Add Element");
+		btnAddElement.setBounds(268, 152, 140, 25);
+		contentPanel.add(btnAddElement);
+		btnAddElement.addActionListener(e -> addElement());
+
+		/**
+		 * Cancel Button
+		 */
+		JButton btnCancel = new JButton("Cancel");
+		btnCancel.setBounds(384, 277, 74, 25);
+		contentPanel.add(btnCancel);
+		btnCancel.addActionListener(e -> dispose());
+
+		/**
+		 * Add Template Button
+		 */
+		JButton btnAddTemplate = new JButton("Add Template");
+		btnAddTemplate.setBounds(75, 271, 113, 25);
+		contentPanel.add(btnAddTemplate);
+		btnAddTemplate.addActionListener(e -> createTemplate());
+
+		/**
+		 * Title
+		 */
+		setTitle("Create Template Menu");
+
+	}
+
+	/**
+	 * Choose the file.
+	 */
+	private void fileChooser() {
+		JFileChooser fileChooser = new JFileChooser();
+		FileNameExtensionFilter filter = new FileNameExtensionFilter(
+				"png, jpg or jpeg", "png", "jpg", "jpeg");
+		fileChooser.setFileFilter(filter);
+		int returnValue = fileChooser.showOpenDialog(null);
+		if (returnValue == JFileChooser.APPROVE_OPTION) {
+			File selectedFile = fileChooser.getSelectedFile();
+			String filePath = selectedFile.getAbsolutePath();
+			textField_imagePath.setText(filePath);
+			ImageIcon icon = new ImageIcon(Util.loadImage(this, filePath, 62,
+					62, Image.SCALE_SMOOTH));
+			lblImagePreview.setIcon(icon);
+		} else {
+			System.out.println("Failed to Load");
+		}
+
+	}
+
+	/**
+	 * create the template and add it to the category
+	 */
+	private void createTemplate() {
+		try {
+			template.setName(textField_name.getText());
+			template.setImage(textField_imagePath.getText());
+			template.getElements().forEach(
+					ele -> ele.setSaving(new Pair<String, String>(choice
+							.getSelectedItem(), template.getName())));
+			controller.addObject(controller.searchCategory(choice
+					.getItem(choice.getSelectedIndex())), template.getName(),
+					template.getElements(), template.getImage());
+			this.dispose();
+		} catch (IOException e) {
+			System.out
+					.println("Could not create Template: Category not found!");
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Add an Holon Element to the template
+	 */
+	private void addElement() {
+		AddElementPopUp popUp = new AddElementPopUp(parent);
+		popUp.setActualCps(template);
+		popUp.setVisible(true);
+		HolonElement he = popUp.getElement();
+		if (he != null) {
+			listModel.addElement(he.getAmount() + " * " + he.getEleName()
+					+ ": " + he.getOverallEnergy() + "U");
+			template.addElement(he);
+			he.setSaving(new Pair<>(category, textField_name.getText()));
+		}
+	}
+
+	/**
+	 * Removes the Selected Element from the template
+	 */
+	private void removeElement() {
+		int index = list.getSelectedIndex();
+		if (index == -1)
+			return;
+		template.deleteElement(index);
+		listModel.remove(index);
+	}
+
+	/**
+	 * Edits the selected HolonElement
+	 */
+	private void editElement() {
+		int index = list.getSelectedIndex();
+		if (index == -1)
+			return;
+		
+		AddElementPopUp popUp = new AddElementPopUp(parent);
+		popUp.setActualCps(template);
+		popUp.setElement(template.getElements().get(index));
+		popUp.setVisible(true);
+		HolonElement he = popUp.getElement();
+		if (he != null) {
+			listModel.addElement(he.getAmount() + " * " + he.getEleName()
+					+ ": " + he.getOverallEnergy() + "U");
+			template.addElement(he);
+			he.setSaving(new Pair<>(category, textField_name.getText()));
+		}
+		
+		System.out.println("Edit "
+				+ template.getElements().get(index).toString());
+	}
+
+}

+ 5 - 4
src/ui/view/Languages.java

@@ -24,13 +24,14 @@ public class Languages {
 	// Exit Pop Up (88)
 	// Simulation ToolTip (89-93)
 	// Image Size Slider (94)
-	// Menu - right click on HolonObjt (95-103)
+	// Menu - right click on HolonObjt (95-104)
+	public static final int right_click_create_template = 104;
 	// to add more: increase languageSize and add them to the arrayEN
 
 	/**
 	 * Number of different Language Array Positions
 	 */
-	private static int languageSize = 104;
+	private static int languageSize = 105;
 
 	static String[] arrayEN = {
 			// ToolBar (0-16)
@@ -71,8 +72,8 @@ public class Languages {
 			"Play", "Reset", "Forward", "Backward", "Time Slider",
 			// Image Size Slider (94)
 			"Image Size",
-			// Menu - right click on HolonObjt (95-103)
-			"Cut", "Copy", "Paste", "Delete", "Group", "Ungroup", "Track", "Untrack"};
+			// Menu - right click on HolonObjt (95-104)
+			"Cut", "Copy", "Paste", "Delete", "Group", "Ungroup", "Track", "Untrack","Category","Create Template"};
 
 	static String[] arrayES = readLanguageFile("Texts/ES.lang"); 
 

+ 48 - 0
src/ui/view/MyCanvas.java

@@ -60,6 +60,7 @@ public class MyCanvas extends AbstractCanvas implements MouseListener,
 		popmenu.add(itemUngroup);
 		popmenu.add(itemTrack);
 		popmenu.add(itemUntrack);
+		popmenu.add(itemCreateTemplate);
 
 		updCon = new UpdateController(mod, control);
 
@@ -353,6 +354,13 @@ public class MyCanvas extends AbstractCanvas implements MouseListener,
 					}
 					repaint();
 				});
+		
+		/*
+		 * create Template
+		 */
+		itemCreateTemplate.addActionListener(actionEvent -> {
+			controller.createTemplate((HolonObject)tempCps,(JFrame)SwingUtilities.getRoot(this));
+		});
 
 		this.addMouseListener(this);
 		this.addMouseMotionListener(this);
@@ -590,6 +598,46 @@ public class MyCanvas extends AbstractCanvas implements MouseListener,
 
 		if (dragged) {
 			try {
+				/** x of the dragged Object */
+				int x = tempCps.getPosition().x;
+				
+				/** y of the dragged Object */
+				int y = tempCps.getPosition().y;
+				
+				/** distance treshold for replacement */
+				int treshhold = controller.getScale()/4;
+				
+				//System.out.println("Dragged "+tempCps.toString()+" to x: "+tempCps.getPosition().x+" y: "+tempCps.getPosition().y);
+				
+				/** number of Objects that might be replaced (should be 1) */
+				int replaceCounter = 0;
+				
+				/** last object that could be replaced */
+				AbstractCpsObject toBeReplaced = null;
+				
+				/** for each cps on Canvas */
+				for (AbstractCpsObject cps : model.getObjectsOnCanvas()){
+					
+					/** same object -> ignore */
+					if(cps == tempCps)continue;
+					
+					/** x of object that might get replaced */
+					int c_x = cps.getPosition().x;
+					
+					/** y of object that might get replaced */
+					int c_y = cps.getPosition().y;
+					
+					/** if near enough */
+					if(Math.abs(x-c_x)<treshhold && Math.abs(y-c_y)<treshhold){
+						replaceCounter++;
+						toBeReplaced = cps;
+					}
+				}
+				/** if replacement of exactly one object possible */
+				if(replaceCounter == 1 && toBeReplaced != null){
+					controller.replaceCanvasObject(toBeReplaced, tempCps);
+				}
+				
 				controller.autoSave();
 			} catch (IOException ex) {
 				System.err.println("AutoSave error by dragging");

+ 49 - 2
src/ui/view/UpperNodeCanvas.java

@@ -1,12 +1,15 @@
 package ui.view;
 
 import classes.*;
+
 import com.google.gson.JsonParseException;
+
 import ui.controller.Control;
 import ui.controller.UpdateController;
 import ui.model.Model;
 
 import javax.swing.*;
+
 import java.awt.*;
 import java.awt.datatransfer.UnsupportedFlavorException;
 import java.awt.event.MouseEvent;
@@ -74,6 +77,7 @@ public class UpperNodeCanvas extends AbstractCanvas implements MouseListener, Mo
         popmenu.add(itemUngroup);
         popmenu.add(itemTrack);
         popmenu.add(itemUntrack);
+        popmenu.add(itemCreateTemplate);
 
         itemDelete.setEnabled(false);
         itemCut.setEnabled(false);
@@ -313,6 +317,13 @@ public class UpperNodeCanvas extends AbstractCanvas implements MouseListener, Mo
             }
             repaint();
         });
+        
+        /*
+		 * create Template
+		 */
+		itemCreateTemplate.addActionListener(actionEvent -> {
+			controller.createTemplate((HolonObject)tempCps, (JFrame)SwingUtilities.getRoot(this));
+		});
 
         this.addMouseListener(this);
         this.addMouseMotionListener(this);
@@ -492,7 +503,6 @@ public class UpperNodeCanvas extends AbstractCanvas implements MouseListener, Mo
                 if (checkPath.exists()) {
                     img = new ImageIcon(cps.getImage()).getImage();
                 } else {
-                    //img = new ImageIcon(this.getClass().getResource(cps.getImage())).getImage();//TODO: and I'm done
                 	img = Util.loadImage(this,cps.getImage());
                 }
             }
@@ -709,7 +719,44 @@ public class UpperNodeCanvas extends AbstractCanvas implements MouseListener, Mo
         }
 
         if (dragged) {
-            try {
+            try { 
+            	/** x of the dragged Object */
+				int x = tempCps.getPosition().x;
+				
+				/** y of the dragged Object */
+				int y = tempCps.getPosition().y;
+				
+				/** distance treshold for replacement */
+				int treshhold = controller.getScale()/4;
+				
+				/** number of Objects that might be replaced (should be 1) */
+				int replaceCounter = 0;
+				
+				/** last object that could be replaced */
+				AbstractCpsObject toBeReplaced = null;
+				
+				/** for each cps on Canvas */
+				for (AbstractCpsObject cps : upperNode.getNodes()){
+					
+					/** same object -> ignore */
+					if(cps == tempCps)continue;
+					
+					/** x of object that might get replaced */
+					int c_x = cps.getPosition().x;
+					
+					/** y of object that might get replaced */
+					int c_y = cps.getPosition().y;
+					
+					/** if near enough */
+					if(Math.abs(x-c_x)<treshhold && Math.abs(y-c_y)<treshhold){
+						replaceCounter++;
+						toBeReplaced = cps;
+					}
+				}
+				/** if replacement of exactly one object possible */
+				if(replaceCounter == 1 && toBeReplaced != null){
+					controller.replaceObjUpperNode(toBeReplaced, tempCps, upperNode);
+				}
                 controller.autoSave();
             } catch (IOException ex) {
                 ex.printStackTrace();

+ 47 - 19
src/ui/view/Util.java

@@ -7,6 +7,7 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.HashMap;
 
 import javax.imageio.ImageIO;
 
@@ -14,34 +15,51 @@ public class Util {
 	
 	/**
 	 * 30x30 pixel FileNotFound Icon, which can be shown without using I/O operations
+	 * a red cross.
 	 */
-	static private Image defaultImage = createDefaultImage();
-	
-	/**
-	 * creates the default Image 
-	 * @return 30x30 Image, showing a red cross
+	static private BufferedImage defaultImage;
+	/*
+	 * Save nothing: Reload every image whenever requested.
+	 * Save external: Only save images that were found as external file.
+	 * Save raw: Save all non-scaled images.
+	 * Save everything: self-explanatory.
 	 */
-	private static Image createDefaultImage() {
-		BufferedImage def = new BufferedImage(30,30,BufferedImage.TYPE_BYTE_INDEXED);
+	private static final byte SAVE_NOTHING=0, /*SAVE_EXTERNAL=1,*/ SAVE_RAW=2, SAVE_EVERYTHING=4,
+								SAVE_MODE=SAVE_EVERYTHING;
+	private static HashMap<String, Image> imgStorage;
+	
+	static{
+		/*
+		 * creates the default Image 
+		 */
+		defaultImage = new BufferedImage(30,30,BufferedImage.TYPE_BYTE_INDEXED);
 		for(int x = 0; x < 30; x++)
 			for(int y = 0; y < 30; y++){
 				if(x == 29 || y == 29)
 					//Border Bottom/Left -> Light Grey
-					def.setRGB(x, y, 13158600);
+					(defaultImage).setRGB(x, y, 13158600);
 				else if(x == 0 || y == 0)
 					//Border Top/Right -> Dark Grey
-					def.setRGB(x, y, 6316128);
+					(defaultImage).setRGB(x, y, 6316128);
 				else if((x == y || x == 31 - y) && 6 < x && x < 25)
 					//Red Cross in the middle
-					def.setRGB(x, y, 13107200);
+					(defaultImage).setRGB(x, y, 13107200);
 				else //all other Pixels are white
-					def.setRGB(x, y, 16777215);
-				
+					(defaultImage).setRGB(x, y, 16777215);
 			}
-		return def;
+		if(SAVE_MODE!=SAVE_NOTHING)imgStorage=new HashMap<String, Image>();
 	}
 	
 	static Image loadImage(Object origin, String url, int w, int h, int scale){
+		if(SAVE_MODE==SAVE_EVERYTHING){
+			String key=url+"?"+w+"?"+h+"?"+scale;
+			if(imgStorage.containsKey(key))return(imgStorage.get(key));
+			else{
+				Image img=loadImage(origin,url).getScaledInstance(w, h, scale);
+				imgStorage.put(key, img);
+				return img;
+			}
+		}
 		return loadImage(origin,url).getScaledInstance(w, h, scale);
 	}
 	
@@ -50,10 +68,23 @@ public class Util {
 	}
 	
 	static Image loadImage(Object origin, String url){
+		if(SAVE_MODE!=SAVE_NOTHING){
+			if(imgStorage.containsKey(url))return imgStorage.get(url);
+			else{
+				Image img;
+				try {
+					img= ImageIO.read(loadStream(origin, url));
+				} catch (IOException e) {
+					e.printStackTrace();
+					return defaultImage;
+				}
+				imgStorage.put(url, img);
+				return img;
+			}
+		}
 		try {
 			return ImageIO.read(loadStream(origin, url));
 		} catch (IOException e) {
-			//System.err.println("Warning: '" + url + "' loading failed!");
 			e.printStackTrace();
 			return defaultImage;
 		}
@@ -63,17 +94,14 @@ public class Util {
 		InputStream o=origin.getClass().getResourceAsStream(url);
 		if(o!=null)return o;
 		else{
-			//System.out.println("Loading of \""+url+"\" as local resource failed.\nWill attempt to load as File.");
 			boolean rootSymbol=false;	//Whether url starts with a / or \
 			switch(url.charAt(0)){		//So we can make sure to construct res/path correctly.
 			case '/':case '\\':rootSymbol=true;
 			}
 			try {
-				//I am checking, whether the requested File is an internal resource.
-				//If it is, res/url has to be used, otherwise url.
 				//Mixed separators might cause problems. Will fix later.
-				File f=new File(url);
-				if(!f.exists()/*||!f.getAbsolutePath().equals(url)*/)url="res"+(rootSymbol?"":"/")+url;
+				File f=new File(url);//Possible bug with duplicate names.
+				if(!f.exists())url="res"+(rootSymbol?"":"/")+url;
 				return new FileInputStream(url);
 			} catch (FileNotFoundException e1) {
 				e1.printStackTrace();