5858import static com .brunomnsilva .smartgraph .graphview .UtilitiesJavaFX .pick ;
5959import static com .brunomnsilva .smartgraph .graphview .UtilitiesPoint2D .attractiveForce ;
6060import static com .brunomnsilva .smartgraph .graphview .UtilitiesPoint2D .repellingForce ;
61+ import java .util .concurrent .Callable ;
62+ import java .util .concurrent .ExecutionException ;
63+ import java .util .concurrent .FutureTask ;
6164
6265/**
6366 * JavaFX {@link Pane} that is capable of plotting a {@link Graph} or {@link Digraph}.
@@ -271,7 +274,7 @@ public void setAutomaticLayout(boolean value) {
271274
272275 /**
273276 * Forces a refresh of the visualization based on current state of the
274- * underlying graph.
277+ * underlying graph, immediately returning to the caller.
275278 *
276279 * This method invokes the refresh in the graphical
277280 * thread through Platform.runLater(), so its not guaranteed that the visualization is in sync
@@ -297,6 +300,46 @@ public void update() {
297300 });
298301
299302 }
303+
304+ /**
305+ * Forces a refresh of the visualization based on current state of the
306+ * underlying graph and waits for completion of the update.
307+ *
308+ * Use this variant only when necessary, e.g., need to style an element
309+ * immediately after adding it to the underlying graph. Otherwise, use
310+ * {@link #update() } instead for performance sake.
311+ * <p>
312+ * New vertices will be added close to adjacent ones or randomly for
313+ * isolated vertices.
314+ */
315+ public void updateAndWait () {
316+ if (this .getScene () == null ) {
317+ throw new IllegalStateException ("You must call this method after the instance was added to a scene." );
318+ }
319+
320+ if (!this .initialized ) {
321+ throw new IllegalStateException ("You must call init() method before any updates." );
322+ }
323+
324+ final FutureTask update = new FutureTask (new Callable <Boolean >() {
325+ @ Override
326+ public Boolean call () throws Exception {
327+ updateNodes ();
328+ return true ;
329+ }
330+ });
331+
332+ //this will be called from a non-javafx thread, so this must be guaranteed to run of the graphics thread
333+ Platform .runLater (update );
334+
335+ try {
336+ //wait for completion
337+ update .get ();
338+ } catch (InterruptedException | ExecutionException ex ) {
339+ Logger .getLogger (SmartGraphPanel .class .getName ()).log (Level .SEVERE , null , ex );
340+ }
341+
342+ }
300343
301344 private synchronized void updateNodes () {
302345 removeNodes ();
0 commit comments