Simplify project structure
[gpl/argeo-suite.git] / org.argeo.suite.ui / src / org / argeo / suite / ui / widgets / DelayedText.java
diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java
new file mode 100644 (file)
index 0000000..a03c250
--- /dev/null
@@ -0,0 +1,127 @@
+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();
+       };
+
+}