diff --git a/src/main/java/ee/ut/dendroloj/Dendrologist.java b/src/main/java/ee/ut/dendroloj/Dendrologist.java
index db4e115..c8d3c3f 100644
--- a/src/main/java/ee/ut/dendroloj/Dendrologist.java
+++ b/src/main/java/ee/ut/dendroloj/Dendrologist.java
@@ -173,7 +173,7 @@ public static void drawGraph(int[][] adjacencyMatrix, String[] labels) {
* EXPERIMENTAL API
*
* Draws a graph based on the provided adjacency matrix.
- * Infinite values and NaN in the adjacency matrix are treated as missing edges.
+ * Infinite and NaN values in the adjacency matrix are treated as missing edges.
*
* @param adjacencyMatrix graph adjacency matrix; value at [i][j] is treated as the weight of the edge from vertex i to vertex j
* @param labels string labels for vertices; pass null to use vertex indices as labels
@@ -199,7 +199,7 @@ public static void drawGraph(double[][] adjacencyMatrix, String[] labels) {
* EXPERIMENTAL API
*
* Draws a graph based on the provided adjacency matrix.
- * Infinite values and NaN in the adjacency matrix are treated as missing edges.
+ * Infinite and NaN values in the adjacency matrix are treated as missing edges.
*
* @param adjacencyMatrix graph adjacency matrix; value at [i][j] is treated as the weight of the edge from vertex i to vertex j
* @param labels string labels for vertices; pass null to use vertex indices as labels
diff --git a/src/main/java/ee/ut/dendroloj/GenericGraphLayout.java b/src/main/java/ee/ut/dendroloj/GenericGraphLayout.java
index a489396..cd0965b 100644
--- a/src/main/java/ee/ut/dendroloj/GenericGraphLayout.java
+++ b/src/main/java/ee/ut/dendroloj/GenericGraphLayout.java
@@ -18,6 +18,11 @@ public static Graph assembleGraph(GraphCanvas> graphCanvas) {
for (var vertex : graphCanvas.vertices) {
Node node = graph.addNode(IdHelper.getNodeId(vertex.vertex));
node.setAttribute("label", vertex.label);
+ if (vertex.fixed) {
+ node.setAttribute("layout._fixed");
+ node.setAttribute("layout.frozen");
+ node.setAttribute("xy", vertex.x, vertex.y);
+ }
if (vertex.color != null) node.setAttribute("ui.color", vertex.color);
}
for (var edge : graphCanvas.edges) {
diff --git a/src/main/java/ee/ut/dendroloj/GraphCanvas.java b/src/main/java/ee/ut/dendroloj/GraphCanvas.java
index 95bbd91..f87f089 100644
--- a/src/main/java/ee/ut/dendroloj/GraphCanvas.java
+++ b/src/main/java/ee/ut/dendroloj/GraphCanvas.java
@@ -2,7 +2,9 @@
import java.awt.*;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* EXPERIMENTAL API
@@ -14,21 +16,52 @@
*/
public final class GraphCanvas {
+ private final Set drawnVertices = new HashSet<>();
final List> vertices = new ArrayList<>();
final List> edges = new ArrayList<>();
- public void drawVertex(V vertex) {
- if (vertex == null) throw new NullPointerException("Vertex must not be null");
- drawVertex(vertex, vertex.toString(), null);
- }
+ // TODO: Add overload that allows drawing a vertex with the vertex itself as a default label.
+ // Note that this will make the order of parameters for drawFixedVertex a little awkward.
+ // Also note that the default label being the vertex itself converted to a string
+ // might be non-obvious for reference types (especially ones that don't override toString).
+
+ // public void drawVertex(V vertex) {
+ // if (vertex == null) throw new NullPointerException("Vertex must not be null");
+ // drawVertex(vertex, vertex.toString(), null);
+ // }
public void drawVertex(V vertex, String label) {
- drawVertex(vertex, label, null);
+ if (vertex == null) throw new NullPointerException("Vertex must not be null");
+ addVertex(new Vertex<>(vertex, label, null));
}
public void drawVertex(V vertex, String label, Color color) {
if (vertex == null) throw new NullPointerException("Vertex must not be null");
- vertices.add(new Vertex<>(vertex, label, color));
+ addVertex(new Vertex<>(vertex, label, color));
+ }
+
+ // public void drawFixedVertex(V vertex, double x, double y) {
+ // if (vertex == null) throw new NullPointerException("Vertex must not be null");
+ // drawVertex(vertex, vertex.toString(), null);
+ // }
+
+ public void drawFixedVertex(V vertex, String label, double x, double y) {
+ if (vertex == null) throw new NullPointerException("Vertex must not be null");
+ addVertex(new Vertex<>(vertex, label, null, x, y));
+ }
+
+ public void drawFixedVertex(V vertex, String label, double x, double y, Color color) {
+ if (vertex == null) throw new NullPointerException("Vertex must not be null");
+ addVertex(new Vertex<>(vertex, label, color, x, y));
+ }
+
+ private void addVertex(Vertex vertex) {
+ String id = IdHelper.getNodeId(vertex.vertex);
+ if (drawnVertices.contains(id)) {
+ throw new IllegalArgumentException("Vertex " + vertex.vertex + " (" + vertex.label + ") has already been drawn");
+ }
+ drawnVertices.add(id);
+ vertices.add(vertex);
}
/**
@@ -79,11 +112,26 @@ static final class Vertex {
public final T vertex;
public final String label;
public final Color color;
+ public final boolean fixed;
+ public final double x;
+ public final double y;
private Vertex(T vertex, String label, Color color) {
this.vertex = vertex;
this.label = label;
this.color = color;
+ this.fixed = false;
+ this.x = 0.0;
+ this.y = 0.0;
+ }
+
+ private Vertex(T vertex, String label, Color color, double x, double y) {
+ this.vertex = vertex;
+ this.label = label;
+ this.color = color;
+ this.fixed = true;
+ this.x = x;
+ this.y = y;
}
}
diff --git a/src/main/java/ee/ut/dendroloj/GraphGUI.java b/src/main/java/ee/ut/dendroloj/GraphGUI.java
index c4c0247..a2af2a7 100644
--- a/src/main/java/ee/ut/dendroloj/GraphGUI.java
+++ b/src/main/java/ee/ut/dendroloj/GraphGUI.java
@@ -3,6 +3,7 @@
import org.graphstream.graph.Graph;
import org.graphstream.ui.geom.Point2;
import org.graphstream.ui.geom.Point3;
+import org.graphstream.ui.graphicGraph.GraphicElement;
import org.graphstream.ui.graphicGraph.GraphicGraph;
import org.graphstream.ui.layout.Layout;
import org.graphstream.ui.swing_viewer.SwingViewer;
@@ -128,6 +129,16 @@ public void mouseDragged(MouseEvent event) {
}
}
}
+
+ @Override
+ protected void mouseButtonReleaseOffElement(GraphicElement element, MouseEvent event) {
+ if (!element.hasAttribute("layout._fixed")) {
+ view.freezeElement(element, false);
+ }
+ if (event.getButton() != 3) {
+ element.removeAttribute("ui.clicked");
+ }
+ }
};
view.setMouseManager(restrictedDefaultMouseManager);
diff --git a/src/test/java/GraafKatsed.java b/src/test/java/GraafKatsed.java
index a8a6ca8..27a6b02 100644
--- a/src/test/java/GraafKatsed.java
+++ b/src/test/java/GraafKatsed.java
@@ -26,11 +26,11 @@ public static void main(String[] args) {
// Dendrologist.drawGraph(M, null);
List tipud = new ArrayList<>();
- tipud.add(new Tipp("A"));
- tipud.add(new Tipp("B"));
- tipud.add(new Tipp("C"));
- tipud.add(new Tipp("D"));
- tipud.add(new Tipp("E"));
+ tipud.add(new Tipp("A", 1, 0));
+ tipud.add(new Tipp("B", 2, 5));
+ tipud.add(new Tipp("C", 0, 1));
+ tipud.add(new Tipp("D", 1, 1));
+ tipud.add(new Tipp("E", 0, 0));
tipud.get(0).kaared.add(new Kaar(11, tipud.get(1)));
tipud.get(0).kaared.add(new Kaar(22, tipud.get(2)));
@@ -40,9 +40,9 @@ public static void main(String[] args) {
GraphCanvas lõuend = new GraphCanvas<>();
for (Tipp tipp : tipud) {
- lõuend.drawVertex(tipp, tipp.tähis, Color.GREEN);
+ lõuend.drawFixedVertex(tipp, tipp.tähis, tipp.x, tipp.y);
for (Kaar kaar : tipp.kaared) {
- lõuend.drawEdge(tipp, kaar.lõppTipp, String.valueOf(kaar.kaal), Color.MAGENTA);
+ lõuend.drawEdge(tipp, kaar.lõppTipp, String.valueOf(kaar.kaal));
}
}
Dendrologist.drawGraph(lõuend);
@@ -50,10 +50,14 @@ public static void main(String[] args) {
private static class Tipp {
public final String tähis;
+ public final double x;
+ public final double y;
public final List kaared;
- public Tipp(String tähis) {
+ public Tipp(String tähis, double x, double y) {
this.tähis = tähis;
+ this.x = x;
+ this.y = y;
this.kaared = new ArrayList<>();
}
}