Fix output stream in textarea. Add blocking actions.
This commit is contained in:
		
							parent
							
								
									0514c627b4
								
							
						
					
					
						commit
						ca94ddf7ff
					
				
					 7 changed files with 315 additions and 119 deletions
				
			
		
							
								
								
									
										58
									
								
								src/main/org/insa/graphics/BlockingActionFactory.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/main/org/insa/graphics/BlockingActionFactory.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.awt.Component; | ||||
| import java.awt.event.ActionEvent; | ||||
| import java.awt.event.ActionListener; | ||||
| import java.util.ArrayList; | ||||
| 
 | ||||
| import javax.swing.JOptionPane; | ||||
| 
 | ||||
| public class BlockingActionFactory { | ||||
| 
 | ||||
|     // List of running actions. | ||||
|     private ArrayList<RunningAction> actions = new ArrayList<>(); | ||||
| 
 | ||||
|     // Parent component. | ||||
|     private Component parentComponent; | ||||
| 
 | ||||
|     public BlockingActionFactory(Component parentComponent) { | ||||
|         this.parentComponent = parentComponent; | ||||
|     } | ||||
| 
 | ||||
|     public void addAction(RunningAction action) { | ||||
|         actions.add(action); | ||||
|     } | ||||
| 
 | ||||
|     public ActionListener createBlockingAction(ActionListener listener) { | ||||
|         return new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 boolean accepted = true; | ||||
| 
 | ||||
|                 // Check if actions... | ||||
|                 for (int i = 0; i < actions.size() && accepted; ++i) { | ||||
|                     RunningAction action = actions.get(i); | ||||
|                     // If action is running, ask user... | ||||
|                     if (action.isRunning()) { | ||||
|                         System.out.println("Action " + action.getInformation() + " is running... "); | ||||
|                         if (JOptionPane.showConfirmDialog(parentComponent, "Action {" + action.getInformation() | ||||
|                                 + "} is running, do you want to stop it?") == JOptionPane.OK_OPTION) { | ||||
|                             System.out.println("Action " + action.getInformation() + " has been interrupted."); | ||||
|                             action.interrupt(); | ||||
|                         } | ||||
|                         else { | ||||
|                             System.out.println("Action " + action.getInformation() + " not interrupted... "); | ||||
|                             accepted = false; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // If action is accepted, run it... | ||||
|                 if (accepted) { | ||||
|                     listener.actionPerformed(e); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,14 +0,0 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.awt.event.ActionEvent; | ||||
| import java.awt.event.ActionListener; | ||||
| 
 | ||||
| public abstract class BlockingActionListener implements ActionListener { | ||||
| 
 | ||||
|     @Override | ||||
|     public void actionPerformed(ActionEvent e) { | ||||
|         this.actionAccepted(e); | ||||
|     } | ||||
| 
 | ||||
|     public abstract void actionAccepted(ActionEvent e); | ||||
| } | ||||
|  | @ -12,10 +12,7 @@ import java.awt.event.WindowEvent; | |||
| import java.io.DataInputStream; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.OutputStream; | ||||
| import java.io.PrintStream; | ||||
| import java.time.Duration; | ||||
| import java.time.Instant; | ||||
| import java.util.ArrayList; | ||||
| 
 | ||||
| import javax.swing.BorderFactory; | ||||
|  | @ -44,17 +41,19 @@ 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; | ||||
| 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.GraphReader; | ||||
| import org.insa.graph.io.BinaryGraphReader; | ||||
| import org.insa.graph.io.BinaryGraphReaderV2; | ||||
| 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.drawing.BasicDrawing; | ||||
| import org.insa.graphics.drawing.BlackAndWhiteGraphPalette; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
|  | @ -62,30 +61,6 @@ import org.insa.graphics.drawing.MapViewDrawing; | |||
| 
 | ||||
| public class MainWindow extends JFrame { | ||||
| 
 | ||||
|     protected class JOutputStream extends OutputStream { | ||||
|         private JTextArea textArea; | ||||
| 
 | ||||
|         public JOutputStream(JTextArea textArea) { | ||||
|             this.textArea = textArea; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void write(int b) throws IOException { | ||||
|             // redirects data to the text area | ||||
|             textArea.setText(textArea.getText() + String.valueOf((char) b)); | ||||
|             // scrolls the text area to the end of data | ||||
|             textArea.setCaretPosition(textArea.getDocument().getLength()); | ||||
|             // keeps the textArea up to date | ||||
|             textArea.update(textArea.getGraphics()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected interface CallableWithNodes { | ||||
| 
 | ||||
|         void call(ArrayList<Node> nodes); | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      */ | ||||
|  | @ -102,14 +77,13 @@ public class MainWindow extends JFrame { | |||
|     private static final int THREAD_TIMER_DELAY = 1000; // in milliseconds | ||||
| 
 | ||||
|     // Current graph. | ||||
|     private Graph graph; | ||||
|     protected Graph graph; | ||||
| 
 | ||||
|     // Current loaded path. | ||||
|     private Path currentPath; | ||||
|     // private Path currentPath; | ||||
| 
 | ||||
|     // Drawing and click adapter. | ||||
|     private Drawing drawing; | ||||
|     private MultiPointsClickListener clickAdapter = null; | ||||
|     protected Drawing drawing; | ||||
| 
 | ||||
|     // Main panel. | ||||
|     private JSplitPane mainPanel; | ||||
|  | @ -124,23 +98,41 @@ public class MainWindow extends JFrame { | |||
|     private JLabel mapIdPanel; | ||||
| 
 | ||||
|     // Thread information | ||||
|     private Instant threadStartTime; | ||||
|     private Timer threadTimer; | ||||
|     private JPanel threadPanel; | ||||
| 
 | ||||
|     // Log stream and print stream | ||||
|     private JOutputStream logStream; | ||||
|     private StreamCapturer logStream; | ||||
| 
 | ||||
|     @SuppressWarnings("unused") | ||||
|     private PrintStream printStream; | ||||
| 
 | ||||
|     // Current running thread | ||||
|     private Thread currentThread; | ||||
|     private ThreadWrapper currentThread; | ||||
| 
 | ||||
|     // Multi point listener | ||||
|     private MultiPointsClickListener clickAdapter = null; | ||||
| 
 | ||||
|     // Factory | ||||
|     private BlockingActionFactory baf; | ||||
| 
 | ||||
|     public MainWindow() { | ||||
|         super(WINDOW_TITLE); | ||||
| 
 | ||||
|         setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); | ||||
|         setLayout(new BorderLayout()); | ||||
| 
 | ||||
|         // Create drawing and action listeners... | ||||
|         this.drawing = new BasicDrawing(); | ||||
| 
 | ||||
|         this.clickAdapter = new MultiPointsClickListener(this); | ||||
|         this.currentThread = new ThreadWrapper(this); | ||||
|         this.baf = new BlockingActionFactory(this); | ||||
|         this.baf.addAction(clickAdapter); | ||||
|         this.baf.addAction(currentThread); | ||||
| 
 | ||||
|         // Click adapter | ||||
|         addDrawingClickListeners(); | ||||
|         setJMenuBar(createMenuBar()); | ||||
| 
 | ||||
|         addWindowListener(new WindowAdapter() { | ||||
|  | @ -158,21 +150,15 @@ public class MainWindow extends JFrame { | |||
|         // Create graph area | ||||
|         mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); | ||||
| 
 | ||||
|         this.drawing = new BasicDrawing(); | ||||
| 
 | ||||
|         // Click adapter | ||||
|         addDrawingClickListeners(); | ||||
| 
 | ||||
|         JTextArea infoPanel = new JTextArea(); | ||||
|         infoPanel.setMinimumSize(new Dimension(200, 50)); | ||||
|         infoPanel.setBackground(Color.WHITE); | ||||
|         infoPanel.setLineWrap(true); | ||||
|         infoPanel.setEditable(false); | ||||
|         this.logStream = new JOutputStream(infoPanel); | ||||
|         this.logStream = new StreamCapturer(infoPanel); | ||||
|         this.printStream = new PrintStream(this.logStream); | ||||
| 
 | ||||
|         mainPanel.setResizeWeight(0.8); | ||||
|         // sp.setEnabled(false); | ||||
|         mainPanel.setDividerSize(5); | ||||
| 
 | ||||
|         mainPanel.setBackground(Color.WHITE); | ||||
|  | @ -183,10 +169,10 @@ public class MainWindow extends JFrame { | |||
|         // Top Panel | ||||
|         this.add(createTopPanel(), BorderLayout.NORTH); | ||||
|         this.add(createStatusBar(), BorderLayout.SOUTH); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private void restartThreadTimer() { | ||||
|         threadStartTime = Instant.now(); | ||||
|         threadTimer.restart(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -200,7 +186,7 @@ public class MainWindow extends JFrame { | |||
|      */ | ||||
|     private void launchThread(Runnable runnable, boolean canInterrupt) { | ||||
|         if (canInterrupt) { | ||||
|             currentThread = new Thread(new Runnable() { | ||||
|             currentThread.setThread(new Thread(new Runnable() { | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     restartThreadTimer(); | ||||
|  | @ -208,22 +194,22 @@ public class MainWindow extends JFrame { | |||
|                     runnable.run(); | ||||
|                     clearCurrentThread(); | ||||
|                 } | ||||
|             }); | ||||
|             })); | ||||
|         } | ||||
|         else { | ||||
|             currentThread = new Thread(runnable); | ||||
|             currentThread.setThread(new Thread(runnable)); | ||||
|         } | ||||
|         currentThread.start(); | ||||
|         currentThread.startThread(); | ||||
|     } | ||||
| 
 | ||||
|     private void launchThread(Runnable runnable) { | ||||
|         launchThread(runnable, true); | ||||
|     } | ||||
| 
 | ||||
|     private void clearCurrentThread() { | ||||
|     protected void clearCurrentThread() { | ||||
|         stopThreadTimer(); | ||||
|         threadPanel.setVisible(false); | ||||
|         currentThread = null; | ||||
|         currentThread.setThread(null); | ||||
|     } | ||||
| 
 | ||||
|     private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) { | ||||
|  | @ -241,7 +227,6 @@ public class MainWindow extends JFrame { | |||
|     } | ||||
| 
 | ||||
|     private void addDrawingClickListeners() { | ||||
|         this.clickAdapter = new MultiPointsClickListener(graph, drawing); | ||||
|         drawing.addDrawingClickListener(this.clickAdapter); | ||||
|     } | ||||
| 
 | ||||
|  | @ -265,9 +250,9 @@ public class MainWindow extends JFrame { | |||
|         // Open Map item... | ||||
|         openMapItem = new JMenuItem("Open Map... ", KeyEvent.VK_O); | ||||
|         openMapItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK)); | ||||
|         openMapItem.addActionListener(new BlockingActionListener() { | ||||
|         openMapItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 JFileChooser chooser = new JFileChooser(); | ||||
|                 FileNameExtensionFilter filter = new FileNameExtensionFilter("Map & compressed map files", "map", | ||||
|                         "map2", "mapgr", "map.gz"); | ||||
|  | @ -313,14 +298,14 @@ public class MainWindow extends JFrame { | |||
|                     }, false); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         })); | ||||
| 
 | ||||
|         // Open Path item... | ||||
|         JMenuItem openPathItem = new JMenuItem("Open Path... ", KeyEvent.VK_P); | ||||
|         openPathItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.ALT_MASK)); | ||||
|         openPathItem.addActionListener(new BlockingActionListener() { | ||||
|         openPathItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 JFileChooser chooser = new JFileChooser(); | ||||
|                 FileNameExtensionFilter filter = new FileNameExtensionFilter("Path & compressed path files", "path", | ||||
|                         "path.gz"); | ||||
|  | @ -336,7 +321,8 @@ public class MainWindow extends JFrame { | |||
|                         return; | ||||
|                     } | ||||
|                     try { | ||||
|                         currentPath = reader.readPath(graph); | ||||
|                         Path path = reader.readPath(graph); | ||||
|                         drawing.drawPath(path); | ||||
|                     } | ||||
|                     catch (MapMismatchException exception) { | ||||
|                         JOptionPane.showMessageDialog(MainWindow.this, | ||||
|  | @ -347,18 +333,17 @@ public class MainWindow extends JFrame { | |||
|                         JOptionPane.showMessageDialog(MainWindow.this, "Unable to read path from the selected file."); | ||||
|                         return; | ||||
|                     } | ||||
|                     drawing.drawPath(currentPath); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         })); | ||||
|         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 BlockingActionListener() { | ||||
|         closeItem.addActionListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 MainWindow.this.dispatchEvent(new WindowEvent(MainWindow.this, WindowEvent.WINDOW_CLOSING)); | ||||
|             } | ||||
|         }); | ||||
|  | @ -373,9 +358,9 @@ public class MainWindow extends JFrame { | |||
|         // Second menu | ||||
|         JMenuItem drawGraphItem = new JMenuItem("Redraw", KeyEvent.VK_R); | ||||
|         drawGraphItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.ALT_MASK)); | ||||
|         drawGraphItem.addActionListener(new BlockingActionListener() { | ||||
|         drawGraphItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 launchThread(new Runnable() { | ||||
|                     @Override | ||||
|                     public void run() { | ||||
|  | @ -384,13 +369,13 @@ public class MainWindow extends JFrame { | |||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|         })); | ||||
|         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(new BlockingActionListener() { | ||||
|         drawGraphBWItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 launchThread(new Runnable() { | ||||
|                     @Override | ||||
|                     public void run() { | ||||
|  | @ -399,13 +384,13 @@ public class MainWindow extends JFrame { | |||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|         })); | ||||
|         graphLockItems.add(drawGraphBWItem); | ||||
|         JMenuItem drawGraphMapsforgeItem = new JMenuItem("Redraw (Map)", KeyEvent.VK_M); | ||||
|         drawGraphMapsforgeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.ALT_MASK)); | ||||
|         drawGraphMapsforgeItem.addActionListener(new BlockingActionListener() { | ||||
|         drawGraphMapsforgeItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 launchThread(new Runnable() { | ||||
|                     @Override | ||||
|                     public void run() { | ||||
|  | @ -414,7 +399,7 @@ public class MainWindow extends JFrame { | |||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|         })); | ||||
|         graphLockItems.add(drawGraphMapsforgeItem); | ||||
| 
 | ||||
|         JMenu graphMenu = new JMenu("Graph"); | ||||
|  | @ -428,13 +413,13 @@ public class MainWindow extends JFrame { | |||
| 
 | ||||
|         // Weakly connected components | ||||
|         JMenuItem wccItem = new JMenuItem("Weakly Connected Components"); | ||||
|         wccItem.addActionListener(new BlockingActionListener() { | ||||
|         wccItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 WeaklyConnectedComponentsData instance = new WeaklyConnectedComponentsData(graph); | ||||
|                 WeaklyConnectedComponentsAlgorithm algo = new WeaklyConnectedComponentsAlgorithm(instance); | ||||
|                 algo.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing)); | ||||
|                 // algo.addObserver(new WeaklyConnectedComponentTextObserver(printStream)); | ||||
|                 algo.addObserver(new WeaklyConnectedComponentTextObserver(printStream)); | ||||
|                 launchThread(new Runnable() { | ||||
|                     @Override | ||||
|                     public void run() { | ||||
|  | @ -442,13 +427,13 @@ public class MainWindow extends JFrame { | |||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|         })); | ||||
| 
 | ||||
|         // Shortest path | ||||
|         JMenuItem bellmanItem = new JMenuItem("Shortest Path (Bellman-Ford)"); | ||||
|         bellmanItem.addActionListener(new BlockingActionListener() { | ||||
|         bellmanItem.addActionListener(baf.createBlockingAction(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionAccepted(ActionEvent e) { | ||||
|             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); | ||||
| 
 | ||||
|  | @ -463,7 +448,7 @@ public class MainWindow extends JFrame { | |||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         })); | ||||
|         graphLockItems.add(wccItem); | ||||
|         graphLockItems.add(bellmanItem); | ||||
| 
 | ||||
|  | @ -487,14 +472,6 @@ public class MainWindow extends JFrame { | |||
|         return menuBar; | ||||
|     } | ||||
| 
 | ||||
|     @SuppressWarnings("deprecation") | ||||
|     private void stopCurrentThread() { | ||||
|         // Should not be used in production code, but here I have no idea how | ||||
|         // to do this properly... Cannot use .interrupt() because it would requires | ||||
|         // the algorithm to watch the ThreadInteruption exception. | ||||
|         currentThread.stop(); | ||||
|     } | ||||
| 
 | ||||
|     private JPanel createStatusBar() { | ||||
|         // create the status bar panel and shove it down the bottom of the frame | ||||
|         JPanel statusPanel = new JPanel(); | ||||
|  | @ -513,14 +490,12 @@ public class MainWindow extends JFrame { | |||
| 
 | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 if (currentThread != null && currentThread.isAlive()) { | ||||
|                 if (currentThread.isRunning()) { | ||||
|                     int confirmed = JOptionPane.showConfirmDialog(null, | ||||
|                             "Are you sure you want to kill the running thread?", "Kill Confirmation", | ||||
|                             JOptionPane.YES_NO_OPTION); | ||||
|                     if (confirmed == JOptionPane.YES_OPTION) { | ||||
|                         stopCurrentThread(); | ||||
|                         clearCurrentThread(); | ||||
|                         threadPanel.setVisible(false); | ||||
|                         currentThread.interrupt(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | @ -529,8 +504,7 @@ public class MainWindow extends JFrame { | |||
|         threadTimer = new Timer(THREAD_TIMER_DELAY, new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 Duration elapsed = Duration.between(threadStartTime, Instant.now()); | ||||
|                 long seconds = elapsed.getSeconds(); | ||||
|                 long seconds = currentThread.getDuration().getSeconds(); | ||||
|                 threadTimerLabel | ||||
|                         .setText(String.format("%02d:%02d:%02d", seconds / 3600, seconds / 60 % 60, seconds % 60)); | ||||
|             } | ||||
|  |  | |||
|  | @ -1,16 +1,26 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.awt.Color; | ||||
| import java.time.Duration; | ||||
| import java.time.Instant; | ||||
| import java.util.ArrayList; | ||||
| 
 | ||||
| import org.insa.graph.Graph; | ||||
| import org.insa.graph.Node; | ||||
| import org.insa.graph.Point; | ||||
| import org.insa.graphics.MainWindow.CallableWithNodes; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
| import org.insa.graphics.drawing.DrawingClickListener; | ||||
| 
 | ||||
| public class MultiPointsClickListener implements DrawingClickListener { | ||||
| public class MultiPointsClickListener implements DrawingClickListener, RunningAction { | ||||
| 
 | ||||
|     protected interface CallableWithNodes { | ||||
| 
 | ||||
|         /** | ||||
|          * Function called when the given number of nodes is reached. | ||||
|          *  | ||||
|          * @param nodes | ||||
|          */ | ||||
|         void call(ArrayList<Node> nodes); | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     // Enable/Disable. | ||||
|     private boolean enabled = false; | ||||
|  | @ -18,6 +28,9 @@ public class MultiPointsClickListener implements DrawingClickListener { | |||
|     // List of points. | ||||
|     private ArrayList<Node> points = new ArrayList<Node>(); | ||||
| 
 | ||||
|     // Starting time | ||||
|     private Instant startTime; | ||||
| 
 | ||||
|     // Number of points to find before running. | ||||
|     private int nTargetPoints = 0; | ||||
| 
 | ||||
|  | @ -25,14 +38,10 @@ public class MultiPointsClickListener implements DrawingClickListener { | |||
|     CallableWithNodes callable = null; | ||||
| 
 | ||||
|     // Graph | ||||
|     private final Graph graph; | ||||
|     private final MainWindow mainWindow; | ||||
| 
 | ||||
|     // Drawing | ||||
|     private final Drawing drawing; | ||||
| 
 | ||||
|     public MultiPointsClickListener(Graph graph, Drawing drawing) { | ||||
|         this.graph = graph; | ||||
|         this.drawing = drawing; | ||||
|     public MultiPointsClickListener(MainWindow mainWindow) { | ||||
|         this.mainWindow = mainWindow; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -45,14 +54,14 @@ public class MultiPointsClickListener implements DrawingClickListener { | |||
|     /** | ||||
|      * Enable this listener. | ||||
|      *  | ||||
|      * @param nTargetPoints | ||||
|      *            Number of point to found before calling the callable. | ||||
|      * @param nTargetPoints Number of point to found before calling the callable. | ||||
|      */ | ||||
|     public void enable(int nTargetPoints, CallableWithNodes callable) { | ||||
|         this.enabled = true; | ||||
|         this.nTargetPoints = nTargetPoints; | ||||
|         this.points.clear(); | ||||
|         this.callable = callable; | ||||
|         this.startTime = Instant.now(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -67,8 +76,8 @@ public class MultiPointsClickListener implements DrawingClickListener { | |||
|         if (!isEnabled()) { | ||||
|             return; | ||||
|         } | ||||
|         Node node = graph.findClosestNode(lonlat); | ||||
|         drawing.drawMarker(node.getPoint(), Color.BLUE); | ||||
|         Node node = mainWindow.graph.findClosestNode(lonlat); | ||||
|         mainWindow.drawing.drawMarker(node.getPoint(), Color.BLUE); | ||||
|         points.add(node); | ||||
|         if (points.size() == nTargetPoints) { | ||||
|             callable.call(points); | ||||
|  | @ -76,4 +85,29 @@ public class MultiPointsClickListener implements DrawingClickListener { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isRunning() { | ||||
|         return isEnabled(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void interrupt() { | ||||
|         disable(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Instant getStartingTime() { | ||||
|         return startTime; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Duration getDuration() { | ||||
|         return Duration.between(getStartingTime(), Instant.now()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getInformation() { | ||||
|         return getClass().getName(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
							
								
								
									
										33
									
								
								src/main/org/insa/graphics/RunningAction.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/main/org/insa/graphics/RunningAction.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.time.Duration; | ||||
| import java.time.Instant; | ||||
| 
 | ||||
| public interface RunningAction { | ||||
| 
 | ||||
|     /** | ||||
|      * @return true if this action is running. | ||||
|      */ | ||||
|     public boolean isRunning(); | ||||
| 
 | ||||
|     /** | ||||
|      * Interrupt this action. | ||||
|      */ | ||||
|     public void interrupt(); | ||||
| 
 | ||||
|     /** | ||||
|      * @return Starting time of this action. | ||||
|      */ | ||||
|     public Instant getStartingTime(); | ||||
| 
 | ||||
|     /** | ||||
|      * @return Current duration of this action. | ||||
|      */ | ||||
|     public Duration getDuration(); | ||||
| 
 | ||||
|     /** | ||||
|      * @return Information for this action. | ||||
|      */ | ||||
|     public String getInformation(); | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										49
									
								
								src/main/org/insa/graphics/StreamCapturer.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/main/org/insa/graphics/StreamCapturer.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.OutputStream; | ||||
| 
 | ||||
| import javax.swing.JTextArea; | ||||
| 
 | ||||
| public class StreamCapturer extends OutputStream { | ||||
| 
 | ||||
|     private StringBuilder buffer; | ||||
|     private String prefix = null; | ||||
|     private JTextArea output; | ||||
| 
 | ||||
|     /** | ||||
|      * @param prefix | ||||
|      * @param output | ||||
|      */ | ||||
|     public StreamCapturer(JTextArea output, String prefix) { | ||||
|         this.prefix = prefix; | ||||
|         buffer = new StringBuilder(128); | ||||
|         this.output = output; | ||||
|     } | ||||
| 
 | ||||
|     public StreamCapturer(JTextArea output) { | ||||
|         this(output, null); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void write(int b) throws IOException { | ||||
|         char c = (char) b; | ||||
|         String value = Character.toString(c); | ||||
|         buffer.append(value); | ||||
|         if (value.equals("\n")) { | ||||
|             output.append(getPrefix() + buffer.toString()); | ||||
|             output.setCaretPosition(output.getText().length()); | ||||
|             buffer.delete(0, buffer.length()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Formatted prefix, or empty string if no prefix is set. | ||||
|      */ | ||||
|     public String getPrefix() { | ||||
|         if (this.prefix == null) { | ||||
|             return ""; | ||||
|         } | ||||
|         return "[" + prefix + "] "; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										62
									
								
								src/main/org/insa/graphics/ThreadWrapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/main/org/insa/graphics/ThreadWrapper.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| package org.insa.graphics; | ||||
| 
 | ||||
| import java.time.Duration; | ||||
| import java.time.Instant; | ||||
| 
 | ||||
| public class ThreadWrapper implements RunningAction { | ||||
| 
 | ||||
|     // Thread hold by this wrapper. | ||||
|     private Thread thread; | ||||
| 
 | ||||
|     // Starting time of the thread. | ||||
|     Instant startingTime; | ||||
| 
 | ||||
|     // MainWindow | ||||
|     private MainWindow mainWindow; | ||||
| 
 | ||||
|     public ThreadWrapper(MainWindow mainWindow) { | ||||
|         this.thread = null; | ||||
|         this.mainWindow = mainWindow; | ||||
|     } | ||||
| 
 | ||||
|     public void setThread(Thread thread) { | ||||
|         this.thread = thread; | ||||
|     } | ||||
| 
 | ||||
|     public void startThread() { | ||||
|         this.startingTime = Instant.now(); | ||||
|         this.thread.start(); | ||||
|     } | ||||
| 
 | ||||
|     public Thread getThread() { | ||||
|         return this.thread; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isRunning() { | ||||
|         return thread != null && thread.isAlive(); | ||||
|     } | ||||
| 
 | ||||
|     @SuppressWarnings("deprecation") | ||||
|     @Override | ||||
|     public void interrupt() { | ||||
|         thread.stop(); | ||||
|         this.mainWindow.clearCurrentThread(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Instant getStartingTime() { | ||||
|         return startingTime; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Duration getDuration() { | ||||
|         return Duration.between(getStartingTime(), Instant.now()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getInformation() { | ||||
|         return getClass().getName(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in a new issue