/*
 * @(#)MouseActionAdapter.java    2.4.0   2 May 2006
 *
 * Copyright 2006
 * 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.
 */

package edu.neu.ccs.gui;

import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
import javax.swing.*;
import javax.swing.event.*;

/**
 * <P>An adapter class for receiving mouse input events
 * and performing actions in response to those events.</P>
 *
 * @author  Richard Rasala
 * @author  Jeff Raab
 * @version 2.4.0
 * @since   1.0
 */
public class MouseActionAdapter
    implements MouseInputListener, Cloneable, Serializable 
{
    /** 
     * List of action listeners to be performed upon the
     * notification of mouse clicked events. 
     */
    protected ActionSequence clickedActions = new ActionSequence();
    
    /** 
     * List of action listeners to be performed upon the
     * notification of mouse entered events. 
     */
    protected ActionSequence enteredActions = new ActionSequence();
    
    /** 
     * List of action listeners to be performed upon the
     * notification of mouse exited events. 
     */
    protected ActionSequence exitedActions = new ActionSequence();
    
    /** 
     * List of action listeners to be performed upon the
     * notification of mouse pressed events. 
     */
    protected ActionSequence pressedActions = new ActionSequence();
    
    /** 
     * List of action listeners to be performed upon the
     * notification of mouse released events. 
     */
    protected ActionSequence releasedActions = new ActionSequence();
    
    /** 
     * List of action listeners to be performed upon the
     * notification of mouse dragged events. 
     */
    protected ActionSequence draggedActions = new ActionSequence();
    
    /** 
     * List of action listeners to be performed upon the
     * notification of mouse moved events. 
     */
    protected ActionSequence movedActions = new ActionSequence();
    
    
    //////////////////
    // Constructors //
    //////////////////
    
    /**
     * Constructs a mouse action adapter.
     */
    public MouseActionAdapter() {
        this(null);
    }
    
    
    /**
     * Constructs a mouse action adapter
     * listening for mouse and mouse motion events
     * generated by the given component.
     *
     * If <CODE>null</CODE>, this adapter does not listen
     * to a particular component by default.
     *
     * @param target the component that is listened to
     */
    public MouseActionAdapter(Component target) {
        addAsListenerTo(target);
    }
    
    
    ///////////////////
    // MouseListener //
    ///////////////////
    
    /**
     * Performs the stored action listener sequence 
     * when the mouse is clicked.
     *
     * @param evt the mouse event
     * @see #addMouseClickedAction(ActionListener)
     * @see #getMouseClickedActions()
     */
    public final void mouseClicked(MouseEvent evt) {
        clickedActions.actionPerformed(
            new MouseActionEvent(evt, evt.getSource()));
    }
    
    
    /**
     * Performs the stored action listener sequence 
     * when the mouse enters the component.
     *
     * @param evt the mouse event
     * @see #addMouseEnteredAction(ActionListener)
     * @see #getMouseEnteredActions()
     */
    public final void mouseEntered(MouseEvent evt) {
        enteredActions.actionPerformed(
            new MouseActionEvent(evt, evt.getSource()));
    }
    
    
    /**
     * Performs the stored action listener sequence 
     * when the mouse exits the component.
     *
     * @param evt the mouse event
     * @see #addMouseExitedAction(ActionListener)
     * @see #getMouseExitedActions()
     */
    public final void mouseExited(MouseEvent evt) {
        exitedActions.actionPerformed(
            new MouseActionEvent(evt, evt.getSource()));
    }
    
    
    /**
     * Performs the stored action listener sequence 
     * when a mouse button is pressed.
     *
     * @param evt the mouse event
     * @see #addMousePressedAction(ActionListener)
     * @see #getMousePressedActions()
     */
    public final void mousePressed(MouseEvent evt) {
        pressedActions.actionPerformed(
            new MouseActionEvent(evt, evt.getSource()));
    }
    
    
    /**
     * Performs the stored action listener sequence 
     * when the mouse button is released.
     *
     * @param evt the mouse event
     * @see #addMouseReleasedAction(ActionListener)
     * @see #getMouseReleasedActions()
     */
    public final void mouseReleased(MouseEvent evt) {
        releasedActions.actionPerformed(
            new MouseActionEvent(evt, evt.getSource()));
    }
    
    
    /////////////////////////
    // MouseMotionListener //
    /////////////////////////
    
    /**
     * Performs the stored action listener sequence
     * when the mouse is dragged.
     *
     * @param evt the mouse event
     * @see #addMouseDraggedAction(ActionListener)
     * @see #getMouseDraggedActions()
     */
    public final void mouseDragged(MouseEvent evt) {
        draggedActions.actionPerformed(
            new MouseActionEvent(evt, evt.getSource()));
    }
    
    
    /**
     * Performs the stored action listener sequence 
     * when the mouse is moved.
     *
     * @param evt the mouse event
     * @see #addMouseMovedAction(ActionListener)
     * @see #getMouseMovedActions()
     */
    public final void mouseMoved(MouseEvent evt) {
        movedActions.actionPerformed(
            new MouseActionEvent(evt, evt.getSource()));
    }
    
    
    ////////////////
    // Public API //
    ////////////////
    
    /**
     * Registers this adapter to receive mouse events
     * generated by the given component.
     *
     * If the given component is <CODE>null</CODE>,
     * no changes are made to this adapter.
     *
     * @param c the component that this adapter should listen to
     */
    public void addAsListenerTo(Component c) {
        if (c == null)
            return;
            
        c.addMouseListener(this);
        c.addMouseMotionListener(this);
    }
    
    
    /**
     * Deregisters this adapter from receiving mouse events
     * generated by the given component.
     *
     * If the given component is <CODE>null</CODE>,
     * no changes are made to this adapter.
     *
     * @param c the component that this adapter should 
     *      stop listening to
     */
    public void removeAsListenerTo(Component c) {
        if (c == null)
            return;

        c.removeMouseListener(this);
        c.removeMouseMotionListener(this);
    }
    
    
    /**
     * Adds the given action listener to the action sequence 
     * so that it will be performed 
     * when the mouse is clicked.
     *
     * @param a the desired action listener
     * @see #removeMouseClickedAction(ActionListener)
     * @see #setMouseClickedActions(ActionSequence)
     * @see #getMouseClickedActions()
     */
    public void addMouseClickedAction(ActionListener a) {
        clickedActions.add(a);
    }
    
    
    /**
     * Adds the given action listener to the action sequence 
     * so that it will be performed 
     * when the mouse enters the component.
     *
     * @param a the desired action listener
     * @see #removeMouseEnteredAction(ActionListener)
     * @see #setMouseEnteredActions(ActionSequence)
     * @see #getMouseEnteredActions()
     */
    public void addMouseEnteredAction(ActionListener a) {
        enteredActions.add(a);
    }
    
    
    /**
     * Adds the given action to the action sequence 
     * so that it will be performed 
     * when the mouse exits the component.
     *
     * @param a the desired action listener
     * @see #removeMouseExitedAction(ActionListener)
     * @see #setMouseExitedActions(ActionSequence)
     * @see #getMouseExitedActions()
     */
    public void addMouseExitedAction(ActionListener a) {
        exitedActions.add(a);
    }
    
    
    /**
     * Adds the given action listener to the action sequence 
     * so that it will be performed 
     * when the mouse button is pressed.
     *
     * @param a the desired action listener
     * @see #removeMousePressedAction(ActionListener)
     * @see #setMousePressedActions(ActionSequence)
     * @see #getMousePressedActions()
     */
    public void addMousePressedAction(ActionListener a) {
        pressedActions.add(a);
    }
    
    
    /**
     * Adds the given action listener to the action sequence 
     * so that it will be performed 
     * when the mouse button is released.
     *
     * @param a the desired action listener
     * @see #removeMouseReleasedAction(ActionListener)
     * @see #setMouseReleasedActions(ActionSequence)
     * @see #getMouseReleasedActions()
     */
    public void addMouseReleasedAction(ActionListener a) {
        releasedActions.add(a);
    }
    
    
    /**
     * Adds the given action listener to the action sequence 
     * so that it will be performed 
     * when the mouse is dragged.
     *
     * @param a the desired action listener
     * @see #removeMouseDraggedAction(ActionListener)
     * @see #setMouseDraggedActions(ActionSequence)
     * @see #getMouseDraggedActions()
     */
    public void addMouseDraggedAction(ActionListener a) {
        draggedActions.add(a);
    }
    
    
    /**
     * Adds the given action listener to the action sequence 
     * so that it will be performed 
     * when the mouse is moved.
     *
     * @param a the desired action listener
     * @see #removeMouseMovedAction(ActionListener)
     * @see #setMouseMovedActions(ActionSequence)
     * @see #getMouseMovedActions()
     */
    public void addMouseMovedAction(ActionListener a) {
        movedActions.add(a);
    }
    
    
    /**
     * Removes the given action listener from this adapter
     * so that it will be no longer be performed 
     * when the mouse is clicked.
     *
     * @param a the action listener to be removed
     * @see #addMouseClickedAction(ActionListener)
     * @see #setMouseClickedActions(ActionSequence)
     * @see #getMouseClickedActions()
     */
    public void removeMouseClickedAction(ActionListener a) {
        clickedActions.remove(a);
    }
    
    
    /**
     * Removes the given action listener from this adapter
     * so that it will be no longer be performed 
     * when the mouse enters the component.
     *
     * @param a the action listener to be removed
     * @see #addMouseEnteredAction(ActionListener)
     * @see #setMouseEnteredActions(ActionSequence)
     * @see #getMouseEnteredActions()
     */
    public void removeMouseEnteredAction(ActionListener a) {
        enteredActions.remove(a);
    }
    
    
    /**
     * Removes the given action listener from this adapter
     * so that it will be no longer be performed 
     * when the mouse exits the component.
     *
     * @param a the action listener to be removed
     * @see #addMouseExitedAction(ActionListener)
     * @see #setMouseExitedActions(ActionSequence)
     * @see #getMouseExitedActions()
     */
    public void removeMouseExitedAction(ActionListener a) {
        exitedActions.remove(a);
    }
    
    
    /**
     * Removes the given action listener from this adapter
     * so that it will be no longer be performed 
     * when the mouse is pressed.
     *
     * @param a the action listener to be removed
     * @see #addMousePressedAction(ActionListener)
     * @see #setMousePressedActions(ActionSequence)
     * @see #getMousePressedActions()
     */
    public void removeMousePressedAction(ActionListener a) {
        pressedActions.remove(a);
    }
    
    
    /**
     * Removes the given action listener from this adapter
     * so that it will be no longer be performed 
     * when the mouse is released.
     *
     * @param a the action listener to be removed
     * @see #addMouseReleasedAction(ActionListener)
     * @see #setMouseReleasedActions(ActionSequence)
     * @see #getMouseReleasedActions()
     */
    public void removeMouseReleasedAction(ActionListener a) {
        releasedActions.remove(a);
    }
    
    
    /**
     * Removes the given action listener from this adapter
     * so that it will be no longer be performed 
     * when the mouse is dragged.
     *
     * @param a the action listener to be removed
     * @see #addMouseDraggedAction(ActionListener)
     * @see #setMouseDraggedActions(ActionSequence)
     * @see #getMouseDraggedActions()
     */
    public void removeMouseDraggedAction(ActionListener a) {
        draggedActions.remove(a);
    }
    
    
    /**
     * Removes the given action listener from this adapter
     * so that it will be no longer be performed 
     * when the mouse is moved.
     *
     * @param a the action listener to be removed
     * @see #addMouseMovedAction(ActionListener)
     * @see #setMouseMovedActions(ActionSequence)
     * @see #getMouseMovedActions()
     */
    public void removeMouseMovedAction(ActionListener a) {
        movedActions.remove(a);
    }
    
    
    /**
     * Sets the action sequence for mouse clicked events
     * to the given action sequence.
     *
     * If <CODE>null</CODE>, the action sequence
     * for mouse clicked events is cleared.
     *
     * @param sequence the desired action sequence
     * @see #getMouseClickedActions()
     * @see #addMouseClickedAction(ActionListener)
     * @see #removeMouseClickedAction(ActionListener)
     */
    public void setMouseClickedActions(ActionSequence sequence) {
        if (sequence == null)
            clickedActions.clear();
        else
            clickedActions = sequence;
    }
    
    
    /**
     * Sets the action sequence for mouse entered events
     * to the given action sequence.
     *
     * If <CODE>null</CODE>, the action sequence
     * for mouse entered events is cleared.
     *
     * @param sequence the desired action sequence
     * @see #getMouseEnteredActions()
     * @see #addMouseEnteredAction(ActionListener)
     * @see #removeMouseEnteredAction(ActionListener)
     */
    public void setMouseEnteredActions(ActionSequence sequence) {
        if (sequence == null)
            enteredActions.clear();
        else
            enteredActions = sequence;
    }
    
    
    /**
     * Sets the action sequence for mouse exited events
     * to the given action sequence.
     *
     * If <CODE>null</CODE>, the action sequence
     * for mouse exited events is cleared.
     *
     * @param sequence the desired action sequence
     * @see #setMouseExitedActions(ActionSequence)
     * @see #addMouseExitedAction(ActionListener)
     * @see #removeMouseExitedAction(ActionListener)
     */
    public void setMouseExitedActions(ActionSequence sequence) {
        if (sequence == null)
            exitedActions.clear();
        else
            exitedActions = sequence;
    }
    
    
    /**
     * Sets the action sequence for mouse pressed events
     * to the given action sequence.
     *
     * If <CODE>null</CODE>, the action sequence
     * for mouse pressed events is cleared.
     *
     * @param sequence the desired action sequence
     * @see #getMousePressedActions()
     * @see #addMousePressedAction(ActionListener)
     * @see #removeMousePressedAction(ActionListener)
     */
    public void setMousePressedActions(ActionSequence sequence) {
        if (sequence == null)
            pressedActions.clear();
        else
            pressedActions = sequence;
    }
    
    
    /**
     * Sets the action sequence for mouse released events
     * to the given action sequence.
     *
     * If <CODE>null</CODE>, the action sequence
     * for mouse released events is cleared.
     *
     * @param sequence the desired action sequence
     * @see #getMouseReleasedActions()
     * @see #addMouseReleasedAction(ActionListener)
     * @see #removeMouseReleasedAction(ActionListener)
     */
    public void setMouseReleasedActions(ActionSequence sequence) {
        if (sequence == null)
            releasedActions.clear();
        else
            releasedActions = sequence;
    }
    
    
    /**
     * Sets the action sequence for mouse dragged events
     * to the given action sequence.
     *
     * If <CODE>null</CODE>, the action sequence
     * for mouse dragged events is cleared.
     *
     * @param sequence the desired action sequence
     * @see #getMouseDraggedActions()
     * @see #addMouseDraggedAction(ActionListener)
     * @see #removeMouseDraggedAction(ActionListener)
     */
    public void setMouseDraggedActions(ActionSequence sequence) {
        if (sequence == null)
            draggedActions.clear();
        else
            draggedActions = sequence;
    }
    
    
    /**
     * Sets the action sequence for mouse moved events
     * to the given action sequence.
     *
     * If <CODE>null</CODE>, the action sequence
     * for mouse moved events is cleared.
     *
     * @param sequence the desired action sequence
     * @see #getMouseMovedActions()
     * @see #addMouseMovedAction(ActionListener)
     * @see #removeMouseMovedAction(ActionListener)
     */
    public void setMouseMovedActions(ActionSequence sequence) {
        if (sequence == null)
            movedActions.clear();
        else
            movedActions = sequence;
    }
    
    
    /**
     * Returns the action sequence for mouse clicked events.
     *
     * @see #setMouseClickedActions(ActionSequence)
     * @see #addMouseClickedAction(ActionListener)
     * @see #removeMouseClickedAction(ActionListener)
     */
    public ActionSequence getMouseClickedActions() {
        return clickedActions;
    }
    
    
    /**
     * Returns the action sequence for mouse entered events.
     *
     * @see #setMouseEnteredActions(ActionSequence)
     * @see #addMouseEnteredAction(ActionListener)
     * @see #removeMouseEnteredAction(ActionListener)
     */
    public ActionSequence getMouseEnteredActions() {
        return enteredActions;
    }
    
    
    /**
     * Returns the action sequence for mouse exited events.
     *
     * @see #setMouseExitedActions(ActionSequence)
     * @see #addMouseExitedAction(ActionListener)
     * @see #removeMouseExitedAction(ActionListener)
     */
    public ActionSequence getMouseExitedActions() {
        return exitedActions;
    }
    
    
    /**
     * Returns the action sequence for mouse pressed events.
     *
     * @see #setMousePressedActions(ActionSequence)
     * @see #addMousePressedAction(ActionListener)
     * @see #removeMousePressedAction(ActionListener)
     */
    public ActionSequence getMousePressedActions() {
        return pressedActions;
    }
    
    
    /**
     * Returns the action sequence for mouse released events.
     *
     * @see #setMouseReleasedActions(ActionSequence)
     * @see #addMouseReleasedAction(ActionListener)
     * @see #removeMouseReleasedAction(ActionListener)
     */
    public ActionSequence getMouseReleasedActions() {
        return releasedActions;
    }
    
    
    /**
     * Returns the action sequence for mouse dragged events.
     *
     * @see #setMouseDraggedActions(ActionSequence)
     * @see #addMouseDraggedAction(ActionListener)
     * @see #removeMouseDraggedAction(ActionListener)
     */
    public ActionSequence getMouseDraggedActions() {
        return draggedActions;
    }
    
    
    /**
     * Returns the action sequence for mouse moved events.
     *
     * @see #setMouseMovedActions(ActionSequence)
     * @see #addMouseMovedAction(ActionListener)
     * @see #removeMouseMovedAction(ActionListener)
     */
    public ActionSequence getMouseMovedActions() {
        return movedActions;
    }
    
    
    /** Uninstall all mouse actions for this adapter. */
    public void uninstallAllMouseActions() {
        setMouseMovedActions   (null);
        setMousePressedActions (null);
        setMouseReleasedActions(null);
        setMouseClickedActions (null);
        setMouseDraggedActions (null);
        setMouseEnteredActions (null);
        setMouseExitedActions  (null);
    }
    
}
