/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package com.bc.ceres.swing.progress; import javax.swing.SwingWorker; import java.awt.Component; import java.awt.Dialog; import java.awt.Frame; import java.awt.Window; import java.util.concurrent.CountDownLatch; /** * A swing worker which may pop-up a progress monitor dialog. */ public abstract class ProgressMonitorSwingWorker<T, V> extends SwingWorker<T, V> { private final CountDownLatch unBlock; private final DialogProgressMonitor dialogPM; private boolean blocking; private Window blockingWindow; protected ProgressMonitorSwingWorker(Component parentComponent, String title) { unBlock = new CountDownLatch(1); dialogPM = new DialogProgressMonitor(parentComponent, title, Dialog.ModalityType.MODELESS); } /** * Overridden in order to call the {@link #doInBackground(com.bc.ceres.core.ProgressMonitor) doInBackground} * method with a {@link com.bc.ceres.core.ProgressMonitor ProgressMonitor}. * * @return the computed result * * @throws Exception */ @Override protected final T doInBackground() throws Exception { T value; try { value = doInBackground(dialogPM); } finally { dialogPM.done(); if (blocking) { unBlock.await(); unblock(); } } return value; } /** * Computes a result, or throws an exception if unable to do so. * <p/> * <p>Note that this method is executed only once in a background thread.</p> * * @param pm the progress monitor * * @return the computed result * * @throws Exception if unable to compute a result */ protected abstract T doInBackground(com.bc.ceres.core.ProgressMonitor pm) throws Exception; /** * Similar to the {@link #execute()} method, but blocks the current thread until * this worker computed its result. However, this method will not * block the <i>Event Dispatch Thread</i>. */ public final void executeWithBlocking() { this.blocking = true; dialogPM.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); execute(); block(); this.blocking = false; } private void block() { if (blockingWindow == null) { blockingWindow = createBlockingWindow(); unBlock.countDown(); blockingWindow.setVisible(true); } } private void unblock() { if (blockingWindow != null) { blockingWindow.dispose(); blockingWindow = null; } } private static Window createBlockingWindow() { final Dialog window = new Dialog((Frame) null); window.setUndecorated(true); window.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); window.setBounds(0, 0, 0, 0); window.setFocusableWindowState(false); return window; } }