package games.strategy.ui;
import static com.google.common.base.Preconditions.checkNotNull;
import java.awt.Window;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.SwingWorker;
import com.google.common.annotations.VisibleForTesting;
/**
* Manages the display of a window during the execution of a {@code SwingWorker}.
*
* <p>
* Use this class when it is necessary to display progress during a potentially long-running operation. If the <i>Event
* Dispatch Thread</i> must be blocked until the operation is complete (i.e. the user should not be allowed to perform
* any other actions in the UI), it is recommended you use a modal dialog.
* </p>
*
* <p>
* For example:
* </p>
*
* <pre>
* JDialog dialog = new JDialog(owner, true);
* swingWorker.addPropertyChangeListener(
* new SwingWorkerCompletionWaiter(dialog));
* swingWorker.execute();
* // the dialog will be visible between the
* // SwingWorker STARTED and DONE states
* </pre>
*/
public final class SwingWorkerCompletionWaiter implements PropertyChangeListener {
@VisibleForTesting
static final String SWING_WORKER_STATE_PROPERTY_NAME = "state";
private final ProgressWindow progressWindow;
/**
* Initializes a new instance of the {@code SwingWorkerCompletionWaiter} class.
*
* @param window The window to display while the operation is in progress; must not be {@code null}.
*/
public SwingWorkerCompletionWaiter(final Window window) {
this.progressWindow = ProgressWindow.fromWindow(checkNotNull(window));
}
@VisibleForTesting
SwingWorkerCompletionWaiter(final ProgressWindow progressWindow) {
this.progressWindow = progressWindow;
}
@Override
public void propertyChange(final PropertyChangeEvent event) {
if (SWING_WORKER_STATE_PROPERTY_NAME.equals(event.getPropertyName())) {
if (SwingWorker.StateValue.STARTED == event.getNewValue()) {
progressWindow.open();
} else if (SwingWorker.StateValue.DONE == event.getNewValue()) {
progressWindow.close();
}
}
}
@VisibleForTesting
static interface ProgressWindow {
void close();
void open();
static ProgressWindow fromWindow(final Window window) {
return new ProgressWindow() {
@Override
public void close() {
window.setVisible(false);
window.dispose();
}
@Override
public void open() {
window.setVisible(true);
}
};
}
}
}