Update solution panel.
This commit is contained in:
parent
08fd7120f2
commit
5d28e12903
@ -9,8 +9,6 @@ import java.io.DataOutputStream;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.IdentityHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
@ -32,25 +30,81 @@ import org.insa.graph.io.BinaryPathWriter;
|
|||||||
import org.insa.graphics.drawing.Drawing;
|
import org.insa.graphics.drawing.Drawing;
|
||||||
import org.insa.graphics.drawing.overlays.PathOverlay;
|
import org.insa.graphics.drawing.overlays.PathOverlay;
|
||||||
|
|
||||||
public class ShortestPathSolutionPanel extends JPanel
|
public class ShortestPathSolutionPanel extends JPanel implements DrawingChangeListener, GraphChangeListener {
|
||||||
implements DrawingChangeListener, GraphChangeListener {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
// Parent components
|
private class ShortestPathBundle {
|
||||||
Component parent;
|
|
||||||
|
// Solution
|
||||||
|
private final ShortestPathSolution solution;
|
||||||
|
|
||||||
|
// Path Overlay (not final due to redraw)
|
||||||
|
private PathOverlay overlay = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new bundle with the given solution and create a new overlay
|
||||||
|
* corresponding to the solution (if the solution is feasible).
|
||||||
|
*
|
||||||
|
* @param solution Solution for this bundle, must not be null.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public ShortestPathBundle(ShortestPathSolution solution) {
|
||||||
|
this.solution = solution;
|
||||||
|
if (this.solution.isFeasible()) {
|
||||||
|
this.overlay = drawing.drawPath(this.solution.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Solution associated with this bundle.
|
||||||
|
*/
|
||||||
|
public ShortestPathSolution getSolution() {
|
||||||
|
return this.solution;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Data assocaited with this bundle.
|
||||||
|
*/
|
||||||
|
public ShortestPathData getData() {
|
||||||
|
return (ShortestPathData) this.solution.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Overlay associated with this bundle, or null.
|
||||||
|
*/
|
||||||
|
public PathOverlay getOverlay() {
|
||||||
|
return this.overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Solution
|
// Solution
|
||||||
private Drawing drawing;
|
private Drawing drawing;
|
||||||
|
|
||||||
// Solution selector
|
// Solution selector
|
||||||
JComboBox<ShortestPathSolution> solutionSelect;
|
private final JComboBox<ShortestPathBundle> solutionSelect;
|
||||||
|
|
||||||
// Map solution -> panel
|
// Map solution -> panel
|
||||||
Map<ShortestPathSolution, JPanel> solutionToPanel = new IdentityHashMap<>();
|
private final JLabel informationPanel;
|
||||||
|
|
||||||
|
// Current bundle
|
||||||
|
private ShortestPathBundle currentBundle = null;
|
||||||
|
|
||||||
public ShortestPathSolutionPanel(Component parent, Drawing drawing) {
|
public ShortestPathSolutionPanel(Component parent, Drawing drawing) {
|
||||||
super();
|
super();
|
||||||
@ -58,87 +112,29 @@ public class ShortestPathSolutionPanel extends JPanel
|
|||||||
setBorder(new CompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK),
|
setBorder(new CompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK),
|
||||||
new EmptyBorder(15, 15, 15, 15)));
|
new EmptyBorder(15, 15, 15, 15)));
|
||||||
|
|
||||||
this.parent = parent;
|
|
||||||
this.drawing = drawing;
|
this.drawing = drawing;
|
||||||
|
|
||||||
// TODO: Create select + Block for JPanel
|
// TODO: Create select + Block for JPanel
|
||||||
|
|
||||||
solutionSelect = new JComboBox<>(new ShortestPathSolution[0]);
|
solutionSelect = new JComboBox<>();
|
||||||
solutionSelect.setBackground(Color.WHITE);
|
solutionSelect.setBackground(Color.WHITE);
|
||||||
solutionSelect.setAlignmentX(Component.LEFT_ALIGNMENT);
|
solutionSelect.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
add(solutionSelect);
|
add(solutionSelect);
|
||||||
|
|
||||||
JPanel bottomPanel = new JPanel();
|
informationPanel = new JLabel();
|
||||||
bottomPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
informationPanel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
|
||||||
add(bottomPanel);
|
informationPanel.setHorizontalAlignment(JLabel.LEFT);
|
||||||
|
add(informationPanel);
|
||||||
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");
|
JButton clearButton = new JButton("Hide");
|
||||||
clearButton.addActionListener(new ActionListener() {
|
clearButton.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
PathOverlay overlay = currentBundle.getOverlay();
|
||||||
|
if (overlay == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (overlay.isVisible()) {
|
if (overlay.isVisible()) {
|
||||||
overlay.setVisible(false);
|
overlay.setVisible(false);
|
||||||
clearButton.setText("Show");
|
clearButton.setText("Show");
|
||||||
@ -149,14 +145,15 @@ public class ShortestPathSolutionPanel extends JPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
JButton saveButton = new JButton("Save");
|
JButton saveButton = new JButton("Save");
|
||||||
saveButton.addActionListener(new ActionListener() {
|
saveButton.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
String filepath = System.getProperty("user.dir");
|
String filepath = System.getProperty("user.dir");
|
||||||
filepath += File.separator
|
filepath += File.separator + String.format("path_%#x_%d_%d.path",
|
||||||
+ String.format("path_%#x_%d_%d.path", data.getGraph().getMapId(),
|
currentBundle.getData().getGraph().getMapId(), currentBundle.getData().getOrigin().getId(),
|
||||||
data.getOrigin().getId(), data.getDestination().getId());
|
currentBundle.getData().getDestination().getId());
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
JFileChooser fileChooser = new JFileChooser();
|
||||||
fileChooser.setSelectedFile(new File(filepath));
|
fileChooser.setSelectedFile(new File(filepath));
|
||||||
fileChooser.setApproveButtonText("Save");
|
fileChooser.setApproveButtonText("Save");
|
||||||
@ -164,13 +161,12 @@ public class ShortestPathSolutionPanel extends JPanel
|
|||||||
if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
|
if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
|
||||||
File file = fileChooser.getSelectedFile();
|
File file = fileChooser.getSelectedFile();
|
||||||
try {
|
try {
|
||||||
BinaryPathWriter writer = new BinaryPathWriter(new DataOutputStream(
|
BinaryPathWriter writer = new BinaryPathWriter(
|
||||||
new BufferedOutputStream(new FileOutputStream(file))));
|
new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))));
|
||||||
writer.writePath(solution.getPath());
|
writer.writePath(currentBundle.getSolution().getPath());
|
||||||
}
|
}
|
||||||
catch (IOException e1) {
|
catch (IOException e1) {
|
||||||
JOptionPane.showMessageDialog(parent,
|
JOptionPane.showMessageDialog(parent, "Unable to write path to the selected file.");
|
||||||
"Unable to write path to the selected file.");
|
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,15 +178,63 @@ public class ShortestPathSolutionPanel extends JPanel
|
|||||||
buttonPanel.add(Box.createHorizontalGlue());
|
buttonPanel.add(Box.createHorizontalGlue());
|
||||||
buttonPanel.add(clearButton);
|
buttonPanel.add(clearButton);
|
||||||
buttonPanel.add(saveButton);
|
buttonPanel.add(saveButton);
|
||||||
|
|
||||||
buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
add(buttonPanel);
|
||||||
|
|
||||||
return buttonPanel;
|
solutionSelect.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
|
ShortestPathBundle bundle = (ShortestPathBundle) solutionSelect.getSelectedItem();
|
||||||
|
|
||||||
|
if (currentBundle.getOverlay() != null) {
|
||||||
|
currentBundle.getOverlay().setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonPanel.setVisible(bundle.getSolution().isFeasible());
|
||||||
|
clearButton.setText(bundle.getSolution().isFeasible() ? "Hide" : "Show");
|
||||||
|
|
||||||
|
if (bundle.getOverlay() != null) {
|
||||||
|
bundle.getOverlay().setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentBundle = bundle;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSolution(ShortestPathSolution solution) {
|
||||||
|
ShortestPathBundle bundle = new ShortestPathBundle(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("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,
|
||||||
|
(bundle.getSolution().getPath().getLength() / 1000.0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
info = String.format("%s, %.2f minutes.", info,
|
||||||
|
(bundle.getSolution().getPath().getMinimumTravelTime() / 60.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
informationPanel.setText(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void newGraphLoaded(Graph graph) {
|
public void newGraphLoaded(Graph graph) {
|
||||||
// TODO:
|
this.solutionSelect.removeAllItems();
|
||||||
|
this.currentBundle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -202,7 +246,9 @@ public class ShortestPathSolutionPanel extends JPanel
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRedrawRequest() {
|
public void onRedrawRequest() {
|
||||||
// TODO:
|
for (int i = 0; i < this.solutionSelect.getItemCount(); ++i) {
|
||||||
|
this.solutionSelect.getItemAt(i).updateOverlay(drawing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user