Inspector.java 8.2 KB

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