Browse Source

Merge branch 'XChart-integration' into updateInProgress

Conflicts:
	.gitignore
	src/api/AlgorithmFrameworkFlex.java
	src/classes/HolonElement.java
	src/ui/controller/Control.java
	src/ui/controller/ObjectController.java
	src/ui/model/Model.java
	src/ui/view/AbstractCanvas.java
	src/ui/view/GUI.java
	src/ui/view/GroupNodeCanvas.java
	src/ui/view/MyCanvas.java
	src/ui/view/Outliner.java
	src/utility/Action.java
	src/utility/Event.java
	tests/tests/PraktikumHolonsTestObjectController.java
TomTroppmann 2 years ago
parent
commit
b126d8e52d
34 changed files with 7446 additions and 278 deletions
  1. 7 0
      .gitignore
  2. 74 0
      jars/xchart-3.8.1/CONTRIBUTORS
  3. 202 0
      jars/xchart-3.8.1/LICENSE
  4. 14 0
      jars/xchart-3.8.1/NOTICE
  5. 595 0
      jars/xchart-3.8.1/README.md
  6. BIN
      jars/xchart-3.8.1/xchart-3.8.1-custom.jar
  7. 0 1
      src/TypeAdapter/AbstractCpsObjectAdapter.java
  8. 11 11
      src/addOns/InformationPanel.java
  9. 1 1
      src/addOns/Randomizer.java
  10. 1 1
      src/addOns/Utility/HolonElementSketch.java
  11. 5 5
      src/algorithm/binary/AcoAlgorithm.java
  12. 13 13
      src/algorithm/binary/GaAlgorithm.java
  13. 14 14
      src/algorithm/binary/PsoAlgorithm.java
  14. 1 1
      src/algorithm/objectiveFunction/ObjectiveFunctionByCarlos.java
  15. 14 14
      src/api/AlgorithmFrameworkFlex.java
  16. 1 1
      src/classes/HolonElement.java
  17. 49 0
      src/preferences/ColorPreference.java
  18. 2 10
      src/ui/controller/Control.java
  19. 2 0
      src/ui/controller/LoadController.java
  20. 1 8
      src/ui/controller/ObjectController.java
  21. 120 44
      src/ui/model/DecoratedGroupNode.java
  22. 0 18
      src/ui/model/Model.java
  23. 16 8
      src/ui/model/VisualRepresentationalState.java
  24. 430 0
      src/ui/view/AbstractCanvas.java.orig
  25. 2686 0
      src/ui/view/GUI.java.orig
  26. 1272 0
      src/ui/view/GroupNodeCanvas.java.orig
  27. 417 0
      src/ui/view/HolonInformationPanel.java.orig
  28. 1126 0
      src/ui/view/MyCanvas.java.orig
  29. 244 0
      src/ui/view/Outliner.java.orig
  30. 0 1
      src/ui/view/canvas/Canvas.java
  31. 0 2
      src/ui/view/canvas/GroupNodeCanvas.java
  32. 0 1
      src/ui/view/main/GUI.java
  33. 127 124
      src/utility/ImageImport.java
  34. 1 0
      tests/tests/PraktikumHolonsTestObjectController.java

+ 7 - 0
.gitignore

@@ -135,3 +135,10 @@ dist/
 nbdist/
 .nb-gradle/
 
+<<<<<<< HEAD
+=======
+### added manually ###
+.idea/
+praktikum-holons.iml
+/target/
+>>>>>>> refs/heads/XChart-integration

+ 74 - 0
jars/xchart-3.8.1/CONTRIBUTORS

@@ -0,0 +1,74 @@
+XChart is developed by Knowm Inc. members and the open-source community.
+
+We thank all of our contributors: https://github.com/timmolter/xchart/graphs/contributors 
+
+For the detailed history of contributions of a given file, try
+
+    git blame file
+
+To see line-by-line credits and to see the change log even across renames and rewrites, try
+
+    git log --follow file
+
+Copyright is held by the original contributor according to the versioning history; see NOTICE.
+
+The following list of authors was automatically generated from the XChart project's git repo with the command:
+
+    git log --format='%aN' | sort -u
+
+Adam Walsh
+Alex Kofke
+Alex Nugent
+AlexanderRadaev
+Anthony Quiros
+Arthur Peters
+Bryan Cardillo
+Bryn Jeffries
+Carlos Lopez-Camey
+Chiamh
+Christoffer SOOP
+Colm Costelloe
+Damian Szczypior
+Ekkart Kleinod
+Emil Sauer Lynge
+Hakan
+Hakan Işıktekin
+Hongjia Cao
+Hua Shao
+Hwaipy Li
+Jean Niklas L'orange
+Jonathan Leitschuh
+Juha-Matti Tilli
+Marc Jakobi
+Marshall Pierce
+Martin Crawford
+Matan Rubin
+Michael Stummvoll
+Mike Jensen
+Mr14huashao
+Mykola Makhin
+Nathan Klick
+Nicolas Roduit
+Niklas Polke
+Ross Jourdain
+Roughy
+Sylvain Furt
+Thomas Diesler
+Thomas Neidhart
+Tim Molter
+Tomas Svensson
+Tornai András, PMK-ACS-SWA
+alessiosavi
+alexmaycon
+dependabot-preview[bot]
+dependabot[bot]
+gitkonst
+hakantkn
+heavySea
+kalan
+kibertoad
+rebaomi
+ruX[Ruslan Zaharov]
+timmolter
+yuan
+

+ 202 - 0
jars/xchart-3.8.1/LICENSE

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!) The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 14 - 0
jars/xchart-3.8.1/NOTICE

@@ -0,0 +1,14 @@
+Copyright 2015-2018 Knowm Inc. (http://knowm.org) and contributors.
+Copyright 2011-2015 Xeiam LLC (http://xeiam.com) and contributors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

+ 595 - 0
jars/xchart-3.8.1/README.md

@@ -0,0 +1,595 @@
+## [![XChart](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_64_64.png)](http://knowm.org/open-source/xchart) XChart
+
+XChart is a light weight Java library for plotting data.
+
+## Description
+
+XChart is a light-weight and convenient library for plotting data designed to go from data to chart in the least amount of time possible and to take the guess-work out of customizing the chart style.
+
+## Simplest Example
+
+Create a `XYChart` instance via `QuickChart`, add a series of data to it, and either display it or save it as a bitmap.  
+
+```java
+
+double[] xData = new double[] { 0.0, 1.0, 2.0 };
+double[] yData = new double[] { 2.0, 1.0, 0.0 };
+
+// Create Chart
+XYChart chart = QuickChart.getChart("Sample Chart", "X", "Y", "y(x)", xData, yData);
+
+// Show it
+new SwingWrapper(chart).displayChart();
+
+// Save it
+BitmapEncoder.saveBitmap(chart, "./Sample_Chart", BitmapFormat.PNG);
+
+// or save it in high-res
+BitmapEncoder.saveBitmapWithDPI(chart, "./Sample_Chart_300_DPI", BitmapFormat.PNG, 300);
+```
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Simplest.png)
+
+## Intermediate Example
+
+Create a `XYChart` via a `XYChartBuilder`, style chart, add a series to it, style series, and display chart.
+
+```java
+
+// Create Chart
+XYChart chart = new XYChartBuilder().width(600).height(500).title("Gaussian Blobs").xAxisTitle("X").yAxisTitle("Y").build();
+
+// Customize Chart
+chart.getStyler().setDefaultSeriesRenderStyle(XYSeriesRenderStyle.Scatter);
+chart.getStyler().setChartTitleVisible(false);
+chart.getStyler().setLegendPosition(LegendPosition.InsideSW);
+chart.getStyler().setMarkerSize(16);
+
+// Series
+chart.addSeries("Gaussian Blob 1", getGaussian(1000, 1, 10), getGaussian(1000, 1, 10));
+XYSeries series = chart.addSeries("Gaussian Blob 2", getGaussian(1000, 1, 10), getGaussian(1000, 0, 5));
+series.setMarker(SeriesMarkers.DIAMOND);
+
+new SwingWrapper(chart).displayChart();
+```
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Intermediate.png)
+
+## Advanced Example
+
+Create a `XYChart` via a `XYChartBuilder`, style chart, add a series to it, add chart to `XChartPanel`, embed in Java Swing App, and display GUI.
+
+```java
+
+// Create Chart
+final XYChart chart = new XYChartBuilder().width(600).height(400).title("Area Chart").xAxisTitle("X").yAxisTitle("Y").build();
+
+// Customize Chart
+chart.getStyler().setLegendPosition(LegendPosition.InsideNE);
+chart.getStyler().setDefaultSeriesRenderStyle(XYSeriesRenderStyle.Area);
+
+// Series
+chart.addSeries("a", new double[] { 0, 3, 5, 7, 9 }, new double[] { -3, 5, 9, 6, 5 });
+chart.addSeries("b", new double[] { 0, 2, 4, 6, 9 }, new double[] { -1, 6, 4, 0, 4 });
+chart.addSeries("c", new double[] { 0, 1, 3, 8, 9 }, new double[] { -2, -1, 1, 0, 1 });
+
+// Schedule a job for the event-dispatching thread:
+// creating and showing this application's GUI.
+javax.swing.SwingUtilities.invokeLater(new Runnable() {
+
+  @Override
+  public void run() {
+
+    // Create and set up the window.
+    JFrame frame = new JFrame("Advanced Example");
+    frame.setLayout(new BorderLayout());
+    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+    // chart
+    JPanel chartPanel = new XChartPanel<XYChart>(chart);
+    frame.add(chartPanel, BorderLayout.CENTER);
+
+    // label
+    JLabel label = new JLabel("Blah blah blah.", SwingConstants.CENTER);
+    frame.add(label, BorderLayout.SOUTH);
+
+    // Display the window.
+    frame.pack();
+    frame.setVisible(true);
+  }
+});
+
+```
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Advanced.png)
+
+To make it real-time, simply call `updateXYSeries` on the `XYChart` instance to update the series data, followed by `revalidate()` and `repaint()` on the `XChartPanel` instance to repaint.
+
+## Features
+
+* [x] No *required* additional dependencies
+* [x] Multiple Y-Axis charts
+* [x] Line charts
+* [x] Step charts
+* [x] Scatter charts
+* [x] Area charts
+* [x] Step Area charts
+* [x] Bar charts
+* [x] Histogram charts
+* [x] Pie charts
+* [x] Donut charts
+* [x] Bubble charts
+* [x] Stick charts
+* [x] Dial charts
+* [x] Radar charts
+* [x] OHLC charts
+* [x] Box charts
+* [x] Heat maps
+* [x] Error bars
+* [x] Logarithmic axes
+* [x] Number, Date, Bubble and Category X-Axis
+* [x] Multiple series
+* [x] Tool tips
+* [x] Extensive customization
+* [x] Themes - XChart, GGPlot2, Matlab
+* [x] Right-click, Save-As...
+* [x] User-defined axes range
+* [x] Definable legend placement
+* [x] CSV import and export
+* [x] High resolution chart export
+* [x] Export as PNG, JPG, BMP, GIF with custom DPI setting
+* [x] Export SVG, EPS using optional `de.erichseifert.vectorgraphics2d` library
+* [x] Export PDF using optional `pdfbox-graphics2d` library
+* [x] Real-time charts
+* [x] Java 8 and up
+
+## Chart Types
+
+Currently, there are 5 major chart types. Each type has its corresponding `ChartBuilder`, `Styler` and `Series`.
+
+| Chart Type | Builder | Styler | Series | Allowed Data Types | Default Series Render Style |
+|---|---|---|---|---|---|
+| XYChart | XYChartBuilder | XYStyler | XYSeries | Number, Date | Line |
+| CategoryChart | CategoryChartBuilder | CategoryStyler | CategorySeries | Number, Date, String | Bar |
+| PieChart | PieChartBuilder | PieStyler | PieSeries | String | Pie |
+| BubbleChart | BubbleChartBuilder | BubbleStyler | BubbleSeries | Number, Date | Round |
+| DialChart | DialChartBuilder | DialStyler | DialSeries | double  | Round |
+| RadarChart | RadarChartBuilder | RadarStyler | RadarSeries | double[] | Round |
+| OHLCChart | OHLCChartBuilder | OHLCStyler | OHLCSeries | OHLC with Date | Candle |
+| BoxChart | BoxChartBuilder | BoxStyler | BoxSeries | Number, Date, String | Box |
+| HeatMapChart | HeatMapChartBuilder | HeatMapStyler | HeatMapSeries | Number, Date, String | -- |
+
+The different Stylers contain chart styling methods specific to the corresponding chart type as well as common styling methods common across all chart types.
+
+### XYChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_XYChart.png)
+
+`XYChart` charts take Date or Number data types for the X-Axis and Number data types for the Y-Axis. For both axes, the tick marks are auto generated to span the range and domain of the data in evenly-spaced intervals. 
+
+Series render styles include: `Line`, `Scatter`, `Area`, `Step` and `StepArea`.
+
+### CategoryChart 
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_CategoryChart.png)
+
+`CategoryChart` charts take Date, Number or String data types for the X-Axis and Number data types for the Y-Axis. For the X-Axis, each category is given its own tick mark.  
+
+Series render styles include: `Bar`, `Line`, `Scatter`, `Area` and `Stick`.
+
+### PieChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_PieChart.png)
+
+`PieChart` charts take String data types for the pie slice name and Number data types for the pie slice value.  
+
+Series render styles include: `Pie` and `Donut`.
+
+### BubbleChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Bubble_Chart.png)
+
+`BubbleChart` charts take Date or Number data types for the X-Axis and Number data types for the Y-Axis and bubble sizes. 
+
+Series render styles include: `Round` and in the near future `Square`.
+
+### DialChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Dial_Chart.png)
+
+`DialChart` charts take a `double` to set the position of the dial pointer.
+
+### RadarChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Radar_Chart.png)
+
+`RadarChart` charts take a `double[]` of values between `0` and `1` to set the position of radar node.
+
+Series render styles include: `Polygon` and  `Circle`.
+
+### OHLCChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_OHLC.png)
+
+`OHLCChart` charts take Date data types for the X-Axis and 4 Number data types for the Y-Axis. For both axes, the tick marks are auto generated to span the range and domain of the data in evenly-spaced intervals.
+
+Series render styles include: `Candle`, `HiLo`.
+
+### BoxChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_BoxChart.png)
+
+`BoxChart` charts take String data (seriesNames) types for the X-Axis and Number data types for the Y-Axis. Each box chart is calculated from the corresponding series yData.
+Create a BoxChart via a BoxChartBuilder, style chart, add a series to it.
+```java
+// Create Chart
+BoxChart chart =
+	new BoxChartBuilder().title("box plot demo").build();
+
+// Choose a calculation method
+chart.getStyler().setBoxplotCalCulationMethod(BoxplotCalCulationMethod.N_LESS_1_PLUS_1);
+chart.getStyler().setToolTipsEnabled(true);
+
+// Series
+chart.addSeries("boxOne", Arrays.asList(1,2,3,4));
+new SwingWrapper<BoxChart>(chart).displayChart();
+```
+Four calculation methods for boxplots:  
+- "N_PLUS_1": determine the position of the quartile, where Qi is = i (n + 1) / 4, where i = 1, 2, and 3. n represents the number of items contained in the sequence.
+Calculate the corresponding quartile based on location.
+- "N_LESS_1": Determine the position of the quartile, where Qi is = i (n-1) / 4, where i = 1, 2, and 3. n represents the number of items contained in the sequence.
+Calculate the corresponding quartile based on location.
+- "NP": Determine the position of the quartile, where Qi is np = (i * n) / 4, where i = 1, 2, and 3. n represents the number of items contained in the sequence.
+If np is not an integer, Qi = X [np + 1];
+If np is an integer, Qi = (X [np] + X [np + 1]) / 2.
+- "N_LESS_1_PLUS_1": Determine the position of the quartile, where Qi is = i (n-1) / 4 + 1, where i = 1, 2, 3. n represents the number of items contained in the sequence.
+Calculate the corresponding quartile based on location.
+
+Interquartile range, IQR = Q3-Q1.
+
+Upper whisker = Q3 + 1.5 * IQR = Q3 + 1.5 * (Q3 - Q1), if Upper whisker is greater than the maximum value of yData, Upper whisker = maximum value of yData.
+
+Lower whisker = Q1 - 1.5 * IQR = Q1 - 1.5 * (Q3 -Q1), if the lower whisker is less than the minimum value of yData, the lower whisker = the minimum value of yData.
+
+E.g:
+
+An example of a set of sequence numbers: 12, 15, 17, 19, 20, 23, 25, 28, 30, 33, 34, 35, 36, 37
+- "N_PLUS_1":
+Q1's position = (14 + 1) /4=3.75,
+Q1 = 0.25 × third term + 0.75 × fourth term = 0.25 × 17 + 0.75 × 19 = 18.5;
+- "N_LESS_1":
+Q1's location = (14-1) /4=3.25,
+Q1 = 0.75 × third term + 0.25 × fourth term = 0.75 × 17 + 0.25 × 19 = 17.5;
+- "NP":
+Q1's position = 14 * 0.25 = 3.5,
+Q1 = 19;
+- "N_LESS_1_PLUS_1":
+Q1's location = (14-1) / 4 + 1 = 4.25
+Q1 = 0.75 × the fourth term + 0.25 × the fifth term = 0.75 × 19 + 0.25 × 20 = 19.25.
+
+### HeatMapChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_HeatMap.png)
+
+`HeatMapChart` take Date, Number or String data types for the X-Axis, Y-Axis. 
+
+## Real-time Java Charts using XChart
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_SimpleRealtime.gif)
+
+Creating real-time charts is as simple as calling `updateXYSeries` for one or more series objects through the `XYChart` instance and triggering a redraw of the `JPanel` containing the chart. This works for all chart types including `XYChart`, `CategoryChart`, `BubbleChart` and `PieChart`, for which example source code can be found [here](https://github.com/knowm/XChart/tree/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/realtime). Examples demonstrate using the `SwingWrapper` with `repaintChart()` method as well as `XChartPanel` with `revalidate()` and `repaint()`. 
+
+The following sample code used to generate the above real-time chart can be found [here](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/standalone/readme/SimpleRealTime.java).
+
+```java
+public class SimpleRealTime {
+
+  public static void main(String[] args) throws Exception {
+
+    double phase = 0;
+    double[][] initdata = getSineData(phase);
+
+    // Create Chart
+    final XYChart chart = QuickChart.getChart("Simple XChart Real-time Demo", "Radians", "Sine", "sine", initdata[0], initdata[1]);
+
+    // Show it
+    final SwingWrapper<XYChart> sw = new SwingWrapper<XYChart>(chart);
+    sw.displayChart();
+
+    while (true) {
+
+      phase += 2 * Math.PI * 2 / 20.0;
+
+      Thread.sleep(100);
+
+      final double[][] data = getSineData(phase);
+
+      javax.swing.SwingUtilities.invokeLater(new Runnable() {
+
+        @Override
+        public void run() {
+
+          chart.updateXYSeries("sine", data[0], data[1], null);
+          sw.repaintChart();
+        }
+      });
+    }
+
+  }
+
+  private static double[][] getSineData(double phase) {
+
+    double[] xData = new double[100];
+    double[] yData = new double[100];
+    for (int i = 0; i < xData.length; i++) {
+      double radians = phase + (2 * Math.PI / xData.length * i);
+      xData[i] = radians;
+      yData[i] = Math.sin(radians);
+    }
+    return new double[][] { xData, yData };
+  }
+}
+```
+
+## Chart Customization
+
+All the styling options can be found in one of two possible places: 1) the Chart's `Styler` or 2) the series' `set` methods. With this chart customization design, all customization options can be quickly "discovered" using an IDE's built in "Content Assist". With centralized styling like this, there is no need to hunt around the entire charting API to find that one customization you're looking for - it's all right in one spot!
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Chart_Customization.png)
+ 
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Series_Customization.png)
+ 
+
+### Customizing Axis Tick Labels
+
+XChart automatically creates axis tick labels for chart types with axes. 
+
+Default axis tick placement can be altered with `chart.getStyler().setXAxisTickMarkSpacingHint(spacingHint);`. 
+
+Default axis label labels can be altered with one of:
+
+```java
+chart.getStyler().setDatePattern(datePattern)
+chart.getStyler().setXAxisDecimalPattern(pattern);
+chart.getStyler().setYAxisDecimalPattern(pattern);
+```
+
+
+You can also create custom axis tick labels with a callback function. In the following example taken from [DateChart09](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/date/DateChart09.java), the X-Axis tick labels are generated 
+via a custom lambda function which takes the numerical (double) tick label values and converts them to a `String`.
+
+
+```java
+// set custom X-Axis tick labels
+LocalDateTime startTime = LocalDateTime.of(2001, Month.JANUARY, 1, 0, 0, 0);
+DateTimeFormatter xTickFormatter = DateTimeFormatter.ofPattern("LLL");
+chart.getStyler().setxAxisTickLabelsFormattingFunction(x -> startTime.plusDays(x.longValue()).format(xTickFormatter));
+```
+
+In the following example taken from [DateChart06](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/date/DateChart06.java), the Y-Axis tick labels are converted 
+to the englich word reprentation of the numbers.
+
+```java
+chart.getStyler().setyAxisTickLabelsFormattingFunction(x -> NumberWordConverter.convert(x.intValue()));
+```
+
+### Multiple Axes
+
+XChart has multiple y axes feature. Y offset is calculated according to the Y-Axis the series configured. Max `y` value in this axis is calculated 
+according to the series on this axis only. 
+To set the y group: 
+
+```java
+series.setYAxisGroup(axisGroup);   
+```
+
+To manually change max/min of axis group: 
+
+```java
+((AxesChartStyler) chart.getStyler()).setYAxisMax(axisGroup, 200.0);
+```
+
+Axis can be drawn on the left (default) or on the right of the chart: 
+
+```java
+chart.getStyler().setYAxisGroupPosition(axisGroup, Styler.YAxisPosition.Right);
+```
+
+To set the Y axes titles:
+
+```java
+chart.setYAxisGroupTitle(0, "A");
+chart.setYAxisGroupTitle(1, "B");
+```
+
+### Zooming In
+
+For the `XYChart` chart type, zooming in is possible on an `XChartPanel` via select-dragging over a range on the X-Axis. Reverting out of the zoom can be accomplished by double-clicking on the chart or by clicking on the "reset" button, which can be posotioned as desired. 
+
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Zoom.png)
+
+
+The following example zoom style options show which are available:
+
+```java
+chart.getStyler().setZoomEnabled(true);
+chart.getStyler().setZoomResetButtomPosition(Styler.CardinalPosition.InsideS);
+chart.getStyler().setZoomResetByDoubleClick(false);
+chart.getStyler().setZoomResetByButton(true);
+chart.getStyler().setZoomSelectionColor(new Color(0,0 , 192, 128));
+```
+
+A working example can be found at [DateChart01](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/date/DateChart01.java).
+
+### Chart Annotations
+
+For all chart types, one or more chart annotations can be super-imposed on top of the chart. The following types of annotatins are available:
+
+- AnnotationLine
+- AnnotationImage
+- AnnotationText
+- AnnotationTextPanel
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_AnnotationLineImageText.png)
+
+A working example can be found at [LineChart10](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/line/LineChart10.java).
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_AnnotationTextPanel.png)
+
+A working example can be found at [ScatterChart04](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/scatter/ScatterChart04.java).
+
+### Tool Tips
+
+For all chart types, tool tips can be activated on an `XChartPanel` via 
+
+```java
+chart.getStyler().setToolTipsEnabled(true);
+```
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Tooltips.png)
+
+
+The following example tooltip options show which are available:
+
+```java
+chart.getStyler().setToolTipsEnabled(true);
+chart.getStyler(). setToolTipsAlwaysVisible(true);
+chart.getStyler().setToolTipFont( new Font("Verdana", Font.BOLD, 12));
+chart.getStyler().setToolTipHighlightColor(Color.CYAN);
+chart.getStyler().setToolTipBorderColor(Color.BLACK);
+chart.getStyler(). setToolTipBackgroundColor(Color.LIGHT_GRAY);
+chart.getStyler().setToolTipType(Styler.ToolTipType.xAndYLabels);
+```
+
+A working example can be found at [LineChart05](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/line/LineChart05.java).
+
+### Cursor
+
+For the `XYChart` chart type, it is possible to add an interactive cursor on an `XChartPanel` via
+
+```java
+chart.getStyler().setCursorEnabled(true);
+```
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Cursor.png)
+
+The following example cursor options show which are available:
+
+```java
+chart.getStyler().setCursorEnabled(true);
+chart.getStyler().setCursorColor(Color.GREEN);
+chart.getStyler().setCursorLineWidth(30f);
+chart.getStyler().setCursorFont(new Font("Verdana", Font.BOLD, 12));
+chart.getStyler().setCursorFontColor(Color.ORANGE);
+chart.getStyler().setCursorBackgroundColor(Color.BLUE);
+chart.getStyler().setCustomCursorXDataFormattingFunction(x -> "hello xvalue: " + x);
+chart.getStyler().setCustomCursorYDataFormattingFunction(y -> "hello yvalue divided by 2: " + y / 2);
+```
+
+A working example can be found at [LineChart09](https://github.com/knowm/XChart/blob/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/line/LineChart09.java).
+
+## Chart Themes
+
+XChart ships with three different themes: Default `XChart`, `GGPlot2` and `Matlab`. Using a different theme is as simple as setting the Chart's theme with the `theme` method of the `ChartBuilder`.
+
+    XYChart chart = new XYChartBuilder().width(800).height(600).theme(ChartTheme.Matlab).build();
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Themes.png)
+
+## What's Next?
+
+Now go ahead and [study some more examples](http://knowm.org/open-source/xchart/xchart-example-code/), [download the thing](http://knowm.org/open-source/xchart/xchart-change-log) and [provide feedback](https://github.com/knowm/XChart/issues).
+ 
+## Getting Started
+
+### Non-Maven
+
+Download Jar: http://knowm.org/open-source/xchart/xchart-change-log
+
+### Maven
+
+The XChart release artifacts are hosted on Maven Central.
+
+Add the XChart library as a dependency to your pom.xml file:
+
+```xml
+    <dependency>
+        <groupId>org.knowm.xchart</groupId>
+        <artifactId>xchart</artifactId>
+        <version>3.8.0</version>
+    </dependency>
+```
+
+For snapshots, add the following to your pom.xml file:
+
+```xml
+    <repository>
+      <id>sonatype-oss-snapshot</id>
+      <snapshots/>
+      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+    </repository>
+
+    <dependency>
+      <groupId>org.knowm.xchart</groupId>
+      <artifactId>xchart</artifactId>
+      <version>3.8.1-SNAPSHOT</version>
+    </dependency>
+```
+
+Snapshots can be manually downloaded from Sonatype: [https://oss.sonatype.org/content/groups/public/org/knowm/xchart/xchart/](https://oss.sonatype.org/content/groups/public/org/knowm/xchart/xchart/)
+
+### SBT
+
+To use XChart with the Scala Build Tool (SBT) add the following to your build.sbt
+
+```scala
+libraryDependencies += "org.knowm.xchart" % "xchart" % "3.8.0" exclude("de.erichseifert.vectorgraphics2d", "VectorGraphics2D") withSources()
+```
+
+## Building with Maven
+
+#### general
+
+    mvn clean package  
+    mvn javadoc:aggregate  
+
+#### Formatting
+
+    mvn com.coveo:fmt-maven-plugin:format
+    
+Formats your code using [google-java-format](https://github.com/google/google-java-format) which follows [Google's code styleguide](https://google.github.io/styleguide/javaguide.html).
+
+If you want your IDE to stick to the same format, check out the available configuration plugins:
+
+#### Eclipse
+
+Download [`google-java-format-eclipse-plugin_*.jar`](https://github.com/google/google-java-format/releases) and place in `/Applications/Eclipse Java.app/Contents/Eclipse/dropins`. Restart Eclipse. Select the plugin in `Preferences > Java > Code Style > Formatter > Formatter Implementation`. 
+
+#### IntelliJ
+
+In the plugins section in IntelliJ search for `google-java-format` and install the plugin. Restart IntelliJ.
+
+## Running Demo
+
+- Linux: execute command `java -cp xchart-demo-3.8.0.jar:xchart-3.8.0.jar org.knowm.xchart.demo.XChartDemo`.
+
+- Windows: In the cmd command window, execute the command `java -cp xchart-demo-3.8.0.jar;xchart-3.8.0.jar org.knowm.xchart.demo.XChartDemo`; In the PowerShell command window, execute the command `java -cp "xchart-demo-3.8.0.jar;xchart-3.8.0.jar" org.knowm.xchart.demo.XChartDemo`.
+
+E.g:
+```sh
+cd /path/to/xchart-demo/jar/
+java -cp xchart-demo-3.8.0.jar:xchart-3.8.0.jar org.knowm.xchart.demo.XChartDemo
+```
+
+![](https://raw.githubusercontent.com/knowm/XChart/develop/etc/XChart_Demo.png)
+
+## Bugs
+
+Please report any bugs or submit feature requests to [XChart's Github issue tracker](https://github.com/knowm/XChart/issues).  
+
+## Continuous Integration
+
+[![Build Status](https://travis-ci.org/knowm/XChart.png?branch=develop)](https://travis-ci.org/timmolter/XChart.png)  
+[Build History](https://travis-ci.org/knowm/XChart/builds)  
+

BIN
jars/xchart-3.8.1/xchart-3.8.1-custom.jar


+ 0 - 1
src/TypeAdapter/AbstractCpsObjectAdapter.java

@@ -39,7 +39,6 @@ public class AbstractCpsObjectAdapter
 		} catch (ClassNotFoundException cnfe) {
 			throw new JsonParseException("Unknown element type: " + type, cnfe);
 		}
-
 	}
 
 }

+ 11 - 11
src/addOns/InformationPanel.java

@@ -131,23 +131,23 @@ public class InformationPanel implements AddOn {
 		
 		
 
-		entryList.add(new Entry(() -> Integer.toString(amountHolonObjects), "HolonObjects", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountHolonObjects), "Holon Objects", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountConsumer) + addPercentage(amountConsumer, amountHolonObjects), "\tConsumer", middle));
-		entryList.add(new Entry(() -> Integer.toString(amountUnderSupplied) + addPercentage(amountUnderSupplied, amountConsumer), "\t\tUnderSupplied", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountUnderSupplied) + addPercentage(amountUnderSupplied, amountConsumer), "\t\tUnsupplied", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountPatiallySupplied) + addPercentage(amountPatiallySupplied, amountConsumer), "\t\tPatiallySupplied", middle));
 		entryList.add(new StatEntry(() -> StatToFancyString(partiallySuppliedStats), middle));		
 		entryList.add(new Entry(() -> Integer.toString(amountFullySupplied) + addPercentage(amountFullySupplied, amountConsumer), "\t\tFullySupplied", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountOversupllied) + addPercentage(amountOversupllied, amountConsumer), "\t\tOversupllied", middle));
 		entryList.add(new StatEntry(() -> StatToFancyString(overSuppliedStats), middle));
-		entryList.add(new Entry(() -> Integer.toString(amountSupplier) + addPercentage(amountSupplier, amountHolonObjects), "\tSupplier", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountSupplier) + addPercentage(amountSupplier, amountHolonObjects), "\tProducers", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountPassiv) + addPercentage(amountPassiv, amountHolonObjects), "\tPassiv", middle));
 		addSeperator(middle);
-		entryList.add(new Entry(() -> Integer.toString(amountSwitch), "Switch (not a HolonObject)", middle));
-		entryList.add(new Entry(() -> Integer.toString(amountActiveSwitch) + addPercentage(amountActiveSwitch, amountSwitch), "\t[Active] Switch", middle));
-		entryList.add(new Entry(() -> Integer.toString(amountInactiveSwitch) + addPercentage(amountInactiveSwitch, amountSwitch), "\t[Inactive] Switch", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountSwitch), "Switches", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountActiveSwitch) + addPercentage(amountActiveSwitch, amountSwitch), "\tClosed Switches", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountInactiveSwitch) + addPercentage(amountInactiveSwitch, amountSwitch), "\tOpen Switches", middle));
 		
 		addSeperator(middle);
-		entryList.add(new Entry(() -> Integer.toString(amountHolonElements), "HolonElements", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountHolonElements), "Holon Elements", middle));
 		entryList.add(new Entry(() -> Integer.toString(this.amountElementLow) + addPercentage(amountElementLow, amountHolonElements), "\tLow", middle));
 		entryList.add(new Entry(() -> Integer.toString(this.amountElementMedium) + addPercentage(amountElementMedium, amountHolonElements), "\tMedium", middle));
 		entryList.add(new Entry(() -> Integer.toString(this.amountElementHigh) + addPercentage(amountElementHigh, amountHolonElements), "\tHigh", middle));
@@ -167,8 +167,8 @@ public class InformationPanel implements AddOn {
 		
 		addSeperator(middle);
 		entryList.add(new Entry(() -> Integer.toString(amountFlexibilities), "Flexibilities", middle));
-		entryList.add(new Entry(() -> Integer.toString(amountConsumingFlexibilities) + addPercentage(amountConsumingFlexibilities, amountFlexibilities), "\tConsumingFlexibilities", middle));
-		entryList.add(new Entry(() -> Integer.toString(amountProducingFlexibilities) + addPercentage(amountProducingFlexibilities, amountFlexibilities), "\tProducingFlexibilities", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountConsumingFlexibilities) + addPercentage(amountConsumingFlexibilities, amountFlexibilities), "\tConsuming Flexibilities", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountProducingFlexibilities) + addPercentage(amountProducingFlexibilities, amountFlexibilities), "\tProducing Flexibilities", middle));
 		addSeperator(middle);
 		entryList.add(new Entry(() -> Integer.toString(amountFlexibilities), "Flexibilities", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountLow) + addPercentage(amountLow, amountFlexibilities), "\tLow", middle));
@@ -176,13 +176,13 @@ public class InformationPanel implements AddOn {
 		entryList.add(new Entry(() -> Integer.toString(amountHigh) + addPercentage(amountHigh, amountFlexibilities), "\tHigh", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountEssential) + addPercentage(amountEssential, amountFlexibilities), "\tEssential", middle));
 		addSeperator(middle);
-		entryList.add(new Entry(() -> Integer.toString(amountActiveFlexibilities), "ActiveFlexibilities", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountActiveFlexibilities), "Active Flexibilities", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountActiveLow) + addPercentage(amountActiveLow, amountActiveFlexibilities), "\tLow", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountActiveMedium) + addPercentage(amountActiveMedium, amountActiveFlexibilities), "\tMedium", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountActiveHigh) + addPercentage(amountActiveHigh, amountActiveFlexibilities), "\tHigh", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountActiveEssential) + addPercentage(amountActiveEssential, amountActiveFlexibilities), "\tEssential", middle));
 		addSeperator(middle);
-		entryList.add(new Entry(() -> Integer.toString(amountGroupNodes), "GroupNodes", middle));
+		entryList.add(new Entry(() -> Integer.toString(amountGroupNodes), "Group Nodes", middle));
 		entryList.add(new Entry(() -> Integer.toString(amountHolons), "Holons", middle));
 		
 		return middle;

+ 1 - 1
src/addOns/Randomizer.java

@@ -45,8 +45,8 @@ import classes.GroupNode;
 import classes.HolonElement;
 import classes.HolonObject;
 import ui.controller.Control;
-import utility.Random;
 import utility.ImageImport;
+import utility.Random;
 
 public class Randomizer implements AddOn {
 	private Control  control;

+ 1 - 1
src/addOns/Utility/HolonElementSketch.java

@@ -4,8 +4,8 @@ import classes.Constrain;
 import classes.Flexibility;
 import classes.HolonElement;
 import classes.HolonElement.Priority;
-import classes.HolonObject;
 import utility.Random;
+import classes.HolonObject;
 
 public class HolonElementSketch {
 	//HolonElement

+ 5 - 5
src/algorithm/binary/AcoAlgorithm.java

@@ -27,11 +27,11 @@ public class AcoAlgorithm extends AlgorithmFrameworkFlex{
 	
 	public AcoAlgorithm() {
 		super();
-		addIntParameter("Population", popsize, intValue -> popsize = intValue, () -> popsize, 1);
-		addIntParameter("maxGenerations", maxGenerations, intValue -> maxGenerations = intValue, () -> maxGenerations, 1);
-		addDoubleParameter("Vaporization", p, doubleValue -> p = doubleValue, () -> p, 0.0, 1.0);
-		addDoubleParameter("FactorReset", convergenceFactorReset, doubleValue -> convergenceFactorReset = doubleValue, () -> convergenceFactorReset, 0.0, 1.0);
-		addBooleanParameter("moreInformation", moreInformation, booleanValue -> moreInformation = booleanValue);
+		addIntParameter("Population size", popsize, intValue -> popsize = intValue, () -> popsize, 1);
+		addIntParameter("Generations", maxGenerations, intValue -> maxGenerations = intValue, () -> maxGenerations, 1);
+		addDoubleParameter("Vaporization rate", p, doubleValue -> p = doubleValue, () -> p, 0.0, 1.0);
+		addDoubleParameter("Convergence factor threshold", convergenceFactorReset, doubleValue -> convergenceFactorReset = doubleValue, () -> convergenceFactorReset, 0.0, 1.0);
+		addBooleanParameter("Detailed information", moreInformation, booleanValue -> moreInformation = booleanValue);
 	}
 	
 	

+ 13 - 13
src/algorithm/binary/GaAlgorithm.java

@@ -19,22 +19,22 @@ public class GaAlgorithm extends AlgorithmFrameworkFlex{
 	private double swapProbability = 0.02;
 	private double mutateProbability = 0.02;
 	private boolean useIntervalMutation = false;
-	private double mutateProbabilityInterval = 0.01;
+	//private double mutateProbabilityInterval = 0.01;
 	private double maxMutationPercent = 0.01;
 	private boolean moreInformation = false;
 	
 	
 	public GaAlgorithm() {
 		super();
-		addIntParameter("popsize", popsize, intValue -> popsize = intValue, () -> popsize, 1);
-		addIntParameter("maxGenerations", maxGenerations, intValue -> maxGenerations = intValue, () -> maxGenerations, 1);
-		addDoubleParameter("tournamentSize", tournamentSize, doubleValue -> tournamentSize = doubleValue, () -> tournamentSize, 1.0);
-		addDoubleParameter("SwapProbability", swapProbability, doubleValue -> swapProbability = doubleValue, () -> swapProbability, 0.0, 1.0);
-		addDoubleParameter("MutateProbability", mutateProbability, doubleValue -> mutateProbability = doubleValue, () -> mutateProbability, 0.0, 1.0);
-		addBooleanParameter("useIntervalMutation", useIntervalMutation, booleanValue -> useIntervalMutation = booleanValue);
-		addDoubleParameter("mutateProbabilityInterval", mutateProbabilityInterval, doubleValue -> mutateProbabilityInterval = doubleValue, () -> mutateProbabilityInterval, 0.0, 1.0);
-		addDoubleParameter("maxMutationPercent", maxMutationPercent, doubleValue -> maxMutationPercent = doubleValue, () -> maxMutationPercent, 0.0, 1.0);
-		addBooleanParameter("moreInformation", moreInformation, booleanValue -> moreInformation = booleanValue);
+		addIntParameter("Population size", popsize, intValue -> popsize = intValue, () -> popsize, 1);
+		addIntParameter("Generations", maxGenerations, intValue -> maxGenerations = intValue, () -> maxGenerations, 1);
+		addDoubleParameter("Tournament size", tournamentSize, doubleValue -> tournamentSize = doubleValue, () -> tournamentSize, 1.0);
+		addDoubleParameter("Swap probability", swapProbability, doubleValue -> swapProbability = doubleValue, () -> swapProbability, 0.0, 1.0);
+		addDoubleParameter("Mutation probability", mutateProbability, doubleValue -> mutateProbability = doubleValue, () -> mutateProbability, 0.0, 1.0);
+		addBooleanParameter("Interval-based mutation", useIntervalMutation, booleanValue -> useIntervalMutation = booleanValue);
+		//addDoubleParameter("mutateProbabilityInterval", mutateProbabilityInterval, doubleValue -> mutateProbabilityInterval = doubleValue, () -> mutateProbabilityInterval, 0.0, 1.0);
+		addDoubleParameter("Mutation severity (% of problem size)", maxMutationPercent, doubleValue -> maxMutationPercent = doubleValue, () -> maxMutationPercent, 0.0, 1.0);
+		addBooleanParameter("Detailed Information", moreInformation, booleanValue -> moreInformation = booleanValue);
 	}
 	
 	public static void main(String[] args)
@@ -117,7 +117,7 @@ public class GaAlgorithm extends AlgorithmFrameworkFlex{
 	 */
 	private void mutateInterval(Individual child, int problemSize) {
 		//If not mutate skip
-		if(Random.nextDouble() >  this.mutateProbabilityInterval) {
+		if(Random.nextDouble() >  this.mutateProbability) {
 			return;
 		}
 		//println("problemSize:" + problemSize + "    maxMutationPercent:" + maxMutationPercent);
@@ -238,8 +238,8 @@ public class GaAlgorithm extends AlgorithmFrameworkFlex{
 				+ " TournamentSize: " +  tournamentSize
 				+ " SwapProbability: " +  swapProbability
 				+ (useIntervalMutation? 
-						(" MutateProbabilityInterval: " +  mutateProbabilityInterval
-						+ " MaxMutationPercent: " +  maxMutationPercent)
+						(//" MutateProbabilityInterval: " +  mutateProbabilityInterval
+						" MaxMutationPercent: " +  maxMutationPercent)
 						: 
 						(" MutateProbability: " +  mutateProbability));
 	}

+ 14 - 14
src/algorithm/binary/PsoAlgorithm.java

@@ -13,7 +13,7 @@ public class PsoAlgorithm extends AlgorithmFrameworkFlex{
 	private int swarmSize = 20; 
 	private int maxIterations = 100; 
 	private double dependency = 2.07; 
-	private int mutationInterval = 1;
+	private int mutationIteration = 1;
 	private boolean useIntervalMutation = true;
 	private double mutationRate = 0.01;
 	private double mutateProbabilityInterval = 0.01;
@@ -37,17 +37,17 @@ public class PsoAlgorithm extends AlgorithmFrameworkFlex{
 	
 	public PsoAlgorithm() {
 		super();
-		addIntParameter("swarmSize", swarmSize, intValue -> swarmSize = intValue, () -> swarmSize, 1);
-		addIntParameter("maxIterations", maxIterations, intValue -> maxIterations = intValue, () -> maxIterations, 1);
-		addDoubleParameter("dependency", dependency, doubleValue -> dependency = doubleValue, () -> dependency, 2.001, 2.4);
-		addIntParameter("mutationInterval", mutationInterval, intValue -> mutationInterval = intValue, () -> mutationInterval, 0);
-		addBooleanParameter("useIntervalMutation", useIntervalMutation, booleanValue -> useIntervalMutation = booleanValue);
-		addDoubleParameter("mutateProbabilityInterval", mutateProbabilityInterval, doubleValue -> mutateProbabilityInterval = doubleValue, () -> mutateProbabilityInterval, 0.0, 1.0);
-		addDoubleParameter("mutationRate", mutationRate, doubleValue -> mutationRate = doubleValue, () -> mutationRate, 0.0, 1.0);
-		addDoubleParameter("maxMutationPercent", maxMutationPercent, doubleValue -> maxMutationPercent = doubleValue, () -> maxMutationPercent, 0.0, 1.0);
-		addDoubleParameter("maxVelocity", maxVelocity, doubleValue -> maxVelocity = doubleValue, () -> maxVelocity, 0.0);
+		addIntParameter("Particles", swarmSize, intValue -> swarmSize = intValue, () -> swarmSize, 1);
+		addIntParameter("Iterations", maxIterations, intValue -> maxIterations = intValue, () -> maxIterations, 1);
+		addDoubleParameter("Dependency", dependency, doubleValue -> dependency = doubleValue, () -> dependency, 2.001, 2.4);
+		addIntParameter("Mutation iteration", mutationIteration, intValue -> mutationIteration = intValue, () -> mutationIteration, 0);
+		addBooleanParameter("Interval-based mutation", useIntervalMutation, booleanValue -> useIntervalMutation = booleanValue);
+		addDoubleParameter("Mutation probability (%)", mutateProbabilityInterval, doubleValue -> mutateProbabilityInterval = doubleValue, () -> mutateProbabilityInterval, 0.0, 1.0);
+	//	addDoubleParameter("mutationRate", mutationRate, doubleValue -> mutationRate = doubleValue, () -> mutationRate, 0.0, 1.0);
+		addDoubleParameter("Mutation severity (% of problem size)", maxMutationPercent, doubleValue -> maxMutationPercent = doubleValue, () -> maxMutationPercent, 0.0, 1.0);
+		addDoubleParameter("Velocity", maxVelocity, doubleValue -> maxVelocity = doubleValue, () -> maxVelocity, 0.0);
 		
-		addBooleanParameter("moreInformation", moreInformation , booleanValue -> moreInformation = booleanValue);
+		addBooleanParameter("Detailed information", moreInformation , booleanValue -> moreInformation = booleanValue);
 	}
 	
 
@@ -103,7 +103,7 @@ public class PsoAlgorithm extends AlgorithmFrameworkFlex{
 		evaluation(globalBest, swarm);
 		runList.add(globalBest.fitness);
 		for (int iteration = 0; iteration < maxIterations ; iteration++) {
-			int mutationAllowed = iteration % mutationInterval;
+			int mutationAllowed = iteration % mutationIteration;
 			double bitsFlipped = 0;
 			for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++) {
 				Particle particle = swarm.get(particleNumber);		
@@ -123,7 +123,7 @@ public class PsoAlgorithm extends AlgorithmFrameworkFlex{
 					for(int index = 0; index < dimensions; index++) {
 						updateVelocity(particle, index, globalBest);
 						updateGenotype(particle, index);
-						if(mutationAllowed == 0 && iteration != 0 && Random.nextDouble() < mutationRate) {
+						if(mutationAllowed == 0 && iteration != 0 && Random.nextDouble() < mutateProbabilityInterval) {
 							count++;
 							mutation(particle, index);
 						}
@@ -264,7 +264,7 @@ public class PsoAlgorithm extends AlgorithmFrameworkFlex{
 				+ " maxIterations:" + maxIterations
 				+ " swarmSize:" + swarmSize
 				+ " dependency:" +  dependency
-				+ " mutationInterval:" +  mutationInterval
+				+ " mutationInterval:" +  mutationIteration
 				+ " maxVelocity: " + maxVelocity
 				+ (useIntervalMutation? 
 						(" mutateProbabilityInterval:" +  mutateProbabilityInterval

+ 1 - 1
src/algorithm/objectiveFunction/ObjectiveFunctionByCarlos.java

@@ -46,7 +46,7 @@ public class ObjectiveFunctionByCarlos {
 	 * <br>
 	 *  {@link ObjectiveFunctionByCarlos#squash}
 	 */
-	static double squash_subtract = 1.0f / (1.f + (float) Math.exp(5.0));
+	static double squash_subtract = 100.f / (1.f + (float) Math.exp(5.0));
 	static double range_for_kappa_f_unre = range(kappa_f_unre);
 	static double range_for_kappa_f_cool = range(kappa_f_cool);
 	static double range_for_kappa_f_dur = range(kappa_f_dur);

+ 14 - 14
src/api/AlgorithmFrameworkFlex.java

@@ -183,16 +183,16 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 		useFlexes.addActionListener(actionEvent -> algoUseFlexes = useFlexes.isSelected());
 		parameterPanel.add(useFlexes);
 		
-		JCheckBox useKillSwitches = new JCheckBox("KillSwitch");
-		useKillSwitches.setSelected(algoUseFlexes);
-		useKillSwitches.setBounds(900, 130, 185, 20);
-		useKillSwitches.addActionListener(actionEvent -> 
+		JCheckBox useSmartMeter = new JCheckBox("SmartMeter");
+		useSmartMeter.setSelected(algoUseFlexes);
+		useSmartMeter.setBounds(900, 130, 185, 20);
+		useSmartMeter.addActionListener(actionEvent -> 
 				{
 					cancel();
 					reset();
-					algoUseKillSwitch = useKillSwitches.isSelected();
+					algoUseKillSwitch = useSmartMeter.isSelected();
 				});
-		parameterPanel.add(useKillSwitches);
+		parameterPanel.add(useSmartMeter);
 		
 		String[] objectiveFunctionStrings = { "Normal", "Switch"};
 		JLabel fitnessLabel = new JLabel("FitnessFunction:");
@@ -232,7 +232,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
 		
 		JButton resetButton =  new JButton("Reset");
-		resetButton.setToolTipText("Resets the State to before the Algorithm has runed.");
+		resetButton.setToolTipText("Resets the state to the initial grid configuration.");
 		resetButton.addActionListener(actionEvent -> reset());
 		buttonPanel.add(resetButton);
 		
@@ -240,8 +240,8 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 		cancelButton.addActionListener(actionEvent -> cancel());
 		buttonPanel.add(cancelButton);
 		
-		JButton fitnessButton =  new JButton("Fitness");
-		fitnessButton.setToolTipText("Fitness for the current state.");
+		JButton fitnessButton =  new JButton("Evaluate");
+		fitnessButton.setToolTipText("Evaluate the current grid configuration.");
 		fitnessButton.addActionListener(actionEvent -> fitness());
 		buttonPanel.add(fitnessButton);
 		
@@ -324,7 +324,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 		stepsTextField.setPreferredSize(new Dimension(40, 30));
 		singleParameterPanel.add(stepsTextField);
 		
-		JLabel stepsSizeLabel = new JLabel("StepsSize: ");
+		JLabel stepsSizeLabel = new JLabel("Step size: ");
 		stepsSizeLabel.setEnabled(false);
 		singleParameterPanel.add(stepsSizeLabel);
 		
@@ -418,7 +418,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 		stepsTextField.setPreferredSize(new Dimension(40, 30));
 		singleParameterPanel.add(stepsTextField);
 		
-		JLabel stepsSizeLabel = new JLabel("StepsSize: ");
+		JLabel stepsSizeLabel = new JLabel("Step size: ");
 		stepsSizeLabel.setEnabled(false);
 		singleParameterPanel.add(stepsSizeLabel);
 		
@@ -465,7 +465,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 	}
 	private long printElapsedTime(){
 		long elapsedMilliSeconds = System.currentTimeMillis() - startTime;
-		console.println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds);
+		console.println("Execution Time in Milliseconds:" + elapsedMilliSeconds);
 		return elapsedMilliSeconds;
 	}
 	
@@ -484,7 +484,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 	
 	private void fitness() {
 		if(runThread.isAlive()) {
-			console.println("Run have to be cancelled First.");
+			console.println("Run have to be cancelled first.");
 			return;
 		}
 		double currentFitness = evaluatePosition(extractPositionAndAccess());
@@ -496,7 +496,7 @@ public abstract class AlgorithmFrameworkFlex implements AddOn{
 	private void selectGroupNode() {
 		Object[] possibilities = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().values().stream().map(aCps -> new Handle<DecoratedGroupNode>(aCps)).toArray();
 		@SuppressWarnings("unchecked")
-		Handle<DecoratedGroupNode> selected = (Handle<DecoratedGroupNode>) JOptionPane.showInputDialog(content, "Select GroupNode:", "GroupNode?",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, "");
+		Handle<DecoratedGroupNode> selected = (Handle<DecoratedGroupNode>) JOptionPane.showInputDialog(content, "Select group-node:", "Select a designated area",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, "");
 		if(selected != null) {
 			console.println("Selected: " + selected);
 			dGroupNode = selected.object;

+ 1 - 1
src/classes/HolonElement.java

@@ -47,7 +47,7 @@ public class HolonElement implements TimelineDependent{
     
     
     @Expose
-    private Priority priority;
+    private Priority priority = Priority.Low;
 
 	public enum Priority {
     	Low, Medium, High, Essential

+ 49 - 0
src/preferences/ColorPreference.java

@@ -0,0 +1,49 @@
+package preferences;
+
+import java.awt.Color;
+
+/**
+ * A Class to save all colors in Holeg.
+ * @author Tom
+ *
+ */
+public class ColorPreference {
+	
+	
+	public static class Element{
+		public static class Priority{
+			public static final Color Essential = new Color(201, 44, 74);
+			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);
+		}
+		public static final Color Active = new Color(255, 203, 35);
+		public static final Color Inactive = new Color(128, 154, 163);
+	}
+	public static class HolonObject{
+		public static final Color Producer = new Color(153, 204, 255);
+		public static final Color OverSupplied = new Color(166, 78, 229);
+		public static final Color Supplied = new Color(13, 175, 28);
+		public static final Color PartiallySupplied = Color.yellow;
+		public static final Color NotSupplied = new Color(230, 120, 100);
+		public static final Color NoEnergy = Color.white;
+	}
+	public static class Energy{
+		public static final Color Production = new Color(61, 133, 243);
+		public static final Color Consumption = new Color(255, 67, 60);
+	}
+	public static class Flexibility{
+		public static final Color InUse = new Color(182, 238, 166);
+		public static final Color OnCooldown = new Color(239, 215, 128);
+		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 class Panel {
+		public static final Color Transparent = new Color(0,0,0,0);
+		public static final Color Background = new Color(250, 250, 250);
+		public static final Color Title = new Color(54, 73, 78);
+	}
+}

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

@@ -36,7 +36,6 @@ import utility.events.Event;
  * @author Gruppe14
  */
 public class Control {
-
 	private final MultiPurposeController multiPurposeController;
 	private final CategoryController categoryController;
 	private final ObjectController objectController;
@@ -269,6 +268,8 @@ public class Control {
 		OnSelectionChanged.broadcast();
 	}
 
+    
+
 	/**
 	 * removes a selectedObject from selection.
 	 *
@@ -395,15 +396,6 @@ public class Control {
 		model.setSelectedEdge(edge);
 	}
 
-	/**
-	 * Returns the ID of the selected Object 0 = no Object is selected.
-	 *
-	 * @param id the ID of the selected Object
-	 */
-	public void setSelectedObjectID(int id) {
-		objectController.setSelectedObjectID(id);
-	}
-
 	/* Operations for Objects and Elements */
 
 	/**

+ 2 - 0
src/ui/controller/LoadController.java

@@ -15,6 +15,7 @@ import org.apache.commons.compress.archivers.ArchiveInputStream;
 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
 import org.apache.commons.compress.utils.IOUtils;
 
+import ui.controller.LoadController.MODE;
 import ui.model.Model;
 
 import java.awt.geom.Point2D;
@@ -494,6 +495,7 @@ public class LoadController {
     void initElements(HolonElement ele) {
         ele.flexList = new ArrayList<Flexibility>();
         ele.setGraphPoints(new LinkedList<>());
+        if(ele.getPriority() == null) ele.setPriority(Priority.Low);
         ele.reset();
         if(ele.getPriority() == null) {
         	ele.setPriority(Priority.Low);

+ 1 - 8
src/ui/controller/ObjectController.java

@@ -146,6 +146,7 @@ public class ObjectController {
 		model.getSelectedObjects().add(obj);
 	}
 
+
 	/**
 	 * add an Object to selectedObject.
 	 *
@@ -170,14 +171,6 @@ public class ObjectController {
 		deleteElement(hObject, element);
 	}
 
-	/**
-	 * Returns the ID of the selected Object 0 = no Object is selected.
-	 *
-	 * @param id the ID of the selected Object
-	 */
-	public void setSelectedObjectID(int id) {
-		model.setSelectedObjectID(id);
-	}
 
 	/**
 	 * Get the number of HolonObjects in the given List

+ 120 - 44
src/ui/model/DecoratedGroupNode.java

@@ -1,12 +1,18 @@
 package ui.model;
 
 import java.util.ArrayList;
+import java.util.stream.Stream;
 
 import classes.Node;
+import jdk.jfr.Unsigned;
 import classes.GroupNode;
+import classes.HolonElement;
+import classes.Flexibility;
 import ui.model.DecoratedHolonObject.HolonObjectState;
+
 /**
  * For the @VisualRepresentationalState only.
+ * 
  * @author Tom
  *
  */
@@ -17,19 +23,18 @@ public class DecoratedGroupNode {
 	private ArrayList<Consumer> consumerList;
 	private ArrayList<Node> nodeList;
 	/**
-	 * 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).
+	 * 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<DecoratedCable> internCableList;
 	/**
-	 * Cables that exit this group node (a Layer Up). From a object in this group node to a object in a upper layer.
+	 * 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;	
+	private ArrayList<ExitCable> exitCableList;
 	private ArrayList<DecoratedSwitch> switchList;
 	private ArrayList<DecoratedGroupNode> groupNodeList;
 
-
-
 	public DecoratedGroupNode(GroupNode model) {
 		this.model = model;
 		this.supplierList = new ArrayList<Supplier>();
@@ -41,93 +46,164 @@ public class DecoratedGroupNode {
 		this.switchList = new ArrayList<DecoratedSwitch>();
 		this.groupNodeList = new ArrayList<DecoratedGroupNode>();
 	}
+
 	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<DecoratedCable> getInternCableList() {
 		return internCableList;
 	}
+
 	public ArrayList<ExitCable> getExitCableList() {
 		return exitCableList;
 	}
+
 	public ArrayList<DecoratedSwitch> getSwitchList() {
 		return switchList;
 	}
+
 	public ArrayList<DecoratedGroupNode> getGroupNodeList() {
 		return groupNodeList;
 	}
-	
-	
-	//Returns the amount of holons and count himself 
+
+	// Returns the amount of holons and count himself
 	public int getAmountOfGroupNodes() {
 		return 1 + groupNodeList.stream().map(groupNode -> groupNode.getAmountOfGroupNodes()).reduce(0, Integer::sum);
 	}
-	
-	
-	//Gather Informations:
+
+	public Stream<Flexibility> getFlexibilitiesStream() {
+
+		Stream<Flexibility> flexInChildGorupNode = this.groupNodeList.stream()
+				.flatMap(groupNode -> groupNode.getFlexibilitiesStream());
+
+		Stream<Flexibility> flexInThisGorupNode = objectStream()
+				.flatMap(object -> object.getModel().getElements().stream().flatMap(ele -> ele.flexList.stream()));
+
+		return Stream.concat(flexInChildGorupNode, flexInThisGorupNode);
+	}
+
+	public Stream<DecoratedHolonObject> objectStream() {
+		return Stream.concat(Stream.concat(this.consumerList.stream(), this.supplierList.stream()),
+				this.passivList.stream());
+	}
+
+	// Gather Informations:
 	public int getAmountOfSupplier() {
-		return supplierList.size() + groupNodeList.stream().map(groupNode -> groupNode.getAmountOfSupplier()).reduce(0, Integer::sum);
+		return supplierList.size()
+				+ groupNodeList.stream().map(groupNode -> groupNode.getAmountOfSupplier()).reduce(0, Integer::sum);
 	}
+
 	public int getAmountOfConsumer() {
-		return consumerList.size() + groupNodeList.stream().map(groupNode -> groupNode.getAmountOfConsumer()).reduce(0,Integer::sum);
+		return consumerList.size()
+				+ groupNodeList.stream().map(groupNode -> groupNode.getAmountOfConsumer()).reduce(0, Integer::sum);
 	}
+
 	public int getAmountOfPassiv() {
-		return passivList.size() + groupNodeList.stream().map(groupNode -> groupNode.getAmountOfPassiv()).reduce(0, Integer::sum);
+		return passivList.size()
+				+ groupNodeList.stream().map(groupNode -> groupNode.getAmountOfPassiv()).reduce(0, Integer::sum);
 	}
-	
+
 	public int getAmountOfConsumerWithState(HolonObjectState state) {
-		return ((int) consumerList.stream().map(con -> con.getState()).filter(rightState -> (rightState == state)).count()) +  groupNodeList.stream().map(groupNode -> groupNode.getAmountOfConsumerWithState(state)).reduce(0, Integer::sum);
+		return ((int) consumerList.stream().map(con -> con.getState()).filter(rightState -> (rightState == state))
+				.count())
+				+ groupNodeList.stream().map(groupNode -> groupNode.getAmountOfConsumerWithState(state)).reduce(0,
+						Integer::sum);
 	}
-	
+
 	public int getAmountOfElemntsFromHolonObjects() {
-		return passivList.stream().map(object -> object.getModel().getElements().size()).reduce(0, Integer::sum)+
-				supplierList.stream().map(object -> object.getModel().getElements().size()).reduce(0, Integer::sum)+
-				consumerList.stream().map(object -> object.getModel().getElements().size()).reduce(0, Integer::sum)+
-				groupNodeList.stream().map(groupNode -> groupNode.getAmountOfElemntsFromHolonObjects()).reduce(0, Integer::sum);
+		return objectStream().map(object -> object.getModel().getElements().size()).reduce(0, Integer::sum)
+				+ groupNodeList.stream().map(groupNode -> groupNode.getAmountOfElemntsFromHolonObjects()).reduce(0,
+						Integer::sum);
+	}
+
+	public PriorityCounts getPriorityCounts() {
+		PriorityCounts priority = new PriorityCounts();
+		objectStream().forEach(object -> object.getModel().getElements().stream().forEach(ele -> priority.Count(ele)));
+		groupNodeList.stream().forEach(groupNode -> priority.Add(groupNode.getPriorityCounts()));
+		return priority;
+	}
+
+	public class PriorityCounts {
+		@Unsigned
+		public int low, medium, high, essential;
+
+		public void Add(PriorityCounts other) {
+			low += other.low;
+			medium += other.medium;
+			high += other.high;
+			essential += other.essential;
+		}
+
+		public void Count(HolonElement element) {
+			switch (element.getPriority()) {
+			case Essential:
+				essential++;
+				break;
+			case High:
+				high++;
+				break;
+			case Medium:
+				medium++;
+				break;
+			case Low:
+				low++;
+				break;
+			default:
+				break;
+
+			}
+		}
 	}
 
 	public int getAmountOfAktiveElemntsFromHolonObjects() {
-		return passivList.stream().map(object -> object.getModel().getNumberOfActiveElements()).reduce(0, Integer::sum)+
-				supplierList.stream().map(object -> object.getModel().getNumberOfActiveElements()).reduce(0, Integer::sum)+
-				consumerList.stream().map(object -> object.getModel().getNumberOfActiveElements()).reduce(0, Integer::sum)+
-				groupNodeList.stream().map(groupNode -> groupNode.getAmountOfAktiveElemntsFromHolonObjects()).reduce(0, Integer::sum);
+		return objectStream().map(object -> object.getModel().getNumberOfActiveElements()).reduce(0,
+						Integer::sum)
+				+ groupNodeList.stream().map(groupNode -> groupNode.getAmountOfAktiveElemntsFromHolonObjects())
+						.reduce(0, Integer::sum);
 	}
-	public float getConsumptionFromConsumer() {		
-		return consumerList.stream().map(con -> con.getEnergyNeededFromNetwork()).reduce(0.f, Float::sum)+
-				groupNodeList.stream().map(groupNode -> groupNode.getConsumptionFromConsumer()).reduce(0.f, Float::sum);
+
+	public float getConsumptionFromConsumer() {
+		return consumerList.stream().map(con -> con.getEnergyNeededFromNetwork()).reduce(0.f, Float::sum)
+				+ groupNodeList.stream().map(groupNode -> groupNode.getConsumptionFromConsumer()).reduce(0.f,
+						Float::sum);
 	}
-	public float getProductionFromSupplier() {		
-		return supplierList.stream().map(sup -> sup.getEnergyToSupplyNetwork()).reduce(0.f, Float::sum)+
-				groupNodeList.stream().map(groupNode -> groupNode.getProductionFromSupplier()).reduce(0.f, Float::sum);
+
+	public float getProductionFromSupplier() {
+		return supplierList.stream().map(sup -> sup.getEnergyToSupplyNetwork()).reduce(0.f, Float::sum) + groupNodeList
+				.stream().map(groupNode -> groupNode.getProductionFromSupplier()).reduce(0.f, Float::sum);
 	}
-	
+
 	public float getAverageConsumption() {
-		return getConsumptionFromConsumer() / (float)getAmountOfGroupNodes();
+		return getConsumptionFromConsumer() / (float) getAmountOfGroupNodes();
 	}
+
 	public float getAverageProduction() {
-		return getProductionFromSupplier() / (float)getAmountOfGroupNodes();
+		return getProductionFromSupplier() / (float) getAmountOfGroupNodes();
 	}
-	
-	
+
 	public String toString() {
-		return 
-				"GroupNode" + model.getId() + " with [Supplier:" + getAmountOfSupplier() 
-				+ ", NotSupplied:" + getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED) 
-				+ ", PartiallySupplied:" + getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED) 
-				+ ", Supplied:" + getAmountOfConsumerWithState(HolonObjectState.SUPPLIED) 
-				+ ", OverSupplied:" + getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED) 
-				+ ", Passiv:"+ getAmountOfPassiv() + "]";
+		return "GroupNode" + model.getId() + " with [Supplier:" + getAmountOfSupplier() + ", NotSupplied:"
+				+ getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED) + ", PartiallySupplied:"
+				+ getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED) + ", Supplied:"
+				+ getAmountOfConsumerWithState(HolonObjectState.SUPPLIED) + ", OverSupplied:"
+				+ getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED) + ", Passiv:" + getAmountOfPassiv()
+				+ "]";
 	}
 }

+ 0 - 18
src/ui/model/Model.java

@@ -51,7 +51,6 @@ public class Model {
     private int canvasX = 3000;
     private int canvasY = 3000;
     private int curIteration = 0;
-    // ID of the Selected Object
     private HolonElement selectedHolonElement;
     private Edge selectedEdge;
     private Set<AbstractCanvasObject> selectedObjects = new HashSet<>();
@@ -247,23 +246,6 @@ public class Model {
         this.objectListeners = linkedList;
     }
 
-    /**
-     * Returns the ID of the selected Object 0 = no Object is selected.
-     *
-     * @return ID
-     */
-    public int getSelectedObjectID() {
-        return selectedID;
-    }
-
-    /**
-     * Set the ID of the selected Object 0 = no Object is selected.
-     *
-     * @param id the ID
-     */
-    public void setSelectedObjectID(int id) {
-        this.selectedID = id;
-    }
 
     /**
      * Returns all selected Objects on the Canvas.

+ 16 - 8
src/ui/model/VisualRepresentationalState.java

@@ -12,6 +12,7 @@ import classes.Edge;
 import classes.Node;
 import ui.model.ExitCable.ExitCableState;
 import classes.GroupNode;
+import classes.HolonObject;
 
 public class VisualRepresentationalState {
 	private ArrayList<Supplier> supplierList = new ArrayList<Supplier>();
@@ -26,6 +27,8 @@ public class VisualRepresentationalState {
 	//ForFastAccessIndividualGroupNodes:
 	private HashMap<GroupNode, DecoratedGroupNode> createdGroupNodes;
 	
+	public HashMap<HolonObject, DecoratedHolonObject> createdHolonObjects;
+	
 	public VisualRepresentationalState(DecoratedState stateFromThisTimestep, MinimumModel minimumModel) {
 		reassignObjects(stateFromThisTimestep, minimumModel);
 	}
@@ -62,6 +65,7 @@ public class VisualRepresentationalState {
 		HashMap<Edge, ArrayList<GroupNode>> inGroupEdges = minimumModel.getInGroupEdges();
 		
 		createdGroupNodes =  new HashMap<GroupNode, DecoratedGroupNode>();
+		createdHolonObjects = new HashMap<HolonObject, DecoratedHolonObject>();
 		
 		ArrayList<IntermediateCalculationCable> exitCables = new ArrayList<IntermediateCalculationCable>();
 		//createThem
@@ -71,28 +75,32 @@ public class VisualRepresentationalState {
 		//unrolling Networks
 		for(DecoratedNetwork net : stateFromThisTimestep.getNetworkList()) {
 			for(Consumer con : net.getConsumerList()) {
-				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, con.getModel(), consumerList, con, createdGroupNodes);
+				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, con.getModel(), consumerList, con);
 				if(groupNodeFromObject != null) {
 					addToGroupNode(con, groupNodeFromObject.getConsumerList());
 				}
+				this.createdHolonObjects.put(con.getModel(), con);
 			}
 			for(Consumer con : net.getConsumerSelfSuppliedList()) {
-				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, con.getModel(), consumerList, con, createdGroupNodes);
+				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, con.getModel(), consumerList, con);
 				if(groupNodeFromObject != null) {
 					addToGroupNode(con, groupNodeFromObject.getConsumerList());
 				}
+				this.createdHolonObjects.put(con.getModel(), con);
 			}
 			for(Supplier sup : net.getSupplierList()) {
-				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, sup.getModel(), supplierList, sup, createdGroupNodes);
+				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, sup.getModel(), supplierList, sup);
 				if(groupNodeFromObject != null) {
 					addToGroupNode(sup, groupNodeFromObject.getSupplierList());
 				}
+				this.createdHolonObjects.put(sup.getModel(), sup);
 			}
 			for(Passiv pas : net.getPassivNoEnergyList()) {
-				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, pas.getModel(), passivList, pas, createdGroupNodes);
+				DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, pas.getModel(), passivList, pas);
 				if(groupNodeFromObject != null) {
 					addToGroupNode(pas, groupNodeFromObject.getPassivList());
 				}
+				this.createdHolonObjects.put(pas.getModel(), pas);
 			}
 			for(DecoratedCable cable : net.getDecoratedCableList()) {
 				addCable(cable, inGroupEdges, inGroupObjects,createdGroupNodes, exitCables);
@@ -102,19 +110,19 @@ public class VisualRepresentationalState {
 			addCable(cable, inGroupEdges, inGroupObjects, createdGroupNodes, exitCables);
 		}
 		for(Node node : minimumModel.getNodeList()) {
-			DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, node, nodeList ,node, createdGroupNodes);
+			DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, node, nodeList ,node);
 			if(groupNodeFromObject != null) {
 				addToGroupNode(node, groupNodeFromObject.getNodeList());
 			}
 		}
 		for(DecoratedSwitch dSwitch: stateFromThisTimestep.getDecoratedSwitches()) {
-			DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, dSwitch.getModel(), switchList, dSwitch, createdGroupNodes);
+			DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, dSwitch.getModel(), switchList, dSwitch);
 			if(groupNodeFromObject != null) {
 				addToGroupNode(dSwitch, groupNodeFromObject.getSwitchList());
 			}
 		}
 		for(DecoratedGroupNode dGroupNode: createdGroupNodes.values()) {
-			DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, dGroupNode.getModel(), groupNodeList, dGroupNode, createdGroupNodes);
+			DecoratedGroupNode groupNodeFromObject = addObject(inGroupObjects, dGroupNode.getModel(), groupNodeList, dGroupNode);
 			if(groupNodeFromObject != null) {
 				addToGroupNode(dGroupNode, groupNodeFromObject.getGroupNodeList());
 			}
@@ -318,7 +326,7 @@ public class VisualRepresentationalState {
 	
 
 	//Generics
-	private <ModelOfObject, DecoratedObject> DecoratedGroupNode addObject(HashMap<ModelOfObject, GroupNode> inGroupObjects, ModelOfObject modelOfObject, ArrayList<DecoratedObject> listToAdd, DecoratedObject object, HashMap<GroupNode, DecoratedGroupNode> createdGroupNodes) {
+	private <ModelOfObject, DecoratedObject> DecoratedGroupNode addObject(HashMap<ModelOfObject, GroupNode> inGroupObjects, ModelOfObject modelOfObject, ArrayList<DecoratedObject> listToAdd, DecoratedObject object) {
 		if(inGroupObjects.containsKey(modelOfObject)) {
 			return  createdGroupNodes.get(inGroupObjects.get(modelOfObject));
 		}

+ 430 - 0
src/ui/view/AbstractCanvas.java.orig

@@ -0,0 +1,430 @@
+package ui.view;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimerTask;
+
+import javax.swing.CellEditor;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTable;
+import javax.swing.Timer;
+
+import classes.AbstractCanvasObject;
+import classes.Edge;
+import classes.GroupNode;
+import classes.HolonElement;
+import classes.HolonObject;
+import classes.Node;
+import ui.controller.Control;
+import ui.controller.UpdateController;
+import ui.model.Model;
+import utility.Vector2Int;
+
+/**
+ * Collection of methods and values needed in both <code>MyCanvas</code> and
+ * <code>UpperNodeCanvas</code>
+ * <p>
+ * Although Java works on references we chose to add explicit return values for
+ * clearer code understanding in most cases
+ *
+ * @author: I. Dix
+ */
+public abstract class AbstractCanvas extends JPanel {
+	/**
+	 * Version
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	final JMenuItem itemCut = new JMenuItem("Cut");
+	final JMenuItem itemCopy = new JMenuItem("Copy");
+	final JMenuItem itemPaste = new JMenuItem("Paste");
+	final JMenuItem itemDelete = new JMenuItem("Delete");
+	final JMenuItem itemGroup = new JMenuItem("Group");
+	final JMenuItem itemUngroup = new JMenuItem("Ungroup");
+	final JMenuItem itemAlign = new JMenuItem("Align selected");
+	final JMenuItem itemCreateTemplate = new JMenuItem("Create Template");
+	
+	final int ANIMTIME = 500; // animation Time
+	private final int animFPS = 60;
+	final int animDelay = 1000 / animFPS; // animation Delay
+	protected Model model;
+	protected Control controller;
+	protected int x = 0;
+	protected int y = 0;
+	// Selection
+	AbstractCanvasObject tempCps = null;
+	UpdateController updCon;
+	
+	//Replacement
+	/**
+	 * the CpsObject that might be replaced by drag&drop
+	 */
+	protected AbstractCanvasObject mayBeReplaced = null;
+	
+	// PopUpMenu
+	JPopupMenu popmenu = new JPopupMenu();
+	// Tooltip
+	boolean toolTip; // Tooltip on or off
+	Vector2Int toolTipPos = new Vector2Int(); // Tooltip Position
+	String toolTipText = "";
+	List<HolonElement> dataSelected = new ArrayList<>();
+	ArrayList<AbstractCanvasObject> tempSelected = new ArrayList<>();
+	boolean[] showedInformation = new boolean[5];
+	boolean showConnectionInformation;
+	boolean dragging = false; // for dragging
+	boolean dragged = false; // if an object/objects was/were dragged
+	boolean drawEdge = false; // for drawing edges
+	boolean doMark = false; // for double click
+	Edge edgeHighlight = null;
+	Point mousePosition = new Point(); // Mouse Position when
+	ArrayList<Vector2Int> savePos;
+	// edge Object Start Point
+	int cx, cy;
+	int sx, sy; // Mark Coords
+	Vector2Int unPos;
+	// Animation
+	Timer animT; // animation Timer
+	int animDuration = ANIMTIME; // animation Duration
+	int animSteps = animDuration / animDelay; // animation Steps;
+	ArrayList<AbstractCanvasObject> animCps = null;
+	// Graphics
+	Image img = null; // Contains the image to draw on the Canvas
+	Graphics2D g2; // For Painting
+	float scalediv20;
+	// Mouse
+	private boolean click = false;
+
+	// ------------------------------------------ METHODS
+	// ------------------------------------------
+	
+
+	
+	
+
+	class ACpsHandle{
+		public AbstractCanvasObject object;
+		ACpsHandle(AbstractCanvasObject object){
+			this.object = object;
+		}
+		public String toString() {
+			return object.toString();
+		}
+	}
+
+	void drawMarker() {
+		if (sx > x && sy > y) {
+			g2.drawRect(x, y, sx - x, sy - y);
+		} else if (sx < x && sy < y) {
+			g2.drawRect(sx, sy, x - sx, y - sy);
+		} else if (sx >= x) {
+			g2.drawRect(x, sy, sx - x, y - sy);
+		} else if (sy >= y) {
+			g2.drawRect(sx, y, x - sx, sy - y);
+		}
+	}
+	/**
+	 * @deprecated
+	 * @param g
+	 */
+	void showTooltip(Graphics g) {
+		if (toolTip) {
+			g2.setColor(new Color(255, 225, 150));
+			g2.setStroke(new BasicStroke(1));
+			int textWidth = g.getFontMetrics().stringWidth(toolTipText) + 2; // Text
+			// width
+
+			// fixed x and y Position to the screen
+			int fixXPos = toolTipPos.getX() - (textWidth >> 1) + model.getScaleDiv2();
+			int fixYPos = toolTipPos.getY();
+
+			if (fixXPos < 0) {
+				fixXPos = 0;
+			} else if (fixXPos + textWidth + 1 > this.getWidth()) {
+				fixXPos -= (fixXPos + textWidth + 1) - this.getWidth();
+			}
+			if (fixYPos + 16 > this.getHeight()) {
+				fixYPos -= (fixYPos + 16) - this.getHeight();
+			}
+			g2.fillRect(fixXPos, fixYPos, textWidth, 15);
+			g2.setColor(Color.BLACK);
+			g2.drawRect(fixXPos, fixYPos, textWidth, 15);
+			g2.drawString(toolTipText, fixXPos + 2, fixYPos + 12);
+		}
+	}
+
+
+
+	void setRightClickMenu(MouseEvent e) {
+		if (e.getButton() == MouseEvent.BUTTON3) {
+			itemPaste.setEnabled(true);
+			if (tempCps != null) {
+				itemPaste.setEnabled(true);
+				itemDelete.setEnabled(true);
+				itemCut.setEnabled(true);
+				itemCopy.setEnabled(true);
+				itemAlign.setEnabled(true);
+				// tracking
+				if (tempCps != null) {
+					itemGroup.setEnabled(true);
+				}
+				// ungrouping
+				if (tempCps instanceof GroupNode)
+					itemUngroup.setEnabled(true);
+				else
+					itemUngroup.setEnabled(false);
+				if (model.getSelectedCpsObjects().size() == 0) {
+					controller.addSelectedObject(tempCps);
+				}
+				if (tempCps instanceof HolonObject) {
+					itemCreateTemplate.setEnabled(true);
+				} else {
+					itemCreateTemplate.setEnabled(false);
+				}
+			} else {
+				itemAlign.setEnabled(false);
+				itemCut.setEnabled(false);
+				itemCopy.setEnabled(false);
+				itemGroup.setEnabled(false);
+				itemUngroup.setEnabled(false);
+				itemCreateTemplate.setEnabled(false);
+				if (edgeHighlight != null) {
+					itemDelete.setEnabled(true);
+					itemPaste.setEnabled(false);
+				} else {
+					itemDelete.setEnabled(false);
+					itemPaste.setEnabled(true);
+				}
+			}
+			mousePosition = this.getMousePosition();
+			popmenu.show(e.getComponent(), e.getX(), e.getY());
+		}
+	}
+
+	void markObjects() {
+		if (doMark) {
+			doMark = false;
+			for (AbstractCanvasObject cps : tempSelected) {
+				if (!model.getSelectedCpsObjects().contains(cps)) {
+					controller.addSelectedObject(cps);
+				}
+			}
+			controller.getObjectsInDepth();
+			tempSelected.clear();
+		}
+	}
+
+
+	int[] determineMousePositionOnEdge(Edge p) {
+		int lx, ly, hx, hy;
+
+		if (p.getA().getPosition().getX() > p.getB().getPosition().getX()) {
+			hx = p.getA().getPosition().getX() + model.getScaleDiv2() + 7;
+			lx = p.getB().getPosition().getX() + model.getScaleDiv2() - 7;
+		} else {
+			lx = p.getA().getPosition().getX() + model.getScaleDiv2() - 7;
+			hx = p.getB().getPosition().getX() + model.getScaleDiv2() + 7;
+		}
+		if (p.getA().getPosition().getY() > p.getB().getPosition().getY()) {
+			hy = p.getA().getPosition().getY() + model.getScaleDiv2() + 7;
+			ly = p.getB().getPosition().getY() + model.getScaleDiv2() - 7;
+		} else {
+			ly = p.getA().getPosition().getY() + model.getScaleDiv2() - 7;
+			hy = p.getB().getPosition().getY() + model.getScaleDiv2() + 7;
+		}
+
+		return new int[] { lx, ly, hx, hy };
+	}
+
+	/**
+	 * Checks if a double click was made.
+	 *
+	 * @return true if doublecklick, false if not
+	 */
+	boolean doubleClick() {
+		if (click) {
+			click = false;
+			return true;
+		} else {
+			click = true;
+			java.util.Timer t = new java.util.Timer("doubleclickTimer", false);
+			t.schedule(new TimerTask() {
+				@Override
+				public void run() {
+					click = false;
+				}
+			}, 500);
+		}
+		return false;
+	}
+
+	boolean setToolTipInfoAndPosition(boolean on, AbstractCanvasObject cps) {
+		if (x - controller.getScale() <= cx && y - controller.getScale() <= cy && x >= cx && y >= cy) {
+			on = true;
+			toolTipPos.setX(cps.getPosition().getX() - controller.getScaleDiv2());
+			toolTipPos.setY(cps.getPosition().getY() + controller.getScaleDiv2());
+			toolTipText = cps.getName() + ", " + cps.getId();
+		}
+
+		return on;
+	}
+
+	abstract void drawDeleteEdge();
+
+	void triggerUpdateController() {
+		updCon.paintProperties(tempCps);
+		updCon.refreshTableHolonElement(model.getMultiTable(), model.getSingleTable());
+		updCon.refreshTableProperties(model.getPropertyTable());
+	}
+	
+	
+	/**
+	 * Checks if {@code draggedCps} or a new cpsObject at Position (x,y) could replace exactly one object
+	 * in {@code objects}.
+	 * Saves the object that would be replaced in {@link AbstractCanvas}.{@code MayBeReplaced}
+	 * @param objects list of objects that could be replaced
+	 * @param draggedCps Object that might replace
+	 * @param x Position of the objects that might replace
+	 * @param y Position of the objects that might replace
+	 * @return true if exactly one Object could be replaced 
+	 */
+	protected boolean checkForReplacement(ArrayList<AbstractCanvasObject> objects, AbstractCanvasObject draggedCps, int x, int y){
+		
+		/** distance treshold for replacement */
+		int treshhold = controller.getScale()/2;
+						
+		/** number of Objects that might be replaced (should be 1) */
+		int replaceCounter = 0;
+		
+		/** last object that could be replaced */
+		AbstractCanvasObject toBeReplaced = null;
+		
+		/** Position of object that might be replaced */
+		Vector2Int p;
+		
+		/** for each cps on Canvas */
+		if(draggedCps == null || !(draggedCps instanceof Node) && !(draggedCps instanceof Node)){
+			for (AbstractCanvasObject cps : objects){
+				/** same object -> ignore */
+				if(cps == draggedCps)continue;
+						
+				/** set Position of object that might be replaced */
+				p = cps.getPosition();
+				
+				/** if near enough */
+				if(Math.abs(x-p.getX())<treshhold && Math.abs(y-p.getY())<treshhold){
+					replaceCounter++;
+					toBeReplaced = cps;
+					
+					/**
+					 * if too many Objects could be replaced:
+					 * stop searching, because it would not be clear which one should
+					 * be replaced
+					 */
+					if(replaceCounter>1)break;
+				}
+			}
+		}
+		/**
+		 * return true if exactly one obect would be replaced
+		 */
+		if( replaceCounter == 1 && toBeReplaced != null){
+			mayBeReplaced = toBeReplaced;
+			return true;
+		}else{
+			mayBeReplaced = null;
+			return false;
+		}
+	}
+	
+	/**
+	 * Checks if an inserted new Object could replace exactly one object on the canvas.
+	 * Saves the object that would be replaced in {@link AbstractCanvas}.{@code MayBeReplaced}
+	 * @param x Position of the objects that might replace
+	 * @param y Position of the objects that might replace
+	 * @return true if exactly one Object could be replaced 
+	 */
+	public abstract boolean checkForReplacement(int x, int y);
+	
+		
+	/**
+	 * highlights the object that mayBeReplaced
+	 * @param g2
+	 */
+	protected void highlightMayBeReplaced(Graphics2D g2) {
+		if(mayBeReplaced != null){
+			g2.setColor(Color.RED);
+			g2.fillRect(
+					(int) (mayBeReplaced.getPosition().getX()
+							- controller.getScaleDiv2() - (scalediv20 + 3)),
+					(int) (mayBeReplaced.getPosition().getY()
+							- controller.getScaleDiv2() - (scalediv20 + 3)),
+					(int) (controller.getScale() + ((scalediv20 + 3) * 2)),
+					(int) (controller.getScale() + ((scalediv20 + 3) * 2)));
+		}
+	}
+	
+	/**
+	 * Align alle Objects on the Canvas to a Grid with objects every 10 pixels
+	 */
+	public abstract void tryToAlignObjects();
+
+	/**
+	 * Aligns the Object the a grid
+	 * @param cps Object that should be aligned
+	 * @param distance distance between the AlignmentGrid Lines. (objects every 'distance' pixels
+	 */
+	protected void align(AbstractCanvasObject cps, int distance) {
+		/** Position of the AbstractCpsObject which should be aligned */
+		Vector2Int p = cps.getPosition();
+		
+		//calculate how many pixels the cps should be decreased to align
+		/** x offset relative to a grid with lines every distance pixels */
+		int x_off = cps.getPosition().getX() % distance;
+		
+		/** y offset relative to a grid with lines every distance pixels */
+		int y_off = cps.getPosition().getY() % distance;
+		
+		//align to the other Line, if it is nearer
+		if(x_off > distance/2)
+			x_off -= distance;
+		if(y_off > distance/2)
+			y_off -= distance;
+		
+		/** set new Position */
+		cps.setPosition(p.getX()-x_off, p.getY()-y_off);
+	}
+	
+	/**
+	 * Stops Editing in HolonElementTable and PropertyTable
+	 */
+	protected void stopEditing() {
+		/**
+		 * Stop Editing, if mouse exits the Table
+		 */
+		JTable holElem = model.getTableHolonElement();
+		CellEditor cellEditor = holElem.getCellEditor();
+		if (cellEditor != null) {
+		    if (cellEditor.getCellEditorValue() != null) {
+		    	/** TODO: Maybe try to save current Data */
+		        cellEditor.stopCellEditing();
+		    } else {
+		        cellEditor.cancelCellEditing();
+		    }
+		}
+	}
+
+	/**
+	 * Closes a tab of the UpperNode with ID upperNodeID
+	 * @param upperNodeId
+	 */
+	public abstract void closeUpperNodeTab(int upperNodeId);
+}

+ 2686 - 0
src/ui/view/GUI.java.orig

@@ -0,0 +1,2686 @@
+package ui.view;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.CellEditor;
+import javax.swing.GrayFilter;
+import javax.swing.ImageIcon;
+import javax.swing.InputMap;
+import javax.swing.JButton;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.JToolBar;
+import javax.swing.JTree;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeCellRenderer;
+
+import org.apache.commons.compress.archivers.ArchiveException;
+import com.google.gson.JsonParseException;
+
+import classes.AbstractCanvasObject;
+import classes.Category;
+import classes.Edge;
+import classes.GroupNode;
+import classes.HolonElement;
+import classes.HolonObject;
+import classes.HolonSwitch;
+import classes.IdCounter;
+import classes.IdCounter.CounterType;
+import interfaces.GraphEditable;
+import ui.controller.Control;
+import ui.controller.UpdateController;
+import ui.model.DecoratedState;
+import ui.model.Model;
+import ui.model.Model.FairnessModel;
+import ui.view.CreateNewDialog.Option;
+import utility.Event;
+import utility.ImageImport;
+
+/**
+ * Graphical User Interface.
+ *
+ * @author Gruppe14
+ */
+public class GUI{
+	
+	static final Color PALE_RED=new Color(255, 192, 192);
+	
+	
+	
+	
+	
+	/**
+	 * Menu on the Top containing File, Edit View Help etc
+	 */
+	private final JMenuBar menuBar = new JMenuBar();
+	private final JMenu mnNewMenu = new JMenu("File");
+	private final JMenu mnNewMenuEdit = new JMenu("Edit");
+	private final JMenu mnNewMenuOptions = new JMenu("Options");
+	private final JMenu mnNewMenuView = new JMenu("View");
+	private final JMenu menuWindow = new JMenu("Window");
+	
+	
+	private final HolonInformationPanel informationPanel;
+	
+	/** Help Menu containing helpful Informations and the AboutUs Popup */
+	private final JMenu mnHelp = new JMenu("Help");
+	
+	/** 
+	 * Help -> Introduction
+	 * A small Introduction of the Application, SmartGrids and Holons 
+	 */
+	private final JMenuItem mntmIntroduction = new JMenuItem("Introduction");
+
+	/** 
+	 * Help -> UserManual
+	 */
+	private final JMenuItem mntmUserManual = new JMenuItem("User Manual");
+	
+	/** Help -> Algorithm Help Menu */
+	private final JMenuItem mntmAlgorithmHelp = new JMenuItem("Algorithm Introduction");
+	
+	/** Help -> CodeDocumentation */
+	private final JMenuItem mntmCodeDoc = new JMenuItem("Code Documentation");
+	
+	/** Help -> AboutUs */
+	private final JMenuItem mntmAboutUs = new JMenuItem("About Us");
+	/** checked if supplyBars should be shown */
+	private final JCheckBoxMenuItem showSupplyBarsCheckBox = new JCheckBoxMenuItem(
+			"Show supply bars.");
+	/** menu for the different fairness Models */
+	private final JMenu mnFairnessModel = new JMenu("Fairness Model");
+	/** press to supply minimum demand first */
+	private final JMenuItem mntmFairMinFirst = new JMenuItem(
+			"Minimum demand first");
+	/** press to give everyone the same energy */
+	private final JMenuItem mntmFairAlleEqual = new JMenuItem(
+			"Equal supply for everyone");
+	private final JMenuItem mntmOpen = new JMenuItem("Open");
+	private final JMenuItem mntmNew = new JMenuItem("New");
+	private final JMenuItem mntmSave = new JMenuItem("Save");
+	private final JMenuItem mntmCanvasSize = new JMenuItem("Set View Size");
+	private final JMenuItem mntmBackground = new JMenuItem("Set Background Image");
+	private final JSplitPane splitPane = new JSplitPane();
+	private final JSplitPane splitPane1 = new JSplitPane();
+	// the tabbed canvas containing the different sub-net tabs of the grid (Main
+	// Grid + Nodes of Nodes)
+
+	private final JPanel myPanel = new JPanel(new BorderLayout());
+	private final JTabbedPane tabbedPaneInnerOriginal = new JTabbedPane(
+			JTabbedPane.TOP);
+	// the main canvas where we can see the grid currently displayed
+	private final JScrollPane canvasSP = new JScrollPane();
+	private final JScrollPane scrollPane1 = new JScrollPane();
+	// private final JScrollPane holonSP = new JScrollPane();
+	// the original tabbed Pane (containing tabs for view, statistics, holon,
+	// flexibility)
+	private final JTabbedPane tabbedPaneOriginal = new JTabbedPane(
+			JTabbedPane.TOP);
+	// the same tabbed Pane that appears once the view is split
+	private final JTabbedPane tabbedPaneSplit = new JTabbedPane(JTabbedPane.TOP);
+	private final JPopupMenu popmenuEdit = new JPopupMenu();
+	private final JMenuItem editItem = new JMenuItem("Edit Object");
+	private final JLabel maxGraph = new JLabel("100%");
+	private final JLabel medGraph = new JLabel("50%");
+	private final JLabel minGraph = new JLabel("0%");
+	private final JLabel elementGraph = new JLabel("None ");
+	private final ArrayList<HolonElement> selectedElements = new ArrayList<>();
+	private final JTree categoryTree = new JTree();
+	/******************************************
+	 ************* Right Container*************
+	 ******************************************
+	 * Right Container: here comes the information about the HolonObject, such
+	 * as HolonElements Information, Properties and Consumption/Production
+	 * graph.
+	 **/
+	private final JSplitPane splitHolonElPro = new JSplitPane(
+			JSplitPane.VERTICAL_SPLIT);
+	private final JSplitPane splitGraphHolonEl = new JSplitPane(
+			JSplitPane.VERTICAL_SPLIT);
+	private final int distanceBetweenElementsAndGraph = 350;
+	// Model for single or multi selection
+	private final JPanel scrollElements = new JPanel();
+	private final JScrollPane tableHolonElementScrollPane = new JScrollPane();
+
+	//Prechoosed local Periods
+	private String[] comboContext = {
+	         "", "5", "10", "20" ,"100", "1000"
+	};
+	private JComboBox<String> localPeriodInput = new JComboBox<String>(comboContext);
+	JButton resetButton = new JButton("", new ImageIcon(ImageImport.loadImage("/Images/resetIcon3.png")));
+	ImageIcon localPeriodButtonImage = new ImageIcon(GrayFilter.createDisabledImage(ImageImport.loadImage("/Images/Graph.png")));
+	private JButton localPeriodButton = new JButton("", localPeriodButtonImage);
+	private final JPanel graphLabel = new JPanel();
+	private final JScrollPane scrollProperties = new JScrollPane();
+	// In this section is the graph for the selected HolonElement of the clicked
+	// HolonObject
+	private final DefaultTableModel tableModelGraph = new DefaultTableModel();
+	private final JScrollPane scrollGraph = new JScrollPane();
+	private final Model model;
+	private final Control controller;
+
+	// In this section are all the Holonelements that correspond to the clicked
+	// HolonObject with consumption/production, name and amount.
+	private final JPanel panel = new JPanel();
+	private final JPanel panelHolonEl = new JPanel();
+	// Buttons
+
+	private final JButton btnAdd = new JButton();
+	private final JPopupMenu btnAddPopUp = new JPopupMenu("Newacac");
+	private final JMenuItem mItemNew = new JMenuItem("New..");
+	private final JMenuItem mItemCategory = new JMenuItem("Category");
+	private final JMenuItem mItemObject = new JMenuItem("Object");
+	private final JMenuItem mItemSwitch = new JMenuItem("Switch");
+	private final JButton btnDel = new JButton();
+	private final JButton btnAddHolEL = new JButton();
+	private final JButton btnDelHolEL = new JButton();
+
+	private final JToolBar toolBar = new JToolBar();
+	private final JToolBar toolBarHolonEl = new JToolBar();
+	private final JToolBar toolBarGraph = new JToolBar();
+	// Languages
+	private final MyCanvas canvas;
+	private final UnitGraph unitGraph;
+	/** Textfield to show the period of an element */
+	private final JTextField unitGraphLocalPeriod = new JTextField(6);
+	private final JMenuItem mntmUndo = new JMenuItem("Undo");
+	private final JMenuItem mntmRedo = new JMenuItem("Redo");
+	private final JMenuItem mntmEditEdges = new JMenuItem("Edge Properties");
+	private final JMenuItem mntmFindReplace = new JMenuItem("Find/ Replace");
+	private final JMenuItem mntmAlignAll = new JMenuItem("Align All");
+	private final JMenuItem mntmResetCategory = new JMenuItem(
+			"Reset Categories");
+	private final String[] columnNamesMulti = { "Object", "Nr.", "Device",
+			"Energy", "Flexibility active", "Quantity", "Activated" };
+	private final String[] columnNamesSingle = { "Nr.", "Device", "Energy",
+			"Flexibility active", "Quantity", "Activated" };
+	private final ArrayList<PropertyTable> tables = new ArrayList<>();
+	private final UpdateController updCon;
+	// for doubleclick
+	private boolean click = false;
+	private JFrame holegJFrame;
+	private JTabbedPane tabTemp; // tabbedPaneOriginal or tabbedPaneSplit
+	private boolean initSplit = true;
+	private String catOfObjToBeEdited;
+	private GroupNodeCanvas unc;
+	private JPanel contentPane;
+	private String holonEleNamesDisplayed = "None ";
+	// Pop up Windows
+	private AddObjectPopUp addObjectPopUP;
+	private AboutUsPopUp aboutUsPopUp;
+	private AddElementPopUp addElementPopUp;
+	// variables
+	private boolean dragging = false;
+	private String actualObjectClicked;
+	private Image img = null;
+	private AbstractCanvasObject tempCps = null;
+	private int yValueElements = 0;
+	// Time Stuff
+	private TimePanel timePanel;
+	public TimePanel getTimePanel() {
+		return timePanel;
+	}
+
+	// Coord for all Cells with text
+	private int yThis;
+	private int xThis;
+	// Coord for all Cells with boolean values (checkbox)
+	private int yBTis;
+	private int xBThis;
+	// Coord for the Edit-Modus in the PropertieTable
+	private AbstractCanvasObject temp = null;
+	private String warningText = "Warning";
+	private String saveBeforeNew = "Do you want to save your current data?";
+	private String eraseCategory = "Do you really want to delete the Category ";
+	private String selectObjBeforeErase = "Please select a Category or an Object in the left library in order to delete something.";
+
+	
+	private List<Outliner> outlinerList = new ArrayList<Outliner>();
+	private List<FlexWindow> flexList = new ArrayList<FlexWindow>();
+
+	private JMenuItem removeItem = new JMenuItem("Remove");
+
+	
+	/**
+	 * Create the application.
+	 *
+	 * @param control
+	 *            the Controller
+	 */
+	GUI(Control control) {
+		this.controller = control;
+		this.informationPanel = new HolonInformationPanel(control);
+		this.model = control.getModel();
+		control.setGui(this);
+		this.unitGraph = new UnitGraph(model, control);
+		this.canvas = new MyCanvas(model, control, unitGraph);
+		initialize();
+		updateCategories(model.getCategories());
+		updCon = new UpdateController(model, controller);
+		control.OnCategoryChanged.addListener(() -> this.updateCategoryUI(model.getCategories()));
+	}
+
+
+	/**
+	 * Initialize the contents of the frame.
+	 */
+	private void initialize() {
+		holegJFrame = new JFrame();
+		holegJFrame.setTitle("HOLEG Simulator");
+		// try to restore old position/dimensions
+		ArrayList<Integer> savedWindowDim = controller
+				.loadSavedWindowDimensionsIfExistent();
+		if (savedWindowDim.size() == 4) {
+			holegJFrame.setBounds(savedWindowDim.get(0),
+					savedWindowDim.get(1), savedWindowDim.get(2),
+					savedWindowDim.get(3));
+		}
+
+		// if the upper part of the window is showing, the windows can still be
+		// moved,
+		// but if it is not, we need to move it to somewhere else
+		if (savedWindowDim.size() != 4 || !isUpperPanelInsideBounds()) {
+			holegJFrame.setBounds(100, 100, 1000, 800);
+			holegJFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
+		}
+		holegJFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+
+		holegJFrame.addWindowListener(new java.awt.event.WindowAdapter() {
+			@Override
+			public void windowClosing(java.awt.event.WindowEvent windowEvent) {
+				if (JOptionPane.showConfirmDialog(holegJFrame,
+						"Are you sure you want to exit?",
+						"HOLEG",
+						JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
+					controller.deleteDirectory(new File(System
+							.getProperty("user.home")
+							+ "/.config/HolonGUI/Autosave"));
+
+					// try to save the position and size of the window, such
+					// that (if possible)
+					// it can be opened in the same position the next time
+					try {
+						controller.savePosAndSizeOfWindow(
+								holegJFrame.getX(),
+								holegJFrame.getY(),
+								holegJFrame.getWidth(),
+								holegJFrame.getHeight());
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+					System.exit(1);
+				}
+				System.exit(0);
+			}
+		});
+
+		contentPane = (JPanel) holegJFrame.getContentPane();
+
+		int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
+		InputMap inputMap = contentPane.getInputMap(condition);
+		ActionMap actionMap = contentPane.getActionMap();
+
+		String cntrlZDown = "controlZ";
+		inputMap.put(KeyStroke.getKeyStroke("control Z"), cntrlZDown);
+		actionMap.put(cntrlZDown, new AbstractAction() {
+
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				try {
+					controller.loadAutoSave(controller.getUndoSave());
+					closeInvalidUpperNodeTabs();
+					
+					controller.calculateStateAndVisualForCurrentTimeStep();
+					canvas.repaint();
+					updateUpperNodes();
+				} catch (IOException eex) {
+					eex.printStackTrace();
+				}
+			}
+		});
+
+		String cntrlYDown = "controlY";
+		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 {
+					controller.loadAutoSave(controller.getRedoSave());
+
+					closeInvalidUpperNodeTabs();
+					
+					controller.calculateStateAndVisualForCurrentTimeStep();
+					canvas.repaint();
+					updateUpperNodes();
+				} catch (IOException ex) {
+					ex.printStackTrace();
+				}
+			}
+		});
+
+		String cntrlADown = "controlA";
+		inputMap.put(KeyStroke.getKeyStroke("control A"), cntrlADown);
+		AbstractAction controlA = new AbstractAction() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				chooseTabTemp();
+
+				controller.clearSelection();
+
+				// Uppernode Canvas?
+				JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+				Component canvasOrUpperNodeCanvas = scrollPane.getViewport()
+						.getComponent(0);
+
+				if (canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+					GroupNodeCanvas uNC = (GroupNodeCanvas) canvasOrUpperNodeCanvas;
+					for (AbstractCanvasObject cps : uNC.upperNode.getNodes()) {
+						controller.addSelectedObject(cps);
+					}
+					uNC.repaint();
+					// or Canvas?
+				} else if (canvasOrUpperNodeCanvas instanceof MyCanvas) {
+					for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
+						controller.addSelectedObject(cps);
+					}
+					canvas.repaint();
+				}
+				controller.getObjectsInDepth();
+
+			}
+		};
+		actionMap.put(cntrlADown, controlA);
+
+		String delDown = "delete";
+		inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false),
+				delDown);
+		actionMap.put(delDown, new AbstractAction() {
+
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				chooseTabTemp();
+
+				// Uppernode Canvas?
+				JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+				Component canvasOrUpperNodeCanvas = scrollPane.getViewport()
+						.getComponent(0);
+
+				// check whether a producer was deleted (this triggers a
+				// complete re-evaluation of the net)
+				boolean wasProducerDeleted = true;
+
+				if (canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+					GroupNodeCanvas uNC = (GroupNodeCanvas) canvasOrUpperNodeCanvas;
+					for (AbstractCanvasObject cps : model.getSelectedCpsObjects()) {
+						if (uNC.upperNode.getNodes().contains(cps)) {
+							controller.delObjUpperNode(cps, uNC.upperNode);
+							unc.setToolTip(false);
+
+							// remove UpperNodeTab if UpperNode deleted
+							removeUpperNodeTab(cps);
+						}
+					}
+					uNC.repaint();
+
+					// or Canvas?
+				} else if (canvasOrUpperNodeCanvas instanceof MyCanvas) {
+					boolean save = false;
+					// Edge Deleting
+					Edge edgeHighlight = model.getSelectedEdge();
+					if (edgeHighlight != null) {
+						controller.removeEdgesOnCanvas(edgeHighlight);
+						((MyCanvas) canvasOrUpperNodeCanvas).edgeHighlight = null;
+					}
+					for (int j = 0; j < model.getSelectedCpsObjects().size(); j++) {
+						AbstractCanvasObject cps = model.getSelectedCpsObjects()
+								.get(j);
+						if (j < model.getSelectedCpsObjects().size() - 1)
+							save = true;
+						controller.delCanvasObject(cps, save);
+						canvas.setToolTip(false);
+
+						// remove UpperNodeTab if UpperNode deleted
+						removeUpperNodeTab(cps);
+					}
+					canvas.repaint();
+				}
+
+				// recalculate net if a producer was deleted
+				if (wasProducerDeleted) {
+					controller.resetSimulation();
+					controller.calculateStateAndVisualForCurrentTimeStep();
+				}
+
+				controller.clearSelection();
+				hideScrollGraph();
+			}
+		});
+
+		String cntrlFDown = "controlF";
+		inputMap.put(KeyStroke.getKeyStroke("control F"), cntrlFDown);
+		actionMap.put(cntrlFDown, new AbstractAction() {
+
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				SearchPopUp dialog = new SearchPopUp(controller, canvas,
+						holegJFrame);
+				dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+				dialog.setVisible(true);
+			}
+		});
+
+		String cntrlCDown = "controlC";
+		inputMap.put(KeyStroke.getKeyStroke("control C"), cntrlCDown);
+		AbstractAction controlC = new AbstractAction() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				chooseTabTemp();
+
+				JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+				if (!model.getSelectedCpsObjects().isEmpty()) {
+					if (scrollPane.getViewport().getComponent(0) instanceof GroupNodeCanvas)
+						controller.copy(((GroupNodeCanvas) scrollPane
+								.getViewport().getComponent(0)).upperNode);
+					else
+						controller.copy(null);
+					if (!model.getClipboradObjects().isEmpty()) {
+						canvas.itemPaste.setEnabled(true);
+					}
+				}
+			}
+		};
+		actionMap.put(cntrlCDown, controlC);
+
+		String cntrlVDown = "controlV";
+		inputMap.put(KeyStroke.getKeyStroke("control V"), cntrlVDown);
+		AbstractAction controlV = new AbstractAction() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				try {
+					tabTemp = null;
+					if (tabbedPaneOriginal.getMousePosition() != null) {
+						tabTemp = tabbedPaneOriginal;
+					} else {
+						if (!initSplit) {
+							tabTemp = tabbedPaneSplit;
+						}
+					}
+
+					if(tabTemp == null)return;
+					JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+					Component canvasOrUpperNodeCanvas = scrollPane
+							.getViewport().getComponent(0);
+
+					if (tabTemp != null
+							&& canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+
+						controller
+								.paste(((GroupNodeCanvas) canvasOrUpperNodeCanvas).upperNode,
+										canvasOrUpperNodeCanvas
+												.getMousePosition());
+						controller.calculateStateAndVisualForCurrentTimeStep();
+						scrollPane.getViewport().getComponent(0).repaint();
+					} else {
+						controller.paste(null, canvas.getMousePosition());
+						controller.calculateStateAndVisualForCurrentTimeStep();
+						canvas.repaint();
+					}
+				} catch (HeadlessException | JsonParseException
+						| UnsupportedFlavorException | IOException e1) {
+					JLabel message = new JLabel(
+							"The Clipboard information cannot be pasted into Application.");
+					JOptionPane.showMessageDialog(holegJFrame, message,
+							"", JOptionPane.ERROR_MESSAGE);
+				}
+
+			}
+		};
+		actionMap.put(cntrlVDown, controlV);
+
+		String cntrlXDown = "controlX";
+		inputMap.put(KeyStroke.getKeyStroke("control X"), cntrlXDown);
+		AbstractAction controlX = new AbstractAction() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				chooseTabTemp();
+
+				JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+				if (!model.getSelectedCpsObjects().isEmpty()) {
+					if (scrollPane.getViewport().getComponent(0) instanceof GroupNodeCanvas) {
+						controller.cut(((GroupNodeCanvas) scrollPane
+								.getViewport().getComponent(0)).upperNode);
+						controller.calculateStateAndVisualForCurrentTimeStep();
+						scrollPane.getViewport().getComponent(0).repaint();
+					} else {
+						controller.cut(null);
+						controller.calculateStateAndVisualForCurrentTimeStep();
+						canvas.repaint();
+					}
+					if (!model.getClipboradObjects().isEmpty()) {
+						canvas.itemPaste.setEnabled(true);
+					}
+				}
+			}
+		};
+		actionMap.put(cntrlXDown, controlX);
+
+		holegJFrame.setJMenuBar(menuBar);
+
+		holegJFrame.setIconImage(ImageImport.loadImage(
+				"/Images/Holeg.png", 30, 30));
+
+		menuBar.add(mnNewMenu);
+
+		mnNewMenu.add(mntmNew);
+
+		mnNewMenu.add(mntmOpen);
+
+		mnNewMenu.add(mntmSave);
+
+		menuBar.add(mnNewMenuEdit);
+
+		mnNewMenuEdit.add(mntmUndo);
+
+		mnNewMenuEdit.add(mntmRedo);
+		mntmFindReplace.addActionListener(actionEvent -> {
+			try {
+				SearchPopUp dialog = new SearchPopUp(controller, canvas,
+						holegJFrame);
+				dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+				dialog.setVisible(true);
+				controller.getObjectsInDepth();
+			} catch (Exception ex) {
+				ex.printStackTrace();
+			}
+		});
+
+		mnNewMenuEdit.add(mntmFindReplace);
+		mnNewMenuEdit.add(mntmEditEdges);
+		mntmEditEdges.addActionListener(actionEvent -> {
+			EditEdgesPopUp edgePopUp = new EditEdgesPopUp(holegJFrame);
+			edgePopUp.setCanvas(canvas);
+			edgePopUp.setController(controller);
+			edgePopUp.setVisible(true);
+		});
+		
+		
+		//Edit -> Align All
+		
+		mnNewMenuEdit.add(mntmAlignAll);
+		mntmAlignAll.addActionListener(actionEvent -> {
+			// getScrollPaneFromTabbedPane().getViewport().getComponent(0) is always the active canvas
+			AbstractCanvas activeCanvas = ((AbstractCanvas) getScrollPaneFromTabbedPane().getViewport().getComponent(0));
+			if (activeCanvas != null) {
+				activeCanvas.tryToAlignObjects();
+				activeCanvas.repaint();
+			}
+		});
+		
+		
+		menuBar.add(mnNewMenuOptions);
+
+		mnNewMenuOptions.add(mntmResetCategory);
+		mntmResetCategory.addActionListener(actionEvent -> {
+			ArrayList<Category> cat = model.getCategories();
+			try {
+				while (!cat.isEmpty()) {
+					controller.deleteCategory(cat.get(0).getName());
+
+				}
+				controller.resetCategorys();
+			} catch (Exception e2) {
+				System.out.println(e2.getMessage());
+			}
+			categoryTree.revalidate();
+			categoryTree.repaint();
+		});
+
+
+		/**
+		 * Add Fairness Model Option to the option Menu
+		 */
+		mnNewMenuOptions.add(mnFairnessModel);
+
+		mnFairnessModel.add(mntmFairMinFirst);
+		mntmFairMinFirst.setForeground(Color.BLUE);
+		mntmFairMinFirst
+				.setToolTipText("HolonObjects with the smallest mininum Demand will be partially supplied first.\n"
+						+ "After that as many HolonObjects as possible will get fully supplied.");
+
+		mntmFairMinFirst
+				.addActionListener(arg0 -> {
+					controller.setFairnessModel(FairnessModel.MininumDemandFirst);
+					mntmFairMinFirst.setForeground(Color.BLUE);
+					mntmFairAlleEqual.setForeground(mnFairnessModel
+							.getForeground());
+					controller.calculateStateAndVisualForCurrentTimeStep();
+					// Update UpperNodes
+					Component canvasOrUpperNodeCanvas = getScrollPaneFromTabbedPane()
+							.getViewport().getComponent(0);
+					if (canvasOrUpperNodeCanvas != null
+							&& canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+						((GroupNodeCanvas) canvasOrUpperNodeCanvas).repaint();
+					}
+				});
+
+		mnFairnessModel.add(mntmFairAlleEqual);
+		mntmFairAlleEqual
+				.setToolTipText("HolonObjects will all get the same amount of energy.");
+
+		mntmFairAlleEqual.addActionListener(arg0 -> {
+			controller.setFairnessModel(FairnessModel.AllEqual);
+			mntmFairAlleEqual.setForeground(Color.BLUE);
+			mntmFairMinFirst.setForeground(mnFairnessModel.getForeground());
+			controller.calculateStateAndVisualForCurrentTimeStep();
+			// Update UpperNodes
+				Component canvasOrUpperNodeCanvas = getScrollPaneFromTabbedPane()
+						.getViewport().getComponent(0);
+				if (canvasOrUpperNodeCanvas != null
+						&& canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+					((GroupNodeCanvas) canvasOrUpperNodeCanvas).repaint();
+				}
+			});
+
+		menuBar.add(mnNewMenuView);
+
+		mnNewMenuView.add(mntmCanvasSize);
+		mntmCanvasSize.addActionListener(actionEvent -> {
+			CanvasResizePopUp popUp = new CanvasResizePopUp(model, controller,
+					canvas, tabbedPaneOriginal, tabbedPaneSplit,
+					holegJFrame);
+			popUp.setVisible(true);
+		});
+		
+		mnNewMenuView.add(mntmCanvasSize);
+
+		/*
+		 * Adds Checkbox to turn supply bars on/off
+		 */
+		mnNewMenuView.add(showSupplyBarsCheckBox);
+		showSupplyBarsCheckBox.setSelected(true);
+		showSupplyBarsCheckBox.addActionListener(arg0 -> {
+			controller.setShowSupplyBars(showSupplyBarsCheckBox.isSelected());
+
+			canvas.repaint();
+
+			// Update UpperNodes
+				JScrollPane spane = getScrollPaneFromTabbedPane();
+				if(spane != null){
+					Component canvasOrUpperNodeCanvas = spane.getViewport().getComponent(0);
+					if (canvasOrUpperNodeCanvas != null
+							&& canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+						((GroupNodeCanvas) canvasOrUpperNodeCanvas).repaint();
+					}
+				}
+			});
+		initWindowMenu();
+		
+		
+		
+		
+		mnNewMenuView.add(mntmBackground);
+
+		mntmBackground
+				.addActionListener(actionEvent -> {
+					tabTemp = tabbedPaneOriginal;
+					JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+
+					if (scrollPane.getViewport().getComponent(0) instanceof MyCanvas) {
+						BackgroundPopUp backgroundDialog = new BackgroundPopUp(
+								model, controller, canvas, null,
+								holegJFrame);
+						backgroundDialog
+								.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+						backgroundDialog.setVisible(true);
+					} else if (scrollPane.getViewport().getComponent(0) instanceof GroupNodeCanvas) {
+						GroupNodeCanvas uNodeCanvas = (GroupNodeCanvas) (scrollPane
+								.getViewport().getComponent(0));
+						BackgroundPopUp backgroundDialog = new BackgroundPopUp(
+								model, controller, null, uNodeCanvas.upperNode,
+								holegJFrame);
+						backgroundDialog
+								.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+						backgroundDialog.setVisible(true);
+						uNodeCanvas.repaint();
+					}
+				});
+
+
+
+
+
+		/**
+		 * add Help Menu and its items
+		 */
+		menuBar.add(mnHelp);
+		mnHelp.add(mntmIntroduction); 
+		mnHelp.add(mntmUserManual); 
+		mnHelp.add(mntmAlgorithmHelp); 
+		mnHelp.add(mntmCodeDoc);
+		mnHelp.add(mntmAboutUs);
+
+		tabbedPaneOriginal.addChangeListener(changeEvent -> {
+			if (tabbedPaneOriginal.getSelectedComponent() == null) {
+				Component tempC = tabbedPaneSplit.getSelectedComponent();
+				tabbedPaneSplit.setComponentAt(
+						tabbedPaneOriginal.getSelectedIndex(), null);
+				tabbedPaneOriginal.setComponentAt(
+						tabbedPaneOriginal.getSelectedIndex(), tempC);
+				tempC = tabbedPaneOriginal.getComponentAt((tabbedPaneOriginal
+						.getSelectedIndex() + 1)
+						% (tabbedPaneOriginal.getTabCount()));
+				tabbedPaneOriginal.setComponentAt(
+						(tabbedPaneOriginal.getSelectedIndex() + 1)
+								% (tabbedPaneOriginal.getTabCount()), null);
+				tabbedPaneSplit.setComponentAt(
+						(tabbedPaneOriginal.getSelectedIndex() + 1)
+								% (tabbedPaneOriginal.getTabCount()), tempC);
+				tabbedPaneSplit.setSelectedIndex((tabbedPaneOriginal
+						.getSelectedIndex() + 1)
+						% (tabbedPaneOriginal.getTabCount()));
+				contentPane.updateUI();
+			}
+		});
+
+		tabbedPaneSplit.addChangeListener(changeEvent -> {
+			if (tabbedPaneSplit.getSelectedComponent() == null && !initSplit) {
+				Component tempC = tabbedPaneOriginal
+						.getComponentAt(tabbedPaneSplit.getSelectedIndex());
+				tabbedPaneOriginal.setComponentAt(
+						tabbedPaneSplit.getSelectedIndex(), null);
+				tabbedPaneSplit.setComponentAt(
+						tabbedPaneSplit.getSelectedIndex(), tempC);
+
+				for (int i = 0; i < tabbedPaneOriginal.getTabCount(); i++) {
+					if (tabbedPaneSplit.getComponentAt(i) != null
+							&& tabbedPaneSplit.getComponentAt(i) != tempC) {
+						tempC = tabbedPaneSplit.getComponentAt(i);
+						tabbedPaneSplit.setComponentAt(i, null);
+						tabbedPaneOriginal.setComponentAt(i, tempC);
+						break;
+					}
+				}
+				if (tabbedPaneOriginal.getSelectedIndex() == tabbedPaneSplit
+						.getSelectedIndex()) {
+					tabbedPaneOriginal.setSelectedIndex((tabbedPaneSplit
+							.getSelectedIndex() + 1)
+							% tabbedPaneOriginal.getTabCount());
+				}
+				contentPane.updateUI();
+			}
+		});
+		canvas.setBackground(Color.WHITE);
+		canvas.setPreferredSize(new Dimension(model.getCanvasX(), model
+				.getCanvasY()));
+		/********************
+		 * RIGHT CONTAINER (INFORMATION)
+		 **********************/
+		// Set up of the HolonElements section
+		// Two different Models: Multi for multi-selection mode and Single for
+		// single-selection mode (CPS-Object)
+		model.getMultiTable().setColumnIdentifiers(columnNamesMulti);
+		model.getSingleTable().setColumnIdentifiers(columnNamesSingle);
+		model.getTableHolonElement().setBorder(null);
+		model.getTableHolonElement().setFillsViewportHeight(true);
+		model.getTableHolonElement().setCellSelectionEnabled(true);
+		model.getTableHolonElement().setColumnSelectionAllowed(true);
+		/*
+		 * Register Clicks on ColumNames for sorting:
+		 */
+		model.getTableHolonElement().getTableHeader()
+				.addMouseListener(new MouseAdapter() {
+					public void mouseClicked(MouseEvent e) {
+						//TODO: sort
+						//clicked column
+						int col = model.getTableHolonElement().columnAtPoint(
+								e.getPoint());
+						//insert column into UpdateController
+						updCon.setSortBy(col);
+						//refresh HolonElementTable
+						updCon.refreshTableHolonElement(model.getMultiTable(), model.getSingleTable());
+					}
+					
+
+					@Override
+					public void mouseExited(MouseEvent e) {
+						/**
+						 * Stop Editing, if mouse exits the Table
+						 */
+						JTable holElem = model.getTableHolonElement();
+						JTableHeader holElemHead = holElem.getTableHeader();
+						if(e.getX()<=0 || e.getX()>=holElemHead.getWidth() 
+								|| e.getY() <= 0){
+							CellEditor cellEditor = holElem.getCellEditor();
+							if (cellEditor != null) {
+							    if (cellEditor.getCellEditorValue() != null) {
+							    	/** TODO: Maybe try to save current Data */
+							        cellEditor.stopCellEditing();
+							    } else {
+							        cellEditor.cancelCellEditing();
+							    }
+							}
+						}
+						
+					}
+				});
+		model.getTableHolonElement().getTableHeader().setReorderingAllowed(false);
+
+		tableHolonElementScrollPane.setViewportView(model
+				.getTableHolonElement());
+		scrollElements.setLayout(new BorderLayout(0, 0));
+		scrollElements.add(panelHolonEl, BorderLayout.NORTH);
+		scrollElements.add(tableHolonElementScrollPane);
+		panelHolonEl.setLayout(new BoxLayout(panelHolonEl, BoxLayout.X_AXIS));
+		toolBarHolonEl.add(btnAddHolEL);
+		toolBarHolonEl.add(btnDelHolEL);
+		toolBarHolonEl.setFloatable(false);
+		panelHolonEl.add(toolBarHolonEl);
+
+		// Set up of the Properties section
+		scrollProperties.setViewportView(this.informationPanel);
+		scrollProperties.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+		scrollProperties.getVerticalScrollBar().setUnitIncrement(16);
+		
+		// Set up of the Graph section
+		scrollGraph.setViewportView(unitGraph);
+		graphLabel.setLayout(new BorderLayout(0, 10));
+		graphLabel.add(maxGraph, BorderLayout.NORTH);
+		graphLabel.add(medGraph, BorderLayout.CENTER);
+		graphLabel.add(minGraph, BorderLayout.SOUTH);
+
+		
+		
+		
+		
+		toolBarGraph.setFloatable(false);
+		toolBarGraph.setAlignmentY(Component.RIGHT_ALIGNMENT);	
+		
+		
+		localPeriodButton.setToolTipText("Toggle Local/Global Mode");
+		toolBarGraph.add(localPeriodButton);
+		//ComboBox
+		localPeriodInput.setEditable(true);
+		localPeriodInput.setVisible(false);
+		localPeriodInput.setMaximumSize(new Dimension(20,23));
+		localPeriodInput.addItemListener(aListener->{
+			if(aListener.getStateChange() == ItemEvent.DESELECTED) {
+				validateInput(localPeriodInput.getEditor().getItem().toString(), true);
+			}
+			
+		});
+		
+		toolBarGraph.add(localPeriodInput);
+				
+		//localPeriodButtonFunction
+		localPeriodButton.addActionListener(actionEvent->{
+			boolean newState= !localPeriodInput.isVisible();
+			changeLocalPeriodButtonAppeareance(newState);
+			unitGraph.setUseLocalPeriod(newState);
+		});
+		
+		
+		toolBarGraph.add(Box.createHorizontalGlue());
+		resetButton.setToolTipText("Reset");
+		resetButton.addActionListener(actionEvent ->  unitGraph.reset());
+		toolBarGraph.add(resetButton);
+		
+		
+		
+		
+		
+		scrollGraph.setRowHeaderView(graphLabel);
+		scrollGraph.setColumnHeaderView(toolBarGraph);
+
+		tables.add(model.getSingleTable());
+		tables.add(model.getMultiTable());
+		/***********************
+		 * HolonElement Table Actions
+		 **********************/
+		/*
+		 * Add HolonElement to given HolonObject
+		 */
+		btnAddHolEL.addActionListener(actionEvent -> {
+			if (model.getSelectedCpsObjects().size() == 1) {
+				AbstractCanvasObject tempCpsObject = updCon.getActualCps();
+				if (tempCpsObject != null
+						&& tempCpsObject.getClass() == HolonObject.class
+						&& tempCpsObject.getId() != 0) {
+					addElementPopUp = new AddElementPopUp(holegJFrame);
+					addElementPopUp.setActualHolonObject((HolonObject)updCon.getActualCps());
+					addElementPopUp.setVisible(true);
+					HolonElement ele = addElementPopUp.getElement();
+					if (ele != null) {
+						controller.addElementCanvasObject(
+								tempCpsObject.getId(), ele.getEleName(),
+								ele.getAmount(), ele.getEnergyPerElement(),
+								ele.getId());
+					}
+					controller.calculateStateAndVisualForTimeStep(model
+							.getCurIteration());
+					triggerUpdateController(null);
+					contentPane.updateUI();
+				}
+			}else
+			{
+				JOptionPane.showMessageDialog(contentPane, "No object selected.\nPlease select a object first." , "Message" , JOptionPane.INFORMATION_MESSAGE);
+			}
+		});
+		btnAddHolEL.setIcon(new ImageIcon(ImageImport.loadImage("Images/plus.png", 16, 16)));
+		btnAddHolEL.setToolTipText("<html><b>Add Element</b><br>Add a new HolonElement to the HolonObject.</html>");
+		
+		
+		/*
+		 * Delete the chosen HolonElement of the selected HolonObject,
+		 * Multi-Selection for CpsObjects as well as for HolonElements possible
+		 */
+		btnDelHolEL.addActionListener(actionEvent -> {
+			// For Single Selection of CpsObject
+				if (model.getSelectedCpsObjects().size() == 1) {
+					if (updCon.getActualCps().getClass() == HolonObject.class) {
+						HolonObject obj = (HolonObject) updCon.getActualCps();
+						if(selectedElements.isEmpty())
+						{
+							JOptionPane.showMessageDialog(contentPane, "No element selectet.\nPlease select a element in the list first." , "Message" , JOptionPane.INFORMATION_MESSAGE);
+						}
+						for (HolonElement e : selectedElements) {
+							controller.deleteElementCanvas(obj.getId(),
+									e.getId());
+							controller.calculateStateAndVisualForTimeStep(model
+									.getCurIteration());
+							triggerUpdateController(null);
+							contentPane.updateUI();
+							// Names displayed in graph are not updated
+			}
+			model.getEleToDelete().clear();
+			selectedElements.clear();
+		}
+		// For MultiSelection of CpsObject
+	} else if (model.getSelectedCpsObjects().size() > 1) {
+		for (Integer i : model.getEleToDelete().keySet()) {
+			for (HolonElement e : model.getEleToDelete().get(i)) {
+				controller.deleteElementCanvas(i, e.getId());
+			}
+		}
+		triggerUpdateController(null);
+		model.getEleToDelete().clear();
+		selectedElements.clear();
+	}else
+			{
+				JOptionPane.showMessageDialog(contentPane, "No object selectet.\nPlease select a object first." , "No object selectet" , JOptionPane.INFORMATION_MESSAGE);
+			}
+	triggerUpdateController(null);
+	elementGraph.setText("None");
+	holonEleNamesDisplayed = "None";
+})		;
+		btnDelHolEL.setIcon(new ImageIcon(ImageImport.loadImage("Images/minus.png", 16, 16)));
+		btnDelHolEL.setToolTipText("<html><b>Remove Element</b><br>Removes the selected HolonElement from the HolonObject.</html>");
+		/*
+		 * Communication between HolonElement Table and displayed Graph and
+		 * Properties, as well as selection of different HolonElements
+		 */
+		model.getTableHolonElement().addMouseListener(new MouseAdapter() {
+			public void mousePressed(MouseEvent e) {
+				HolonObject obj = null;
+				if (model.getSelectedCpsObjects().size() == 1
+						&& model.getSelectedCpsObjects().get(0) instanceof HolonObject) {
+					obj = (HolonObject) updCon.getActualCps();
+				}
+				yValueElements = e.getY();
+				HolonElement ele;
+				// Search for current clicked HolonElement
+				if (model.getSelectedCpsObjects().size() == 1) {
+					ele = updCon.getActualHolonElement(obj, yValueElements, 0,
+							tables);
+				} else {
+					ele = updCon.getActualHolonElement(null, yValueElements, 0,
+							tables);
+				}
+				// Multi-Selection of HolonElements through control button +
+				// mouse click
+				if (ele != null) {
+					// make energy-consumption graph visible
+					showScrollGraph();
+
+					if (e.isControlDown()) {
+						if (!selectedElements.contains(ele)) {
+							selectedElements.add(ele);
+							if (!holonEleNamesDisplayed.equals("None")) {
+								holonEleNamesDisplayed = holonEleNamesDisplayed
+										+ "; " + ele.getEleName() + " ";
+							} else {
+								holonEleNamesDisplayed = ele.getEleName() + " ";
+							}
+							updateUnitGraph((GraphEditable)selectedElements.get(selectedElements.size()-1));
+						}
+						updCon.getActualHolonElement(null, yValueElements, 2,
+								tables);
+					}
+					// if no control-button pressed but a HolonElement chosen
+					else {
+						selectedElements.clear();
+						selectedElements.add(ele);
+						updCon.getActualHolonElement(null, yValueElements, 1,
+								tables);
+						holonEleNamesDisplayed = ele.getEleName() + " ";
+						updateUnitGraph((GraphEditable)selectedElements.get(selectedElements.size()-1));
+					}
+				} else {
+					elementGraph.setText("None");
+					hideScrollGraph();
+				}
+				// if any HolonElement is double-clicked --> Edit-Mode started
+				// for selected HolonElement
+				if (e.getClickCount() == 2) {
+					yThis = e.getY();
+					xThis = e.getX();
+				}
+				// for single click and empty slot
+				if (e.getClickCount() == 1 && ele == null) {
+					selectedElements.clear();
+					holonEleNamesDisplayed = "None";
+				}
+				elementGraph.setText(holonEleNamesDisplayed);
+				yBTis = e.getY();
+				xBThis = e.getX();
+
+			}
+			
+			@Override
+			public void mouseExited(MouseEvent e) {
+				/**
+				 * Stop Editing, if mouse exits the Table
+				 */
+				JTable holElem = model.getTableHolonElement();
+				if(e.getX()<=0 || e.getX()>=holElem.getWidth() 
+						/*|| e.getY() <= 0*/|| e.getY()>= holElem.getHeight()){
+					CellEditor cellEditor = holElem.getCellEditor();
+					if (cellEditor != null) {
+					    if (cellEditor.getCellEditorValue() != null) {
+					    	/** TODO: Maybe try to save current Data */
+					        cellEditor.stopCellEditing();
+					    } else {
+					        cellEditor.cancelCellEditing();
+					    }
+					}
+				}
+				
+			}
+			
+		});
+		
+		/*
+		 * Triggered every time a change is made
+		 */
+		model.getTableHolonElement()
+				.addPropertyChangeListener(propertyChangeEvent -> {
+					try {
+						int yMouse = yThis;
+						int yBMouse = yBTis;
+						int selectedValueY = (int) Math.floor(yMouse / 16);
+						int selectedValueBY = (int) Math.floor(yBMouse / 16);
+						// ------------------ multi-selection mode
+						// ------------------
+						if (model.getSelectedCpsObjects().size() > 1) {
+							int selectedValueX = (int) Math
+									.floor(xThis
+											/ (model.getTableHolonElement()
+													.getWidth() / 8));
+							int selectedValueBX = (int) Math
+									.floor(xBThis
+											/ (model.getTableHolonElement()
+													.getWidth() / 8));
+							if (updCon.getHolonObj(yMouse,
+									model.getMultiTable()) != null) {
+								// For active column (boolean with a checkbox)
+								if (selectedValueBX == 6) {
+									System.out.println("selectedValueBX == 6");
+									HolonElement eleBTemp = updCon
+											.getActualHolonElement(null,
+													yBMouse, 0, tables);
+									String newBStuff = model
+											.getMultiTable()
+											.getValueAt(selectedValueBY,
+													selectedValueBX).toString();
+									Boolean bTemp = Boolean
+											.parseBoolean(newBStuff);
+									eleBTemp.setActive(bTemp);
+								}
+								// For activeFlex column (boolean with a
+								// checkbox)
+								else if (selectedValueBX == 7) {
+									HolonElement eleBTemp = updCon
+											.getActualHolonElement(null,
+													yBMouse, 0, tables);
+									String newBStuff = model
+											.getMultiTable()
+											.getValueAt(selectedValueBY,
+													selectedValueBX).toString();
+									Boolean bTemp = Boolean
+											.parseBoolean(newBStuff);
+									eleBTemp.setActive(bTemp);
+								} else {
+									//TODO: check all possible fields.
+									// Update of HolonElement
+									HolonElement eleTemp = updCon
+											.getActualHolonElement(null,
+													yMouse, 0, tables);
+									String newStuff = model
+											.getMultiTable()
+											.getValueAt(selectedValueY,
+													selectedValueX).toString();
+									
+									// Name update
+									if (selectedValueX == 2) {
+										eleTemp.setEleName(newStuff);
+									}
+									// Energy Update
+									else if (selectedValueX == 3) {
+										Float ftemp = Float
+												.parseFloat(newStuff);
+										eleTemp.setEnergyPerElement(ftemp);
+									}
+									// Flexibility
+									else if (selectedValueX == 4) {
+										
+										
+										
+									}
+									// Amount of Elements update
+									else if (selectedValueX == 5) {
+										Integer iTemp = Integer
+												.parseInt(newStuff);
+										eleTemp.setAmount(iTemp);
+									}
+									else if (selectedValueX == 6) {
+									}
+								}
+							}
+						} // ------------------ single-selection mode
+							// ------------------
+						else if (model.getSelectedCpsObjects().size() == 1) {
+							int selectedValueX = (int) Math
+									.floor(xThis
+											/ (model.getTableHolonElement()
+													.getWidth() / 7));
+							int selectedValueBX = (int) Math
+									.floor(xBThis
+											/ (model.getTableHolonElement()
+													.getWidth() / 7));
+							if (updCon.getActualCps() != null
+									&& updCon.getActualCps().getClass() == HolonObject.class) {
+								HolonElement eleTemp;
+
+								// For active column (boolean with a checkbox)
+								if (selectedValueBX == 5) {
+									eleTemp = updCon.getActualHolonElement(
+											(HolonObject) updCon.getActualCps(),
+											yBMouse, 0, tables);
+									String newBStuff = model
+											.getSingleTable()
+											.getValueAt(selectedValueBY,
+													selectedValueBX).toString();
+									Boolean bTemp = Boolean
+											.parseBoolean(newBStuff);
+									eleTemp.setActive(bTemp);
+
+								} // For activeFlex column (boolean with a
+									// checkbox)
+								else if (selectedValueBX == 6) {
+									eleTemp = updCon.getActualHolonElement(
+											(HolonObject) updCon.getActualCps(),
+											yBMouse, 0, tables);
+									String newBStuff = model
+											.getSingleTable()
+											.getValueAt(selectedValueBY,
+													selectedValueBX -1).toString();
+									eleTemp.setActive(Boolean
+											.parseBoolean(newBStuff));
+
+								} else {
+									//TODO check all possible assignements.
+									// Update of HolonElement
+									eleTemp = updCon.getActualHolonElement(
+											(HolonObject) updCon.getActualCps(),
+											yMouse, 0, tables);
+									String newStuff = model
+											.getSingleTable()
+											.getValueAt(selectedValueY,
+													selectedValueX).toString();
+									// Name update
+									if (selectedValueX == 1) {
+										eleTemp.setEleName(newStuff);
+									} // Energy Update
+									else if (selectedValueX == 2) {
+										Float ftemp = Float
+												.parseFloat(newStuff);
+										eleTemp.setEnergyPerElement(ftemp);
+									} // Flexibility
+									else if (selectedValueX == 3) {
+									}
+									// Amount of Elements update
+									else if (selectedValueX == 4) {
+										Integer iTemp = Integer
+												.parseInt(newStuff);
+										eleTemp.setAmount(iTemp);
+									}
+								}
+
+								// set all cells anew, if anything was changed
+								updateElementTableAfterChange(eleTemp,
+										selectedValueBY);
+							}
+						}
+						controller.calculateStateAndVisualForTimeStep(model
+								.getCurIteration());
+						model.getSingleTable().fireTableDataChanged();
+						triggerUpdateController(null);
+						contentPane.updateUI();
+						unitGraph.repaint();
+
+						// trigger update of table after UnitGraph was painted
+						SwingUtilities.invokeLater(() -> {
+							triggerUpdateController(null);
+						});
+					} catch (Exception e) {
+					}
+				});
+	
+		/***********************
+		 * HolonElement Graph Actions
+		 **********************/
+		
+		/*
+		 * Update Local Period of an Element Graph
+		 */
+		unitGraphLocalPeriod.addKeyListener(new KeyAdapter() {
+			@Override
+			 public void keyReleased(KeyEvent e) {
+				try{
+					int localLength = Integer.parseInt(unitGraphLocalPeriod.getText());
+					unitGraphLocalPeriod.setBackground(Color.WHITE);
+					/**
+					 * set local graph Period
+					 */
+					if(e.getKeyCode() == KeyEvent.VK_ENTER)
+						unitGraph.setLocalPeriod(localLength);						
+				}catch(NumberFormatException ex){
+					unitGraphLocalPeriod.setBackground(PALE_RED);
+				}
+				
+			}
+		});
+		
+		/*****************************
+		 * RIGHT CONTAINER DONE
+		 *****************************/
+
+		holegJFrame.getContentPane().setLayout(new BorderLayout(0, 0));
+		/****************
+		 * Tree Stuff
+		 ****************/
+
+		// Override Key Actions
+		inputMap = categoryTree.getInputMap();
+		inputMap.put(KeyStroke.getKeyStroke("control C"), cntrlCDown);
+		inputMap.put(KeyStroke.getKeyStroke("control V"), cntrlVDown);
+		inputMap.put(KeyStroke.getKeyStroke("control X"), cntrlXDown);
+		inputMap.put(KeyStroke.getKeyStroke("control A"), cntrlADown);
+
+		TreeCellRenderer customRenderer = new TreeCellRenderer() {
+			@Override
+			public Component getTreeCellRendererComponent(JTree tree,
+					Object value, boolean selected, boolean expanded,
+					boolean leaf, int row, boolean hasFocus) {
+				JLabel label = new JLabel();
+				Image imgR;
+				if (leaf) {
+					for (Category cat : model.getCategories()) {
+						for (AbstractCanvasObject cps : cat.getObjects()) {
+							if (value.toString().compareTo(cps.getObjName()) == 0) {
+								imgR = ImageImport.loadImage(cps.getImage(), 50,
+										50);
+								if (imgR != null) {
+									label.setIcon(new ImageIcon(imgR));
+								}
+								label.setText(cps.getName());
+							}
+						}
+					}
+				}
+				tree.setRowHeight(50);
+				if (hasFocus) {
+					label.setForeground(new Color(0, 0, 255));
+					label.setOpaque(true);
+				}
+				if (label.getText().length() == 0) {
+					label.setText(value.toString());
+					if (value.toString().compareTo("Categories") != 0) {
+						label.setIcon(new ImageIcon(ImageImport.loadImage(
+								"/Images/folder.png")));
+					}
+				}
+
+				return label;
+
+			}
+		};
+		
+		categoryTree.setCellRenderer(customRenderer);
+
+		categoryTree.addMouseMotionListener(new MouseMotionAdapter() {
+
+			public void mouseDragged(MouseEvent e){
+				checkForDragAndDrop(e);
+			}
+			
+			/**
+			 * checks if an object of the current Panel
+			 * could be replaced by the dragged object
+			 * @param e
+			 */
+			private void checkForDragAndDrop(MouseEvent e){
+				try {
+					/**
+					 * if no object gets dragged -> finished
+					 */
+					if(!dragging)return;
+					
+					/**
+					 * select the current Panel
+					 */
+					chooseTabTemp();				
+					JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+					if(scrollPane == null)return;
+					Component canvasOrUpperNodeCanvas = scrollPane
+							.getViewport().getComponent(0);
+					
+					/**
+					 * check for replacements on the canvas
+					 */
+					if (canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+						GroupNodeCanvas unc = (GroupNodeCanvas) canvasOrUpperNodeCanvas;
+						if(unc.getMousePosition()==null)return;
+						int x = (int) unc.getMousePosition().getX()+16;
+						int y = (int) unc.getMousePosition().getY()+16;
+						
+						/**
+						 * if in upperNode
+						 */
+						if (x <= unc.upperNode.getLeftBorder()) return;
+						
+						/**
+						 * check for replacement
+						 */
+						unc.checkForReplacement(x, y);
+						
+						/**
+						 * repaint 
+						 */
+						unc.invalidate();
+						unc.repaint();
+					} else {
+						if(canvas.getMousePosition()==null)return;
+						int x = (int) canvas.getMousePosition().getX()+16;
+						int y = (int) canvas.getMousePosition().getY()+16;
+						
+						/**
+						 * check for replacement
+						 */
+						canvas.checkForReplacement(x, y);
+						
+						/**
+						 * repaint
+						 */
+						canvas.invalidate();
+						canvas.repaint();
+					}
+					contentPane.updateUI();
+					
+				} catch (Exception eex) {
+					eex.printStackTrace();
+				}
+			}});
+
+		
+		categoryTree.addMouseListener(new MouseAdapter() {
+			
+			public void mouseReleased(MouseEvent e) {
+				try {
+					if (dragging) {
+						chooseTabTemp();
+						JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+						Component canvasOrUpperNodeCanvas = scrollPane
+								.getViewport().getComponent(0);
+
+						if (canvasOrUpperNodeCanvas instanceof GroupNodeCanvas) {
+							GroupNodeCanvas unc = (GroupNodeCanvas) canvasOrUpperNodeCanvas;
+							int x = (int) unc.getMousePosition().getX() + 16;
+							int y = (int) unc.getMousePosition().getY() + 16;
+
+							if (x > unc.upperNode.getLeftBorder()) {
+
+								AbstractCanvasObject h = null;
+								if (tempCps instanceof HolonObject) {
+									h = new HolonObject((HolonObject)tempCps);
+								}
+								if (tempCps instanceof HolonSwitch) {
+									h = new HolonSwitch(tempCps);
+								}
+								h.setPosition(x, y);
+
+								/**
+								 * close UpperNodeTabs of replaced UpperNode
+								 */
+								if(unc.mayBeReplaced!=null &&unc.mayBeReplaced instanceof GroupNode){
+									unc.closeUpperNodeTab(unc.mayBeReplaced.getId());
+								}
+								controller.addObjUpperNode(h, unc.upperNode);
+								
+								/**
+								 * object would be replaced
+								 */
+								unc.mayBeReplaced = null; 
+								unc.invalidate();
+								controller.calculateStateAndVisualForCurrentTimeStep();
+								unc.repaint();
+								unc.setXY((int) canvas.getMousePosition()
+										.getX(), (int) canvas
+										.getMousePosition().getY());
+							}
+						} else {
+							int x = (int) canvas.getMousePosition().getX() + 16;
+							int y = (int) canvas.getMousePosition().getY() + 16;
+
+							AbstractCanvasObject h = null;
+							if (tempCps instanceof HolonObject) {
+								h = new HolonObject((HolonObject)tempCps);
+							}
+							if (tempCps instanceof HolonSwitch) {
+								h = new HolonSwitch(tempCps);
+							}
+							
+							h.setPosition(x, y);
+							
+							/**
+							 * close UpperNodeTabs of replaced UpperNode
+							 */
+							if(canvas.mayBeReplaced!=null &&canvas.mayBeReplaced instanceof GroupNode){
+								canvas.closeUpperNodeTab(canvas.mayBeReplaced.getId());
+							}
+							controller.addObjectCanvas(h);
+							/**
+							 * no object should get replaced
+							 */
+							canvas.mayBeReplaced = null;
+							canvas.invalidate();
+							canvas.setXY(
+									(int) canvas.getMousePosition().getX(),
+									(int) canvas.getMousePosition().getY());
+							canvas.repaint();
+						}
+						controller.calculateStateAndVisualForCurrentTimeStep();
+						contentPane.updateUI();
+						dragging = false;
+					}
+				} catch (Exception eex) {
+				}
+				holegJFrame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+			}
+		});
+		
+
+		popmenuEdit.add(editItem);
+		popmenuEdit.add(removeItem);
+		editItem.setEnabled(false);
+		editItem.addActionListener(actionEvent -> {
+		});
+		categoryTree.addMouseListener(new MouseAdapter() {
+		
+			public void mousePressed(MouseEvent e) {
+				try {
+					actualObjectClicked = categoryTree
+							.getPathForLocation(e.getX(), e.getY())
+							.getLastPathComponent().toString();
+					// if an Object was selected, the porperties are shown in
+					// the table
+					DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) categoryTree
+							.getPathForLocation(e.getX(), e.getY())
+							.getLastPathComponent();
+					if (selectedNode.getLevel() == 2) {
+						controller.searchCategoryObject(selectedNode
+								.getParent().toString(), selectedNode
+								.toString());
+						updCon.deleteRows(model.getSingleTable());
+						updCon.deleteRows(model.getMultiTable());
+						// if (selected instanceof HolonObject && selected !=
+						// null) {
+						// selected = (HolonObject) selected;
+						// fillElementTable(((HolonObject)
+						// selected).getElements());
+						// }
+					}
+					if (SwingUtilities.isRightMouseButton(e)) {
+						for (Category cat : model.getCategories()) {
+							for (AbstractCanvasObject cps : cat.getObjects()) {
+								if (actualObjectClicked.compareTo(cps
+										.getObjName()) == 0
+										&& !(cps instanceof HolonSwitch)) {
+									editItem.setEnabled(true);
+									popmenuEdit.show(e.getComponent(),
+											e.getX(), e.getY());
+									catOfObjToBeEdited = selectedNode
+											.getParent().toString();
+									tempCps = cps;
+								}
+							}
+						}
+					} else {
+						for (Category cat : model.getCategories()) {
+							for (AbstractCanvasObject cps : cat.getObjects()) {
+								if (actualObjectClicked.compareTo(cps
+										.getObjName()) == 0) {
+									File checkPath = new File(cps.getImage());
+									if (checkPath.exists()) {
+										img = new ImageIcon(cps.getImage())
+												.getImage()
+												.getScaledInstance(
+														32,
+														32,
+														java.awt.Image.SCALE_SMOOTH);
+									} else {
+										img = ImageImport.loadImage(
+												cps.getImage(), 32, 32);
+									}
+									tempCps = cps;
+									dragging = true;
+									Cursor cursor = Toolkit.getDefaultToolkit()
+											.createCustomCursor(img,
+													new Point(0, 0), "Image");
+									holegJFrame.setCursor(cursor);
+								}
+							}
+						}
+					}
+				} catch (Exception eex) {
+				}
+			}
+		});
+		editItem.addActionListener(actionEvent -> {
+			// Remove the selected Object object
+			//AddObjectPopUp(boolean edit, AbstractCpsObject obj, String cat, JFrame parentFrame)
+			System.out.println("Edit");
+			addObjectPopUP = new AddObjectPopUp(true, tempCps,
+					catOfObjToBeEdited, holegJFrame);
+			addObjectPopUP.setCategory(catOfObjToBeEdited);
+			addObjectPopUP.setController(controller);
+			addObjectPopUP.setVisible(true);
+		});
+		removeItem.addActionListener(actionEvent -> {
+			// Remove the selected Object object
+			try {
+				System.out.println("catOfObjToBeEdited:" + catOfObjToBeEdited + ", tempCps:" + tempCps);
+				controller.delObjectCategory(catOfObjToBeEdited, tempCps.getName());				
+			}catch(IOException e) {
+				System.err.println("IOException");
+				e.printStackTrace();
+			}
+		});
+		scrollPane1.setViewportView(categoryTree);
+
+		scrollPane1.setColumnHeaderView(panel);
+		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+		toolBar.setAlignmentX(Component.LEFT_ALIGNMENT);
+		toolBar.setFloatable(false);
+
+		panel.add(toolBar);
+		btnAddPopUp.add(mItemNew);
+		mItemNew.addActionListener(actionEvent -> {
+			new CreateNewDialog(controller, holegJFrame);
+		});
+		btnAddPopUp.addSeparator();
+		btnAddPopUp.add(mItemCategory);
+		mItemCategory.addActionListener(actionEvent -> {
+			new CreateNewDialog(controller,Option.Category, holegJFrame);
+		});
+		btnAddPopUp.add(mItemObject);
+		mItemObject.addActionListener(actionEvent -> {
+			new CreateNewDialog(controller,Option.Object, holegJFrame);
+		});
+		btnAddPopUp.add(mItemSwitch);
+		mItemSwitch.addActionListener(actionEvent -> {
+			new CreateNewDialog(controller,Option.Switch, holegJFrame);
+		});
+		btnAdd.addActionListener(actionEvent -> btnAddPopUp.show(btnAdd, -1, +20));
+		btnAdd.setIcon(new ImageIcon(ImageImport.loadImage("Images/plus.png", 16, 16)));
+		btnAdd.setToolTipText("<html><b>New</b><br>Add a new Category or Item to the library.</html>");
+		toolBar.add(btnAdd);
+		/**
+		 * Help Menu Action Listeners
+		 */
+		
+		/**
+		 * URL of the telecommunication git Wiki
+		 */
+		String tkWikiWebpage = "https://git.tk.informatik.tu-darmstadt.de/carlos.garcia/praktikum-holons/wiki/";
+		
+		/** open Introduction Web Page */
+		mntmIntroduction.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e){
+				openWebpage(tkWikiWebpage + "Introduction+V2.1");
+			}
+		});
+		
+		/** open UserManual WebPage */
+		mntmUserManual.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e){
+				openWebpage(tkWikiWebpage + "User+Manual+V2.1");
+			}
+		});
+		
+		/** open Algorithm Help Web Page*/
+		mntmAlgorithmHelp.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e){
+				openWebpage(tkWikiWebpage + "Algorithms+V2.1");
+			}
+		});
+		
+		/** open Code Documentation Web Page */
+		mntmCodeDoc.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e){
+				openWebpage(tkWikiWebpage + "Code+documentation+V2.1");
+			}
+		});
+		
+		/**
+		 * Pop up - About Us with some important information about the
+		 * developers, source and programming stuff
+		 */
+		mntmAboutUs.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e) {
+				aboutUsPopUp = new AboutUsPopUp(holegJFrame);
+				aboutUsPopUp.setVisible(true);
+			}
+		});
+
+		/**
+		 * Update of every interaction between the user and the canvas (only on
+		 * the canvas). Basically the update of all the information concerning
+		 * the clicked HolonObject. For multi-selection, the propertyTable would
+		 * be disabled
+		 */
+		canvas.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e) {
+
+			}
+
+			@Override
+			public void mouseReleased(MouseEvent e) {
+				holonEleNamesDisplayed = "None";
+				// If any empty space is clicked
+				if (temp == null || temp.getId() != model.getSelectedObjectID()) {
+					hideScrollGraph();
+					elementGraph.setText("None");
+				}
+				temp = updCon.getActualCps();
+				// Erase old data in the PropertyTable
+				if (model.getPropertyTable().getRowCount() > 0) {
+					for (int i = model.getPropertyTable().getRowCount() - 1; i > -1; i--) {
+						model.getPropertyTable().removeRow(i);
+					}
+				}
+				if (e.isControlDown() && temp != null) {
+					if (model.getSelectedCpsObjects().contains(temp)) {
+						controller.removeSelectedObjectFromSelection(temp);
+					} else {
+						controller.addSelectedObject(temp);
+					}
+				}
+				if (temp instanceof HolonSwitch) {
+					showScrollGraph();
+					updateUnitGraph((GraphEditable)temp);
+				}
+				// Write new data in the PropertyTable
+				triggerUpdateController(temp);
+
+				// New Tab with NodeOfNode
+				if (doubleClick() && MouseEvent.BUTTON3 != e.getButton()
+						&& temp instanceof GroupNode) {
+					openNewUpperNodeTab();
+					try {
+						controller.autoSave();
+					} catch (IOException e1) {
+						e1.printStackTrace();
+					}
+				}
+				if (model.getSelectedCpsObjects().size() > 1) {
+					model.getTableHolonElement()
+							.setModel(model.getMultiTable());
+				} else if (model.getSelectedCpsObjects().size() == 1) {
+					model.getTableHolonElement().setModel(
+							model.getSingleTable());
+				}
+
+			}
+
+		});
+
+
+		
+
+		// Del Button
+		btnDel.addActionListener(actionEvent -> {
+			Object nodeInfo = categoryTree.getLastSelectedPathComponent();
+			if (nodeInfo != null) {
+				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) nodeInfo;
+				String nodeName = selectedNode.getUserObject().toString();
+				int depthOfNode = selectedNode.getLevel();
+				try {
+					switch (depthOfNode) {
+					case 1:
+						int dialogResult = JOptionPane.showConfirmDialog(
+								holegJFrame, eraseCategory + nodeName
+										+ "?", warningText,
+								JOptionPane.YES_NO_OPTION);
+						if (dialogResult == JOptionPane.YES_OPTION) {
+							controller.deleteCategory(nodeName);
+						}
+						break;
+					case 2:
+						DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode
+								.getParent();
+						controller.delObjectCategory(parent.getUserObject()
+								.toString(), nodeName);
+						break;
+
+					default:
+						JOptionPane.showMessageDialog(holegJFrame,
+								selectObjBeforeErase);
+					}
+				} catch (Exception e2) {
+				}
+
+			} else {
+				JOptionPane.showMessageDialog(holegJFrame,
+						selectObjBeforeErase);
+			}
+			categoryTree.repaint();
+		});
+		btnDel.setIcon(new ImageIcon(ImageImport.loadImage("Images/minus.png", 16, 16)));
+		btnDel.setToolTipText("<html><b>Delete</b><br>Removes a Category or a Category Item.</html>");
+		toolBar.add(btnDel);
+		
+
+		holegJFrame.getContentPane().add(splitPane);
+
+		mntmNew.addActionListener(actionEvent -> {
+			if (model.getObjectsOnCanvas().size() != 0) {
+				int newWarning = JOptionPane.YES_NO_OPTION;
+				int dialogForNewWarning = JOptionPane.showConfirmDialog(
+						holegJFrame, saveBeforeNew, warningText,
+						newWarning);
+				if (dialogForNewWarning == JOptionPane.YES_OPTION) {
+					mntmSave.doClick();
+				}
+			}
+
+			model.getEdgesOnCanvas().removeAll(model.getEdgesOnCanvas());
+			model.getObjectsOnCanvas().removeAll(model.getObjectsOnCanvas());
+			controller.setSelectedObjectID(0);
+			controller.setSelecteEdge(null);
+			controller.setCurIteration(0);
+			hideScrollGraph();
+			elementGraph.setText("None");
+			canvas.tempCps = null;
+			canvas.repaint();
+			IdCounter.resetObjectCounter(CounterType.Object);
+			IdCounter.resetObjectCounter(CounterType.Element);
+			controller.calculateStateAndVisualForCurrentTimeStep();
+		});
+
+		mntmOpen.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				menuFileExitActionPerformed();
+			}
+
+			private void menuFileExitActionPerformed() {
+				JFileChooser fileChooser = new JFileChooser();
+				fileChooser.setCurrentDirectory(new File(System.getProperty("user.dir")+"/exampleNetworks/"));
+				FileNameExtensionFilter holonFilter = new FileNameExtensionFilter(
+						"Holon Save File(*.holon)", "holon");
+				fileChooser.setFileFilter(holonFilter);
+
+				if (fileChooser.showOpenDialog(holegJFrame) == JFileChooser.APPROVE_OPTION) {
+					File file = fileChooser.getSelectedFile();
+
+					try {
+						controller.loadFile(file.getAbsolutePath());
+						canvas.repaint();
+						categoryTree.repaint();
+						controller.calculateStateAndVisualForCurrentTimeStep();
+					} catch (IOException | ArchiveException e) {
+						e.printStackTrace();
+						JLabel message = new JLabel(
+								"The savefile is corrupt and cannot be opened.");
+						JOptionPane.showMessageDialog(holegJFrame,
+								message, "", JOptionPane.ERROR_MESSAGE);
+					}
+				}
+			}
+		});
+
+		mntmSave.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				menuSaveActionPerformed();
+			}
+
+			private void menuSaveActionPerformed() {
+				JFileChooser fileChooser = new JFileChooser();
+				FileNameExtensionFilter holonFilter = new FileNameExtensionFilter(
+						"Holon Save File(*.holon)", "holon");
+				fileChooser.setFileFilter(holonFilter);
+
+				if (fileChooser.showSaveDialog(holegJFrame) == JFileChooser.APPROVE_OPTION) {
+					File selectedFile = fileChooser.getSelectedFile();
+					String fileName = selectedFile.getName();
+					String fullPath = fileChooser.getSelectedFile().getPath();
+					if (fileChooser.getFileFilter().equals(holonFilter)) {
+						if (!fileName.contains("."))
+							fullPath += ".holon";
+					}
+					if (!fullPath.endsWith(".holon")) {
+						String suffix = fullPath.substring(fullPath.lastIndexOf("."),
+								fullPath.length());
+						String[] options = new String[] { "keep .holon",
+								"use " + suffix };
+
+						JLabel message = new JLabel(
+								"Are you sure to use the extension \"" + suffix
+										+ "\" instead of \".holon\"?");
+
+						int response = JOptionPane.showOptionDialog(
+								holegJFrame, message, "",
+								JOptionPane.DEFAULT_OPTION,
+								JOptionPane.QUESTION_MESSAGE, null, options,
+								options[1]);
+
+						if (response == 0)
+							fullPath = fullPath.replace(suffix, ".holon");
+					}
+
+					try {
+						controller.saveFile(new File(fullPath).getAbsolutePath());
+					} catch (IOException | ArchiveException e) {
+						e.printStackTrace();
+					}
+				}
+			}
+		});
+
+
+		mntmUndo.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				menuUndoActionPerformed();
+			}
+
+			private void menuUndoActionPerformed() {
+				try {
+					controller.loadAutoSave(controller.getUndoSave());
+					
+					closeInvalidUpperNodeTabs();
+					
+					controller.calculateStateAndVisualForCurrentTimeStep();
+					canvas.repaint();
+					hideScrollGraph();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		});
+
+		mntmRedo.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				menuRedoActionPerformed();
+			}
+
+			private void menuRedoActionPerformed() {
+				try {
+					controller.loadAutoSave(controller.getRedoSave());
+					
+					closeInvalidUpperNodeTabs();
+					
+					controller.calculateStateAndVisualForCurrentTimeStep();
+					canvas.repaint();
+					hideScrollGraph();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		});
+
+		timePanel = new TimePanel(controller);
+		timePanel.setBorder(null);
+		timePanel.getTimeSlider()
+				.addChangeListener(changeEvent -> {
+					//TimeSliderChanged event
+					controller.calculateStateAndVisualForTimeStep(timePanel.getTimeSlider().getValue());
+					unitGraph.repaint();
+					contentPane.updateUI();
+				});
+		splitPane1.setMinimumSize(new Dimension(0, 25));
+		splitPane.setRightComponent(splitPane1);
+		splitPane.setDividerLocation(200);
+		splitPane1.setDividerLocation(500);
+
+		splitPane.setLeftComponent(scrollPane1);
+		tabbedPaneOriginal.addTab("View", tabbedPaneInnerOriginal);
+		
+		
+		myPanel.add(canvasSP, BorderLayout.CENTER);
+		
+		
+		tabbedPaneInnerOriginal.addTab("Main Grid", myPanel);
+		splitPane1.setLeftComponent(tabbedPaneOriginal);
+		splitPane1.setRightComponent(splitHolonElPro);
+
+		splitPane1.setResizeWeight(0.9);
+
+		splitHolonElPro.setDividerLocation(700);
+		// containing the graph and the elements-list
+		splitHolonElPro.setTopComponent(splitGraphHolonEl);
+		// containing the object's properties
+		splitHolonElPro.setBottomComponent(scrollProperties);
+
+		splitGraphHolonEl.setDividerLocation(distanceBetweenElementsAndGraph);
+		splitGraphHolonEl.setTopComponent(scrollElements);
+		splitGraphHolonEl.setBottomComponent(scrollGraph);
+		canvasSP.setViewportView(canvas);
+
+		tabbedPaneOriginal.setBorder(null);
+		scrollProperties.setBorder(null);
+		scrollGraph.setBorder(null);
+		scrollElements.setBorder(null);
+		splitPane.setBorder(null);
+		splitPane1.setBorder(null);
+		splitHolonElPro.setBorder(null);
+		splitGraphHolonEl.setBorder(null);
+		panelHolonEl.setBorder(null);
+		canvasSP.setBorder(null);
+		hideScrollGraph();
+		tableHolonElementScrollPane.setBorder(null);
+
+		holegJFrame.getContentPane().add(timePanel, BorderLayout.SOUTH);
+
+
+
+		try {
+			controller.loadAutoSave(System.getProperty("user.home")
+					+ "/.config/HolonGUI/Category/Category.json");
+		} catch (IOException e1) {
+		}
+
+		String autoPath = System.getProperty("user.home")
+				+ "/.config/HolonGUI/Autosave/";
+		File dest = new File(autoPath);
+		ArrayList<File> oldAutoSaves = controller.filterOldAutoSaveFiles();
+		int nrOfOldSaves = oldAutoSaves.size();
+
+		if (nrOfOldSaves > 0) {
+			int dialogButton = JOptionPane.YES_NO_OPTION;
+			int dialogResult = JOptionPane.showConfirmDialog(holegJFrame,
+					"Old autosave file was found, should it be loaded?",
+					warningText, dialogButton);
+			if (dialogResult == JOptionPane.YES_OPTION) {
+				if (dest.exists()) {
+					model.setAutoSaveNr(nrOfOldSaves - 1);
+					mntmRedo.doClick();
+				} else {
+					JOptionPane.showMessageDialog(holegJFrame,
+							"Autosave could not be loaded.");
+					setUpAutoSave(dest);
+				}
+			} else {
+				setUpAutoSave(dest);
+			}
+
+			// after all: delete the obsolete/old autosave files from the
+			// directory
+			controller.deleteObsoleteAutoSaveFiles();
+		}
+
+		canvasSP.addComponentListener(new ComponentAdapter() {
+			@Override
+			public void componentResized(ComponentEvent e) {
+				controller.setCanvasX(Math.max(model.getCanvasX(), canvasSP
+						.getViewport().getWidth()));
+				controller.setCanvasY(Math.max(model.getCanvasY(), canvasSP
+						.getViewport().getHeight()));
+				canvas.repaint();
+			}
+		});
+	}
+
+	private void initWindowMenu() {
+		menuBar.add(menuWindow);
+		//Algo
+		JMenuItem openMenu =  new JMenuItem("Open Algorithm Panel", new ImageIcon(ImageImport.loadImage("/Button_Images/iconAlgo.png").getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));
+		openMenu.addActionListener(actionEvent -> {
+			new AddOnWindow(holegJFrame, controller);
+		});
+		openMenu.setAccelerator(KeyStroke.getKeyStroke('N', Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx()));
+		menuWindow.add(openMenu);
+		//Outliner
+		JMenuItem openOutliner =  new JMenuItem("Open Outliner", new ImageIcon(ImageImport.loadImage("/Button_Images/iconOutliner.png").getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));
+		openOutliner.addActionListener(actionEvent -> {
+			outlinerList.add(new Outliner(holegJFrame, model, controller));
+		});
+		openOutliner.setAccelerator(KeyStroke.getKeyStroke('O', Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx()));
+		menuWindow.add(openOutliner);
+		//FlexWindow
+		JMenuItem openFlexMenuItem =  new JMenuItem("Open Flexibility Panel", new ImageIcon(ImageImport.loadImage("/Button_Images/iconAlgo.png").getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));
+		openFlexMenuItem.addActionListener(actionEvent -> {
+			flexList.add(new FlexWindow(holegJFrame, controller));
+		});
+		openFlexMenuItem.setAccelerator(KeyStroke.getKeyStroke('L', Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx()));
+		menuWindow.add(openFlexMenuItem);
+	}
+
+
+	public void updateOutliners(DecoratedState state)
+	{
+		//remove closed Outliner
+		ListIterator<Outliner> iter = outlinerList.listIterator();
+		while(iter.hasNext())
+		{
+			if(iter.next().isClosed) iter.remove();
+		}
+		//update open Outliner
+		for(Outliner out : outlinerList) {
+			out.repaintWithDecoratedState(state);
+		}
+	}
+	public void updateFlexWindows()
+	{
+		//remove closed Outliner
+		ListIterator<FlexWindow> iter = flexList.listIterator();
+		while(iter.hasNext())
+		{
+			if(iter.next().isClosed) iter.remove();
+		}
+		//update open Flex
+		for(FlexWindow out : flexList) {
+			out.update();
+		}
+	}
+	
+	
+	
+	private void showScrollGraph() {
+		scrollGraph.setVisible(true);
+		splitGraphHolonEl.setBottomComponent(scrollGraph);
+		splitGraphHolonEl.setDividerLocation(distanceBetweenElementsAndGraph);
+	}
+
+	private void hideScrollGraph() {
+		scrollGraph.setVisible(false);
+		splitGraphHolonEl.remove(scrollGraph);
+		splitGraphHolonEl.setDividerLocation(0);
+	}
+
+	private boolean isUpperPanelInsideBounds() {
+		int x = holegJFrame.getX();
+		int y = holegJFrame.getY();
+		int width = holegJFrame.getWidth();
+
+		// get all connected screen devices
+		GraphicsDevice[] screenDevices = GraphicsEnvironment
+				.getLocalGraphicsEnvironment().getScreenDevices();
+		boolean isUpperPanelVisible = false;
+
+		// and check whether they contain the upper left or upper right point of
+		// the frame
+		for (GraphicsDevice device : screenDevices) {
+			Rectangle bounds = device.getDefaultConfiguration().getBounds();
+			if (bounds.contains(x, y) || bounds.contains(x + width, y)) {
+				isUpperPanelVisible = true;
+				break;
+			}
+		}
+
+		return isUpperPanelVisible;
+	}
+
+	/**
+	 * Sets up autosave if no old one is loaded at the beginning
+	 *
+	 * @param dest
+	 *            path to save-folder
+	 */
+	private void setUpAutoSave(File dest) {
+		dest.mkdirs();
+		try {
+			controller.autoSave();
+		} catch (IOException e1) {
+			e1.printStackTrace();
+		}
+	}
+
+	/**
+	 * reloads the Categories from Model.
+	 *
+	 * @param categories
+	 *            the current categories
+	 */
+	private void updateCategories(final ArrayList<Category> categories) {
+		DefaultTreeModel treemodel = new DefaultTreeModel(new DefaultMutableTreeNode(
+				"Categories") {
+
+			private static final long serialVersionUID = 1L;
+
+			{
+				DefaultMutableTreeNode node1;
+				for (Category c : categories) {
+					node1 = new DefaultMutableTreeNode(c.getName());
+					
+					for (AbstractCanvasObject obj : c.getObjects()) {
+						node1.add(new DefaultMutableTreeNode(obj.getObjName()));
+					}
+					add(node1);
+				}
+
+			}
+		});
+		categoryTree.setModel(treemodel);
+	}
+
+	/**
+	 * When changes are made to the Categories.
+	 *
+	 * @param categories
+	 *            the Categories
+	 */
+	public void updateCategoryUI(ArrayList<Category> categories) {
+		DefaultTreeModel model = (DefaultTreeModel) categoryTree.getModel();
+		updateCategories(categories);
+		model.reload();
+	}
+
+	/**
+	 * Get the Frame.
+	 *
+	 * @return the Frame
+	 */
+	JFrame getFrmCyberPhysical() {
+		return holegJFrame;
+	}
+
+
+	/**
+	 * Checks if a double click was made.
+	 *
+	 * @return true if doublecklick, false if not
+	 */
+	private boolean doubleClick() {
+		if (click) {
+			click = false;
+			return true;
+		} else {
+			click = true;
+			Timer t = new Timer("doubleclickTimer", false);
+			t.schedule(new TimerTask() {
+				@Override
+				public void run() {
+					click = false;
+				}
+			}, 350);
+		}
+		return false;
+	}
+
+	/*
+	 * Open a new Tab with an UpperNodeCanvas
+	 */
+	private void openNewUpperNodeTab() {
+		chooseTabTemp();
+
+		JScrollPane scrollPane = getScrollPaneFromTabbedPane();
+		if (scrollPane.getViewport().getComponent(0) instanceof MyCanvas) {
+			unc = new GroupNodeCanvas(model, controller, unitGraph,
+					(GroupNode) temp, "", scrollPane.getViewport().getComponent(0));
+
+		} else {
+			unc = new GroupNodeCanvas(model, controller, unitGraph,
+					(GroupNode) temp, ((GroupNodeCanvas) scrollPane
+							.getViewport().getComponent(0)).path + " -> ", scrollPane.getViewport().getComponent(0));
+		}
+		unc.setShowedInformation(canvas.getShowedInformation());
+
+		// check if tab already open for clicked NodeOfNode
+		boolean dupl = false;
+
+		for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) {
+			JScrollPane paneOriginal = (JScrollPane) tabbedPaneInnerOriginal
+					.getComponentAt(i);
+			if (paneOriginal != null
+					&& ((GroupNodeCanvas) paneOriginal.getViewport()
+							.getComponent(0)).upperNode.getId() == temp.getId()) {
+				dupl = true;
+				// set selected component to view
+				tabbedPaneOriginal
+						.setSelectedComponent(tabbedPaneInnerOriginal);
+				// set selected tab in view to found upper-node-canvas
+				tabbedPaneInnerOriginal
+						.setSelectedComponent(tabbedPaneInnerOriginal
+								.getComponentAt(i));
+			}
+
+			if (tabbedPaneSplit.getTabCount() > 0) {
+				JTabbedPane tabbedPaneInnerSplit = (JTabbedPane) tabbedPaneSplit
+						.getComponentAt(0);
+				if (tabbedPaneInnerSplit != null) {
+					JScrollPane paneSplit = (JScrollPane) tabbedPaneInnerSplit
+							.getComponentAt(i);
+					if (!initSplit
+							&& paneSplit != null
+							&& ((GroupNodeCanvas) paneSplit.getViewport()
+									.getComponent(0)).upperNode.getId() == temp
+									.getId()) {
+						dupl = true;
+						// set selected component to view
+						tabbedPaneSplit
+								.setSelectedComponent(tabbedPaneInnerSplit);
+						// set selected tab in view to found upper-node-canvas
+						tabbedPaneInnerSplit
+								.setSelectedComponent(tabbedPaneInnerSplit
+										.getComponentAt(i));
+					}
+				}
+			}
+
+			// if we found a duplicate, break
+			if (dupl) {
+				break;
+			}
+		}
+		if (!dupl) {
+			unc.setBorder(null);
+			unc.setBackground(Color.WHITE);
+			unc.setPreferredSize(new Dimension(model.getCanvasX(), model
+					.getCanvasY()));
+
+			unc.addMouseListener(new MouseAdapter() {
+				@Override
+				public void mousePressed(MouseEvent e) {
+					hideScrollGraph();
+					holonEleNamesDisplayed = "None";
+					elementGraph.setText(holonEleNamesDisplayed);
+
+					chooseTabTemp();
+
+					JScrollPane scrollPane1 = getScrollPaneFromTabbedPane();
+					temp = ((GroupNodeCanvas) scrollPane1.getViewport()
+							.getComponent(0)).tempCps;
+					if (doubleClick() && MouseEvent.BUTTON3 != e.getButton()
+							&& temp instanceof GroupNode) {
+						openNewUpperNodeTab();
+					}
+					if (temp instanceof HolonSwitch) {
+						updateUnitGraph((GraphEditable)temp);
+					}
+				}
+
+			});
+
+			JScrollPane sp = new JScrollPane(unc);
+			sp.setBorder(null);
+
+			// Selected tabbed Pane = tabbedPaneOriginal or tabbedPaneSplit
+			if (tabTemp == tabbedPaneOriginal) {
+				this.tabbedPaneInnerOriginal.add(temp.getName(), sp);
+				this.tabbedPaneInnerOriginal.setSelectedComponent(sp);
+				this.tabbedPaneInnerOriginal.setTabComponentAt(
+						this.tabbedPaneInnerOriginal.getTabCount() - 1,
+						new ButtonTabComponent(this.tabbedPaneInnerOriginal,
+								tabbedPaneSplit));
+
+			} else {
+				JTabbedPane tabbedPaneInnerSplit = (JTabbedPane) tabbedPaneSplit
+						.getComponentAt(0);
+				tabbedPaneInnerSplit.add(temp.getName(), sp);
+				Component tempC = tabbedPaneInnerSplit.getSelectedComponent();
+				tabbedPaneInnerSplit.setComponentAt(
+						tabbedPaneInnerSplit.getSelectedIndex(), null);
+				tabbedPaneOriginal.setComponentAt(
+						tabbedPaneInnerSplit.getSelectedIndex(), tempC);
+				tabbedPaneInnerSplit.setSelectedComponent(sp);
+
+				tabbedPaneInnerOriginal.add(temp.getName(), null);
+				tabbedPaneInnerOriginal.setTabComponentAt(
+						tabbedPaneInnerOriginal.getTabCount() - 1,
+						new ButtonTabComponent(tabbedPaneInnerOriginal,
+								tabbedPaneInnerSplit));
+			}
+
+			temp = null;
+		}
+	}
+
+	private void updateUpperNodes() {
+		for (Component c : tabbedPaneInnerOriginal.getComponents()) {
+			if (!(c instanceof JScrollPane)) {
+				continue;
+			}
+			Component pane = ((JScrollPane) c).getViewport().getComponent(0);
+			if (pane instanceof GroupNodeCanvas) {
+				temp = model.getHashcodeMap()
+						.get(((GroupNodeCanvas) pane).code);
+				((GroupNodeCanvas) pane).upperNode = (GroupNode) temp;
+			}
+		}
+	}
+
+	/**
+	 * Removes UpperNodeTab if UpperNode was deleted
+	 *
+	 * @param cps
+	 *            the CPS object that is currently selected
+	 */
+	private void removeUpperNodeTab(AbstractCanvasObject cps) {
+		if (cps instanceof GroupNode) {
+			boolean splitView = false;
+			for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) {
+				JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal
+						.getComponentAt(i);
+
+				if (scrollPaneOriginal == null) {
+					splitView = true;
+				} else if (((GroupNodeCanvas) scrollPaneOriginal.getViewport()
+						.getComponent(0)).upperNode.getId() == cps.getId()) {
+					((ButtonTabComponent) tabbedPaneInnerOriginal
+							.getTabComponentAt(i)).removeTabs();
+					break;
+				}
+			}
+			// If SplitView is on and the view on
+			// tabbedPaneSplit is the deleted upperNode
+			if (splitView && tabbedPaneSplit.getComponentCount() > 0) {
+				JTabbedPane tabbedPaneInnerSplit = (JTabbedPane) tabbedPaneSplit
+						.getComponentAt(0);
+
+				if (((GroupNodeCanvas) ((JScrollPane) tabbedPaneInnerSplit
+						.getSelectedComponent()).getViewport().getComponent(0)).upperNode
+						.getId() == cps.getId()) {
+					((ButtonTabComponent) tabbedPaneInnerOriginal
+							.getTabComponentAt(tabbedPaneInnerSplit
+									.getSelectedIndex())).removeTabs();
+				}
+			}
+		}
+	}
+
+
+	/**
+	 * chooses whether to set the tabTemp to tabbedPaneOriginal or
+	 * tabbedPaneSplit
+	 */
+	private void chooseTabTemp() {
+		// is the uppernode on tabbedPaneOriginal or tabbedPaneSplit
+		/* TODO: Fix or Remove SplitView */
+		if (tabbedPaneOriginal.getMousePosition() != null || initSplit) {
+			tabTemp = tabbedPaneOriginal;
+		} else {
+			tabTemp = tabbedPaneSplit;
+		}
+	}
+
+	private JScrollPane getScrollPaneFromTabbedPane() {
+		return getScrollPaneFromTabbedPane(-1);
+	}
+
+	private JScrollPane getScrollPaneFromTabbedPane(int index) {
+		Component upperLevelSelectedComponent;
+		if(tabTemp == null)
+		{
+			return null;
+		}
+		if (index == -1) {
+			upperLevelSelectedComponent = tabTemp.getSelectedComponent();
+		} else {
+			upperLevelSelectedComponent = tabTemp.getComponentAt(index);
+		}
+		if (upperLevelSelectedComponent instanceof JTabbedPane) {
+			Component nextLevel = ((JTabbedPane) upperLevelSelectedComponent).getSelectedComponent();
+			if(nextLevel instanceof JPanel)
+				return (JScrollPane) ((JPanel)nextLevel).getComponent(0);
+			else
+				return (JScrollPane) nextLevel;
+			
+		} else if (upperLevelSelectedComponent instanceof JScrollPane) {
+			return (JScrollPane) upperLevelSelectedComponent;
+		} else {
+			return null;
+		}
+	}
+
+
+	/**
+	 * if flexibility was turned on, then active needs to be turned off, the
+	 * energy currently produced/consumed
+	 *
+	 * @param eleBTemp
+	 *            element that needs to be updated
+	 * @param selectedValueBY
+	 *            the y value in the table
+	 */
+	private void updateElementTableAfterChange(HolonElement eleBTemp,
+			int selectedValueBY) {
+//		model.getSingleTable().setValueAt(false,
+//				selectedValueBY, 6);
+		model.getSingleTable().setValueAt(eleBTemp.isActive(), selectedValueBY,
+				5);
+		model.getSingleTable().setValueAt(eleBTemp.getAmount(),
+				selectedValueBY, 4);
+		model.getSingleTable().setValueAt(
+				controller.getSimManager().getActualFlexManager().isAFlexInUseOfHolonElement(eleBTemp),
+				selectedValueBY, 3);
+		model.getSingleTable().setValueAt(eleBTemp.getEnergyPerElement(),
+				selectedValueBY, 2);
+	}
+
+	public void triggerUpdateController(AbstractCanvasObject temp) {
+		if(model != null) { return;}
+		if (temp != null) {
+			updCon.paintProperties(temp);
+		}
+		updCon.refreshTableHolonElement(model.getMultiTable(),
+				model.getSingleTable());
+		updCon.refreshTableProperties(model.getPropertyTable());
+	}
+
+	/**
+	 * This Method updates the UnitGraph, saves the old LocalModeState and load the new LocalModeState.
+	 * @param element The new Element to load the UnitGraph
+	 */
+	private void updateUnitGraph(GraphEditable element){
+		//SaveOld LocalMode State.
+		if(localPeriodInput.isVisible())
+		{
+			//Save Old State
+			validateInput(localPeriodInput.getEditor().getItem().toString(), false);
+		}
+		//Update UnitGraph
+		unitGraph.initNewElement(element);
+		//Load LocalMode State.
+		changeLocalPeriodButtonAppeareance(unitGraph.isUsingLocalPeriod());
+		localPeriodInput.getEditor().setItem(unitGraph.getLocalPeriod());
+	}
+	
+	/**
+	 * Displayed the actual LocalModeState.
+	 * @param enabled
+	 */
+	private void changeLocalPeriodButtonAppeareance(boolean enabled) {
+		localPeriodInput.setVisible(enabled);
+		if(enabled)
+		{
+			localPeriodButtonImage.setImage(ImageImport.loadImage("/Images/Graph.png"));
+		}else {
+			localPeriodButtonImage.setImage(GrayFilter.createDisabledImage(ImageImport.loadImage("/Images/Graph.png")));
+		}
+	}
+	/**
+	 * Validate the LocalMode Input and when its valid save on the Element.
+	 * @param text the inputText to validate. 
+	 * @param bShowMessage when true, open a MessageDialog when text invalid.
+	 */
+	private void validateInput(String text, boolean bShowMessage) {
+		int localPeriodInputValue;
+		try {
+		      localPeriodInputValue = Integer.parseInt(text);
+		} catch (NumberFormatException e) {
+			if(bShowMessage)
+				JOptionPane.showMessageDialog(contentPane, '"' +text + '"'+ " is not a valid Input. \n Use whole numbers.");
+			return;
+		}
+		unitGraph.setLocalPeriod(localPeriodInputValue);
+	}
+
+	
+	private void openWebpage(String URL){
+		try {
+			java.awt.Desktop.getDesktop().browse(new URI(URL));
+		} catch (IOException e1) {
+			// TODO Auto-generated catch block
+			e1.printStackTrace();
+		} catch (URISyntaxException e1) {
+			// TODO Auto-generated catch block
+			e1.printStackTrace();
+		}
+	}
+	
+	/**
+	 * closes all UpperNodeTabs, that don't have a
+	 * valid UpperNode (e.g. if it was ungrouped/deleted/replaced and so on)
+	 */
+	private void closeInvalidUpperNodeTabs() {
+		/**
+		 * close bugged Tabs
+		 */
+		for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) {
+			JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal
+					.getComponentAt(i);
+			if (((GroupNodeCanvas) scrollPaneOriginal.getViewport()
+					.getComponent(0)).upperNode == null) {
+				((ButtonTabComponent) tabbedPaneInnerOriginal
+						.getTabComponentAt(i)).removeTabs();
+				break;
+			}
+		}
+	}
+	
+	public void repaintCanvas() {
+		tabbedPaneInnerOriginal.repaint();
+	}
+	
+	/**
+	 * Class should be reworked as soon as possible!
+	 * @param state
+	 */
+	public void guiDisable(boolean state) {
+		canvas.disabled = state;
+		for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) {
+			JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal
+					.getComponentAt(i);
+			if (((GroupNodeCanvas) scrollPaneOriginal.getViewport()
+					.getComponent(0)).upperNode != null) {
+				((GroupNodeCanvas) scrollPaneOriginal.getViewport()
+						.getComponent(0)).disable = state;
+			}
+		}
+	}
+}

+ 1272 - 0
src/ui/view/GroupNodeCanvas.java.orig

@@ -0,0 +1,1272 @@
+package ui.view;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.geom.Line2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+
+import com.google.gson.JsonParseException;
+
+import classes.AbstractCanvasObject;
+import classes.Edge;
+import classes.GroupNode;
+import classes.HolonObject;
+import classes.HolonSwitch;
+import classes.Node;
+import ui.controller.Control;
+import ui.controller.UpdateController;
+import ui.model.Consumer;
+import ui.model.DecoratedCable;
+import ui.model.DecoratedGroupNode;
+import ui.model.DecoratedHolonObject;
+import ui.model.DecoratedHolonObject.HolonObjectState;
+import ui.model.DecoratedSwitch;
+import ui.model.ExitCable;
+import ui.model.DecoratedSwitch.SwitchState;
+import ui.model.Model;
+import ui.model.Passiv;
+import ui.model.Supplier;
+import utility.ImageImport;
+import utility.Vector2Float;
+import utility.Vector2Int;
+
+/**
+ * This Class is the Canvas. All Objects will be visualized here
+ *
+ * @author Gruppe14
+ */
+public class GroupNodeCanvas extends AbstractCanvas implements MouseListener, MouseMotionListener {
+
+    private static final long serialVersionUID = 1L;
+    // The UpperNode
+    public GroupNode upperNode;
+    // Path
+    protected String path;
+    int code;
+    public boolean disable = false;
+    /**
+     * Constructor.
+     *
+     * @param mod       the Model
+     * @param control   the Controller
+     * @param unitGraph
+     */
+    GroupNodeCanvas(Model mod, Control control, UnitGraph unitGraph, GroupNode UpperNode, String parentPath, Component parentComponent) {
+        toolTip = false;
+
+        this.controller = control;
+        this.model = mod;
+        this.upperNode = UpperNode;
+        this.code = UpperNode.hashCode();
+        this.path = parentPath + upperNode.getName();
+        scalediv20 = model.getScale() / 20;
+
+        // Cps objecte aus dem border links schieben
+        upperNode.setLeftBorder(/*(int) (50 + scalediv20 + scalediv20 + 10)*/ 0);
+        for (AbstractCanvasObject cps : upperNode.getNodes()) {
+            if (cps.getPosition().getX() < model.getScaleDiv2() + upperNode.getLeftBorder() + 5) {
+                cps.setPosition(
+                        new Vector2Int(upperNode.getLeftBorder() + 5 + model.getScaleDiv2(), cps.getPosition().getY()));
+            }
+        }
+
+        showedInformation[0] = true;
+        showedInformation[1] = true;
+        showedInformation[4] = true;
+
+        popmenu.add(itemCut);
+        popmenu.add(itemCopy);
+        popmenu.add(itemPaste);
+        popmenu.add(itemDelete);
+        popmenu.add(itemAlign);
+        popmenu.addSeparator();
+        popmenu.add(itemGroup);
+        popmenu.add(itemUngroup);
+        popmenu.add(itemCreateTemplate);
+        
+        itemAlign.setEnabled(true);
+        itemDelete.setEnabled(false);
+        itemCut.setEnabled(false);
+        itemCopy.setEnabled(false);
+        itemPaste.setEnabled(true);
+        itemGroup.setEnabled(false);
+        itemUngroup.setEnabled(false);
+        
+        updCon = new UpdateController(model, controller);
+        
+        itemAlign.addActionListener(actionEvent -> {
+        	for(AbstractCanvasObject cps: model.getSelectedCpsObjects())
+        		align(cps, model.getScaleDiv2());
+        	repaint();
+        });
+        
+        itemGroup.addActionListener(actionEvent -> {
+            // calculate uppernode pos (taken from the controller)
+            unPos = new Vector2Int(0, 0);
+            animCps = new ArrayList<>();
+            for (AbstractCanvasObject cps : model.getSelectedCpsObjects()) {
+                animCps.add(cps); // add to animation Cps ArrayList
+                unPos = unPos.add(cps.getPosition());
+            }
+            unPos = unPos.divide(animCps.size());
+
+            // save old Position
+            savePos = new ArrayList<>();
+            for (int i = 0; i < animCps.size(); i++) {
+                savePos.add(animCps.get(i).getPosition().clone());
+            }
+
+            animT = new javax.swing.Timer(animDelay, actionEvent1 -> {
+                if (animDuration - animDelay > 0 && animCps.size() > 1) {
+                    for (AbstractCanvasObject currentAnimCps : animCps) {
+                    	Vector2Int pos = currentAnimCps.getPosition();
+                    	Vector2Int difference = pos.subtract(unPos);
+                    	Vector2Int result = pos.subtract(difference.divide(animSteps));
+                    	pos.set(result);
+                    }
+                    repaint();
+                    animDuration -= animDelay;
+                    animSteps--;
+                } else {
+                    animDuration = ANIMTIME;
+                    animSteps = animDuration / animDelay;
+                    animT.stop();
+                    for (int i = 0; i < animCps.size(); i++) {
+                        animCps.get(i).getPosition().set(savePos.get(i));
+                    }
+                    controller.addUpperNode("GroupNode", upperNode, model.getSelectedCpsObjects());
+                    controller.calculateStateAndVisualForCurrentTimeStep();
+                    repaint();
+                }
+            });
+            animT.start();
+        });
+
+        itemUngroup.addActionListener(actionEvent -> {
+            // save old Position
+        	closeUpperNodeTab(tempCps.getId());
+
+            savePos = new ArrayList<>();
+            animCps = ((GroupNode) tempCps).getNodes();
+            controller.ungroupGroupNode((GroupNode) tempCps, upperNode);
+
+            for (int i = 0; i < animCps.size(); i++) {
+                savePos.add(animCps.get(i).getPosition().clone());
+            }
+            for (AbstractCanvasObject cps : animCps) {
+                cps.setPosition(tempCps.getPosition().clone());
+            }
+
+            animT = new javax.swing.Timer(animDelay, actionEvent1 -> {
+                if (animDuration - animDelay >= 0) {
+                    for (int i = 0; i < animCps.size(); i++) {
+                        Vector2Int pos = animCps.get(i).getPosition();
+                    	Vector2Int difference = pos.subtract(savePos.get(i));
+                    	Vector2Int result = pos.subtract(difference.divide(animSteps));
+                    	pos.set(result);
+                    }
+                    repaint();
+                    animDuration -= animDelay;
+                    animSteps--;
+                } else {
+                    animDuration = ANIMTIME;
+                    animSteps = animDuration / animDelay;
+                    animT.stop();
+                    for (int i = 0; i < animCps.size(); i++) {
+                        animCps.get(i).getPosition().set(savePos.get(i));
+                    }
+
+                    controller.calculateStateAndVisualForCurrentTimeStep();
+                    repaint();
+                }
+            });
+            animT.start();
+        });
+
+        
+
+        itemDelete.addActionListener(actionEvent -> {
+            // Remove the selected Object objects
+            for (AbstractCanvasObject cps : model.getSelectedCpsObjects()) {
+                if (upperNode.getNodes().contains(cps)) {
+                    controller.delObjUpperNode(cps, upperNode);
+                    // Remove UpperNodeTab if UpperNode deleted
+                    if (cps instanceof GroupNode) {
+                        JTabbedPane tabbedPane = (JTabbedPane) getParent().getParent().getParent().getParent();
+                        // Look if the uppernode is open in a Tab
+                        for (int i = 4; i < tabbedPane.getTabCount(); i++) {
+
+                            if (tabbedPane.getComponentAt(i) != null &&
+                                    ((GroupNodeCanvas) ((JScrollPane) tabbedPane.getComponentAt(i)).getViewport()
+                                            .getComponent(0)).upperNode.getId() == cps.getId()) {
+                                ((ButtonTabComponent) tabbedPane.getTabComponentAt(i)).removeTabs();
+                                break;
+                            }
+                        }
+                      
+                    }
+                }
+            }
+            toolTip = false;
+            controller.clearSelection();
+            tempCps = null;
+            repaint();
+        });
+
+        itemCut.addActionListener(actionEvent -> {
+            controller.cut(upperNode);
+            itemPaste.setEnabled(true);
+            repaint();
+        });
+
+        itemCopy.addActionListener(actionEvent -> {
+        	if(tempCps instanceof GroupNode)
+				controller.getObjectsInDepth();
+            controller.copy(upperNode);
+            itemPaste.setEnabled(true);
+            repaint();
+        });
+
+        itemPaste.addActionListener(actionEvent -> {
+            try {
+                controller.paste(upperNode, mousePosition);
+            } catch (JsonParseException | UnsupportedFlavorException | IOException e1) {
+                JLabel message = new JLabel("The Clipboard information cannot be pastet into Application.");
+                JOptionPane.showMessageDialog(null, message, "", JOptionPane.ERROR_MESSAGE);
+            }
+            repaint();
+        });
+        
+        /*
+		 * create Template
+		 */
+		itemCreateTemplate.addActionListener(actionEvent -> {
+			controller.createTemplate((HolonObject)tempCps, (JFrame)SwingUtilities.getRoot(this));
+		});
+
+        this.addMouseListener(this);
+        this.addMouseMotionListener(this);
+    }
+
+	/**
+	 * Paints all Components on the Canvas.
+	 *
+	 * @param g
+	 *            Graphics
+	 */
+	
+	private Color getStateColor(HolonObjectState state) {
+		switch(state) {
+		case NOT_SUPPLIED:
+			return new Color(230, 120, 100);
+		case NO_ENERGY:
+			return Color.white;
+		case OVER_SUPPLIED:
+			return new Color(166, 78, 229);
+		case PARTIALLY_SUPPLIED:
+			return Color.yellow;
+		case PRODUCER:
+			return Color.lightGray;
+		case SUPPLIED:
+			return new Color(13, 175, 28);
+		default:
+			return Color.BLACK;
+		}
+	}
+	private void paintCanvasObject(Graphics2D g, DecoratedHolonObject decoratedHolonObject){
+		Vector2Int pos = decoratedHolonObject.getModel().getPosition();
+		Color statecolor = getStateColor(decoratedHolonObject.getState());
+		g.setColor(statecolor);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() - controller.getScaleDiv2(), controller.getScale(), controller.getScale());
+		drawCanvasObject(g, decoratedHolonObject.getModel().getImage(), pos);
+	}
+	private void drawCanvasObjectString(Graphics2D g, Vector2Int posOfCanvasObject, float energy) {
+		g.setColor(Color.BLACK);
+		g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (controller.getScale() / 4f) )); 
+		g.drawString((energy > 0)? "+" + Float.toString(energy): Float.toString(energy), posOfCanvasObject.getX() - controller.getScaleDiv2(), posOfCanvasObject.getY() - controller.getScaleDiv2() - 1);
+	}
+	private void paintConsumer(Graphics2D g, Consumer con){
+		paintCanvasObject(g, con);
+		paintSupplyBar(g,con.getSupplyBarPercentage(), getStateColor(con.getState()), con.getModel().getPosition());
+		drawCanvasObjectString(g, con.getModel().getPosition(), -con.getEnergyNeededFromNetwork());
+	}
+	private void paintSupplier(Graphics2D g, Supplier sup){
+		paintCanvasObject(g, sup);
+		drawCanvasObjectString(g, sup.getModel().getPosition(), sup.getEnergyToSupplyNetwork());
+	}
+	
+	private void drawCanvasObject(Graphics2D g, String Image, Vector2Int pos) {
+		g.drawImage(ImageImport.loadImage(Image, controller.getScale(), controller.getScale()) , 
+				pos.getX() - controller.getScaleDiv2(),
+				pos.getY() - controller.getScaleDiv2(),
+				controller.getScale(), controller.getScale() , null);
+	}
+	
+	private void paintCable(Graphics2D g, DecoratedCable cable, boolean isSelected)
+	{
+		Vector2Int start = cable.getModel().getA().getPosition();
+		Vector2Int end =  cable.getModel().getB().getPosition();
+		float currentEnergy = cable.getFlowEnergy();
+		float capacity = cable.getModel().getCapacity();
+		boolean unlimited = cable.getModel().isUnlimitedCapacity();
+		switch(cable.getState()) {
+		case Burned:
+			g.setColor(Color.RED);
+			g.setStroke(new BasicStroke(2));
+			break;
+		case Working:
+			g.setColor(new Color(13, 175, 28));
+			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());
+		Vector2Int middle = new Vector2Int((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
+		g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (controller.getScale() / 3.5f), 10) )); 
+		g.drawString(currentEnergy + "/" + (unlimited?"\u221E":capacity) , middle.getX(), middle.getY());
+	}
+	private void paintSwitch(Graphics2D g, DecoratedSwitch dSwitch)
+	{
+		drawCanvasObject(g, dSwitch.getState() == SwitchState.Open ? HolonSwitch.getSwitchOpenImage(): HolonSwitch.getSwitchClosedImage() , dSwitch.getModel().getPosition());
+	}
+	private void paintGroupNode(Graphics2D g, DecoratedGroupNode dGroupNode) {
+		Vector2Int pos = dGroupNode.getModel().getPosition();
+		g.setColor(Color.lightGray);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() - controller.getScaleDiv2(), controller.getScale(), controller.getScale());
+		drawCanvasObject(g, "/Images/upper_node.png" , pos);
+		paintGroupNodeBar(g, dGroupNode, pos);
+	}
+	private void paintGroupNodeBar(Graphics2D g, DecoratedGroupNode dGroupNode , Vector2Int pos) {
+		// +1, -2, -1 little Adjustment for pixel perfect alignment
+		int barWidth = (int) (controller.getScale());
+		int barHeight = (int) (controller.getScale() / 5);
+		g.setColor(Color.WHITE);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) barWidth, barHeight);
+		float[] percentages = getGroupNodeBarPercentages(dGroupNode);
+		Color[] colors = new Color[6];
+		colors[0] = getStateColor(HolonObjectState.PRODUCER);
+		colors[1] = getStateColor(HolonObjectState.NOT_SUPPLIED);
+		colors[2] = getStateColor(HolonObjectState.PARTIALLY_SUPPLIED);
+		colors[3] = getStateColor(HolonObjectState.SUPPLIED);
+		colors[4] = getStateColor(HolonObjectState.OVER_SUPPLIED);
+		colors[5] = getStateColor(HolonObjectState.NO_ENERGY);
+				
+		for(int i = 5; i>=0; i--) {
+			g.setColor(colors[i]);
+			g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) (barWidth * percentages[i] - 1), barHeight);		
+		}
+//		g.setColor(color);
+//		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
+		g.setColor(Color.BLACK);
+		g.setStroke(new BasicStroke(1));
+		g.drawRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 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 paintExitCable(Graphics2D g, ExitCable eCable) {
+		if(eCable.getStart() == null || eCable.getFinish() == null) {
+			System.out.println("Null wrong exitcable");
+			System.out.println(" wrongCable: " + " start:"  +eCable.getStart() + " end:"  +eCable.getFinish() + " state:" + eCable.getState());
+			return;
+		}
+		Vector2Int start = eCable.getStart().getPosition();
+		Vector2Int end = eCable.getFinish().getPosition();
+		float currentEnergy = eCable.getCable().getFlowEnergy();
+		float capacity = eCable.getCable().getModel().getCapacity();
+		boolean unlimited = eCable.getCable().getModel().isUnlimitedCapacity();
+		switch(eCable.getCable().getState()) {
+		case Burned:
+			g.setColor(Color.RED);
+			g.setStroke(new BasicStroke(2));
+			break;
+		case Working:
+			g.setColor(new Color(13, 175, 28));
+			g.setStroke(new BasicStroke(unlimited?2f:(currentEnergy / capacity * 2f) + 1));
+			break;
+		}
+		switch(eCable.getState()) {
+		case DOWN:
+		case DOWNDOWN:
+			g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
+			Vector2Int middle = new Vector2Int((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
+			g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (controller.getScale() / 3.5f), 10) )); 
+			g.drawString(currentEnergy + "/" + (unlimited?"\u221E":capacity) , middle.getX(), middle.getY());
+			break;
+		case DOWNUP:
+		case UP:
+			Vector2Float vStart = new Vector2Float(start.getX(), start.getY());
+			Vector2Float vEnd = new Vector2Float(end.getX(), end.getY());
+			float stretchFactor = 4 * model.getScale();
+			stretchFactor =  (stretchFactor > vStart.getDistance(vEnd))? vStart.getDistance(vEnd) : stretchFactor;
+			Vector2Float vPosition = vStart.add((vEnd.subtract(vStart)).normalize().multiply(stretchFactor));
+			Vector2Int result = new Vector2Int(Math.round(vPosition.getX()),Math.round(vPosition.getY()));
+			g.drawLine(start.getX(), start.getY(), result.getX(), result.getY());
+			Vector2Int middle1 = new Vector2Int((start.getX() +result.getX()) / 2, (start.getY() + +result.getY()) / 2);
+			g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (controller.getScale() / 3.5f), 10) )); 
+			g.drawString(currentEnergy + "/" + (unlimited?"\u221E":capacity) , middle1.getX(), middle1.getY());
+			drawCanvasObject(g, "/Images/arrowUp.png" , result);
+			break;
+		default:
+			System.out.println("Error");
+			break;
+		}
+	}
+	private void paintSupplyBar(Graphics2D g, float percentage, Color color, Vector2Int pos) {
+		// +1, -2, -1 little Adjustment for pixel perfect alignment
+		int barWidth = (int) (controller.getScale());
+		int barHeight = (int) (controller.getScale() / 5);
+		g.setColor(Color.WHITE);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) barWidth, barHeight);
+		g.setColor(color);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
+		g.setColor(Color.BLACK);
+		g.setStroke(new BasicStroke(1));
+		g.drawRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 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() + controller.getScaleDiv2() - 1+ barHeight);
+		
+	}
+	
+	//old code
+	void drawMarker(Graphics2D g) {
+		Color transparentGrey = new Color(128, 174, 247, 40);
+		if (sx > x && sy > y) {
+			g.drawRect(x, y, sx - x, sy - y);
+			g.setColor(transparentGrey);
+			g.fillRect(x, y, sx - x, sy - y);
+		} else if (sx < x && sy < y) {
+			g.drawRect(sx, sy, x - sx, y - sy);
+			g.setColor(transparentGrey);
+			g.fillRect(sx, sy, x - sx, y - sy);
+		} else if (sx >= x) {
+			g.drawRect(x, sy, sx - x, y - sy);
+			g.setColor(transparentGrey);
+			g.fillRect(x, sy, sx - x, y - sy);
+		} else if (sy >= y) {
+			g.drawRect(sx, y, x - sx, sy - y);
+			g.setColor(transparentGrey);
+			g.fillRect(sx, y, x - sx, sy - y);
+		}
+	}
+	public void paintComponent(Graphics g) {		
+		super.paintComponent(g);
+		Graphics2D g2d = (Graphics2D) g;
+		g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING,
+				RenderingHints.VALUE_ANTIALIAS_ON));
+		//-->Old code
+		if (drawEdge) {
+			g2d.setColor(Color.BLACK);
+			g2d.setStroke(new BasicStroke(1));
+			g2d.drawLine(tempCps.getPosition().getX(), tempCps.getPosition().getY(), x, y);
+		}
+		//<--
+		//SelectedCable
+		HashSet<Edge> selectedEdges = new HashSet<Edge>();
+		for(AbstractCanvasObject aCps:  model.getSelectedCpsObjects()) {
+			for(Edge edge: aCps.getConnections()) {
+				selectedEdges.add(edge);
+			}
+		}
+		if(model.getSelectedEdge() != null) selectedEdges.add(model.getSelectedEdge());
+
+		
+		DecoratedGroupNode  actualGroupNode = controller.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().get(upperNode);
+		//VisualState Representation:
+		for(ExitCable cable : actualGroupNode.getExitCableList()) {
+			paintExitCable(g2d, cable);
+		}
+		for(DecoratedCable cable : actualGroupNode.getInternCableList()) {
+			paintCable(g2d, cable, selectedEdges.contains(cable.getModel()));
+		}
+	
+		
+		for(DecoratedGroupNode dGroupNode : actualGroupNode.getGroupNodeList()) {
+			paintGroupNode(g2d, dGroupNode);
+		}
+		for(Consumer con: actualGroupNode.getConsumerList()) {
+			paintConsumer(g2d, con);					
+		}
+		for(Supplier sup: actualGroupNode.getSupplierList()) {
+			paintSupplier(g2d, sup);				
+		}
+		for(Passiv pas: actualGroupNode.getPassivList()) {
+			paintCanvasObject(g2d, pas);
+		}
+		for(DecoratedSwitch dSwitch : actualGroupNode.getSwitchList()) {
+				paintSwitch(g2d, dSwitch);
+		}
+		for(Node node : actualGroupNode.getNodeList()) {
+			drawCanvasObject(g2d, "/Images/node.png" , 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 = new Color(128, 174, 247, 40);
+		for(AbstractCanvasObject aCps:  model.getSelectedCpsObjects()) {
+			if(aCps instanceof Node) {
+				Vector2Int pos = aCps.getPosition();
+				g2d.setColor(transparentGrey);
+				g2d.fillOval(pos.getX() - (int) (controller.getScaleDiv2()), pos.getY() - (int) (controller.getScaleDiv2()),  controller.getScale(),  controller.getScale());
+				g2d.setColor(Color.LIGHT_GRAY);
+				g2d.setStroke(new BasicStroke(2));
+				g2d.drawOval(pos.getX() - (int) (controller.getScaleDiv2()), pos.getY() - (int) (controller.getScaleDiv2()),  controller.getScale(),  controller.getScale());
+			}
+			else {
+				Vector2Int pos = aCps.getPosition();
+				g2d.setColor(transparentGrey);
+				g2d.fillRect(pos.getX() - (int) (controller.getScaleDiv2()* 1.5f), pos.getY() - (int) (controller.getScaleDiv2()* 1.5f), (int) (controller.getScale()* 1.5f) , (int) (controller.getScale()* 1.5f));
+				g2d.setColor(Color.LIGHT_GRAY);
+				g2d.setStroke(new BasicStroke(2));
+				g2d.drawRect(pos.getX() - (int) (controller.getScaleDiv2()* 1.5f), pos.getY() - (int) (controller.getScaleDiv2()* 1.5f), (int) (controller.getScale()* 1.5f) , (int) (controller.getScale()* 1.5f));				
+			}
+
+		}
+		//maybeReplace:
+		if(mayBeReplaced != null){
+			g2d.setColor(Color.RED);
+			Vector2Int pos = mayBeReplaced.getPosition();
+			g.drawImage(ImageImport.loadImage("/Images/replace.png") , 
+					pos.getX() + controller.getScaleDiv2(),
+					pos.getY() - controller.getScale(),
+					controller.getScaleDiv2(), controller.getScaleDiv2(), null);
+		}
+		//<-- OldCode
+	}
+   
+
+    @Override
+    public void mouseClicked(MouseEvent e) {
+    	if(!disable){
+        triggerUpdateController();
+        stopEditing();
+    	}
+    }
+
+    @Override
+    public void mouseEntered(MouseEvent e) {
+    }
+
+    @Override
+    public void mouseExited(MouseEvent e) {
+    }
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+    	if(!disable){
+    	stopEditing();
+        tempCps = null;
+        dataSelected = null;
+        edgeHighlight = null;
+        controller.setSelecteEdge(null);
+        controller.setSelectedObjectID(-1);
+        // Object Selection
+
+        // Erase old data in the PropertyTable
+        if (model.getPropertyTable().getRowCount() > 0) {
+            for (int i = model.getPropertyTable().getRowCount() - 1; i > -1; i--) {
+                model.getPropertyTable().removeRow(i);
+            }
+        }
+
+        if (e.getX() > upperNode.getLeftBorder()) {
+            for (AbstractCanvasObject cps : upperNode.getNodes()) {
+                cx = cps.getPosition().getX() - model.getScaleDiv2();
+                cy = cps.getPosition().getY() - model.getScaleDiv2();
+                if (x - controller.getScale() <= cx && y - controller.getScale() <= cy && x >= cx && y >= cy) {
+                    tempCps = cps;
+
+
+                    dragging = true;
+                    if (e.isControlDown() && tempCps != null) {
+                        if (model.getSelectedCpsObjects().contains(tempCps)) {
+                            controller.removeSelectedObjectFromSelection(tempCps);
+                        } else {
+                            controller.addSelectedObject(tempCps);
+                            if(tempCps instanceof GroupNode)
+    							controller.getObjectsInDepth();
+                        }
+                    }
+
+                    // If drawing an Edge (CTRL down)
+                    if (tempCps.getClass() == HolonObject.class) {
+                        HolonObject tempObj = ((HolonObject) tempCps);
+                        dataSelected = tempObj.getElements();
+                    }
+                    if (e.isShiftDown()) {
+                        drawEdge = true;
+                        dragging = false;
+                    }
+                    break;
+                }
+            }
+        } else {
+            // look for objects connected to uppernode
+            int count = 0;
+            for (Edge ed : upperNode.getConnections()) {
+                AbstractCanvasObject cps;
+                if (ed.getA().equals(this.upperNode)) {
+                    cps = ed.getB();
+                } else {
+                    cps = ed.getA();
+                }
+                if (x - controller.getScale() <= ((upperNode.getLeftBorder() >> 1) - model.getScaleDiv2())
+                        && y - controller.getScale() <= (scalediv20 + 5 + (model.getScale() + scalediv20 + 10) * count)
+                        && x >= (upperNode.getLeftBorder() >> 1) - model.getScaleDiv2()
+                        && y >= (scalediv20 + 5 + (model.getScale() + scalediv20 + 10) * count)) {
+                    tempCps = cps;
+                    // If drawing an Edge (CTRL down)
+                    if (tempCps.getClass() == HolonObject.class) {
+                        HolonObject tempObj = ((HolonObject) tempCps);
+                        dataSelected = tempObj.getElements();
+                    }
+                    if (e.isShiftDown()) {
+                        drawEdge = true;
+                    }
+                }
+                count++;
+            }
+        }
+
+        // Selection of CpsObject
+        // model.setSelectedCpsObject(tempCps);
+
+        // Edge Selection
+        if (e.getButton() == MouseEvent.BUTTON1) {
+            if (tempCps == null) {
+                edgeHighlight = mousePositionOnEdge(x, y);
+                controller.setSelecteEdge(edgeHighlight);
+                controller.setSelectedObjectID(0);
+                if (!e.isControlDown() && e.getButton() != MouseEvent.BUTTON3) {
+                    controller.clearSelection();
+                }
+                updCon.deleteRows(model.getMultiTable());
+                updCon.deleteRows(model.getSingleTable());
+            }
+
+            if (edgeHighlight == null && tempCps == null) {
+                sx = e.getX();
+                sy = e.getY();
+                doMark = true;
+            }
+            // System.out.println("Selected Objects");
+            // for (AbstractCpsObject temp : model.getSelectedCpsObjects()) {
+            // System.out.println(temp.getName() + " " + temp.getID());
+            // }
+            repaint();
+        }
+    	}
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+    	if(!disable){
+        x = e.getX();
+        y = e.getY();
+        dragging = false;
+        if (model.getSelectedCpsObjects().size() > 1) {
+            model.getTableHolonElement().setModel(model.getMultiTable());
+        } else if (model.getSelectedCpsObjects().size() == 1) {
+            model.getTableHolonElement().setModel(model.getSingleTable());
+        }
+
+        if (drawEdge) {
+            drawEdge = false;
+            drawDeleteEdge();
+        }
+
+        if (dragged) {
+            try { 
+            	/**
+            	 * Save State before performing NodePlacement, replacement e.g.
+            	 */
+                controller.autoSave();
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+            
+            /**
+             * check if tempCps could replace an Object on the UpperNodeanvas
+             */
+            if(model.getSelectedCpsObjects().size() == 1 && checkForReplacement(upperNode.getNodes(), tempCps, tempCps.getPosition().getX(), tempCps.getPosition().getY())){
+            	/**
+            	 * if UpperNode would be replaced, close its tabs
+            	 */
+            	if(mayBeReplaced instanceof GroupNode)
+            		closeUpperNodeTab(mayBeReplaced.getId());
+            	/**
+            	 * replace on canvas
+            	 */
+            	controller.replaceObjUpperNode(mayBeReplaced, tempCps, upperNode);
+            	mayBeReplaced=null;
+            }
+        }
+
+        if (!e.isControlDown() && !dragged && tempCps != null && MouseEvent.BUTTON3 != e.getButton()) {
+            controller.clearSelection();
+            controller.addSelectedObject(tempCps);
+            if(tempCps instanceof GroupNode)
+				controller.getObjectsInDepth();
+        }
+
+        dragged = false;
+
+        // Rightclick List
+        setRightClickMenu(e);
+
+        markObjects();
+
+        if (doubleClick() && tempCps != null && tempCps instanceof HolonSwitch) {
+            ((HolonSwitch) tempCps).switchState();
+        }
+
+        controller.calculateStateAndVisualForTimeStep(model.getCurIteration());
+        triggerUpdateController();
+        repaint();
+    	}
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent e) {
+    	if(!disable){
+        // If Edge is drawn
+        x = e.getX();
+        y = e.getY();
+        if (!model.getSelectedCpsObjects().contains(tempCps) && !doMark) {
+            controller.clearSelection();
+            if (tempCps != null) {
+                controller.addSelectedObject(tempCps);
+            }
+        }
+        if (dragging) {
+            try {            	
+                // tempCps in the upperNode? else its a connected Object from
+                // outside
+                if (upperNode.getNodes().contains(tempCps)) {
+                    dragged = true;
+                    float xDist, yDist; // Distance
+
+                    x = e.getX();
+                    y = e.getY();
+
+                    // Make sure its in bounds
+                    if (e.getX() < controller.getScaleDiv2() + upperNode.getLeftBorder() + 5)
+                        x = controller.getScaleDiv2() + upperNode.getLeftBorder() + 5;
+                    else if (e.getX() > this.getWidth() - controller.getScaleDiv2())
+                        x = this.getWidth() - controller.getScaleDiv2();
+                    if (e.getY() < controller.getScaleDiv2())
+                        y = controller.getScaleDiv2();
+                    else if (e.getY() > this.getHeight() - controller.getScaleDiv2())
+                        y = this.getHeight() - controller.getScaleDiv2();
+
+                    // Distance
+                    xDist = x - tempCps.getPosition().getX();
+                    yDist = y - tempCps.getPosition().getY();
+
+                    tempCps.setPosition(x, y); // Drag Position
+
+                    // TipText Position and name
+                    toolTip = true;
+                    toolTipText = tempCps.getName() + ", " + tempCps.getId();
+                    toolTipPos.setX(tempCps.getPosition().getX() - model.getScaleDiv2());
+                    toolTipPos.setY(tempCps.getPosition().getY() - model.getScaleDiv2());
+
+                    // All Selected Objects
+                    for (AbstractCanvasObject cps : model.getSelectedCpsObjects()) {
+                        if (cps != tempCps) {
+                            x = (int) (cps.getPosition().getX() + xDist);
+                            y = (int) (cps.getPosition().getY() + yDist);
+
+                            // Make sure its in bounds
+                            if (x < upperNode.getLeftBorder() + 5 + controller.getScaleDiv2())
+                                x = controller.getScaleDiv2() + upperNode.getLeftBorder() + 5;
+                            else if (x > this.getWidth() - controller.getScaleDiv2())
+                                x = this.getWidth() - controller.getScaleDiv2();
+                            if (y <= controller.getScaleDiv2())
+                                y = controller.getScaleDiv2();
+                            else if (y > this.getHeight() - controller.getScaleDiv2())
+                                y = this.getHeight() - controller.getScaleDiv2();
+
+                            cps.setPosition(x, y);
+                        }
+                    }
+                }
+                /**
+            	 * check if something would be replaced
+            	 */
+                if(model.getSelectedCpsObjects().size()==1)
+                	checkForReplacement(upperNode.getNodes(), tempCps, x, y);
+
+               repaint();
+            } catch (Exception eex) {
+
+            }
+        	
+        }
+
+        // Mark Objects
+        if (doMark) {
+            tempSelected.clear();
+            for (AbstractCanvasObject cps : upperNode.getNodes()) {
+                int x1 = sx, x2 = x, y1 = sy, y2 = y;
+
+                if (sx >= x) {
+                    x1 = x;
+                    x2 = sx;
+                }
+                if (sy >= y) {
+                    y1 = y;
+                    y2 = sy;
+                }
+                if (x1 <= cps.getPosition().getX() + model.getScaleDiv2() && y1 <= cps.getPosition().getY() + model.getScaleDiv2()
+                        && x2 >= cps.getPosition().getX() && y2 >= cps.getPosition().getY()) {
+                    tempSelected.add(cps);
+
+                }
+            }
+            int count = 0;
+            for (Edge ed : upperNode.getConnections()) {
+                AbstractCanvasObject cps;
+                if (ed.getA().equals(upperNode)) {
+                    cps = ed.getB();
+                } else {
+                    cps = ed.getA();
+                }
+
+                int x1 = sx, x2 = x, y1 = sy, y2 = y;
+
+                if (sx >= x) {
+                    x1 = x;
+                    x2 = sx;
+                }
+                if (sy >= y) {
+                    y1 = y;
+                    y2 = sy;
+                }
+
+                if (x1 <= upperNode.getLeftBorder() >> 1
+                        && y1 <= (int) (5 + (model.getScale() + scalediv20 + 10) * count) + model.getScaleDiv2()
+                        && x2 >= upperNode.getLeftBorder() >> 1
+                        && y2 >= (int) (5 + (model.getScale() + scalediv20 + 10) * count)) {
+                    tempSelected.add(cps);
+
+                }
+                count++;
+            }
+        }
+
+        repaint();
+    	}
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent e) {
+    	{
+        x = e.getX();
+        y = e.getY();
+        // Everything for the tooltip :)
+        boolean on = false;
+        for (AbstractCanvasObject cps : upperNode.getNodes()) {
+
+            cx = cps.getPosition().getX() - controller.getScaleDiv2();
+            cy = cps.getPosition().getY() - controller.getScaleDiv2();
+
+            on = setToolTipInfoAndPosition(on, cps);
+        }
+        int count = 0;
+        for (Edge ed : upperNode.getConnections()) {
+
+            AbstractCanvasObject cps;
+            if (ed.getA().equals(this.upperNode)) {
+                cps = ed.getB();
+            } else {
+                cps = ed.getA();
+            }
+
+            cx = upperNode.getLeftBorder() >> 1;
+            cy = (int) (scalediv20 + 5 + (50 + scalediv20 + 10) * count);
+            if (x - 50 <= cx && y - 50 <= cy && x >= cx && y >= cy) {
+
+                on = true;
+                toolTipPos.setX(cx - 25);
+                toolTipPos.setY(cy + 50);
+                toolTipText = cps.getName() + ", " + cps.getId();
+
+            }
+            count++;
+        }
+
+        toolTip = on;
+        repaint();
+    	}
+    }
+
+    /**
+     * Draws or Deletes an Edge.
+     */
+    void drawDeleteEdge() {
+        boolean node = true; // new node?
+        boolean newEdge = true;
+        boolean onEdge = true;
+        boolean deleteNode = false;
+        boolean outsideCon = !upperNode.getNodes().contains(tempCps); // Connection to the outside
+        boolean found = false; // dont search for outside connetion if inside
+        // connection is found
+        Edge e = null;
+        for (AbstractCanvasObject cps : upperNode.getNodes()) {
+
+            cx = cps.getPosition().getX() - controller.getScaleDiv2();
+            cy = cps.getPosition().getY() - controller.getScaleDiv2();
+
+            if (x - controller.getScale() <= cx && y - controller.getScale() <= cy && x >= cx && y >= cy
+                    && cps != tempCps) {
+                found = true;
+                node = false;
+                onEdge = false;
+                for (Edge p : tempCps.getConnections()) {
+                    if ((p.getA() == tempCps && p.getB() == cps) || (p.getB() == tempCps && p.getA() == cps)) {
+                        newEdge = false;
+                        e = p;
+                    }
+                }
+                if (!newEdge) {
+                    if (outsideCon) {
+                    } else {
+                        controller.removeEdgesOnCanvas(e);
+                    }
+                    // Node ohne Edge?
+                    if (e.getA().getClass() == Node.class && e.getA().getConnections().isEmpty()) {
+                        tempCps = e.getA();
+                        deleteNode = true;
+                    }
+                    if (e.getB().getClass() == Node.class && e.getB().getConnections().isEmpty()) {
+                        deleteNode = true;
+                    }
+                } else {
+                	if(!(cps instanceof GroupNode || tempCps instanceof GroupNode)) {
+						e = new Edge(cps, tempCps, model.getMaxCapacity());
+						controller.addEdgeOnCanvas(e);
+					}else if (cps instanceof GroupNode && !(tempCps instanceof GroupNode)){
+						GroupNode thisUpperNode = (GroupNode)cps;
+						Object[] possibilities = thisUpperNode.getNodes().stream().map(aCps -> new ACpsHandle(aCps)).filter(aCpsHandle -> !(aCpsHandle.object instanceof GroupNode)).toArray();
+						if(possibilities.length != 0) {
+							ACpsHandle selected = (ACpsHandle) JOptionPane.showInputDialog(this, "Select a inside Object:", "Connection To?",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, "");
+							if(selected != null) {
+								e = new Edge(selected.object, tempCps, model.getMaxCapacity());
+								controller.addEdgeOnCanvas(e);
+							}
+						}else {
+							Node n = new Node("Node");
+
+							n.setPosition(x, y);
+							controller.addObjUpperNode(n, thisUpperNode);
+							e = new Edge(n, tempCps, model.getMaxCapacity());
+							controller.addEdgeOnCanvas(e);
+						}
+						
+					}
+                }
+            }
+        }
+        if (!found && !outsideCon) {
+            int count = 0;
+            for (Edge ed : upperNode.getConnections()) {
+                AbstractCanvasObject cps;
+                if (ed.getA().equals(upperNode)) {
+                    cps = ed.getB();
+                } else {
+                    cps = ed.getA();
+                }
+
+                cx = upperNode.getLeftBorder() >> 1;
+                cy = (int) (scalediv20 + 5 + (model.getScale() + scalediv20 + 10) * count);
+
+                if (x - controller.getScale() <= cx && y - controller.getScale() <= cy && x >= cx && y >= cy
+                        && cps != tempCps) {
+                    outsideCon = true;
+                    node = false;
+                    onEdge = false;
+                    for (Edge p : tempCps.getConnections()) {
+                        if ((p.getA() == tempCps && p.getB() == cps) || (p.getB() == tempCps && p.getA() == cps)) {
+                            newEdge = false;
+                            e = p;
+                        }
+                    }
+                    if (!newEdge) {
+
+                        // Node ohne Edge?
+                        if (e.getA().getClass() == Node.class && e.getA().getConnections().isEmpty()) {
+                            tempCps = e.getA();
+                            deleteNode = true;
+                        }
+                        if (e.getB().getClass() == Node.class && e.getB().getConnections().isEmpty()) {
+                            deleteNode = true;
+                        }
+                    } else {
+                        Edge edge = new Edge(cps, tempCps, model.getMaxCapacity());
+                        if (outsideCon) {
+                        } else {
+                            controller.addEdgeOnCanvas(edge);
+                        }
+                    }
+                }
+                count++;
+            }
+        }
+
+        // Edge auf eine Edge gezogen?
+        if (onEdge && !checkForReplacement(x, y)) {
+            Edge p = mousePositionOnEdge(x, y);
+            if (p != null) {
+                Edge e1;
+                Edge e2;
+
+                node = false;
+
+                Node n = new Node("Node");
+
+                n.setPosition(x, y);
+                controller.addObjUpperNode(n, upperNode);
+
+                AbstractCanvasObject r, k;
+                r = p.getA();
+                k = p.getB();
+
+                e = new Edge(n, tempCps, model.getMaxCapacity());
+
+                e1 = new Edge(n, r, model.getMaxCapacity());
+
+                e2 = new Edge(n, k, model.getMaxCapacity());
+
+                controller.addEdgeOnCanvas(e1);
+                controller.addEdgeOnCanvas(e2);
+            }
+        }else{
+        	mayBeReplaced = null;
+        }
+
+        // ins leere Gedragged
+        if (node && x > upperNode.getLeftBorder() && !checkForReplacement(x, y)) {
+            Node n = new Node("Node");
+
+            n.setPosition(x, y);
+            controller.addObjUpperNode(n, upperNode);
+
+            e = new Edge(n, tempCps, model.getMaxCapacity());
+
+        }else{
+        	mayBeReplaced = null;
+        }
+
+        // Wenn ein Node ohne Connections da ist
+        if (deleteNode) {
+            controller.delCanvasObject(tempCps, true);
+            tempCps = null;
+        }
+    }
+
+    /**
+     * Checks if the mouse is on an Edge.
+     *
+     * @param x Position of the Mouse
+     * @param y Position of the Mouse
+     * @return CpsEdge the Mouse is on, null if the mouse is not on an Edge
+     */
+    private Edge mousePositionOnEdge(int x, int y) {
+        x += controller.getScaleDiv2();
+        y += controller.getScaleDiv2();
+        int lx, ly, hx, hy;
+
+//TODO: is this right
+//        for (CpsEdge p : upperNode.getNodeEdges()) {
+//            Line2D l = new Line2D.Float(p.getA().getPosition().getX(), p.getA().getPosition().getY(), p.getB().getPosition().getX(),
+//                    p.getB().getPosition().getY());
+//
+//            int[] positions = determineMousePositionOnEdge(p);
+//            lx = positions[0];
+//            ly = positions[1];
+//            hx = positions[2];
+//            hy = positions[3];
+//
+//            // distance from a point to a line and between both Objects
+//            if (l.ptLineDistSq(x - model.getScaleDiv2(), y - model.getScaleDiv2()) < 20 && x > lx && x < hx && y > ly
+//                    && y < hy) {
+//                return p;
+//            }
+//        }
+
+        // edge to outside connection
+
+        int count = 0;
+        for (Edge e : upperNode.getConnections()) {
+            AbstractCanvasObject cps;
+            if (e.getA().equals(this.upperNode)) {
+                cps = e.getB();
+            } else {
+                cps = e.getA();
+            }
+            for (Edge p : cps.getConnections()) {
+                AbstractCanvasObject obj = null;
+                boolean doTest = false;
+                if (upperNode.getNodes().contains(p.getA())) {
+                    obj = p.getA();
+                    doTest = true;
+                } else if (upperNode.getNodes().contains(p.getB())) {
+                    obj = p.getB();
+                    doTest = true;
+                }
+                // g2.drawImage(img, (borderPos >> 1) - 25, (int) (scalediv20 +
+                // 5 + (50 + scalediv20 + 10) * count), 50, 50, null);
+                if (doTest) {
+                    Line2D l = new Line2D.Float((upperNode.getLeftBorder() >> 1) - 25,
+                            (int) (scalediv20 + 5 + 25 + (50 + scalediv20 + 10) * count), obj.getPosition().getX(),
+                            obj.getPosition().getY());
+                    if ((upperNode.getLeftBorder() >> 1) > obj.getPosition().getX()) {
+                        hx = (upperNode.getLeftBorder() >> 1) - 25 + model.getScaleDiv2() + 7;
+                        lx = obj.getPosition().getX() + model.getScaleDiv2() - 7;
+                    } else {
+                        lx = (upperNode.getLeftBorder() >> 1) - 25 + model.getScaleDiv2() - 7;
+                        hx = obj.getPosition().getX() + model.getScaleDiv2() + 7;
+                    }
+                    if ((int) (scalediv20 + 5 + (50 + scalediv20 + 10) * count) > obj.getPosition().getY()) {
+                        hy = (int) (scalediv20 + 5 + (50 + scalediv20 + 10) * count) + model.getScaleDiv2() + 7;
+                        ly = obj.getPosition().getY() + model.getScaleDiv2() - 7;
+                    } else {
+                        ly = (int) (scalediv20 + 5 + (50 + scalediv20 + 10) * count) + model.getScaleDiv2() - 7;
+                        hy = obj.getPosition().getY() + model.getScaleDiv2() + 7;
+                    }
+
+                    // distance from a point to a line and between both Objects
+                    if (l.ptLineDistSq(x - model.getScaleDiv2(), y - model.getScaleDiv2()) < 20 && x > lx && x < hx
+                            && y > ly && y < hy) {
+                        return p;
+                    }
+                }
+            }
+            count++;
+        }
+        return null;
+    }
+
+
+
+    /**
+     * copies a set of given informations
+     *
+     * @param informations
+     */
+    protected void setShowedInformation(boolean[] informations) {
+        showedInformation = informations;
+    }
+
+
+    /**
+     * set tooltIp
+     *
+     * @param bool
+     */
+    void setToolTip(boolean bool) {
+        this.toolTip = bool;
+    }
+
+    /**
+     * Set the Mouse Position on the UpperNodeCanvas;
+     *
+     * @param x
+     * @param y
+     */
+    void setXY(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+    
+    @Override
+	public boolean checkForReplacement(int x, int y) {
+		return checkForReplacement(upperNode.getNodes(), null, x, y);
+	}
+    
+
+	@Override
+	public void tryToAlignObjects(){
+		/**
+		 * Align all Objects
+		 */
+		for(AbstractCanvasObject cps: upperNode.getNodes())
+			align(cps,3*model.getScaleDiv2());
+		
+		/**
+		 * AutoSave new Positons
+		 */
+		try{	
+			controller.autoSave();
+		} catch (IOException ex) {
+			System.err.println("AutoSave error by aligning");
+			ex.printStackTrace();
+		}
+	}
+
+	@Override
+	public void closeUpperNodeTab(int upperNodeId) {
+        JTabbedPane tabbedPane = (JTabbedPane) getParent().getParent().getParent();
+        for (int i = 4; i < tabbedPane.getTabCount(); i++) {
+            if (((GroupNodeCanvas) ((JScrollPane) tabbedPane.getComponentAt(i)).getViewport()
+                    .getComponent(0)).upperNode.getId() == upperNodeId) {
+                tabbedPane.remove(i);
+                break;
+            }
+        }
+	}
+
+}

+ 417 - 0
src/ui/view/HolonInformationPanel.java.orig

@@ -0,0 +1,417 @@
+package ui.view;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+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.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.swing.BorderFactory;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+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 classes.AbstractCanvasObject;
+import classes.GroupNode;
+import classes.HolonObject;
+import preferences.ColorPreference;
+import ui.controller.Control;
+import ui.controller.FlexManager;
+import ui.controller.FlexManager.FlexWrapper;
+import ui.model.Consumer;
+import ui.model.DecoratedGroupNode;
+import ui.model.DecoratedGroupNode.PriorityCounts;
+import ui.model.DecoratedHolonObject;
+import ui.model.DecoratedHolonObject.HolonObjectState;
+import ui.model.Model;
+import ui.model.Passiv;
+import ui.model.Supplier;
+import utility.FormatFloat;
+
+public class HolonInformationPanel extends JPanel {
+
+	private final int defaultWidth = 50;
+	private final int defaultHeight = 200;
+
+	private PieChart supplyChart = createSupplyStateChart();
+	private PieChart priorityChart = createPriorityChart();
+	private PieChart flexibilityChart = createFlexibilityChart();
+	private PieChart energyChart = createProductionChart();
+	private PieChart activeChart = createActiveChart();
+
+	private XChartPanel<PieChart> panelHolonObject;
+	private XChartPanel<PieChart> panelPriority;
+	private XChartPanel<PieChart> panelFlexibility;
+	private XChartPanel<PieChart> panelEnergy;
+	private XChartPanel<PieChart> panelActive;
+
+	// TODO is this needed to be fields
+	private JPanel graphPanel = new JPanel(new GridLayout(0, 2));
+	private JPanel titlePanel = new JPanel(new BorderLayout(0, 0));
+
+	private Control control;
+	private JTextField titleTextField;
+	private JLabel differenceEnergyLabelAmount;
+
+	public static void main(String[] args) {
+		HolonInformationPanel exampleChart = new HolonInformationPanel(new Control(new Model()));
+		JFrame frame = new JFrame();
+		frame.setContentPane(exampleChart);
+
+		frame.pack();
+		frame.setBounds(0, 0, 540, 600);
+		frame.setLocationRelativeTo(null);
+		frame.setVisible(true);
+	}
+
+	public void updateCharts() {
+		DecoratedGroupNode decoratedGroupNode;
+		switch (control.getModel().getSelectedObjects().size()) {
+		case 0:
+			return;
+		case 1:
+//			titleTextField.setText(control.getModel().getSelectedObjects().getName());
+			titleTextField.setText("TODO");
+			decoratedGroupNode = multiSelectionToDecoratedGroupNode();
+			break;
+		default:
+			titleTextField.setText(getMultiSelectionName());
+			decoratedGroupNode = multiSelectionToDecoratedGroupNode();
+			break;
+		}
+
+		// UPDATE SUPPLY STATE
+		int producerAmount = decoratedGroupNode.getAmountOfSupplier();
+		int overSuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED);
+		int suppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED);
+		int partiallySuppliedAmount = decoratedGroupNode
+				.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED);
+		int notSuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED);
+		int noEnergyAmount = decoratedGroupNode.getAmountOfPassiv();
+
+		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);
+		panelHolonObject.updateToolTips();
+
+		// UPDATE PRIORITYS
+		PriorityCounts priorityCounts = decoratedGroupNode.getPriorityCounts();
+
+		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);
+		panelPriority.updateToolTips();
+
+		// UPDATE PRODUCTION
+		float production = decoratedGroupNode.getProductionFromSupplier();
+		float consumption = decoratedGroupNode.getConsumptionFromConsumer();
+		float difference = Math.abs(production - consumption);
+		energyChart.updatePieSeries("Production", production);
+		energyChart.updatePieSeries("Consumption", consumption);
+		differenceEnergyLabelAmount.setText(FormatFloat.doubleFixedPlaces(1, difference));
+		panelEnergy.updateToolTips();
+
+		// UPDATE FLEXIBILITIES
+		int inUse = 0;
+		int offered = 0;
+		int onCooldown = 0;
+		int notOffered = 0;
+		int unavailable = 0;
+		FlexManager manager = control.getSimManager().getActualFlexManager();
+		Stream<FlexWrapper> flexWrapperStream = decoratedGroupNode.getFlexibilitiesStream()
+				.map(flex -> manager.getFlexWrapperFromFlexibility(flex));
+		List<FlexWrapper> wrapperList = flexWrapperStream.collect(Collectors.toList());
+		for (FlexWrapper wrapper : wrapperList) {
+			switch (wrapper.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);
+		panelFlexibility.updateToolTips();
+
+		// UPDATE ActiveInActive
+		int activeAmount = decoratedGroupNode.getAmountOfAktiveElemntsFromHolonObjects();
+		int inactiveAmounts = decoratedGroupNode.getAmountOfElemntsFromHolonObjects() - activeAmount;
+		activeChart.updatePieSeries("Active", activeAmount);
+		activeChart.updatePieSeries("Inactive", inactiveAmounts);
+		panelActive.updateToolTips();
+
+		this.revalidate();
+		this.repaint();
+	}
+
+	private String getMultiSelectionName() {
+		String name =  control.getModel().getSelectedObjects().stream().map(AbstractCanvasObject::getName)
+				.collect(Collectors.joining(", "));
+		if(name.length() > 25) {
+			name = name.substring(0, 25);
+			name += "...";
+		}
+		return name;
+	}
+
+
+	private DecoratedGroupNode multiSelectionToDecoratedGroupNode() {
+		// TODO Create DecoratedGroupNode
+		DecoratedGroupNode temp = new DecoratedGroupNode(new GroupNode("Temp"));
+
+		// TODO get consumer, supplier, passiv
+		// GroupNodes
+		HashMap<GroupNode, DecoratedGroupNode> accessMapGroupNode = control.getSimManager()
+				.getActualVisualRepresentationalState().getCreatedGroupNodes();
+		List<DecoratedGroupNode> groupNodeList = control.getModel().getSelectedObjects().stream()
+				.filter(object -> object instanceof GroupNode).map(object -> accessMapGroupNode.get(object))
+				.collect(Collectors.toList());
+
+		temp.getGroupNodeList().addAll(groupNodeList);
+
+		// HolonObjects
+		HashMap<HolonObject, DecoratedHolonObject> accessMapHolonObject = control.getSimManager()
+				.getActualVisualRepresentationalState().createdHolonObjects;
+		List<DecoratedHolonObject> holonObjectList = control.getModel().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 temp;
+	}
+
+	public HolonInformationPanel(Control control) {
+		control.OnSelectionChanged.addListener(() -> updateCharts());
+		this.control = control;
+		this.setLayout(new BorderLayout());
+		initGraphPanel();
+		initTitlePanel();
+		this.setBackground(ColorPreference.Panel.Background);
+		this.add(titlePanel, BorderLayout.PAGE_START);
+		this.add(graphPanel, BorderLayout.CENTER);
+	}
+
+	public void initGraphPanel() {
+		graphPanel.setBackground(ColorPreference.Panel.Background);
+		panelHolonObject = new XChartPanel<PieChart>(supplyChart);
+		panelHolonObject.setBackground(ColorPreference.Panel.Background);
+		graphPanel.add(panelHolonObject);
+		panelPriority = new XChartPanel<PieChart>(priorityChart);
+		panelPriority.setBackground(ColorPreference.Panel.Background);
+		graphPanel.add(panelPriority);
+		panelFlexibility = new XChartPanel<PieChart>(flexibilityChart);
+		panelFlexibility.setBackground(ColorPreference.Panel.Background);
+		graphPanel.add(panelFlexibility);
+		Component panel = initEnergyChart();
+		graphPanel.add(panel);
+		panelActive = new XChartPanel<PieChart>(activeChart);
+		panelActive.setBackground(ColorPreference.Panel.Background);
+		panelActive.setLayout(new GridBagLayout());
+		graphPanel.add(panelActive);
+		graphPanel.setBorder(BorderFactory.createLineBorder(Color.lightGray));
+	}
+
+	private JLayeredPane initEnergyChart() {
+		JLayeredPane panel = new JLayeredPane();
+		JPanel panelMiddle = new JPanel(new GridBagLayout());
+		panelEnergy = new XChartPanel<PieChart>(energyChart);
+		panelEnergy.setBackground(ColorPreference.Panel.Background);
+		GridBagConstraints c = new GridBagConstraints();
+		c.gridx = 0;
+		c.gridy = 0;
+		c.insets = new Insets(15, 0, 0, 0); // top padding
+		JLabel difference = new JLabel("Difference:");
+		difference.setHorizontalAlignment(JLabel.CENTER);
+		difference.setAlignmentX(Component.CENTER_ALIGNMENT);
+		difference.setForeground(ColorPreference.Panel.Title);
+		difference.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 10));
+		panelMiddle.add(difference, c);
+		differenceEnergyLabelAmount = new JLabel("");
+		differenceEnergyLabelAmount.setHorizontalAlignment(JLabel.CENTER);
+		differenceEnergyLabelAmount.setForeground(Color.red);
+		differenceEnergyLabelAmount.setAlignmentX(Component.CENTER_ALIGNMENT);
+		differenceEnergyLabelAmount.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 12));
+		c.insets = new Insets(0, 0, 0, 0);
+		c.gridy = 1;
+		panelMiddle.add(differenceEnergyLabelAmount, c);
+		panel.setLayout(new OverlayLayout(panel));
+		panelEnergy.setOpaque(false);
+		panelMiddle.setOpaque(false);
+		panel.add(panelMiddle, Integer.valueOf(0));
+		panel.add(panelEnergy, Integer.valueOf(1));
+		return panel;
+	}
+
+	public void initTitlePanel() {
+		titleTextField = new JTextField("");
+		titleTextField.setFont(new Font("Arial", Font.BOLD, 24));
+		titleTextField.setForeground(ColorPreference.Panel.Title);
+		titleTextField.setBackground(ColorPreference.Panel.Background);
+		titleTextField.setBackground(null);
+		titleTextField.setBorder(null);
+		titlePanel.setBackground(ColorPreference.Panel.Background);
+		titlePanel.setBorder(new EmptyBorder(5, 5, 2, 0));
+		titlePanel.add(titleTextField, BorderLayout.CENTER);
+	}
+
+	public void setDefaultPieChartSettings(PieChart chart) {
+		PieStyler styler = chart.getStyler();
+		styler.setChartTitleVisible(true);
+		styler.setDefaultSeriesRenderStyle(PieSeriesRenderStyle.Donut);
+		styler.setLabelsFont(new java.awt.Font("Arial", java.awt.Font.PLAIN, 14));
+		styler.setLabelType(LabelType.Percentage);
+		styler.setLabelsFontColor(Color.black);
+		styler.setLabelsFontColorAutomaticEnabled(false);
+		styler.setLabelsDistance(0.8);
+		styler.setChartFontColor(ColorPreference.Panel.Title);
+		styler.setToolTipsEnabled(true);
+		styler.setPlotContentSize(0.9);
+		styler.setPlotBackgroundColor(ColorPreference.Panel.Transparent);
+		styler.setPlotBorderColor(ColorPreference.Panel.Transparent);
+		styler.setLegendVisible(false);
+		styler.setChartBackgroundColor(ColorPreference.Panel.Transparent);
+	}
+
+	public PieChart createSupplyStateChart() {
+		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Holon Objects").build();
+		setDefaultPieChartSettings(chart);
+		Color[] sliceColors = new Color[] { ColorPreference.HolonObject.Producer,
+				ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.Supplied,
+				ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.NotSupplied,
+				ColorPreference.HolonObject.NoEnergy };
+		chart.getStyler().setSeriesColors(sliceColors);
+
+		// Series
+		chart.addSeries("Producer", 0);
+		chart.addSeries("Over supplied", 0);
+		chart.addSeries("Supplied", 0);
+		chart.addSeries("Partial supplied", 0);
+		chart.addSeries("Not supplied", 0);
+		chart.addSeries("No energy", 0);
+		return chart;
+	}
+
+	public PieChart createPriorityChart() {
+		// Create Chart
+		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Priotities").build();
+		setDefaultPieChartSettings(chart);
+		// Customize Chart
+		Color[] sliceColors = new Color[] { ColorPreference.Element.Priority.Essential,
+				ColorPreference.Element.Priority.High, ColorPreference.Element.Priority.Medium,
+				ColorPreference.Element.Priority.Low, ColorPreference.Element.Priority.NoData };
+		chart.getStyler().setSeriesColors(sliceColors);
+		// Series
+		chart.addSeries("Essential", 0);
+		chart.addSeries("High", 0);
+		chart.addSeries("Medium", 0);
+		chart.addSeries("Low", 0);
+		chart.addSeries("No Data", 0);
+		return chart;
+	}
+
+	public PieChart createFlexibilityChart() {
+		// IN_USE, ON_COOLDOWN, OFFERED, NOT_OFFERED, UNAVAILABLE
+		// Create Chart
+		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Flexibilities").build();
+		setDefaultPieChartSettings(chart);
+		// Customize Chart
+		Color[] sliceColors = new Color[] { ColorPreference.Flexibility.Offered, ColorPreference.Flexibility.InUse,
+				ColorPreference.Flexibility.OnCooldown, ColorPreference.Flexibility.NotOffered,
+				ColorPreference.Flexibility.Unavailable, ColorPreference.Element.Priority.NoData };
+		chart.getStyler().setSeriesColors(sliceColors);
+		// Series
+		chart.addSeries("Offered", 0);
+		chart.addSeries("In use", 0);
+		chart.addSeries("On cooldown", 0);
+		chart.addSeries("Not offered", 0);
+		chart.addSeries("Unavailable", 0);
+		chart.addSeries("No Data", 0);
+		return chart;
+	}
+
+	public PieChart createProductionChart() {
+		// Create Chart
+		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight)
+				.title("Production vs. Consumption").build();
+		setDefaultPieChartSettings(chart);
+
+		// Customize Chart
+		// Customize Chart
+		Color[] barColors = new Color[] { ColorPreference.Energy.Production, ColorPreference.Energy.Consumption };
+		chart.getStyler().setSeriesColors(barColors);
+		// Series
+		chart.addSeries("Production", 0);
+		chart.addSeries("Consumption", 0);
+		return chart;
+	}
+
+	public PieChart createActiveChart() {
+		// Create Chart
+		PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Active").build();
+		setDefaultPieChartSettings(chart);
+		// Customize Chart
+		// Customize Chart
+		Color[] barColors = new Color[] { ColorPreference.Element.Active, ColorPreference.Element.Inactive };
+		chart.getStyler().setSeriesColors(barColors);
+		// Series
+		chart.addSeries("Active", 0);
+		chart.addSeries("Inactive", 0);
+		return chart;
+	}
+}

+ 1126 - 0
src/ui/view/MyCanvas.java.orig

@@ -0,0 +1,1126 @@
+package ui.view;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.geom.Line2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+
+import com.google.gson.JsonParseException;
+
+import classes.AbstractCanvasObject;
+import classes.Edge;
+import classes.GroupNode;
+import classes.HolonObject;
+import classes.HolonSwitch;
+import classes.Node;
+import preferences.ColorPreference;
+import ui.controller.Control;
+import ui.controller.UpdateController;
+import ui.model.Consumer;
+import ui.model.DecoratedCable;
+import ui.model.DecoratedGroupNode;
+import ui.model.DecoratedHolonObject;
+import ui.model.DecoratedHolonObject.HolonObjectState;
+import ui.model.DecoratedSwitch;
+import ui.model.ExitCable;
+import ui.model.DecoratedSwitch.SwitchState;
+import ui.model.Model;
+import ui.model.Passiv;
+import ui.model.Supplier;
+import ui.model.VisualRepresentationalState;
+import utility.ImageImport;
+import utility.Vector2Int;
+
+/**
+ * This Class is the Canvas. All Objects will be visualized here
+ *
+ * @author Gruppe14
+ */
+public class MyCanvas extends AbstractCanvas implements MouseListener,
+		MouseMotionListener {
+
+	private static final long serialVersionUID = 1L;
+	public boolean disabled = false;
+	/**
+	 * Constructor.
+	 *
+	 * @param mod
+	 *            the Model
+	 * @param control
+	 *            the Controller
+	 * @param unitGraph
+	 */
+	public MyCanvas(Model mod, Control control, UnitGraph unitGraph) {
+		toolTip = false;
+		this.controller = control;
+		this.model = mod;
+		
+		scalediv20 = model.getScale() / 20;
+		
+		showConnectionInformation = true;
+		showedInformation[1] = true;
+		showedInformation[3] = false;
+		showedInformation[4] = true;
+		control.setMaxCapacity(10000);
+		popmenu.add(itemCut);
+		popmenu.add(itemCopy);
+		popmenu.add(itemPaste);
+		popmenu.add(itemDelete);
+		popmenu.add(itemAlign);
+		popmenu.addSeparator();
+		popmenu.add(itemGroup);
+		popmenu.add(itemUngroup);
+		popmenu.add(itemCreateTemplate);
+
+		updCon = new UpdateController(mod, control);
+
+		itemDelete.setEnabled(false);
+		itemCut.setEnabled(false);
+		itemCopy.setEnabled(false);
+		itemPaste.setEnabled(true);
+		itemAlign.setEnabled(false);
+		itemGroup.setEnabled(false);
+		itemUngroup.setEnabled(false);
+
+		itemCut.setText("Cut");
+		
+		itemGroup.addActionListener(actionEvent -> {
+			// calculate uppernode pos (taken from the controller)
+				unPos = new Vector2Int(0, 0);
+				animCps = new ArrayList<>();
+				for (AbstractCanvasObject cps : model.getSelectedCpsObjects()) {
+					animCps.add(cps); // add to animation Cps ArrayList
+					unPos = unPos.add(cps.getPosition());
+				}
+				unPos = unPos.divide(animCps.size());
+
+				// save old Position
+				savePos = new ArrayList<>();
+				for (int i = 0; i < animCps.size(); i++) {
+					savePos.add(animCps.get(i).getPosition().clone());
+				}
+
+				animT = new javax.swing.Timer(animDelay, actionEvent1 -> {
+					if (animDuration - animDelay > 0 && animCps.size() > 1) {
+						for (AbstractCanvasObject animCpObject : animCps) {
+							Vector2Int pos = animCpObject.getPosition();
+	                    	Vector2Int difference = pos.subtract(unPos);
+	                    	Vector2Int result = pos.subtract(difference.divide(animSteps));
+	                    	pos.set(result);
+						}
+						repaint();
+						animDuration -= animDelay;
+						animSteps--;
+					} else {
+						animDuration = ANIMTIME;
+						animSteps = animDuration / animDelay;
+						animT.stop();
+						for (int i = 0; i < animCps.size(); i++) {
+							animCps.get(i).getPosition().set(savePos.get(i));
+						}
+						controller.addUpperNode("GroupNode", null, animCps);
+						controller.calculateStateAndVisualForCurrentTimeStep();
+						triggerUpdateController();
+						controller.clearSelection();
+						repaint();
+					}
+				});
+				animT.start();
+			});
+
+		itemUngroup
+				.addActionListener(actionEvent -> {
+					// save old Position
+					int upperNodeId = tempCps.getId();
+					
+					closeUpperNodeTab(upperNodeId);
+
+					savePos = new ArrayList<>();
+					animCps = ((GroupNode) tempCps).getNodes();
+					controller.ungroupGroupNode((GroupNode) tempCps, null);
+
+					for (int i = 0; i < animCps.size(); i++) {
+						savePos.add(animCps.get(i).getPosition().clone());
+					}
+					for (AbstractCanvasObject cps : animCps) {
+						int x = tempCps.getPosition().getX();
+						int y = tempCps.getPosition().getY();
+
+						cps.setPosition(new Vector2Int(x, y));
+					}
+
+					animT = new javax.swing.Timer(
+							animDelay,
+							actionEvent1 -> {
+								controller.clearSelection();
+								if (animDuration - animDelay >= 0) {
+									for (int i = 0; i < animCps.size(); i++) {
+										Vector2Int pos =  animCps.get(i).getPosition();
+				                    	Vector2Int difference = pos.subtract(savePos.get(i));
+				                    	Vector2Int result = pos.subtract(difference.divide(animSteps));
+				                    	pos.set(result);
+									}
+									repaint();
+									animDuration -= animDelay;
+									animSteps--;
+								} else {
+									animDuration = ANIMTIME;
+									animSteps = animDuration / animDelay;
+									animT.stop();
+									for (int i = 0; i < animCps.size(); i++) {
+										animCps.get(i).getPosition().set(savePos
+												.get(i));
+									}
+									controller.calculateStateAndVisualForCurrentTimeStep();
+									triggerUpdateController();
+									repaint();
+								}
+							});
+					animT.start();
+				});
+
+		// adds the selected object(s) to the statistic panel
+
+		itemDelete.addActionListener(actionEvent -> {
+			// Remove the selected Object objects
+				//Edge Deleting
+				if (tempCps == null && edgeHighlight != null) {
+					controller.removeEdgesOnCanvas(edgeHighlight);
+					//Look for a CPSNode with no Connections and delete them
+					if(edgeHighlight.getA().getClass() == Node.class && edgeHighlight.getA().getConnections().size() == 0){ 
+						controller.delCanvasObject(edgeHighlight.getA(), false);	
+					}
+					if(edgeHighlight.getB().getClass() == Node.class && edgeHighlight.getB().getConnections().size() == 0){ //Look on the other end of the cable
+						controller.delCanvasObject(edgeHighlight.getB(), false);
+					}
+					edgeHighlight = null;
+				}
+				boolean save = false;
+				for (int j = 0; j < model.getSelectedCpsObjects().size(); j++) {
+					AbstractCanvasObject cps = model.getSelectedCpsObjects()
+							.get(j);
+					if (j == model.getSelectedCpsObjects().size() - 1)
+						save = true;
+					controller.delCanvasObject(cps, save);
+					// Remove UpperNodeTab if UpperNode deleted
+				if (cps instanceof GroupNode) {
+					JTabbedPane tabbedPane = (JTabbedPane)getParent().getParent()
+							.getParent().getParent();
+					// Look if the uppernode is open in a Tab
+					for (int i = 4; i < tabbedPane.getTabCount(); i++) {
+						if (tabbedPane.getComponentAt(i) != null
+								&& ((GroupNodeCanvas) ((JScrollPane) tabbedPane
+										.getComponentAt(i)).getViewport()
+										.getComponent(0)).upperNode.getId() == cps
+										.getId()) {
+							((ButtonTabComponent) tabbedPane
+									.getTabComponentAt(i)).removeTabs();
+							break;
+						}
+					}
+				}
+				toolTip = false;
+			}
+			controller.clearSelection();
+			tempCps = null;
+			repaint();
+		});
+
+		itemCut.addActionListener(actionEvent -> {
+			controller.cut(null);
+			itemPaste.setEnabled(true);
+			repaint();
+		});
+
+		itemCopy.addActionListener(actionEvent -> {
+			if(tempCps instanceof GroupNode)
+				controller.getObjectsInDepth();
+			controller.copy(null);
+			itemPaste.setEnabled(true);
+			repaint();
+		});
+
+		itemAlign.addActionListener(actionEvent ->
+		{
+			for(AbstractCanvasObject cps: model.getSelectedCpsObjects())
+				align(cps, model.getScaleDiv2());
+			repaint();
+		});
+		itemPaste
+				.addActionListener(actionEvent -> {
+					try {
+						controller.paste(null, mousePosition);
+
+					} catch (JsonParseException | UnsupportedFlavorException
+							| IOException e1) {
+						JLabel message = new JLabel(
+								"The Clipboard information cannot be pastet into Application.");
+						JOptionPane.showMessageDialog(null, message, "",
+								JOptionPane.ERROR_MESSAGE);
+					}
+					repaint();
+				});
+		
+		/*
+		 * create Template
+		 */
+		itemCreateTemplate.addActionListener(actionEvent -> {
+			controller.createTemplate((HolonObject)tempCps,(JFrame)SwingUtilities.getRoot(this));
+		});
+
+		this.addMouseListener(this);
+		this.addMouseMotionListener(this);
+	}
+
+	/**
+	 * Paints all Components on the Canvas.
+	 *
+	 * @param g
+	 *            Graphics
+	 */
+	
+	public static Color getStateColor(HolonObjectState state) {
+		switch(state) {
+		case NOT_SUPPLIED:
+			return ColorPreference.HolonObject.NotSupplied;
+		case NO_ENERGY:
+			return ColorPreference.HolonObject.NoEnergy;
+		case OVER_SUPPLIED:
+			return ColorPreference.HolonObject.OverSupplied;
+		case PARTIALLY_SUPPLIED:
+			return ColorPreference.HolonObject.PartiallySupplied;
+		case PRODUCER:
+			return ColorPreference.HolonObject.Producer;
+		case SUPPLIED:
+			return ColorPreference.HolonObject.Supplied;
+		default:
+			return Color.BLACK;
+		}
+	}
+	private void paintCanvasObject(Graphics2D g, DecoratedHolonObject decoratedHolonObject){
+		Vector2Int pos = decoratedHolonObject.getModel().getPosition();
+		Color statecolor = getStateColor(decoratedHolonObject.getState());
+		g.setColor(statecolor);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() - controller.getScaleDiv2(), controller.getScale(), controller.getScale());
+		drawCanvasObject(g, decoratedHolonObject.getModel().getImage(), pos);
+	}
+	private void drawCanvasObjectString(Graphics2D g, Vector2Int posOfCanvasObject, float energy) {
+		g.setColor(Color.BLACK);
+		g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (controller.getScale() / 4f) )); 
+		g.drawString((energy > 0)? "+" + Float.toString(energy): Float.toString(energy), posOfCanvasObject.getX() - controller.getScaleDiv2(), posOfCanvasObject.getY() - controller.getScaleDiv2() - 1);
+	}
+	private void paintConsumer(Graphics2D g, Consumer con){
+		paintCanvasObject(g, con);
+		paintSupplyBar(g,con.getSupplyBarPercentage(), getStateColor(con.getState()), con.getModel().getPosition());
+		drawCanvasObjectString(g, con.getModel().getPosition(), -con.getEnergyNeededFromNetwork());
+	}
+	private void paintSupplier(Graphics2D g, Supplier sup){
+		paintCanvasObject(g, sup);
+		drawCanvasObjectString(g, sup.getModel().getPosition(), sup.getEnergyToSupplyNetwork());
+	}
+	
+	private void drawCanvasObject(Graphics2D g, String Image, Vector2Int pos) {
+		g.drawImage(ImageImport.loadImage(Image, controller.getScale(), controller.getScale()) , 
+				pos.getX() - controller.getScaleDiv2(),
+				pos.getY() - controller.getScaleDiv2(),
+				controller.getScale(), controller.getScale() , null);
+	}
+	
+	private void paintCable(Graphics2D g, DecoratedCable cable, boolean isSelected)
+	{
+		Vector2Int start = cable.getModel().getA().getPosition();
+		Vector2Int end =  cable.getModel().getB().getPosition();
+		float currentEnergy = cable.getFlowEnergy();
+		float capacity = cable.getModel().getCapacity();
+		boolean unlimited = cable.getModel().isUnlimitedCapacity();
+		switch(cable.getState()) {
+		case Burned:
+			g.setColor(Color.RED);
+			g.setStroke(new BasicStroke(2));
+			break;
+		case Working:
+			g.setColor(new Color(13, 175, 28));
+			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) {			
+			Vector2Int middle = new Vector2Int((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
+			g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (controller.getScale() / 3.5f), 10) )); 
+			g.drawString(currentEnergy + "/" + (unlimited?"\u221E":capacity) , middle.getX(), middle.getY());
+		}
+	}
+	private void paintSwitch(Graphics2D g, DecoratedSwitch dSwitch)
+	{
+		drawCanvasObject(g, dSwitch.getState() == SwitchState.Open ? HolonSwitch.getSwitchOpenImage(): HolonSwitch.getSwitchClosedImage() , dSwitch.getModel().getPosition());
+	}
+	
+	private void paintExitCable(Graphics2D g, ExitCable eCable) {
+		Vector2Int start = eCable.getStart().getPosition();
+		Vector2Int end = eCable.getFinish().getPosition();
+		float currentEnergy = eCable.getCable().getFlowEnergy();
+		float capacity = eCable.getCable().getModel().getCapacity();
+		boolean unlimited = eCable.getCable().getModel().isUnlimitedCapacity();
+		switch(eCable.getCable().getState()) {
+		case Burned:
+			g.setColor(Color.RED);
+			g.setStroke(new BasicStroke(2));
+			break;
+		case Working:
+			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());
+		Vector2Int middle = new Vector2Int((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
+		g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (controller.getScale() / 3.5f), 10) )); 
+		g.drawString(currentEnergy + "/" + (unlimited?"\u221E":capacity) , middle.getX(), middle.getY());
+	}
+	private void paintGroupNode(Graphics2D g, DecoratedGroupNode dGroupNode) {
+		Vector2Int pos = dGroupNode.getModel().getPosition();
+		g.setColor(Color.lightGray);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() - controller.getScaleDiv2(), controller.getScale(), controller.getScale());
+		drawCanvasObject(g, "/Images/upper_node.png" , pos);
+		paintGroupNodeBar(g, dGroupNode, pos);
+	}
+	private void paintGroupNodeBar(Graphics2D g, DecoratedGroupNode dGroupNode , Vector2Int pos) {
+		// +1, -2, -1 little Adjustment for pixel perfect alignment
+		int barWidth = (int) (controller.getScale());
+		int barHeight = (int) (controller.getScale() / 5);
+		g.setColor(Color.WHITE);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) barWidth, barHeight);
+		float[] percentages = getGroupNodeBarPercentages(dGroupNode);
+		Color[] colors = new Color[6];
+		colors[0] = getStateColor(HolonObjectState.PRODUCER);
+		colors[1] = getStateColor(HolonObjectState.NOT_SUPPLIED);
+		colors[2] = getStateColor(HolonObjectState.PARTIALLY_SUPPLIED);
+		colors[3] = getStateColor(HolonObjectState.SUPPLIED);
+		colors[4] = getStateColor(HolonObjectState.OVER_SUPPLIED);
+		colors[5] = getStateColor(HolonObjectState.NO_ENERGY);
+				
+		for(int i = 5; i>=0; i--) {
+			g.setColor(colors[i]);
+			g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) (barWidth * percentages[i] - 1), barHeight);		
+		}
+//		g.setColor(color);
+//		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
+		g.setColor(Color.BLACK);
+		g.setStroke(new BasicStroke(1));
+		g.drawRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 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, Vector2Int pos) {
+		// +1, -2, -1 little Adjustment for pixel perfect alignment
+		int barWidth = (int) (controller.getScale());
+		int barHeight = (int) (controller.getScale() / 5);
+		g.setColor(Color.WHITE);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) barWidth, barHeight);
+		g.setColor(color);
+		g.fillRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
+		g.setColor(Color.BLACK);
+		g.setStroke(new BasicStroke(1));
+		g.drawRect(pos.getX() - controller.getScaleDiv2(), pos.getY() + controller.getScaleDiv2() - 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() + controller.getScaleDiv2() - 1+ barHeight);
+		
+	}
+	
+	//old code
+	void drawMarker(Graphics2D g) {
+		Color transparentGrey = new Color(128, 174, 247, 40);
+		if (sx > x && sy > y) {
+			g.drawRect(x, y, sx - x, sy - y);
+			g.setColor(transparentGrey);
+			g.fillRect(x, y, sx - x, sy - y);
+		} else if (sx < x && sy < y) {
+			g.drawRect(sx, sy, x - sx, y - sy);
+			g.setColor(transparentGrey);
+			g.fillRect(sx, sy, x - sx, y - sy);
+		} else if (sx >= x) {
+			g.drawRect(x, sy, sx - x, y - sy);
+			g.setColor(transparentGrey);
+			g.fillRect(x, sy, sx - x, y - sy);
+		} else if (sy >= y) {
+			g.drawRect(sx, y, x - sx, sy - y);
+			g.setColor(transparentGrey);
+			g.fillRect(sx, y, x - sx, sy - y);
+		}
+	}
+	public void paintComponent(Graphics g) {		
+		super.paintComponent(g);
+		Graphics2D g2d = (Graphics2D) g;
+		g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING,
+				RenderingHints.VALUE_ANTIALIAS_ON));
+		//-->Old code
+		if (drawEdge) {
+			g2d.setColor(Color.BLACK);
+			g2d.setStroke(new BasicStroke(1));
+			g2d.drawLine(tempCps.getPosition().getX(), tempCps.getPosition().getY(), x, y);
+		}
+		//<--
+		//SelectedCable
+		HashSet<Edge> selectedEdges = new HashSet<Edge>();
+		for(AbstractCanvasObject aCps:  model.getSelectedCpsObjects()) {
+			for(Edge edge: aCps.getConnections()) {
+				selectedEdges.add(edge);
+			}
+		}
+		if(model.getSelectedEdge() != null) selectedEdges.add(model.getSelectedEdge());
+		//timstep:
+		g.setFont(new Font("TimesNewRoman", Font.PLAIN, Math.max((int) (controller.getScale() / 3.5f), 10) )); 
+		g2d.setColor(Color.BLACK);
+		
+		VisualRepresentationalState  visualState = controller.getSimManager().getActualVisualRepresentationalState();
+		//VisualState Representation:
+		if(visualState == null) System.out.println("AHHH"); 
+		for(ExitCable cable : visualState.getExitCableList()) {
+			paintExitCable(g2d, cable);
+		}
+		for(DecoratedCable cable : visualState.getCableList()) {
+			paintCable(g2d, cable, selectedEdges.contains(cable.getModel()));
+		}
+		for(DecoratedGroupNode dGroupNode : visualState.getGroupNodeList()) {
+			paintGroupNode(g2d, dGroupNode);
+		}
+		for(Consumer con: visualState.getConsumerList()) {
+			paintConsumer(g2d, con);					
+		}
+		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, "/Images/node.png" , 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 = new Color(128, 174, 247, 40);
+		for(AbstractCanvasObject aCps:  model.getSelectedCpsObjects()) {
+			if(aCps instanceof Node) {
+				Vector2Int pos = aCps.getPosition();
+				g2d.setColor(transparentGrey);
+				g2d.fillOval(pos.getX() - (int) (controller.getScaleDiv2()), pos.getY() - (int) (controller.getScaleDiv2()),  controller.getScale(),  controller.getScale());
+				g2d.setColor(Color.LIGHT_GRAY);
+				g2d.setStroke(new BasicStroke(2));
+				g2d.drawOval(pos.getX() - (int) (controller.getScaleDiv2()), pos.getY() - (int) (controller.getScaleDiv2()),  controller.getScale(),  controller.getScale());
+			}
+			else {
+				Vector2Int pos = aCps.getPosition();
+				g2d.setColor(transparentGrey);
+				g2d.fillRect(pos.getX() - (int) (controller.getScaleDiv2()* 1.5f), pos.getY() - (int) (controller.getScaleDiv2()* 1.5f), (int) (controller.getScale()* 1.5f) , (int) (controller.getScale()* 1.5f));
+				g2d.setColor(Color.LIGHT_GRAY);
+				g2d.setStroke(new BasicStroke(2));
+				g2d.drawRect(pos.getX() - (int) (controller.getScaleDiv2()* 1.5f), pos.getY() - (int) (controller.getScaleDiv2()* 1.5f), (int) (controller.getScale()* 1.5f) , (int) (controller.getScale()* 1.5f));				
+			}
+
+		}
+		//maybeReplace:
+		if(mayBeReplaced != null){
+			g2d.setColor(Color.RED);
+			Vector2Int pos = mayBeReplaced.getPosition();
+			g2d.drawImage(ImageImport.loadImage("/Images/replace.png") , 
+					pos.getX() + controller.getScaleDiv2(),
+					pos.getY() - controller.getScale(),
+					controller.getScaleDiv2(), controller.getScaleDiv2(), null);
+		}
+		//<-- OldCode
+	}
+
+	@Override
+	public void mouseClicked(MouseEvent e) {
+		if(!disabled){
+			if (e.getButton() == MouseEvent.BUTTON1) {
+			DefaulTable propertyTable = model.getPropertyTable();
+			if (propertyTable.getRowCount() > 0) {
+				for (int i = propertyTable.getRowCount() - 1; i > -1; i--) {
+					propertyTable.removeRow(i);
+				}
+			}
+
+			triggerUpdateController();
+			}
+			stopEditing();
+		}
+	}
+
+	@Override
+	public void mouseEntered(MouseEvent e) {
+	}
+
+	@Override
+	public void mouseExited(MouseEvent e) {
+	}
+
+	@Override
+	public void mousePressed(MouseEvent e) {
+		if(!disabled){
+		stopEditing();
+		tempCps = null;
+		edgeHighlight = null;
+		controller.setSelecteEdge(null);
+		// Object Selection
+		for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
+			cx = cps.getPosition().getX() - controller.getScaleDiv2();
+			cy = cps.getPosition().getY() - controller.getScaleDiv2();
+			if (x - controller.getScale() <= cx
+					&& y - controller.getScale() <= cy && x >= cx && y >= cy) {
+				tempCps = cps;
+
+
+				dragging = true;
+
+				if (e.isControlDown() && tempCps != null) {
+					if (model.getSelectedCpsObjects().contains(tempCps)) {
+						controller.removeSelectedObjectFromSelection(tempCps);
+							//TODO: RemoveDepth
+					} else {
+						controller.addSelectedObject(tempCps);
+						if(tempCps instanceof GroupNode)
+							controller.getObjectsInDepth();
+					}
+
+				}
+
+				// If drawing an Edge (CTRL down)
+				if (tempCps.getClass() == HolonObject.class) {
+					HolonObject tempObj = ((HolonObject) tempCps);
+					dataSelected = tempObj.getElements();
+				}
+				if (e.isShiftDown()) {
+					drawEdge = true;
+					dragging = false;
+				}
+			}
+		}
+
+		// Edge Selection
+		if (tempCps == null) {
+			edgeHighlight = mousePositionOnEdge(x, y);
+			controller.setSelecteEdge(edgeHighlight);
+			controller.setSelectedObjectID(0);
+			if (!e.isControlDown() && e.getButton() != MouseEvent.BUTTON3) {
+				controller.clearSelection();
+			}
+		}
+
+		if (edgeHighlight == null && tempCps == null) {
+			sx = e.getX();
+			sy = e.getY();
+			doMark = true;
+		}
+
+		repaint();
+		}
+	}
+
+	@Override
+	public void mouseReleased(MouseEvent e) {
+		if(!disabled){
+		x = e.getX();
+		y = e.getY();
+
+		dragging = false;
+
+		if (drawEdge) {
+			drawEdge = false;
+			drawDeleteEdge();
+		}
+
+		if (dragged) {
+			try {
+				/**
+				 * Save before further Dragged interactions happen
+				 */
+				controller.autoSave();
+				
+			} catch (IOException ex) {
+				System.err.println("AutoSave error by dragging");
+				ex.printStackTrace();
+			}
+			
+			/**
+			 * check if a unique tempCps could replace an Object on the canvas
+			 */
+			if(model.getSelectedCpsObjects().size()==1 
+					&& checkForReplacement(model.getObjectsOnCanvas(), tempCps, tempCps.getPosition().getX(), tempCps.getPosition().getY())){
+				/**
+            	 * if UpperNode would be replaced, close its tabs
+            	 */
+            	if(mayBeReplaced instanceof GroupNode)
+            		closeUpperNodeTab(mayBeReplaced.getId());
+				/**
+				 * replace on canvas (will save)
+				 */
+				controller.replaceCanvasObject(mayBeReplaced, tempCps);
+				mayBeReplaced=null;
+			}
+		}
+
+		if (!e.isControlDown() && !dragged && tempCps != null
+				&& MouseEvent.BUTTON3 != e.getButton()) {
+			controller.clearSelection();
+			controller.addSelectedObject(tempCps);
+			if(tempCps instanceof GroupNode)
+				controller.getObjectsInDepth();
+		}
+
+		dragged = false;
+
+		// Rightclick List
+		setRightClickMenu(e);
+
+		markObjects();
+
+		if (doubleClick() && tempCps instanceof HolonSwitch 
+				&& MouseEvent.BUTTON3 != e.getButton()&& tempCps != null) {
+			((HolonSwitch) tempCps).switchState();
+
+		}
+		controller.calculateStateAndVisualForTimeStep(model.getCurIteration());
+
+		triggerUpdateController();
+
+		repaint();
+		}
+	}
+
+	@Override
+	public void mouseDragged(MouseEvent e) {
+		if(!disabled){
+		// If Edge is drawn
+		x = e.getX();
+		y = e.getY();
+		
+		if (!model.getSelectedCpsObjects().contains(tempCps) && !doMark) {
+			controller.clearSelection();
+			if (tempCps != null) {
+				controller.addSelectedObject(tempCps);
+			}
+		}
+		if (dragging) {
+			try {
+				dragged = true;
+				float xDist, yDist; // Distance
+
+				x = e.getX();
+				y = e.getY();
+
+				// Make sure its in bounds
+				int scaleDiv2 = controller.getScaleDiv2();
+				if (e.getX() < scaleDiv2)
+					x = scaleDiv2;
+				else if (e.getX() > this.getWidth() - scaleDiv2)
+					x = this.getWidth() - scaleDiv2;
+				if (e.getY() < scaleDiv2)
+					y = scaleDiv2;
+				else if (e.getY() > this.getHeight()
+						- scaleDiv2)
+					y = this.getHeight() - scaleDiv2;
+
+				// Distance
+				xDist = x - tempCps.getPosition().getX();
+				yDist = y - tempCps.getPosition().getY();
+
+				tempCps.setPosition(x, y); // Drag Position
+				// ToolTipText Position and name
+				toolTip = true;
+				toolTipText = tempCps.getName() + ", " + tempCps.getId();
+				toolTipPos.setX(tempCps.getPosition().getX()
+						- scaleDiv2);
+				toolTipPos.setY(tempCps.getPosition().getY()
+						+ scaleDiv2);
+
+				// All Selected Objects
+				for (AbstractCanvasObject cps : model.getSelectedCpsObjects()) {
+					if (cps != tempCps) {
+						x = (int) (cps.getPosition().getX() + xDist);
+						y = (int) (cps.getPosition().getY() + yDist);
+
+						// Make sure its in bounds
+						if (x <= scaleDiv2)
+							x = scaleDiv2;
+						else if (x > this.getWidth()
+								- scaleDiv2)
+							x = this.getWidth() - scaleDiv2;
+						if (y <= scaleDiv2)
+							y = scaleDiv2;
+						else if (y > this.getHeight()
+								- scaleDiv2)
+							y = this.getHeight() - scaleDiv2;
+
+						cps.setPosition(x, y);
+					}
+				}
+				
+				/**
+				 * check if something might be replaced
+				 */
+				if(model.getSelectedCpsObjects().size()==1)
+					checkForReplacement(model.getObjectsOnCanvas(), tempCps, x, y);
+				
+				repaint();
+			} catch (Exception eex) {
+			}
+		}
+
+		// Mark Objects
+		if (doMark) {
+			tempSelected.clear();
+			for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
+				int x1 = sx, x2 = x, y1 = sy, y2 = y;
+
+				if (sx >= x) {
+					x1 = x;
+					x2 = sx;
+				}
+				if (sy >= y) {
+					y1 = y;
+					y2 = sy;
+				}
+				if (x1 <= cps.getPosition().getX() + model.getScaleDiv2()
+						&& y1 <= cps.getPosition().getY() + model.getScaleDiv2()
+						&& x2 >= cps.getPosition().getX()
+						&& y2 >= cps.getPosition().getY()) {
+					tempSelected.add(cps);
+
+				}
+			}
+		}
+
+		repaint();
+		}
+	}
+
+	@Override
+	public void mouseMoved(MouseEvent e) {	
+		if(!disabled){
+		x = e.getX();
+		y = e.getY();
+
+		// Everything for the tooltip :)
+		boolean on = false;
+		for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
+			cx = cps.getPosition().getX() - controller.getScaleDiv2();
+			cy = cps.getPosition().getY() - controller.getScaleDiv2();
+
+			on = setToolTipInfoAndPosition(on, cps);
+		}
+		if(on||(!on && toolTip))
+		repaint();
+		toolTip = on;
+		}
+	}
+
+
+	/**
+	 * Draws or Deletes an Edge.
+	 */
+	void drawDeleteEdge() {
+		if (getMousePosition() != null) {
+			boolean node = true;
+			boolean newEdge = true;
+			boolean onEdge = true;
+			boolean deleteNode = false;
+			Edge e = null;
+
+			for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
+				cx = cps.getPosition().getX() - controller.getScaleDiv2();
+				cy = cps.getPosition().getY() - controller.getScaleDiv2();
+				if (x - controller.getScale() <= cx
+						&& y - controller.getScale() <= cy && x >= cx
+						&& y >= cy && cps != tempCps) {
+					node = false;
+					onEdge = false;
+					for (Edge p : tempCps.getConnections()) {
+						if ((p.getA() == tempCps && p.getB() == cps)
+								|| (p.getB() == tempCps && p.getA() == cps)) {
+							newEdge = false;
+							e = p;
+						}
+					}
+					if (!newEdge) {
+						controller.removeEdgesOnCanvas(e);
+						// Node ohne Edge?
+						if (e.getA().getClass() == Node.class
+								&& e.getA().getConnections().isEmpty()) {
+							tempCps = e.getA();
+							deleteNode = true;
+						}
+						if (e.getB().getClass() == Node.class
+								&& e.getB().getConnections().isEmpty()) {
+							deleteNode = true;
+						}
+					} else {
+						if(!(cps instanceof GroupNode || tempCps instanceof GroupNode)) {
+							e = new Edge(cps, tempCps, model.getMaxCapacity());
+							controller.addEdgeOnCanvas(e);
+						}else if (cps instanceof GroupNode && !(tempCps instanceof GroupNode)){
+							GroupNode thisUpperNode = (GroupNode)cps;
+							Object[] possibilities = thisUpperNode.getNodes().stream().map(aCps -> new ACpsHandle(aCps)).filter(aCpsHandle -> !(aCpsHandle.object instanceof GroupNode)).toArray();
+							if(possibilities.length != 0) {
+								ACpsHandle selected = (ACpsHandle) JOptionPane.showInputDialog(this, "Select a inside Object:", "Connection To?",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, "");
+								if(selected != null) {
+									e = new Edge(selected.object, tempCps, model.getMaxCapacity());
+									controller.addEdgeOnCanvas(e);
+								}
+							}else {
+								Node n = new Node("Node");
+
+								n.setPosition(x, y);
+								controller.addObjUpperNode(n, thisUpperNode);
+								e = new Edge(n, tempCps, model.getMaxCapacity());
+								controller.addEdgeOnCanvas(e);
+							}
+							
+						}
+						
+					}
+				}
+			}
+			// Edge auf eine Edge gezogen?
+			if (onEdge && !checkForReplacement(x, y)) {
+				Edge p = mousePositionOnEdge(x, y);
+				if (p != null) {
+					Edge e1;
+					Edge e2;
+
+					node = false;
+
+					Node n = new Node("Node");
+
+					n.setPosition(x, y);
+					controller.addObjectCanvas(n);
+
+					AbstractCanvasObject r, k;
+					r = p.getA();
+					k = p.getB();
+
+					e = new Edge(n, tempCps, model.getMaxCapacity());
+
+					e1 = new Edge(n, r, model.getMaxCapacity());
+
+					e2 = new Edge(n, k, model.getMaxCapacity());
+
+					controller.removeEdgesOnCanvas(p);
+					controller.addEdgeOnCanvas(e);
+					controller.addEdgeOnCanvas(e1);
+					controller.addEdgeOnCanvas(e2);
+				}
+			}else{
+				mayBeReplaced = null;
+			}
+
+			// ins leere Gedragged
+			if (node && !checkForReplacement(x, y)) {
+				Node n = new Node("Node");
+
+				n.setPosition(x, y);
+				
+					controller.addObjectCanvas(n);
+
+				e = new Edge(n, tempCps, model.getMaxCapacity());
+
+				controller.addEdgeOnCanvas(e);
+			}else{
+				mayBeReplaced = null;
+			}
+
+			// Wenn ein Node ohne Connections da ist
+			if (deleteNode) {
+				controller.delCanvasObject(tempCps, true);
+				tempCps = null;
+			}
+		}
+	}
+
+	/**
+	 * Checks if the mouse is on an Edge.
+	 *
+	 * @param x
+	 *            Position of the Mouse
+	 * @param y
+	 *            Position of the Mouse
+	 * @return CpsEdge the Mouse is on, null if the mouse is not on an Edge
+	 */
+	private Edge mousePositionOnEdge(int x, int y) {
+		x += controller.getScaleDiv2();
+		y += controller.getScaleDiv2();
+		for (Edge p : model.getEdgesOnCanvas()) {
+			Line2D l = new Line2D.Float(p.getA().getPosition().getX(), p.getA()
+					.getPosition().getY(), p.getB().getPosition().getX(), p.getB()
+					.getPosition().getY());
+
+			int[] positions = determineMousePositionOnEdge(p);
+			int lx = positions[0];
+			int ly = positions[1];
+			int hx = positions[2];
+			int hy = positions[3];
+
+			// distance from a point to a line and between both Objects
+			if (l.ptLineDistSq(x - model.getScaleDiv2(),
+					y - model.getScaleDiv2()) < 20
+					&& x > lx && x < hx && y > ly && y < hy) {
+				return p;
+			}
+		}
+		return null;
+	}
+
+	void updateLanguages() {
+		itemCut.setText("Cut");
+		itemCopy.setText("Copy");
+		itemPaste.setText("Paste");
+		itemDelete.setText("Delete");
+		itemGroup.setText("Group");
+		itemUngroup.setText("Ungroup");
+	}
+
+	/**
+	 * Set if Information should be shown.
+	 *
+	 * @param connection
+	 *            boolean for conecction
+	 * @param object
+	 *            boolean for objects
+	 * @param nodeOfnode
+	 */
+	void setShowedInformation(boolean connection, boolean object,
+			boolean border, boolean nodeOfnode) {
+		showConnectionInformation = connection;
+		showedInformation[1] = object;
+		showedInformation[3] = border;
+		showedInformation[4] = nodeOfnode;
+	}
+
+	/**
+	 * Returns if Information should be shown.
+	 *
+	 * @return Array of boolean [0] = connection, [1] = objects
+	 */
+	boolean[] getShowedInformation() {
+		return showedInformation;
+	}
+
+	/**
+	 * set toolTip
+	 *
+	 * @param bool
+	 */
+	void setToolTip(boolean bool) {
+		this.toolTip = bool;
+	}
+
+	/**
+	 * Set the Mouse
+	 *
+	 * @param x
+	 * @param y
+	 */
+	void setXY(int x, int y) {
+		this.x = x;
+		this.y = y;
+	}
+
+	@Override
+	public boolean checkForReplacement(int x, int y) {
+		
+		return checkForReplacement(model.getObjectsOnCanvas(), null, x, y);
+	}
+	
+	@Override
+	public void tryToAlignObjects(){
+		/**
+		 * Align all Objects
+		 */
+		for(AbstractCanvasObject cps: model.getObjectsOnCanvas())
+			align(cps,3*model.getScaleDiv2());
+		
+		/**
+		 * AutoSave new Positons
+		 */
+		try{	
+			controller.autoSave();
+		} catch (IOException ex) {
+			System.err.println("AutoSave error by aligning");
+			ex.printStackTrace();
+		}
+	}
+	
+	
+	@Override
+	public void closeUpperNodeTab(int upperNodeId) {
+		JTabbedPane tabbedPaneInner = (JTabbedPane) getParent()
+				.getParent().getParent().getParent();
+		for (int i = 1; i < tabbedPaneInner.getTabCount(); i++) {
+			if (((GroupNodeCanvas) ((JScrollPane) tabbedPaneInner
+					.getComponentAt(i)).getViewport().getComponent(
+							0)).upperNode.getId() == upperNodeId) {
+				tabbedPaneInner.remove(i);
+				break;
+			}
+		}
+	}
+	
+	
+	   
+}

+ 244 - 0
src/ui/view/Outliner.java.orig

@@ -0,0 +1,244 @@
+package ui.view;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.util.ArrayList;
+
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTree;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import classes.AbstractCanvasObject;
+import ui.controller.Control;
+import ui.model.Consumer;
+import ui.model.DecoratedCable;
+import ui.model.DecoratedHolonObject.HolonObjectState;
+import utility.ImageImport;
+import ui.model.DecoratedNetwork;
+import ui.model.DecoratedState;
+import ui.model.DecoratedSwitch;
+import ui.model.MinimumNetwork;
+import ui.model.Model;
+import ui.model.Passiv;
+import ui.model.Supplier;
+
+
+
+
+
+
+public class Outliner extends JFrame {
+	private static final long serialVersionUID = 1L;
+	JTabbedPane tabbedPane = new JTabbedPane();
+	JPanel listPanel = new JPanel(new BorderLayout());
+	JPanel statePanel = new JPanel(new BorderLayout());
+	public boolean isClosed = false;
+	ArrayList<MinimumNetwork> list;
+	Outliner(JFrame parentFrame, Model model, Control controller){ 
+		setBounds(0, 0, 400, parentFrame.getHeight());
+		this.setIconImage(ImageImport.loadImage("/Images/Holeg.png", 30, 30));
+		this.setTitle("Outliner");
+		setLocationRelativeTo(parentFrame);
+		this.setVisible(true);
+		repaintWithDecoratedState(controller.getSimManager().getActualDecorState());
+		this.getContentPane().add(tabbedPane);
+		this.addWindowListener(new java.awt.event.WindowAdapter() {
+		    @Override
+		    public void windowClosing(java.awt.event.WindowEvent windowEvent) {
+		    	isClosed = true;
+		    }
+		});
+		tabbedPane.addTab("List", listPanel);
+		tabbedPane.addTab("State", statePanel);
+	}
+
+	public void repaintWithDecoratedState(DecoratedState decoratedState) {
+		//tabbedPane.removeAll();
+		listPanel.removeAll();
+		statePanel.removeAll();
+		DefaultMutableTreeNode topListPanel = new DefaultMutableTreeNode();
+		DefaultMutableTreeNode objects = new DefaultMutableTreeNode("HolonObjects");
+		DefaultMutableTreeNode switches = new DefaultMutableTreeNode("Switches");
+		DefaultMutableTreeNode nodes = new DefaultMutableTreeNode("Nodes");
+		DefaultMutableTreeNode cables = new DefaultMutableTreeNode("Cable");
+		topListPanel.add(objects);
+		topListPanel.add(switches);
+		topListPanel.add(nodes);
+		topListPanel.add(cables);
+		DefaultMutableTreeNode topStatePanel = new DefaultMutableTreeNode();
+		
+		for(DecoratedSwitch dSwitch: decoratedState.getDecoratedSwitches()) {
+			switches.add(new DefaultMutableTreeNode(dSwitch.getModel().getName()));
+		}
+		
+		/*for(CpsNode node: decoratedState.getNodeList()) {
+			nodes.add(new DefaultMutableTreeNode(node.getName()));
+		}*/
+		
+		for(DecoratedNetwork dNet: decoratedState.getNetworkList()) {
+			DefaultMutableTreeNode network = new DefaultMutableTreeNode("Network");
+			if(!dNet.getConsumerList().isEmpty() || !dNet.getConsumerSelfSuppliedList().isEmpty()) {
+				DefaultMutableTreeNode consumer = new DefaultMutableTreeNode("ConsumerList");
+				for (Consumer con : dNet.getConsumerList()) {
+					DefaultMutableTreeNode consumerNode = new ColoredTreeNode(con.toString(),con.getState().toString(), getStateColor(con.getState()) );
+					consumer.add(consumerNode);
+					objects.add(new DefaultMutableTreeNode(con.getModel().getName()));
+				}
+				for (Consumer con : dNet.getConsumerSelfSuppliedList()) {
+					DefaultMutableTreeNode consumerNode = new DefaultMutableTreeNode(con.toString() + con.getState());
+					consumer.add(consumerNode);
+					objects.add(new DefaultMutableTreeNode(con.getModel().getName()));
+				}
+				network.add(consumer);
+			}
+			if(!dNet.getSupplierList().isEmpty()) {
+				DefaultMutableTreeNode supplier = new DefaultMutableTreeNode("SupplierList");
+				for (Supplier sup : dNet.getSupplierList()) {
+					supplier.add(new DefaultMutableTreeNode(sup.toString()));
+					objects.add(new DefaultMutableTreeNode(sup.getModel().getName()));
+				}
+				network.add(supplier);
+			}
+			for(Passiv pas: dNet.getPassivNoEnergyList()) {
+				objects.add(new DefaultMutableTreeNode(pas.getModel().getName()));
+			}
+			topStatePanel.add(network);
+			for(DecoratedCable cable : dNet.getDecoratedCableList()) {
+				cables.add(new DefaultMutableTreeNode(cable.getModel().toString()));
+			}
+		}
+		
+		for(DecoratedCable cable : decoratedState.getLeftOverEdges()) {
+			cables.add(new DefaultMutableTreeNode(cable.getModel().toString()));
+		}
+		
+		
+		JTree listTree = new JTree(topListPanel);
+		signIconsForTree(listTree);
+		listTree.setRootVisible(false);
+		for (int i = 0; i < listTree.getRowCount(); i++) {
+			listTree.expandRow(i);
+		}
+		JScrollPane listScroller = new JScrollPane(listTree);
+		listPanel.add(listScroller);
+		
+		JTree stateTree = new JTree(topStatePanel);
+		signIconsForTree(stateTree);
+		stateTree.setRootVisible(false);
+		for (int i = 0; i < stateTree.getRowCount(); i++) {
+			stateTree.expandRow(i);
+		}
+		statePanel.add(new JScrollPane(stateTree));
+		
+		listPanel.revalidate();;
+		statePanel.revalidate();
+		listPanel.repaint();
+	}
+
+
+
+
+
+
+	private void signIconsForTree(JTree t) {
+		ImageIcon ClosedIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/Close.png",9,9));
+		ImageIcon OpenIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/Open.png",9,9));
+		ImageIcon LeafIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/Leaf.png",9,9));
+		if (ClosedIcon != null && OpenIcon != null && LeafIcon!= null) {
+		    DefaultTreeCellRenderer renderer = 
+		        new DefaultTreeCellRenderer();
+		    renderer.setClosedIcon(ClosedIcon);
+		    renderer.setOpenIcon(OpenIcon);
+		    renderer.setLeafIcon(LeafIcon);
+		    t.setCellRenderer(renderer);
+		}
+	}
+	
+	class MyTreeModelListener implements TreeModelListener {
+
+		@Override
+		public void treeNodesChanged(TreeModelEvent tmE) {
+			// TODO Auto-generated method stub
+			System.out.println("treeNodesChanged");
+		}
+
+		@Override
+		public void treeNodesInserted(TreeModelEvent tmE) {
+			// TODO Auto-generated method stub
+			System.out.println("treeNodesInserted");
+		}
+
+		@Override
+		public void treeNodesRemoved(TreeModelEvent tmE) {
+			// TODO Auto-generated method stub
+			System.out.println("treeNodesRemoved");
+		}
+
+		@Override
+		public void treeStructureChanged(TreeModelEvent tmE) {
+			// TODO Auto-generated method stub
+			System.out.println("treeStructureChanged");
+		}
+	
+	}
+	private Color getStateColor(HolonObjectState state) {
+		switch(state) {
+		case NOT_SUPPLIED:
+			return new Color(230, 120, 100);
+		case NO_ENERGY:
+			return Color.white;
+		case OVER_SUPPLIED:
+			return new Color(166, 78, 229);
+		case PARTIALLY_SUPPLIED:
+			return Color.yellow;
+		case PRODUCER:
+			return Color.lightGray;
+		case SUPPLIED:
+			return new Color(13, 175, 28);
+		default:
+			return Color.BLACK;
+		}
+	}
+	
+	
+	class ColoredTreeNode extends DefaultMutableTreeNode{
+		private Color color;
+		public ColoredTreeNode(String string, String state, Color color) {
+			//"<html>Some text <font color='red'>" + "bla" + "some text in red</font></html>"
+			//Integer.toHexString(color.getRGB()).substring(2)
+			//String c = string + "<html><font bgcolor='#132122'>" + state +"</font></html>";
+			super(( "<html>" + string + "<font bgcolor='#" + Integer.toHexString(color.getRGB()).substring(2) + "'>" + state +"</font></html>"));
+			//this.color = color;
+		}
+		public Color getColor(){
+			return color;
+		}
+		public void setColor(Color color) {
+			this.color = color;
+		}
+		
+	}
+	
+	class AbstractCpsObjectInfo {
+		private AbstractCanvasObject aCps;
+		AbstractCpsObjectInfo(AbstractCanvasObject aCps){
+			this.aCps = aCps;
+		}
+		@Override
+		public String toString(){
+			return aCps.getName() + " Id:"+ aCps.getId();
+		}
+		
+		public AbstractCanvasObject getAbstractCpsObject()
+		{
+			return aCps;
+		}
+	}
+}

+ 0 - 1
src/ui/view/canvas/Canvas.java

@@ -636,7 +636,6 @@ public class Canvas extends AbstractCanvas implements MouseListener, MouseMotion
 			if (tempCps == null) {
 				edgeHighlight = mousePositionOnEdge(x, y);
 				controller.setSelecteEdge(edgeHighlight);
-				controller.setSelectedObjectID(0);
 				if (!e.isControlDown() && e.getButton() != MouseEvent.BUTTON3) {
 					controller.clearSelection();
 				}

+ 0 - 2
src/ui/view/canvas/GroupNodeCanvas.java

@@ -163,7 +163,6 @@ public class GroupNodeCanvas extends Canvas {
 			dataSelected = null;
 			edgeHighlight = null;
 			controller.setSelecteEdge(null);
-			controller.setSelectedObjectID(-1);
 			// Object Selection
 
 			if (e.getX() > 0) {
@@ -230,7 +229,6 @@ public class GroupNodeCanvas extends Canvas {
 				if (tempCps == null) {
 					edgeHighlight = mousePositionOnEdge(x, y);
 					controller.setSelecteEdge(edgeHighlight);
-					controller.setSelectedObjectID(0);
 					if (!e.isControlDown() && e.getButton() != MouseEvent.BUTTON3) {
 						controller.clearSelection();
 					}

+ 0 - 1
src/ui/view/main/GUI.java

@@ -1194,7 +1194,6 @@ public class GUI {
 			model.getEdgesOnCanvas().clear();
 			model.getObjectsOnCanvas().clear();
 			controller.OnSelectionChanged.broadcast();
-			controller.setSelectedObjectID(0);
 			controller.setSelecteEdge(null);
 			controller.setCurIteration(0);
 			elementGraph.setText("None");

+ 127 - 124
src/utility/ImageImport.java

@@ -1,125 +1,128 @@
-package utility;
-
-import java.awt.Image;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import javax.imageio.ImageIO;
-
-/**
- * 
- * @author TU-Darmstadt BP Gruppe 7 WS17/18 Centralized resource loading methods
- *         for improved performance and easier troubleshooting.
- */
-public class ImageImport {
-	/*
-	 * Save nothing: Reload every image whenever requested. Save external: Only save
-	 * images that were found as external file. Save raw: Save all non-scaled
-	 * images. Save everything: self-explanatory.
-	 */
-	private static HashMap<String, Image> imgStorage;
-	private static ImageImport xmp = new ImageImport();// Used to load resources from the JAR.
-
-	static {
-		imgStorage = new HashMap<String, Image>();
-	}
-
-	/**
-	 * The rawest function replacing the old method without any default parameters.
-	 * Currently not used in HOLEG at all(aside form calls from the convenience
-	 * methods).
-	 * 
-	 * @param url   Path to the image to be loaded.
-	 * @param w     Width the loaded image should be scaled to.
-	 * @param h     Height the loaded image should be scaled to.
-	 * @param hints Hints for the scaling algorithm to be used. Same as the
-	 *              parameter in the getScaledInstance function of Image.
-	 * @return A loaded and scaled image from the requested path.
-	 */
-	static Image loadImage(String url, int w, int h, int hints) {
-		String key = url + "?" + w + "?" + h + "?" + hints;
-		if (imgStorage.containsKey(key))
-			return (imgStorage.get(key));
-		else {
-			Image img = loadImage(url).getScaledInstance(w, h, hints);
-			imgStorage.put(key, img);
-			return img;
-		}
-	}
-
-	/**
-	 * Loads an image from the given path and scales it using the smooth algorithm.
-	 * 
-	 * @param url Path to the image to be loaded.
-	 * @param w   Width the loaded image should be scaled to.
-	 * @param h   Height the loaded image should be scaled to.
-	 * @return A loaded and (smoothly) scaled image from the requested path.
-	 */
-	public static Image loadImage(String url, int w, int h) {
-		return loadImage(url, w, h, Image.SCALE_SMOOTH);
-	}
-
-	/**
-	 * Loads an image from the given path and scales it using the smooth algorithm.
-	 * 
-	 * @param url Path to the image to be loaded.
-	 * @param w   Width the loaded image should be scaled to.
-	 * @param h   Height the loaded image should be scaled to.
-	 * @return An image loaded from the requested path.
-	 */
-	public static Image loadImage(String url) {
-		if (imgStorage.containsKey(url))
-			return imgStorage.get(url);
-		else {
-			Image img;
-			try {
-				img = ImageIO.read(loadStream(url));
-			} catch (IOException e) {
-				System.err.println(e);
-				return null;
-			}
-			imgStorage.put(url, img);
-			return img;
-		}
-	}
-
-	/**
-	 * Loads any resource with a given path, regardless of whether it is inside the
-	 * jar or an external resource. Every loadImage() function uses this as a basis.
-	 * 
-	 * @param url The path (and file name) of the requested resource.
-	 * @return An InputStream from the requested resource.
-	 * @throws FileNotFoundException
-	 */
-	public static InputStream loadStream(String url) throws FileNotFoundException {
-		InputStream o = xmp.getClass().getResourceAsStream(url);
-		if (o != null)
-			return o;
-		else {
-			boolean rootSymbol = false; // Whether url starts with a / or \
-			switch (url.charAt(0)) { // So we can make sure to construct res/path correctly.
-			case '/':
-			case '\\':
-				rootSymbol = true;
-			}
-			File f = new File(url);
-			if (!f.exists()) {
-				url = "res" + (rootSymbol ? "" : "/") + url;
-			}
-			f = new File(url);// Possible bug with duplicate names.
-			if (!f.exists()) {
-				url = "res/Images/image_not_found.png";
-			}
-			return new FileInputStream(url);
-
-		}
-	}
-
-	// Nobody needs an instance of this. I do, because I use it to load images from
-	// inside the JAR.
-	private ImageImport() {
-	}
+package utility;
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import javax.imageio.ImageIO;
+
+/**
+ * 
+ * @author TU-Darmstadt BP Gruppe 7 WS17/18 Centralized resource loading methods
+ *         for improved performance and easier troubleshooting.
+ */
+public class ImageImport {
+	/*
+	 * Save nothing: Reload every image whenever requested. Save external: Only save
+	 * images that were found as external file. Save raw: Save all non-scaled
+	 * images. Save everything: self-explanatory.
+	 */
+	private static HashMap<String, Image> imgStorage;
+	private static ImageImport xmp = new ImageImport();// Used to load resources from the JAR.
+
+	static {
+		imgStorage = new HashMap<String, Image>();
+	}
+
+	/**
+	 * The rawest function replacing the old method without any default parameters.
+	 * Currently not used in HOLEG at all(aside form calls from the convenience
+	 * methods).
+	 * 
+	 * @param url   Path to the image to be loaded.
+	 * @param w     Width the loaded image should be scaled to.
+	 * @param h     Height the loaded image should be scaled to.
+	 * @param hints Hints for the scaling algorithm to be used. Same as the
+	 *              parameter in the getScaledInstance function of Image.
+	 * @return A loaded and scaled image from the requested path.
+	 */
+	static Image loadImage(String url, int w, int h, int hints) {
+		String key = url + "?" + w + "?" + h + "?" + hints;
+		if (imgStorage.containsKey(key))
+			return (imgStorage.get(key));
+		else {
+			Image img = loadImage(url).getScaledInstance(w, h, hints);
+			imgStorage.put(key, img);
+			return img;
+		}
+	}
+
+	/**
+	 * Loads an image from the given path and scales it using the smooth algorithm.
+	 * 
+	 * @param url Path to the image to be loaded.
+	 * @param w   Width the loaded image should be scaled to.
+	 * @param h   Height the loaded image should be scaled to.
+	 * @return A loaded and (smoothly) scaled image from the requested path.
+	 */
+	public static Image loadImage(String url, int w, int h) {
+		return loadImage(url, w, h, Image.SCALE_SMOOTH);
+	}
+
+	/**
+	 * Loads an image from the given path and scales it using the smooth algorithm.
+	 * 
+	 * @param url Path to the image to be loaded.
+	 * @param w   Width the loaded image should be scaled to.
+	 * @param h   Height the loaded image should be scaled to.
+	 * @return An image loaded from the requested path.
+	 */
+	public static Image loadImage(String url) {
+		if (imgStorage.containsKey(url))
+			return imgStorage.get(url);
+		else {
+			Image img;
+			try {
+				img = ImageIO.read(loadStream(url));
+			} catch (IOException e) {
+				System.err.println(e);
+				return null;
+			}
+			imgStorage.put(url, img);
+			return img;
+		}
+	}
+
+	/**
+	 * Loads any resource with a given path, regardless of whether it is inside the
+	 * jar or an external resource. Every loadImage() function uses this as a basis.
+	 * 
+	 * @param url The path (and file name) of the requested resource.
+	 * @return An InputStream from the requested resource.
+	 * @throws FileNotFoundException
+	 */
+	public static InputStream loadStream(String url) throws FileNotFoundException {
+		InputStream o = xmp.getClass().getResourceAsStream(url);
+		if (o != null)
+			return o;
+		else {
+			boolean rootSymbol = false; // Whether url starts with a / or \
+			switch (url.charAt(0)) { // So we can make sure to construct res/path correctly.
+			case '/':
+			case '\\':
+				rootSymbol = true;
+			}
+			File f = new File(url);
+			if (!f.exists()) {
+				url = "res" + (rootSymbol ? "" : "/") + url;
+			}
+			f = new File(url);// Possible bug with duplicate names.
+			if (!f.exists()) {
+				url = "res/Images/image_not_found.png";
+			}
+			return new FileInputStream(url);
+
+		}
+	}
+
+	// Nobody needs an instance of this. I do, because I use it to load images from
+	// inside the JAR.
+	private ImageImport() {
+	}
 }

+ 1 - 0
tests/tests/PraktikumHolonsTestObjectController.java

@@ -97,6 +97,7 @@ public class PraktikumHolonsTestObjectController {
 			assertTrue("Size does not Match", model.getSelectedObjects().size() == size - 1);
 			assertTrue("Object was not unselected", !model.getSelectedObjects().contains(cps));
 
+
 		}
 	}