/* * @(#)BackgroundTask.java * * Copyright (c) 1996-2010 The authors and contributors of JHotDraw. * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.gui; import javax.annotation.Nullable; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; /** * This is an abstract class that you can subclass to * perform GUI-related work in a dedicated event dispatcher. * <p> * This class is similar to SwingWorker but less complex. * * @author Werner Randelshofer * @version $Id$ */ public abstract class BackgroundTask implements Runnable { private Throwable error; // see getError(), setError() /** * Calls #construct on the current thread and invokes * #done on the AWT event dispatcher thread. */ @Override public final void run() { try { construct(); } catch (Throwable e) { setError(e); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { failed(getError()); finished(); } }); return; } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { done(); } finally { finished(); } } }); } /** * Compute the value to be returned by the <code>get</code> method. */ @Nullable protected abstract void construct() throws Exception; /** * Called on the event dispatching thread (not on the worker thread) * after the <code>construct</code> method has returned without throwing * an error. * <p> * The default implementation does nothing. Subclasses may override this * method to perform done actions on the Event Dispatch Thread. */ protected void done() { } /** * Called on the event dispatching thread (not on the worker thread) * after the <code>construct</code> method has thrown an error. * <p> * The default implementation prints a stack trace. Subclasses may override * this method to perform failure actions on the Event Dispatch Thread. * * @param error The error thrown by construct. */ protected void failed(Throwable error) { JOptionPane.showMessageDialog(null, error.getMessage()==null?error.toString():error.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); error.printStackTrace(); } /** * Called on the event dispatching thread (not on the worker thread) * after the <code>construct</code> method has finished and after * done() or failed() has been invoked. * <p> * The default implementation does nothing. Subclasses may override this * method to perform completion actions on the Event Dispatch Thread. */ protected void finished() { } /** * Get the error produced by the worker thread, or null if it * hasn't thrown one. */ protected synchronized Throwable getError() { return error; } /** * Set the error thrown by constrct. */ private synchronized void setError(Throwable x) { error = x; } /** * Starts the Worker on an internal worker thread. */ public void start() { new Thread(this).start(); } }