HolonInformationPanel.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. package holeg.ui.view.information;
  2. import holeg.model.AbstractCanvasObject;
  3. import holeg.model.Flexibility;
  4. import holeg.model.GroupNode;
  5. import holeg.model.HolonElement;
  6. import holeg.model.HolonObject;
  7. import holeg.model.HolonObject.HolonObjectState;
  8. import holeg.model.HolonSwitch;
  9. import holeg.model.Node;
  10. import holeg.preferences.ColorPreference;
  11. import holeg.preferences.ImagePreference;
  12. import holeg.ui.controller.Control;
  13. import holeg.ui.model.GuiSettings;
  14. import holeg.ui.view.image.Import;
  15. import holeg.utility.math.decimal.Format;
  16. import java.awt.BorderLayout;
  17. import java.awt.Color;
  18. import java.awt.Component;
  19. import java.awt.GridBagConstraints;
  20. import java.awt.GridBagLayout;
  21. import java.awt.GridLayout;
  22. import java.awt.Insets;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.logging.Logger;
  26. import java.util.stream.Collectors;
  27. import javax.swing.BorderFactory;
  28. import javax.swing.Icon;
  29. import javax.swing.ImageIcon;
  30. import javax.swing.JCheckBoxMenuItem;
  31. import javax.swing.JLabel;
  32. import javax.swing.JLayeredPane;
  33. import javax.swing.JPanel;
  34. import javax.swing.JPopupMenu;
  35. import javax.swing.JToggleButton;
  36. import javax.swing.OverlayLayout;
  37. import javax.swing.event.PopupMenuEvent;
  38. import javax.swing.event.PopupMenuListener;
  39. import org.knowm.xchart.PieChart;
  40. import org.knowm.xchart.PieChartBuilder;
  41. import org.knowm.xchart.PieSeries.PieSeriesRenderStyle;
  42. import org.knowm.xchart.XChartPanel;
  43. import org.knowm.xchart.style.PieStyler;
  44. import org.knowm.xchart.style.PieStyler.LabelType;
  45. /**
  46. * This panel shows aggregated information of the selection of the canvas objects.
  47. */
  48. public class HolonInformationPanel extends JPanel {
  49. private static final Logger log = Logger.getLogger(HolonInformationPanel.class.getName());
  50. private static final Color[] supplyStateColors = new Color[]{ColorPreference.HolonObject.Producer,
  51. ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.Supplied,
  52. ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.NotSupplied,
  53. ColorPreference.HolonObject.NoEnergy, ColorPreference.InformationPanel.NoData};
  54. private static final Color[] productionColors = new Color[]{ColorPreference.Energy.Production,
  55. ColorPreference.Energy.Consumption, ColorPreference.InformationPanel.NoData};
  56. private static final Color[] activeColors = new Color[]{ColorPreference.Element.Active,
  57. ColorPreference.Element.Inactive, ColorPreference.InformationPanel.NoData};
  58. private static final Color[] flexibilityColors = new Color[]{ColorPreference.Flexibility.Offered,
  59. ColorPreference.Flexibility.InUse, ColorPreference.Flexibility.OnCooldown,
  60. ColorPreference.Flexibility.NotOffered, ColorPreference.Flexibility.Unavailable,
  61. ColorPreference.Flexibility.NoFlexibility,
  62. ColorPreference.InformationPanel.NoData};
  63. private static final Color[] priorityColors = new Color[]{
  64. ColorPreference.Element.Priority.Essential,
  65. ColorPreference.Element.Priority.High, ColorPreference.Element.Priority.Medium,
  66. ColorPreference.Element.Priority.Low, ColorPreference.InformationPanel.NoData};
  67. private final int defaultWidth = 50;
  68. private final int defaultHeight = 200;
  69. private final PieChart supplyChart = createSupplyStateChart();
  70. private final PieChart priorityChart = createPriorityChart();
  71. private final PieChart flexibilityChart = createFlexibilityChart();
  72. private final PieChart energyChart = createProductionChart();
  73. private final PieChart activeChart = createActiveChart();
  74. private final JPanel graphPanel = new JPanel(new GridLayout(0, 2));
  75. private final JCheckBoxMenuItem producerCheckBox = new JCheckBoxMenuItem("Producer", true);
  76. private final JCheckBoxMenuItem overSuppliedCheckBox = new JCheckBoxMenuItem("Over supplied",
  77. true);
  78. private final JCheckBoxMenuItem suppliedCheckBox = new JCheckBoxMenuItem("Supplied", true);
  79. private final JCheckBoxMenuItem partiallySuppliedCheckBox = new JCheckBoxMenuItem(
  80. "Partial supplied", true);
  81. private final JCheckBoxMenuItem notSuppliedCheckBox = new JCheckBoxMenuItem("Not supplied", true);
  82. private final JCheckBoxMenuItem noEnergyCheckBox = new JCheckBoxMenuItem("No energy", true);
  83. private final JCheckBoxMenuItem essentialCheckBox = new JCheckBoxMenuItem("Essential", true);
  84. private final JCheckBoxMenuItem highCheckBox = new JCheckBoxMenuItem("High", true);
  85. private final JCheckBoxMenuItem mediumBox = new JCheckBoxMenuItem("Medium", true);
  86. private final JCheckBoxMenuItem lowCheckBox = new JCheckBoxMenuItem("Low", true);
  87. private final JCheckBoxMenuItem activeCheckBox = new JCheckBoxMenuItem("Active", true);
  88. private final JCheckBoxMenuItem inactiveCheckBox = new JCheckBoxMenuItem("Inactive", true);
  89. private final JCheckBoxMenuItem noFlexibilityCheckBox = new JCheckBoxMenuItem("No Flexibility",
  90. true);
  91. private final JCheckBoxMenuItem inUseCheckBox = new JCheckBoxMenuItem("In use", true);
  92. private final JCheckBoxMenuItem offeredCheckBox = new JCheckBoxMenuItem("Offered", true);
  93. private final JCheckBoxMenuItem notOfferedCheckBox = new JCheckBoxMenuItem("Not offered", true);
  94. private final JCheckBoxMenuItem onCooldownCheckBox = new JCheckBoxMenuItem("On cooldown", true);
  95. private final JCheckBoxMenuItem unavailableCheckBox = new JCheckBoxMenuItem("Unavailable", true);
  96. private final Control control;
  97. private final JLabel differenceEnergyLabelAmount = new JLabel("");
  98. public HolonInformationPanel(Control control) {
  99. control.OnSelectionChanged.addListener(this::updateCharts);
  100. control.OnCanvasUpdate.addListener(this::updateCharts);
  101. this.control = control;
  102. this.setLayout(new BorderLayout());
  103. initGraphPanel();
  104. this.setBackground(ColorPreference.Panel.Background);
  105. this.add(graphPanel, BorderLayout.CENTER);
  106. }
  107. private void updateCharts() {
  108. TempGroupNode tempGroupNode = new TempGroupNode();
  109. if (GuiSettings.getSelectedObjects().isEmpty()) {
  110. tempGroupNode.add(control.getModel().getCanvas());
  111. } else {
  112. tempGroupNode.addAll(GuiSettings.getSelectedObjects());
  113. }
  114. List<HolonObject> filteredHolonObjectList = tempGroupNode.getAllHolonObjectsRecursive()
  115. .filter(this::stateFilter).toList();
  116. Map<HolonObjectState, Long> stateMap = filteredHolonObjectList.stream()
  117. .collect(Collectors.groupingBy(HolonObject::getState, Collectors.counting()));
  118. // UPDATE SUPPLY STATE
  119. int producerAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.PRODUCER, 0L));
  120. int overSuppliedAmount = Math.toIntExact(
  121. stateMap.getOrDefault(HolonObjectState.OVER_SUPPLIED, 0L));
  122. int suppliedAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.SUPPLIED, 0L));
  123. int partiallySuppliedAmount = Math.toIntExact(
  124. stateMap.getOrDefault(HolonObjectState.PARTIALLY_SUPPLIED, 0L));
  125. int notSuppliedAmount = Math.toIntExact(
  126. stateMap.getOrDefault(HolonObjectState.NOT_SUPPLIED, 0L));
  127. int noEnergyAmount = Math.toIntExact(stateMap.getOrDefault(HolonObjectState.NO_ENERGY, 0L));
  128. supplyChart.updatePieSeries("Producer", producerAmount);
  129. supplyChart.updatePieSeries("Over supplied", overSuppliedAmount);
  130. supplyChart.updatePieSeries("Supplied", suppliedAmount);
  131. supplyChart.updatePieSeries("Partial supplied", partiallySuppliedAmount);
  132. supplyChart.updatePieSeries("Not supplied", notSuppliedAmount);
  133. supplyChart.updatePieSeries("No energy", noEnergyAmount);
  134. supplyChart.updatePieSeries("No Data", filteredHolonObjectList.isEmpty() ? 1 : 0);
  135. //UPDATE PRIORITIES
  136. List<HolonElement> filteredHolonElements = filteredHolonObjectList.stream()
  137. .flatMap(HolonObject::elementsStream)
  138. .filter(ele -> priorityFilter(ele) && activeFilter(ele) && flexibilityFilter(ele)).toList();
  139. Map<HolonElement.Priority, Long> priorityCounts = filteredHolonElements.stream()
  140. .collect(Collectors.groupingBy(HolonElement::getPriority, Collectors.counting()));
  141. long essential = priorityCounts.getOrDefault(HolonElement.Priority.Essential, 0L);
  142. long high = priorityCounts.getOrDefault(HolonElement.Priority.High, 0L);
  143. long medium = priorityCounts.getOrDefault(HolonElement.Priority.Medium, 0L);
  144. long low = priorityCounts.getOrDefault(HolonElement.Priority.Low, 0L);
  145. priorityChart.updatePieSeries("Essential", essential);
  146. priorityChart.updatePieSeries("High", high);
  147. priorityChart.updatePieSeries("Medium", medium);
  148. priorityChart.updatePieSeries("Low", low);
  149. boolean hasPriority = essential + high + medium + low > 0;
  150. priorityChart.updatePieSeries("No Data", hasPriority ? 0 : 1);
  151. // UPDATE PRODUCTION
  152. float consumption = filteredHolonElements.stream()
  153. .filter(element -> element.getActualEnergy() < 0)
  154. .map(element -> -element.getActualEnergy()).reduce(0.0f, Float::sum);
  155. float production = filteredHolonElements.stream()
  156. .map(HolonElement::getActualEnergy).filter(energy -> energy > 0).reduce(0.0f, Float::sum);
  157. float difference = Math.abs(production - consumption);
  158. energyChart.updatePieSeries("Production", production);
  159. energyChart.updatePieSeries("Consumption", consumption);
  160. energyChart.updatePieSeries("No Data", production + consumption == 0 ? 1 : 0);
  161. differenceEnergyLabelAmount.setText(Format.doubleFixedPlaces(1, difference));
  162. // UPDATE FLEXIBILITIES
  163. int inUse = 0;
  164. int offered = 0;
  165. int onCooldown = 0;
  166. int notOffered = 0;
  167. int unavailable = 0;
  168. List<Flexibility> flexList = filteredHolonElements.stream()
  169. .flatMap(ele -> ele.flexList.stream()).toList();
  170. for (Flexibility flex : flexList) {
  171. switch (flex.getState()) {
  172. case IN_USE -> inUse++;
  173. case NOT_OFFERED -> notOffered++;
  174. case OFFERED -> offered++;
  175. case ON_COOLDOWN -> onCooldown++;
  176. case UNAVAILABLE -> unavailable++;
  177. default -> {
  178. }
  179. }
  180. }
  181. int noFlexibility = (int) filteredHolonElements.stream().filter(ele -> ele.flexList.isEmpty())
  182. .count();
  183. flexibilityChart.updatePieSeries("No flexibility", noFlexibility);
  184. flexibilityChart.updatePieSeries("Offered", offered);
  185. flexibilityChart.updatePieSeries("In use", inUse);
  186. flexibilityChart.updatePieSeries("On cooldown", onCooldown);
  187. flexibilityChart.updatePieSeries("Not offered", notOffered);
  188. flexibilityChart.updatePieSeries("Unavailable", unavailable);
  189. boolean hasFlex = noFlexibility + offered + inUse + onCooldown + notOffered + unavailable > 0;
  190. flexibilityChart.updatePieSeries("No Data", hasFlex ? 0 : 1);
  191. Map<Boolean, Long> activeCounts = filteredHolonElements.stream()
  192. .collect(Collectors.groupingBy(HolonElement::isOn, Collectors.counting()));
  193. // UPDATE ActiveInActive
  194. int activeAmount = Math.toIntExact(activeCounts.getOrDefault(true, 0L));
  195. int inactiveAmounts = Math.toIntExact(activeCounts.getOrDefault(false, 0L));
  196. activeChart.updatePieSeries("Active", activeAmount);
  197. activeChart.updatePieSeries("Inactive", inactiveAmounts);
  198. activeChart.updatePieSeries("No Data", activeAmount + inactiveAmounts == 0 ? 1 : 0);
  199. this.revalidate();
  200. this.repaint();
  201. }
  202. private JPopupMenu createHolonStateSelection() {
  203. JPopupMenu menu = new JPopupMenu();
  204. producerCheckBox.addActionListener(clicked -> updateCharts());
  205. overSuppliedCheckBox.addActionListener(clicked -> updateCharts());
  206. suppliedCheckBox.addActionListener(clicked -> updateCharts());
  207. partiallySuppliedCheckBox.addActionListener(clicked -> updateCharts());
  208. notSuppliedCheckBox.addActionListener(clicked -> updateCharts());
  209. noEnergyCheckBox.addActionListener(clicked -> updateCharts());
  210. menu.add(producerCheckBox);
  211. menu.add(overSuppliedCheckBox);
  212. menu.add(suppliedCheckBox);
  213. menu.add(partiallySuppliedCheckBox);
  214. menu.add(notSuppliedCheckBox);
  215. menu.add(noEnergyCheckBox);
  216. return menu;
  217. }
  218. private JPopupMenu createPrioritySelection() {
  219. JPopupMenu menu = new JPopupMenu();
  220. essentialCheckBox.addActionListener(clicked -> updateCharts());
  221. highCheckBox.addActionListener(clicked -> updateCharts());
  222. mediumBox.addActionListener(clicked -> updateCharts());
  223. lowCheckBox.addActionListener(clicked -> updateCharts());
  224. menu.add(essentialCheckBox);
  225. menu.add(highCheckBox);
  226. menu.add(mediumBox);
  227. menu.add(lowCheckBox);
  228. return menu;
  229. }
  230. private JPopupMenu createActiveSelection() {
  231. JPopupMenu menu = new JPopupMenu();
  232. activeCheckBox.addActionListener(clicked -> updateCharts());
  233. inactiveCheckBox.addActionListener(clicked -> updateCharts());
  234. menu.add(activeCheckBox);
  235. menu.add(inactiveCheckBox);
  236. return menu;
  237. }
  238. private JPopupMenu createFlexibilitySelection() {
  239. JPopupMenu menu = new JPopupMenu();
  240. noFlexibilityCheckBox.addActionListener(clicked -> updateCharts());
  241. offeredCheckBox.addActionListener(clicked -> updateCharts());
  242. notOfferedCheckBox.addActionListener(clicked -> updateCharts());
  243. unavailableCheckBox.addActionListener(clicked -> updateCharts());
  244. inUseCheckBox.addActionListener(clicked -> updateCharts());
  245. onCooldownCheckBox.addActionListener(clicked -> updateCharts());
  246. menu.add(noFlexibilityCheckBox);
  247. menu.add(offeredCheckBox);
  248. menu.add(notOfferedCheckBox);
  249. menu.add(unavailableCheckBox);
  250. menu.add(inUseCheckBox);
  251. menu.add(onCooldownCheckBox);
  252. return menu;
  253. }
  254. private JPanel initMenuButtonPanel(JPopupMenu menu) {
  255. JPanel buttonPanel = new JPanel(new BorderLayout());
  256. MenuButton button = new MenuButton(
  257. new ImageIcon(Import.loadImage(ImagePreference.HolonInformationPanel.Filter, 20, 20)),
  258. menu);
  259. buttonPanel.add(button, BorderLayout.LINE_END);
  260. buttonPanel.setOpaque(false);
  261. button.setPressedIcon(new ImageIcon(
  262. Import.loadImage(ImagePreference.HolonInformationPanel.FilterHovered, 20, 20)));
  263. button.setRolloverIcon(new ImageIcon(
  264. Import.loadImage(ImagePreference.HolonInformationPanel.FilterHovered, 20, 20)));
  265. button.setBorderPainted(false);
  266. button.setBorder(null);
  267. button.setFocusable(false);
  268. button.setMargin(new Insets(0, 0, 0, 0));
  269. button.setContentAreaFilled(false);
  270. return buttonPanel;
  271. }
  272. private boolean stateFilter(HolonObject holonObject) {
  273. return switch (holonObject.getState()) {
  274. case PRODUCER -> producerCheckBox.isSelected();
  275. case OVER_SUPPLIED -> overSuppliedCheckBox.isSelected();
  276. case SUPPLIED -> suppliedCheckBox.isSelected();
  277. case PARTIALLY_SUPPLIED -> partiallySuppliedCheckBox.isSelected();
  278. case NOT_SUPPLIED -> notSuppliedCheckBox.isSelected();
  279. case NO_ENERGY -> noEnergyCheckBox.isSelected();
  280. };
  281. }
  282. private boolean priorityFilter(HolonElement ele) {
  283. return switch (ele.priority) {
  284. case Essential -> essentialCheckBox.isSelected();
  285. case High -> highCheckBox.isSelected();
  286. case Medium -> mediumBox.isSelected();
  287. case Low -> lowCheckBox.isSelected();
  288. };
  289. }
  290. private boolean activeFilter(HolonElement ele) {
  291. return ele.active ? activeCheckBox.isSelected() : inactiveCheckBox.isSelected();
  292. }
  293. private boolean flexibilityFilter(HolonElement ele) {
  294. if (ele.flexList.isEmpty()) {
  295. return noFlexibilityCheckBox.isSelected();
  296. }
  297. Map<Flexibility.FlexState, Long> flexes = ele.flexList.stream()
  298. .collect(Collectors.groupingBy(Flexibility::getState, Collectors.counting()));
  299. return flexes.keySet().stream().anyMatch(flexState -> switch (flexState) {
  300. case IN_USE -> inUseCheckBox.isSelected();
  301. case UNAVAILABLE -> unavailableCheckBox.isSelected();
  302. case OFFERED -> offeredCheckBox.isSelected();
  303. case NOT_OFFERED -> notOfferedCheckBox.isSelected();
  304. case ON_COOLDOWN -> onCooldownCheckBox.isSelected();
  305. });
  306. }
  307. private void initGraphPanel() {
  308. graphPanel.setBackground(ColorPreference.Panel.Background);
  309. XChartPanel<PieChart> panelHolonObject = new XChartPanel<>(supplyChart);
  310. panelHolonObject.setLayout(new BorderLayout());
  311. panelHolonObject.add(initMenuButtonPanel(createHolonStateSelection()), BorderLayout.PAGE_START);
  312. panelHolonObject.setBackground(ColorPreference.Panel.Background);
  313. graphPanel.add(panelHolonObject);
  314. XChartPanel<PieChart> panelPriority = new XChartPanel<>(priorityChart);
  315. panelPriority.setLayout(new BorderLayout());
  316. panelPriority.add(initMenuButtonPanel(createPrioritySelection()), BorderLayout.PAGE_START);
  317. panelPriority.setBackground(ColorPreference.Panel.Background);
  318. graphPanel.add(panelPriority);
  319. XChartPanel<PieChart> panelFlexibility = new XChartPanel<>(flexibilityChart);
  320. panelFlexibility.setLayout(new BorderLayout());
  321. panelFlexibility.add(initMenuButtonPanel(createFlexibilitySelection()),
  322. BorderLayout.PAGE_START);
  323. panelFlexibility.setBackground(ColorPreference.Panel.Background);
  324. graphPanel.add(panelFlexibility);
  325. Component panel = initEnergyChart();
  326. graphPanel.add(panel);
  327. XChartPanel<PieChart> panelActive = new XChartPanel<>(activeChart);
  328. panelActive.setLayout(new BorderLayout());
  329. panelActive.add(initMenuButtonPanel(createActiveSelection()), BorderLayout.PAGE_START);
  330. panelActive.setBackground(ColorPreference.Panel.Background);
  331. graphPanel.add(panelActive);
  332. graphPanel.setBorder(BorderFactory.createLineBorder(Color.lightGray));
  333. }
  334. private JLayeredPane initEnergyChart() {
  335. JLayeredPane panel = new JLayeredPane();
  336. JPanel panelMiddle = new JPanel(new GridBagLayout());
  337. XChartPanel<PieChart> panelEnergy = new XChartPanel<>(energyChart);
  338. panelEnergy.setBackground(ColorPreference.Panel.Background);
  339. GridBagConstraints c = new GridBagConstraints();
  340. c.gridx = 0;
  341. c.gridy = 0;
  342. c.insets = new Insets(15, 0, 0, 0); // top padding
  343. JLabel difference = new JLabel("Difference:");
  344. difference.setHorizontalAlignment(JLabel.CENTER);
  345. difference.setAlignmentX(Component.CENTER_ALIGNMENT);
  346. difference.setForeground(ColorPreference.Panel.Title);
  347. difference.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 10));
  348. panelMiddle.add(difference, c);
  349. differenceEnergyLabelAmount.setHorizontalAlignment(JLabel.CENTER);
  350. differenceEnergyLabelAmount.setForeground(Color.red);
  351. differenceEnergyLabelAmount.setAlignmentX(Component.CENTER_ALIGNMENT);
  352. differenceEnergyLabelAmount.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 12));
  353. c.insets = new Insets(0, 0, 0, 0);
  354. c.gridy = 1;
  355. panelMiddle.add(differenceEnergyLabelAmount, c);
  356. panel.setLayout(new OverlayLayout(panel));
  357. panelEnergy.setOpaque(false);
  358. panelMiddle.setOpaque(false);
  359. panel.add(panelMiddle, Integer.valueOf(0));
  360. panel.add(panelEnergy, Integer.valueOf(1));
  361. return panel;
  362. }
  363. public void setDefaultPieChartSettings(PieChart chart) {
  364. PieStyler styler = chart.getStyler();
  365. styler.setChartTitleVisible(true);
  366. styler.setDefaultSeriesRenderStyle(PieSeriesRenderStyle.Donut);
  367. styler.setLabelsFont(new java.awt.Font("Arial", java.awt.Font.PLAIN, 14));
  368. styler.setLabelType(LabelType.Percentage);
  369. styler.setLabelsFontColor(Color.black);
  370. styler.setLabelsFontColorAutomaticEnabled(false);
  371. styler.setLabelsDistance(0.8);
  372. styler.setChartFontColor(ColorPreference.Panel.Title);
  373. styler.setToolTipsEnabled(true);
  374. styler.setPlotContentSize(0.9);
  375. styler.setPlotBackgroundColor(ColorPreference.Panel.Transparent);
  376. styler.setPlotBorderColor(ColorPreference.Panel.Transparent);
  377. styler.setLegendVisible(false);
  378. styler.setChartBackgroundColor(ColorPreference.Panel.Transparent);
  379. }
  380. public PieChart createSupplyStateChart() {
  381. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight)
  382. .title("HolonObjects").build();
  383. setDefaultPieChartSettings(chart);
  384. chart.getStyler().setSeriesColors(supplyStateColors);
  385. // Series
  386. chart.addSeries("Producer", 0);
  387. chart.addSeries("Over supplied", 0);
  388. chart.addSeries("Supplied", 0);
  389. chart.addSeries("Partial supplied", 0);
  390. chart.addSeries("Not supplied", 0);
  391. chart.addSeries("No energy", 0);
  392. chart.addSeries("No Data", 0);
  393. return chart;
  394. }
  395. public PieChart createPriorityChart() {
  396. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight)
  397. .title("Priorities").build();
  398. setDefaultPieChartSettings(chart);
  399. // Customize Chart
  400. chart.getStyler().setSeriesColors(priorityColors);
  401. // Series
  402. chart.addSeries("Essential", 0);
  403. chart.addSeries("High", 0);
  404. chart.addSeries("Medium", 0);
  405. chart.addSeries("Low", 0);
  406. chart.addSeries("No Data", 0);
  407. return chart;
  408. }
  409. public PieChart createFlexibilityChart() {
  410. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight)
  411. .title("Flexibilities").build();
  412. setDefaultPieChartSettings(chart);
  413. // Customize Chart
  414. chart.getStyler().setSeriesColors(flexibilityColors);
  415. // Series
  416. chart.addSeries("Offered", 0);
  417. chart.addSeries("In use", 0);
  418. chart.addSeries("On cooldown", 0);
  419. chart.addSeries("Not offered", 0);
  420. chart.addSeries("Unavailable", 0);
  421. chart.addSeries("No flexibility", 0);
  422. chart.addSeries("No Data", 0);
  423. return chart;
  424. }
  425. public PieChart createProductionChart() {
  426. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight)
  427. .title("Production vs. Consumption").build();
  428. setDefaultPieChartSettings(chart);
  429. // Customize Chart
  430. // Customize Chart
  431. chart.getStyler().setSeriesColors(productionColors);
  432. // Series
  433. chart.addSeries("Production", 0);
  434. chart.addSeries("Consumption", 0);
  435. chart.addSeries("No Data", 0);
  436. return chart;
  437. }
  438. public PieChart createActiveChart() {
  439. PieChart chart = new PieChartBuilder().width(defaultWidth).height(defaultHeight).title("Active")
  440. .build();
  441. setDefaultPieChartSettings(chart);
  442. // Customize Chart
  443. // Customize Chart
  444. chart.getStyler().setSeriesColors(activeColors);
  445. // Series
  446. chart.addSeries("Active", 0);
  447. chart.addSeries("Inactive", 0);
  448. chart.addSeries("No Data", 0);
  449. return chart;
  450. }
  451. /**
  452. * A MenuButton that shows a popupmenu on click.
  453. */
  454. public static class MenuButton extends JToggleButton {
  455. JPopupMenu popup;
  456. public MenuButton(Icon icon, JPopupMenu menu) {
  457. super(icon);
  458. this.popup = menu;
  459. addActionListener(clicked -> {
  460. if (MenuButton.this.isSelected()) {
  461. popup.show(MenuButton.this, 0, MenuButton.this.getBounds().height);
  462. } else {
  463. popup.setVisible(false);
  464. }
  465. });
  466. popup.addPopupMenuListener(new PopupMenuListener() {
  467. @Override
  468. public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
  469. }
  470. @Override
  471. public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
  472. MenuButton.this.setSelected(false);
  473. }
  474. @Override
  475. public void popupMenuCanceled(PopupMenuEvent e) {
  476. }
  477. });
  478. }
  479. }
  480. /**
  481. * A temporary groupNode that don't interfere with ownership like a normal GroupNode.
  482. */
  483. private static class TempGroupNode extends GroupNode {
  484. public TempGroupNode() {
  485. super("temp");
  486. }
  487. @Override
  488. public void add(AbstractCanvasObject object) {
  489. if (object instanceof HolonObject hObject) {
  490. objectList.add(hObject);
  491. } else if (object instanceof HolonSwitch hSwitch) {
  492. switchList.add(hSwitch);
  493. } else if (object instanceof Node node) {
  494. nodeList.add(node);
  495. } else if (object instanceof GroupNode groupNode) {
  496. groupNodeList.add(groupNode);
  497. }
  498. }
  499. @Override
  500. public void remove(AbstractCanvasObject object) {
  501. if (object instanceof HolonObject hObject) {
  502. objectList.remove(hObject);
  503. } else if (object instanceof HolonSwitch hSwitch) {
  504. switchList.remove(hSwitch);
  505. } else if (object instanceof Node node) {
  506. nodeList.remove(node);
  507. } else if (object instanceof GroupNode groupNode) {
  508. groupNodeList.remove(groupNode);
  509. }
  510. }
  511. }
  512. }