Create new solution panel.

This commit is contained in:
Mikael Capelle 2018-03-01 19:51:37 +01:00
parent 8bca08f795
commit 08fd7120f2
2 changed files with 222 additions and 101 deletions

View File

@ -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) {

View 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:
}
}