Browse Source

HolonInformationPanel

UndoRedo
GroupNode Edge
TomTroppmann 2 years ago
parent
commit
b2ab9cce73

BIN
res/images/buttons/down.png


BIN
res/images/buttons/down_hovered.png


+ 2 - 2
src/holeg/addon/RandomOfferdFlexibility.java

@@ -95,7 +95,7 @@ public class RandomOfferdFlexibility implements AddOn {
 				negativeList.get(i).offered = (i < offer.negative.targetOffered);
 			}
 			if(control != null) {
-				control.calculateStateAndVisualForCurrentTimeStep();
+				control.calculateStateForCurrentIteration();
 			}
 		}
 	}
@@ -323,7 +323,7 @@ public class RandomOfferdFlexibility implements AddOn {
 		if(control == null) {
 			return;
 		}
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 		List<Flexibility> flexList = control.getModel().getAllFlexibilities();
 		List<Flexibility> allOfferedFlex = flexList.stream().filter(flex -> flex.getState().equals(FlexState.OFFERED)).toList();
 

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

@@ -70,7 +70,7 @@ public class RandomSwitch implements AddOn {
 				s.flipManualState();
 			}
 		});
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 	}
 	@Override
 	public JPanel getPanel() {

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

@@ -235,7 +235,7 @@ public class Randomizer implements AddOn {
 			}
 			
 		});
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 	}
 
 	

+ 2 - 2
src/holeg/algorithm/binary/BaseLine.java

@@ -272,7 +272,7 @@ public class BaseLine implements AddOn {
 		extractPositionAndAccess();
 		if(closeSwitches)setAllSwitchesClosed();
 		setHolonElemntsAktiv();
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 //		DecoratedState actualstate = control.getSimManager().getActualDecorState().get();	
 //		for(DecoratedNetwork net : actualstate.getNetworkList()) {
 //			float production = net.getSupplierList().stream().map(supplier -> supplier.getEnergyToSupplyNetwork()).reduce(0.0f, (a, b) -> a + b);
@@ -387,7 +387,7 @@ public class BaseLine implements AddOn {
 	 * To let the User See the current state without touching the Canvas.
 	 */
 	private void updateVisual() {
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 	}
 	/**
 	 * Sets the Model back to its original State before the LAST run.

+ 1 - 1
src/holeg/algorithm/example/DemoAlgo.java

@@ -395,7 +395,7 @@ public class DemoAlgo implements AddOn {
 		 * To let the User See the current state without touching the Canvas.
 		 */
 		private void updateVisual() {
-			control.calculateStateAndVisualForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 		}
 		/**
 		 * Sets the Model back to its original State before the LAST run.

+ 3 - 3
src/holeg/algorithm/example/FlexExample.java

@@ -333,7 +333,7 @@ public class FlexExample implements AddOn {
 			extractPositionAndAccess();
 			int actualIteration = control.getModel().getCurrentIteration();
 			println("TimeStep:" + actualIteration);
-			control.calculateStateOnlyForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 			List<Priority> priorityListASC = createPriorityListASC();
 //			DecoratedState actualstate = control.getSimManager().getActualDecorState().get();	
 //			for(DecoratedNetwork net : actualstate.getNetworkList()) {
@@ -383,7 +383,7 @@ public class FlexExample implements AddOn {
 			calculateStateResult(result);
 		}
 		private void calculateStateResult(RunResult result) {
-			control.calculateStateOnlyForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 //			RunResult.TimeStepStateResult timeStepState = result.addTimeStepStateResult();
 //			
 //			for(DecoratedNetwork network: control.getSimManager().getActualDecorState().get().getNetworkList()) {
@@ -506,7 +506,7 @@ public class FlexExample implements AddOn {
 		 * To let the User See the current state without touching the Canvas.
 		 */
 		private void updateVisual() {
-			control.calculateStateAndVisualForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 			//control.updateCanvas();
 			//control.getGui().triggerUpdateController(null);
 		}

+ 2 - 2
src/holeg/algorithm/objective_function/ObjectiveFunctionByCarlos.java

@@ -109,8 +109,8 @@ public class ObjectiveFunctionByCarlos {
 		for (Holon net : model.holons) {
 			double f_elements_deviation_production = net.getDeviationInProductionInNetworkForHolonObjects();
 			double f_elements_deviation_consumption = net.getDeviationInProductionInNetworkForHolonObjects();
-			double f_flexibility_deviation_consumption = net.getDiviationInFlexibilityConsumption();
-			double f_flexibility_deviation_production = net.getDiviationInFlexibilityProduction();
+			double f_flexibility_deviation_consumption = net.getDeviationInFlexibilityConsumption();
+			double f_flexibility_deviation_production = net.getDeviationInFlexibilityProduction();
 
 			double con = net.getTotalConsumption();
 			double prod = net.getTotalProduction();

+ 2 - 2
src/holeg/api/AlgorithmFrameworkFlex.java

@@ -737,7 +737,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 	 * To let the User See the current state without touching the Canvas.
 	 */
 	private void updateVisual() {
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 	}
 	/**
 	 * Sets the Model back to its original State before the LAST run.
@@ -757,7 +757,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 		for(Boolean bool: position) {
 			access.get(i++).setState(bool);
 		}
-		control.calculateStateOnlyForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 }
 
 

+ 3 - 3
src/holeg/api/TopologieAlgorithmFramework.java

@@ -487,7 +487,7 @@ public abstract class TopologieAlgorithmFramework implements AddOn{
 	private double evaluateNetworkAndPrint() {
 		runProgressbar.step();
 		openAllSwitchInSwitchList();
-		control.calculateStateOnlyForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 		return evaluateState(control.getModel() ,calculateAmountOfAddedSwitches(), addedCableMeter(), true);
 	}
 	
@@ -653,7 +653,7 @@ public abstract class TopologieAlgorithmFramework implements AddOn{
 	 * To let the User See the current state without touching the Canvas.
 	 */
 	private void updateVisual() {
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 	}
 	/**
 	 * Sets the Model back to its original State before the LAST run.
@@ -687,7 +687,7 @@ public abstract class TopologieAlgorithmFramework implements AddOn{
 			accessWildcards.get(count++).setState(position.get(i));
 		}
 		openAllSwitchInSwitchList();
-		control.calculateStateOnlyForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 }
 
 

+ 22 - 4
src/holeg/model/GroupNode.java

@@ -16,10 +16,10 @@ import holeg.utility.math.vector.Vec2i;
 public class GroupNode extends AbstractCanvasObject implements PostDeserialize {
 	private static final Logger log = Logger.getLogger(AbstractCanvasObject.class.getName());
 
-	private final List<HolonObject> objectList = new ArrayList<>();
-	private final List<HolonSwitch> switchList = new ArrayList<>();
-	private final List<Node> nodeList = new ArrayList<>();
-	private final List<GroupNode> groupNodeList = new ArrayList<>();
+	protected final List<HolonObject> objectList = new ArrayList<>();
+	protected final List<HolonSwitch> switchList = new ArrayList<>();
+	protected final List<Node> nodeList = new ArrayList<>();
+	protected final List<GroupNode> groupNodeList = new ArrayList<>();
 
 	public GroupNode(String nodeName) {
 		super(nodeName);
@@ -142,6 +142,15 @@ public class GroupNode extends AbstractCanvasObject implements PostDeserialize {
 	public Stream<HolonElement> getHolonElements(){
 		return objectList.stream().flatMap(HolonObject::elementsStream);
 	}
+	public Stream<HolonElement> getAllHolonElements(){
+		return Stream.concat(getHolonElements(),
+				groupNodeList.stream().flatMap(GroupNode::getAllHolonElements));
+	}
+
+	public Stream<Flexibility> getAllFlexibilities() {
+		return getAllHolonObjectsRecursive().flatMap(hO -> hO.elementsStream().flatMap(ele -> ele.flexList.stream()));
+	}
+
 
 	public void ungroup(){
 		getObjectsInThisLayer().forEach(obj -> {
@@ -164,6 +173,15 @@ public class GroupNode extends AbstractCanvasObject implements PostDeserialize {
 		return middle;
 	}
 
+	public float getTotalConsumption() {
+		return getAllHolonObjectsRecursive().map(HolonObject::getConsumption).reduce(0.f, Float::sum);
+	}
+
+	public float getTotalProduction() {
+		return getAllHolonObjectsRecursive().map(HolonObject::getProduction).reduce(0.f, Float::sum);
+	}
+
+
 
 	public void clear() {
 		objectList.clear();

+ 4 - 4
src/holeg/model/Holon.java

@@ -221,7 +221,7 @@ public class Holon {
         return (amountOfFlexibilities > 0) ? sum / (float) amountOfFlexibilities : 0.f;
     }
 
-    public float getVarianzInFlexibilitieProduction() {
+    public float getVarianzInFlexibilityProduction() {
         float average = getAverageFlexibilityProduction();
         float sum = getListOfEnergyInProductionThatIsOfferedByFlexibilitiesInThisNetwork()
                 .map(energy -> squared(energy - average)).reduce(0.f, Float::sum);
@@ -229,12 +229,12 @@ public class Holon {
         return (amountOfFlexibilities > 0) ? sum / (float) amountOfFlexibilities : 0.f;
     }
 
-    public float getDiviationInFlexibilityConsumption() {
+    public float getDeviationInFlexibilityConsumption() {
         return (float) Math.sqrt(getVarianzInFlexibilitiesConsumption());
     }
 
-    public float getDiviationInFlexibilityProduction() {
-        return (float) Math.sqrt(getVarianzInFlexibilitieProduction());
+    public float getDeviationInFlexibilityProduction() {
+        return (float) Math.sqrt(getVarianzInFlexibilityProduction());
     }
 
     public float getTotalConsumption() {

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

@@ -22,7 +22,6 @@ public class ColorPreference {
             public static final Color High = new Color(255, 92, 26);
             public static final Color Medium = new Color(255, 216, 57);
             public static final Color Low = new Color(255, 255, 175);
-            public static final Color NoData = new Color(21, 8, 17);
         }
     }
 
@@ -63,6 +62,7 @@ public class ColorPreference {
         public static final Color Offered = new Color(75, 170, 72);
         public static final Color NotOffered = new Color(237, 106, 90);
         public static final Color Unavailable = new Color(193, 193, 193);
+        public static final Color NoFlexibility = new Color(101, 101, 101);
 
         public static Color getStateColor(FlexState state) {
             return switch (state) {
@@ -88,6 +88,9 @@ public class ColorPreference {
         public static final Color ObjectSelectionFill = new Color(205, 233, 255);
     }
 
+    public static class InformationPanel{
+        public static final Color NoData = new Color(243, 243, 243, 255);
+    }
 
     public static class Dialog {
         public static final Color BackgroundColor = new Color(255, 50, 50);

+ 5 - 0
src/holeg/preferences/ImagePreference.java

@@ -59,5 +59,10 @@ public class ImagePreference {
 		public static final String Add = "/images/buttons/plus.png";
 		public static final String Delete = "/images/buttons/minus.png";
 	}
+	public static class HolonInformationPanel{
+		public static final String Filter = "/images/buttons/down.png";
+		public static final String FilterHovered = "/images/buttons/down_hovered.png";
+		public static final String FilterPressed = "/images/buttons/down_pressed.png";
+	}
 	public static final String Logo = "/images/logo/holeg.png";
 }

+ 48 - 38
src/holeg/ui/controller/Control.java

@@ -6,6 +6,7 @@ import holeg.preferences.PreferenceKeys;
 import holeg.serialize.CategoryAdapter;
 import holeg.ui.model.GuiSettings;
 import holeg.ui.model.IdCounter;
+import holeg.ui.model.UndoHistory;
 import holeg.ui.view.category.Category;
 import holeg.ui.view.dialog.CreateTemplatePopUp;
 import holeg.utility.events.Action;
@@ -46,9 +47,15 @@ public class Control {
         this.model = model;
         this.canvasController = new CanvasController(this);
         this.simulationManager = new SimulationManager(this);
+        OnCanvasUpdate.addListener(() -> UndoHistory.addSave(saveModelToJsonString()));
+        UndoHistory.addSave(saveModelToJsonString());
     }
 
 
+
+
+
+
     /* Operations for Categories and Objects */
 
     /**
@@ -115,13 +122,13 @@ public class Control {
         }
     }
 
-    public void addSelectedObject(AbstractCanvasObject obj) {
+    public void addObjectToSelection(AbstractCanvasObject obj) {
         if (GuiSettings.getSelectedObjects().add(obj)) {
             OnSelectionChanged.broadcast();
         }
     }
 
-    public void addSelectedObjects(Collection<AbstractCanvasObject> objects) {
+    public void addObjectsToSelection(Collection<AbstractCanvasObject> objects) {
         if (GuiSettings.getSelectedObjects().addAll(objects)) {
             OnSelectionChanged.broadcast();
         }
@@ -131,7 +138,7 @@ public class Control {
 
     public void setSelection(Collection<AbstractCanvasObject> objects) {
         GuiSettings.getSelectedObjects().clear();
-        addSelectedObjects(objects);
+        addObjectsToSelection(objects);
     }
 
     public void clearSelection() {
@@ -143,14 +150,10 @@ public class Control {
 
     public void addObjectOnCanvas(GroupNode node, AbstractCanvasObject object) {
         canvasController.addObject(node, object);
-        calculateStateAndVisualForTimeStep(model.getCurrentIteration());
+        calculateStateForCurrentIterationAndBroadcastCanvasUpdate(model.getCurrentIteration());
     }
 
 
-    public void addCopyOnCanvas(GroupNode node, AbstractCanvasObject object) {
-        addObjectOnCanvas(node, object.copy());
-    }
-
     /**
      * Deletes an CpsObject on the Canvas and its connections.
      *
@@ -161,12 +164,14 @@ public class Control {
         if (obj instanceof GroupNode groupnode) {
             canvasController.deleteAllObjectsInGroupNode(groupnode);
         }
-        calculateStateAndVisualForCurrentTimeStep();
+        calculateStateForCurrentIteration();
+        OnCanvasUpdate.broadcast();
     }
 
     public void deleteCanvasObjects(Collection<AbstractCanvasObject> objects) {
         canvasController.deleteObjects(objects);
-        calculateStateAndVisualForCurrentTimeStep();
+        calculateStateForCurrentIteration();
+        OnCanvasUpdate.broadcast();
     }
 
     /**
@@ -177,6 +182,7 @@ public class Control {
      */
     public void replaceCanvasObject(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) {
         canvasController.replaceObject(toBeReplaced, by);
+        OnCanvasUpdate.broadcast();
     }
 
     /**
@@ -192,6 +198,7 @@ public class Control {
             return false;
         }
         canvasController.addEdgeOnCanvas(edge);
+        OnCanvasUpdate.broadcast();
         return true;
     }
 
@@ -202,19 +209,13 @@ public class Control {
      */
     public void removeEdgesOnCanvas(Edge edge) {
         canvasController.removeEdgesOnCanvas(edge);
+        OnCanvasUpdate.broadcast();
     }
 
 
-    /**
-     * calculates the flow of the edges and the supply for objects for the current
-     * Timestep.
-     */
-    public void calculateStateAndVisualForCurrentTimeStep() {
-        calculateStateAndVisualForTimeStep(model.getCurrentIteration());
-    }
 
-    public void calculateStateOnlyForCurrentTimeStep() {
-        calculateStateForTimeStep(model.getCurrentIteration());
+    public void calculateStateForCurrentIteration() {
+        calculateStateForCurrentIteration(model.getCurrentIteration());
     }
 
     /**
@@ -222,7 +223,7 @@ public class Control {
      *
      * @param x current Iteration
      */
-    public void calculateStateAndVisualForTimeStep(int x) {
+    public void calculateStateForCurrentIterationAndBroadcastCanvasUpdate(int x) {
         simulationManager.calculateStateForTimeStep(x);
         log.info("OnCanvasUpdate");
         OnCanvasUpdate.broadcast();
@@ -230,10 +231,8 @@ public class Control {
 
     /**
      * calculates the flow of the edges and the supply for objects.
-     *
-     * @param x current Iteration
      */
-    public void calculateStateForTimeStep(int x) {
+    public void calculateStateForCurrentIteration(int x) {
         simulationManager.calculateStateForTimeStep(x);
     }
 
@@ -280,7 +279,7 @@ public class Control {
             obj.getPosition().clampY(0, GuiSettings.canvasSize.getY());
         });
         groupNode.addAll(copies);
-        calculateStateAndVisualForTimeStep(model.getCurrentIteration());
+        calculateStateForCurrentIterationAndBroadcastCanvasUpdate(model.getCurrentIteration());
         OnSelectionChanged.broadcast();
     }
 
@@ -401,18 +400,6 @@ public class Control {
     }
 
 
-    /**
-     * Removes an Object from a Category.
-     *
-     * @param category Category
-     * @param cps      the Object
-     */
-    public void removeObject(Category category, AbstractCanvasObject cps) {
-        category.getObjects().remove(cps);
-        OnCategoryChanged.broadcast();
-    }
-
-
     public Optional<Category> findCategoryWithName(String categoryName) {
         return GuiSettings.getCategories().stream().filter(cat -> cat.getName().equals(categoryName)).findAny();
     }
@@ -424,7 +411,7 @@ public class Control {
             Model model = gson.fromJson(reader, Model.class);
             reader.close();
             this.model = model;
-            calculateStateAndVisualForCurrentTimeStep();
+            calculateStateForCurrentIteration();
             OnModelChanged.broadcast();
         } catch (IOException e) {
             log.warning(e.getLocalizedMessage());
@@ -432,6 +419,16 @@ public class Control {
         clearSelection();
         GuiSettings.setActualSaveFile(file);
     }
+    public void loadModelFromJsonString(String json){
+        this.model = gson.fromJson(json, Model.class);
+        calculateStateForCurrentIteration();
+        OnModelChanged.broadcast();
+    }
+
+    public String saveModelToJsonString(){
+        return gson.toJson(model);
+    }
+
 
 
     public void toggleSelectedObjects(Collection<AbstractCanvasObject> objects) {
@@ -467,12 +464,25 @@ public class Control {
         OnCanvasUpdate.broadcast();
     }
 
+
+    public void undo(){
+        UndoHistory.undo().ifPresent(this::loadModelFromJsonString);
+    }
+    public void redo(){
+        UndoHistory.redo().ifPresent(this::loadModelFromJsonString);
+    }
+
+
+
+
+
+
     public void clearModel() {
         model.clear();
         clearSelection();
         model.setCurrentIteration(0);
         IdCounter.reset();
-        calculateStateAndVisualForCurrentTimeStep();
+        calculateStateForCurrentIteration();
         OnModelChanged.broadcast();
         GuiSettings.setActualSaveFile(null);
     }

+ 10 - 5
src/holeg/ui/model/GuiSettings.java

@@ -1,15 +1,15 @@
 package holeg.ui.model;
 
 import java.io.File;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
+
 import holeg.model.AbstractCanvasObject;
 import holeg.model.Edge;
 import holeg.ui.view.category.Category;
-import holeg.ui.view.dialog.CreateNewDialog;
 import holeg.utility.math.vector.Vec2i;
 
+import javax.swing.text.html.Option;
+
 public class GuiSettings {
 
     private static int pictureScale = 50; // Picture Scale
@@ -28,7 +28,12 @@ public class GuiSettings {
 	private static final Set<AbstractCanvasObject> selectedObjects = new HashSet<>();
     
 	public static int autoSaveNr = -1;
-    public static int numberOfSaves = 35;
+
+
+
+
+
+
 
     public static float dragThresholdDistance = 5;
     private static File actualSaveFile = null;

+ 31 - 0
src/holeg/ui/model/LimitedSizeQueue.java

@@ -0,0 +1,31 @@
+package holeg.ui.model;
+
+import java.util.ArrayList;
+
+public class LimitedSizeQueue<T> extends ArrayList<T> {
+
+    private final int maxSize;
+
+    public LimitedSizeQueue(int size){
+        this.maxSize = size;
+    }
+
+    public boolean add(T k){
+        boolean r = super.add(k);
+        if (size() > maxSize){
+            removeRange(0, size() - maxSize);
+        }
+        return r;
+    }
+    public void removeRange(int a, int b){
+        super.removeRange(a, b);
+    }
+
+    public T getYoungest() {
+        return get(size() - 1);
+    }
+
+    public T getOldest() {
+        return get(0);
+    }
+}

+ 46 - 0
src/holeg/ui/model/UndoHistory.java

@@ -0,0 +1,46 @@
+package holeg.ui.model;
+
+import java.util.Optional;
+
+public class UndoHistory {
+    public static final int NumberOfSaves = 35;
+    private static final LimitedSizeQueue<String> jsonSaves = new LimitedSizeQueue<>(NumberOfSaves);
+    private static int actualIndex = -1;
+
+
+    public static boolean canUndo(){
+        return actualIndex > 0;
+    }
+    public static Optional<String> undo(){
+        if(canUndo()){
+            actualIndex -= 1;
+            return Optional.of(jsonSaves.get(actualIndex));
+        }
+        return Optional.empty();
+    }
+    public static boolean canRedo(){
+        return actualIndex < jsonSaves.size() -1;
+    }
+    public static Optional<String> redo(){
+        if(canRedo()){
+            actualIndex += 1;
+            return Optional.of(jsonSaves.get(actualIndex));
+        }
+        return Optional.empty();
+    }
+
+    public static  void addSave(String save){
+        if(canRedo()){
+            jsonSaves.removeRange(actualIndex + 1, jsonSaves.size());
+        }
+        if(actualIndex < NumberOfSaves){
+            actualIndex += 1;
+        }
+        jsonSaves.add(save);
+    }
+
+
+
+
+
+}

+ 16 - 18
src/holeg/ui/view/canvas/Canvas.java

@@ -32,7 +32,6 @@ public class Canvas extends JPanel {
         control.OnCanvasUpdate.addListener(this::repaint);
         this.setBackground(Color.WHITE);
         this.setPreferredSize(new Dimension(GuiSettings.canvasSize.getX(), GuiSettings.canvasSize.getY()));
-        // TODO(Tom2022-01-14): remove listener when not needed anymore
         this.addMouseListener(canvasMouseListener);
         this.addMouseMotionListener(canvasMouseListener);
     }
@@ -173,7 +172,7 @@ public class Canvas extends JPanel {
                     }
                     if (SwingUtilities.isLeftMouseButton(e)) {
                         state = State.ObjectDragging;
-                    } else if (SwingUtilities.isRightMouseButton(e)) {
+                    } else if (SwingUtilities.isRightMouseButton(e) && !(selectedOnPressed instanceof GroupNode)) {
                         state = State.EdgeCreation;
                     }
                 }
@@ -182,7 +181,7 @@ public class Canvas extends JPanel {
                     groupNode.getObjectsInThisLayer().forEach(obj -> {
                         Rectangle bounds = getBoundsOfObject(obj);
                         if (selectionBox.intersects(bounds) ^ selectionBeforeBoxSelection.contains(obj)) {
-                            control.addSelectedObject(obj);
+                            control.addObjectToSelection(obj);
                         } else {
                             control.removeObjectFromSelection(obj);
                         }
@@ -210,22 +209,21 @@ public class Canvas extends JPanel {
                     if (GuiSettings.getSelectedObjects().contains(selectedOnPressed)) {
                         control.removeObjectFromSelection(selectedOnPressed);
                     } else {
-                        control.addSelectedObject(selectedOnPressed);
+                        control.addObjectToSelection(selectedOnPressed);
                     }
                 }
-                case EdgeCreation -> {
-                    getObjectAtPosition(lastPosition).ifPresentOrElse(obj -> {
-                        if (control.addEdgeOnCanvas(new Edge(selectedOnPressed, obj, GuiSettings.maxCapacityForNewCreatedEdges))) {
-                            control.calculateStateAndVisualForCurrentTimeStep();
-                        }
-                    }, () -> {
-                        Node node = new Node("Node");
-                        groupNode.add(node);
-                        node.setPosition(new Vec2i(lastPosition));
-                        control.addEdgeOnCanvas(new Edge(selectedOnPressed, node, GuiSettings.maxCapacityForNewCreatedEdges));
-                        control.calculateStateAndVisualForCurrentTimeStep();
-                    });
-                }
+                case EdgeCreation -> getObjectAtPosition(lastPosition).ifPresentOrElse(obj -> {
+                    boolean isGroupNode = obj instanceof GroupNode;
+                    if (!isGroupNode && control.addEdgeOnCanvas(new Edge(selectedOnPressed, obj, GuiSettings.maxCapacityForNewCreatedEdges))) {
+                        control.calculateStateForCurrentIteration();
+                    }
+                }, () -> {
+                    Node node = new Node("Node");
+                    groupNode.add(node);
+                    node.setPosition(new Vec2i(lastPosition));
+                    control.addEdgeOnCanvas(new Edge(selectedOnPressed, node, GuiSettings.maxCapacityForNewCreatedEdges));
+                    control.calculateStateForCurrentIteration();
+                });
             }
             state = State.None;
             repaint();
@@ -240,7 +238,7 @@ public class Canvas extends JPanel {
                     if (obj instanceof HolonSwitch sw) {
                         sw.setMode(HolonSwitch.SwitchMode.Manual);
                         sw.flipManualState();
-                        control.calculateStateAndVisualForCurrentTimeStep();
+                        control.calculateStateForCurrentIteration();
                     } else if (obj instanceof GroupNode gNode) {
                         control.showGroupNode(gNode);
                     }

+ 1 - 1
src/holeg/ui/view/category/CategoryPanel.java

@@ -249,7 +249,7 @@ public class CategoryPanel extends JScrollPane {
                 }
                 obj.setPosition(pos.x + halfCursorSize, pos.y + halfCursorSize);
                 control.addObjectOnCanvas(groupNodeCanvas.getGroupNode(), obj);
-                control.calculateStateAndVisualForCurrentTimeStep();
+                control.calculateStateForCurrentIteration();
             });
         }
     }

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

@@ -130,7 +130,7 @@ public class EditEdgesPopUp extends JDialog {
 			edge.maxCapacity = cap;
         }
 		control.resetSimulation();
-		control.calculateStateAndVisualForCurrentTimeStep();
+		control.calculateStateForCurrentIteration();
 	}
 
 

+ 30 - 89
src/holeg/ui/view/information/FilterableGroupNode.java

@@ -1,96 +1,37 @@
 package holeg.ui.view.information;
 
-import java.util.ArrayList;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
+import holeg.model.*;
+
+public class FilterableGroupNode extends GroupNode {
+    public FilterableGroupNode() {
+        super("temp");
+    }
+
+    public void add(AbstractCanvasObject object) {
+        if (object instanceof HolonObject hObject) {
+            objectList.add(hObject);
+        }else if(object instanceof HolonSwitch hSwitch) {
+            switchList.add(hSwitch);
+        }else if(object instanceof Node node) {
+            nodeList.add(node);
+        }else if(object instanceof GroupNode groupNode) {
+            groupNodeList.add(groupNode);
+        }
+    }
+
+    public void remove(AbstractCanvasObject object) {
+        if (object instanceof HolonObject hObject) {
+            objectList.remove(hObject);
+        }else if(object instanceof HolonSwitch hSwitch) {
+            switchList.remove(hSwitch);
+        }else if(object instanceof Node node) {
+            nodeList.remove(node);
+        }else if(object instanceof GroupNode groupNode) {
+            groupNodeList.remove(groupNode);
+        }
+    }
 
-import holeg.model.Edge;
-import holeg.model.Flexibility;
-import holeg.model.GroupNode;
-import holeg.model.HolonElement;
-import holeg.model.HolonObject.HolonObjectState;
-import holeg.model.Node;
-import jdk.jfr.Unsigned;
 
-/**
- * For the @VisualRepresentationalState only.
- * 
- * @author Tom
- *
- */
-//TODO(Tom2022-01-13): Fix or remove
-public class FilterableGroupNode {
-//	private GroupNode model;
-//	private ArrayList<Supplier> supplierList = new ArrayList<>();
-//	private ArrayList<Passiv> passivList = new ArrayList<>();
-//	private ArrayList<Consumer> consumerList = new ArrayList<>();
-//	private ArrayList<Node> nodeList = new ArrayList<>();
-//	/**
-//	 * Cables that only exist on that group node. From a object in that group node
-//	 * to a object in that group Node. Not exit the group node (a layer down).
-//	 */
-//	private ArrayList<Edge> internCableList = new ArrayList<>();
-//	/**
-//	 * Cables that exit this group node (a Layer Up). From a object in this group
-//	 * node to a object in a upper layer.
-//	 */
-//	private ArrayList<ExitCable> exitCableList = new ArrayList<>();
-//	private ArrayList<DecoratedSwitch> switchList = new ArrayList<>();
-//	private ArrayList<FilterableGroupNode> groupNodeList = new ArrayList<>();
-//
-//	public FilterableGroupNode(GroupNode model, int iteration) {
-//		this.model = model;
-//	}
-//
-//	public FilterableGroupNode(DecoratedGroupNode dGroupNode, int iteration) {
-//		model = dGroupNode.getModel();
-//		supplierList = dGroupNode.getSupplierList();
-//		passivList = dGroupNode.getPassivList();
-//		consumerList = dGroupNode.getConsumerList();
-//		nodeList = dGroupNode.getNodeList();
-//		internCableList = dGroupNode.getInternCableList();
-//		exitCableList = dGroupNode.getExitCableList();
-//		switchList = dGroupNode.getSwitchList();
-//		groupNodeList = (ArrayList<FilterableGroupNode>) dGroupNode.getGroupNodeList().stream()
-//				.map(node -> new FilterableGroupNode(node, iteration)).collect(Collectors.toList());
-//	}
-//
-//	public GroupNode getModel() {
-//		return model;
-//	}
-//
-//	public ArrayList<Supplier> getSupplierList() {
-//		return supplierList;
-//	}
-//
-//	public ArrayList<Passiv> getPassivList() {
-//		return passivList;
-//	}
-//
-//	public ArrayList<Consumer> getConsumerList() {
-//		return consumerList;
-//	}
-//
-//	public ArrayList<Node> getNodeList() {
-//		return nodeList;
-//	}
-//
-//	public ArrayList<Edge> getInternCableList() {
-//		return internCableList;
-//	}
-//
-//	public ArrayList<ExitCable> getExitCableList() {
-//		return exitCableList;
-//	}
-//
-//	public ArrayList<DecoratedSwitch> getSwitchList() {
-//		return switchList;
-//	}
-//
-//	public ArrayList<FilterableGroupNode> getGroupNodeList() {
-//		return groupNodeList;
-//	}
 //
 //	// Returns the amount of holons and count himself
 //	public int getAmountOfGroupNodes() {

+ 309 - 193
src/holeg/ui/view/information/HolonInformationPanel.java

@@ -1,89 +1,93 @@
 package holeg.ui.view.information;
 
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.GridLayout;
-import java.awt.Insets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import javax.swing.BorderFactory;
-import javax.swing.JLabel;
-import javax.swing.JLayeredPane;
-import javax.swing.JPanel;
-import javax.swing.OverlayLayout;
-import javax.swing.border.EmptyBorder;
-
-import org.knowm.xchart.PieChart;
-import org.knowm.xchart.PieChartBuilder;
-import org.knowm.xchart.PieSeries.PieSeriesRenderStyle;
-import org.knowm.xchart.XChartPanel;
-import org.knowm.xchart.style.PieStyler;
-import org.knowm.xchart.style.PieStyler.LabelType;
-
 import holeg.model.Flexibility;
-import holeg.model.GroupNode;
 import holeg.model.HolonElement;
 import holeg.model.HolonObject;
 import holeg.model.HolonObject.HolonObjectState;
 import holeg.preferences.ColorPreference;
+import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
-import holeg.utility.math.decimal.Format;
 import holeg.ui.model.GuiSettings;
+import holeg.ui.view.image.Import;
+import holeg.utility.math.decimal.Format;
+import org.knowm.xchart.PieChart;
+import org.knowm.xchart.PieChartBuilder;
+import org.knowm.xchart.PieSeries.PieSeriesRenderStyle;
+import org.knowm.xchart.XChartPanel;
+import org.knowm.xchart.style.PieStyler;
+import org.knowm.xchart.style.PieStyler.LabelType;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+import java.awt.*;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
 
-//TODO(Tom2022-01-13): Fix;
 public class HolonInformationPanel extends JPanel {
-	private static final Logger log = Logger.getLogger(JPanel.class.getName());
+	private static final Logger log = Logger.getLogger(HolonInformationPanel.class.getName());
 	//private Predicate<DecoratedHolonObject> stateFilter = (object) -> true;// = (object) -> object.getState() ==
 																			// HolonObjectState.PRODUCER;
-	private Predicate<HolonElement> priorityFilter = (ele) -> true;
 	private final int defaultWidth = 50;
 	private final int defaultHeight = 200;
 
 	private static final Color[] supplyStateColors = new Color[] { ColorPreference.HolonObject.Producer,
 			ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.Supplied,
 			ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.NotSupplied,
-			ColorPreference.HolonObject.NoEnergy };
+			ColorPreference.HolonObject.NoEnergy, ColorPreference.InformationPanel.NoData };
 	private static final Color[] productionColors = new Color[] { ColorPreference.Energy.Production,
-			ColorPreference.Energy.Consumption };
+			ColorPreference.Energy.Consumption, ColorPreference.InformationPanel.NoData };
 	private static final Color[] activeColors = new Color[] { ColorPreference.Element.Active,
-			ColorPreference.Element.Inactive };
+			ColorPreference.Element.Inactive, ColorPreference.InformationPanel.NoData };
 	private static final Color[] flexibilityColors = new Color[] { ColorPreference.Flexibility.Offered,
 			ColorPreference.Flexibility.InUse, ColorPreference.Flexibility.OnCooldown,
-			ColorPreference.Flexibility.NotOffered, ColorPreference.Flexibility.Unavailable,
-			ColorPreference.Element.Priority.NoData };
+			ColorPreference.Flexibility.NotOffered, ColorPreference.Flexibility.Unavailable, ColorPreference.Flexibility.NoFlexibility,
+			ColorPreference.InformationPanel.NoData };
 	private static final Color[] priorityColors = new Color[] { ColorPreference.Element.Priority.Essential,
 			ColorPreference.Element.Priority.High, ColorPreference.Element.Priority.Medium,
-			ColorPreference.Element.Priority.Low, ColorPreference.Element.Priority.NoData };
+			ColorPreference.Element.Priority.Low, ColorPreference.InformationPanel.NoData };
 	
-	private PieChart supplyChart = createSupplyStateChart();
-	private PieChart priorityChart = createPriorityChart();
-	private PieChart flexibilityChart = createFlexibilityChart();
-	private PieChart energyChart = createProductionChart();
-	private PieChart activeChart = createActiveChart();
+	private final PieChart supplyChart = createSupplyStateChart();
+	private final PieChart priorityChart = createPriorityChart();
+	private final PieChart flexibilityChart = createFlexibilityChart();
+	private final PieChart energyChart = createProductionChart();
+	private final PieChart activeChart = createActiveChart();
+
+	private final JPanel graphPanel = new JPanel(new GridLayout(0, 2));
+	private final JPanel titlePanel = new JPanel(new BorderLayout(0, 0));
+
+	private final JCheckBoxMenuItem producerCheckBox = new JCheckBoxMenuItem("Producer", true);
+	private final JCheckBoxMenuItem overSuppliedCheckBox = new JCheckBoxMenuItem("Over supplied", true);
+	private final JCheckBoxMenuItem suppliedCheckBox = new JCheckBoxMenuItem("Supplied", true);
+	private final JCheckBoxMenuItem partiallySuppliedCheckBox = new JCheckBoxMenuItem("Partial supplied", true);
+	private final JCheckBoxMenuItem notSuppliedCheckBox = new JCheckBoxMenuItem("Not supplied", true);
+	private final JCheckBoxMenuItem noEnergyCheckBox = new JCheckBoxMenuItem("No energy", true);
 
-	private XChartPanel<PieChart> panelHolonObject;
-	private XChartPanel<PieChart> panelPriority;
-	private XChartPanel<PieChart> panelFlexibility;
-	private XChartPanel<PieChart> panelEnergy;
-	private XChartPanel<PieChart> panelActive;
+	private final JCheckBoxMenuItem essentialCheckBox = new JCheckBoxMenuItem("Essential", true);
+	private final JCheckBoxMenuItem highCheckBox = new JCheckBoxMenuItem("High", true);
+	private final JCheckBoxMenuItem mediumBox = new JCheckBoxMenuItem("Medium", true);
+	private final JCheckBoxMenuItem lowCheckBox = new JCheckBoxMenuItem("Low", true);
 
-	private JPanel graphPanel = new JPanel(new GridLayout(0, 2));
-	private JPanel titlePanel = new JPanel(new BorderLayout(0, 0));
+	private final JCheckBoxMenuItem activeCheckBox = new JCheckBoxMenuItem("Active", true);
+	private final JCheckBoxMenuItem inactiveCheckBox = new JCheckBoxMenuItem("Inactive", true);
 
-	private Control control;
-	private JLabel differenceEnergyLabelAmount = new JLabel("");
+	private final JCheckBoxMenuItem noFlexibilityCheckBox = new JCheckBoxMenuItem("No Flexibility", true);
+	private final JCheckBoxMenuItem inUseCheckBox = new JCheckBoxMenuItem("In use", true);
+	private final JCheckBoxMenuItem offeredCheckBox = new JCheckBoxMenuItem("Offered", true);
+	private final JCheckBoxMenuItem notOfferedCheckBox = new JCheckBoxMenuItem("Not offered", true);
+	private final JCheckBoxMenuItem onCooldownCheckBox = new JCheckBoxMenuItem("On cooldown", true);
+	private final JCheckBoxMenuItem unavailableCheckBox = new JCheckBoxMenuItem("Unavailable", true);
+
+
+	private final Control control;
+	private final JLabel differenceEnergyLabelAmount = new JLabel("");
 
 	public HolonInformationPanel(Control control) {
-		control.OnSelectionChanged.addListener(() -> updateCharts());
+		control.OnSelectionChanged.addListener(this::updateCharts);
+		control.OnCanvasUpdate.addListener(this::updateCharts);
 		this.control = control;
 		this.setLayout(new BorderLayout());
 		initGraphPanel();
@@ -94,163 +98,271 @@ public class HolonInformationPanel extends JPanel {
 	}
 	
 	public void updateCharts() {
-		if (GuiSettings.getSelectedObjects().isEmpty()) {
-			return;
-		}
-		Optional<FilterableGroupNode> filteredGroupNode = multiSelectionToFilterableGroupNode();
-		if(filteredGroupNode.isEmpty()) {
-			return;
+		FilterableGroupNode tempGroupNode = new FilterableGroupNode();
+		if(GuiSettings.getSelectedObjects().isEmpty()){
+			tempGroupNode.add(control.getModel().getCanvas());
+		}else{
+			tempGroupNode.addAll(GuiSettings.getSelectedObjects());
 		}
-		
-		FilterableGroupNode decoratedGroupNode = filteredGroupNode.get();
+
+		List<HolonObject> filteredHolonObjectList = tempGroupNode.getAllHolonObjectsRecursive().filter(this::stateFilter).toList();
+		Map<HolonObjectState, Long> stateMap = filteredHolonObjectList.stream().collect(Collectors.groupingBy(HolonObject::getState, Collectors.counting()));
 		// UPDATE SUPPLY STATE
-//		int producerAmount = decoratedGroupNode.getAmountOfSupplier(stateFilter);
-//		int overSuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter,
-//				HolonObjectState.OVER_SUPPLIED);
-//		int suppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter, HolonObjectState.SUPPLIED);
-//		int partiallySuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter,
-//				HolonObjectState.PARTIALLY_SUPPLIED);
-//		int notSuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter,
-//				HolonObjectState.NOT_SUPPLIED);
-//		int noEnergyAmount = decoratedGroupNode.getAmountOfPassiv(stateFilter);
-//
-//		supplyChart.updatePieSeries("Producer", producerAmount);
-//		supplyChart.updatePieSeries("Over supplied", overSuppliedAmount);
-//		supplyChart.updatePieSeries("Supplied", suppliedAmount);
-//		supplyChart.updatePieSeries("Partial supplied", partiallySuppliedAmount);
-//		supplyChart.updatePieSeries("Not supplied", notSuppliedAmount);
-//		supplyChart.updatePieSeries("No energy", noEnergyAmount);
-
-		// UPDATE PRIORITYS
-//		holeg.ui.view.information.FilterableGroupNode.PriorityCounts priorityCounts = decoratedGroupNode
-//				.getPriorityCounts(stateFilter);
-//
-//		priorityChart.updatePieSeries("Essential", priorityCounts.essential);
-//		priorityChart.updatePieSeries("High", priorityCounts.high);
-//		priorityChart.updatePieSeries("Medium", priorityCounts.medium);
-//		priorityChart.updatePieSeries("Low", priorityCounts.low);
-//		boolean hasPriority = priorityCounts.essential + priorityCounts.high + priorityCounts.medium
-//				+ priorityCounts.low > 0;
-//		priorityChart.updatePieSeries("No Data", hasPriority ? 0 : 1);
-//		updateToolTips(panelPriority);
+		int producerAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.PRODUCER, 0L));
+		int overSuppliedAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.OVER_SUPPLIED, 0L));
+		int suppliedAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.SUPPLIED, 0L));
+		int partiallySuppliedAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.PARTIALLY_SUPPLIED, 0L));
+		int notSuppliedAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.NOT_SUPPLIED, 0L));
+		int noEnergyAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.NO_ENERGY, 0L));
+
+		supplyChart.updatePieSeries("Producer", producerAmount);
+		supplyChart.updatePieSeries("Over supplied", overSuppliedAmount);
+		supplyChart.updatePieSeries("Supplied", suppliedAmount);
+		supplyChart.updatePieSeries("Partial supplied", partiallySuppliedAmount);
+		supplyChart.updatePieSeries("Not supplied", notSuppliedAmount);
+		supplyChart.updatePieSeries("No energy", noEnergyAmount);
+		supplyChart.updatePieSeries("No Data", filteredHolonObjectList.isEmpty() ? 1 : 0);
+		//UPDATE PRIORITIES
+
+		List<HolonElement> filteredHolonElements = filteredHolonObjectList.stream().flatMap(HolonObject::elementsStream)
+				.filter(ele -> priorityFilter(ele) && activeFilter(ele) && flexibilityFilter(ele)).toList();
+		Map<HolonElement.Priority, Long> priorityCounts = filteredHolonElements.stream()
+				.collect(Collectors.groupingBy(HolonElement::getPriority, Collectors.counting()));
+
+		long essential = priorityCounts.getOrDefault(HolonElement.Priority.Essential, 0L);
+		long high = priorityCounts.getOrDefault(HolonElement.Priority.High, 0L);
+		long medium = priorityCounts.getOrDefault(HolonElement.Priority.Medium, 0L);
+		long low = priorityCounts.getOrDefault(HolonElement.Priority.Low, 0L);
+
+
+		priorityChart.updatePieSeries("Essential", essential);
+		priorityChart.updatePieSeries("High", high);
+		priorityChart.updatePieSeries("Medium", medium);
+		priorityChart.updatePieSeries("Low", low);
+		boolean hasPriority = essential + high + medium + low > 0;
+		priorityChart.updatePieSeries("No Data", hasPriority ? 0 : 1);
 
 		// UPDATE PRODUCTION
-//		float production = decoratedGroupNode.getProduction(stateFilter, priorityFilter);
-//		float consumption = decoratedGroupNode.getConsumption(stateFilter, priorityFilter);
-//		log.info("production" + production + " consumption" + consumption);
-//		float difference = Math.abs(production - consumption);
-//		energyChart.updatePieSeries("Production", production);
-//		energyChart.updatePieSeries("Consumption", consumption);
-//		differenceEnergyLabelAmount.setText(Format.doubleFixedPlaces(1, difference));
-//
-//		// UPDATE FLEXIBILITIES
-//		int inUse = 0;
-//		int offered = 0;
-//		int onCooldown = 0;
-//		int notOffered = 0;
-//		int unavailable = 0;
-//
-//		Stream<Flexibility> flexWrapperStream = decoratedGroupNode.getFlexibilitiesStream(stateFilter, priorityFilter);
-//		List<Flexibility> flexList = flexWrapperStream.collect(Collectors.toList());
-//		for (Flexibility flex : flexList) {
-//			switch (flex.getState()) {
-//			case IN_USE:
-//				inUse++;
-//				break;
-//			case NOT_OFFERED:
-//				notOffered++;
-//				break;
-//			case OFFERED:
-//				offered++;
-//				break;
-//			case ON_COOLDOWN:
-//				onCooldown++;
-//				break;
-//			case UNAVAILABLE:
-//				unavailable++;
-//				break;
-//			default:
-//				break;
-//
-//			}
-//		}
-//		flexibilityChart.updatePieSeries("Offered", offered);
-//		flexibilityChart.updatePieSeries("In use", inUse);
-//		flexibilityChart.updatePieSeries("On cooldown", onCooldown);
-//		flexibilityChart.updatePieSeries("Not offered", notOffered);
-//		flexibilityChart.updatePieSeries("Unavailable", unavailable);
-//		boolean hasFlex = offered + inUse + onCooldown + notOffered + unavailable > 0;
-//		flexibilityChart.updatePieSeries("No Data", hasFlex ? 0 : 1);
-//		// UPDATE ActiveInActive
-//		int activeAmount = decoratedGroupNode.getAmountOfAktiveElementsFromHolonObjects(stateFilter, priorityFilter);
-//		int inactiveAmounts = decoratedGroupNode.getAmountOfElementsFromHolonObjects(stateFilter, priorityFilter)
-//				- activeAmount;
-//		activeChart.updatePieSeries("Active", activeAmount);
-//		activeChart.updatePieSeries("Inactive", inactiveAmounts);
-
+		float consumption = filteredHolonElements.stream().filter(element -> element.getActualEnergy() < 0)
+				.map(element -> -element.getActualEnergy()).reduce(0.0f, Float::sum);
+		float production = filteredHolonElements.stream()
+				.map(HolonElement::getActualEnergy).filter(energy -> energy > 0).reduce(0.0f, Float::sum);
+
+		float difference = Math.abs(production - consumption);
+		energyChart.updatePieSeries("Production", production);
+		energyChart.updatePieSeries("Consumption", consumption);
+		energyChart.updatePieSeries("No Data", production + consumption == 0 ? 1 : 0);
+		differenceEnergyLabelAmount.setText(Format.doubleFixedPlaces(1, difference));
+
+		// UPDATE FLEXIBILITIES
+		int inUse = 0;
+		int offered = 0;
+		int onCooldown = 0;
+		int notOffered = 0;
+		int unavailable = 0;
+
+		List<Flexibility> flexList = filteredHolonElements.stream().flatMap(ele -> ele.flexList.stream()).toList();
+		for (Flexibility flex : flexList) {
+			switch (flex.getState()) {
+				case IN_USE -> inUse++;
+				case NOT_OFFERED -> notOffered++;
+				case OFFERED -> offered++;
+				case ON_COOLDOWN -> onCooldown++;
+				case UNAVAILABLE -> unavailable++;
+				default -> {
+				}
+			}
+		}
+		int noFlexibility = (int)filteredHolonElements.stream().filter(ele -> ele.flexList.isEmpty()).count();
+		flexibilityChart.updatePieSeries("No flexibility", noFlexibility);
+		flexibilityChart.updatePieSeries("Offered", offered);
+		flexibilityChart.updatePieSeries("In use", inUse);
+		flexibilityChart.updatePieSeries("On cooldown", onCooldown);
+		flexibilityChart.updatePieSeries("Not offered", notOffered);
+		flexibilityChart.updatePieSeries("Unavailable", unavailable);
+		boolean hasFlex = noFlexibility + offered + inUse + onCooldown + notOffered + unavailable > 0;
+		flexibilityChart.updatePieSeries("No Data", hasFlex ? 0 : 1);
+
+		Map<Boolean, Long> activeCounts = filteredHolonElements.stream()
+				.collect(Collectors.groupingBy(HolonElement::isOn, Collectors.counting()));
+
+		// UPDATE ActiveInActive
+		int activeAmount = Math.toIntExact(activeCounts.getOrDefault(true, 0L));
+		int inactiveAmounts = Math.toIntExact(activeCounts.getOrDefault(false, 0L));
+		activeChart.updatePieSeries("Active", activeAmount);
+		activeChart.updatePieSeries("Inactive", inactiveAmounts);
+		activeChart.updatePieSeries("No Data", activeAmount + inactiveAmounts == 0 ? 1 : 0);
 		this.revalidate();
 		this.repaint();
 	}
 
 
-	private Optional<FilterableGroupNode> multiSelectionToFilterableGroupNode() {
-//		FilterableGroupNode temp = new FilterableGroupNode(new GroupNode("Temp"),
-//				control.getModel().getCurrentIteration());
-
-//		Optional<VisualRepresentationalState> visState = control.getSimManager().getActualVisualRepresentationalState();
-//		if(visState.isEmpty()) {
-//			return Optional.empty();
-//		}
-//		
-//		// GroupNodes
-//		HashMap<GroupNode, DecoratedGroupNode> accessMapGroupNode = visState.get().getCreatedGroupNodes();
-//		List<FilterableGroupNode> groupNodeList = GuiSettings.getSelectedObjects().stream()
-//				.filter(object -> object instanceof GroupNode).map(object -> accessMapGroupNode.get(object))
-//				.map(node -> new FilterableGroupNode(node, control.getModel().getCurrentIteration()))
-//				.collect(Collectors.toList());
-//
-//		temp.getGroupNodeList().addAll(groupNodeList);
-//
-//		// HolonObjects
-//		HashMap<HolonObject, DecoratedHolonObject> accessMapHolonObject = visState.get().createdHolonObjects;
-//		List<DecoratedHolonObject> holonObjectList = GuiSettings.getSelectedObjects().stream()
-//				.filter(object -> object instanceof HolonObject).map(object -> accessMapHolonObject.get(object))
-//				.collect(Collectors.toList());
-//
-//		for (DecoratedHolonObject object : holonObjectList) {
-//			switch (object.getState()) {
-//			case NO_ENERGY:
-//				temp.getPassivList().add((Passiv) object);
-//				break;
-//			case PRODUCER:
-//				temp.getSupplierList().add((Supplier) object);
-//				break;
-//			default:
-//				temp.getConsumerList().add((Consumer) object);
-//				break;
-//			}
-//		}
-//		return Optional.of(temp);
-		return Optional.empty();
+	private JPopupMenu createHolonStateSelection(){
+		JPopupMenu menu = new JPopupMenu();
+		producerCheckBox.addActionListener(clicked -> updateCharts());
+		overSuppliedCheckBox.addActionListener(clicked -> updateCharts());
+		suppliedCheckBox.addActionListener(clicked -> updateCharts());
+		partiallySuppliedCheckBox.addActionListener(clicked -> updateCharts());
+		notSuppliedCheckBox.addActionListener(clicked -> updateCharts());
+		noEnergyCheckBox.addActionListener(clicked -> updateCharts());
+		menu.add(producerCheckBox);
+		menu.add(overSuppliedCheckBox);
+		menu.add(suppliedCheckBox);
+		menu.add(partiallySuppliedCheckBox);
+		menu.add(notSuppliedCheckBox);
+		menu.add(noEnergyCheckBox);
+		return menu;
+	}
+
+	private JPopupMenu createPrioritySelection(){
+		JPopupMenu menu = new JPopupMenu();
+		essentialCheckBox.addActionListener(clicked -> updateCharts());
+		highCheckBox.addActionListener(clicked -> updateCharts());
+		mediumBox.addActionListener(clicked -> updateCharts());
+		lowCheckBox.addActionListener(clicked -> updateCharts());
+		menu.add(essentialCheckBox);
+		menu.add(highCheckBox);
+		menu.add(mediumBox);
+		menu.add(lowCheckBox);
+		return menu;
+	}
+	private JPopupMenu createActiveSelection(){
+		JPopupMenu menu = new JPopupMenu();
+		activeCheckBox.addActionListener(clicked -> updateCharts());
+		inactiveCheckBox.addActionListener(clicked -> updateCharts());
+		menu.add(activeCheckBox);
+		menu.add(inactiveCheckBox);
+		return menu;
+	}
+
+	private JPopupMenu createFlexibilitySelection(){
+		JPopupMenu menu = new JPopupMenu();
+		noFlexibilityCheckBox.addActionListener(clicked -> updateCharts());
+		offeredCheckBox.addActionListener(clicked -> updateCharts());
+		notOfferedCheckBox.addActionListener(clicked -> updateCharts());
+		unavailableCheckBox.addActionListener(clicked -> updateCharts());
+		inUseCheckBox.addActionListener(clicked -> updateCharts());
+		onCooldownCheckBox.addActionListener(clicked -> updateCharts());
+		menu.add(noFlexibilityCheckBox);
+		menu.add(offeredCheckBox);
+		menu.add(notOfferedCheckBox);
+		menu.add(unavailableCheckBox);
+		menu.add(inUseCheckBox);
+		menu.add(onCooldownCheckBox);
+		return menu;
+	}
+
+
+	private JPanel initMenuButtonPanel(JPopupMenu menu){
+		JPanel buttonPanel = new JPanel(new BorderLayout());
+		MenuButton button = new MenuButton(new ImageIcon(Import.loadImage(ImagePreference.HolonInformationPanel.Filter, 20, 20)), menu);
+		buttonPanel.add(button, BorderLayout.LINE_END);
+		buttonPanel.setOpaque(false);
+		button.setPressedIcon(new ImageIcon(Import.loadImage(ImagePreference.HolonInformationPanel.FilterHovered, 20, 20)));
+		button.setRolloverIcon(new ImageIcon(Import.loadImage(ImagePreference.HolonInformationPanel.FilterHovered, 20, 20)));
+		button.setBorderPainted(false);
+		button.setBorder(null);
+		button.setFocusable(false);
+		button.setMargin(new Insets(0, 0, 0, 0));
+		button.setContentAreaFilled(false);
+		return buttonPanel;
+	}
+
+
+
+	private boolean stateFilter(HolonObject holonObject){
+		return switch (holonObject.getState())	{
+			case PRODUCER -> producerCheckBox.isSelected();
+			case OVER_SUPPLIED -> overSuppliedCheckBox.isSelected();
+			case SUPPLIED -> suppliedCheckBox.isSelected();
+			case PARTIALLY_SUPPLIED -> partiallySuppliedCheckBox.isSelected();
+			case NOT_SUPPLIED -> notSuppliedCheckBox.isSelected();
+			case NO_ENERGY -> noEnergyCheckBox.isSelected();
+		};
+ 	}
+
+	private boolean priorityFilter(HolonElement ele){
+		return switch (ele.priority)	{
+			case Essential -> essentialCheckBox.isSelected();
+			case High -> highCheckBox.isSelected();
+			case Medium -> mediumBox.isSelected();
+			case Low -> lowCheckBox.isSelected();
+		};
+	}
+
+	private boolean activeFilter(HolonElement ele){
+		return ele.active ? activeCheckBox.isSelected(): inactiveCheckBox.isSelected();
+	}
+
+	private boolean flexibilityFilter(HolonElement ele){
+		if(ele.flexList.isEmpty()){
+			return noFlexibilityCheckBox.isSelected();
+		}
+		Map<Flexibility.FlexState,Long> flexes =  ele.flexList.stream().collect(Collectors.groupingBy(Flexibility::getState, Collectors.counting()));
+		return  flexes.keySet().stream().anyMatch(flexState -> switch (flexState)	{
+			case IN_USE -> inUseCheckBox.isSelected();
+			case UNAVAILABLE -> unavailableCheckBox.isSelected();
+			case OFFERED -> offeredCheckBox.isSelected();
+			case NOT_OFFERED -> notOfferedCheckBox.isSelected();
+			case ON_COOLDOWN -> onCooldownCheckBox.isSelected();
+		});
 	}
 
 
-	public void initGraphPanel() {
+
+
+	public static class MenuButton extends JToggleButton {
+
+		JPopupMenu popup;
+
+		public MenuButton(Icon icon, JPopupMenu menu) {
+			super(icon);
+			this.popup = menu;
+			addActionListener(clicked -> {
+				if (MenuButton.this.isSelected()) {
+					popup.show(MenuButton.this, 0, MenuButton.this.getBounds().height);
+				} else {
+					popup.setVisible(false);
+				}
+			});
+			popup.addPopupMenuListener(new PopupMenuListener() {
+				@Override
+				public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
+				@Override
+				public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+					MenuButton.this.setSelected(false);
+				}
+				@Override
+				public void popupMenuCanceled(PopupMenuEvent e) {}
+			});
+		}
+	}
+
+
+
+	private void initGraphPanel() {
 		graphPanel.setBackground(ColorPreference.Panel.Background);
-		panelHolonObject = new XChartPanel<PieChart>(supplyChart);
+		XChartPanel<PieChart> panelHolonObject = new XChartPanel<>(supplyChart);
+		panelHolonObject.setLayout(new BorderLayout());
+		panelHolonObject.add(initMenuButtonPanel(createHolonStateSelection()), BorderLayout.PAGE_START);
 		panelHolonObject.setBackground(ColorPreference.Panel.Background);
 		graphPanel.add(panelHolonObject);
-		panelPriority = new XChartPanel<PieChart>(priorityChart);
+		XChartPanel<PieChart> panelPriority = new XChartPanel<>(priorityChart);
+		panelPriority.setLayout(new BorderLayout());
+		panelPriority.add(initMenuButtonPanel(createPrioritySelection()), BorderLayout.PAGE_START);
 		panelPriority.setBackground(ColorPreference.Panel.Background);
 		graphPanel.add(panelPriority);
-		panelFlexibility = new XChartPanel<PieChart>(flexibilityChart);
+		XChartPanel<PieChart> panelFlexibility = new XChartPanel<>(flexibilityChart);
+		panelFlexibility.setLayout(new BorderLayout());
+		panelFlexibility.add(initMenuButtonPanel(createFlexibilitySelection()), BorderLayout.PAGE_START);
 		panelFlexibility.setBackground(ColorPreference.Panel.Background);
 		graphPanel.add(panelFlexibility);
 		Component panel = initEnergyChart();
 		graphPanel.add(panel);
-		panelActive = new XChartPanel<PieChart>(activeChart);
+		XChartPanel<PieChart> panelActive = new XChartPanel<>(activeChart);
+		panelActive.setLayout(new BorderLayout());
+		panelActive.add(initMenuButtonPanel(createActiveSelection()), BorderLayout.PAGE_START);
 		panelActive.setBackground(ColorPreference.Panel.Background);
-		panelActive.setLayout(new GridBagLayout());
 		graphPanel.add(panelActive);
 		graphPanel.setBorder(BorderFactory.createLineBorder(Color.lightGray));
 	}
@@ -258,7 +370,7 @@ public class HolonInformationPanel extends JPanel {
 	private JLayeredPane initEnergyChart() {
 		JLayeredPane panel = new JLayeredPane();
 		JPanel panelMiddle = new JPanel(new GridBagLayout());
-		panelEnergy = new XChartPanel<PieChart>(energyChart);
+		XChartPanel<PieChart> panelEnergy = new XChartPanel<>(energyChart);
 		panelEnergy.setBackground(ColorPreference.Panel.Background);
 		GridBagConstraints c = new GridBagConstraints();
 		c.gridx = 0;
@@ -310,7 +422,7 @@ public class HolonInformationPanel extends JPanel {
 	}
 
 	public PieChart createSupplyStateChart() {
-		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Holon Objects").build();
+		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("HolonObjects").build();
 		setDefaultPieChartSettings(chart);
 
 		chart.getStyler().setSeriesColors(supplyStateColors);
@@ -322,11 +434,12 @@ public class HolonInformationPanel extends JPanel {
 		chart.addSeries("Partial supplied", 0);
 		chart.addSeries("Not supplied", 0);
 		chart.addSeries("No energy", 0);
+		chart.addSeries("No Data", 0);
 		return chart;
 	}
 
 	public PieChart createPriorityChart() {
-		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Priotities").build();
+		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Priorities").build();
 		setDefaultPieChartSettings(chart);
 		// Customize Chart
 
@@ -352,6 +465,7 @@ public class HolonInformationPanel extends JPanel {
 		chart.addSeries("On cooldown", 0);
 		chart.addSeries("Not offered", 0);
 		chart.addSeries("Unavailable", 0);
+		chart.addSeries("No flexibility", 0);
 		chart.addSeries("No Data", 0);
 		return chart;
 	}
@@ -368,6 +482,7 @@ public class HolonInformationPanel extends JPanel {
 		// Series
 		chart.addSeries("Production", 0);
 		chart.addSeries("Consumption", 0);
+		chart.addSeries("No Data", 0);
 		return chart;
 	}
 
@@ -381,6 +496,7 @@ public class HolonInformationPanel extends JPanel {
 		// Series
 		chart.addSeries("Active", 0);
 		chart.addSeries("Inactive", 0);
+		chart.addSeries("No Data", 0);
 		return chart;
 	}
 }

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

@@ -240,7 +240,7 @@ public class InspectorTable extends JPanel {
 					.map(obj -> (HolonObject) obj);
 			last.ifPresent(obj -> {
 				obj.add(new HolonElement(obj, "Element", 0.0f));
-				control.calculateStateAndVisualForCurrentTimeStep();
+				control.calculateStateForCurrentIteration();
 				updateInspectorUi();
 			});
 		});
@@ -254,7 +254,7 @@ public class InspectorTable extends JPanel {
 					row.element.parentObject.add(new HolonElement(row.element));
 				}
 			});
-			control.calculateStateAndVisualForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 			updateInspectorUi();
 		});
 		buttonPanel.add(duplicateButton);
@@ -267,7 +267,7 @@ public class InspectorTable extends JPanel {
 					row.element.parentObject.remove(row.element);
 				}
 			});
-			control.calculateStateAndVisualForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 			updateInspectorUi();
 		});
 		buttonPanel.add(deleteButton);
@@ -478,7 +478,7 @@ public class InspectorTable extends JPanel {
 					float energy = Float.parseFloat(energyTextField.getText());
 					if (this.element.getEnergy() != energy) {
 						this.element.setEnergy(energy);
-						control.calculateStateAndVisualForCurrentTimeStep();
+						control.calculateStateForCurrentIteration();
 					}
 				} catch (NumberFormatException e) {
 					// Dont Update
@@ -507,7 +507,7 @@ public class InspectorTable extends JPanel {
 			activeCheckBox.setOpaque(false);
 			activeCheckBox.addActionListener(actionEvent -> {
 				this.element.active = activeCheckBox.isSelected();
-				control.calculateStateAndVisualForCurrentTimeStep();
+				control.calculateStateForCurrentIteration();
 			});
 			checkBoxWrapperPanel.add(activeCheckBox, BorderLayout.CENTER);
 			cellsInRow[6] = checkBoxWrapperPanel;

+ 3 - 0
src/holeg/ui/view/main/Gui.java

@@ -284,6 +284,9 @@ public class Gui extends JFrame {
             cutButton.addActionListener(clicked -> control.cut());
             pasteButton.addActionListener(clicked -> paste());
 
+            undoButton.addActionListener(clicked -> control.undo());
+            redoButton.addActionListener(clicked -> control.redo());
+
             removeButton.addActionListener(clicked -> removeSelectedObjects());
 
             String tkWikiWebpage = "https://git.tk.informatik.tu-darmstadt.de/carlos.garcia/praktikum-holons/wiki/";

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

@@ -121,7 +121,7 @@ public class TimePanel extends JPanel implements ActionListener {
 
 		this.setBorder(null);
 		timeSlider.addChangeListener(changeEvent -> {
-			control.calculateStateAndVisualForTimeStep(timeSlider.getValue());
+			control.calculateStateForCurrentIterationAndBroadcastCanvasUpdate(timeSlider.getValue());
 		});
 
 		timeSlider.addMouseListener(new MouseAdapter() {
@@ -165,7 +165,7 @@ public class TimePanel extends JPanel implements ActionListener {
 				timeSlider.setValue(timeSlider.getMinimum());
 				control.getModel().setCurrentIteration(timeSlider.getValue());
 				control.resetSimulation();
-				control.calculateStateAndVisualForCurrentTimeStep();
+				control.calculateStateForCurrentIteration();
 				if (running) {
 					play();
 				}
@@ -303,7 +303,7 @@ public class TimePanel extends JPanel implements ActionListener {
 			public void actionPerformed(ActionEvent e) {
 				timeSlider.setValue(timeSlider.getValue() - 1);
 				control.resetSimulation();
-				control.calculateStateAndVisualForCurrentTimeStep();
+				control.calculateStateForCurrentIteration();
 			}
 		});
 

+ 3 - 4
src/holeg/ui/view/window/FlexWindow.java

@@ -58,7 +58,6 @@ import holeg.model.HolonObject;
 import holeg.preferences.ColorPreference;
 import holeg.preferences.ImagePreference;
 import holeg.ui.controller.Control;
-import holeg.model.Model;
 import holeg.ui.view.image.Import;
 import holeg.utility.listener.WindowClosingListener;
 
@@ -226,7 +225,7 @@ public class FlexWindow extends JFrame {
 			listPanel.add(labelButton, c);
 			labelButton.addActionListener(clicked ->{
 				flex.order();
-				control.calculateStateAndVisualForCurrentTimeStep();
+				control.calculateStateForCurrentIteration();
 			});
 			labelButton.setToolTipText(createToolTipp(flex));
 			i++;
@@ -443,7 +442,7 @@ public class FlexWindow extends JFrame {
 		Flexibility toDeleteFlex =(Flexibility) JOptionPane.showInputDialog(this, "Select to Delete Flexibility:", "Flexibility?",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , allFlexes, "");
 		if(toDeleteFlex != null) {
 			toDeleteFlex.getElement().flexList.remove(toDeleteFlex);
-			control.calculateStateOnlyForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 			updateSelectedPanel();
 		}
 	}
@@ -656,7 +655,7 @@ public class FlexWindow extends JFrame {
 			this.offConstrain = offConstrainCheckBox.isSelected();
 			
 			
-			control.calculateStateOnlyForCurrentTimeStep();
+			control.calculateStateForCurrentIteration();
 			
 			update();
 			addDialog.dispose();