package sk.stuba.fiit.perconik.eclipse.swt.widgets;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import com.google.common.base.Supplier;
import org.eclipse.swt.widgets.Display;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
public abstract class DisplayExecutor implements Executor {
final Display display;
DisplayExecutor(final Display display) {
this.display = checkNotNull(display);
}
public static DisplayExecutor defaultAsynchronous() {
return createAsynchronous(Display.getDefault());
}
public static DisplayExecutor defaultSynchronous() {
return createSynchronous(Display.getDefault());
}
public static DisplayExecutor currentAsynchronous() {
return createAsynchronous(Display.getCurrent());
}
public static DisplayExecutor currentSynchronous() {
return createSynchronous(Display.getCurrent());
}
public static DisplayExecutor createAsynchronous(final Display display) {
return new Asynchronous(display);
}
public static DisplayExecutor createSynchronous(final Display display) {
return new Synchronous(display);
}
static final class Asynchronous extends DisplayExecutor {
Asynchronous(final Display display) {
super(display);
}
@Override
public void execute(final Runnable command) {
this.display.asyncExec(command);
}
@Override
<V> Supplier<V> submit(final DisplayTask<V> task) {
throw new UnsupportedOperationException("Unable to asynchronously execute display task");
}
}
static final class Synchronous extends DisplayExecutor {
Synchronous(final Display display) {
super(display);
}
private static final class Call<V> implements Runnable, Supplier<V> {
private final Callable<V> callable;
private V result;
Call(final Callable<V> callable) {
this.callable = checkNotNull(callable);
}
public void run() {
try {
this.result = this.callable.call();
} catch (Throwable failure) {
propagate(failure);
}
}
public V get() {
return this.result;
}
}
@Override
public void execute(final Runnable command) {
this.display.syncExec(command);
}
@Override
<V> Supplier<V> submit(final DisplayTask<V> task) {
Call<V> call = new Call<>(task);
this.execute(call);
return call;
}
}
abstract <V> Supplier<V> submit(DisplayTask<V> task);
public final Display getDisplay() {
return this.display;
}
}