Create new solution panel.
This commit is contained in:
parent
8bca08f795
commit
08fd7120f2
@ -12,20 +12,15 @@ import java.awt.event.KeyEvent;
|
|||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.Box;
|
|
||||||
import javax.swing.BoxLayout;
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
@ -49,7 +44,6 @@ import javax.swing.filechooser.FileNameExtensionFilter;
|
|||||||
import org.insa.algo.shortestpath.ShortestPathAlgorithm;
|
import org.insa.algo.shortestpath.ShortestPathAlgorithm;
|
||||||
import org.insa.algo.shortestpath.ShortestPathAlgorithmFactory;
|
import org.insa.algo.shortestpath.ShortestPathAlgorithmFactory;
|
||||||
import org.insa.algo.shortestpath.ShortestPathData;
|
import org.insa.algo.shortestpath.ShortestPathData;
|
||||||
import org.insa.algo.shortestpath.ShortestPathData.Mode;
|
|
||||||
import org.insa.algo.shortestpath.ShortestPathGraphicObserver;
|
import org.insa.algo.shortestpath.ShortestPathGraphicObserver;
|
||||||
import org.insa.algo.shortestpath.ShortestPathSolution;
|
import org.insa.algo.shortestpath.ShortestPathSolution;
|
||||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver;
|
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver;
|
||||||
@ -61,7 +55,6 @@ import org.insa.graph.Path;
|
|||||||
import org.insa.graph.io.BinaryGraphReaderInsa2016;
|
import org.insa.graph.io.BinaryGraphReaderInsa2016;
|
||||||
import org.insa.graph.io.BinaryGraphReaderInsa2018;
|
import org.insa.graph.io.BinaryGraphReaderInsa2018;
|
||||||
import org.insa.graph.io.BinaryPathReader;
|
import org.insa.graph.io.BinaryPathReader;
|
||||||
import org.insa.graph.io.BinaryPathWriter;
|
|
||||||
import org.insa.graph.io.GraphReader;
|
import org.insa.graph.io.GraphReader;
|
||||||
import org.insa.graph.io.MapMismatchException;
|
import org.insa.graph.io.MapMismatchException;
|
||||||
import org.insa.graphics.ShortestPathPanel.StartActionEvent;
|
import org.insa.graphics.ShortestPathPanel.StartActionEvent;
|
||||||
@ -71,7 +64,6 @@ import org.insa.graphics.drawing.BlackAndWhiteGraphPalette;
|
|||||||
import org.insa.graphics.drawing.Drawing;
|
import org.insa.graphics.drawing.Drawing;
|
||||||
import org.insa.graphics.drawing.GraphPalette;
|
import org.insa.graphics.drawing.GraphPalette;
|
||||||
import org.insa.graphics.drawing.MapViewDrawing;
|
import org.insa.graphics.drawing.MapViewDrawing;
|
||||||
import org.insa.graphics.drawing.overlays.PathOverlay;
|
|
||||||
|
|
||||||
public class MainWindow extends JFrame {
|
public class MainWindow extends JFrame {
|
||||||
|
|
||||||
@ -106,6 +98,7 @@ public class MainWindow extends JFrame {
|
|||||||
|
|
||||||
// Shortest path panel
|
// Shortest path panel
|
||||||
private ShortestPathPanel spPanel;
|
private ShortestPathPanel spPanel;
|
||||||
|
private ShortestPathSolutionPanel spSolPanel;
|
||||||
|
|
||||||
// List of items that cannot be used without a graph
|
// List of items that cannot be used without a graph
|
||||||
private ArrayList<JMenuItem> graphLockItems = new ArrayList<JMenuItem>();
|
private ArrayList<JMenuItem> graphLockItems = new ArrayList<JMenuItem>();
|
||||||
@ -170,12 +163,17 @@ public class MainWindow extends JFrame {
|
|||||||
});
|
});
|
||||||
spPanel.setVisible(false);
|
spPanel.setVisible(false);
|
||||||
|
|
||||||
|
spSolPanel = new ShortestPathSolutionPanel(this, drawing);
|
||||||
|
spSolPanel.setVisible(false);
|
||||||
|
|
||||||
// Add click listeners to both drawing.
|
// Add click listeners to both drawing.
|
||||||
basicDrawing.addDrawingClickListener(spPanel.nodesInputPanel);
|
basicDrawing.addDrawingClickListener(spPanel.nodesInputPanel);
|
||||||
mapViewDrawing.addDrawingClickListener(spPanel.nodesInputPanel);
|
mapViewDrawing.addDrawingClickListener(spPanel.nodesInputPanel);
|
||||||
|
|
||||||
this.graphChangeListeneres.add(spPanel.nodesInputPanel);
|
this.graphChangeListeneres.add(spPanel.nodesInputPanel);
|
||||||
|
this.graphChangeListeneres.add(spSolPanel);
|
||||||
this.drawingChangeListeners.add(spPanel.nodesInputPanel);
|
this.drawingChangeListeners.add(spPanel.nodesInputPanel);
|
||||||
|
this.drawingChangeListeners.add(spSolPanel);
|
||||||
|
|
||||||
// Create action factory.
|
// Create action factory.
|
||||||
this.currentThread = new ThreadWrapper(this);
|
this.currentThread = new ThreadWrapper(this);
|
||||||
@ -218,6 +216,12 @@ public class MainWindow extends JFrame {
|
|||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
rightComponent.add(spPanel, c);
|
rightComponent.add(spPanel, c);
|
||||||
|
|
||||||
|
c = new GridBagConstraints();
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 1;
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
rightComponent.add(spSolPanel, c);
|
||||||
|
|
||||||
c = new GridBagConstraints();
|
c = new GridBagConstraints();
|
||||||
c.gridx = 0;
|
c.gridx = 0;
|
||||||
c.gridy = 2;
|
c.gridy = 2;
|
||||||
@ -275,99 +279,8 @@ public class MainWindow extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void displayShortestPathSolution(ShortestPathSolution solution) {
|
private void displayShortestPathSolution(ShortestPathSolution solution) {
|
||||||
JPanel infoPanel = new JPanel();
|
spSolPanel.addSolution(solution);
|
||||||
infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.PAGE_AXIS));
|
spSolPanel.setVisible(true);
|
||||||
infoPanel.setBorder(
|
|
||||||
new CompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK),
|
|
||||||
new EmptyBorder(15, 15, 15, 15)));
|
|
||||||
|
|
||||||
ShortestPathData data = (ShortestPathData) solution.getInstance();
|
|
||||||
|
|
||||||
String info = null;
|
|
||||||
if (solution == null || !solution.isFeasible()) {
|
|
||||||
info = String.format("Shortest path: No path found from node #%d to node #%d.",
|
|
||||||
data.getOrigin().getId(), data.getDestination().getId());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
info = String.format("Shortest path: Found a path from node #%d to node #%d",
|
|
||||||
data.getOrigin().getId(), data.getDestination().getId());
|
|
||||||
if (data.getMode() == Mode.LENGTH) {
|
|
||||||
info = String.format("%s, %.2f kilometers.", info,
|
|
||||||
(solution.getPath().getLength() / 1000.0));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
info = String.format("%s, %.2f minutes.", info,
|
|
||||||
(solution.getPath().getMinimumTravelTime() / 60.0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
infoPanel.add(new JLabel(info));
|
|
||||||
|
|
||||||
if (solution != null && solution.isFeasible()) {
|
|
||||||
infoPanel.add(Box.createVerticalStrut(8));
|
|
||||||
|
|
||||||
PathOverlay overlay = drawing.drawPath(solution.getPath());
|
|
||||||
|
|
||||||
JPanel buttonPanel = new JPanel();
|
|
||||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
|
|
||||||
buttonPanel.add(Box.createHorizontalGlue());
|
|
||||||
JButton clearButton = new JButton("Hide");
|
|
||||||
clearButton.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
private PathOverlay thisOverlay = overlay;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
if (thisOverlay.isVisible()) {
|
|
||||||
thisOverlay.setVisible(false);
|
|
||||||
clearButton.setText("Show");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
thisOverlay.setVisible(true);
|
|
||||||
clearButton.setText("Hide");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JButton saveButton = new JButton("Save");
|
|
||||||
saveButton.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
String filepath = System.getProperty("user.dir");
|
|
||||||
filepath += File.separator
|
|
||||||
+ String.format("path_%#x_%d_%d.path", graph.getMapId(),
|
|
||||||
data.getOrigin().getId(), data.getDestination().getId());
|
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
|
||||||
fileChooser.setSelectedFile(new File(filepath));
|
|
||||||
fileChooser.setApproveButtonText("Save");
|
|
||||||
|
|
||||||
if (fileChooser
|
|
||||||
.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
|
|
||||||
File file = fileChooser.getSelectedFile();
|
|
||||||
try {
|
|
||||||
BinaryPathWriter writer = new BinaryPathWriter(new DataOutputStream(
|
|
||||||
new BufferedOutputStream(new FileOutputStream(file))));
|
|
||||||
writer.writePath(solution.getPath());
|
|
||||||
}
|
|
||||||
catch (IOException e1) {
|
|
||||||
JOptionPane.showMessageDialog(MainWindow.this,
|
|
||||||
"Unable to write path to the selected file.");
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
buttonPanel.add(clearButton);
|
|
||||||
buttonPanel.add(saveButton);
|
|
||||||
infoPanel.add(buttonPanel);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add panel to the right side
|
|
||||||
GridBagConstraints c = new GridBagConstraints();
|
|
||||||
c.gridx = 0;
|
|
||||||
c.gridy = 1;
|
|
||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
|
||||||
((JPanel) mainPanel.getRightComponent()).add(infoPanel, c);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) {
|
private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) {
|
||||||
|
208
src/main/org/insa/graphics/ShortestPathSolutionPanel.java
Normal file
208
src/main/org/insa/graphics/ShortestPathSolutionPanel.java
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
package org.insa.graphics;
|
||||||
|
|
||||||
|
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.util.IdentityHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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.border.CompoundBorder;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
|
import org.insa.algo.shortestpath.ShortestPathData;
|
||||||
|
import org.insa.algo.shortestpath.ShortestPathData.Mode;
|
||||||
|
import org.insa.algo.shortestpath.ShortestPathSolution;
|
||||||
|
import org.insa.graph.Graph;
|
||||||
|
import org.insa.graph.io.BinaryPathWriter;
|
||||||
|
import org.insa.graphics.drawing.Drawing;
|
||||||
|
import org.insa.graphics.drawing.overlays.PathOverlay;
|
||||||
|
|
||||||
|
public class ShortestPathSolutionPanel extends JPanel
|
||||||
|
implements DrawingChangeListener, GraphChangeListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// Parent components
|
||||||
|
Component parent;
|
||||||
|
|
||||||
|
// Solution
|
||||||
|
private Drawing drawing;
|
||||||
|
|
||||||
|
// Solution selector
|
||||||
|
JComboBox<ShortestPathSolution> solutionSelect;
|
||||||
|
|
||||||
|
// Map solution -> panel
|
||||||
|
Map<ShortestPathSolution, JPanel> solutionToPanel = new IdentityHashMap<>();
|
||||||
|
|
||||||
|
public ShortestPathSolutionPanel(Component parent, Drawing drawing) {
|
||||||
|
super();
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
|
||||||
|
setBorder(new CompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK),
|
||||||
|
new EmptyBorder(15, 15, 15, 15)));
|
||||||
|
|
||||||
|
this.parent = parent;
|
||||||
|
this.drawing = drawing;
|
||||||
|
|
||||||
|
// TODO: Create select + Block for JPanel
|
||||||
|
|
||||||
|
solutionSelect = new JComboBox<>(new ShortestPathSolution[0]);
|
||||||
|
solutionSelect.setBackground(Color.WHITE);
|
||||||
|
solutionSelect.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
add(solutionSelect);
|
||||||
|
|
||||||
|
JPanel bottomPanel = new JPanel();
|
||||||
|
bottomPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
add(bottomPanel);
|
||||||
|
|
||||||
|
solutionSelect.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
JComboBox<ShortestPathSolution> combo = (JComboBox<ShortestPathSolution>) e
|
||||||
|
.getSource();
|
||||||
|
ShortestPathSolution solution = (ShortestPathSolution) combo.getSelectedItem();
|
||||||
|
|
||||||
|
bottomPanel.removeAll();
|
||||||
|
bottomPanel.add(solutionToPanel.get(solution));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSolution(ShortestPathSolution solution) {
|
||||||
|
|
||||||
|
// add info panel
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
|
||||||
|
panel.add(createInformationLabel(solution));
|
||||||
|
if (solution != null && solution.isFeasible()) {
|
||||||
|
panel.add(Box.createVerticalStrut(8));
|
||||||
|
panel.add(createPathPanel(solution));
|
||||||
|
}
|
||||||
|
|
||||||
|
solutionToPanel.put(solution, panel);
|
||||||
|
solutionSelect.addItem(solution);
|
||||||
|
solutionSelect.setSelectedItem(solution);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JLabel createInformationLabel(ShortestPathSolution solution) {
|
||||||
|
ShortestPathData data = (ShortestPathData) solution.getInstance();
|
||||||
|
String info = null;
|
||||||
|
if (solution == null || !solution.isFeasible()) {
|
||||||
|
info = String.format("Shortest path: No path found from node #%d to node #%d.",
|
||||||
|
data.getOrigin().getId(), data.getDestination().getId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
info = String.format("Shortest path: Found a path from node #%d to node #%d",
|
||||||
|
data.getOrigin().getId(), data.getDestination().getId());
|
||||||
|
if (data.getMode() == Mode.LENGTH) {
|
||||||
|
info = String.format("%s, %.2f kilometers.", info,
|
||||||
|
(solution.getPath().getLength() / 1000.0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
info = String.format("%s, %.2f minutes.", info,
|
||||||
|
(solution.getPath().getMinimumTravelTime() / 60.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JLabel label = new JLabel(info);
|
||||||
|
label.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
label.setHorizontalAlignment(JLabel.LEFT);
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JPanel createPathPanel(ShortestPathSolution solution) {
|
||||||
|
|
||||||
|
ShortestPathData data = (ShortestPathData) solution.getInstance();
|
||||||
|
|
||||||
|
final PathOverlay overlay = drawing.drawPath(solution.getPath());
|
||||||
|
|
||||||
|
JButton clearButton = new JButton("Hide");
|
||||||
|
clearButton.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (overlay.isVisible()) {
|
||||||
|
overlay.setVisible(false);
|
||||||
|
clearButton.setText("Show");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
overlay.setVisible(true);
|
||||||
|
clearButton.setText("Hide");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
JButton saveButton = new JButton("Save");
|
||||||
|
saveButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
String filepath = System.getProperty("user.dir");
|
||||||
|
filepath += File.separator
|
||||||
|
+ String.format("path_%#x_%d_%d.path", data.getGraph().getMapId(),
|
||||||
|
data.getOrigin().getId(), data.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(solution.getPath());
|
||||||
|
}
|
||||||
|
catch (IOException e1) {
|
||||||
|
JOptionPane.showMessageDialog(parent,
|
||||||
|
"Unable to write path to the selected file.");
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
|
||||||
|
buttonPanel.add(Box.createHorizontalGlue());
|
||||||
|
buttonPanel.add(clearButton);
|
||||||
|
buttonPanel.add(saveButton);
|
||||||
|
|
||||||
|
buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
|
||||||
|
return buttonPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void newGraphLoaded(Graph graph) {
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawingLoaded(Drawing oldDrawing, Drawing newDrawing) {
|
||||||
|
if (newDrawing != drawing) {
|
||||||
|
drawing = newDrawing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRedrawRequest() {
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user