Make solution panel a bit more generic using reflections.
This commit is contained in:
		
							parent
							
								
									6d8c2462ab
								
							
						
					
					
						commit
						f22c1c93fa
					
				
					 5 changed files with 209 additions and 134 deletions
				
			
		|  | @ -1,22 +1,100 @@ | |||
| package org.insa.algo; | ||||
| 
 | ||||
| import org.insa.graph.Arc; | ||||
| import org.insa.graph.Graph; | ||||
| 
 | ||||
| public abstract class AbstractInputData { | ||||
| 
 | ||||
|     protected Graph graph; | ||||
|     public enum Mode { | ||||
|         TIME, LENGTH | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new AbstractInputData instance with the given graph. | ||||
|      *  | ||||
|      * | ||||
|      */ | ||||
|     public interface ArcFilter { | ||||
| 
 | ||||
|         /** | ||||
|          * @param arc | ||||
|          *  | ||||
|          * @return true if the given arc is allowed. | ||||
|          */ | ||||
|         public boolean isAllowed(Arc arc); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     // Graph | ||||
|     protected Graph graph; | ||||
| 
 | ||||
|     // Mode for the computation of the costs. | ||||
|     private final AbstractInputData.Mode mode; | ||||
| 
 | ||||
|     // Arc filter. | ||||
|     private final AbstractInputData.ArcFilter arcFilter; | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new AbstractInputData instance for the given graph, mode and filter. | ||||
|      *  | ||||
|      * @param graph | ||||
|      */ | ||||
|     protected AbstractInputData(Graph graph) { | ||||
|     protected AbstractInputData(Graph graph, Mode mode, ArcFilter arcFilter) { | ||||
|         this.graph = graph; | ||||
|         this.mode = mode; | ||||
|         this.arcFilter = arcFilter; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new AbstractInputData instance for the given graph and mode, with no | ||||
|      * filtering on the arc. | ||||
|      *  | ||||
|      * @param graph | ||||
|      * @param mode | ||||
|      */ | ||||
|     protected AbstractInputData(Graph graph, Mode mode) { | ||||
|         this(graph, mode, new AbstractInputData.ArcFilter() { | ||||
|             @Override | ||||
|             public boolean isAllowed(Arc arc) { | ||||
|                 return true; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new AbstractInputData instance for the given graph, with default | ||||
|      * mode (LENGHT), with no filtering on the arc. | ||||
|      *  | ||||
|      * @param graph | ||||
|      * @param mode | ||||
|      */ | ||||
|     protected AbstractInputData(Graph graph) { | ||||
|         this(graph, Mode.LENGTH, new AbstractInputData.ArcFilter() { | ||||
|             @Override | ||||
|             public boolean isAllowed(Arc arc) { | ||||
|                 return true; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Graph associated with this input. | ||||
|      */ | ||||
|     public Graph getGraph() { | ||||
|         return graph; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Mode of the algorithm (time or length). | ||||
|      */ | ||||
|     public Mode getMode() { | ||||
|         return mode; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return true if the given arc is allowed. | ||||
|      */ | ||||
|     public boolean isAllowed(Arc arc) { | ||||
|         return this.arcFilter.isAllowed(arc); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -5,12 +5,12 @@ import org.insa.graph.Graph; | |||
| 
 | ||||
| public class StronglyConnectedComponentsData extends AbstractInputData { | ||||
| 
 | ||||
| 	/** | ||||
| 	 *  | ||||
| 	 * @param graph | ||||
| 	 */ | ||||
| 	public StronglyConnectedComponentsData(Graph graph) { | ||||
| 		super(graph); | ||||
| 	} | ||||
| 	 | ||||
|     /** | ||||
|      *  | ||||
|      * @param graph | ||||
|      */ | ||||
|     public StronglyConnectedComponentsData(Graph graph) { | ||||
|         super(graph); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -25,16 +25,16 @@ import javax.swing.JRadioButton; | |||
| import javax.swing.border.EmptyBorder; | ||||
| 
 | ||||
| import org.insa.algo.AbstractAlgorithm; | ||||
| import org.insa.algo.AbstractInputData; | ||||
| import org.insa.algo.AbstractInputData.ArcFilter; | ||||
| import org.insa.algo.AbstractInputData.Mode; | ||||
| import org.insa.algo.AlgorithmFactory; | ||||
| import org.insa.algo.shortestpath.ShortestPathAlgorithm; | ||||
| import org.insa.algo.shortestpath.ShortestPathData.ArcFilter; | ||||
| import org.insa.algo.shortestpath.ShortestPathData.Mode; | ||||
| import org.insa.graph.Arc; | ||||
| import org.insa.graph.Node; | ||||
| import org.insa.graph.RoadInformation.AccessMode; | ||||
| import org.insa.graphics.NodesInputPanel.InputChangedEvent; | ||||
| 
 | ||||
| public class ShortestPathPanel extends JPanel { | ||||
| public class AlgorithmPanel extends JPanel { | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|  | @ -53,17 +53,17 @@ public class ShortestPathPanel extends JPanel { | |||
|         protected static final int START_EVENT_ID = 0x1; | ||||
| 
 | ||||
|         private final List<Node> nodes; | ||||
|         private final Mode mode; | ||||
|         private final AbstractInputData.Mode mode; | ||||
|         private final Class<? extends AbstractAlgorithm<?>> algoClass; | ||||
| 
 | ||||
|         private final ArcFilter arcFilter; | ||||
|         private final AbstractInputData.ArcFilter arcFilter; | ||||
| 
 | ||||
|         private final boolean graphicVisualization; | ||||
|         private final boolean textualVisualization; | ||||
| 
 | ||||
|         public StartActionEvent(Class<? extends AbstractAlgorithm<?>> algoClass, List<Node> nodes, Mode mode, | ||||
|                 ArcFilter arcFilter, boolean graphicVisualization, boolean textualVisualization) { | ||||
|             super(ShortestPathPanel.this, START_EVENT_ID, START_EVENT_COMMAND); | ||||
|         public StartActionEvent(Class<? extends AbstractAlgorithm<?>> algoClass, List<Node> nodes, AbstractInputData.Mode mode, | ||||
|                 AbstractInputData.ArcFilter arcFilter, boolean graphicVisualization, boolean textualVisualization) { | ||||
|             super(AlgorithmPanel.this, START_EVENT_ID, START_EVENT_COMMAND); | ||||
|             this.nodes = nodes; | ||||
|             this.mode = mode; | ||||
|             this.algoClass = algoClass; | ||||
|  | @ -82,14 +82,14 @@ public class ShortestPathPanel extends JPanel { | |||
|         /** | ||||
|          * @return Mode associated with this event. | ||||
|          */ | ||||
|         public Mode getMode() { | ||||
|         public AbstractInputData.Mode getMode() { | ||||
|             return this.mode; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Arc filter associated with this event. | ||||
|          */ | ||||
|         public ArcFilter getArcFilter() { | ||||
|         public AbstractInputData.ArcFilter getArcFilter() { | ||||
|             return this.arcFilter; | ||||
|         } | ||||
| 
 | ||||
|  | @ -120,7 +120,7 @@ public class ShortestPathPanel extends JPanel { | |||
|     protected NodesInputPanel nodesInputPanel; | ||||
| 
 | ||||
|     // Solution | ||||
|     protected ShortestPathSolutionPanel solutionPanel; | ||||
|     protected SolutionPanel solutionPanel; | ||||
| 
 | ||||
|     // Component that can be enabled/disabled. | ||||
|     private ArrayList<JComponent> components = new ArrayList<>(); | ||||
|  | @ -132,7 +132,7 @@ public class ShortestPathPanel extends JPanel { | |||
| 
 | ||||
|     /** | ||||
|      */ | ||||
|     public ShortestPathPanel(Component parent) { | ||||
|     public AlgorithmPanel(Component parent, Class<? extends AbstractAlgorithm<?>> baseAlgorithm) { | ||||
|         super(); | ||||
|         setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); | ||||
| 
 | ||||
|  | @ -152,7 +152,7 @@ public class ShortestPathPanel extends JPanel { | |||
| 
 | ||||
|         // Add algorithm selection | ||||
|         JComboBox<String> algoSelect = new JComboBox<>( | ||||
|                 AlgorithmFactory.getAlgorithmNames(ShortestPathAlgorithm.class).toArray(new String[0])); | ||||
|                 AlgorithmFactory.getAlgorithmNames(baseAlgorithm).toArray(new String[0])); | ||||
|         algoSelect.setBackground(Color.WHITE); | ||||
|         algoSelect.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||
|         add(algoSelect); | ||||
|  | @ -168,7 +168,7 @@ public class ShortestPathPanel extends JPanel { | |||
|         add(this.nodesInputPanel); | ||||
|         components.add(this.nodesInputPanel); | ||||
| 
 | ||||
|         JComboBox<ArcFilter> arcFilterSelect = new JComboBox<>(new ArcFilter[] { new ArcFilter() { | ||||
|         JComboBox<AbstractInputData.ArcFilter> arcFilterSelect = new JComboBox<>(new AbstractInputData.ArcFilter[] { new AbstractInputData.ArcFilter() { | ||||
|             @Override | ||||
|             public boolean isAllowed(Arc arc) { | ||||
|                 return true; | ||||
|  | @ -178,7 +178,7 @@ public class ShortestPathPanel extends JPanel { | |||
|             public String toString() { | ||||
|                 return "All arcs are allowed"; | ||||
|             } | ||||
|         }, new ArcFilter() { | ||||
|         }, new AbstractInputData.ArcFilter() { | ||||
|             @Override | ||||
|             public boolean isAllowed(Arc arc) { | ||||
|                 return arc.getRoadInformation().getAccessRestrictions().isAllowedFor(AccessMode.MOTORCAR) | ||||
|  | @ -250,7 +250,7 @@ public class ShortestPathPanel extends JPanel { | |||
| 
 | ||||
|         add(modeAndObserverPanel); | ||||
| 
 | ||||
|         solutionPanel = new ShortestPathSolutionPanel(parent); | ||||
|         solutionPanel = new SolutionPanel(parent); | ||||
|         solutionPanel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||
|         solutionPanel.setVisible(false); | ||||
|         add(Box.createVerticalStrut(10)); | ||||
|  | @ -265,13 +265,12 @@ public class ShortestPathPanel extends JPanel { | |||
|         startAlgoButton.addActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 Mode mode = lengthModeButton.isSelected() ? Mode.LENGTH : Mode.TIME; | ||||
|                 AbstractInputData.Mode mode = lengthModeButton.isSelected() ? AbstractInputData.Mode.LENGTH : AbstractInputData.Mode.TIME; | ||||
| 
 | ||||
|                 for (ActionListener lis: startActionListeners) { | ||||
|                     lis.actionPerformed(new StartActionEvent( | ||||
|                             AlgorithmFactory.getAlgorithmClass(ShortestPathAlgorithm.class, | ||||
|                                     (String) algoSelect.getSelectedItem()), | ||||
|                             nodesInputPanel.getNodeForInputs(), mode, (ArcFilter) arcFilterSelect.getSelectedItem(), | ||||
|                             AlgorithmFactory.getAlgorithmClass(baseAlgorithm, (String) algoSelect.getSelectedItem()), | ||||
|                             nodesInputPanel.getNodeForInputs(), mode, (AbstractInputData.ArcFilter) arcFilterSelect.getSelectedItem(), | ||||
|                             graphicObserver.isSelected(), textObserver.isSelected())); | ||||
|                 } | ||||
|             } | ||||
|  | @ -58,7 +58,7 @@ import org.insa.graph.io.BinaryGraphReaderInsa2018; | |||
| import org.insa.graph.io.BinaryPathReader; | ||||
| import org.insa.graph.io.GraphReader; | ||||
| import org.insa.graph.io.MapMismatchException; | ||||
| import org.insa.graphics.ShortestPathPanel.StartActionEvent; | ||||
| import org.insa.graphics.AlgorithmPanel.StartActionEvent; | ||||
| import org.insa.graphics.drawing.BasicGraphPalette; | ||||
| import org.insa.graphics.drawing.BlackAndWhiteGraphPalette; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
|  | @ -107,7 +107,7 @@ public class MainWindow extends JFrame { | |||
|     private JSplitPane mainPanel; | ||||
| 
 | ||||
|     // Shortest path panel | ||||
|     private ShortestPathPanel spPanel; | ||||
|     private AlgorithmPanel spPanel; | ||||
| 
 | ||||
|     // List of items that cannot be used without a graph | ||||
|     private ArrayList<JMenuItem> graphLockItems = new ArrayList<JMenuItem>(); | ||||
|  | @ -148,7 +148,7 @@ public class MainWindow extends JFrame { | |||
| 
 | ||||
|         this.drawing = this.basicDrawing; | ||||
| 
 | ||||
|         spPanel = new ShortestPathPanel(this); | ||||
|         spPanel = new AlgorithmPanel(this, ShortestPathAlgorithm.class); | ||||
|         spPanel.addStartActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|  |  | |||
|  | @ -4,48 +4,45 @@ import java.awt.Color; | |||
| import java.awt.Component; | ||||
| import java.awt.event.ActionEvent; | ||||
| import java.awt.event.ActionListener; | ||||
| import java.io.BufferedOutputStream; | ||||
| import java.io.DataOutputStream; | ||||
| import java.io.File; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import javax.swing.BorderFactory; | ||||
| import javax.swing.Box; | ||||
| import javax.swing.BoxLayout; | ||||
| import javax.swing.JButton; | ||||
| import javax.swing.JComboBox; | ||||
| import javax.swing.JFileChooser; | ||||
| import javax.swing.JLabel; | ||||
| import javax.swing.JOptionPane; | ||||
| import javax.swing.JPanel; | ||||
| import javax.swing.JTextArea; | ||||
| import javax.swing.UIManager; | ||||
| import javax.swing.border.CompoundBorder; | ||||
| import javax.swing.border.EmptyBorder; | ||||
| 
 | ||||
| import org.insa.algo.shortestpath.ShortestPathData; | ||||
| import org.insa.algo.shortestpath.ShortestPathData.Mode; | ||||
| import org.insa.algo.AbstractInputData; | ||||
| import org.insa.algo.AbstractSolution; | ||||
| import org.insa.algo.shortestpath.ShortestPathSolution; | ||||
| import org.insa.graph.Graph; | ||||
| import org.insa.graph.io.BinaryPathWriter; | ||||
| import org.insa.graph.Path; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
| import org.insa.graphics.drawing.overlays.PathOverlay; | ||||
| 
 | ||||
| public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeListener, GraphChangeListener { | ||||
| public class SolutionPanel extends JPanel implements DrawingChangeListener, GraphChangeListener { | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      */ | ||||
|     private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|     private class ShortestPathBundle { | ||||
|     private class SolutionBundle { | ||||
| 
 | ||||
|         // Solution | ||||
|         private final ShortestPathSolution solution; | ||||
|         private final AbstractSolution solution; | ||||
| 
 | ||||
|         // Path Overlay (not final due to redraw) | ||||
|         private PathOverlay overlay = null; | ||||
|         private List<PathOverlay> overlays = new ArrayList<>(); | ||||
| 
 | ||||
|         /** | ||||
|          * Create a new bundle with the given solution and create a new overlay | ||||
|  | @ -54,72 +51,88 @@ public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeLi | |||
|          * @param solution Solution for this bundle, must not be null. | ||||
|          *  | ||||
|          */ | ||||
|         public ShortestPathBundle(ShortestPathSolution solution) { | ||||
|         public SolutionBundle(AbstractSolution solution) { | ||||
|             this.solution = solution; | ||||
|             if (this.solution.isFeasible()) { | ||||
|                 this.overlay = drawing.drawPath(this.solution.getPath()); | ||||
|             } | ||||
|             this.overlays = createOverlaysFromSolution(); | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Solution associated with this bundle. | ||||
|          */ | ||||
|         public ShortestPathSolution getSolution() { | ||||
|         public AbstractSolution getSolution() { | ||||
|             return this.solution; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Data assocaited with this bundle. | ||||
|          */ | ||||
|         public ShortestPathData getData() { | ||||
|         public AbstractInputData getData() { | ||||
|             return this.solution.getInputData(); | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Overlay associated with this bundle, or null. | ||||
|          * @return Overlays associated with this bundle, or null. | ||||
|          */ | ||||
|         public PathOverlay getOverlay() { | ||||
|             return this.overlay; | ||||
|         public List<PathOverlay> getOverlays() { | ||||
|             return this.overlays; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Re-draw the current overlay (if any) on the new drawing. | ||||
|          *  | ||||
|          */ | ||||
|         public void updateOverlay(Drawing newDrawing) { | ||||
|             if (this.overlay != null) { | ||||
|                 PathOverlay oldOverlay = this.overlay; | ||||
|                 this.overlay = newDrawing.drawPath(this.solution.getPath()); | ||||
|                 this.overlay.setVisible(oldOverlay.isVisible()); | ||||
|                 oldOverlay.delete(); | ||||
|         public void updateOverlays() { | ||||
|             List<PathOverlay> oldOverlays = this.overlays; | ||||
|             this.overlays = createOverlaysFromSolution(); | ||||
|             for (int i = 0; i < oldOverlays.size(); ++i) { | ||||
|                 oldOverlays.get(i).delete(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private List<PathOverlay> createOverlaysFromSolution() { | ||||
|             List<PathOverlay> overlays = new ArrayList<>(); | ||||
|             if (solution.isFeasible()) { | ||||
|                 Method[] methods = this.solution.getClass().getDeclaredMethods(); | ||||
|                 for (Method method: methods) { | ||||
|                     if (method.getReturnType().equals(Path.class) && method.getParameterCount() == 0) { | ||||
|                         try { | ||||
|                             Path path = (Path) method.invoke(this.solution); | ||||
|                             overlays.add(drawing.drawPath(path)); | ||||
|                         } | ||||
|                         catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { | ||||
|                             // This has been check before, so should never happen... | ||||
|                             e.printStackTrace(); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return overlays; | ||||
|         } | ||||
| 
 | ||||
|         /* | ||||
|          * (non-Javadoc) | ||||
|          *  | ||||
|          * @see java.lang.Object#toString() | ||||
|          */ | ||||
|         public String toString() { | ||||
|             return "Shortest-path from #" + this.getData().getOrigin().getId() + " to #" | ||||
|                     + this.getData().getDestination().getId() + " [" + this.getData().getMode().toString().toLowerCase() | ||||
|                     + "]"; | ||||
|             return getData().toString(); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     // Solution | ||||
|     private Drawing drawing; | ||||
| 
 | ||||
|     // Solution selector | ||||
|     private final JComboBox<ShortestPathBundle> solutionSelect; | ||||
|     private final JComboBox<SolutionBundle> solutionSelect; | ||||
| 
 | ||||
|     // Map solution -> panel | ||||
|     private final JTextArea informationPanel; | ||||
| 
 | ||||
|     // Current bundle | ||||
|     private ShortestPathBundle currentBundle = null; | ||||
|     private SolutionBundle currentBundle = null; | ||||
| 
 | ||||
|     public ShortestPathSolutionPanel(Component parent) { | ||||
|     public SolutionPanel(Component parent) { | ||||
|         super(); | ||||
|         setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); | ||||
|         setBorder(new CompoundBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.LIGHT_GRAY), | ||||
|  | @ -147,17 +160,15 @@ public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeLi | |||
| 
 | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 PathOverlay overlay = currentBundle.getOverlay(); | ||||
|                 if (overlay == null) { | ||||
|                     return; | ||||
|                 } | ||||
|                 if (overlay.isVisible()) { | ||||
|                     overlay.setVisible(false); | ||||
|                     clearButton.setText("Show"); | ||||
|                 } | ||||
|                 else { | ||||
|                     overlay.setVisible(true); | ||||
|                     clearButton.setText("Hide"); | ||||
|                 for (PathOverlay overlay: currentBundle.getOverlays()) { | ||||
|                     if (overlay.isVisible()) { | ||||
|                         overlay.setVisible(false); | ||||
|                         clearButton.setText("Show"); | ||||
|                     } | ||||
|                     else { | ||||
|                         overlay.setVisible(true); | ||||
|                         clearButton.setText("Hide"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|  | @ -166,26 +177,29 @@ public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeLi | |||
|         saveButton.addActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 String filepath = System.getProperty("user.dir"); | ||||
|                 filepath += File.separator + String.format("path_%s_%d_%d.path", | ||||
|                         currentBundle.getData().getGraph().getMapId().toLowerCase().replaceAll("[^a-z0-9_]", "_"), | ||||
|                         currentBundle.getData().getOrigin().getId(), currentBundle.getData().getDestination().getId()); | ||||
|                 JFileChooser fileChooser = new JFileChooser(); | ||||
|                 fileChooser.setSelectedFile(new File(filepath)); | ||||
|                 fileChooser.setApproveButtonText("Save"); | ||||
| 
 | ||||
|                 if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) { | ||||
|                     File file = fileChooser.getSelectedFile(); | ||||
|                     try { | ||||
|                         BinaryPathWriter writer = new BinaryPathWriter( | ||||
|                                 new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))); | ||||
|                         writer.writePath(currentBundle.getSolution().getPath()); | ||||
|                     } | ||||
|                     catch (IOException e1) { | ||||
|                         JOptionPane.showMessageDialog(parent, "Unable to write path to the selected file."); | ||||
|                         e1.printStackTrace(); | ||||
|                     } | ||||
|                 } | ||||
|                 // String filepath = System.getProperty("user.dir"); | ||||
|                 // filepath += File.separator + String.format("path_%s_%d_%d.path", | ||||
|                 // currentBundle.getData().getGraph().getMapId().toLowerCase().replaceAll("[^a-z0-9_]", | ||||
|                 // "_"), | ||||
|                 // currentBundle.getData().getOrigin().getId(), | ||||
|                 // currentBundle.getData().getDestination().getId()); | ||||
|                 // JFileChooser fileChooser = new JFileChooser(); | ||||
|                 // fileChooser.setSelectedFile(new File(filepath)); | ||||
|                 // fileChooser.setApproveButtonText("Save"); | ||||
|                 // | ||||
|                 // if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) { | ||||
|                 // File file = fileChooser.getSelectedFile(); | ||||
|                 // try { | ||||
|                 // BinaryPathWriter writer = new BinaryPathWriter( | ||||
|                 // new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))); | ||||
|                 // writer.writePath(currentBundle.getSolution().getPath()); | ||||
|                 // } | ||||
|                 // catch (IOException e1) { | ||||
|                 // JOptionPane.showMessageDialog(parent, "Unable to write path to the selected | ||||
|                 // file."); | ||||
|                 // e1.printStackTrace(); | ||||
|                 // } | ||||
|                 // } | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|  | @ -200,23 +214,25 @@ public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeLi | |||
|         solutionSelect.addActionListener(new ActionListener() { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
| 
 | ||||
|                 ShortestPathBundle bundle = (ShortestPathBundle) solutionSelect.getSelectedItem(); | ||||
|                 SolutionBundle bundle = (SolutionBundle) solutionSelect.getSelectedItem(); | ||||
| 
 | ||||
|                 // Handle case when the JComboBox is empty. | ||||
|                 if (bundle == null) { | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 if (currentBundle != null && currentBundle.getOverlay() != null) { | ||||
|                     currentBundle.getOverlay().setVisible(false); | ||||
|                 if (currentBundle != null) { | ||||
|                     for (PathOverlay overlay: currentBundle.getOverlays()) { | ||||
|                         overlay.setVisible(false); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 updateInformationLabel(bundle); | ||||
|                 buttonPanel.setVisible(bundle.getSolution().isFeasible()); | ||||
|                 clearButton.setText(bundle.getSolution().isFeasible() ? "Hide" : "Show"); | ||||
| 
 | ||||
|                 if (bundle.getOverlay() != null) { | ||||
|                     bundle.getOverlay().setVisible(true); | ||||
|                 for (PathOverlay overlay: bundle.getOverlays()) { | ||||
|                     overlay.setVisible(true); | ||||
|                 } | ||||
| 
 | ||||
|                 currentBundle = bundle; | ||||
|  | @ -226,31 +242,13 @@ public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeLi | |||
|     } | ||||
| 
 | ||||
|     public void addSolution(ShortestPathSolution solution) { | ||||
|         ShortestPathBundle bundle = new ShortestPathBundle(solution); | ||||
|         SolutionBundle bundle = new SolutionBundle(solution); | ||||
|         solutionSelect.addItem(bundle); | ||||
|         solutionSelect.setSelectedItem(bundle); | ||||
|     } | ||||
| 
 | ||||
|     protected void updateInformationLabel(ShortestPathBundle bundle) { | ||||
|         ShortestPathData data = bundle.getData(); | ||||
|         String info = null; | ||||
|         if (!bundle.getSolution().isFeasible()) { | ||||
|             info = String.format("No path found from node #%d to node #%d.", data.getOrigin().getId(), | ||||
|                     data.getDestination().getId()); | ||||
|         } | ||||
|         else { | ||||
|             info = String.format("Found a path from node #%d to node #%d", data.getOrigin().getId(), | ||||
|                     data.getDestination().getId()); | ||||
|             if (data.getMode() == Mode.LENGTH) { | ||||
|                 info = String.format("%s, %.4f kilometers.", info, | ||||
|                         (bundle.getSolution().getPath().getLength() / 1000.0)); | ||||
|             } | ||||
|             else { | ||||
|                 info = String.format("%s, %.4f minutes.", info, | ||||
|                         (bundle.getSolution().getPath().getMinimumTravelTime() / 60.0)); | ||||
|             } | ||||
|         } | ||||
|         informationPanel.setText(info); | ||||
|     protected void updateInformationLabel(SolutionBundle bundle) { | ||||
|         informationPanel.setText(bundle.getSolution().toString()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|  | @ -263,19 +261,19 @@ public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeLi | |||
|             solutionSelect.actionPerformed(null); | ||||
|         } | ||||
|         else { | ||||
|             ShortestPathBundle bundle = (ShortestPathBundle) this.solutionSelect.getSelectedItem(); | ||||
|             if (bundle != null && bundle.getOverlay() != null) { | ||||
|                 bundle.getOverlay().setVisible(false); | ||||
|             SolutionBundle bundle = (SolutionBundle) this.solutionSelect.getSelectedItem(); | ||||
|             if (bundle != null) { | ||||
|                 for (PathOverlay overlay: bundle.getOverlays()) { | ||||
|                     overlay.setVisible(false); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void newGraphLoaded(Graph graph) { | ||||
|         for (int i = 0; i < this.solutionSelect.getItemCount(); ++i) { | ||||
|             PathOverlay overlay = this.solutionSelect.getItemAt(i).getOverlay(); | ||||
|             if (overlay != null) { | ||||
|             for (PathOverlay overlay: this.solutionSelect.getItemAt(i).getOverlays()) { | ||||
|                 overlay.delete(); | ||||
|             } | ||||
|         } | ||||
|  | @ -294,7 +292,7 @@ public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeLi | |||
|     @Override | ||||
|     public void onRedrawRequest() { | ||||
|         for (int i = 0; i < this.solutionSelect.getItemCount(); ++i) { | ||||
|             this.solutionSelect.getItemAt(i).updateOverlay(drawing); | ||||
|             this.solutionSelect.getItemAt(i).updateOverlays(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
		Loading…
	
		Reference in a new issue