Inspector.java 8.9 KB

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