View Javadoc
1   /*
2    * Copyright (c) 2005, The JUNG Authors
3    * All rights reserved.
4    *
5    * This software is open-source under the BSD license; see either "license.txt"
6    * or https://github.com/jrtom/jung/blob/master/LICENSE for a description.
7    *
8    * 
9    */
10  package edu.uci.ics.jung.algorithms.layout.util;
11  
12  import edu.uci.ics.jung.algorithms.util.IterativeContext;
13  
14  /**
15   * 
16   * Implementation of a relaxer thread for layouts.
17   * Extracted from the {@code VisualizationModel} in previous
18   * versions of JUNG.
19   * 
20   * @author Tom Nelson - tomnelson@dev.java.net
21   *
22   */
23  public class VisRunner implements Relaxer, Runnable {
24  	
25  	protected boolean running;
26  	protected IterativeContext process;
27  	protected boolean stop;
28  	protected boolean manualSuspend;
29  	protected Thread thread;
30  	
31  	/**
32  	 * how long the relaxer thread pauses between iteration loops.
33  	 */
34  	protected long sleepTime = 100L;
35  
36  	
37  	/**
38  	 * Creates an instance for the specified process.
39  	 * @param process the process (generally a layout) for which this instance is created
40  	 */
41  	public VisRunner(IterativeContext process) {
42  		this.process = process;
43  	}
44  
45  	/**
46  	 * @return the relaxerThreadSleepTime
47  	 */
48  	public long getSleepTime() {
49  		return sleepTime;
50  	}
51  
52  	/**
53  	 * @param sleepTime the sleep time to set for this thread
54  	 */
55  	public void setSleepTime(long sleepTime) {
56  		this.sleepTime = sleepTime;
57  	}
58  	
59  	public void prerelax() {
60  		manualSuspend = true;
61  		long timeNow = System.currentTimeMillis();
62  		while (System.currentTimeMillis() - timeNow < 500 && !process.done()) {
63  			process.step();
64  		}
65  		manualSuspend = false;
66  	}
67  
68  	public void pause() {
69  		manualSuspend = true;
70  	}
71  
72  	public void relax() {
73  		// in case its running
74  		stop();
75  		stop = false;
76  		thread = new Thread(this);
77  		thread.setPriority(Thread.MIN_PRIORITY);
78  		thread.start();
79  	}
80  	
81  	/**
82  	 * Used for synchronization.
83  	 */
84  	public Object pauseObject = new String("PAUSE OBJECT");
85  
86  	public void resume() {
87  		manualSuspend = false;
88  		if(running == false) {
89  			prerelax();
90  			relax();
91  		} else {
92  			synchronized(pauseObject) {
93  				pauseObject.notifyAll();
94  			}
95  		}
96  	}
97  
98  	public synchronized void stop() {
99  		if(thread != null) {
100 			manualSuspend = false;
101 			stop = true;
102 			// interrupt the relaxer, in case it is paused or sleeping
103 			// this should ensure that visRunnerIsRunning gets set to false
104 			try { thread.interrupt(); }
105 			catch(Exception ex) {
106 				// the applet security manager may have prevented this.
107 				// just sleep for a second to let the thread stop on its own
108 				try { Thread.sleep(1000); }
109 				catch(InterruptedException ie) {} // ignore
110 			}
111 			synchronized (pauseObject) {
112 				pauseObject.notifyAll();
113 			}
114 		}
115 	}
116 
117 	public void run() {
118 	    running = true;
119 	    try {
120 	        while (!process.done() && !stop) {
121 	            synchronized (pauseObject) {
122 	                while (manualSuspend && !stop) {
123 	                    try {
124 	                        pauseObject.wait();
125 	                    } catch (InterruptedException e) {
126 	                    	// ignore
127 	                    }
128 	                }
129 	            }
130 	            process.step();
131 	            
132 	            if (stop)
133 	                return;
134 	            
135 	            try {
136 	                Thread.sleep(sleepTime);
137 	            } catch (InterruptedException ie) {
138 	            	// ignore
139 	            }
140 	        }
141 
142 	    } finally {
143 	        running = false;
144 	    }
145 	}
146 }