Add shortest path panel.
This commit is contained in:
		
							parent
							
								
									b6eb6d97ea
								
							
						
					
					
						commit
						6bc633e5bb
					
				
					 3 changed files with 633 additions and 21 deletions
				
			
		|  | @ -4,6 +4,8 @@ import java.awt.BorderLayout; | |||
| import java.awt.Color; | ||||
| import java.awt.Component; | ||||
| import java.awt.Dimension; | ||||
| import java.awt.GridBagConstraints; | ||||
| import java.awt.GridBagLayout; | ||||
| import java.awt.event.ActionEvent; | ||||
| import java.awt.event.ActionListener; | ||||
| import java.awt.event.KeyEvent; | ||||
|  | @ -34,10 +36,11 @@ import javax.swing.Timer; | |||
| import javax.swing.UIManager; | ||||
| import javax.swing.filechooser.FileNameExtensionFilter; | ||||
| 
 | ||||
| import org.insa.algo.shortestpath.AStarAlgorithm; | ||||
| import org.insa.algo.shortestpath.BellmanFordAlgorithm; | ||||
| import org.insa.algo.shortestpath.DijkstraAlgorithm; | ||||
| import org.insa.algo.shortestpath.ShortestPathAlgorithm; | ||||
| import org.insa.algo.shortestpath.ShortestPathData; | ||||
| import org.insa.algo.shortestpath.ShortestPathData.Mode; | ||||
| import org.insa.algo.shortestpath.ShortestPathGraphicObserver; | ||||
| import org.insa.algo.shortestpath.ShortestPathSolution; | ||||
| import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver; | ||||
|  | @ -45,7 +48,6 @@ import org.insa.algo.weakconnectivity.WeaklyConnectedComponentTextObserver; | |||
| import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm; | ||||
| import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsData; | ||||
| import org.insa.graph.Graph; | ||||
| import org.insa.graph.Node; | ||||
| import org.insa.graph.Path; | ||||
| import org.insa.graph.io.BinaryGraphReader; | ||||
| import org.insa.graph.io.BinaryGraphReaderV2; | ||||
|  | @ -53,7 +55,7 @@ import org.insa.graph.io.BinaryPathReader; | |||
| import org.insa.graph.io.GraphReader; | ||||
| import org.insa.graph.io.MapMismatchException; | ||||
| import org.insa.graph.io.Openfile; | ||||
| import org.insa.graphics.MultiPointsClickListener.CallableWithNodes; | ||||
| import org.insa.graphics.ShortestPathPanel.StartActionEvent; | ||||
| import org.insa.graphics.drawing.BasicDrawing; | ||||
| import org.insa.graphics.drawing.BlackAndWhiteGraphPalette; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
|  | @ -88,6 +90,9 @@ public class MainWindow extends JFrame { | |||
|     // Main panel. | ||||
|     private JSplitPane mainPanel; | ||||
| 
 | ||||
|     // Shortest path panel | ||||
|     private ShortestPathPanel spPanel; | ||||
| 
 | ||||
|     // List of item for the top menus. | ||||
|     private JMenuItem openMapItem; | ||||
| 
 | ||||
|  | @ -158,12 +163,24 @@ public class MainWindow extends JFrame { | |||
|         this.logStream = new StreamCapturer(infoPanel); | ||||
|         this.printStream = new PrintStream(this.logStream); | ||||
| 
 | ||||
|         JPanel rightComponent = new JPanel(); | ||||
|         rightComponent.setLayout(new GridBagLayout()); | ||||
| 
 | ||||
|         GridBagConstraints c = new GridBagConstraints(); | ||||
|         c.gridx = 0; | ||||
|         c.gridy = 1; | ||||
|         c.weightx = 1; | ||||
|         c.weighty = 1; | ||||
|         c.fill = GridBagConstraints.BOTH; | ||||
|         c.gridheight = GridBagConstraints.REMAINDER; | ||||
|         rightComponent.add(new JScrollPane(infoPanel), c); | ||||
| 
 | ||||
|         mainPanel.setResizeWeight(0.8); | ||||
|         mainPanel.setDividerSize(5); | ||||
| 
 | ||||
|         mainPanel.setBackground(Color.WHITE); | ||||
|         mainPanel.setLeftComponent((Component) this.drawing); | ||||
|         mainPanel.setRightComponent(new JScrollPane(infoPanel)); | ||||
|         mainPanel.setRightComponent(rightComponent); | ||||
|         this.add(mainPanel, BorderLayout.CENTER); | ||||
| 
 | ||||
|         // Top Panel | ||||
|  | @ -201,6 +218,7 @@ public class MainWindow extends JFrame { | |||
|         threadTimer.stop(); | ||||
|         threadPanel.setVisible(false); | ||||
|         currentThread.setThread(null); | ||||
|         spPanel.setEnabled(true); | ||||
|     } | ||||
| 
 | ||||
|     private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) { | ||||
|  | @ -422,33 +440,49 @@ public class MainWindow extends JFrame { | |||
|         })); | ||||
| 
 | ||||
|         // Shortest path | ||||
|         JMenuItem bellmanItem = new JMenuItem("Shortest Path (Bellman-Ford)"); | ||||
|         bellmanItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|         JMenuItem spItem = new JMenuItem("Shortest Path"); | ||||
|         spItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 int idx = JOptionPane.showOptionDialog(MainWindow.this, "Which mode do you want?", "Mode selection", | ||||
|                         JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, Mode.values(), Mode.LENGTH); | ||||
|                 int dividerLocation = mainPanel.getDividerLocation(); | ||||
|                 spPanel = new ShortestPathPanel(drawing, graph); | ||||
| 
 | ||||
|                 if (idx != -1) { | ||||
|                     Mode mode = Mode.values()[idx]; | ||||
|                     clickAdapter.enable(2, new CallableWithNodes() { | ||||
|                         @Override | ||||
|                         public void call(ArrayList<Node> nodes) { | ||||
|                             launchShortestPathThread(new BellmanFordAlgorithm( | ||||
|                                     new ShortestPathData(graph, nodes.get(0), nodes.get(1), mode))); | ||||
|                 GridBagConstraints c = new GridBagConstraints(); | ||||
|                 c.gridx = 0; | ||||
|                 c.gridy = 0; | ||||
|                 c.fill = GridBagConstraints.HORIZONTAL; | ||||
|                 ((JPanel) mainPanel.getRightComponent()).add(spPanel, c); | ||||
| 
 | ||||
|                 mainPanel.setDividerLocation(dividerLocation); | ||||
| 
 | ||||
|                 spPanel.addStartActionListener(new ActionListener() { | ||||
|                     @Override | ||||
|                     public void actionPerformed(ActionEvent e) { | ||||
|                         StartActionEvent evt = (StartActionEvent) e; | ||||
|                         ShortestPathData data = new ShortestPathData(graph, evt.getOrigin(), evt.getDestination(), | ||||
|                                 evt.getMode()); | ||||
|                         ShortestPathAlgorithm spAlgorithm = null; | ||||
|                         if (evt.getAlgorithmClass() == BellmanFordAlgorithm.class) { | ||||
|                             spAlgorithm = new BellmanFordAlgorithm(data); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|                         else if (evt.getAlgorithmClass() == DijkstraAlgorithm.class) { | ||||
|                             spAlgorithm = new DijkstraAlgorithm(data); | ||||
|                         } | ||||
|                         else if (evt.getAlgorithmClass() == AStarAlgorithm.class) { | ||||
|                             spAlgorithm = new AStarAlgorithm(data); | ||||
|                         } | ||||
|                         spPanel.setEnabled(false); | ||||
|                         launchShortestPathThread(spAlgorithm); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         })); | ||||
|         graphLockItems.add(wccItem); | ||||
|         graphLockItems.add(bellmanItem); | ||||
|         graphLockItems.add(spItem); | ||||
| 
 | ||||
|         algoMenu.add(wccItem); | ||||
|         algoMenu.addSeparator(); | ||||
|         algoMenu.add(bellmanItem); | ||||
|         // algoMenu.add(djikstraItem); | ||||
|         // algoMenu.add(aStarItem); | ||||
|         algoMenu.add(spItem); | ||||
| 
 | ||||
|         // Create the menu bar. | ||||
|         JMenuBar menuBar = new JMenuBar(); | ||||
|  |  | |||
							
								
								
									
										307
									
								
								src/main/org/insa/graphics/NodesInputPanel.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								src/main/org/insa/graphics/NodesInputPanel.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,307 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.awt.Color; | ||||
| import java.awt.Font; | ||||
| import java.awt.GridBagConstraints; | ||||
| import java.awt.GridBagLayout; | ||||
| import java.awt.Insets; | ||||
| import java.awt.event.ActionEvent; | ||||
| import java.awt.event.ActionListener; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.IdentityHashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import javax.swing.JButton; | ||||
| import javax.swing.JComponent; | ||||
| import javax.swing.JLabel; | ||||
| import javax.swing.JPanel; | ||||
| import javax.swing.JTextField; | ||||
| import javax.swing.event.DocumentEvent; | ||||
| import javax.swing.event.DocumentListener; | ||||
| 
 | ||||
| import org.insa.graph.Graph; | ||||
| import org.insa.graph.Node; | ||||
| import org.insa.graph.Point; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
| import org.insa.graphics.drawing.DrawingClickListener; | ||||
| import org.insa.graphics.drawing.MarkerTracker; | ||||
| 
 | ||||
| public class NodesInputPanel extends JPanel implements DrawingClickListener { | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      */ | ||||
|     private static final long serialVersionUID = -1638302070013027690L; | ||||
| 
 | ||||
|     private static final Color DEFAULT_MARKER_COLOR = Color.BLUE; | ||||
| 
 | ||||
|     public class InputChangedEvent extends ActionEvent { | ||||
| 
 | ||||
|         /** | ||||
|          *  | ||||
|          */ | ||||
|         private static final long serialVersionUID = 3440024811352247731L; | ||||
| 
 | ||||
|         protected static final String ALL_INPUT_FILLED_EVENT_COMMAND = "allInputFilled"; | ||||
| 
 | ||||
|         protected static final int ALL_INPUT_FILLED_EVENT_ID = 0x1; | ||||
| 
 | ||||
|         // List of nodes | ||||
|         List<Node> nodes; | ||||
| 
 | ||||
|         public InputChangedEvent(List<Node> nodes2) { | ||||
|             super(NodesInputPanel.this, ALL_INPUT_FILLED_EVENT_ID, ALL_INPUT_FILLED_EVENT_COMMAND); | ||||
|             this.nodes = nodes2; | ||||
|         } | ||||
| 
 | ||||
|         List<Node> getNodes() { | ||||
|             return Collections.unmodifiableList(nodes); | ||||
|         } | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     // Node inputs and markers. | ||||
|     private ArrayList<JTextField> nodeInputs = new ArrayList<>(); | ||||
|     private Map<JTextField, MarkerTracker> markerTrackers = new IdentityHashMap<JTextField, MarkerTracker>(); | ||||
| 
 | ||||
|     // Component that can be enabled/disabled. | ||||
|     private ArrayList<JComponent> components = new ArrayList<>(); | ||||
|     private int inputToFillIndex; | ||||
| 
 | ||||
|     // ActionListener called when all inputs are filled. | ||||
|     private ArrayList<ActionListener> inputChangeListeners = new ArrayList<>(); | ||||
| 
 | ||||
|     // Graph & Drawing. | ||||
|     private Graph graph; | ||||
|     private Drawing drawing; | ||||
| 
 | ||||
|     public NodesInputPanel(Drawing drawing, Graph graph) { | ||||
|         super(new GridBagLayout()); | ||||
|         this.graph = graph; | ||||
|         this.drawing = drawing; | ||||
|         initInputToFill(); | ||||
|         drawing.addDrawingClickListener(this); | ||||
|     } | ||||
| 
 | ||||
|     public void addInputChangedListener(ActionListener listener) { | ||||
|         inputChangeListeners.add(listener); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setEnabled(boolean enabled) { | ||||
|         for (JComponent component: components) { | ||||
|             component.setEnabled(enabled); | ||||
|         } | ||||
|         super.setEnabled(enabled); | ||||
|         if (enabled) { | ||||
|             // Enable: Check if there is an input to fill, otherwize find the next one. | ||||
|             if (getInputToFill() == null) { | ||||
|                 nextInputToFill(); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             // Disable, next input to fill = -1. | ||||
|             this.inputToFillIndex = -1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public void clear() { | ||||
|         for (JTextField field: nodeInputs) { | ||||
|             field.setText(""); | ||||
|         } | ||||
|         initInputToFill(); | ||||
|     } | ||||
| 
 | ||||
|     public void addTextField(String label) { | ||||
|         addTextField(label, DEFAULT_MARKER_COLOR); | ||||
|     } | ||||
| 
 | ||||
|     public void addTextField(String label, Color markerColor) { | ||||
| 
 | ||||
|         GridBagConstraints c = new GridBagConstraints(); | ||||
|         c.insets = new Insets(3, 3, 3, 3); | ||||
| 
 | ||||
|         JLabel jLabel = new JLabel(label); | ||||
|         jLabel.setFont(jLabel.getFont().deriveFont(~Font.BOLD)); | ||||
|         JTextField textField = new JTextField(); | ||||
|         jLabel.setLabelFor(textField); | ||||
| 
 | ||||
|         c.gridx = 0; | ||||
|         c.gridy = nodeInputs.size(); | ||||
|         c.weightx = 0; | ||||
|         c.gridwidth = 1; | ||||
|         c.fill = GridBagConstraints.HORIZONTAL; | ||||
|         add(jLabel, c); | ||||
| 
 | ||||
|         c.gridx = 1; | ||||
|         c.gridy = nodeInputs.size(); | ||||
|         c.weightx = 1; | ||||
|         c.gridwidth = 1; | ||||
|         c.fill = GridBagConstraints.HORIZONTAL; | ||||
|         add(textField, c); | ||||
| 
 | ||||
|         JButton clearButton = new JButton("Clear"); | ||||
|         c.gridx = 2; | ||||
|         c.gridy = nodeInputs.size(); | ||||
|         c.weightx = 0; | ||||
|         c.gridwidth = 1; | ||||
|         c.fill = GridBagConstraints.HORIZONTAL; | ||||
|         add(clearButton, c); | ||||
| 
 | ||||
|         JButton clickButton = new JButton("Click"); | ||||
|         c.gridx = 3; | ||||
|         c.gridy = nodeInputs.size(); | ||||
|         c.weightx = 0; | ||||
|         c.gridwidth = 1; | ||||
|         c.fill = GridBagConstraints.HORIZONTAL; | ||||
|         add(clickButton, c); | ||||
| 
 | ||||
|         // Did not find something easier that this... ? | ||||
|         textField.getDocument().addDocumentListener(new DocumentListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void changedUpdate(DocumentEvent e) { | ||||
|                 insertUpdate(e); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void removeUpdate(DocumentEvent e) { | ||||
|                 insertUpdate(e); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void insertUpdate(DocumentEvent e) { | ||||
| 
 | ||||
|                 // Draw marker if possible | ||||
|                 Node curnode = getNodeForInput(textField); | ||||
|                 MarkerTracker tracker = markerTrackers.getOrDefault(textField, null); | ||||
|                 if (curnode != null) { | ||||
|                     if (tracker == null) { | ||||
|                         tracker = drawing.drawMarker(curnode.getPoint(), markerColor); | ||||
|                         markerTrackers.put(textField, tracker); | ||||
|                     } | ||||
|                     else { | ||||
|                         tracker.moveTo(curnode.getPoint()); | ||||
|                     } | ||||
|                     tracker.setVisible(true); | ||||
|                 } | ||||
|                 else if (tracker != null) { | ||||
|                     tracker.setVisible(false); | ||||
|                 } | ||||
| 
 | ||||
|                 // Create array of nodes | ||||
|                 List<Node> nodes = getNodeForInputs(); | ||||
| 
 | ||||
|                 // Trigger change event. | ||||
|                 for (ActionListener lis: inputChangeListeners) { | ||||
|                     lis.actionPerformed(new InputChangedEvent(nodes)); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         clearButton.addActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 textField.setText(""); | ||||
|                 setInputToFill(textField); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         clickButton.addActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 setInputToFill(textField); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         nodeInputs.add(textField); | ||||
|         components.add(textField); | ||||
|         components.add(clearButton); | ||||
|         components.add(clickButton); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The node for the given text field, or null if the content of the text | ||||
|      *         field is invalid. | ||||
|      */ | ||||
|     protected Node getNodeForInput(JTextField textfield) { | ||||
|         try { | ||||
|             Node node = graph.getNodes().get(Integer.valueOf(textfield.getText().trim())); | ||||
|             return node; | ||||
|         } | ||||
|         catch (IllegalArgumentException | IndexOutOfBoundsException ex) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return List of nodes associated with the input. Some nodes may be null if | ||||
|      *         their associated input is invalid. | ||||
|      */ | ||||
|     public List<Node> getNodeForInputs() { | ||||
|         List<Node> nodes = new ArrayList<>(nodeInputs.size()); | ||||
|         for (JTextField input: nodeInputs) { | ||||
|             nodes.add(getNodeForInput(input)); | ||||
|         } | ||||
|         return nodes; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the next input that should be filled by a click, or null if none should | ||||
|      * be filled. | ||||
|      *  | ||||
|      * @return | ||||
|      */ | ||||
|     protected JTextField getInputToFill() { | ||||
|         if (inputToFillIndex < 0 || inputToFillIndex >= nodeInputs.size()) { | ||||
|             return null; | ||||
|         } | ||||
|         return nodeInputs.get(inputToFillIndex); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Initialize the next input to fill. | ||||
|      */ | ||||
|     protected void initInputToFill() { | ||||
|         inputToFillIndex = 0; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set the next input to fill to the given text field. | ||||
|      *  | ||||
|      * @param input | ||||
|      */ | ||||
|     protected void setInputToFill(JTextField input) { | ||||
|         inputToFillIndex = nodeInputs.indexOf(input); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Find the next input to fill, if any. | ||||
|      */ | ||||
|     protected void nextInputToFill() { | ||||
|         boolean found = false; | ||||
|         for (int i = 1; i < nodeInputs.size() && !found; ++i) { | ||||
|             int nextIndex = (i + inputToFillIndex) % nodeInputs.size(); | ||||
|             JTextField input = nodeInputs.get(nextIndex); | ||||
|             if (input.getText().trim().isEmpty()) { | ||||
|                 inputToFillIndex = nextIndex; | ||||
|                 found = true; | ||||
|             } | ||||
|         } | ||||
|         if (!found) { | ||||
|             inputToFillIndex = -1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void mouseClicked(Point point) { | ||||
|         Node node = graph.findClosestNode(point); | ||||
|         JTextField input = getInputToFill(); | ||||
|         if (input != null) { | ||||
|             input.setText(String.valueOf(node.getId())); | ||||
|             nextInputToFill(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										271
									
								
								src/main/org/insa/graphics/ShortestPathPanel.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								src/main/org/insa/graphics/ShortestPathPanel.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,271 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.awt.BorderLayout; | ||||
| import java.awt.Color; | ||||
| import java.awt.Component; | ||||
| import java.awt.Font; | ||||
| import java.awt.event.ActionEvent; | ||||
| import java.awt.event.ActionListener; | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import javax.swing.Box; | ||||
| import javax.swing.BoxLayout; | ||||
| import javax.swing.ButtonGroup; | ||||
| import javax.swing.JButton; | ||||
| import javax.swing.JComboBox; | ||||
| import javax.swing.JComponent; | ||||
| import javax.swing.JFrame; | ||||
| import javax.swing.JLabel; | ||||
| import javax.swing.JPanel; | ||||
| import javax.swing.JRadioButton; | ||||
| import javax.swing.JSplitPane; | ||||
| import javax.swing.border.EmptyBorder; | ||||
| 
 | ||||
| import org.insa.algo.shortestpath.AStarAlgorithm; | ||||
| import org.insa.algo.shortestpath.BellmanFordAlgorithm; | ||||
| import org.insa.algo.shortestpath.DijkstraAlgorithm; | ||||
| import org.insa.algo.shortestpath.ShortestPathAlgorithm; | ||||
| import org.insa.algo.shortestpath.ShortestPathData.Mode; | ||||
| import org.insa.graph.Graph; | ||||
| import org.insa.graph.Node; | ||||
| import org.insa.graph.io.BinaryGraphReaderV2; | ||||
| import org.insa.graph.io.GraphReader; | ||||
| import org.insa.graph.io.Openfile; | ||||
| import org.insa.graphics.NodesInputPanel.InputChangedEvent; | ||||
| import org.insa.graphics.drawing.BasicDrawing; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
| 
 | ||||
| public class ShortestPathPanel extends JPanel { | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      */ | ||||
|     private static final long serialVersionUID = 406148710808045035L; | ||||
| 
 | ||||
|     public class StartActionEvent extends ActionEvent { | ||||
| 
 | ||||
|         /** | ||||
|          *  | ||||
|          */ | ||||
|         private static final long serialVersionUID = 4090710269781229078L; | ||||
| 
 | ||||
|         protected static final String START_EVENT_COMMAND = "allInputFilled"; | ||||
| 
 | ||||
|         protected static final int START_EVENT_ID = 0x1; | ||||
| 
 | ||||
|         private final Node origin, destination; | ||||
|         private final Mode mode; | ||||
|         private final Class<? extends ShortestPathAlgorithm> algoClass; | ||||
| 
 | ||||
|         public StartActionEvent(Class<? extends ShortestPathAlgorithm> algoClass, Node origin, Node destination, | ||||
|                 Mode mode) { | ||||
|             super(ShortestPathPanel.this, START_EVENT_ID, START_EVENT_COMMAND); | ||||
|             this.origin = origin; | ||||
|             this.destination = destination; | ||||
|             this.mode = mode; | ||||
|             this.algoClass = algoClass; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Origin node associated with this event. | ||||
|          */ | ||||
|         public Node getOrigin() { | ||||
|             return this.origin; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Destination node associated with this event. | ||||
|          */ | ||||
|         public Node getDestination() { | ||||
|             return this.destination; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Mode associated with this event. | ||||
|          */ | ||||
|         public Mode getMode() { | ||||
|             return this.mode; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @return Algorithm class associated with this event. | ||||
|          */ | ||||
|         public Class<? extends ShortestPathAlgorithm> getAlgorithmClass() { | ||||
|             return this.algoClass; | ||||
|         } | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     // Map between algorithm names and class, see end of this class for | ||||
|     // initialization. | ||||
|     private static Map<String, Class<? extends ShortestPathAlgorithm>> SHORTEST_PATH_ALGORITHMS = new HashMap<>(); | ||||
| 
 | ||||
|     // Input panels for node. | ||||
|     private NodesInputPanel nodesInputPanel; | ||||
| 
 | ||||
|     // Component that can be enabled/disabled. | ||||
|     private ArrayList<JComponent> components = new ArrayList<>(); | ||||
| 
 | ||||
|     // Start listeners | ||||
|     List<ActionListener> startActionListeners = new ArrayList<>(); | ||||
| 
 | ||||
|     public ShortestPathPanel(Drawing drawing, Graph graph) { | ||||
|         super(); | ||||
|         setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); | ||||
| 
 | ||||
|         setBorder(new EmptyBorder(15, 15, 15, 15)); | ||||
| 
 | ||||
|         // Set title. | ||||
|         JLabel titleLabel = new JLabel("Shortest-Path"); | ||||
|         titleLabel.setBackground(Color.RED); | ||||
|         titleLabel.setHorizontalAlignment(JLabel.LEFT); | ||||
|         titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||
|         Font font = titleLabel.getFont(); | ||||
|         font = font.deriveFont(Font.BOLD, 18); | ||||
|         titleLabel.setFont(font); | ||||
|         add(titleLabel); | ||||
| 
 | ||||
|         add(Box.createVerticalStrut(8)); | ||||
| 
 | ||||
|         // Add algorithm selection | ||||
|         JComboBox<String> algoSelect = new JComboBox<>(SHORTEST_PATH_ALGORITHMS.keySet().toArray(new String[0])); | ||||
|         algoSelect.setBackground(Color.WHITE); | ||||
|         algoSelect.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||
|         add(algoSelect); | ||||
|         components.add(algoSelect); | ||||
| 
 | ||||
|         // Add inputs for node. | ||||
|         this.nodesInputPanel = new NodesInputPanel(drawing, graph); | ||||
|         this.nodesInputPanel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||
|         nodesInputPanel.addTextField("Origin: ", new Color(57, 172, 115)); | ||||
|         nodesInputPanel.addTextField("Destination: ", new Color(255, 77, 77)); | ||||
| 
 | ||||
|         add(this.nodesInputPanel); | ||||
|         components.add(this.nodesInputPanel); | ||||
| 
 | ||||
|         // Add mode selection | ||||
|         JPanel modePanel = new JPanel(); | ||||
|         modePanel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||
|         modePanel.setLayout(new BoxLayout(modePanel, BoxLayout.LINE_AXIS)); | ||||
|         JRadioButton lengthModeButton = new JRadioButton("Length"); | ||||
|         lengthModeButton.setSelected(true); | ||||
|         JRadioButton timeModeButton = new JRadioButton("Time"); | ||||
|         ButtonGroup group = new ButtonGroup(); | ||||
|         group.add(lengthModeButton); | ||||
|         group.add(timeModeButton); | ||||
|         modePanel.add(Box.createHorizontalGlue()); | ||||
|         modePanel.add(lengthModeButton); | ||||
|         modePanel.add(Box.createHorizontalGlue()); | ||||
|         modePanel.add(timeModeButton); | ||||
|         modePanel.add(Box.createHorizontalGlue()); | ||||
| 
 | ||||
|         add(modePanel); | ||||
|         components.add(timeModeButton); | ||||
|         components.add(lengthModeButton); | ||||
| 
 | ||||
|         // Bottom panel | ||||
|         JPanel bottomPanel = new JPanel(); | ||||
|         bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS)); | ||||
|         JButton startAlgoButton = new JButton("Start"); | ||||
|         startAlgoButton.setEnabled(false); | ||||
|         startAlgoButton.addActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 List<Node> nodes = nodesInputPanel.getNodeForInputs(); | ||||
|                 Node origin = nodes.get(0), destination = nodes.get(1); | ||||
|                 Mode mode = lengthModeButton.isSelected() ? Mode.LENGTH : Mode.TIME; | ||||
| 
 | ||||
|                 for (ActionListener lis: startActionListeners) { | ||||
|                     lis.actionPerformed(new StartActionEvent(SHORTEST_PATH_ALGORITHMS.get(algoSelect.getSelectedItem()), | ||||
|                             origin, destination, mode)); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         JButton hideButton = new JButton("Hide"); | ||||
|         hideButton.addActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 nodesInputPanel.setEnabled(false); | ||||
|                 setVisible(false); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         bottomPanel.add(startAlgoButton); | ||||
|         bottomPanel.add(Box.createHorizontalGlue()); | ||||
|         bottomPanel.add(hideButton); | ||||
| 
 | ||||
|         components.add(startAlgoButton); | ||||
|         components.add(hideButton); | ||||
| 
 | ||||
|         bottomPanel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||
| 
 | ||||
|         add(Box.createVerticalStrut(8)); | ||||
|         add(bottomPanel); | ||||
| 
 | ||||
|         nodesInputPanel.addInputChangedListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 InputChangedEvent evt = (InputChangedEvent) e; | ||||
|                 boolean allNotNull = true; | ||||
|                 for (Node node: evt.getNodes()) { | ||||
|                     if (node == null) { | ||||
|                         allNotNull = false; | ||||
|                     } | ||||
|                 } | ||||
|                 startAlgoButton.setEnabled(allNotNull); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setEnabled(boolean enabled) { | ||||
|         super.setEnabled(enabled); | ||||
|         nodesInputPanel.setEnabled(enabled); | ||||
|         for (JComponent component: components) { | ||||
|             component.setEnabled(enabled); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Add a new start action listener to this class. | ||||
|      *  | ||||
|      * @param listener | ||||
|      */ | ||||
|     public void addStartActionListener(ActionListener listener) { | ||||
|         this.startActionListeners.add(listener); | ||||
|     } | ||||
| 
 | ||||
|     static { | ||||
|         SHORTEST_PATH_ALGORITHMS.put("Bellman-Ford", BellmanFordAlgorithm.class); | ||||
|         SHORTEST_PATH_ALGORITHMS.put("Dijkstra", DijkstraAlgorithm.class); | ||||
|         SHORTEST_PATH_ALGORITHMS.put("A*", AStarAlgorithm.class); | ||||
|     } | ||||
| 
 | ||||
|     public static void main(String[] args) throws IOException { | ||||
| 
 | ||||
|         String nomcarte = "../BE_Graphe_Maps/morbihan3.mapgr"; | ||||
|         GraphReader reader = new BinaryGraphReaderV2(Openfile.open(nomcarte)); | ||||
|         Graph graph = reader.read(); | ||||
| 
 | ||||
|         JFrame frame = new JFrame(); | ||||
|         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
|         frame.setLayout(new BorderLayout()); | ||||
|         JSplitPane p = new JSplitPane(); | ||||
|         BasicDrawing drawing = new BasicDrawing(); | ||||
|         JPanel pane = new ShortestPathPanel(drawing, graph); | ||||
|         p.setLeftComponent(drawing); | ||||
|         p.setRightComponent(pane); | ||||
|         p.setResizeWeight(0.8); | ||||
|         frame.add(p, BorderLayout.CENTER); | ||||
|         frame.show(); | ||||
|         frame.setSize(800, 600); | ||||
|         // pane.setSize(new Dimension(400, 0)); | ||||
| 
 | ||||
|         drawing.drawGraph(graph); | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in a new issue