diff --git a/src/main/org/insa/graphics/DrawingChangeListener.java b/src/main/org/insa/graphics/DrawingChangeListener.java new file mode 100644 index 0000000..7b06ac4 --- /dev/null +++ b/src/main/org/insa/graphics/DrawingChangeListener.java @@ -0,0 +1,24 @@ +package org.insa.graphics; + +import org.insa.graphics.drawing.Drawing; + +public interface DrawingChangeListener { + + /** + * Event fired when a new drawing is loaded. + * + * @param oldDrawing Old drawing, may be null if no drawing exits prior to this + * one. + * @param newDrawing New drawing. + */ + public void onDrawingLoaded(Drawing oldDrawing, Drawing newDrawing); + + /** + * Event fired when a redraw request is emitted - This is typically emitted + * after a onDrawingLoaded event, but not always, and request that elements are + * drawn again on the new drawing. + * + */ + public void onRedrawRequest(); + +} diff --git a/src/main/org/insa/graphics/GraphChangeListener.java b/src/main/org/insa/graphics/GraphChangeListener.java new file mode 100644 index 0000000..3cfb1fc --- /dev/null +++ b/src/main/org/insa/graphics/GraphChangeListener.java @@ -0,0 +1,14 @@ +package org.insa.graphics; + +import org.insa.graph.Graph; + +public interface GraphChangeListener { + + /** + * Event fire when a new graph has been loaded. + * + * @param graph The new graph. + */ + public void newGraphLoaded(Graph graph); + +} diff --git a/src/main/org/insa/graphics/MainWindow.java b/src/main/org/insa/graphics/MainWindow.java index 4577494..831b892 100644 --- a/src/main/org/insa/graphics/MainWindow.java +++ b/src/main/org/insa/graphics/MainWindow.java @@ -21,6 +21,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; +import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; @@ -131,6 +132,10 @@ public class MainWindow extends JFrame { // Factory private BlockingActionFactory baf; + // Observers + private List drawingChangeListeners = new ArrayList<>(); + private List graphChangeListeneres = new ArrayList<>(); + public MainWindow() { super(WINDOW_TITLE); @@ -143,7 +148,7 @@ public class MainWindow extends JFrame { this.drawing = this.basicDrawing; - spPanel = new ShortestPathPanel(MainWindow.this); + spPanel = new ShortestPathPanel(); spPanel.addStartActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -166,15 +171,19 @@ public class MainWindow extends JFrame { }); spPanel.setVisible(false); + // Add click listeners to both drawing. basicDrawing.addDrawingClickListener(spPanel.nodesInputPanel); mapViewDrawing.addDrawingClickListener(spPanel.nodesInputPanel); + this.graphChangeListeneres.add(spPanel.nodesInputPanel); + this.drawingChangeListeners.add(spPanel.nodesInputPanel); + + // Create action factory. this.currentThread = new ThreadWrapper(this); this.baf = new BlockingActionFactory(this); this.baf.addAction(currentThread); // Click adapter - addDrawingClickListeners(); setJMenuBar(createMenuBar()); addWindowListener(new WindowAdapter() { @@ -229,6 +238,8 @@ public class MainWindow extends JFrame { // Top Panel this.add(createStatusBar(), BorderLayout.SOUTH); + // Notify everythin + notifyDrawingLoaded(null, drawing); } /** @@ -369,7 +380,34 @@ public class MainWindow extends JFrame { }); } - private void addDrawingClickListeners() { + /** + * 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(); + } } /** @@ -414,22 +452,26 @@ public class MainWindow extends JFrame { drawing = mapViewDrawing; mainPanel.setLeftComponent(mapViewDrawing); mainPanel.setDividerLocation(oldLocation); + notifyDrawingLoaded(basicDrawing, mapViewDrawing); } // 2. We draw the graph. drawing.clear(); ((MapViewDrawing) drawing).drawGraph(mfile); + notifyRedrawRequest(); + } else if (!isMapView || (isMapView && mfile == null && isNewGraph)) { if (drawing == mapViewDrawing) { mapViewDrawing.clear(); drawing = basicDrawing; - addDrawingClickListeners(); mainPanel.setLeftComponent(basicDrawing); mainPanel.setDividerLocation(oldLocation); + notifyDrawingLoaded(mapViewDrawing, basicDrawing); } drawing.clear(); drawing.drawGraph(graph, palette); + notifyRedrawRequest(); } } @@ -485,6 +527,7 @@ public class MainWindow extends JFrame { exception.printStackTrace(System.out); return; } + notifyNewGraphLoaded(); // Save file path. graphFilePath = path; diff --git a/src/main/org/insa/graphics/NodesInputPanel.java b/src/main/org/insa/graphics/NodesInputPanel.java index 3787103..4aa8d40 100644 --- a/src/main/org/insa/graphics/NodesInputPanel.java +++ b/src/main/org/insa/graphics/NodesInputPanel.java @@ -21,12 +21,15 @@ import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import org.insa.graph.Graph; import org.insa.graph.Node; import org.insa.graph.Point; +import org.insa.graphics.drawing.Drawing; import org.insa.graphics.drawing.DrawingClickListener; import org.insa.graphics.drawing.overlays.MarkerOverlay; -public class NodesInputPanel extends JPanel implements DrawingClickListener { +public class NodesInputPanel extends JPanel + implements DrawingClickListener, DrawingChangeListener, GraphChangeListener { /** * @@ -61,8 +64,8 @@ public class NodesInputPanel extends JPanel implements DrawingClickListener { }; // Node inputs and markers. - private ArrayList nodeInputs = new ArrayList<>(); - private Map markerTrackers = new IdentityHashMap(); + private final ArrayList nodeInputs = new ArrayList<>(); + private final Map markerTrackers = new IdentityHashMap(); // Component that can be enabled/disabled. private ArrayList components = new ArrayList<>(); @@ -71,12 +74,16 @@ public class NodesInputPanel extends JPanel implements DrawingClickListener { // ActionListener called when all inputs are filled. private ArrayList inputChangeListeners = new ArrayList<>(); - // Instance of mainwindow. - MainWindow mainWindow; + // Drawing and graph + private Drawing drawing; + private Graph graph; - public NodesInputPanel(MainWindow mainWindow) { + /** + * @param drawing Original drawing used (see {@link:newDrawingLoaded}). + * @param graph Original graph used (see {@link:newGraphLoaded}); + */ + public NodesInputPanel() { super(new GridBagLayout()); - this.mainWindow = mainWindow; initInputToFill(); } @@ -105,6 +112,7 @@ public class NodesInputPanel extends JPanel implements DrawingClickListener { public void clear() { for (JTextField field: nodeInputs) { field.setText(""); + markerTrackers.put(field, null); } initInputToFill(); } @@ -174,7 +182,7 @@ public class NodesInputPanel extends JPanel implements DrawingClickListener { MarkerOverlay tracker = markerTrackers.getOrDefault(textField, null); if (curnode != null) { if (tracker == null) { - tracker = mainWindow.drawing.drawMarker(curnode.getPoint(), markerColor); + tracker = drawing.drawMarker(curnode.getPoint(), markerColor); markerTrackers.put(textField, tracker); } else { @@ -223,7 +231,7 @@ public class NodesInputPanel extends JPanel implements DrawingClickListener { */ protected Node getNodeForInput(JTextField textfield) { try { - Node node = this.mainWindow.graph.getNodes().get(Integer.valueOf(textfield.getText().trim())); + Node node = graph.getNodes().get(Integer.valueOf(textfield.getText().trim())); return node; } catch (IllegalArgumentException | IndexOutOfBoundsException ex) { @@ -292,11 +300,38 @@ public class NodesInputPanel extends JPanel implements DrawingClickListener { @Override public void mouseClicked(Point point) { - Node node = this.mainWindow.graph.findClosestNode(point); + Node node = graph.findClosestNode(point); JTextField input = getInputToFill(); if (input != null) { input.setText(String.valueOf(node.getId())); nextInputToFill(); } } + + @Override + public void newGraphLoaded(Graph graph) { + if (graph != this.graph) { + this.clear(); + this.graph = graph; + } + } + + @Override + public void onDrawingLoaded(Drawing oldDrawing, Drawing newDrawing) { + if (newDrawing != drawing) { + this.drawing = newDrawing; + + } + } + + @Override + public void onRedrawRequest() { + for (JTextField input: nodeInputs) { + MarkerOverlay tracker = markerTrackers.getOrDefault(input, null); + if (tracker != null) { + markerTrackers.put(input, this.drawing.drawMarker(tracker.getPoint(), tracker.getColor())); + tracker.delete(); + } + } + } } diff --git a/src/main/org/insa/graphics/ShortestPathPanel.java b/src/main/org/insa/graphics/ShortestPathPanel.java index 5d7c76a..37b2bbf 100644 --- a/src/main/org/insa/graphics/ShortestPathPanel.java +++ b/src/main/org/insa/graphics/ShortestPathPanel.java @@ -95,7 +95,9 @@ public class ShortestPathPanel extends JPanel { // Start listeners List startActionListeners = new ArrayList<>(); - public ShortestPathPanel(MainWindow mainWindow) { + /** + */ + public ShortestPathPanel() { super(); setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); @@ -122,7 +124,7 @@ public class ShortestPathPanel extends JPanel { components.add(algoSelect); // Add inputs for node. - this.nodesInputPanel = new NodesInputPanel(mainWindow); + this.nodesInputPanel = new NodesInputPanel(); this.nodesInputPanel.setAlignmentX(Component.LEFT_ALIGNMENT); nodesInputPanel.addTextField("Origin: ", new Color(57, 172, 115)); nodesInputPanel.addTextField("Destination: ", new Color(255, 77, 77)); diff --git a/src/main/org/insa/graphics/drawing/BasicDrawing.java b/src/main/org/insa/graphics/drawing/BasicDrawing.java index cfe7144..d11fa1a 100644 --- a/src/main/org/insa/graphics/drawing/BasicDrawing.java +++ b/src/main/org/insa/graphics/drawing/BasicDrawing.java @@ -99,6 +99,11 @@ public class BasicDrawing extends JPanel implements Drawing { return point; } + @Override + public Color getColor() { + return color; + } + @Override public void moveTo(Point point) { this.point = point; @@ -440,7 +445,7 @@ public class BasicDrawing extends JPanel implements Drawing { @Override public void drawGraph(Graph graph, GraphPalette palette) { - clear(); + this.clear(); initialize(graph); for (Node node: graph.getNodes()) { for (Arc arc: node.getSuccessors()) { diff --git a/src/main/org/insa/graphics/drawing/MapViewDrawing.java b/src/main/org/insa/graphics/drawing/MapViewDrawing.java index b7e20b9..7c13a3a 100644 --- a/src/main/org/insa/graphics/drawing/MapViewDrawing.java +++ b/src/main/org/insa/graphics/drawing/MapViewDrawing.java @@ -80,8 +80,12 @@ public class MapViewDrawing extends MapView implements Drawing { private class MapViewMarkerOverlay extends MapViewOverlay implements MarkerOverlay { - public MapViewMarkerOverlay(Marker marker) { + // Color of this marker + Color color; + + public MapViewMarkerOverlay(Marker marker, Color color) { super(new Layer[] { marker }); + this.color = color; } @Override @@ -90,6 +94,11 @@ public class MapViewDrawing extends MapView implements Drawing { return new Point(marker.getLatLong().getLongitude(), marker.getLatLong().getLatitude()); } + @Override + public Color getColor() { + return color; + } + @Override public void moveTo(Point point) { Marker marker = (Marker) this.layers[0]; @@ -187,7 +196,7 @@ public class MapViewDrawing extends MapView implements Drawing { @Override public MarkerOverlay drawMarker(Point point, Color color) { - return new MapViewMarkerOverlay(createMarker(point, color)); + return new MapViewMarkerOverlay(createMarker(point, color), color); } @Override diff --git a/src/main/org/insa/graphics/drawing/overlays/MarkerOverlay.java b/src/main/org/insa/graphics/drawing/overlays/MarkerOverlay.java index a761af9..6d1f1ee 100644 --- a/src/main/org/insa/graphics/drawing/overlays/MarkerOverlay.java +++ b/src/main/org/insa/graphics/drawing/overlays/MarkerOverlay.java @@ -1,9 +1,16 @@ package org.insa.graphics.drawing.overlays; +import java.awt.Color; + import org.insa.graph.Point; public interface MarkerOverlay extends Overlay { + /** + * @return Color associated with this marker. + */ + public Color getColor(); + /** * @return The point associated with this marker. */