123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892 |
- package org.insa.graphics;
-
- 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;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.io.BufferedInputStream;
- import java.io.DataInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.prefs.Preferences;
-
- import javax.swing.BorderFactory;
- import javax.swing.Box;
- import javax.swing.BoxLayout;
- import javax.swing.JButton;
- import javax.swing.JFileChooser;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JMenu;
- import javax.swing.JMenuBar;
- import javax.swing.JMenuItem;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.JScrollPane;
- import javax.swing.JSplitPane;
- import javax.swing.JTextArea;
- import javax.swing.KeyStroke;
- import javax.swing.SwingConstants;
- import javax.swing.Timer;
- import javax.swing.UIManager;
- import javax.swing.border.CompoundBorder;
- import javax.swing.border.EmptyBorder;
- import javax.swing.filechooser.FileNameExtensionFilter;
-
- import org.insa.algo.AbstractSolution;
- import org.insa.algo.AlgorithmFactory;
- import org.insa.algo.carpooling.CarPoolingAlgorithm;
- import org.insa.algo.packageswitch.PackageSwitchAlgorithm;
- import org.insa.algo.shortestpath.ShortestPathAlgorithm;
- import org.insa.algo.shortestpath.ShortestPathData;
- import org.insa.algo.shortestpath.ShortestPathGraphicObserver;
- import org.insa.algo.shortestpath.ShortestPathSolution;
- import org.insa.algo.shortestpath.ShortestPathTextObserver;
- import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver;
- 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.Path;
- import org.insa.graph.io.BinaryGraphReader;
- import org.insa.graph.io.BinaryPathReader;
- import org.insa.graph.io.GraphReader;
- import org.insa.graph.io.MapMismatchException;
- import org.insa.graphics.AlgorithmPanel.StartActionEvent;
- import org.insa.graphics.drawing.BasicGraphPalette;
- import org.insa.graphics.drawing.BlackAndWhiteGraphPalette;
- import org.insa.graphics.drawing.Drawing;
- import org.insa.graphics.drawing.GraphPalette;
- import org.insa.graphics.drawing.components.BasicDrawing;
- import org.insa.graphics.drawing.components.MapViewDrawing;
-
- public class MainWindow extends JFrame {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- /**
- *
- */
- private static final String WINDOW_TITLE = "BE Graphes INSA";
-
- /**
- *
- */
- private static final int THREAD_TIMER_DELAY = 1000; // in milliseconds
-
- private static final String DEFAULT_MAP_FOLDER_KEY = "DefaultMapFolder";
- private static final String DEFAULT_MAP_FOLDER_INSA = "/home/commetud/...";
-
- private static final String DEFAULT_PATH_FOLDER_KEY = "DefaultPathFolder";
- private static final String DEFAULT_PATH_FOLDER_INSA = "/home/commetud/...";
-
- // Preferences
- private Preferences preferences = Preferences.userRoot().node(getClass().getName());
-
- // Current graph.
- protected Graph graph;
-
- // Path to the last opened graph file.
- private String graphFilePath;
-
- // Drawing and click adapter.
- protected Drawing drawing;
- private final MapViewDrawing mapViewDrawing;
- private final BasicDrawing basicDrawing;
-
- private final GraphPalette basicPalette, blackAndWhitePalette;
- private GraphPalette currentPalette;
-
- // Main panel.
- private final JSplitPane mainPanel;
-
- // Algorithm panels
- private final List<AlgorithmPanel> algoPanels = new ArrayList<>();
- private final AlgorithmPanel wccPanel, spPanel, cpPanel, psPanel;
-
- // Path panel
- private final PathsPanel pathPanel;
-
- // List of items that cannot be used without a graph
- private final ArrayList<JMenuItem> graphLockItems = new ArrayList<JMenuItem>();
-
- // Label containing the map ID of the current graph.
- private JLabel graphInfoPanel;
-
- // Thread information
- private Timer threadTimer;
- private JPanel threadPanel;
-
- // Log stream and print stream
- private StreamCapturer logStream;
-
- private PrintStream printStream;
-
- // Current running thread
- private ThreadWrapper currentThread;
-
- // Factory
- private BlockingActionFactory baf;
-
- // Observers
- private List<DrawingChangeListener> drawingChangeListeners = new ArrayList<>();
- private List<GraphChangeListener> graphChangeListeneres = new ArrayList<>();
-
- public MainWindow() {
- super(WINDOW_TITLE);
-
- setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
- setLayout(new BorderLayout());
-
- setMinimumSize(new Dimension(800, 600));
-
- // Create drawing and action listeners...
- this.basicDrawing = new BasicDrawing();
- this.mapViewDrawing = new MapViewDrawing();
- this.drawing = basicDrawing;
-
- // Createa palettes
- this.basicPalette = new BasicGraphPalette();
- this.blackAndWhitePalette = new BlackAndWhiteGraphPalette();
- this.currentPalette = this.basicPalette;
-
- wccPanel = new AlgorithmPanel(this, WeaklyConnectedComponentsAlgorithm.class,
- "Weakly-Connected Components", new String[] {}, false, false);
- wccPanel.addStartActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- StartActionEvent evt = (StartActionEvent) e;
- WeaklyConnectedComponentsData data = new WeaklyConnectedComponentsData(graph);
-
- WeaklyConnectedComponentsAlgorithm wccAlgorithm = null;
- try {
- wccAlgorithm = (WeaklyConnectedComponentsAlgorithm) AlgorithmFactory
- .createAlgorithm(evt.getAlgorithmClass(), data);
- }
- catch (Exception e1) {
- JOptionPane.showMessageDialog(MainWindow.this,
- "An error occurred while creating the specified algorithm.",
- "Internal error: Algorithm instantiation failure",
- JOptionPane.ERROR_MESSAGE);
- e1.printStackTrace();
- return;
- }
-
- wccPanel.setEnabled(false);
-
- if (evt.isGraphicVisualizationEnabled()) {
- wccAlgorithm.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing));
- }
- if (evt.isTextualVisualizationEnabled()) {
- wccAlgorithm.addObserver(new WeaklyConnectedComponentTextObserver(printStream));
- }
-
- // We love Java...
- final WeaklyConnectedComponentsAlgorithm copyAlgorithm = wccAlgorithm;
- launchThread(new Runnable() {
- @Override
- public void run() {
- AbstractSolution solution = copyAlgorithm.run();
- wccPanel.solutionPanel.addSolution(solution, false);
- wccPanel.solutionPanel.setVisible(true);
- wccPanel.setEnabled(true);
- }
- });
- }
- });
-
- spPanel = new AlgorithmPanel(this, ShortestPathAlgorithm.class, "Shortest-Path",
- new String[] { "Origin", "Destination" }, true, true);
- spPanel.addStartActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- StartActionEvent evt = (StartActionEvent) e;
- ShortestPathData data = new ShortestPathData(graph, evt.getNodes().get(0),
- evt.getNodes().get(1), evt.getMode(), evt.getArcFilter());
-
- ShortestPathAlgorithm spAlgorithm = null;
- try {
- spAlgorithm = (ShortestPathAlgorithm) AlgorithmFactory
- .createAlgorithm(evt.getAlgorithmClass(), data);
- }
- catch (Exception e1) {
- JOptionPane.showMessageDialog(MainWindow.this,
- "An error occurred while creating the specified algorithm.",
- "Internal error: Algorithm instantiation failure",
- JOptionPane.ERROR_MESSAGE);
- e1.printStackTrace();
- return;
- }
-
- spPanel.setEnabled(false);
-
- if (evt.isGraphicVisualizationEnabled()) {
- spAlgorithm.addObserver(new ShortestPathGraphicObserver(drawing));
- }
- if (evt.isTextualVisualizationEnabled()) {
- spAlgorithm.addObserver(new ShortestPathTextObserver(printStream));
- }
-
- final ShortestPathAlgorithm copyAlgorithm = spAlgorithm;
- launchThread(new Runnable() {
- @Override
- public void run() {
- // Run the algorithm.
- ShortestPathSolution solution = copyAlgorithm.run();
- // Add the solution to the solution panel (but do not display
- // overlay).
- spPanel.solutionPanel.addSolution(solution, false);
- // If the solution is feasible, add the path to the path panel.
- if (solution.isFeasible()) {
- pathPanel.addPath(solution.getPath());
- }
- // Show the solution panel and enable the shortest-path panel.
- spPanel.solutionPanel.setVisible(true);
- spPanel.setEnabled(true);
- }
- });
- }
- });
-
- cpPanel = new AlgorithmPanel(
- this, CarPoolingAlgorithm.class, "Car-Pooling", new String[] { "Origin Car",
- "Origin Pedestrian", "Destination Car", "Destination Pedestrian" },
- true, true);
-
- psPanel = new AlgorithmPanel(this, PackageSwitchAlgorithm.class, "Car-Pooling",
- new String[] { "Oribin A", "Origin B", "Destination A", "Destination B" }, true,
- true);
-
- // add algorithm panels
- algoPanels.add(wccPanel);
- algoPanels.add(spPanel);
- algoPanels.add(cpPanel);
- algoPanels.add(psPanel);
-
- this.pathPanel = new PathsPanel(this);
-
- // Add click listeners to both drawing.
-
- for (AlgorithmPanel panel: algoPanels) {
- this.basicDrawing.addDrawingClickListener(panel.nodesInputPanel);
- this.mapViewDrawing.addDrawingClickListener(panel.nodesInputPanel);
- this.graphChangeListeneres.add(panel.nodesInputPanel);
- this.graphChangeListeneres.add(panel.solutionPanel);
- this.drawingChangeListeners.add(panel.nodesInputPanel);
- this.drawingChangeListeners.add(panel.solutionPanel);
- this.drawingChangeListeners.add(panel);
- }
-
- this.graphChangeListeneres.add(pathPanel);
- this.drawingChangeListeners.add(pathPanel);
-
- // Create action factory.
- this.currentThread = new ThreadWrapper(this);
- this.baf = new BlockingActionFactory(this);
- this.baf.addAction(currentThread);
-
- // Click adapter
- ActionListener openMapActionListener = new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- JFileChooser chooser = new JFileChooser();
- FileNameExtensionFilter filter = new FileNameExtensionFilter("Graph files",
- "mapgr");
- File mapFolder = new File(
- preferences.get(DEFAULT_MAP_FOLDER_KEY, DEFAULT_MAP_FOLDER_INSA));
- if (!mapFolder.exists()) {
- mapFolder = new File(System.getProperty("user.dir"));
- }
- chooser.setCurrentDirectory(mapFolder);
- chooser.setFileFilter(filter);
- if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
- graphFilePath = chooser.getSelectedFile().getAbsolutePath();
-
- // Check...
- if (chooser.getSelectedFile().exists()) {
- preferences.put(DEFAULT_MAP_FOLDER_KEY,
- chooser.getSelectedFile().getParent());
- }
-
- DataInputStream stream;
- try {
- stream = new DataInputStream(new BufferedInputStream(
- new FileInputStream(chooser.getSelectedFile())));
- }
- catch (IOException e1) {
- JOptionPane.showMessageDialog(MainWindow.this,
- "Cannot open the selected file.");
- return;
- }
- loadGraph(new BinaryGraphReader(stream));
- }
- }
- };
-
- setJMenuBar(createMenuBar(openMapActionListener));
-
- // Initial panel to show "Open Map... "
- JPanel openPanel = new JPanel();
- openPanel.setLayout(new BoxLayout(openPanel, BoxLayout.PAGE_AXIS));
- JButton openButton = new JButton("Open Map... ");
- openButton.setAlignmentX(Component.CENTER_ALIGNMENT);
- openButton.addActionListener(openMapActionListener);
- openButton.setFocusPainted(false);
- openPanel.add(Box.createVerticalGlue());
- openPanel.add(openButton);
- openPanel.add(Box.createVerticalGlue());
-
- addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- int confirmed = JOptionPane.showConfirmDialog(MainWindow.this,
- "Are you sure you want to close the application?", "Exit Confirmation",
- JOptionPane.YES_NO_OPTION);
-
- if (confirmed == JOptionPane.YES_OPTION) {
- dispose();
- System.exit(0);
- }
- }
- });
-
- // Create graph area
- mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
-
- JTextArea infoPanel = new JTextArea();
- infoPanel.setMinimumSize(new Dimension(200, 50));
- infoPanel.setBackground(Color.WHITE);
- infoPanel.setLineWrap(true);
- infoPanel.setEditable(false);
- 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 = 0;
- c.fill = GridBagConstraints.HORIZONTAL;
- rightComponent.add(pathPanel, c);
-
- c.gridy = 1;
- for (AlgorithmPanel panel: algoPanels) {
- panel.setVisible(false);
- rightComponent.add(panel, c);
- }
-
- c = new GridBagConstraints();
- c.gridx = 0;
- c.gridy = 2;
- 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(openPanel);
- mainPanel.setRightComponent(rightComponent);
- this.add(mainPanel, BorderLayout.CENTER);
-
- // Top Panel
- this.add(createStatusBar(), BorderLayout.SOUTH);
-
- // Notify everythin
- notifyDrawingLoaded(null, drawing);
- }
-
- /**
- * @param runnable
- * @param canInterrupt
- */
- private void launchThread(Runnable runnable, boolean canInterrupt) {
- if (canInterrupt) {
- currentThread.setThread(new Thread(new Runnable() {
- @Override
- public void run() {
- threadTimer.restart();
- threadPanel.setVisible(true);
- runnable.run();
- clearCurrentThread();
- }
- }));
- }
- else {
- currentThread.setThread(new Thread(runnable));
- }
- currentThread.startThread();
- }
-
- private void launchThread(Runnable runnable) {
- launchThread(runnable, true);
- }
-
- protected void clearCurrentThread() {
- threadTimer.stop();
- threadPanel.setVisible(false);
- currentThread.setThread(null);
- if (spPanel.isVisible()) {
- spPanel.setEnabled(true);
- }
- }
-
- /**
- * Notify all listeners that a new graph has been loaded.
- */
- private void notifyNewGraphLoaded() {
- for (GraphChangeListener listener: graphChangeListeneres) {
- listener.newGraphLoaded(graph);
- }
- }
-
- /**
- * Notify all listeners that a new drawing has been set up.
- *
- * @param oldDrawing
- * @param newDrawing
- */
- private void notifyDrawingLoaded(Drawing oldDrawing, Drawing newDrawing) {
- for (DrawingChangeListener listener: drawingChangeListeners) {
- listener.onDrawingLoaded(oldDrawing, newDrawing);
- }
- }
-
- /**
- * Notify all listeners that a redraw request is emitted.
- */
- private void notifyRedrawRequest() {
- for (DrawingChangeListener listener: drawingChangeListeners) {
- listener.onRedrawRequest();
- }
- }
-
- /**
- * Draw the stored graph on the drawing.
- */
- private void drawGraph(Class<? extends Drawing> newClass, GraphPalette palette) {
-
- // Save old divider location
- int oldLocation = mainPanel.getDividerLocation();
-
- // Set drawing if not set
- if (!(mainPanel.getLeftComponent() instanceof Drawing)) {
- mainPanel.setLeftComponent((Component) this.drawing);
- mainPanel.setDividerLocation(oldLocation);
- }
-
- boolean isNewGraph = newClass == null;
- boolean isMapView = (isNewGraph && drawing == mapViewDrawing)
- || (!isNewGraph && newClass.equals(MapViewDrawing.class));
-
- // We need to draw MapView, we have to check if the file exists.
- File mfile = null;
- if (isMapView) {
- String mfpath = graphFilePath.substring(0, graphFilePath.lastIndexOf(".map"))
- + ".mapfg";
- mfile = new File(mfpath);
- if (!mfile.exists()) {
- if (JOptionPane.showConfirmDialog(this,
- "The associated mapsforge (.mapfg) file has not been found, do you want to specify it manually?",
- "File not found",
- JOptionPane.YES_NO_CANCEL_OPTION) == JOptionPane.YES_OPTION) {
- JFileChooser chooser = new JFileChooser(mfile.getParentFile());
- if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
- mfile = chooser.getSelectedFile();
- }
- else {
- mfile = null;
- }
- }
- else {
- mfile = null;
- }
- }
- }
-
- Runnable runnable = null;
-
- if (isMapView && mfile != null) {
- final File mfileFinal = mfile;
- // It is a mapview drawing and the file was found, so:
- // 1. We create the drawing if necessary.
- if (drawing != mapViewDrawing) {
- drawing.clear();
- drawing = mapViewDrawing;
- mainPanel.setLeftComponent(mapViewDrawing);
- mainPanel.setDividerLocation(oldLocation);
- notifyDrawingLoaded(basicDrawing, mapViewDrawing);
- drawing.clear();
- isNewGraph = true;
- }
- if (isNewGraph) {
- drawing.clear();
- runnable = new Runnable() {
- public void run() {
- ((MapViewDrawing) drawing).drawGraph(mfileFinal);
- notifyRedrawRequest();
- }
- };
- }
-
- }
- else if (!isMapView || (isMapView && mfile == null && isNewGraph)) {
- if (drawing == mapViewDrawing) {
- mapViewDrawing.clear();
- drawing = basicDrawing;
- mainPanel.setLeftComponent(basicDrawing);
- mainPanel.setDividerLocation(oldLocation);
- notifyDrawingLoaded(mapViewDrawing, basicDrawing);
- isNewGraph = true;
- }
- if (isNewGraph || palette != this.currentPalette) {
- this.currentPalette = palette;
- drawing.clear();
- runnable = new Runnable() {
- public void run() {
- drawing.drawGraph(graph, palette);
- notifyRedrawRequest();
- }
- };
- }
- }
-
- if (runnable != null) {
- launchThread(runnable, false);
- }
- else {
- drawing.clearOverlays();
- notifyRedrawRequest();
- }
-
- }
-
- /**
- * @param newClass
- */
- private void drawGraph(Class<? extends Drawing> newClass) {
- drawGraph(newClass, new BasicGraphPalette());
- }
-
- /**
- *
- */
- private void drawGraph() {
- drawGraph(null, this.currentPalette);
- }
-
- private void loadGraph(GraphReader reader) {
- launchThread(new Runnable() {
- @Override
- public void run() {
- GraphReaderProgressBar progressBar = new GraphReaderProgressBar(MainWindow.this);
- progressBar.setLocationRelativeTo(mainPanel.getLeftComponent());
- reader.addObserver(progressBar);
- try {
- graph = reader.read();
- System.out.flush();
- }
- catch (Exception exception) {
- progressBar.setVisible(false);
- progressBar = null;
- JOptionPane.showMessageDialog(MainWindow.this,
- "Unable to read graph from the selected file.");
- exception.printStackTrace(System.out);
- return;
- }
-
- String info = graph.getMapId();
- if (graph.getMapName() != null && !graph.getMapName().isEmpty()) {
- // The \u200e character is the left-to-right mark, we need to avoid issue with
- // name that are right-to-left (e.g. arabic names).
- info += " - " + graph.getMapName() + "\u200e";
- }
- info += ", " + graph.getNodes().size() + " nodes";
- graphInfoPanel.setText(info);
-
- drawGraph();
-
- notifyNewGraphLoaded();
-
- for (JMenuItem item: graphLockItems) {
- item.setEnabled(true);
- }
- }
- }, false);
- }
-
- /**
- * Show and enable the given AlgorithmPanel (and hide all others).
- *
- * @param algorithmPanel
- */
- private void enableAlgorithmPanel(AlgorithmPanel algorithmPanel) {
- int dividerLocation = mainPanel.getDividerLocation();
- for (AlgorithmPanel panel: algoPanels) {
- panel.setVisible(panel == algorithmPanel);
- }
- mainPanel.setDividerLocation(dividerLocation);
- }
-
- private JMenuBar createMenuBar(ActionListener openMapActionListener) {
-
- // Open Map item...
- JMenuItem openMapItem = new JMenuItem("Open Map... ", KeyEvent.VK_O);
- openMapItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK));
- openMapItem.addActionListener(baf.createBlockingAction(openMapActionListener));
-
- // Open Path item...
- JMenuItem openPathItem = new JMenuItem("Open Path... ", KeyEvent.VK_P);
- openPathItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.ALT_MASK));
- openPathItem.addActionListener(baf.createBlockingAction(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- JFileChooser chooser = new JFileChooser();
- FileNameExtensionFilter filter = new FileNameExtensionFilter(
- "Path & compressed path files", "path");
- File pathFolder = new File(
- preferences.get(DEFAULT_PATH_FOLDER_KEY, DEFAULT_PATH_FOLDER_INSA));
- if (!pathFolder.exists()) {
- pathFolder = new File(System.getProperty("user.dir"));
- }
- chooser.setCurrentDirectory(pathFolder);
- chooser.setFileFilter(filter);
- if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
-
- // Check & Update
- if (chooser.getSelectedFile().exists()) {
- preferences.put(DEFAULT_PATH_FOLDER_KEY,
- chooser.getSelectedFile().getParent());
- }
-
- BinaryPathReader reader;
- try {
- reader = new BinaryPathReader(new DataInputStream(new BufferedInputStream(
- new FileInputStream(chooser.getSelectedFile()))));
- }
- catch (IOException e1) {
- JOptionPane.showMessageDialog(MainWindow.this,
- "Cannot open the selected file.");
- return;
- }
- try {
- Path path = reader.readPath(graph);
- pathPanel.addPath(path);
- }
- catch (MapMismatchException exception) {
- JOptionPane.showMessageDialog(MainWindow.this,
- "The selected file does not contain a path for the current graph.");
- return;
- }
- catch (Exception exception) {
- JOptionPane.showMessageDialog(MainWindow.this,
- "Unable to read path from the selected file.");
- return;
- }
- }
- }
- }));
- graphLockItems.add(openPathItem);
-
- // Close item
- JMenuItem closeItem = new JMenuItem("Quit", KeyEvent.VK_Q);
- closeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.ALT_MASK));
- closeItem.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- MainWindow.this.dispatchEvent(
- new WindowEvent(MainWindow.this, WindowEvent.WINDOW_CLOSING));
- }
- });
-
- // Build the first menu.
- JMenu fileMenu = new JMenu("File");
- fileMenu.add(openMapItem);
- fileMenu.add(openPathItem);
- fileMenu.addSeparator();
- fileMenu.add(closeItem);
-
- // Second menu
- JMenuItem drawGraphItem = new JMenuItem("Redraw", KeyEvent.VK_R);
- drawGraphItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.ALT_MASK));
- drawGraphItem.addActionListener(baf.createBlockingAction(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- drawGraph(BasicDrawing.class, basicPalette);
- }
- }));
- graphLockItems.add(drawGraphItem);
- JMenuItem drawGraphBWItem = new JMenuItem("Redraw (B&W)", KeyEvent.VK_B);
- drawGraphBWItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.ALT_MASK));
- drawGraphBWItem.addActionListener(baf.createBlockingAction(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- drawGraph(BasicDrawing.class, blackAndWhitePalette);
- }
- }));
- graphLockItems.add(drawGraphBWItem);
- JMenuItem drawGraphMapsforgeItem = new JMenuItem("Redraw (Map)", KeyEvent.VK_M);
- drawGraphMapsforgeItem
- .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.ALT_MASK));
- drawGraphMapsforgeItem.addActionListener(baf.createBlockingAction(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- drawGraph(MapViewDrawing.class);
- }
- }));
- graphLockItems.add(drawGraphMapsforgeItem);
-
- JMenu graphMenu = new JMenu("Graph");
- graphMenu.add(drawGraphItem);
- graphMenu.add(drawGraphBWItem);
- graphMenu.addSeparator();
- graphMenu.add(drawGraphMapsforgeItem);
-
- // Algo menu
- JMenu algoMenu = new JMenu("Algorithms");
-
- // Weakly connected components
- JMenuItem wccItem = new JMenuItem("Weakly Connected Components");
- wccItem.addActionListener(baf.createBlockingAction(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- enableAlgorithmPanel(wccPanel);
- }
- }));
-
- // Shortest path
- JMenuItem spItem = new JMenuItem("Shortest-Path");
- spItem.addActionListener(baf.createBlockingAction(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- enableAlgorithmPanel(spPanel);
- }
- }));
-
- // Car pooling
- JMenuItem cpItem = new JMenuItem("Car Pooling");
- cpItem.addActionListener(baf.createBlockingAction(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- enableAlgorithmPanel(cpPanel);
- }
- }));
-
- // Car pooling
- JMenuItem psItem = new JMenuItem("Package Switch");
- psItem.addActionListener(baf.createBlockingAction(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- enableAlgorithmPanel(psPanel);
- }
- }));
-
- graphLockItems.add(wccItem);
- graphLockItems.add(spItem);
- graphLockItems.add(cpItem);
- graphLockItems.add(psItem);
-
- algoMenu.add(wccItem);
- algoMenu.addSeparator();
- algoMenu.add(spItem);
- algoMenu.add(cpItem);
- algoMenu.add(psItem);
-
- // Create the menu bar.
- JMenuBar menuBar = new JMenuBar();
-
- menuBar.add(fileMenu);
- menuBar.add(graphMenu);
- menuBar.add(algoMenu);
-
- for (JMenuItem item: graphLockItems) {
- item.setEnabled(false);
- }
-
- return menuBar;
- }
-
- private JPanel createStatusBar() {
- // create the status bar panel and shove it down the bottom of the frame
- JPanel statusPanel = new JPanel();
- statusPanel.setBorder(
- new CompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY),
- new EmptyBorder(0, 15, 0, 15)));
- statusPanel.setPreferredSize(new Dimension(getWidth(), 38));
- statusPanel.setLayout(new BorderLayout());
-
- graphInfoPanel = new JLabel();
- graphInfoPanel.setHorizontalAlignment(SwingConstants.LEFT);
- statusPanel.add(graphInfoPanel, BorderLayout.WEST);
-
- JLabel threadInfo = new JLabel("Thread running... ");
- JLabel threadTimerLabel = new JLabel("00:00:00");
- JButton threadButton = new JButton("Stop");
- threadButton.addActionListener(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if (currentThread.isRunning()) {
- int confirmed = JOptionPane.showConfirmDialog(MainWindow.this,
- "Are you sure you want to kill the running thread?",
- "Kill Confirmation", JOptionPane.YES_NO_OPTION);
- if (confirmed == JOptionPane.YES_OPTION) {
- currentThread.interrupt();
- }
- }
- }
- });
-
- threadTimer = new Timer(THREAD_TIMER_DELAY, new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- long seconds = currentThread.getDuration().getSeconds();
- threadTimerLabel.setText(String.format("%02d:%02d:%02d", seconds / 3600,
- seconds / 60 % 60, seconds % 60));
- }
- });
- threadTimer.setInitialDelay(0);
-
- threadPanel = new JPanel();
- threadPanel.add(threadInfo);
- threadPanel.add(threadTimerLabel);
- threadPanel.add(threadButton);
- threadPanel.setVisible(false);
- statusPanel.add(threadPanel, BorderLayout.EAST);
-
- return statusPanel;
- }
-
- public static void main(final String[] args) {
-
- // Try to set system look and feel.
- try {
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- }
- catch (Exception e) {
- }
-
- MainWindow w = new MainWindow();
- w.setExtendedState(JFrame.MAXIMIZED_BOTH);
- w.setVisible(true);
- }
-
- }
|