No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SolutionPanel.java 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. package org.insa.graphics;
  2. import java.awt.Color;
  3. import java.awt.Component;
  4. import java.awt.event.ActionEvent;
  5. import java.awt.event.ActionListener;
  6. import java.lang.reflect.InvocationTargetException;
  7. import java.lang.reflect.Method;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. import javax.swing.BorderFactory;
  11. import javax.swing.Box;
  12. import javax.swing.BoxLayout;
  13. import javax.swing.JButton;
  14. import javax.swing.JComboBox;
  15. import javax.swing.JLabel;
  16. import javax.swing.JPanel;
  17. import javax.swing.border.CompoundBorder;
  18. import javax.swing.border.EmptyBorder;
  19. import org.insa.algo.AbstractInputData;
  20. import org.insa.algo.AbstractSolution;
  21. import org.insa.graph.Graph;
  22. import org.insa.graph.Path;
  23. import org.insa.graphics.drawing.Drawing;
  24. import org.insa.graphics.drawing.overlays.PathOverlay;
  25. public class SolutionPanel extends JPanel implements DrawingChangeListener, GraphChangeListener {
  26. /**
  27. *
  28. */
  29. private static final long serialVersionUID = 1L;
  30. private class SolutionBundle {
  31. // Solution
  32. private final AbstractSolution solution;
  33. // Path Overlay (not final due to redraw)
  34. private List<PathOverlay> overlays = new ArrayList<>();
  35. /**
  36. * Create a new bundle with the given solution and create a new overlay
  37. * corresponding to the solution (if the solution is feasible).
  38. *
  39. * @param solution Solution for this bundle, must not be null.
  40. *
  41. */
  42. public SolutionBundle(AbstractSolution solution, boolean createOverlays) {
  43. this.solution = solution;
  44. if (createOverlays) {
  45. this.overlays = createOverlaysFromSolution();
  46. }
  47. }
  48. /**
  49. * @return Solution associated with this bundle.
  50. */
  51. public AbstractSolution getSolution() {
  52. return this.solution;
  53. }
  54. /**
  55. * @return Data assocaited with this bundle.
  56. */
  57. public AbstractInputData getData() {
  58. return this.solution.getInputData();
  59. }
  60. /**
  61. * @return Overlays associated with this bundle, or null.
  62. */
  63. public List<PathOverlay> getOverlays() {
  64. return this.overlays;
  65. }
  66. /**
  67. * @return true if this bundle has overlays.
  68. */
  69. public boolean hasOverlays() {
  70. return !this.overlays.isEmpty();
  71. }
  72. /**
  73. * Re-draw the current overlay (if any) on the new drawing.
  74. *
  75. */
  76. public void updateOverlays() {
  77. if (this.overlays.isEmpty()) {
  78. return; // This bundle has no overlay.
  79. }
  80. List<PathOverlay> oldOverlays = this.overlays;
  81. this.overlays = createOverlaysFromSolution();
  82. for (int i = 0; i < oldOverlays.size(); ++i) {
  83. oldOverlays.get(i).delete();
  84. }
  85. }
  86. private List<PathOverlay> createOverlaysFromSolution() {
  87. List<PathOverlay> overlays = new ArrayList<>();
  88. if (solution.isFeasible()) {
  89. Method[] methods = this.solution.getClass().getDeclaredMethods();
  90. for (Method method: methods) {
  91. if (method.getReturnType().equals(Path.class)
  92. && method.getParameterCount() == 0) {
  93. try {
  94. Path path = (Path) method.invoke(this.solution);
  95. overlays.add(drawing.drawPath(path));
  96. }
  97. catch (IllegalAccessException | IllegalArgumentException
  98. | InvocationTargetException e) {
  99. // This has been check before, so should never happen...
  100. e.printStackTrace();
  101. }
  102. }
  103. }
  104. }
  105. return overlays;
  106. }
  107. /*
  108. * (non-Javadoc)
  109. * @see java.lang.Object#toString()
  110. */
  111. public String toString() {
  112. return getData().toString();
  113. }
  114. }
  115. // Solution
  116. private Drawing drawing;
  117. // Solution selector
  118. private final JComboBox<SolutionBundle> solutionSelect;
  119. private final JLabel informationPanel;
  120. // Current bundle
  121. private SolutionBundle currentBundle = null;
  122. public SolutionPanel(Component parent) {
  123. super();
  124. setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
  125. setBorder(new CompoundBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.LIGHT_GRAY),
  126. new EmptyBorder(10, 0, 10, 0)));
  127. solutionSelect = new JComboBox<>();
  128. solutionSelect.setBackground(Color.WHITE);
  129. solutionSelect.setAlignmentX(Component.LEFT_ALIGNMENT);
  130. add(solutionSelect);
  131. informationPanel = new JLabel();
  132. informationPanel.setOpaque(true);
  133. informationPanel.setFocusable(false);
  134. // informationPanel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
  135. informationPanel.setHorizontalAlignment(JLabel.LEFT);
  136. add(Box.createVerticalStrut(8));
  137. add(informationPanel);
  138. JButton clearButton = new JButton("Hide");
  139. clearButton.addActionListener(new ActionListener() {
  140. @Override
  141. public void actionPerformed(ActionEvent e) {
  142. for (PathOverlay overlay: currentBundle.getOverlays()) {
  143. if (overlay.isVisible()) {
  144. overlay.setVisible(false);
  145. clearButton.setText("Show");
  146. }
  147. else {
  148. overlay.setVisible(true);
  149. clearButton.setText("Hide");
  150. }
  151. }
  152. }
  153. });
  154. JPanel buttonPanel = new JPanel();
  155. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
  156. buttonPanel.add(Box.createHorizontalGlue());
  157. buttonPanel.add(clearButton);
  158. buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
  159. add(Box.createVerticalStrut(4));
  160. add(buttonPanel);
  161. solutionSelect.addActionListener(new ActionListener() {
  162. public void actionPerformed(ActionEvent e) {
  163. if (currentBundle != null) {
  164. for (PathOverlay overlay: currentBundle.getOverlays()) {
  165. overlay.setVisible(false);
  166. }
  167. }
  168. SolutionBundle bundle = (SolutionBundle) solutionSelect.getSelectedItem();
  169. if (bundle != null) {
  170. updateInformationLabel(bundle);
  171. buttonPanel
  172. .setVisible(bundle.getSolution().isFeasible() && bundle.hasOverlays());
  173. clearButton.setText(bundle.getSolution().isFeasible() ? "Hide" : "Show");
  174. for (PathOverlay overlay: bundle.getOverlays()) {
  175. overlay.setVisible(true);
  176. }
  177. }
  178. currentBundle = bundle;
  179. }
  180. });
  181. }
  182. public void addSolution(AbstractSolution solution) {
  183. addSolution(solution, true);
  184. }
  185. /**
  186. * Add the given solution to the panel.
  187. *
  188. * @param solution the solution to add to the panel
  189. * @param createOverlays Whether or not overlay should be created for this
  190. * solution.
  191. */
  192. public void addSolution(AbstractSolution solution, boolean createOverlays) {
  193. SolutionBundle bundle = new SolutionBundle(solution, createOverlays);
  194. solutionSelect.addItem(bundle);
  195. solutionSelect.setSelectedItem(bundle);
  196. }
  197. protected void updateInformationLabel(SolutionBundle bundle) {
  198. informationPanel.setText(bundle.getSolution().toString());
  199. revalidate();
  200. repaint();
  201. }
  202. @Override
  203. public void setEnabled(boolean enabled) {
  204. super.setEnabled(enabled);
  205. solutionSelect.setEnabled(enabled);
  206. if (enabled) {
  207. // Trigger event
  208. solutionSelect.setSelectedItem(currentBundle);
  209. }
  210. else {
  211. SolutionBundle bundle = (SolutionBundle) this.solutionSelect.getSelectedItem();
  212. if (bundle != null) {
  213. for (PathOverlay overlay: bundle.getOverlays()) {
  214. overlay.setVisible(false);
  215. }
  216. }
  217. }
  218. }
  219. @Override
  220. public void newGraphLoaded(Graph graph) {
  221. for (int i = 0; i < this.solutionSelect.getItemCount(); ++i) {
  222. for (PathOverlay overlay: this.solutionSelect.getItemAt(i).getOverlays()) {
  223. overlay.delete();
  224. }
  225. }
  226. this.solutionSelect.removeAllItems();
  227. this.currentBundle = null;
  228. this.setVisible(false);
  229. }
  230. @Override
  231. public void onDrawingLoaded(Drawing oldDrawing, Drawing newDrawing) {
  232. if (newDrawing != drawing) {
  233. drawing = newDrawing;
  234. }
  235. }
  236. @Override
  237. public void onRedrawRequest() {
  238. for (int i = 0; i < this.solutionSelect.getItemCount(); ++i) {
  239. this.solutionSelect.getItemAt(i).updateOverlays();
  240. }
  241. }
  242. }