Просмотр исходного кода

WIP No Load|Save

Adds Canvas Selection
TomTroppmann 2 лет назад
Родитель
Сommit
596c4638e4
36 измененных файлов с 992 добавлено и 1014 удалено
  1. 0 35
      src/holeg/adapter/PairAdapter.java
  2. 0 36
      src/holeg/adapter/PositionAdapter.java
  3. 1 1
      src/holeg/addon/Randomizer.java
  4. 1 1
      src/holeg/addon/helper/EmailNotification.java
  5. 1 3
      src/holeg/api/AlgorithmFrameworkFlex.java
  6. 123 161
      src/holeg/model/AbstractCanvasObject.java
  7. 6 1
      src/holeg/model/GroupNode.java
  8. 0 23
      src/holeg/model/HolonElement.java
  9. 205 195
      src/holeg/model/HolonSwitch.java
  10. 0 1
      src/holeg/model/Node.java
  11. 8 4
      src/holeg/preferences/ColorPreference.java
  12. 0 2
      src/holeg/ui/controller/CanvasController.java
  13. 0 7
      src/holeg/ui/controller/CategoryController.java
  14. 7 23
      src/holeg/ui/controller/ClipboardController.java
  15. 12 10
      src/holeg/ui/controller/Control.java
  16. 5 28
      src/holeg/ui/controller/LoadController.java
  17. 0 5
      src/holeg/ui/controller/NodeController.java
  18. 2 6
      src/holeg/ui/model/GuiSettings.java
  19. 204 341
      src/holeg/ui/view/canvas/Canvas.java
  20. 289 0
      src/holeg/ui/view/canvas/Rendering.java
  21. 1 1
      src/holeg/ui/view/component/Console.java
  22. 1 1
      src/holeg/ui/view/dialog/AboutUsPopUp.java
  23. 1 1
      src/holeg/ui/view/dialog/AddElementPopUp.java
  24. 1 4
      src/holeg/ui/view/dialog/AddObjectPopUp.java
  25. 1 1
      src/holeg/ui/view/dialog/CanvasResizePopUp.java
  26. 1 6
      src/holeg/ui/view/dialog/CreateTemplatePopUp.java
  27. 1 1
      src/holeg/ui/view/image/Import.java
  28. 1 1
      src/holeg/ui/view/inspector/Inspector.java
  29. 1 1
      src/holeg/ui/view/inspector/InspectorTable.java
  30. 1 23
      src/holeg/ui/view/main/GUI.java
  31. 1 1
      src/holeg/ui/view/main/TimePanel.java
  32. 1 1
      src/holeg/ui/view/window/AddOnWindow.java
  33. 1 1
      src/holeg/ui/view/window/FlexWindow.java
  34. 1 3
      src/holeg/ui/view/window/Outliner.java
  35. 14 0
      src/holeg/utility/math/vector/Geometry.java
  36. 100 85
      src/holeg/utility/math/vector/Vec2i.java

+ 0 - 35
src/holeg/adapter/PairAdapter.java

@@ -1,35 +0,0 @@
-package holeg.adapter;
-
-import java.lang.reflect.Type;
-import java.util.AbstractMap.SimpleEntry;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-
-
-public class PairAdapter implements JsonSerializer<SimpleEntry<String, String>>, JsonDeserializer<SimpleEntry<String, String>>{
-
-	@Override
-	public SimpleEntry<String, String> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-			throws JsonParseException {
-		JsonObject object = json.getAsJsonObject();	
-		return new SimpleEntry<String, String>(object.get("KEY").getAsString(), object.get("VALUE").getAsString());
-	}
-
-	@Override
-	public JsonElement serialize(SimpleEntry<String, String> src, Type typeOfSrc, JsonSerializationContext context) {		
-		JsonObject object = new JsonObject();
-		object.add("KEY", new JsonPrimitive(src.getKey()));
-		object.add("VALUE", new JsonPrimitive(src.getValue()));
-		return object;
-
-	}
-
-}

+ 0 - 36
src/holeg/adapter/PositionAdapter.java

@@ -1,36 +0,0 @@
-package holeg.adapter;
-
-import java.lang.reflect.Type;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import holeg.utility.math.vector.Vec2i;
-
-public class PositionAdapter implements JsonSerializer<Vec2i>, JsonDeserializer<Vec2i> {
-
-	@Override
-	public JsonElement serialize(Vec2i arg0, Type arg1, JsonSerializationContext arg2) {
-		return new JsonPrimitive(arg0.getX() + ":" + arg0.getY());
-	}
-
-	@Override
-	public Vec2i deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2) {
-		try {
-			String arg = arg0.getAsString();
-			int mid = arg.indexOf(':');
-			int x = Integer.parseInt(arg.substring(0, mid));
-			int y = Integer.parseInt(arg.substring(mid + 1, arg.length()));
-			return new Vec2i(x, y);
-
-		} catch (NumberFormatException e) {
-			System.err.println(e);
-		}
-		return new Vec2i(-1, -1);
-	}
-
-}

+ 1 - 1
src/holeg/addon/Randomizer.java

@@ -43,7 +43,7 @@ import holeg.api.AddOn;
 import holeg.model.HolonElement;
 import holeg.model.HolonObject;
 import holeg.ui.controller.Control;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.math.Random;
 
 public class Randomizer implements AddOn {

+ 1 - 1
src/holeg/addon/helper/EmailNotification.java

@@ -17,7 +17,7 @@ import javax.swing.JTextField;
 import org.apache.commons.mail.*;
 
 import holeg.preferences.ImagePreference;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 
 
 public class EmailNotification {

+ 1 - 3
src/holeg/api/AlgorithmFrameworkFlex.java

@@ -14,7 +14,6 @@ import java.math.RoundingMode;
 import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.DoubleSummaryStatistics;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -54,13 +53,12 @@ import holeg.model.HolonSwitch;
 import holeg.preferences.ImagePreference;
 import holeg.model.Flexibility.FlexState;
 import holeg.model.GroupNode;
-import holeg.model.HolonElement.Priority;
 import holeg.model.HolonSwitch.SwitchMode;
 import holeg.model.HolonSwitch.SwitchState;
 import holeg.ui.controller.Control;
 import holeg.ui.model.Model;
 import holeg.ui.view.component.Console;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.math.decimal.Format;
 
 public abstract class AlgorithmFrameworkFlex implements AddOn{

+ 123 - 161
src/holeg/model/AbstractCanvasObject.java

@@ -1,176 +1,138 @@
 package holeg.model;
 
-import java.util.Optional;
-
 import com.google.gson.annotations.Expose;
-
 import holeg.ui.model.IdCounter;
 import holeg.ui.model.IdCounter.CounterType;
 import holeg.utility.math.vector.Vec2i;
 
+import java.util.Optional;
+
 /**
  * The abstract class "CpsObject" represents any possible object in the system
  * (except Edges). The representation of any object contains following
  * variables: see description of variables
- * 
- * @author Gruppe14
  *
+ * @author Gruppe14
  */
 public abstract class AbstractCanvasObject {
-	/* Type of the Object. */
-	@Expose
-	String objName;
-	/* Name given by the user. */
-	@Expose
-	String name;
-	/* ID of the Obj. */
-	@Expose
-	private int id;
-	/* Path of the image for the Obj. */
-	@Expose
-	String image;
-	/* Position with a X and Y value */
-	@Expose
-	Vec2i position = new Vec2i(0,0);
-	//TODO(Tom2022-01-11): Saving should be removed
-	@Expose
-	String sav;
-	
-	
-	private Optional<GroupNode> groupNode = Optional.empty();
-
-	/**
-	 * Constructor for a CpsObejct with an unique ID.
-	 * 
-	 * @param objName
-	 *            of the Object
-	 */
-	public AbstractCanvasObject(String objName) {
-		setName(objName);
-		this.id = IdCounter.nextId(CounterType.Object);
-	}
-
-	public void setGroupNode(GroupNode groupNode) {
-		this.groupNode = Optional.of(groupNode);
-	}
-	
-	public Optional<GroupNode> getGroupNode() {
-		return groupNode;
-	}
-
-	
-	/**
-	 * Constructor for a new CpsObject with an unique ID (This constructor
-	 * correspond to the interaction between the Categories and Canvas)-->
-	 * actually the "new" Object is a copy.
-	 * 
-	 * @param obj
-	 *            Object to be copied
-	 */
-	public AbstractCanvasObject(AbstractCanvasObject obj) {
-		setName(obj.getName());
-		setImage(obj.getImage());
-		this.id = IdCounter.nextId(CounterType.Object);
-
-	}
-	
-	public abstract void initForReflection();
-	
-	
-	
-
-	/**
-	 * Getter for the user-defined name (no unique).
-	 * 
-	 * @return String
-	 */
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * Set the name.
-	 * 
-	 * @param name
-	 *            String
-	 */
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	/**
-	 * Get the path of the image for the selected Object.
-	 * 
-	 * @return String
-	 */
-	public String getImage() {
-		return image;
-	}
-
-	/**
-	 * Set the path of the image.
-	 * 
-	 * @param image
-	 *            the Image to set
-	 */
-	public void setImage(String image) {
-		this.image = image;
-	}
-
-	public int getId() {
-		return id;
-	}
-	
-	
-	/**
-	 * Set the position of the Object in the canvas.
-	 *
-	 * @param x
-	 *            X-Coord
-	 * @param y
-	 *            Y-Coord
-	 */
-	public void setPosition(int x, int y) {
-		setPosition(new Vec2i(x, y));
-	}
-
-	/**
-	 * Get the actual position of the Object.
-	 *
-	 * @return Position Position of this Object
-	 */
-	public Vec2i getPosition() {
-		return position;
-	}
-
-	/**
-	 * Set the position of the Object in the canvas.
-	 *
-	 * @param pos Coordinates
-	 */
-	public void setPosition(Vec2i pos) {
-		this.position = pos;
-	}
-
-	/**
-	 * For save purpose.
-	 * 
-	 * @return the stored
-	 */
-	public String getSav() {
-		return sav;
-	}
-
-	/**
-	 * For save purpose.
-	 * 
-	 * @param sav
-	 *            the stored to set
-	 */
-	//TODO(Tom2021-12-1): Remove SAV
-	public void setSav(String sav) {
-		this.sav = sav;
-	}
-
-
+    /* Type of the Object. */
+    @Expose
+    String objName;
+    /* Name given by the user. */
+    @Expose
+    String name;
+    /* Path of the image for the Obj. */
+    @Expose
+    String image;
+    /* Position with a X and Y value */
+    @Expose
+    Vec2i position = new Vec2i(0, 0);
+    /* ID of the Obj. */
+    @Expose
+    private final int id;
+    private Optional<GroupNode> groupNode = Optional.empty();
+
+    /**
+     * Constructor for a CpsObejct with an unique ID.
+     *
+     * @param objName of the Object
+     */
+    public AbstractCanvasObject(String objName) {
+        setName(objName);
+        this.id = IdCounter.nextId(CounterType.Object);
+    }
+
+    /**
+     * Constructor for a new CpsObject with an unique ID (This constructor
+     * correspond to the interaction between the Categories and Canvas)-->
+     * actually the "new" Object is a copy.
+     *
+     * @param obj Object to be copied
+     */
+    public AbstractCanvasObject(AbstractCanvasObject obj) {
+        setName(obj.getName());
+        setImage(obj.getImage());
+        this.id = IdCounter.nextId(CounterType.Object);
+
+    }
+
+    public Optional<GroupNode> getGroupNode() {
+        return groupNode;
+    }
+
+    public void setGroupNode(GroupNode groupNode) {
+        this.groupNode = Optional.of(groupNode);
+    }
+
+    public abstract void initForReflection();
+
+
+    /**
+     * Getter for the user-defined name (no unique).
+     *
+     * @return String
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Set the name.
+     *
+     * @param name String
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Get the path of the image for the selected Object.
+     *
+     * @return String
+     */
+    public String getImage() {
+        return image;
+    }
+
+    /**
+     * Set the path of the image.
+     *
+     * @param image the Image to set
+     */
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+
+    /**
+     * Set the position of the Object in the canvas.
+     *
+     * @param x X-Coord
+     * @param y Y-Coord
+     */
+    public void setPosition(int x, int y) {
+        setPosition(new Vec2i(x, y));
+    }
+
+    /**
+     * Get the actual position of the Object.
+     *
+     * @return Position Position of this Object
+     */
+    public Vec2i getPosition() {
+        return position;
+    }
+
+    /**
+     * Set the position of the Object in the canvas.
+     *
+     * @param pos Coordinates
+     */
+    public void setPosition(Vec2i pos) {
+        this.position = pos;
+    }
 }

+ 6 - 1
src/holeg/model/GroupNode.java

@@ -5,6 +5,8 @@ import java.util.Collection;
 import java.util.logging.Logger;
 import java.util.stream.Stream;
 
+import holeg.preferences.ImagePreference;
+
 public class GroupNode extends AbstractCanvasObject {
 	private static final Logger log = Logger.getLogger(AbstractCanvasObject.class.getName());
 
@@ -15,7 +17,6 @@ public class GroupNode extends AbstractCanvasObject {
 
 	public GroupNode(String nodeName) {
 		super(nodeName);
-		this.setSav("CVS");
 	}
 
 	@Override
@@ -27,6 +28,10 @@ public class GroupNode extends AbstractCanvasObject {
 		groupNodeList = new ArrayList<>();
 	}
 
+	@Override
+	public String getImage() {
+		return ImagePreference.Canvas.GroupNode;
+	}
 	public void addAll(Stream<AbstractCanvasObject> stream) {
 		stream.forEach(obj -> add(obj));
 	}

+ 0 - 23
src/holeg/model/HolonElement.java

@@ -13,7 +13,6 @@ import holeg.utility.math.vector.Vec2f;
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.ListIterator;
-import java.util.AbstractMap.SimpleEntry;
 import java.util.logging.Logger;
 /**
  * The class "HolonElement" represents any possible element that can be added to
@@ -58,10 +57,6 @@ public class HolonElement implements TimelineDependent{
     public Priority priority = Priority.Low;
 
 
-    
-    /** Place where the Object is Stored */
-    @Expose
-    private SimpleEntry<String, String> saving;
     /** ID */
     @Expose
     private int id;
@@ -86,9 +81,7 @@ public class HolonElement implements TimelineDependent{
      * element, energyPerElement and corresponding model.
      *
      * @param eleName String
-     * @param amount  int
      * @param energy  float
-     * @param model Model
      */
     //TODO(Tom2021-12-20): constructor should be remade
     public HolonElement(HolonObject parentObject, String eleName, float energy) {
@@ -131,7 +124,6 @@ public class HolonElement implements TimelineDependent{
             this.graphPoints.add(new Vec2f(p));
         }
         sampleGraph();
-        setSaving(null);
         this.id = IdCounter.nextId(CounterType.Element);
     }
 
@@ -209,23 +201,8 @@ public class HolonElement implements TimelineDependent{
     
     public void setPriority(Priority priority) {
     	this.priority = priority;
-    }    
-
-    /**
-     * @return the saving
-     */
-    public SimpleEntry<String, String> getSaving() {
-        return saving;
     }
 
-    /**
-     * @param saving the saving to set
-     */
-    public void setSaving(SimpleEntry<String, String> saving) {
-        this.saving = saving;
-    }
-
-
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("[HolonElement: ");

+ 205 - 195
src/holeg/model/HolonSwitch.java

@@ -1,69 +1,43 @@
 package holeg.model;
 
-import java.util.LinkedList;
-import java.util.ListIterator;
-
 import com.google.gson.annotations.Expose;
-
 import holeg.interfaces.LocalMode;
 import holeg.interfaces.TimelineDependent;
+import holeg.preferences.ImagePreference;
 import holeg.ui.controller.IndexTranslator;
 import holeg.utility.math.vector.Vec2f;
 
+import java.util.LinkedList;
+import java.util.ListIterator;
+
 /**
  * The class HolonSwitch represents an Object in the system, that has the
  * capacity of manipulate the electricity flow. The switch can be manage
  * automatically through a graph or direct manually.
- * 
- * @author Gruppe14
  *
+ * @author Gruppe14
  */
 public class HolonSwitch extends AbstractCanvasObject implements TimelineDependent {
 
-	
-	public enum SwitchState {
-		Open, Closed;
-		public static SwitchState opposite(SwitchState state) {
-			switch(state) {
-			case Closed:
-				return Open;
-			case Open:
-			default:
-				return Closed;
-			}
-		}
-		public boolean isOpen() {
-			return this == Open;
-		}
-		public boolean isClosed() {
-			return this == Closed;
-		}
-	}
 
-	public enum SwitchMode {
-		Manual, Auto
-	}
-
-	@Expose
-	private SwitchMode mode = SwitchMode.Auto;
-	@Expose
-	private SwitchState manualState = SwitchState.Closed;
-	@Expose
-	private int localPeriod;
-	@Expose
-	boolean localPeriodActive = false;
-
-	
-	
-	
-	
-	/**
-	 * Energy at each point of the graph with 50 predefined points. At the
-	 * beginning, it starts with all values at energy
-	 */
-	boolean[] activeAt = new boolean[LocalMode.STANDARD_GRAPH_ACCURACY];
-	/** Points on the UnitGraph */
-	LinkedList<Vec2f> graphPoints = new LinkedList<>();
+    @Expose
+    boolean localPeriodActive = false;
+    /**
+     * Energy at each point of the graph with 50 predefined points. At the
+     * beginning, it starts with all values at energy
+     */
+    boolean[] activeAt = new boolean[LocalMode.STANDARD_GRAPH_ACCURACY];
+    /**
+     * Points on the UnitGraph
+     */
+    LinkedList<Vec2f> graphPoints = new LinkedList<>();
+    @Expose
+    private SwitchMode mode = SwitchMode.Auto;
+    @Expose
+    private SwitchState manualState = SwitchState.Closed;
+    @Expose
+    private int localPeriod;
+    private SwitchState state = SwitchState.Closed;
 
 	/**
 	 * Create a new HolonSwitch with a custom name, a default value of automatic
@@ -84,6 +58,10 @@ public class HolonSwitch extends AbstractCanvasObject implements TimelineDepende
 	 */
 	public HolonSwitch(HolonSwitch other) {
 		super(other);
+		mode = other.mode;
+		manualState = other.manualState;
+		state = other.state;
+
 		setLocalPeriod(other.getLocalPeriod());
 		setUseLocalPeriod(other.isUsingLocalPeriod());
 		activeAt = new boolean[LocalMode.STANDARD_GRAPH_ACCURACY];
@@ -94,150 +72,182 @@ public class HolonSwitch extends AbstractCanvasObject implements TimelineDepende
 		sampleGraph();
 	}
 
-	@Override
-	public void initForReflection() {
-		this.graphPoints = new LinkedList<>();
-		this.reset();
-	}
-
-	/**
-	 * Calculates the state of the Switch.
-	 */
-	public void flipManualState() {
-		manualState = SwitchState.opposite(manualState);
-	}
-	
-	/*
-	 * STATE
-	 */
-	
-	private SwitchState state;
-	public void calculateState(int timestep) {
-		switch (mode) {
-		case Auto:
-			state = activeAt[IndexTranslator.getEffectiveIndex(this, timestep)] ? SwitchState.Open : SwitchState.Closed;
-		case Manual:
-		default:
-			state =  manualState;
-		}
-	}
-	public SwitchState getState() {
-		return state;
-	}
-	
-	/**
-	 * For automatic use only (through the graph).
-	 * 
-	 * @return the Graph Points
-	 */
-	public LinkedList<Vec2f> getGraphPoints() {
-		return graphPoints;
-	}
-
-	/**
-	 * Set the values of the switch in the graph (auto. mode only).
-	 * 
-	 * @param linkedList the Graph points
-	 */
-	public void setGraphPoints(LinkedList<Vec2f> linkedList) {
-		this.graphPoints = linkedList;
-	}
-
-	/**
-	 * Initialize the Graph as a closed Switch.
-	 */
-	private void initGraphPoints() {
-		graphPoints.clear();
-		graphPoints.add(new Vec2f(0, 1));
-		graphPoints.add(new Vec2f(1, 1));
-	}
-
-	public SwitchMode getMode() {
-		return mode;
-	}
-
-	public void setMode(SwitchMode mode) {
-		this.mode = mode;
-	}
-
-	public SwitchState getManualState() {
-		return manualState;
-	}
-
-	public void setManualState(SwitchState manuelState) {
-		this.manualState = manuelState;
-	}
-
-	// interfaces.GraphEditable
-	@Override
-	public GraphType getGraphType() {
-		return GraphType.boolGraph;
-	}
-
-	@Override
-	public LinkedList<Vec2f> getStateGraph() {
-		return graphPoints;
-	}
-
-	@Override
-	public void reset() {
-		initGraphPoints();
-		sampleGraph();
-	}
-
-	@Override
-	public void sampleGraph() {
-		activeAt = sampleGraph(100);
-	}
-
-	/**
-	 * Generate out of the Graph Points a array of boolean that represent the
-	 * Curve("on or off"-Graph) at each sample position. The Values are in the Range
-	 * [0,1].
-	 * 
-	 * @param sampleLength amount of samplePositions. The positions are equidistant
-	 *                     on the Range[0,1].
-	 * @return the boolean array of samplepoints.
-	 */
-	private boolean[] sampleGraph(int sampleLength) {
-		ListIterator<Vec2f> iter = this.graphPoints.listIterator();
-		Vec2f before = iter.next();
-		Vec2f after = iter.next();
-		boolean[] activeTriggerPos = new boolean[sampleLength];
-		for (int i = 0; i < sampleLength; i++) {
-			double graphX = (double) i / (double) (sampleLength - 1); // from 0.0 to 1.0
-			if (graphX > after.x) {
-				before = after;
-				after = iter.next();
-			}
-			activeTriggerPos[i] = (before.getY() >= 0.5);
-		}
-		return activeTriggerPos;
-	}
-
-	// interfaces.LocalMode
-	@Override
-	public void setLocalPeriod(int period) {
-		localPeriod = period;
-	}
-
-	@Override
-	public int getLocalPeriod() {
-		return localPeriod;
-	}
-
-	@Override
-	public boolean isUsingLocalPeriod() {
-		return localPeriodActive;
-	}
-
-	@Override
-	public void setUseLocalPeriod(boolean state) {
-		this.localPeriodActive = state;
-	}
-
-	public String toString() {
-		return name + "[ID:" + getId() + "]";
-
-	}
+    @Override
+    public String getImage() {
+		return switch (state) {
+			case Open -> ImagePreference.Canvas.Switch.Open;
+			case Closed -> ImagePreference.Canvas.Switch.Closed;
+		};
+    }
+
+    @Override
+    public void initForReflection() {
+        this.graphPoints = new LinkedList<>();
+        this.state = SwitchState.Closed;
+        this.reset();
+    }
+
+    /**
+     * Calculates the state of the Switch.
+     */
+    public void flipManualState() {
+        manualState = SwitchState.opposite(manualState);
+    }
+
+    public void calculateState(int timestep) {
+        switch (mode) {
+            case Auto:
+                state = activeAt[IndexTranslator.getEffectiveIndex(this, timestep)] ? SwitchState.Open : SwitchState.Closed;
+            case Manual:
+            default:
+                state = manualState;
+        }
+    }
+
+    /*
+     * STATE
+     */
+
+    public SwitchState getState() {
+        return state;
+    }
+
+    /**
+     * For automatic use only (through the graph).
+     *
+     * @return the Graph Points
+     */
+    public LinkedList<Vec2f> getGraphPoints() {
+        return graphPoints;
+    }
+
+    /**
+     * Set the values of the switch in the graph (auto. mode only).
+     *
+     * @param linkedList the Graph points
+     */
+    public void setGraphPoints(LinkedList<Vec2f> linkedList) {
+        this.graphPoints = linkedList;
+    }
+
+    /**
+     * Initialize the Graph as a closed Switch.
+     */
+    private void initGraphPoints() {
+        graphPoints.clear();
+        graphPoints.add(new Vec2f(0, 1));
+        graphPoints.add(new Vec2f(1, 1));
+    }
+
+    public SwitchMode getMode() {
+        return mode;
+    }
+
+    public void setMode(SwitchMode mode) {
+        this.mode = mode;
+    }
+
+    public SwitchState getManualState() {
+        return manualState;
+    }
+
+    public void setManualState(SwitchState manuelState) {
+        this.manualState = manuelState;
+    }
+
+    // interfaces.GraphEditable
+    @Override
+    public GraphType getGraphType() {
+        return GraphType.boolGraph;
+    }
+
+    @Override
+    public LinkedList<Vec2f> getStateGraph() {
+        return graphPoints;
+    }
+
+    @Override
+    public void reset() {
+        initGraphPoints();
+        sampleGraph();
+    }
+
+    @Override
+    public void sampleGraph() {
+        activeAt = sampleGraph(100);
+    }
+
+    /**
+     * Generate out of the Graph Points a array of boolean that represent the
+     * Curve("on or off"-Graph) at each sample position. The Values are in the Range
+     * [0,1].
+     *
+     * @param sampleLength amount of samplePositions. The positions are equidistant
+     *                     on the Range[0,1].
+     * @return the boolean array of samplepoints.
+     */
+    private boolean[] sampleGraph(int sampleLength) {
+        ListIterator<Vec2f> iter = this.graphPoints.listIterator();
+        Vec2f before = iter.next();
+        Vec2f after = iter.next();
+        boolean[] activeTriggerPos = new boolean[sampleLength];
+        for (int i = 0; i < sampleLength; i++) {
+            double graphX = (double) i / (double) (sampleLength - 1); // from 0.0 to 1.0
+            if (graphX > after.x) {
+                before = after;
+                after = iter.next();
+            }
+            activeTriggerPos[i] = (before.getY() >= 0.5);
+        }
+        return activeTriggerPos;
+    }
+
+    @Override
+    public int getLocalPeriod() {
+        return localPeriod;
+    }
+
+    // interfaces.LocalMode
+    @Override
+    public void setLocalPeriod(int period) {
+        localPeriod = period;
+    }
+
+    @Override
+    public boolean isUsingLocalPeriod() {
+        return localPeriodActive;
+    }
+
+    @Override
+    public void setUseLocalPeriod(boolean state) {
+        this.localPeriodActive = state;
+    }
+
+    public String toString() {
+        return name + "[ID:" + getId() + "]";
+
+    }
+
+    public enum SwitchState {
+        Open, Closed;
+
+        public static SwitchState opposite(SwitchState state) {
+			return switch (state) {
+				case Closed -> Open;
+				case Open -> Closed;
+			};
+        }
+
+        public boolean isOpen() {
+            return this == Open;
+        }
+
+        public boolean isClosed() {
+            return this == Closed;
+        }
+    }
+
+    public enum SwitchMode {
+        Manual, Auto
+    }
 }

+ 0 - 1
src/holeg/model/Node.java

@@ -17,7 +17,6 @@ public class Node extends AbstractCanvasObject {
 	 */
 	public Node(String objName) {
 		super(objName);
-		this.setSav("CVS");
 	}
 	
 	public Node(Node node){

+ 8 - 4
src/holeg/preferences/ColorPreference.java

@@ -88,13 +88,17 @@ public class ColorPreference {
 	
 	public static class Panel {
 		public static final Color Transparent = new Color(0,0,0,0);
-		public static final Color ObjectSelection = new Color(128, 174, 247, 40);
-		public static final Color ObjectSelectionBorder = Color.lightGray;
-		public static final Color MouseSelection = Color.blue;
 		public static final Color Background = new Color(250, 250, 250);
 		public static final Color Title = new Color(54, 73, 78);
 	}
-	
+	public static class Canvas {
+		public static final Color MouseSelectionBorder = new Color(0, 120, 215);
+		public static final Color MouseSelectionFill = new Color(128, 174, 247, 40);
+		public static final Color ObjectSelectionBorder = new Color(153, 209, 255);;
+		public static final Color ObjectSelectionFill = new Color(205, 233, 255);
+	}
+
+
 	public static class Dialog{
 		public static final Color BackgroundColor = new Color(255, 50, 50);
 	}

+ 0 - 2
src/holeg/ui/controller/CanvasController.java

@@ -100,7 +100,6 @@ public class CanvasController {
 	 *            the Object
 	 */
 	public void addNewObject(AbstractCanvasObject object) {
-		object.setSav("CVS");
 		// object.setConnections(new ArrayList<CpsEdge>());
 		addObject(object, true);
 	}
@@ -201,7 +200,6 @@ public class CanvasController {
 				tCps = new Node("Node");
 			}
 			tCps.setPosition(new Vec2i(p.x + (cps.getPosition().getX() - x), p.y + (cps.getPosition().getY() - y)));
-			tCps.setSav(cps.getSav());
 			addObject(tCps, false);
 		}
 

+ 0 - 7
src/holeg/ui/controller/CategoryController.java

@@ -118,11 +118,6 @@ public class CategoryController {
 			object.setName(name);
 			i++;
 		}
-		if(updateElementSaves && object instanceof HolonObject hO&&hO.getElements()!=null){
-			for(HolonElement hE : hO.getElements().toList()) {
-				hE.setSaving(new SimpleEntry<String,String>(hE.getSaving().getKey(), name));				
-			}
-		}
 		category.getObjects().add(object);
 	}
 
@@ -143,7 +138,6 @@ public class CategoryController {
 		obj.setImage(image);
 		obj.clearElements();
 		obj.add(list);
-		obj.setSav(category.getName());
 		addObject(category, obj);
 		return obj;
 	}
@@ -161,7 +155,6 @@ public class CategoryController {
 	 */
 	public HolonSwitch addNewHolonSwitch(Category cat, String objName) {
 		HolonSwitch holonSwitch = new HolonSwitch(objName);
-		holonSwitch.setSav(cat.getName());
 		addObject(cat, holonSwitch);
 		return holonSwitch;
 	}

+ 7 - 23
src/holeg/ui/controller/ClipboardController.java

@@ -203,29 +203,13 @@ public class ClipboardController {
         updatePosition(temp, upperNode);
 
         // if its stored before on the canvas just put it there
-        if (temp.getSav().equals(sav)) {
-            if (upperNode == null)
-                cvsC.addObject(temp, false);
-            else
-                uppC.addObjectInGroupNode(temp, upperNode, false);
-            // mark the Pasted Objects
-            GuiSettings.getSelectedObjects().add(temp);
-        } else {
-            // else look up the table and put it into the right Uppernode
-            GroupNode temp2 = (GroupNode) objDispatch.get(objIDMap.get(Integer.parseInt(temp.getSav())));
-            if(temp2!=null)
-            	uppC.addObjectInGroupNode(temp, temp2, false);
-            else{
-            	/**
-            	 * if corresponding Uppernode doesn't exist:
-            	 * Add it to the current Canvas/UpperNode
-            	 */
-            	 if (upperNode == null)
-                     cvsC.addObject(temp, false);
-                 else
-                     uppC.addObjectInGroupNode(temp, upperNode, false);
-            }
-        }
+        if (upperNode == null)
+            cvsC.addObject(temp, false);
+        else
+            uppC.addObjectInGroupNode(temp, upperNode, false);
+        // mark the Pasted Objects
+        GuiSettings.getSelectedObjects().add(temp);
+
 
         objDispatch.put(temp.getId(), temp);
     }

+ 12 - 10
src/holeg/ui/controller/Control.java

@@ -210,13 +210,11 @@ public class Control {
 	/**
 	 * removes a selectedObject from selection.
 	 *
-	 * @param obj Cpsobject
 	 */
 	public void removeObjectsFromSelection(Collection<AbstractCanvasObject> objects) {
-		for (AbstractCanvasObject obj : objects) {
-			GuiSettings.getSelectedObjects().remove(obj);
+		if(GuiSettings.getSelectedObjects().removeAll(objects)){
+			OnSelectionChanged.broadcast();
 		}
-		OnSelectionChanged.broadcast();
 	}
 
 	/**
@@ -225,8 +223,9 @@ public class Control {
 	 * @param obj Cpsobject
 	 */
 	public void removeObjectFromSelection(AbstractCanvasObject obj) {
-		GuiSettings.getSelectedObjects().remove(obj);
-		OnSelectionChanged.broadcast();
+		if(GuiSettings.getSelectedObjects().remove(obj)){
+			OnSelectionChanged.broadcast();
+		}
 	}
 
 	/**
@@ -235,13 +234,16 @@ public class Control {
 	 * @param obj AbstractCpsobject
 	 */
 	public void addSelectedObject(AbstractCanvasObject obj) {
-		GuiSettings.getSelectedObjects().add(obj);
-		OnSelectionChanged.broadcast();
+		if(GuiSettings.getSelectedObjects().add(obj)){
+			OnSelectionChanged.broadcast();
+		}
 	}
 
 	public void addSelectedObjects(Collection<AbstractCanvasObject> objects) {
-		GuiSettings.getSelectedObjects().addAll(objects);
-		OnSelectionChanged.broadcast();
+		if(GuiSettings.getSelectedObjects().addAll(objects)){
+			OnSelectionChanged.broadcast();
+		}
+
 	}
 
 	public void clearSelection() {

+ 5 - 28
src/holeg/ui/controller/LoadController.java

@@ -53,8 +53,6 @@ public class LoadController {
      * @param model Model
      * @param cg    CategoryController
      * @param cvs   CanvasController
-     * @param obj   ObjectController
-     * @param mp    MultiPurposeController
      */
     LoadController(Model model, CategoryController cg, CanvasController cvs,
                    NodeController uppC) {
@@ -226,9 +224,10 @@ public class LoadController {
     		return;
     	}
         
-        temp.setImage(checkOS(temp.getImage()));
         temp.initForReflection();
-        cgC.findCategoryWithName(temp.getSav()).ifPresent(cat -> {
+        temp.setImage(checkOS(temp.getImage()));
+        //TODO(Tom2022-01-16): Cat name should be stored somewhere
+        cgC.findCategoryWithName(temp.getName()).ifPresent(cat -> {
         	cat.findObjectWithName(temp.getName()).ifPresent(obj -> {
         		cgC.removeObject(cat, obj);
         	});
@@ -257,12 +256,6 @@ public class LoadController {
         if(amount != null) {
         	ele.setEnergy(amount.getAsInt() * ele.getEnergy());
         }
-        cgC.findCategoryWithName(ele.getSaving().getKey()).ifPresent(cat -> {
-        	cat.findObjectWithName(ele.getSaving().getValue()).ifPresent(obj -> {
-        		HolonObject hObject = (HolonObject) obj;
-        		hObject.add(ele);
-        	});
-        });
         
     }
 
@@ -275,28 +268,12 @@ public class LoadController {
     	try {
     		temp = GuiSettings.gson.fromJson(jsonObject, AbstractCanvasObject.class);
     	}catch (com.google.gson.JsonParseException e){
-    		System.err.println(jsonObject.get("type").getAsString());
+            log.warning(e + jsonObject.get("type").getAsString());
     		return;
     	}
         temp.initForReflection();
         temp.setImage(checkOS(temp.getImage()));
-        // if its stored before on the canvas just put it there
-        if (temp.getSav().equals("CVS")) {
-            cvsC.addObject(temp, false);
-
-        } else {
-            // else look up the table and put it into the right Uppernode
-            GroupNode temp2 = (GroupNode) objDispatch.get(Integer.parseInt(temp.getSav()));
-            if(temp2 != null)
-            	uppC.addObjectInGroupNode(temp, temp2, false);
-            else{
-            	/**
-            	 * if null try to load on canvas
-            	 */
-            	cvsC.addObject(temp, false);
-            }
-
-       }
+        cvsC.addObject(temp, false);
 
         objDispatch.put(temp.getId(), temp);
 

+ 0 - 5
src/holeg/ui/controller/NodeController.java

@@ -89,10 +89,6 @@ class NodeController {
 
 		node.getObjectsInThisLayer().forEach(obj -> {
 			updatePosition(obj, upperNode);
-			if (upperNode == null)
-				obj.setSav("CVS");
-			else
-				obj.setSav("" + upperNode.getId());
 		});
 		if (upperNode == null) {
 			model.getCanvas().addAll(node.getObjectsInThisLayer());
@@ -145,7 +141,6 @@ class NodeController {
     		new Error("upperNode == null while adding "+object.toString()).printStackTrace();
     		return;
     	}
-    	object.setSav("" + upperNode.getId());
 		upperNode.add(object);
 		
 		/**

+ 2 - 6
src/holeg/ui/model/GuiSettings.java

@@ -1,6 +1,5 @@
 package holeg.ui.model;
 
-import java.util.AbstractMap.SimpleEntry;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -8,8 +7,6 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 
 import holeg.adapter.AbstractCpsObjectAdapter;
-import holeg.adapter.PairAdapter;
-import holeg.adapter.PositionAdapter;
 import holeg.model.AbstractCanvasObject;
 import holeg.model.Edge;
 import holeg.ui.view.main.Category;
@@ -34,7 +31,8 @@ public class GuiSettings {
     
 	public static int autoSaveNr = -1;
     public static int numberOfSaves = 35;
-    
+
+    public static float dragThresholdDistance = 5;
     
     
     public static int getPictureScale() {
@@ -79,8 +77,6 @@ public class GuiSettings {
         builder.excludeFieldsWithoutExposeAnnotation();
         builder.setPrettyPrinting();
         builder.registerTypeAdapter(AbstractCanvasObject.class, new AbstractCpsObjectAdapter());
-        builder.registerTypeAdapter(Vec2i.class, new PositionAdapter());
-        builder.registerTypeAdapter(SimpleEntry.class, new PairAdapter());
         return builder.create();
     }
 }

+ 204 - 341
src/holeg/ui/view/canvas/Canvas.java

@@ -1,23 +1,21 @@
 package holeg.ui.view.canvas;
 
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics;
-import java.util.logging.Logger;
-
-import javax.swing.JPanel;
-
+import holeg.model.AbstractCanvasObject;
 import holeg.model.GroupNode;
-import holeg.model.HolonObject;
-import holeg.preferences.ColorPreference;
 import holeg.ui.controller.Control;
 import holeg.ui.model.GuiSettings;
-import holeg.utility.image.Import;
+import holeg.utility.math.vector.Geometry;
 import holeg.utility.math.vector.Vec2i;
 
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.RenderingHints;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.logging.Logger;
 
 /**
  * This Class is the Canvas. All Objects will be visualized here
@@ -25,333 +23,198 @@ import java.awt.RenderingHints;
  * @author Gruppe14
  */
 public class Canvas extends JPanel {
-	private static final Logger log = Logger.getLogger(Canvas.class.getName());
-	private boolean enabled = false;
-
-	private GroupNode groupNode;
-	private Control control;
-	private static Color[] colors = { ColorPreference.HolonObject.Producer, ColorPreference.HolonObject.NotSupplied,
-			ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.Supplied,
-			ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.NoEnergy };
-
-	public Canvas(Control control, GroupNode groupNode) {
-		this.control = control;
-		this.groupNode = groupNode;
-		control.OnGuiSetEnabled.addListener(this::setCanvasEnabled);
-		// TODO(Tom2022-01-14): remove listener when not needed anymore
-	}
-
-	private void setCanvasEnabled(boolean state) {
-		enabled = state;
-	}
-
-//	protected void paintCanvasObject(Graphics2D g, DecoratedHolonObject decoratedHolonObject) {
-//		Vec2i pos = decoratedHolonObject.getModel().getPosition();
-//		Color statecolor = ColorPreference.HolonObject.getStateColor(decoratedHolonObject.getState());
-//		g.setColor(statecolor);
-//		g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
-//				GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
-//		drawCanvasObject(g, decoratedHolonObject.getModel().getImage(), pos);
-//	}
-//
-//	protected void drawCanvasObjectString(Graphics2D g, Vec2i posOfCanvasObject, float energy) {
-//		g.setColor(Color.BLACK);
-//		g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (GuiSettings.getPictureScale() / 4f)));
-//		g.drawString((energy > 0) ? "+" + Float.toString(energy) : Float.toString(energy),
-//				posOfCanvasObject.getX() - GuiSettings.getPictureScaleDiv2(),
-//				posOfCanvasObject.getY() - GuiSettings.getPictureScaleDiv2() - 1);
-//	}
-//
-//	protected void paintConsumer(Graphics2D g, Consumer con) {
-//		paintCanvasObject(g, con);
-//		drawCanvasObjectString(g, con.getModel().getPosition(), -con.getEnergyNeededFromNetwork());
-//		if (GuiSettings.showSupplyBars) {
-//			paintSupplyBar(g, con.getSupplyBarPercentage(), ColorPreference.HolonObject.getStateColor(con.getState()),
-//					con.getModel().getPosition());
-//		}
-//	}
-//
-//	protected void paintSupplier(Graphics2D g, Supplier sup) {
-//		paintCanvasObject(g, sup);
-//		drawCanvasObjectString(g, sup.getModel().getPosition(), sup.getEnergyToSupplyNetwork());
-//	}
-//
-//	protected void drawCanvasObject(Graphics2D g, String Image, Vec2i pos) {
-//		g.drawImage(Import.loadImage(Image, GuiSettings.getPictureScale(), GuiSettings.getPictureScale()),
-//				pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(), GuiSettings.getPictureScale(),
-//				GuiSettings.getPictureScale(), null);
-//	}
-//
-//	protected void paintCable(Graphics2D g, Edge cable, boolean isSelected) {
-//		Vec2i start = cable.getA().getPosition();
-//		Vec2i end = cable.getB().getPosition();
-//		float currentEnergy = cable.getActualFlow();
-//		float capacity = cable.maxCapacity;
-//		boolean unlimited = cable.isUnlimitedCapacity();
-//		switch (cable.getState()) {
-//		case Burned:
-//			g.setColor(ColorPreference.Edge.Burned);
-//			g.setStroke(new BasicStroke(2));
-//			break;
-//		case Working:
-//			g.setColor(ColorPreference.Edge.Working);
-//			g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1));
-//			break;
-//		}
-//		if (isSelected) {
-//			g.setColor(Color.lightGray);
-//		}
-//		g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
-//		if (showConnectionInformation) {
-//			Vec2i middle = new Vec2i((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
-//			g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10)));
-//			g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY());
-//		}
-//	}
-//
-//	protected void paintSwitch(Graphics2D g, DecoratedSwitch dSwitch) {
-//		drawCanvasObject(g, dSwitch.getState() == SwitchState.Open ? HolonSwitch.getSwitchOpenImage()
-//				: HolonSwitch.getSwitchClosedImage(), dSwitch.getModel().getPosition());
-//	}
-//
-//	protected void paintExitCable(Graphics2D g, ExitCable eCable) {
-//		Vec2i start = eCable.getStart().getPosition();
-//		Vec2i end = eCable.getFinish().getPosition();
-//		float currentEnergy;
-//		float capacity = eCable.getEdge().maxCapacity;
-//		boolean unlimited = eCable.getEdge().isUnlimitedCapacity();
-//		if(eCable.getEdge().getState() == null) {
-//			System.err.print(eCable.getEdge());
-//		}
-//		switch (eCable.getEdge().getState()) {
-//		case Burned:
-//			currentEnergy = 0.0f;
-//			g.setColor(Color.RED);
-//			g.setStroke(new BasicStroke(2));
-//			break;
-//		case Working:
-//		default:
-//			currentEnergy = eCable.getEdge().getActualFlow();
-//			g.setColor(new Color(13, 175, 28));
-//			g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1));
-//			break;
-//		}
-//		g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
-//		Vec2i middle = new Vec2i((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
-//		g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10)));
-//		g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY());
-//	}
-//
-//	protected void paintGroupNode(Graphics2D g, DecoratedGroupNode dGroupNode) {
-//		Vec2i pos = dGroupNode.getModel().getPosition();
-//		g.setColor(Color.lightGray);
-//		g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
-//				GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
-//		drawCanvasObject(g, ImagePreference.Canvas.GroupNode, pos);
-//		paintGroupNodeBar(g, dGroupNode, pos);
-//	}
-//
-//	private void paintGroupNodeBar(Graphics2D g, DecoratedGroupNode dGroupNode, Vec2i pos) {
-//		// +1, -2, -1 little Adjustment for pixel perfect alignment
-//		int barWidth = (int) (GuiSettings.getPictureScale());
-//		int barHeight = (int) (GuiSettings.getPictureScale() / 5);
-//		g.setColor(Color.WHITE);
-//		g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth,
-//				barHeight);
-//		float[] percentages = getGroupNodeBarPercentages(dGroupNode);
-//
-//		for (int i = 5; i >= 0; i--) {
-//			g.setColor(colors[i]);
-//			g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1,
-//					(int) (barWidth * percentages[i] - 1), barHeight);
-//		}
-////		g.setColor(color);
-////		g.fillRect(pos.getX() - GuiSettings.GetPictureScaleDiv2(), pos.getY() + GuiSettings.GetPictureScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
-//		g.setColor(Color.BLACK);
-//		g.setStroke(new BasicStroke(1));
-//		g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1,
-//				barHeight);
-//	}
-//
-//	/**
-//	 * HardCoded Stuff dont try at Home ;)
-//	 * 
-//	 * @param dGroupNode
-//	 * @return
-//	 */
-//	public float[] getGroupNodeBarPercentages(DecoratedGroupNode dGroupNode) {
-//		int[] amountOfObjects = new int[6];
-//		amountOfObjects[0] = dGroupNode.getAmountOfSupplier();
-//		amountOfObjects[1] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED);
-//		amountOfObjects[2] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED);
-//		amountOfObjects[3] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED);
-//		amountOfObjects[4] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED);
-//		amountOfObjects[5] = dGroupNode.getAmountOfPassiv();
-//		int countHolonObjects = amountOfObjects[0] + amountOfObjects[1] + amountOfObjects[2] + amountOfObjects[3]
-//				+ amountOfObjects[4] + amountOfObjects[5];
-//		float[] percentages = new float[6];
-//		int count = 0;
-//		for (int i = 0; i < 6; i++) {
-//			count += amountOfObjects[i];
-//			percentages[i] = (float) count / (float) countHolonObjects;
-//		}
-//		return percentages;
-//	}
-
-//	private void paintSupplyBar(Graphics2D g, float percentage, Color color, Vec2i pos) {
-//		// +1, -2, -1 little Adjustment for pixel perfect alignment
-//		int barWidth = (int) (GuiSettings.getPictureScale());
-//		int barHeight = (int) (GuiSettings.getPictureScale() / 5);
-//		g.setColor(Color.WHITE);
-//		g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth,
-//				barHeight);
-//		g.setColor(color);
-//		g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1,
-//				(int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
-//		g.setColor(Color.BLACK);
-//		g.setStroke(new BasicStroke(1));
-//		g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1,
-//				barHeight);
-//		g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (barHeight * 1.5) - 2));
-//		String percentageString = (Math.round((percentage * 100))) + "%";
-//		int stringWidth = (int) g.getFontMetrics().getStringBounds(percentageString, g).getWidth();
-//		if (percentage > 1.0f)
-//			g.setColor(Color.WHITE); // Just to see better on purple
-//		g.drawString(percentageString, pos.getX() + 1 - stringWidth / 2,
-//				pos.getY() + GuiSettings.getPictureScaleDiv2() - 1 + barHeight);
-//
-//	}
-
-	@Override
-	public void paintComponent(Graphics g) {
-		super.paintComponent(g);
-		Graphics2D g2d = initGraphics2D(g);
-		log.info("Draw");
-		
-		groupNode.getHolonObjects().forEach(hO -> {
-			drawHolonObject(g2d, hO);
-		});
-
-//		
-//		Optional<VisualRepresentationalState> optVisualState = control.getSimManager().getActualVisualRepresentationalState();
-//		// VisualState Representation:
-//		if (optVisualState.isEmpty()) {
-//			return;
-//		}
-//		VisualRepresentationalState visualState = optVisualState.get();
-//		
-//		for (ExitCable cable : visualState.getExitCableList()) {
-//			paintExitCable(g2d, cable);
-//		}
-//		for (Edge cable : visualState.getCableList()) {
-//			paintCable(g2d, cable, GuiSettings.getSelectedEdges().contains(cable));
-//		}
-//		for (DecoratedGroupNode dGroupNode : visualState.getGroupNodeList()) {
-//			paintGroupNode(g2d, dGroupNode);
-//		}
-//		log.info(visualState.getConsumerList().stream().map(Object::toString).collect(Collectors.joining(", ")));
-//		for (Consumer con : visualState.getConsumerList()) {
-//			paintConsumer(g2d, con);
-//		}
-//		log.info(visualState.getSupplierList().stream().map(Object::toString).collect(Collectors.joining(", ")));
-//		for (Supplier sup : visualState.getSupplierList()) {
-//			paintSupplier(g2d, sup);
-//		}
-//		for (Passiv pas : visualState.getPassivList()) {
-//			paintCanvasObject(g2d, pas);
-//		}
-//		for (DecoratedSwitch dSwitch : visualState.getSwitchList()) {
-//			paintSwitch(g2d, dSwitch);
-//		}
-//		for (Node node : visualState.getNodeList()) {
-//			drawCanvasObject(g2d, ImagePreference.Canvas.Node.Unselected, node.getPosition());
-//		}
-//
-//		// -->oldCode
-//		if (doMark) {
-//			g2d.setColor(Color.BLACK);
-//			g2d.setStroke(new BasicStroke(0));
-//			drawMarker(g2d);
-//		}
-//		// Test Selection
-//		// Objects:
-//		g2d.setColor(Color.BLUE);
-//		g2d.setStroke(new BasicStroke(1));
-//		Color transparentGrey = ColorPreference.Panel.ObjectSelection;
-//		for (AbstractCanvasObject aCps : GuiSettings.getSelectedObjects()) {
-//			if (aCps instanceof Node) {
-//				Vec2i pos = aCps.getPosition();
-//				g2d.setColor(transparentGrey);
-//				g2d.fillOval(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2()),
-//						pos.getY() - (int) (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
-//				g2d.setColor(Color.LIGHT_GRAY);
-//				g2d.setStroke(new BasicStroke(2));
-//				g2d.drawOval(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2()),
-//						pos.getY() - (int) (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
-//			} else {
-//				Vec2i pos = aCps.getPosition();
-//				g2d.setColor(transparentGrey);
-//				g2d.fillRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f),
-//						pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f),
-//						(int) (GuiSettings.getPictureScale() * 1.5f));
-//				g2d.setColor(Color.LIGHT_GRAY);
-//				g2d.setStroke(new BasicStroke(2));
-//				g2d.drawRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f),
-//						pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f),
-//						(int) (GuiSettings.getPictureScale() * 1.5f));
-//			}
-//
-//		}
-//		// maybeReplace:
-//		if (mayBeReplaced != null) {
-//			g2d.setColor(Color.RED);
-//			Vec2i pos = mayBeReplaced.getPosition();
-//			g2d.drawImage(Import.loadImage(ImagePreference.Canvas.ReplaceSymbol), pos.getX() + GuiSettings.getPictureScaleDiv2(),
-//					pos.getY() - GuiSettings.getPictureScale(), GuiSettings.getPictureScaleDiv2(), GuiSettings.getPictureScaleDiv2(), null);
-//		}
-//		// <-- OldCode
-	}
-
-	private void drawHolonObject(Graphics2D g, HolonObject hO) {
-		Vec2i pos = hO.getPosition();
-//		Color statecolor = ColorPreference.HolonObject.getStateColor(hO.getState());
-//		g.setColor(statecolor);
-		g.setColor(Color.cyan);
-		g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
-				GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
-		drawCanvasObject(g, hO.getImage(), pos);
-	}
-
-	private void drawCanvasObject(Graphics2D g, String imageName, Vec2i pos) {
-		int pictureScale = GuiSettings.getPictureScale();
-		int pictureScaleDiv2 = GuiSettings.getPictureScaleDiv2();
-		Image image = Import.loadImage(imageName, pictureScale, pictureScale);
-		g.drawImage(image, pos.getX() - pictureScaleDiv2, pos.getY() - pictureScaleDiv2, pictureScale, pictureScale,
-				null);
-	}
-
-	private static final RenderingHints RenderingHint = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
-			RenderingHints.VALUE_ANTIALIAS_ON);
-	private static final Font CanvasFont = new Font("TimesNewRoman", Font.PLAIN,
-			Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10));
-
-	private static Graphics2D initGraphics2D(Graphics g) {
-		Graphics2D g2d = (Graphics2D) g;
-		g2d.setRenderingHints(RenderingHint);
-		g2d.setFont(CanvasFont);
-		return g2d;
-	}
-
-	public GroupNode getGroupNode() {
-		return this.groupNode;
-	}
-
-	public void setGroupNode(GroupNode groupNode) {
-		this.groupNode = groupNode;
-	}
-
-	public void checkForReplacement(int x, int y) {
-
-	}
+    private static final Logger log = Logger.getLogger(Canvas.class.getName());
+    private final GroupNode groupNode;
+    private final Control control;
+    private final CanvasMouseListener listener = new CanvasMouseListener();
+    private boolean enabled = true;
+
+    public Canvas(Control control, GroupNode groupNode) {
+        this.control = control;
+        this.groupNode = groupNode;
+        control.OnGuiSetEnabled.addListener(this::setCanvasEnabled);
+        control.OnSelectionChanged.addListener(this::repaint);
+        // TODO(Tom2022-01-14): remove listener when not needed anymore
+        this.addMouseListener(listener);
+        this.addMouseMotionListener(listener);
+    }
+
+    public static Rectangle getBoundsOfObject(AbstractCanvasObject obj) {
+        int pictureScale = GuiSettings.getPictureScale();
+        int pictureScaleDiv2 = GuiSettings.getPictureScaleDiv2();
+        Vec2i pos = obj.getPosition();
+        return new Rectangle(pos.getX() - pictureScaleDiv2, pos.getY() - pictureScaleDiv2, pictureScale, pictureScale);
+    }
+
+    private void setCanvasEnabled(boolean state) {
+        enabled = state;
+    }
+
+    public GroupNode getGroupNode() {
+        return this.groupNode;
+    }
+
+    @Override
+    public void paintComponent(java.awt.Graphics g) {
+        super.paintComponent(g);
+        Graphics2D g2d = Rendering.initGraphics2D(g);
+        Rendering.drawSelection(g2d);
+        log.info("Draw");
+        groupNode.getHolonObjects().forEach(hO -> Rendering.drawHolonObject(g2d, hO));
+        groupNode.getSwitches().forEach(hS -> Rendering.drawSwitchObject(g2d, hS));
+        groupNode.getGroupNodes().forEach(groupNode -> Rendering.drawGroupNode(g2d, groupNode));
+        groupNode.getNodes().forEach(node -> Rendering.drawNode(g2d, node));
+        control.getModel().getEdgesOnCanvas().forEach(edge -> {
+            boolean edgeAinside = edge.getA().getGroupNode().get() == groupNode;
+            boolean edgeBinside = edge.getB().getGroupNode().get() == groupNode;
+            //both
+            if (edgeAinside && edgeBinside) {
+                Rendering.drawEdge(g2d, edge);
+            }
+            //TODO(Tom2022-01-16): oneside
+            //none
+        });
+
+        if (listener.boxSelection) {
+            Rendering.drawSelectionBox(g2d, listener.getRectangleOfSelectionBox());
+        }
+    }
+
+    private Optional<AbstractCanvasObject> getObjectAtPosition(Vec2i pos) {
+        return groupNode.getObjectsInThisLayer().filter(obj ->
+                getBoundsOfObject(obj).contains(pos.getX(), pos.getY())
+        ).findAny();
+    }
+
+    //TODO(Tom2022-01-17): checkForReplacement replace with getObjectAtPosition
+    public Optional<AbstractCanvasObject> checkForReplacement(int x, int y) {
+        return Optional.empty();
+    }
+
+    /**
+     * Microsoft Windows10 selection & dragging behavior
+     */
+    private class CanvasMouseListener implements MouseListener, MouseMotionListener {
+        private Vec2i lastPosition = new Vec2i();
+        private Vec2i pressedPosition = new Vec2i();
+        private boolean dragDetected = false;
+        private boolean ctrlAdded = false;
+        private boolean boxSelection = false;
+        private Set<AbstractCanvasObject> selectionBeforeBoxSelection = new HashSet<>();
+
+        private static boolean LeftMouseButtonIsDown(MouseEvent e) {
+            int onMask = MouseEvent.BUTTON1_DOWN_MASK;
+            return (e.getModifiersEx() & onMask) == onMask;
+        }
+
+        @Override
+        public void mousePressed(MouseEvent e) {
+            if (!enabled) {
+                return;
+            }
+            log.info("Pressed");
+            Vec2i pos = new Vec2i(e.getPoint());
+            if (e.isControlDown()) {
+                getObjectAtPosition(pos).ifPresentOrElse(obj -> {
+                    if (!GuiSettings.getSelectedObjects().contains(obj)) {
+                        control.addSelectedObject(obj);
+                        ctrlAdded = true;
+                    }
+                }, this::initBoxSelection);
+            } else {
+                getObjectAtPosition(pos).ifPresentOrElse(obj -> {
+                    if (!GuiSettings.getSelectedObjects().contains(obj)) {
+                        GuiSettings.getSelectedObjects().clear();
+                        control.addSelectedObject(obj);
+                    }
+                }, () -> {
+                    control.clearSelection();
+                    initBoxSelection();
+                });
+            }
+
+            lastPosition = pressedPosition = pos;
+            dragDetected = false;
+        }
+
+        private void initBoxSelection() {
+            boxSelection = true;
+            selectionBeforeBoxSelection = Set.copyOf(GuiSettings.getSelectedObjects());
+        }
+
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            log.info("Released");
+            if (enabled && !dragDetected) {
+                if (e.isControlDown()) {
+                    getObjectAtPosition(lastPosition).ifPresent(obj -> {
+                        if (!ctrlAdded && GuiSettings.getSelectedObjects().contains(obj)) {
+                            control.removeObjectFromSelection(obj);
+                        }
+                    });
+                } else if (!GuiSettings.getSelectedObjects().isEmpty()) {
+                    getObjectAtPosition(lastPosition).ifPresent(obj -> {
+                        GuiSettings.getSelectedObjects().clear();
+                        control.addSelectedObject(obj);
+                    });
+                }
+            }
+            ctrlAdded = false;
+            boxSelection = false;
+            repaint();
+        }
+
+        @Override
+        public void mouseDragged(MouseEvent e) {
+            if (!enabled) {
+                return;
+            }
+            log.info("Dragged");
+            Vec2i actualPos = new Vec2i(e.getPoint());
+            dragDetected = dragDetected || (pressedPosition.getSquaredDistance(actualPos) > GuiSettings.dragThresholdDistance);
+            if (dragDetected) {
+                repaint();
+            }
+            if (boxSelection) {
+                log.info("BoxSelection");
+                Rectangle selectionBox = getRectangleOfSelectionBox();
+                groupNode.getObjectsInThisLayer().forEach(obj -> {
+                    Rectangle bounds = getBoundsOfObject(obj);
+                    if (selectionBox.intersects(bounds) ^ selectionBeforeBoxSelection.contains(obj)) {
+                        control.addSelectedObject(obj);
+                    } else {
+                        control.removeObjectFromSelection(obj);
+                    }
+                });
+            } else if (LeftMouseButtonIsDown(e)) {
+                Vec2i delta = actualPos.subtract(lastPosition);
+                GuiSettings.getSelectedObjects().forEach(obj -> obj.getPosition().addAssign(delta));
+            }
+            lastPosition = actualPos;
+
+        }
+
+        Rectangle getRectangleOfSelectionBox() {
+            return Geometry.createRectangleFromCorners(lastPosition, pressedPosition);
+        }
+
+        @Override
+        public void mouseClicked(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseMoved(MouseEvent e) {
+        }
+
+    }
 
 }

+ 289 - 0
src/holeg/ui/view/canvas/Rendering.java

@@ -0,0 +1,289 @@
+package holeg.ui.view.canvas;
+
+import holeg.model.*;
+import holeg.preferences.ColorPreference;
+import holeg.preferences.ImagePreference;
+import holeg.ui.model.GuiSettings;
+import holeg.ui.view.image.Import;
+import holeg.utility.math.vector.Vec2i;
+
+import java.awt.*;
+
+
+class Rendering {
+    private static final RenderingHints RenderingHint = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
+            RenderingHints.VALUE_ANTIALIAS_ON);
+    private static final Font CanvasFont = new Font("TimesNewRoman", Font.PLAIN,
+            Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10));
+    private static Color[] colors = {ColorPreference.HolonObject.Producer, ColorPreference.HolonObject.NotSupplied,
+            ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.Supplied,
+            ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.NoEnergy};
+    private static final BasicStroke OnePixelStroke = new BasicStroke(1);
+    private static final BasicStroke TwoPixelStroke = new BasicStroke(2);
+
+
+
+    static Graphics2D initGraphics2D(Graphics g) {
+        Graphics2D g2d = (Graphics2D) g;
+        g2d.setRenderingHints(RenderingHint);
+        g2d.setFont(CanvasFont);
+        return g2d;
+    }
+
+    static void drawSwitchObject(Graphics2D g, HolonSwitch hS) {
+        drawCanvasObject(g, hS);
+    }
+
+    static void drawHolonObject(Graphics2D g, HolonObject hO) {
+        Vec2i pos = hO.getPosition();
+//		Color statecolor = ColorPreference.HolonObject.getStateColor(hO.getState());
+//		g.setColor(statecolor);
+        g.setColor(Color.cyan);
+        g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
+                GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
+        drawCanvasObject(g, hO.getImage(), pos);
+    }
+
+    static void drawCanvasObject(Graphics2D g, AbstractCanvasObject obj) {
+        drawCanvasObject(g, obj.getImage(), obj.getPosition());
+    }
+
+    static void drawCanvasObject(Graphics2D g, String imageName, Vec2i pos) {
+        int pictureScale = GuiSettings.getPictureScale();
+        int pictureScaleDiv2 = GuiSettings.getPictureScaleDiv2();
+        Image image = Import.loadImage(imageName, pictureScale, pictureScale);
+        g.drawImage(image, pos.getX() - pictureScaleDiv2, pos.getY() - pictureScaleDiv2, pictureScale, pictureScale,
+                null);
+    }
+
+
+
+
+
+    static void drawNode(Graphics2D g, Node node) {
+        Vec2i pos = node.getPosition();
+        drawCanvasObject(g, ImagePreference.Canvas.Node.Unselected, pos);
+    }
+
+    static void drawEdge(Graphics2D g, Edge edge) {
+        //both
+        Vec2i start = edge.getA().getPosition();
+        Vec2i end = edge.getB().getPosition();
+        float currentEnergy = edge.getActualFlow();
+        float capacity = edge.maxCapacity;
+        boolean unlimited = edge.isUnlimitedCapacity();
+        switch (edge.getState()) {
+            case Burned -> {
+                g.setColor(ColorPreference.Edge.Burned);
+                g.setStroke(TwoPixelStroke);
+            }
+            case Working -> {
+                g.setColor(ColorPreference.Edge.Working);
+                g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1));
+            }
+        }
+//		if (isSelected) {
+//			g.setColor(Color.lightGray);
+//		}
+        g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
+        Vec2i middle = new Vec2i((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
+        g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY());
+    }
+
+    static void drawGroupNode(Graphics2D g, GroupNode groupNode) {
+        Vec2i pos = groupNode.getPosition();
+        g.setColor(Color.gray);
+        g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
+                GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
+        drawCanvasObject(g, groupNode.getImage(), pos);
+    }
+
+    static void drawSelection(Graphics2D g) {
+        g.setStroke(OnePixelStroke);
+        for (AbstractCanvasObject aCps : GuiSettings.getSelectedObjects()) {
+            Vec2i pos = aCps.getPosition();
+            if (aCps instanceof Node) {
+                g.setColor(ColorPreference.Canvas.ObjectSelectionFill);
+                g.fillOval(pos.getX() - (GuiSettings.getPictureScaleDiv2()),
+                        pos.getY() - (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
+                g.setColor(ColorPreference.Canvas.ObjectSelectionBorder);
+                g.drawOval(pos.getX() - (GuiSettings.getPictureScaleDiv2()),
+                        pos.getY() - (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
+            } else {
+                g.setColor(ColorPreference.Canvas.ObjectSelectionFill);
+                g.fillRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f),
+                        pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f),
+                        (int) (GuiSettings.getPictureScale() * 1.5f));
+                g.setColor(ColorPreference.Canvas.ObjectSelectionBorder);
+                g.drawRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f),
+                        pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f),
+                        (int) (GuiSettings.getPictureScale() * 1.5f));
+            }
+        }
+    }
+
+    static void drawSelectionBox(Graphics2D g, Rectangle selectionBox) {
+        g.setStroke(OnePixelStroke);
+        g.setColor(ColorPreference.Canvas.MouseSelectionBorder);
+        g.draw(selectionBox);
+        g.setColor(ColorPreference.Canvas.MouseSelectionFill);
+        g.fill(selectionBox);
+
+    }
+
+
+
+//protected void drawCanvasObjectString(Graphics2D g, Vec2i posOfCanvasObject, float energy) {
+//	g.setColor(Color.BLACK);
+//	g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (GuiSettings.getPictureScale() / 4f)));
+//	g.drawString((energy > 0) ? "+" + Float.toString(energy) : Float.toString(energy),
+//			posOfCanvasObject.getX() - GuiSettings.getPictureScaleDiv2(),
+//			posOfCanvasObject.getY() - GuiSettings.getPictureScaleDiv2() - 1);
+//}
+//
+//protected void paintConsumer(Graphics2D g, Consumer con) {
+//	paintCanvasObject(g, con);
+//	drawCanvasObjectString(g, con.getModel().getPosition(), -con.getEnergyNeededFromNetwork());
+//	if (GuiSettings.showSupplyBars) {
+//		paintSupplyBar(g, con.getSupplyBarPercentage(), ColorPreference.HolonObject.getStateColor(con.getState()),
+//				con.getModel().getPosition());
+//	}
+//}
+//
+//protected void paintSupplier(Graphics2D g, Supplier sup) {
+//	paintCanvasObject(g, sup);
+//	drawCanvasObjectString(g, sup.getModel().getPosition(), sup.getEnergyToSupplyNetwork());
+//}
+//
+//protected void drawCanvasObject(Graphics2D g, String Image, Vec2i pos) {
+//	g.drawImage(Import.loadImage(Image, GuiSettings.getPictureScale(), GuiSettings.getPictureScale()),
+//			pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(), GuiSettings.getPictureScale(),
+//			GuiSettings.getPictureScale(), null);
+//}
+//
+//protected void paintCable(Graphics2D g, Edge cable, boolean isSelected) {
+//	Vec2i start = cable.getA().getPosition();
+//	Vec2i end = cable.getB().getPosition();
+//	float currentEnergy = cable.getActualFlow();
+//	float capacity = cable.maxCapacity;
+//	boolean unlimited = cable.isUnlimitedCapacity();
+//	switch (cable.getState()) {
+//	case Burned:
+//		g.setColor(ColorPreference.Edge.Burned);
+//		g.setStroke(new BasicStroke(2));
+//		break;
+//	case Working:
+//		g.setColor(ColorPreference.Edge.Working);
+//		g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1));
+//		break;
+//	}
+//	if (isSelected) {
+//		g.setColor(Color.lightGray);
+//	}
+//	g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
+//	if (showConnectionInformation) {
+//		Vec2i middle = new Vec2i((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
+//		g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10)));
+//		g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY());
+//	}
+//}
+
+//protected void paintExitCable(Graphics2D g, ExitCable eCable) {
+//	Vec2i start = eCable.getStart().getPosition();
+//	Vec2i end = eCable.getFinish().getPosition();
+//	float currentEnergy;
+//	float capacity = eCable.getEdge().maxCapacity;
+//	boolean unlimited = eCable.getEdge().isUnlimitedCapacity();
+//	if(eCable.getEdge().getState() == null) {
+//		System.err.print(eCable.getEdge());
+//	}
+//	switch (eCable.getEdge().getState()) {
+//	case Burned:
+//		currentEnergy = 0.0f;
+//		g.setColor(Color.RED);
+//		g.setStroke(new BasicStroke(2));
+//		break;
+//	case Working:
+//	default:
+//		currentEnergy = eCable.getEdge().getActualFlow();
+//		g.setColor(new Color(13, 175, 28));
+//		g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1));
+//		break;
+//	}
+//	g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
+//	Vec2i middle = new Vec2i((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
+//	g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10)));
+//	g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY());
+//}
+
+//private void paintGroupNodeBar(Graphics2D g, DecoratedGroupNode dGroupNode, Vec2i pos) {
+//	// +1, -2, -1 little Adjustment for pixel perfect alignment
+//	int barWidth = (int) (GuiSettings.getPictureScale());
+//	int barHeight = (int) (GuiSettings.getPictureScale() / 5);
+//	g.setColor(Color.WHITE);
+//	g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth,
+//			barHeight);
+//	float[] percentages = getGroupNodeBarPercentages(dGroupNode);
+//
+//	for (int i = 5; i >= 0; i--) {
+//		g.setColor(colors[i]);
+//		g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1,
+//				(int) (barWidth * percentages[i] - 1), barHeight);
+//	}
+////	g.setColor(color);
+////	g.fillRect(pos.getX() - GuiSettings.GetPictureScaleDiv2(), pos.getY() + GuiSettings.GetPictureScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
+//	g.setColor(Color.BLACK);
+//	g.setStroke(new BasicStroke(1));
+//	g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1,
+//			barHeight);
+//}
+//
+///**
+// * HardCoded Stuff dont try at Home ;)
+// * 
+// * @param dGroupNode
+// * @return
+// */
+//public float[] getGroupNodeBarPercentages(DecoratedGroupNode dGroupNode) {
+//	int[] amountOfObjects = new int[6];
+//	amountOfObjects[0] = dGroupNode.getAmountOfSupplier();
+//	amountOfObjects[1] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED);
+//	amountOfObjects[2] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED);
+//	amountOfObjects[3] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED);
+//	amountOfObjects[4] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED);
+//	amountOfObjects[5] = dGroupNode.getAmountOfPassiv();
+//	int countHolonObjects = amountOfObjects[0] + amountOfObjects[1] + amountOfObjects[2] + amountOfObjects[3]
+//			+ amountOfObjects[4] + amountOfObjects[5];
+//	float[] percentages = new float[6];
+//	int count = 0;
+//	for (int i = 0; i < 6; i++) {
+//		count += amountOfObjects[i];
+//		percentages[i] = (float) count / (float) countHolonObjects;
+//	}
+//	return percentages;
+//}
+
+//private void paintSupplyBar(Graphics2D g, float percentage, Color color, Vec2i pos) {
+//	// +1, -2, -1 little Adjustment for pixel perfect alignment
+//	int barWidth = (int) (GuiSettings.getPictureScale());
+//	int barHeight = (int) (GuiSettings.getPictureScale() / 5);
+//	g.setColor(Color.WHITE);
+//	g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth,
+//			barHeight);
+//	g.setColor(color);
+//	g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1,
+//			(int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
+//	g.setColor(Color.BLACK);
+//	g.setStroke(new BasicStroke(1));
+//	g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1,
+//			barHeight);
+//	g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (barHeight * 1.5) - 2));
+//	String percentageString = (Math.round((percentage * 100))) + "%";
+//	int stringWidth = (int) g.getFontMetrics().getStringBounds(percentageString, g).getWidth();
+//	if (percentage > 1.0f)
+//		g.setColor(Color.WHITE); // Just to see better on purple
+//	g.drawString(percentageString, pos.getX() + 1 - stringWidth / 2,
+//			pos.getY() + GuiSettings.getPictureScaleDiv2() - 1 + barHeight);
+//
+//}
+}

+ 1 - 1
src/holeg/ui/view/component/Console.java

@@ -12,7 +12,7 @@ import javax.swing.JToolBar;
 import javax.swing.text.DefaultCaret;
 
 import holeg.preferences.ImagePreference;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 /**
  * Little new swing object to print data to a console.
  * @author tom

+ 1 - 1
src/holeg/ui/view/dialog/AboutUsPopUp.java

@@ -3,7 +3,7 @@ package holeg.ui.view.dialog;
 import javax.swing.*;
 
 import holeg.preferences.ImagePreference;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 
 import java.awt.*;
 

+ 1 - 1
src/holeg/ui/view/dialog/AddElementPopUp.java

@@ -20,7 +20,7 @@ import holeg.model.HolonElement;
 import holeg.model.HolonObject;
 import holeg.preferences.ColorPreference;
 import holeg.preferences.ImagePreference;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 
 /**
  * popup for adding an Holon Element to a holon Object.

+ 1 - 4
src/holeg/ui/view/dialog/AddObjectPopUp.java

@@ -37,7 +37,7 @@ import holeg.model.HolonObject;
 import holeg.preferences.ColorPreference;
 import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 
 /**
  * Popup for adding a Holon Object to a Category.
@@ -167,7 +167,6 @@ public class AddObjectPopUp extends JDialog {
 				addElement.setActualHolonObject((HolonObject) toEdit);
 				addElement.setVisible(true);
 				HolonElement hl = addElement.getElement();
-				hl.setSaving(new SimpleEntry<>(givenCategory, objectName.getText()));
 				// if (hl != null) {
 				// hl.setSav(givenCategory);
 				// }
@@ -234,8 +233,6 @@ public class AddObjectPopUp extends JDialog {
 											cat.findObjectWithName(toEdit.getName()).ifPresent(object -> {
 												cat.getObjects().remove(object);
 											});
-											hElements.forEach(ele -> ele.setSaving(
-													new SimpleEntry<>(ele.getSaving().getKey(), objectName.getText())));
 											controller.addObject(cat, objectName.getText(), hElements, imagePath);
 										});
 

+ 1 - 1
src/holeg/ui/view/dialog/CanvasResizePopUp.java

@@ -7,7 +7,7 @@ import holeg.ui.controller.Control;
 import holeg.ui.model.GuiSettings;
 import holeg.ui.model.Model;
 import holeg.ui.view.canvas.Canvas;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.math.vector.Vec2i;
 
 import java.awt.*;

+ 1 - 6
src/holeg/ui/view/dialog/CreateTemplatePopUp.java

@@ -26,7 +26,7 @@ import holeg.ui.controller.Control;
 import holeg.ui.model.GuiSettings;
 import holeg.ui.model.Model;
 import holeg.ui.view.main.Category;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 
 /**
  * PopUp for creating Holon Object Template.
@@ -294,9 +294,6 @@ public class CreateTemplatePopUp extends JDialog {
 	private void createTemplate() {
 		template.setName(textField_name.getText());
 		template.setImage(textField_imagePath.getText());
-		template.getElements().forEach(
-				ele -> ele.setSaving(new SimpleEntry<String, String>(choice
-						.getSelectedItem(), template.getName())));
 		controller.findCategoryWithName(choice
 				.getItem(choice.getSelectedIndex())).ifPresent(cat -> {
 					controller.addObject(cat, template.getName(),
@@ -317,7 +314,6 @@ public class CreateTemplatePopUp extends JDialog {
 			listModel.addElement(he.getName()
 					+ ": " + he.getEnergy() + "U");
 			template.add(he);
-			he.setSaving(new SimpleEntry<>(category, textField_name.getText()));
 		}
 	}
 
@@ -351,7 +347,6 @@ public class CreateTemplatePopUp extends JDialog {
 					+ ": " + he.getEnergy() + "U");
 			template.removeElement(index);
 			template.add(he);
-			he.setSaving(new SimpleEntry<>(category, textField_name.getText()));
 		}
 	}
 

+ 1 - 1
src/holeg/utility/image/Import.java → src/holeg/ui/view/image/Import.java

@@ -1,4 +1,4 @@
-package holeg.utility.image;
+package holeg.ui.view.image;
 
 import java.awt.Image;
 import java.io.File;

+ 1 - 1
src/holeg/ui/view/inspector/Inspector.java

@@ -26,7 +26,7 @@ import holeg.model.HolonSwitch;
 import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
 import holeg.ui.model.GuiSettings;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.listener.ResizeListener;
 import holeg.utility.math.Maths;
 import holeg.utility.math.decimal.Format;

+ 1 - 1
src/holeg/ui/view/inspector/InspectorTable.java

@@ -47,7 +47,7 @@ import holeg.ui.model.GuiSettings;
 import holeg.ui.view.component.TrippleCheckBox;
 import holeg.ui.view.component.TrippleCheckBox.State;
 import holeg.utility.events.Action;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.listener.SimpleDocumentListener;
 import holeg.utility.pooling.Pool;
 import net.miginfocom.swing.MigLayout;

+ 1 - 23
src/holeg/ui/view/main/GUI.java

@@ -90,7 +90,7 @@ import holeg.ui.view.inspector.UnitGraph;
 import holeg.ui.view.window.AddOnWindow;
 import holeg.ui.view.window.FlexWindow;
 import holeg.ui.view.window.Outliner;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 
 /**
  * Graphical User Interface.
@@ -322,7 +322,6 @@ public class GUI {
 					control.calculateStateAndVisualForCurrentTimeStep();
 					log.info("canvas.repaint0");
 					canvas.repaint();
-					updateUpperNodes();
 				} catch (IOException eex) {
 					eex.printStackTrace();
 				}
@@ -333,8 +332,6 @@ public class GUI {
 		inputMap.put(KeyStroke.getKeyStroke("control Y"), cntrlYDown);
 		actionMap.put(cntrlYDown, new AbstractAction() {
 
-			private static final long serialVersionUID = 1L;
-
 			@Override
 			public void actionPerformed(ActionEvent e) {
 				try {
@@ -345,7 +342,6 @@ public class GUI {
 					control.calculateStateAndVisualForCurrentTimeStep();
 					log.info("canvas.repaint1");
 					canvas.repaint();
-					updateUpperNodes();
 				} catch (IOException ex) {
 					ex.printStackTrace();
 				}
@@ -1407,24 +1403,6 @@ public class GUI {
 		}
 	}
 
-	// TODO(Tom2021-12-1) refactor tabbedPane and access to groupNodeViews
-	private void updateUpperNodes() {
-		for (Component c : tabbedPaneInnerOriginal.getComponents()) {
-			if (!(c instanceof JScrollPane)) {
-				continue;
-			}
-			Component pane = ((JScrollPane) c).getViewport().getComponent(0);
-			if (pane instanceof Canvas groupNodeCanvas) {
-				//TODO(Tom2021-12-20) maybe 
-				if(temp instanceof GroupNode node) {
-					groupNodeCanvas.setGroupNode(node);					
-				}else {
-					log.warning("TODO tabbedPane confickt");
-				}
-			}
-		}
-	}
-
 	/**
 	 * Removes UpperNodeTab if UpperNode was deleted
 	 *

+ 1 - 1
src/holeg/ui/view/main/TimePanel.java

@@ -37,7 +37,7 @@ import holeg.preferences.ColorPreference;
 import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
 import holeg.ui.model.GuiSettings;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.listener.LostFocusListener;
 
 /**

+ 1 - 1
src/holeg/ui/view/window/AddOnWindow.java

@@ -28,7 +28,7 @@ import javax.tools.ToolProvider;
 import holeg.api.AddOn;
 import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 
 public class AddOnWindow extends JFrame{
 	private AddOn actual;

+ 1 - 1
src/holeg/ui/view/window/FlexWindow.java

@@ -59,7 +59,7 @@ import holeg.preferences.ColorPreference;
 import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
 import holeg.ui.model.Model;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.listener.WindowClosingListener;
 
 

+ 1 - 3
src/holeg/ui/view/window/Outliner.java

@@ -17,13 +17,11 @@ import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.DefaultTreeCellRenderer;
 
 import holeg.model.AbstractCanvasObject;
-import holeg.model.Edge;
-import holeg.preferences.ColorPreference;
 import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
 import holeg.ui.model.MinimumNetwork;
 import holeg.ui.model.Model;
-import holeg.utility.image.Import;
+import holeg.ui.view.image.Import;
 import holeg.utility.listener.WindowClosingListener;
 
 public class Outliner extends JFrame {

+ 14 - 0
src/holeg/utility/math/vector/Geometry.java

@@ -0,0 +1,14 @@
+package holeg.utility.math.vector;
+
+import java.awt.*;
+
+public class Geometry {
+    public static Rectangle createRectangleFromCorners(Vec2i corner, Vec2i otherCorner){
+        //Calculate left top corner, width, height
+        Vec2i topLeft = new Vec2i(Math.min(corner.getX(), otherCorner.getX()), Math.min(corner.getY(), otherCorner.getY()));
+        Vec2i bottomRight = new Vec2i(Math.max(corner.getX(), otherCorner.getX()), Math.max(corner.getY(), otherCorner.getY()));
+        int width = bottomRight.getX() - topLeft.getX();
+        int height = bottomRight.getY() - topLeft.getY();
+        return new Rectangle(topLeft.getX(),topLeft.getY(), width, height);
+    }
+}

+ 100 - 85
src/holeg/utility/math/vector/Vec2i.java

@@ -1,107 +1,113 @@
 package holeg.utility.math.vector;
 
 
+import java.awt.*;
+
 /**
- * 
  * @author Tom Troppmann
- *
  */
 public class Vec2i {
-	private int x;
-	private int y;
+    private int x;
+    private int y;
 
-	public Vec2i()
-	{
-		x = y = 0;
-	}
+    public Vec2i() {
+        x = y = 0;
+    }
 
-	public Vec2i(int x, int y)
-	{
-		setX(x);
-		setY(y);
-	}
-	public Vec2i(Vec2i other)
-	{
-		x = other.x;
-		y = other.y;
-	}
-	public void setX(int x) {
-		this.x = x;
-	}
+    public Vec2i(int x, int y) {
+        setX(x);
+        setY(y);
+    }
 
-	public int getX() {
-		return x;
-	}
+    public Vec2i(Vec2i other) {
+        x = other.x;
+        y = other.y;
+    }
 
-	public void setY(int y) {
-		this.y = y;
-	}
+    public Vec2i(Point point) {
+        x = point.x;
+        y = point.y;
+    }
 
-	public int getY() {
-		return y;
-	}
+    public int getX() {
+        return x;
+    }
 
-	public void set(int x, int y)
-	{
-		setX(x);
-		setY(y);
-	}
-	public void set(Vec2i other)
-	{
-		setX(other.x);
-		setY(other.y);
-	}
+    public void setX(int x) {
+        this.x = x;
+    }
 
+    public int getY() {
+        return y;
+    }
 
-	public float dot(Vec2i other)
-	{
-		float result = 0.0f;
-		result = x * other.getX() + y * other.getY();
-		return result;
-	}
+    public void setY(int y) {
+        this.y = y;
+    }
 
-	public float getLength()
-	{
-		return (float)Math.sqrt(x * x + y * y);
-	}
+    public void set(int x, int y) {
+        setX(x);
+        setY(y);
+    }
 
-	/**
-	 * Return the Distance to a other Position.
-	 * @param other the other Position.
-	 * @return distance to the Position.
-	 */
-	public float getDistance(Vec2i other)
-	{
-		return (float) Math.sqrt(getSquaredDistance(other));
-	}
-	/**
-	 * Return the Distance squared to a other Position.
-	 * Faster then Distance because no Sqrt() needed.
-	 * @param other the other Position.
-	 * @return squared distance to the Position
-	 */
-	public float getSquaredDistance(Vec2i other)
-	{
-		int xDistance = other.getX() - x;
-		int yDistance = other.getY() - y;
-		return xDistance * xDistance + yDistance * yDistance;
-	}
+    public void set(Vec2i other) {
+        setX(other.x);
+        setY(other.y);
+    }
 
-	public Vec2i add(Vec2i other)
-	{
-		Vec2i result = new Vec2i();
-		result.setX(x + other.getX());
-		result.setY(y + other.getY());
-		return result;
-	}
 
-	public Vec2i subtract(Vec2i other)
-	{
-		Vec2i result = new Vec2i();
-		result.setX(x - other.getX());
-		result.setY(y - other.getY());
-		return result;
-	}
+    public float dot(Vec2i other) {
+        return (float) (x * other.getX() + y * other.getY());
+    }
+
+    public float getLength() {
+        return (float) Math.sqrt(x * x + y * y);
+    }
+
+    /**
+     * Return the Distance to a other Position.
+     *
+     * @param other the other Position.
+     * @return distance to the Position.
+     */
+    public float getDistance(Vec2i other) {
+        return (float) Math.sqrt(getSquaredDistance(other));
+    }
+
+    /**
+     * Return the Distance squared to a other Position.
+     * Faster then Distance because no Sqrt() needed.
+     *
+     * @param other the other Position.
+     * @return squared distance to the Position
+     */
+    public float getSquaredDistance(Vec2i other) {
+        int xDistance = other.getX() - x;
+        int yDistance = other.getY() - y;
+        return xDistance * xDistance + yDistance * yDistance;
+    }
+
+    public Vec2i add(Vec2i other) {
+        Vec2i result = new Vec2i();
+        result.setX(x + other.getX());
+        result.setY(y + other.getY());
+        return result;
+    }
+    public void addAssign(Vec2i other) {
+        x += other.getX();
+        y += other.getY();
+    }
+
+    public Vec2i subtract(Vec2i other) {
+        Vec2i result = new Vec2i();
+        result.setX(x - other.getX());
+        result.setY(y - other.getY());
+        return result;
+    }
+    public void subtractAssign(Vec2i other) {
+        x -= other.getX();
+        y -= other.getY();
+    }
 
 	public Vec2i multiply(float scaleFactor)
 	{
@@ -110,11 +116,20 @@ public class Vec2i {
 		result.setY((int)(y * scaleFactor));
 		return result;
 	}
+    public void multiplyAssign(float scaleFactor)
+    {
+        x *= scaleFactor;
+        y *= scaleFactor;
+    }
 	
 	public Vec2i divide(float divideFactor)
 	{
 		return this.multiply(1.0f/divideFactor);
 	}
+    public void divideAssign(float divideFactor)
+    {
+        multiplyAssign(1.0f/divideFactor);
+    }
 	
 	/**
 	 * Clamp the X Value two a upper or lower bound