Coverage details for edu.uci.ics.jung.visualization.DefaultVisualizationModel

LineHitsSource
1 /*
2 * Copyright (c) 2003, the JUNG Project and the Regents of the University
3 * of California
4 * All rights reserved.
5 *
6 * This software is open-source under the BSD license; see either
7 * "license.txt" or
8 * http://jung.sourceforge.net/license.txt for a description.
9 */
10 package edu.uci.ics.jung.visualization;
11  
12 import java.awt.Dimension;
13  
14 import javax.swing.event.ChangeEvent;
15 import javax.swing.event.ChangeListener;
16 import javax.swing.event.EventListenerList;
17  
18 import edu.uci.ics.jung.utils.ChangeEventSupport;
19 import edu.uci.ics.jung.utils.DefaultChangeEventSupport;
20  
21 /**
22  * The model containing state values for
23  * visualizations of graphs.
24  * Refactored and extracted from the 1.6.0 version of VisualizationViewer
25  *
26  * @author Tom Nelson
27  */
28 public class DefaultVisualizationModel implements VisualizationModel, ChangeEventSupport {
29     
300    ChangeEventSupport changeSupport =
31         new DefaultChangeEventSupport(this);
32  
33     /**
34      * a callback called during relaxer iteration
35      */
36     protected StatusCallback statusCallback;
37  
38     /**
39      * the thread that applies the current layout algorithm
40      */
41     Thread relaxer;
42     
43     /**
44      * when <code>true</code>, the relaxer thread will enter a wait state
45      * until unsuspend is called
46      */
47     boolean manualSuspend;
48     
49     /**
50      * the layout algorithm currently in use
51      */
52     protected Layout layout;
53     
54     /**
55      * how long the relaxer thread pauses between iteration loops.
56      */
570    protected long relaxerThreadSleepTime = 100L;
58     
59     protected ChangeListener changeListener;
60     
61     /**
62      *
63      * @param layout The Layout to apply, with its associated Graph
64      */
65     public DefaultVisualizationModel(Layout layout) {
660        this(layout, null);
670    }
68     
69     /**
70      *
71      * @param layout
72      * @param d The preferred size of the View that will display this graph
73      */
740    public DefaultVisualizationModel(Layout layout, Dimension d) {
750        if(changeListener == null) {
760            changeListener = new ChangeListener() {
77                 public void stateChanged(ChangeEvent e) {
78                     fireStateChanged();
79                 }
80             };
81         }
820        setGraphLayout(layout, d);
830        init();
840    }
85     
86     /**
87      * Returns the time between iterations of the
88      * Relaxer thread. The Relaxer thread sleeps for
89      * a moment before calling the Layout to update
90      * again. This tells
91      * how long the current delay is.
92      * The default, 20 milliseconds, essentially
93      * causes the system to run the next iteration
94      * with virtually no pause.
95      * @return Returns the relaxerThreadSleepTime.
96      */
97     public long getRelaxerThreadSleepTime() {
980        return relaxerThreadSleepTime;
99     }
100     
101     /**
102      * Sets the relaxerThreadSleepTime.
103      * @see #getRelaxerThreadSleepTime()
104      * @param relaxerThreadSleepTime The relaxerThreadSleepTime to set.
105      */
106     public void setRelaxerThreadSleepTime(long relaxerThreadSleepTime) {
1070        this.relaxerThreadSleepTime = relaxerThreadSleepTime;
1080    }
109     
110     /**
111      * Removes the current graph layout, and adds a new one.
112      * @param layout the new layout to use
113      * @param viewSize the size of the View that will display this layout
114      */
115     public void setGraphLayout(Layout layout, Dimension viewSize) {
1160        if(this.layout != null && this.layout instanceof AbstractLayout) {
1170            ((AbstractLayout)this.layout).removeChangeListener(changeListener);
118         }
1190        if(viewSize == null) {
1200            viewSize = new Dimension(600,600);
121         }
1220        suspend();
1230        Dimension layoutSize = layout.getCurrentSize();
124         // if the layout has NOT been initialized yet, initialize it
125         // now to the size of the VisualizationViewer window
1260        if(layoutSize == null) {
1270            layout.initialize(viewSize);
128         } else {
1290            layout.restart();
130         }
1310        layoutSize = layout.getCurrentSize();
132  
1330        this.layout = layout;
1340        if(this.layout instanceof ChangeEventSupport) {
1350            ((ChangeEventSupport)this.layout).addChangeListener(changeListener);
136         }
1370        prerelax();
1380        unsuspend();
1390    }
140  
141     /**
142      * set the graph Layout and if it is not already initialized, initialize
143      * it to the default VisualizationViewer preferred size of 600x600
144      */
145     public void setGraphLayout(Layout layout) {
1460        setGraphLayout(layout, null);
1470    }
148  
149     /**
150      * Returns the current graph layout.
151      */
152     public Layout getGraphLayout() {
1530            return layout;
154     }
155  
156     /**
157      * starts a visRunner thread without prerelaxing
158      */
159     public synchronized void restartThreadOnly() {
1600        if (visRunnerIsRunning ) {
1610            stop();
162             //throw new FatalException("Can't init while a visrunner is running");
163         }
1640        relaxer = new VisRunner();
1650        relaxer.setPriority(Thread.MIN_PRIORITY);
1660        relaxer.start();
1670    }
168     
169     /**
170      * Pre-relaxes and starts a visRunner thread
171      */
172     public synchronized void init() {
1730        if (visRunnerIsRunning ) {
1740            stop();
175            // throw new FatalException("Can't init while a visrunner is running");
176         }
1770        prerelax();
1780        relaxer = new VisRunner();
1790        relaxer.start();
1800    }
181  
182     /**
183      * Restarts layout, then calls init();
184      */
185     public synchronized void restart() {
1860        if (visRunnerIsRunning ) {
1870            stop();
188             //throw new FatalException("Can't restart while a visrunner is running");
189         }
1900        stop = false;
1910        layout.restart();
1920        init();
1930        fireStateChanged();
1940    }
195  
196     /**
197      * Runs the visualization forward a few hundred iterations (for half a
198      * second)
199      */
200     public void prerelax() {
2010        suspend();
202  
2030        int i = 0;
2040        if (layout.isIncremental()) {
205             // then increment layout for half a second
2060            long timeNow = System.currentTimeMillis();
2070            while (System.currentTimeMillis() - timeNow < 500 && !layout.incrementsAreDone()) {
2080                i++;
2090                layout.advancePositions();
210             }
211         }
2120        unsuspend();
2130    }
214     
215     /**
216      * If the visualization runner is not yet running, kick it off.
217      */
218     public synchronized void start() {
2190        synchronized (pauseObject) {
2200            pauseObject.notifyAll();
2210        }
2220    }
223  
224     /**
225      * set a flag to suspend the relaxer thread
226      */
227     public synchronized void suspend() {
2280        manualSuspend = true;
2290    }
230  
231     /**
232      * un-set the suspend flag for the relaxer thead
233      */
234     public synchronized void unsuspend() {
2350        manualSuspend = false;
2360        synchronized (pauseObject) {
2370            pauseObject.notifyAll();
2380        }
2390    }
240  
2410    public Object pauseObject = new String("PAUSE OBJECT");
242  
2430    long[] relaxTimes = new long[5];
2440    long[] paintTimes = new long[5];
2450    int relaxIndex = 0;
2460    int paintIndex = 0;
247     double paintfps, relaxfps;
248  
249  
2500    boolean stop = false;
251  
2520    boolean visRunnerIsRunning = false;
253     
254     /**
255      * the relaxer thread that applies the Layout algorithm to the graph
256      *
257      */
258     protected class VisRunner extends Thread {
259         public VisRunner() {
260             super("Relaxer Thread");
261         }
262  
263         public void run() {
264             visRunnerIsRunning = true;
265             try {
266                 while (!layout.incrementsAreDone() && !stop) {
267                     synchronized (pauseObject) {
268                         while (manualSuspend && !stop) {
269                             try {
270                                 pauseObject.wait();
271                             } catch (InterruptedException e) {
272 // System.err.println("vis runner wait interrupted");
273                             }
274                         }
275                     }
276                     long start = System.currentTimeMillis();
277                     layout.advancePositions();
278                     long delta = System.currentTimeMillis() - start;
279                     
280                     if (stop)
281                         return;
282                     
283                     String status = layout.getStatus();
284                     if (statusCallback != null && status != null) {
285                         statusCallback.callBack(status);
286                     }
287                     
288                     if (stop)
289                         return;
290                     
291                     relaxTimes[relaxIndex++] = delta;
292                     relaxIndex = relaxIndex % relaxTimes.length;
293                     relaxfps = average(relaxTimes);
294                     
295                     if (stop)
296                         return;
297                     fireStateChanged();
298                     
299                     if (stop)
300                         return;
301                     
302                     try {
303                         sleep(relaxerThreadSleepTime);
304                     } catch (InterruptedException ie) {
305 // System.err.println("vis runner sleep insterrupted");
306                     }
307                 }
308             } finally {
309                 visRunnerIsRunning = false;
310             }
311         }
312     }
313     
314     /**
315      * Returns a flag that says whether the visRunner thread is running. If
316      * it is not, then you may need to restart the thread.
317      */
318     public boolean isVisRunnerRunning() {
3190        return visRunnerIsRunning;
320     }
321  
322     /**
323      * Returns the double average of a number of long values.
324      * @param paintTimes an array of longs
325      * @return the average of the doubles
326      */
327     protected double average(long[] paintTimes) {
3280        double l = 0;
3290        for (int i = 0; i < paintTimes.length; i++) {
3300            l += paintTimes[i];
331         }
3320        return l / paintTimes.length;
333     }
334  
335     /**
336      * @param scb
337      */
338     public void setTextCallback(StatusCallback scb) {
3390        this.statusCallback = scb;
3400    }
341  
342     /**
343      * set a flag to stop the VisRunner relaxer thread
344      */
345     public synchronized void stop() {
3460        manualSuspend = false;
3470        stop = true;
348         // interrupt the relaxer, in case it is paused or sleeping
349         // this should ensure that visRunnerIsRunning gets set to false
3500        try { relaxer.interrupt(); }
3510        catch(Exception ex) {
352             // the applet security manager may have prevented this.
353             // just sleep for a second to let the thread stop on its own
3540            System.err.println("got "+ex);
3550            try { Thread.sleep(1000); }
3560            catch(InterruptedException ie) {} // swallow
3570        }
3580        synchronized (pauseObject) {
3590            pauseObject.notifyAll();
3600        }
3610    }
362  
363     /**
364      * Adds a <code>ChangeListener</code>.
365      * @param l the listener to be added
366      */
367     public void addChangeListener(ChangeListener l) {
3680        changeSupport.addChangeListener(l);
3690    }
370     
371     /**
372      * Removes a ChangeListener.
373      * @param l the listener to be removed
374      */
375     public void removeChangeListener(ChangeListener l) {
3760        changeSupport.removeChangeListener(l);
3770    }
378     
379     /**
380      * Returns an array of all the <code>ChangeListener</code>s added
381      * with addChangeListener().
382      *
383      * @return all of the <code>ChangeListener</code>s added or an empty
384      * array if no listeners have been added
385      */
386     public ChangeListener[] getChangeListeners() {
3870        return changeSupport.getChangeListeners();
388     }
389  
390     /**
391      * Notifies all listeners that have registered interest for
392      * notification on this event type. The event instance
393      * is lazily created.
394      * The primary listeners will be views that need to be repainted
395      * because of changes in this model instance
396      * @see EventListenerList
397      */
398     public void fireStateChanged() {
3990        changeSupport.fireStateChanged();
4000    }
401     
402 }

this report was generated by version 1.0.5 of jcoverage.
visit www.jcoverage.com for updates.

copyright © 2003, jcoverage ltd. all rights reserved.
Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.