package org.tessell.util;
import org.tessell.dispatch.client.events.DispatchActionEvent;
import org.tessell.dispatch.client.events.DispatchActionHandler;
import org.tessell.dispatch.client.events.DispatchFailureEvent;
import org.tessell.dispatch.client.events.DispatchFailureHandler;
import org.tessell.dispatch.client.events.DispatchResultEvent;
import org.tessell.dispatch.client.events.DispatchResultHandler;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.user.client.ui.HasText;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.HandlerRegistration;
/** Updates {@link HasText} elements on the screen with the outstanding/total dispatch actions, for testing. */
public class OutstandingWatcher {
private final HasText outstandingText;
private final HasText totalText;
private int outstanding;
private int total;
private boolean isUpdateScheduled;
public OutstandingWatcher(HasText outstandingText, HasText totalText) {
this.outstandingText = outstandingText;
this.totalText = totalText;
}
/** Starts listening on {@code bus}. */
public HandlerRegistration[] listenOn(EventBus bus) {
HandlerRegistration a = bus.addHandler(DispatchActionEvent.getType(), new OnAction());
HandlerRegistration b = bus.addHandler(DispatchResultEvent.getType(), new OnResult());
HandlerRegistration c = bus.addHandler(DispatchFailureEvent.getType(), new OnFailure());
return new HandlerRegistration[] { a, b, c };
}
private void scheduleUpdate() {
if (GWT.isClient()) {
if (outstanding > 0) {
// if outstanding > 0, we want to update the DOM right away
update();
} else if (!isUpdateScheduled) {
// but if outstanding == 0, just because this request is done
// doesn't mean another won't be started within this event loop
// by some other business logic. to avoid selenium potentially
// seems a very brief "0", defer this update until the current
// loop is finished.
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
update();
isUpdateScheduled = false;
}
});
isUpdateScheduled = true;
}
} else {
// during unit tests just update the view immediately
update();
}
}
private void update() {
outstandingText.setText(Integer.toString(outstanding));
totalText.setText(Integer.toString(total));
}
/** Increment total/outstanding. */
private class OnAction implements DispatchActionHandler {
public void onDispatchAction(DispatchActionEvent event) {
outstanding++;
total++;
scheduleUpdate();
}
}
/** Decrement outstanding. */
private class OnResult implements DispatchResultHandler {
public void onDispatchResult(DispatchResultEvent event) {
outstanding--;
scheduleUpdate();
}
}
/** Decrement outstanding. */
private class OnFailure implements DispatchFailureHandler {
public void onDispatchFailure(DispatchFailureEvent event) {
outstanding--;
scheduleUpdate();
}
}
}