Skip to content

Commit 7b3cd99

Browse files
author
brunomnsilva
committed
Addressed issues #9 and #19. See README's What's new.
1 parent ecea9b9 commit 7b3cd99

15 files changed

Lines changed: 334 additions & 14 deletions

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ In windows the JVM machine should automatically take care of that, while in Linu
2727

2828
## Getting Started
2929

30+
### What's **new**?
31+
32+
- (0.9.4) You can now annotate a method with `@SmartLabelSource` within a model class to provide the displayed label for a vertex/edge; see the example at `com.brunomnsilva.smartgraph.example`. If no annotation is present, then the `toString()` method is used to obtain the label's text.
33+
34+
- (0.9.4) You can mannualy alter a vertex position on the panel at anytime, through `SmartGraphPanel.setVertexPosition(Vertex<V> v)`; see the example at `com.brunomnsilva.smartgraph.example`.
35+
36+
- (0.9.4) You can override specific default properties by using a *String* parameter to the `SmartGraphProperties` constructor; see the example at `com.brunomnsilva.smartgraph.example`. This is useful if you want to display visually different graphs within the same application.
37+
38+
- (0.9.4) You can now style labels and arrows individually.
39+
3040
### Basic usage
3141

3242
```java
71.6 KB
Binary file not shown.
410 KB
Binary file not shown.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* To change this license header, choose License Headers in Project Properties.
3+
* To change this template file, choose Tools | Templates
4+
* and open the template in the editor.
5+
*/
6+
package com.brunomnsilva.smartgraph.example;
7+
8+
import com.brunomnsilva.smartgraph.graphview.SmartLabelSource;
9+
10+
/**
11+
*
12+
* @author brunomnsilva
13+
*/
14+
public class City {
15+
private String name;
16+
private int population;
17+
18+
public City(String name, int age) {
19+
this.name = name;
20+
this.population = age;
21+
}
22+
23+
@SmartLabelSource
24+
public String getName() {
25+
return name;
26+
}
27+
28+
public void setName(String name) {
29+
this.name = name;
30+
}
31+
32+
33+
public int getPopulation() {
34+
return population;
35+
}
36+
37+
public void setPopulation(int population) {
38+
this.population = population;
39+
}
40+
41+
@Override
42+
public String toString() {
43+
return "City{" + "name=" + name + ", population=" + population + '}';
44+
}
45+
46+
47+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* To change this license header, choose License Headers in Project Properties.
3+
* To change this template file, choose Tools | Templates
4+
* and open the template in the editor.
5+
*/
6+
package com.brunomnsilva.smartgraph.example;
7+
8+
import com.brunomnsilva.smartgraph.graphview.SmartLabelSource;
9+
10+
/**
11+
*
12+
* @author brunomnsilva
13+
*/
14+
public class Distance {
15+
private int distance;
16+
17+
public Distance(int distance) {
18+
this.distance = distance;
19+
}
20+
21+
public int getDistance() {
22+
return distance;
23+
}
24+
25+
public void setDistance(int distance) {
26+
this.distance = distance;
27+
}
28+
29+
@SmartLabelSource
30+
public String getDisplayDistance() {
31+
/* If the above annotation is not present, the toString()
32+
will be used as the edge label. */
33+
34+
return distance + " km";
35+
}
36+
37+
@Override
38+
public String toString() {
39+
return "Distance{" + "distance=" + distance + '}';
40+
}
41+
42+
43+
44+
45+
46+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* To change this license header, choose License Headers in Project Properties.
3+
* To change this template file, choose Tools | Templates
4+
* and open the template in the editor.
5+
*/
6+
package com.brunomnsilva.smartgraph.example;
7+
8+
import com.brunomnsilva.smartgraph.containers.SmartGraphDemoContainer;
9+
import com.brunomnsilva.smartgraph.graph.Graph;
10+
import com.brunomnsilva.smartgraph.graph.GraphEdgeList;
11+
import com.brunomnsilva.smartgraph.graph.Vertex;
12+
import com.brunomnsilva.smartgraph.graphview.SmartCircularSortedPlacementStrategy;
13+
import com.brunomnsilva.smartgraph.graphview.SmartGraphPanel;
14+
import com.brunomnsilva.smartgraph.graphview.SmartGraphProperties;
15+
import javafx.application.Application;
16+
import javafx.scene.Scene;
17+
import javafx.stage.Stage;
18+
import javafx.stage.StageStyle;
19+
20+
/**
21+
*
22+
* @author brunomnsilva
23+
*/
24+
public class ExampleMain extends Application {
25+
26+
@Override
27+
public void start(Stage ignored) {
28+
29+
Graph<City, Distance> distances = new GraphEdgeList<>();
30+
31+
Vertex<City> prague = distances.insertVertex(new City("Prague", 0));
32+
Vertex<City> tokyo = distances.insertVertex(new City("Tokyo", 0));
33+
Vertex<City> beijing = distances.insertVertex(new City("Beijing", 0));
34+
Vertex<City> newYork = distances.insertVertex(new City("New York", 0));
35+
Vertex<City> london = distances.insertVertex(new City("London", 0));
36+
Vertex<City> helsinky = distances.insertVertex(new City("Helsinky", 0));
37+
38+
distances.insertEdge(tokyo, newYork, new Distance(10838));
39+
distances.insertEdge(beijing, newYork, new Distance(11550));
40+
distances.insertEdge(beijing, tokyo, new Distance(1303));
41+
distances.insertEdge(london, newYork, new Distance(5567));
42+
distances.insertEdge(london, prague, new Distance(1264));
43+
distances.insertEdge(helsinky, tokyo, new Distance(7815));
44+
distances.insertEdge(prague, helsinky, new Distance(1845));
45+
distances.insertEdge(beijing, london, new Distance(8132));
46+
47+
/* Only Java 15 allows for multi-line strings */
48+
String customProps = "edge.label = true" + "\n" + "edge.arrow = false";
49+
50+
SmartGraphProperties properties = new SmartGraphProperties(customProps);
51+
52+
SmartGraphPanel<City, Distance> graphView = new SmartGraphPanel<>(distances, properties, new SmartCircularSortedPlacementStrategy());
53+
54+
Scene scene = new Scene(new SmartGraphDemoContainer(graphView), 1024, 768);
55+
56+
Stage stage = new Stage(StageStyle.DECORATED);
57+
stage.setTitle("JavaFX SmartGraph City Distances");
58+
stage.setMinHeight(500);
59+
stage.setMinWidth(800);
60+
stage.setScene(scene);
61+
stage.show();
62+
63+
graphView.init();
64+
65+
//graphView.setAutomaticLayout(true);
66+
67+
/* You can mannualy place vertices at any time. However, these are
68+
absolute coordinates inside the container panel. */
69+
graphView.setVertexPosition(beijing, 100, 100);
70+
graphView.setVertexPosition(helsinky, 924, 100);
71+
graphView.setVertexPosition(london, 200, 668);
72+
graphView.setVertexPosition(prague, 824, 668);
73+
graphView.setVertexPosition(tokyo, 512, 300);
74+
graphView.setVertexPosition(newYork, 512, 400);
75+
76+
graphView.getStylableLabel(tokyo).setStyle("-fx-stroke: red; -fx-fill: red;");
77+
78+
}
79+
80+
public static void main(String[] args) {
81+
launch(args);
82+
}
83+
}

src/com/brunomnsilva/smartgraph/graphview/SmartGraphEdge.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,11 @@ public interface SmartGraphEdge<E, V> extends SmartStylableNode {
5959
* @return arrow reference; null if does not exist.
6060
*/
6161
public SmartStylableNode getStylableArrow();
62+
63+
/**
64+
* Returns the label node for further styling.
65+
*
66+
* @return the label node.
67+
*/
68+
public SmartStylableNode getStylableLabel();
6269
}

src/com/brunomnsilva/smartgraph/graphview/SmartGraphEdgeCurve.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,9 @@ public SmartArrow getAttachedArrow() {
223223
public SmartStylableNode getStylableArrow() {
224224
return this.attachedArrow;
225225
}
226+
227+
@Override
228+
public SmartStylableNode getStylableLabel() {
229+
return this.attachedLabel;
230+
}
226231
}

src/com/brunomnsilva/smartgraph/graphview/SmartGraphEdgeLine.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,9 @@ public SmartStylableNode getStylableArrow() {
140140
return this.attachedArrow;
141141
}
142142

143+
@Override
144+
public SmartStylableNode getStylableLabel() {
145+
return this.attachedLabel;
146+
}
147+
143148
}

src/com/brunomnsilva/smartgraph/graphview/SmartGraphPanel.java

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
import static com.brunomnsilva.smartgraph.graphview.UtilitiesJavaFX.pick;
5959
import static com.brunomnsilva.smartgraph.graphview.UtilitiesPoint2D.attractiveForce;
6060
import static com.brunomnsilva.smartgraph.graphview.UtilitiesPoint2D.repellingForce;
61+
import java.lang.reflect.InvocationTargetException;
62+
import java.lang.reflect.Method;
6163
import java.net.URI;
6264
import java.util.concurrent.Callable;
6365
import java.util.concurrent.ExecutionException;
@@ -99,6 +101,7 @@ public class SmartGraphPanel<V, E> extends Pane {
99101
private final Map<Tuple<SmartGraphVertexNode>, Integer> placedEdges = new HashMap<>();
100102
private boolean initialized = false;
101103
private final boolean edgesWithArrows;
104+
102105
/*
103106
INTERACTION WITH VERTICES AND EDGES
104107
*/
@@ -480,9 +483,7 @@ private SmartGraphEdgeBase createEdge(Edge<E, V> edge, SmartGraphVertexNode<V> g
480483
private void addVertex(SmartGraphVertexNode<V> v) {
481484
this.getChildren().add(v);
482485

483-
String labelText = (v.getUnderlyingVertex().element() != null) ?
484-
v.getUnderlyingVertex().element().toString() :
485-
"<NULL>";
486+
String labelText = generateVertexLabel(v.getUnderlyingVertex().element());
486487

487488
if (graphProperties.getUseVertexTooltip()) {
488489
Tooltip t = new Tooltip(labelText);
@@ -503,9 +504,7 @@ private void addEdge(SmartGraphEdgeBase e, Edge<E, V> edge) {
503504
this.getChildren().add(0, (Node) e);
504505
edgeNodes.put(edge, e);
505506

506-
String labelText = (edge.element() != null) ?
507-
edge.element().toString() :
508-
"<NULL>";
507+
String labelText = generateEdgeLabel(edge.element());
509508

510509
if (graphProperties.getUseEdgeTooltip()) {
511510
Tooltip t = new Tooltip(labelText);
@@ -703,7 +702,8 @@ private void updateLabels() {
703702
if (vertexNode != null) {
704703
SmartLabel label = vertexNode.getAttachedLabel();
705704
if(label != null) {
706-
label.setText(v.element() != null ? v.element().toString() : "<NULL>");
705+
String text = generateVertexLabel(v.element());
706+
label.setText( text );
707707
}
708708

709709
}
@@ -714,12 +714,49 @@ private void updateLabels() {
714714
if (edgeNode != null) {
715715
SmartLabel label = edgeNode.getAttachedLabel();
716716
if (label != null) {
717-
label.setText(e.element() != null ? e.element().toString() : "<NULL>");
717+
String text = generateEdgeLabel(e.element());
718+
label.setText( text );
718719
}
719720
}
720721
});
721722
}
722723

724+
private String generateVertexLabel(V vertex) {
725+
726+
try {
727+
Class<?> clazz = vertex.getClass();
728+
for (Method method : clazz.getDeclaredMethods()) {
729+
if (method.isAnnotationPresent(SmartLabelSource.class)) {
730+
method.setAccessible(true);
731+
Object value = method.invoke(vertex);
732+
return value.toString();
733+
}
734+
}
735+
} catch (SecurityException | IllegalAccessException | IllegalArgumentException |InvocationTargetException ex) {
736+
Logger.getLogger(SmartGraphPanel.class.getName()).log(Level.SEVERE, null, ex);
737+
}
738+
739+
return vertex != null ? vertex.toString() : "<NULL>";
740+
}
741+
742+
private String generateEdgeLabel(E edge) {
743+
744+
try {
745+
Class<?> clazz = edge.getClass();
746+
for (Method method : clazz.getDeclaredMethods()) {
747+
if (method.isAnnotationPresent(SmartLabelSource.class)) {
748+
method.setAccessible(true);
749+
Object value = method.invoke(edge);
750+
return value.toString();
751+
}
752+
}
753+
} catch (SecurityException | IllegalAccessException | IllegalArgumentException |InvocationTargetException ex) {
754+
Logger.getLogger(SmartGraphPanel.class.getName()).log(Level.SEVERE, null, ex);
755+
}
756+
757+
return edge != null ? edge.toString() : "<NULL>";
758+
}
759+
723760
/**
724761
* Computes the bounding box from all displayed vertices.
725762
*
@@ -1001,7 +1038,31 @@ public SmartStylableNode getStylableEdge(E edgeElement) {
10011038
}
10021039
return null;
10031040
}
1041+
1042+
/**
1043+
* Returns the associated stylable element with a graph vertex.
1044+
*
1045+
* @param v underlying vertex
1046+
* @return stylable element (label)
1047+
*/
1048+
public SmartStylableNode getStylableLabel(Vertex<V> v) {
1049+
SmartGraphVertexNode<V> vertex = vertexNodes.get(v);
1050+
1051+
return vertex != null ? vertex.getStylableLabel() : null;
1052+
}
1053+
1054+
/**
1055+
* Returns the associated stylable element with a graph edge.
1056+
*
1057+
* @param e underlying graph edge
1058+
* @return stylable element (label)
1059+
*/
1060+
public SmartStylableNode getStylableLabel(Edge<E,V> e) {
1061+
SmartGraphEdgeBase edge = edgeNodes.get(e);
10041062

1063+
return edge != null ? edge.getStylableLabel() : null;
1064+
}
1065+
10051066

10061067
/**
10071068
* Loads the stylesheet and applies the .graph class to this panel.

0 commit comments

Comments
 (0)