View Javadoc
1   package org.argeo.connect.ui.widgets;
2   
3   import java.util.Timer;
4   import java.util.TimerTask;
5   
6   import org.eclipse.rap.rwt.service.ServerPushSession;
7   import org.eclipse.swt.events.ModifyEvent;
8   import org.eclipse.swt.events.ModifyListener;
9   import org.eclipse.swt.widgets.Composite;
10  import org.eclipse.swt.widgets.Event;
11  import org.eclipse.swt.widgets.Text;
12  
13  /**
14   * Text that introduce a timer in the attached ModifyListener.
15   * 
16   * Note that corresponding ModifyEvent will *NOT* be sent in the UI thread.
17   * Calling ModifierInstance must be implemented in consequence. Note also that
18   * this delayed text only manages one listener at a time.
19   *
20   */
21  public class DelayedText {
22  	final int delay;
23  	private Object lock = new Object();
24  	private MyTimer timer = new MyTimer(DelayedText.this.toString());
25  	private ModifyListener delayedModifyListener;
26  	private ServerPushSession pushSession;
27  
28  	private Text text;
29  
30  	private ModifyListener modifyListener = new ModifyListener() {
31  		private static final long serialVersionUID = 1117506414462641980L;
32  
33  		public void modifyText(ModifyEvent e) {
34  			ModifyEvent delayedEvent = null;
35  			synchronized (lock) {
36  				if (delayedModifyListener != null) {
37  					Event tmpEvent = new Event();
38  					tmpEvent.widget = text;
39  					tmpEvent.display = e.display;
40  					tmpEvent.data = e.data;
41  					tmpEvent.time = e.time;
42  					delayedEvent = new ModifyEvent(tmpEvent);
43  				}
44  			}
45  			final ModifyEvent timerModifyEvent = delayedEvent;
46  
47  			synchronized (timer) {
48  				if (timer.timerTask != null) {
49  					timer.timerTask.cancel();
50  					timer.timerTask = null;
51  				}
52  
53  				if (delayedEvent != null) {
54  					timer.timerTask = new TimerTask() {
55  						public void run() {
56  							synchronized (lock) {
57  								delayedModifyListener.modifyText(timerModifyEvent);
58  								// Bad approach: it is not a good idea to put a
59  								// display.asyncExec in a lock...
60  								// DelayedText.this.getDisplay().asyncExec(new
61  								// Runnable() {
62  								// @Override
63  								// public void run() {
64  								// delayedModifyListener.modifyText(timerModifyEvent);
65  								// }
66  								// }
67  								// );
68  							}
69  							synchronized (timer) {
70  								timer.timerTask = null;
71  							}
72  						}
73  					};
74  					timer.schedule(timer.timerTask, delay);
75  					if (pushSession != null)
76  						pushSession.start();
77  				}
78  			}
79  		};
80  	};
81  
82  	public DelayedText(Composite parent, int style, int delayInMs) {
83  		// super(parent, style);
84  		text = new Text(parent, style);
85  		this.delay = delayInMs;
86  		text.addModifyListener(modifyListener);
87  	}
88  
89  	/**
90  	 * Adds a modify text listener that will be delayed. If another Modify event
91  	 * happens during the waiting delay, the older event will be canceled an a new
92  	 * one will be scheduled after another new delay.
93  	 */
94  	public void addDelayedModifyListener(ServerPushSession pushSession, ModifyListener listener) {
95  		synchronized (lock) {
96  			delayedModifyListener = listener;
97  			this.pushSession = pushSession;
98  		}
99  	}
100 
101 	public void removeDelayedModifyListener(ModifyListener listener) {
102 		synchronized (lock) {
103 			delayedModifyListener = null;
104 			pushSession = null;
105 		}
106 	}
107 
108 	private class MyTimer extends Timer {
109 		private TimerTask timerTask = null;
110 
111 		public MyTimer(String name) {
112 			super(name);
113 		}
114 	}
115 
116 	public Text getText() {
117 		return text;
118 	};
119 
120 }