HolonInformationPanel.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. package holeg.ui.view.information;
  2. import java.awt.BorderLayout;
  3. import java.awt.Color;
  4. import java.awt.Component;
  5. import java.awt.GridBagConstraints;
  6. import java.awt.GridBagLayout;
  7. import java.awt.GridLayout;
  8. import java.awt.Insets;
  9. import java.util.HashMap;
  10. import java.util.List;
  11. import java.util.Optional;
  12. import java.util.function.Predicate;
  13. import java.util.logging.Logger;
  14. import java.util.stream.Collectors;
  15. import java.util.stream.Stream;
  16. import javax.swing.BorderFactory;
  17. import javax.swing.JLabel;
  18. import javax.swing.JLayeredPane;
  19. import javax.swing.JPanel;
  20. import javax.swing.OverlayLayout;
  21. import javax.swing.border.EmptyBorder;
  22. import org.knowm.xchart.PieChart;
  23. import org.knowm.xchart.PieChartBuilder;
  24. import org.knowm.xchart.PieSeries.PieSeriesRenderStyle;
  25. import org.knowm.xchart.XChartPanel;
  26. import org.knowm.xchart.style.PieStyler;
  27. import org.knowm.xchart.style.PieStyler.LabelType;
  28. import holeg.model.Flexibility;
  29. import holeg.model.GroupNode;
  30. import holeg.model.HolonElement;
  31. import holeg.model.HolonObject;
  32. import holeg.model.HolonObject.HolonObjectState;
  33. import holeg.preferences.ColorPreference;
  34. import holeg.ui.controller.Control;
  35. import holeg.utility.math.decimal.Format;
  36. import holeg.ui.model.GuiSettings;
  37. //TODO(Tom2022-01-13): Fix;
  38. public class HolonInformationPanel extends JPanel {
  39. private static final Logger log = Logger.getLogger(JPanel.class.getName());
  40. //private Predicate<DecoratedHolonObject> stateFilter = (object) -> true;// = (object) -> object.getState() ==
  41. // HolonObjectState.PRODUCER;
  42. private Predicate<HolonElement> priorityFilter = (ele) -> true;
  43. private final int defaultWidth = 50;
  44. private final int defaultHeight = 200;
  45. private static final Color[] supplyStateColors = new Color[] { ColorPreference.HolonObject.Producer,
  46. ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.Supplied,
  47. ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.NotSupplied,
  48. ColorPreference.HolonObject.NoEnergy };
  49. private static final Color[] productionColors = new Color[] { ColorPreference.Energy.Production,
  50. ColorPreference.Energy.Consumption };
  51. private static final Color[] activeColors = new Color[] { ColorPreference.Element.Active,
  52. ColorPreference.Element.Inactive };
  53. private static final Color[] flexibilityColors = new Color[] { ColorPreference.Flexibility.Offered,
  54. ColorPreference.Flexibility.InUse, ColorPreference.Flexibility.OnCooldown,
  55. ColorPreference.Flexibility.NotOffered, ColorPreference.Flexibility.Unavailable,
  56. ColorPreference.Element.Priority.NoData };
  57. private static final Color[] priorityColors = new Color[] { ColorPreference.Element.Priority.Essential,
  58. ColorPreference.Element.Priority.High, ColorPreference.Element.Priority.Medium,
  59. ColorPreference.Element.Priority.Low, ColorPreference.Element.Priority.NoData };
  60. private PieChart supplyChart = createSupplyStateChart();
  61. private PieChart priorityChart = createPriorityChart();
  62. private PieChart flexibilityChart = createFlexibilityChart();
  63. private PieChart energyChart = createProductionChart();
  64. private PieChart activeChart = createActiveChart();
  65. private XChartPanel<PieChart> panelHolonObject;
  66. private XChartPanel<PieChart> panelPriority;
  67. private XChartPanel<PieChart> panelFlexibility;
  68. private XChartPanel<PieChart> panelEnergy;
  69. private XChartPanel<PieChart> panelActive;
  70. private JPanel graphPanel = new JPanel(new GridLayout(0, 2));
  71. private JPanel titlePanel = new JPanel(new BorderLayout(0, 0));
  72. private Control control;
  73. private JLabel differenceEnergyLabelAmount = new JLabel("");
  74. public HolonInformationPanel(Control control) {
  75. control.OnSelectionChanged.addListener(() -> updateCharts());
  76. this.control = control;
  77. this.setLayout(new BorderLayout());
  78. initGraphPanel();
  79. initTitlePanel();
  80. this.setBackground(ColorPreference.Panel.Background);
  81. this.add(titlePanel, BorderLayout.PAGE_START);
  82. this.add(graphPanel, BorderLayout.CENTER);
  83. }
  84. public void updateCharts() {
  85. if (GuiSettings.getSelectedObjects().isEmpty()) {
  86. return;
  87. }
  88. Optional<FilterableGroupNode> filteredGroupNode = multiSelectionToFilterableGroupNode();
  89. if(filteredGroupNode.isEmpty()) {
  90. return;
  91. }
  92. FilterableGroupNode decoratedGroupNode = filteredGroupNode.get();
  93. // UPDATE SUPPLY STATE
  94. // int producerAmount = decoratedGroupNode.getAmountOfSupplier(stateFilter);
  95. // int overSuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter,
  96. // HolonObjectState.OVER_SUPPLIED);
  97. // int suppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter, HolonObjectState.SUPPLIED);
  98. // int partiallySuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter,
  99. // HolonObjectState.PARTIALLY_SUPPLIED);
  100. // int notSuppliedAmount = decoratedGroupNode.getAmountOfConsumerWithState(stateFilter,
  101. // HolonObjectState.NOT_SUPPLIED);
  102. // int noEnergyAmount = decoratedGroupNode.getAmountOfPassiv(stateFilter);
  103. //
  104. // supplyChart.updatePieSeries("Producer", producerAmount);
  105. // supplyChart.updatePieSeries("Over supplied", overSuppliedAmount);
  106. // supplyChart.updatePieSeries("Supplied", suppliedAmount);
  107. // supplyChart.updatePieSeries("Partial supplied", partiallySuppliedAmount);
  108. // supplyChart.updatePieSeries("Not supplied", notSuppliedAmount);
  109. // supplyChart.updatePieSeries("No energy", noEnergyAmount);
  110. // UPDATE PRIORITYS
  111. // holeg.ui.view.information.FilterableGroupNode.PriorityCounts priorityCounts = decoratedGroupNode
  112. // .getPriorityCounts(stateFilter);
  113. //
  114. // priorityChart.updatePieSeries("Essential", priorityCounts.essential);
  115. // priorityChart.updatePieSeries("High", priorityCounts.high);
  116. // priorityChart.updatePieSeries("Medium", priorityCounts.medium);
  117. // priorityChart.updatePieSeries("Low", priorityCounts.low);
  118. // boolean hasPriority = priorityCounts.essential + priorityCounts.high + priorityCounts.medium
  119. // + priorityCounts.low > 0;
  120. // priorityChart.updatePieSeries("No Data", hasPriority ? 0 : 1);
  121. // updateToolTips(panelPriority);
  122. // UPDATE PRODUCTION
  123. // float production = decoratedGroupNode.getProduction(stateFilter, priorityFilter);
  124. // float consumption = decoratedGroupNode.getConsumption(stateFilter, priorityFilter);
  125. // log.info("production" + production + " consumption" + consumption);
  126. // float difference = Math.abs(production - consumption);
  127. // energyChart.updatePieSeries("Production", production);
  128. // energyChart.updatePieSeries("Consumption", consumption);
  129. // differenceEnergyLabelAmount.setText(Format.doubleFixedPlaces(1, difference));
  130. //
  131. // // UPDATE FLEXIBILITIES
  132. // int inUse = 0;
  133. // int offered = 0;
  134. // int onCooldown = 0;
  135. // int notOffered = 0;
  136. // int unavailable = 0;
  137. //
  138. // Stream<Flexibility> flexWrapperStream = decoratedGroupNode.getFlexibilitiesStream(stateFilter, priorityFilter);
  139. // List<Flexibility> flexList = flexWrapperStream.collect(Collectors.toList());
  140. // for (Flexibility flex : flexList) {
  141. // switch (flex.getState()) {
  142. // case IN_USE:
  143. // inUse++;
  144. // break;
  145. // case NOT_OFFERED:
  146. // notOffered++;
  147. // break;
  148. // case OFFERED:
  149. // offered++;
  150. // break;
  151. // case ON_COOLDOWN:
  152. // onCooldown++;
  153. // break;
  154. // case UNAVAILABLE:
  155. // unavailable++;
  156. // break;
  157. // default:
  158. // break;
  159. //
  160. // }
  161. // }
  162. // flexibilityChart.updatePieSeries("Offered", offered);
  163. // flexibilityChart.updatePieSeries("In use", inUse);
  164. // flexibilityChart.updatePieSeries("On cooldown", onCooldown);
  165. // flexibilityChart.updatePieSeries("Not offered", notOffered);
  166. // flexibilityChart.updatePieSeries("Unavailable", unavailable);
  167. // boolean hasFlex = offered + inUse + onCooldown + notOffered + unavailable > 0;
  168. // flexibilityChart.updatePieSeries("No Data", hasFlex ? 0 : 1);
  169. // // UPDATE ActiveInActive
  170. // int activeAmount = decoratedGroupNode.getAmountOfAktiveElementsFromHolonObjects(stateFilter, priorityFilter);
  171. // int inactiveAmounts = decoratedGroupNode.getAmountOfElementsFromHolonObjects(stateFilter, priorityFilter)
  172. // - activeAmount;
  173. // activeChart.updatePieSeries("Active", activeAmount);
  174. // activeChart.updatePieSeries("Inactive", inactiveAmounts);
  175. this.revalidate();
  176. this.repaint();
  177. }
  178. private Optional<FilterableGroupNode> multiSelectionToFilterableGroupNode() {
  179. // FilterableGroupNode temp = new FilterableGroupNode(new GroupNode("Temp"),
  180. // control.getModel().getCurrentIteration());
  181. // Optional<VisualRepresentationalState> visState = control.getSimManager().getActualVisualRepresentationalState();
  182. // if(visState.isEmpty()) {
  183. // return Optional.empty();
  184. // }
  185. //
  186. // // GroupNodes
  187. // HashMap<GroupNode, DecoratedGroupNode> accessMapGroupNode = visState.get().getCreatedGroupNodes();
  188. // List<FilterableGroupNode> groupNodeList = GuiSettings.getSelectedObjects().stream()
  189. // .filter(object -> object instanceof GroupNode).map(object -> accessMapGroupNode.get(object))
  190. // .map(node -> new FilterableGroupNode(node, control.getModel().getCurrentIteration()))
  191. // .collect(Collectors.toList());
  192. //
  193. // temp.getGroupNodeList().addAll(groupNodeList);
  194. //
  195. // // HolonObjects
  196. // HashMap<HolonObject, DecoratedHolonObject> accessMapHolonObject = visState.get().createdHolonObjects;
  197. // List<DecoratedHolonObject> holonObjectList = GuiSettings.getSelectedObjects().stream()
  198. // .filter(object -> object instanceof HolonObject).map(object -> accessMapHolonObject.get(object))
  199. // .collect(Collectors.toList());
  200. //
  201. // for (DecoratedHolonObject object : holonObjectList) {
  202. // switch (object.getState()) {
  203. // case NO_ENERGY:
  204. // temp.getPassivList().add((Passiv) object);
  205. // break;
  206. // case PRODUCER:
  207. // temp.getSupplierList().add((Supplier) object);
  208. // break;
  209. // default:
  210. // temp.getConsumerList().add((Consumer) object);
  211. // break;
  212. // }
  213. // }
  214. // return Optional.of(temp);
  215. return Optional.empty();
  216. }
  217. public void initGraphPanel() {
  218. graphPanel.setBackground(ColorPreference.Panel.Background);
  219. panelHolonObject = new XChartPanel<PieChart>(supplyChart);
  220. panelHolonObject.setBackground(ColorPreference.Panel.Background);
  221. graphPanel.add(panelHolonObject);
  222. panelPriority = new XChartPanel<PieChart>(priorityChart);
  223. panelPriority.setBackground(ColorPreference.Panel.Background);
  224. graphPanel.add(panelPriority);
  225. panelFlexibility = new XChartPanel<PieChart>(flexibilityChart);
  226. panelFlexibility.setBackground(ColorPreference.Panel.Background);
  227. graphPanel.add(panelFlexibility);
  228. Component panel = initEnergyChart();
  229. graphPanel.add(panel);
  230. panelActive = new XChartPanel<PieChart>(activeChart);
  231. panelActive.setBackground(ColorPreference.Panel.Background);
  232. panelActive.setLayout(new GridBagLayout());
  233. graphPanel.add(panelActive);
  234. graphPanel.setBorder(BorderFactory.createLineBorder(Color.lightGray));
  235. }
  236. private JLayeredPane initEnergyChart() {
  237. JLayeredPane panel = new JLayeredPane();
  238. JPanel panelMiddle = new JPanel(new GridBagLayout());
  239. panelEnergy = new XChartPanel<PieChart>(energyChart);
  240. panelEnergy.setBackground(ColorPreference.Panel.Background);
  241. GridBagConstraints c = new GridBagConstraints();
  242. c.gridx = 0;
  243. c.gridy = 0;
  244. c.insets = new Insets(15, 0, 0, 0); // top padding
  245. JLabel difference = new JLabel("Difference:");
  246. difference.setHorizontalAlignment(JLabel.CENTER);
  247. difference.setAlignmentX(Component.CENTER_ALIGNMENT);
  248. difference.setForeground(ColorPreference.Panel.Title);
  249. difference.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 10));
  250. panelMiddle.add(difference, c);
  251. differenceEnergyLabelAmount.setHorizontalAlignment(JLabel.CENTER);
  252. differenceEnergyLabelAmount.setForeground(Color.red);
  253. differenceEnergyLabelAmount.setAlignmentX(Component.CENTER_ALIGNMENT);
  254. differenceEnergyLabelAmount.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 12));
  255. c.insets = new Insets(0, 0, 0, 0);
  256. c.gridy = 1;
  257. panelMiddle.add(differenceEnergyLabelAmount, c);
  258. panel.setLayout(new OverlayLayout(panel));
  259. panelEnergy.setOpaque(false);
  260. panelMiddle.setOpaque(false);
  261. panel.add(panelMiddle, Integer.valueOf(0));
  262. panel.add(panelEnergy, Integer.valueOf(1));
  263. return panel;
  264. }
  265. public void initTitlePanel() {
  266. titlePanel.setBackground(ColorPreference.Panel.Background);
  267. titlePanel.setBorder(new EmptyBorder(5, 5, 2, 0));
  268. }
  269. public void setDefaultPieChartSettings(PieChart chart) {
  270. PieStyler styler = chart.getStyler();
  271. styler.setChartTitleVisible(true);
  272. styler.setDefaultSeriesRenderStyle(PieSeriesRenderStyle.Donut);
  273. styler.setLabelsFont(new java.awt.Font("Arial", java.awt.Font.PLAIN, 14));
  274. styler.setLabelType(LabelType.Percentage);
  275. styler.setLabelsFontColor(Color.black);
  276. styler.setLabelsFontColorAutomaticEnabled(false);
  277. styler.setLabelsDistance(0.8);
  278. styler.setChartFontColor(ColorPreference.Panel.Title);
  279. styler.setToolTipsEnabled(true);
  280. styler.setPlotContentSize(0.9);
  281. styler.setPlotBackgroundColor(ColorPreference.Panel.Transparent);
  282. styler.setPlotBorderColor(ColorPreference.Panel.Transparent);
  283. styler.setLegendVisible(false);
  284. styler.setChartBackgroundColor(ColorPreference.Panel.Transparent);
  285. }
  286. public PieChart createSupplyStateChart() {
  287. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Holon Objects").build();
  288. setDefaultPieChartSettings(chart);
  289. chart.getStyler().setSeriesColors(supplyStateColors);
  290. // Series
  291. chart.addSeries("Producer", 0);
  292. chart.addSeries("Over supplied", 0);
  293. chart.addSeries("Supplied", 0);
  294. chart.addSeries("Partial supplied", 0);
  295. chart.addSeries("Not supplied", 0);
  296. chart.addSeries("No energy", 0);
  297. return chart;
  298. }
  299. public PieChart createPriorityChart() {
  300. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Priotities").build();
  301. setDefaultPieChartSettings(chart);
  302. // Customize Chart
  303. chart.getStyler().setSeriesColors(priorityColors);
  304. // Series
  305. chart.addSeries("Essential", 0);
  306. chart.addSeries("High", 0);
  307. chart.addSeries("Medium", 0);
  308. chart.addSeries("Low", 0);
  309. chart.addSeries("No Data", 0);
  310. return chart;
  311. }
  312. public PieChart createFlexibilityChart() {
  313. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Flexibilities").build();
  314. setDefaultPieChartSettings(chart);
  315. // Customize Chart
  316. chart.getStyler().setSeriesColors(flexibilityColors);
  317. // Series
  318. chart.addSeries("Offered", 0);
  319. chart.addSeries("In use", 0);
  320. chart.addSeries("On cooldown", 0);
  321. chart.addSeries("Not offered", 0);
  322. chart.addSeries("Unavailable", 0);
  323. chart.addSeries("No Data", 0);
  324. return chart;
  325. }
  326. public PieChart createProductionChart() {
  327. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight)
  328. .title("Production vs. Consumption").build();
  329. setDefaultPieChartSettings(chart);
  330. // Customize Chart
  331. // Customize Chart
  332. chart.getStyler().setSeriesColors(productionColors);
  333. // Series
  334. chart.addSeries("Production", 0);
  335. chart.addSeries("Consumption", 0);
  336. return chart;
  337. }
  338. public PieChart createActiveChart() {
  339. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Active").build();
  340. setDefaultPieChartSettings(chart);
  341. // Customize Chart
  342. // Customize Chart
  343. chart.getStyler().setSeriesColors(activeColors);
  344. // Series
  345. chart.addSeries("Active", 0);
  346. chart.addSeries("Inactive", 0);
  347. return chart;
  348. }
  349. }