/*
* 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;
}
}
}