/*
 * @(#)SimpleThreadedAction.java    2.6   12 April 2007
 *
 * Copyright 2007
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */


import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.beans.*;

/**
 * <p>An extension of the Java <CODE>AbstractAction</CODE>
 * class used to both simplify the programming interface
 * for a class that represents a GUI action and to arrange
 * that the action is performed in a separate thread.</p>
 *
 * <p>For convenience, this class also implements
 * <CODE>ChangeListener</CODE> and
 * <CODE>PropertyChangeListener</CODE></p>
 *
 * <p>This class is inspired by the class <code>ThreadedAction</p>
 * but is programmed directly without use of that class.</p>
 * 
 * @author  Richard Rasala
 * @version 2.6
 */
public abstract class SimpleThreadedAction
    extends AbstractAction
    implements ChangeListener, PropertyChangeListener
{
    
    /**
     * Constructs a simple threaded action with no name or icon.
     */
    public SimpleThreadedAction() {
        super();
    }
    
    /**
     * Constructs a simple threaded action with the given name but no icon.
     *
     * @param name the name for this action
     */
    public SimpleThreadedAction(String name) {
        super(name);
    }
    
    /**
     * Constructs a simple threaded action with the given name and icon.
     *
     * @param name the name for this action
     * @param icon the icon for this action
     */
    public SimpleThreadedAction(String name, Icon icon) {
        super(name, icon);
    }

    ////////////////////
    // ActionListener //
    ////////////////////
    
    /**
     * Performs this action
     * by calling the
     * <CODE>{@link #performThreaded() performThreaded}</CODE> method
     * which executes the simplified
     * <CODE>{@link #perform() perform}</CODE> method
     * in a separate thread
     *
     * @param evt an object encapsulating an event that triggered this action
     *     this parameter is ignored
     */
    public final void actionPerformed(ActionEvent evt) {
        performThreaded();
    }
    
    ////////////////////
    // ChangeListener //
    ////////////////////
    
    /**
     * Performs this state change action
     * by calling the
     * <CODE>{@link #performThreaded() performThreaded}</CODE> method
     * which executes the simplified
     * <CODE>{@link #perform() perform}</CODE> method
     * in a separate thread
     *
     * @param evt an object encapsulating an event that triggered this action
     *     this parameter is ignored
     */
    public final void stateChanged(ChangeEvent evt) {
        performThreaded();
    }
    
    ////////////////////////////
    // PropertyChangeListener //
    ////////////////////////////
    
    /**
     * Performs this property change action
     * by calling the
     * <CODE>{@link #performThreaded() performThreaded}</CODE> method
     * which executes the simplified
     * <CODE>{@link #perform() perform}</CODE> method
     * in a separate thread
     *
     * @param evt an object encapsulating an event that triggered this action
     *     this parameter is ignored
     */
    public final void propertyChange(PropertyChangeEvent evt) {
        performThreaded();
    }
    
    ////////////////
    // Public API //
    ////////////////

    /**
     * <p>Performs the tasks encapsulated by this action.</p>
     *
     * <p>Subclasses should override this method to provide tasks this action
     * performs.</p>
     * 
     * <p>If this method is called directly, the tasks will be executed in the
     * same thread.  To cause the tasks to be performed in a separate thread,
     * call the method <CODE>{@link #performThreaded() performThreaded}</CODE>.</p>
     */
    public abstract void perform();
    
    
    /**
     * <p>Executes the <CODE>{@link #perform() perform}</CODE> method
     * in a separate thread.</p>
     * 
     * <p>To utilize this action algorithmically, this method should be called
     * rather than the <CODE>{@link #perform() perform}</CODE> method.</p>
     */
    public final void performThreaded() {
        // construct the thread
        Thread thread = new Thread() {
            public void run() {
                perform();
            }
        };
        
        // run the thread
        thread.setDaemon(true);
        thread.start();
    }
}

