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