HolonInformationPanel.java 14 KB

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