]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/DelayRunnable.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / DelayRunnable.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.utils.ui;
13
14 import org.eclipse.swt.widgets.Display;
15
16 /**
17  * An overridable Runnable class that can be implemented to execute the runnable
18  * with a specific delay. The delay is implemented using SWT's
19  * {@link Display#timerExec(int, Runnable)}.
20  * 
21  * <p>
22  * The nice thing is that this class allows the user to schedule runs repeatedly
23  * but guarantees that the runnable is still only ran once.
24  * </p>
25  * 
26  * <p>Use as follows:
27  * <pre>
28  *   DelayRunnable runnable = new DelayRunnable(display, delay) {
29  *       public void perform() {
30  *           // Do the things you want...
31  *       }
32  *   };
33  * </pre>
34  * After this you can do multiple schedulings of the runnable as follows,
35  * but the Runnable will only get ran once after the specified delay.
36  * <pre>
37  * runnable.scheduleRefresh();
38  * </pre>
39  * </p>
40  * 
41  * @author Tuukka Lehtonen
42  */
43 public abstract class DelayRunnable implements Runnable {
44
45     /** Default delay: 500 ms */
46     private static final int DEFAULT_REFRESH_DELAY_MS = 500; 
47     
48     private int refreshDelay;
49     
50     private volatile boolean scheduled = false;
51     
52     private Display display;
53
54     public DelayRunnable(Display display) {
55         this(display, DEFAULT_REFRESH_DELAY_MS);
56     }
57
58     public DelayRunnable(Display display, int refreshDelay) {
59         this.display = display;
60         this.refreshDelay = refreshDelay;
61     }
62
63     protected void release() {
64         scheduled = false;
65     }
66     
67     public boolean isScheduled() {
68         return scheduled;
69     }
70
71     public void scheduleRefresh() {
72         synchronized (this) {
73             if (scheduled)
74                 return;
75             scheduled = true;
76         }
77         display.asyncExec(timerSync);
78     }
79
80     /**
81      * The default implementation of run calls release first in order to allow
82      * more schedulings of this Runnable to happen. After releasing the runnable
83      * {@link #perform()} is called.
84      * 
85      * <p>
86      * If you need to override the release-behaviour of this DelayRunnable, you
87      * need to override this method instead of {@link #perform()}.
88      * </p>
89      */
90     public void run() {
91         release();
92         perform();
93     }
94     
95     /**
96      * The method to override for performing your own actions when this runnable
97      * gets ran. The default implementation is empty.
98      */
99     public void perform() {
100     }
101     
102     /**
103      * This exists because timerExec can only be ran from the SWT thread or the
104      * thread that created the tree.
105      */
106     private Runnable timerSync = new Runnable() {
107         public void run() {
108             display.timerExec(refreshDelay, DelayRunnable.this);
109         }
110     };
111     
112 }