]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DisposingPolicy.java
a3cd08b068745f43bc0599fb04968b738b4ef9dc
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / DisposingPolicy.java
1 package org.simantics.modeling.ui.diagramEditor;
2
3 import gnu.trove.map.hash.TObjectLongHashMap;
4
5 import java.util.ArrayDeque;
6
7 import org.eclipse.swt.widgets.Display;
8
9
10 public class DisposingPolicy {
11     
12     public static final boolean DEBUG = false;
13     
14     public static final int MAX_QUEUE_LENGTH = 8;
15     public static final long DISPOSE_TIME = 30000L; // ms
16     public static final long MIN_DELAY = 200L; // ms
17     
18     private ArrayDeque<Runnable> disposerQueue = new ArrayDeque<Runnable>(MAX_QUEUE_LENGTH);
19     private TObjectLongHashMap<Runnable> disposeTime =
20             new TObjectLongHashMap<Runnable>(MAX_QUEUE_LENGTH);
21     private Runnable currentlyScheduled = null;
22     
23     private Runnable disposeOne = new Runnable() {
24         @Override
25         public void run() {
26             if(!disposerQueue.isEmpty()) {
27                 Runnable runnable = disposerQueue.removeFirst();
28                 disposeTime.remove(runnable);
29                 currentlyScheduled = null;
30                 runnable.run();
31                 if(DEBUG)
32                     System.out.println("Executed disposer " + runnable);
33                 if(!disposerQueue.isEmpty())
34                     scheduleDispose();
35             }
36         }
37     };
38     
39     private void scheduleDispose() {
40         currentlyScheduled = disposerQueue.peekFirst();
41         long delay = Math.max(
42                 disposeTime.get(currentlyScheduled) - System.currentTimeMillis(),
43                 MIN_DELAY);
44         Display.getCurrent().timerExec((int)delay, disposeOne);
45         if(DEBUG)
46             System.out.println("Scheduled disposer " + currentlyScheduled + " in " + delay + " ms");
47     }
48     
49     /**
50      * Runs the disposer either after DISPOSE_TIME or when there are
51      * more than MAX_QUEUE_LENGTH disposers active and this is first
52      * of them (by activation order). This method must be called from
53      * UI thread.
54      */
55     public void addDisposer(Runnable disposer) {
56         if(DEBUG)
57             System.out.println("Added disposer " + disposer);
58         if(disposeTime.contains(disposer))
59             return;
60         if(disposerQueue.size() >= MAX_QUEUE_LENGTH)
61             disposeOne.run();
62         disposerQueue.addLast(disposer);
63         disposeTime.put(disposer, System.currentTimeMillis()+DISPOSE_TIME);
64         if(disposerQueue.size() == 1)
65             scheduleDispose();
66     }
67     
68     /**
69      * Cancels a disposer added before. This method must be called from
70      * UI thread.
71      */
72     public void removeDisposer(Runnable disposer) {
73         if(DEBUG)
74             System.out.println("Removed disposer " + disposer);
75         disposerQueue.remove(disposer);
76         disposeTime.remove(disposer);
77         if(disposer == currentlyScheduled) {
78             currentlyScheduled = null;
79             if(!disposerQueue.isEmpty())
80                 scheduleDispose();
81         }
82     }
83     
84 }