HolonInformationPanel.java 16 KB

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