package edu.ualberta.med.biobank.mvp.event.impl;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
public abstract class DelayedValueChangeHandler<T> implements
ValueChangeHandler<T> {
private static final ScheduledExecutorService SERVICE = Executors
.newScheduledThreadPool(10);
private final ScheduledExecutorService service;
private final int delay;
private final TimeUnit unit;
private ScheduledFuture<?> future;
public DelayedValueChangeHandler(int delay) {
this(SERVICE, delay, TimeUnit.MILLISECONDS);
}
public DelayedValueChangeHandler(ScheduledExecutorService service, int delay) {
this(service, delay, TimeUnit.MILLISECONDS);
}
public DelayedValueChangeHandler(ScheduledExecutorService service,
int delay, TimeUnit unit) {
this.service = service;
this.delay = delay;
this.unit = unit;
}
@Override
public synchronized void onValueChange(ValueChangeEvent<T> event) {
if (future != null) {
future.cancel(false);
}
future = service.schedule(new DelayedEventRunnable(event), delay, unit);
}
/**
* Will only be called with the last {@link ValueChangeEvent} fired in the
* last n milliseconds, where n is the delay. For example, if n = 500ms and
* 3 events are fired no more than 500ms apart, then only the third event
* will be called.
* <p>
* This method should be executed quickly as it may cause other delayed
* events to be handled late.
*
* @param event
*/
protected abstract void onDelayedValueChange(ValueChangeEvent<T> event);
private class DelayedEventRunnable implements Runnable {
private ValueChangeEvent<T> event;
public DelayedEventRunnable(ValueChangeEvent<T> event) {
this.event = event;
}
@Override
public void run() {
onDelayedValueChange(event);
}
}
}