Inspector.java 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package holeg.ui.view.inspector;
  2. import holeg.interfaces.LocalMode;
  3. import holeg.interfaces.TimelineDependent;
  4. import holeg.model.HolonElement;
  5. import holeg.model.HolonSwitch;
  6. import holeg.preferences.ColorPreference;
  7. import holeg.preferences.ImagePreference;
  8. import holeg.ui.controller.Control;
  9. import holeg.ui.model.GuiSettings;
  10. import holeg.ui.view.image.Import;
  11. import holeg.utility.listener.ResizeListener;
  12. import holeg.utility.math.Maths;
  13. import holeg.utility.math.decimal.Format;
  14. import java.awt.BorderLayout;
  15. import java.awt.Color;
  16. import java.awt.Component;
  17. import java.awt.Dimension;
  18. import java.awt.event.ItemEvent;
  19. import java.util.Set;
  20. import java.util.logging.Logger;
  21. import java.util.stream.Collectors;
  22. import javax.swing.Box;
  23. import javax.swing.GrayFilter;
  24. import javax.swing.ImageIcon;
  25. import javax.swing.JButton;
  26. import javax.swing.JComboBox;
  27. import javax.swing.JLabel;
  28. import javax.swing.JOptionPane;
  29. import javax.swing.JPanel;
  30. import javax.swing.JScrollPane;
  31. import javax.swing.JSplitPane;
  32. import javax.swing.JToolBar;
  33. public class Inspector extends JSplitPane {
  34. private static final Logger log = Logger.getLogger(Inspector.class.getName());
  35. private final UnitGraph unitGraph;
  36. private final InspectorTable table;
  37. private final JPanel scrollGraph = new JPanel();
  38. private final JPanel graphLabel = new JPanel();
  39. private final JLabel maxGraph = new JLabel("100%");
  40. private final JLabel medGraph = new JLabel("50%");
  41. private final JLabel minGraph = new JLabel("0%");
  42. private final JPanel globalCurveLabel = new JPanel();
  43. private final JLabel minEnergy = new JLabel("0.0");
  44. private final JLabel maxEnergy = new JLabel("0.0");
  45. private final JLabel zeroEnergy = new JLabel("0.0");
  46. private final JToolBar toolBarGraph = new JToolBar();
  47. private final ImageIcon localPeriodButtonImageEnabled = new ImageIcon(
  48. Import.loadImage(ImagePreference.Button.Inspector.Graph));
  49. private final ImageIcon localPeriodButtonImageDisabled = new ImageIcon(
  50. GrayFilter.createDisabledImage(Import.loadImage(ImagePreference.Button.Inspector.Graph)));
  51. private String[] comboContext = {"", "5", "10", "20", "100", "1000"};
  52. private JComboBox<String> localPeriodInput = new JComboBox<String>(comboContext);
  53. private JButton resetButton = new JButton("",
  54. new ImageIcon(Import.loadImage(ImagePreference.Button.Inspector.Reset)));
  55. private JButton localPeriodButton = new JButton("", localPeriodButtonImageEnabled);
  56. public Inspector(Control control) {
  57. table = new InspectorTable(control);
  58. unitGraph = new UnitGraph(control);
  59. table.OnElementSelectionChanged.addListener(this::updateUnitGraph);
  60. initUI();
  61. control.OnSelectionChanged.addListener(this::updateGlobalCurve);
  62. }
  63. private void initUI() {
  64. this.setOrientation(JSplitPane.VERTICAL_SPLIT);
  65. JScrollPane scrollPane = new JScrollPane(table);
  66. scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  67. this.setTopComponent(scrollPane);
  68. this.setBottomComponent(scrollGraph);
  69. this.setDividerLocation(550);
  70. scrollGraph.setLayout(new BorderLayout());
  71. scrollGraph.add(unitGraph, BorderLayout.CENTER);
  72. // Set up of the Properties section
  73. graphLabel.setLayout(new BorderLayout(0, 10));
  74. graphLabel.add(maxGraph, BorderLayout.NORTH);
  75. graphLabel.add(medGraph, BorderLayout.CENTER);
  76. graphLabel.add(minGraph, BorderLayout.SOUTH);
  77. globalCurveLabel.setLayout(null);
  78. globalCurveLabel.setMinimumSize(new Dimension(20, 0));
  79. globalCurveLabel.setPreferredSize(new Dimension(20, 0));
  80. maxEnergy.setForeground(Color.red);
  81. minEnergy.setForeground(Color.red);
  82. zeroEnergy.setForeground(ColorPreference.UnitGraph.ZeroLineColor);
  83. globalCurveLabel.add(maxEnergy);
  84. globalCurveLabel.add(zeroEnergy);
  85. globalCurveLabel.add(minEnergy);
  86. this.globalCurveLabel.addComponentListener((ResizeListener) resize -> updateGlobalCurve());
  87. toolBarGraph.setFloatable(false);
  88. toolBarGraph.setAlignmentY(Component.RIGHT_ALIGNMENT);
  89. localPeriodButton.setToolTipText("Toggle Local/Global Mode");
  90. toolBarGraph.add(localPeriodButton);
  91. // ComboBox
  92. localPeriodInput.setEditable(true);
  93. localPeriodInput.setVisible(false);
  94. localPeriodInput.setMaximumSize(new Dimension(20, 23));
  95. localPeriodInput.addItemListener(aListener -> {
  96. if (aListener.getStateChange() == ItemEvent.DESELECTED) {
  97. validateInput(localPeriodInput.getEditor().getItem().toString(), true);
  98. }
  99. });
  100. toolBarGraph.add(localPeriodInput);
  101. // localPeriodButtonFunction
  102. localPeriodButton.addActionListener(actionEvent -> {
  103. boolean newState = !localPeriodInput.isVisible();
  104. changeLocalPeriodButtonAppearance(newState);
  105. log.info("LocalPeriodButton");
  106. });
  107. toolBarGraph.add(Box.createHorizontalGlue());
  108. resetButton.setToolTipText("Reset");
  109. resetButton.addActionListener(actionEvent -> unitGraph.reset());
  110. toolBarGraph.add(resetButton);
  111. scrollGraph.add(graphLabel, BorderLayout.WEST);
  112. scrollGraph.add(globalCurveLabel, BorderLayout.EAST);
  113. scrollGraph.add(toolBarGraph, BorderLayout.NORTH);
  114. }
  115. /**
  116. * Validate the LocalMode Input and when its valid save on the Element.
  117. *
  118. * @param text the inputText to validate.
  119. * @param bShowMessage when true, open a MessageDialog when text invalid.
  120. */
  121. private void validateInput(String text, boolean bShowMessage) {
  122. int localPeriodInputValue;
  123. try {
  124. localPeriodInputValue = Integer.parseInt(text);
  125. } catch (NumberFormatException e) {
  126. if (bShowMessage) {
  127. JOptionPane.showMessageDialog(null,
  128. '"' + text + '"' + " is not a valid Input. \n Use whole numbers.");
  129. }
  130. return;
  131. }
  132. LocalMode.Period period = new LocalMode.Period(7);
  133. period.setInterval(localPeriodInputValue);
  134. unitGraph.setPeriod(period);
  135. }
  136. /**
  137. * This Method updates the UnitGraph, saves the old LocalModeState and load the new
  138. * LocalModeState.
  139. *
  140. * @param elements The new Element to load the UnitGraph
  141. */
  142. private void updateUnitGraph(Set<HolonElement> elements) {
  143. // SaveOld LocalMode State.
  144. if (localPeriodInput.isVisible()) {
  145. // Save Old State
  146. validateInput(localPeriodInput.getEditor().getItem().toString(), false);
  147. }
  148. // Update UnitGraph
  149. unitGraph.clearSeries();
  150. for (TimelineDependent element : elements) {
  151. unitGraph.addNewSeries(element);
  152. }
  153. if (elements.isEmpty()) {
  154. GuiSettings.getSelectedObjects().stream().filter(obj -> obj instanceof HolonSwitch)
  155. .forEach(obj -> unitGraph.addNewSeries((HolonSwitch) obj));
  156. }
  157. // if (elements.isEmpty()) {
  158. // this.setDividerLocation(1.0);
  159. // }
  160. // Load LocalMode State.
  161. changeLocalPeriodButtonAppearance(unitGraph.isUsingLocalPeriod());
  162. localPeriodInput.getEditor()
  163. .setItem(
  164. unitGraph.isLocalPeriedDifferentInSeries() ? "-" : unitGraph.getFirstLocalPeriod());
  165. }
  166. private void updateGlobalCurve() {
  167. Set<HolonElement> elements = InspectorTable.extractElements(GuiSettings.getSelectedObjects())
  168. .collect(Collectors.toSet());
  169. unitGraph.setGlobalCurve(elements);
  170. double maxEnergy = elements.stream().map(HolonElement::getEnergy).filter(energy -> energy > 0)
  171. .reduce(0.0f,
  172. Float::sum);
  173. double minEnergy = elements.stream().map(HolonElement::getEnergy).filter(energy -> energy < 0)
  174. .reduce(0.0f,
  175. Float::sum);
  176. double percentage = Maths.invLerp(maxEnergy, minEnergy, 0.0);
  177. int widgetHeight = this.globalCurveLabel.getHeight();
  178. int textMiddle = this.zeroEnergy.getPreferredSize().height / 4;
  179. int zeroYPos = (int) (widgetHeight * percentage) - 5;
  180. this.minEnergy.setText(Format.doubleTwoPlaces(minEnergy));
  181. this.maxEnergy.setText(Format.doubleTwoPlaces(maxEnergy));
  182. this.maxEnergy.setBounds(0, 0, this.maxEnergy.getPreferredSize().width,
  183. this.maxEnergy.getPreferredSize().height);
  184. this.minEnergy.setBounds(0, widgetHeight - this.minEnergy.getPreferredSize().height,
  185. this.minEnergy.getPreferredSize().width,
  186. this.minEnergy.getPreferredSize().height);
  187. this.zeroEnergy.setBounds(0, zeroYPos, this.zeroEnergy.getPreferredSize().width,
  188. this.zeroEnergy.getPreferredSize().height);
  189. this.globalCurveLabel.setPreferredSize(new Dimension(
  190. Math.max(this.zeroEnergy.getPreferredSize().width,
  191. Math.max(this.maxEnergy.getPreferredSize().width,
  192. this.minEnergy.getPreferredSize().width)),
  193. 0));
  194. }
  195. /**
  196. * Displayed the actual LocalModeState.
  197. *
  198. * @param enabled
  199. */
  200. private void changeLocalPeriodButtonAppearance(boolean enabled) {
  201. localPeriodInput.setVisible(enabled);
  202. localPeriodButton.setIcon(
  203. enabled ? localPeriodButtonImageEnabled : localPeriodButtonImageDisabled);
  204. }
  205. }