package org.argeo.suite.ui.widgets; import java.util.Timer; import java.util.TimerTask; import org.eclipse.rap.rwt.service.ServerPushSession; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Text; /** * Text that introduce a timer in the attached ModifyListener. * * Note that corresponding ModifyEvent will *NOT* be sent in the UI thread. * Calling ModifierInstance must be implemented in consequence. Note also that * this delayed text only manages one listener at a time. * */ public class DelayedText { final int delay; private Object lock = new Object(); private MyTimer timer = new MyTimer(DelayedText.this.toString()); private ModifyListener delayedModifyListener; private ServerPushSession pushSession; private Text text; private ModifyListener modifyListener = new ModifyListener() { private static final long serialVersionUID = 1117506414462641980L; public void modifyText(ModifyEvent e) { ModifyEvent delayedEvent = null; synchronized (lock) { if (delayedModifyListener != null) { Event tmpEvent = new Event(); tmpEvent.widget = text; tmpEvent.display = e.display; tmpEvent.data = e.data; tmpEvent.time = e.time; delayedEvent = new ModifyEvent(tmpEvent); } } final ModifyEvent timerModifyEvent = delayedEvent; synchronized (timer) { if (timer.timerTask != null) { timer.timerTask.cancel(); timer.timerTask = null; } if (delayedEvent != null) { timer.timerTask = new TimerTask() { public void run() { synchronized (lock) { delayedModifyListener.modifyText(timerModifyEvent); // Bad approach: it is not a good idea to put a // display.asyncExec in a lock... // DelayedText.this.getDisplay().asyncExec(new // Runnable() { // @Override // public void run() { // delayedModifyListener.modifyText(timerModifyEvent); // } // } // ); } synchronized (timer) { timer.timerTask = null; } } }; timer.schedule(timer.timerTask, delay); if (pushSession != null) pushSession.start(); } } }; }; public DelayedText(Composite parent, int style, int delayInMs) { // super(parent, style); text = new Text(parent, style); this.delay = delayInMs; text.addModifyListener(modifyListener); } /** * Adds a modify text listener that will be delayed. If another Modify event * happens during the waiting delay, the older event will be canceled an a new * one will be scheduled after another new delay. */ public void addDelayedModifyListener(ServerPushSession pushSession, ModifyListener listener) { synchronized (lock) { delayedModifyListener = listener; this.pushSession = pushSession; } } public void removeDelayedModifyListener(ModifyListener listener) { synchronized (lock) { delayedModifyListener = null; pushSession = null; } } private class MyTimer extends Timer { private TimerTask timerTask = null; public MyTimer(String name) { super(name); } } public Text getText() { return text; } public void close() { if (pushSession != null) pushSession.stop(); if (timer != null) timer.cancel(); }; }