--- /dev/null
+/*
+ * Copyright (c) 2005, the JUNG Project and the Regents of the University of
+ * California All rights reserved.
+ *
+ * This software is open-source under the BSD license; see either "license.txt"
+ * or http://jung.sourceforge.net/license.txt for a description.
+ *
+ *
+ */
+package edu.uci.ics.jung.algorithms.layout.util;
+
+import edu.uci.ics.jung.algorithms.util.IterativeContext;
+
+/**
+ *
+ * Implementation of a relaxer thread for layouts.
+ * Extracted from the {@code VisualizationModel} in previous
+ * versions of JUNG.
+ *
+ * @author Tom Nelson - tomnelson@dev.java.net
+ *
+ */
+public class VisRunner implements Relaxer, Runnable {
+
+ protected boolean running;
+ protected IterativeContext process;
+ protected boolean stop;
+ protected boolean manualSuspend;
+ protected Thread thread;
+
+ /**
+ * how long the relaxer thread pauses between iteration loops.
+ */
+ protected long sleepTime = 100L;
+
+
+ /**
+ * Creates an instance for the specified process.
+ */
+ public VisRunner(IterativeContext process) {
+ this.process = process;
+ }
+
+ /**
+ * @return the relaxerThreadSleepTime
+ */
+ public long getSleepTime() {
+ return sleepTime;
+ }
+
+ /**
+ * @param sleepTime the sleep time to set for this thread
+ */
+ public void setSleepTime(long sleepTime) {
+ this.sleepTime = sleepTime;
+ }
+
+ public void prerelax() {
+ manualSuspend = true;
+ long timeNow = System.currentTimeMillis();
+ while (System.currentTimeMillis() - timeNow < 500 && !process.done()) {
+ process.step();
+ }
+ manualSuspend = false;
+ }
+
+ public void pause() {
+ manualSuspend = true;
+ }
+
+ public void relax() {
+ // in case its running
+ stop();
+ stop = false;
+ thread = new Thread(this);
+ thread.setPriority(Thread.MIN_PRIORITY);
+ thread.start();
+ }
+
+ /**
+ * Used for synchronization.
+ */
+ public Object pauseObject = new String("PAUSE OBJECT");
+
+ public void resume() {
+ manualSuspend = false;
+ if(running == false) {
+ prerelax();
+ relax();
+ } else {
+ synchronized(pauseObject) {
+ pauseObject.notifyAll();
+ }
+ }
+ }
+
+ public synchronized void stop() {
+ if(thread != null) {
+ manualSuspend = false;
+ stop = true;
+ // interrupt the relaxer, in case it is paused or sleeping
+ // this should ensure that visRunnerIsRunning gets set to false
+ try { thread.interrupt(); }
+ catch(Exception ex) {
+ // the applet security manager may have prevented this.
+ // just sleep for a second to let the thread stop on its own
+ try { Thread.sleep(1000); }
+ catch(InterruptedException ie) {} // ignore
+ }
+ synchronized (pauseObject) {
+ pauseObject.notifyAll();
+ }
+ }
+ }
+
+ public void run() {
+ running = true;
+ try {
+ while (!process.done() && !stop) {
+ synchronized (pauseObject) {
+ while (manualSuspend && !stop) {
+ try {
+ pauseObject.wait();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+ process.step();
+
+ if (stop)
+ return;
+
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException ie) {
+ // ignore
+ }
+ }
+
+ } finally {
+ running = false;
+ }
+ }
+}