/*
 * Copyright 1997-2003 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.swing.event;

import java.util.EventObject;
import javax.swing.tree.TreePath;


/**
 * Encapsulates information describing changes to a tree model, and
 * used to notify tree model listeners of the change.
 * For more information and examples see
 * <a
 href="http://java.sun.com/docs/books/tutorial/uiswing/events/treemodellistener.html">How to Write a Tree Model Listener</a>,
 * a section in <em>The Java Tutorial.</em>
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases. The current serialization support is
 * appropriate for short term storage or RMI between applications running
 * the same version of Swing.  As of 1.4, support for long term storage
 * of all JavaBeans<sup><font size="-2">TM</font></sup>
 * has been added to the <code>java.beans</code> package.
 * Please see {@link java.beans.XMLEncoder}.
 *
 * @author Rob Davis
 * @author Ray Ryan
 * @author Scott Violet
 */
public class TreeModelEvent extends EventObject {
    /** Path to the parent of the nodes that have changed. */
    protected TreePath  path;
    /** Indices identifying the position of where the children were. */
    protected int[]     childIndices;
    /** Children that have been removed. */
    protected Object[]  children;

    /**
     * Used to create an event when nodes have been changed, inserted, or
     * removed, identifying the path to the parent of the modified items as
     * an array of Objects. All of the modified objects are siblings which are
     * direct descendents (not grandchildren) of the specified parent.
     * The positions at which the inserts, deletes, or changes occurred are
     * specified by an array of <code>int</code>. The indexes in that array
     * must be in order, from lowest to highest.
     * <p>
     * For changes, the indexes in the model correspond exactly to the indexes
     * of items currently displayed in the UI. As a result, it is not really
     * critical if the indexes are not in their exact order. But after multiple
     * inserts or deletes, the items currently in the UI no longer correspond
     * to the items in the model. It is therefore critical to specify the
     * indexes properly for inserts and deletes.
     * <p>
     * For inserts, the indexes represent the <i>final</i> state of the tree,
     * after the inserts have occurred. Since the indexes must be specified in
     * order, the most natural processing methodology is to do the inserts
     * starting at the lowest index and working towards the highest. Accumulate
     * a Vector of <code>Integer</code> objects that specify the
     * insert-locations as you go, then convert the Vector to an
     * array of <code>int</code> to create the event. When the postition-index
     * equals zero, the node is inserted at the beginning of the list. When the
     * position index equals the size of the list, the node is "inserted" at
     * (appended to) the end of the list.
     * <p>
     * For deletes, the indexes represent the <i>initial</i> state of the tree,
     * before the deletes have occurred. Since the indexes must be specified in
     * order, the most natural processing methodology is to use a delete-counter.
     * Start by initializing the counter to zero and start work through the
     * list from lowest to higest. Every time you do a delete, add the current
     * value of the delete-counter to the index-position where the delete occurred,
     * and append the result to a Vector of delete-locations, using
     * <code>addElement()</code>. Then increment the delete-counter. The index
     * positions stored in the Vector therefore reflect the effects of all previous
     * deletes, so they represent each object's position in the initial tree.
     * (You could also start at the highest index and working back towards the
     * lowest, accumulating a Vector of delete-locations as you go using the
     * <code>insertElementAt(Integer, 0)</code>.) However you produce the Vector
     * of initial-positions, you then need to convert the Vector of <code>Integer</code>
     * objects to an array of <code>int</code> to create the event.
     * <p>
     * <b>Notes:</b><ul>
     * <li>Like the <code>insertNodeInto</code> method in the
     *    <code>DefaultTreeModel</code> class, <code>insertElementAt</code>
     *    appends to the <code>Vector</code> when the index matches the size
     *    of the vector. So you can use <code>insertElementAt(Integer, 0)</code>
     *    even when the vector is empty.
     * <ul>To create a node changed event for the root node, specify the parent
     *     and the child indices as <code>null</code>.
     * </ul>
     *
     * @param source the Object responsible for generating the event (typically
     *               the creator of the event object passes <code>this</code>
     *               for its value)
     * @param path   an array of Object identifying the path to the
     *               parent of the modified item(s), where the first element
     *               of the array is the Object stored at the root node and
     *               the last element is the Object stored at the parent node
     * @param childIndices an array of <code>int</code> that specifies the
     *               index values of the removed items. The indices must be
     *               in sorted order, from lowest to highest
     * @param children an array of Object containing the inserted, removed, or
     *                 changed objects
     * @see TreePath
     */
    public TreeModelEvent(Object source, Object[] path, int[] childIndices,
                          Object[] children)
    {
        this(source, new TreePath(path), childIndices, children);
    }

    /**
     * Used to create an event when nodes have been changed, inserted, or
     * removed, identifying the path to the parent of the modified items as
     * a TreePath object. For more information on how to specify the indexes
     * and objects, see
     * <code>TreeModelEvent(Object,Object[],int[],Object[])</code>.
     *
     * @param source the Object responsible for generating the event (typically
     *               the creator of the event object passes <code>this</code>
     *               for its value)
     * @param path   a TreePath object that identifies the path to the
     *               parent of the modified item(s)
     * @param childIndices an array of <code>int</code> that specifies the
     *               index values of the modified items
     * @param children an array of Object containing the inserted, removed, or
     *                 changed objects
     *
     * @see #TreeModelEvent(Object,Object[],int[],Object[])
     */
    public TreeModelEvent(Object source, TreePath path, int[] childIndices,
                          Object[] children)
    {
        super(source);
        this.path = path;
        this.childIndices = childIndices;
        this.children = children;
    }

    /**
     * Used to create an event when the node structure has changed in some way,
     * identifying the path to the root of a modified subtree as an array of
     * Objects. A structure change event might involve nodes swapping position,
     * for example, or it might encapsulate multiple inserts and deletes in the
     * subtree stemming from the node, where the changes may have taken place at
     * different levels of the subtree.
     * <blockquote>
     *   <b>Note:</b><br>
     *   JTree collapses all nodes under the specified node, so that only its
     *   immediate children are visible.
     * </blockquote>
     *
     * @param source the Object responsible for generating the event (typically
     *               the creator of the event object passes <code>this</code>
     *               for its value)
     * @param path   an array of Object identifying the path to the root of the
     *               modified subtree, where the first element of the array is
     *               the object stored at the root node and the last element
     *               is the object stored at the changed node
     * @see TreePath
     */
    public TreeModelEvent(Object source, Object[] path)
    {
        this(source, new TreePath(path));
    }

    /**
     * Used to create an event when the node structure has changed in some way,
     * identifying the path to the root of the modified subtree as a TreePath
     * object. For more information on this event specification, see
     * <code>TreeModelEvent(Object,Object[])</code>.
     *
     * @param source the Object responsible for generating the event (typically
     *               the creator of the event object passes <code>this</code>
     *               for its value)
     * @param path   a TreePath object that identifies the path to the
     *               change. In the DefaultTreeModel,
     *               this object contains an array of user-data objects,
     *               but a subclass of TreePath could use some totally
     *               different mechanism -- for example, a node ID number
     *
     * @see #TreeModelEvent(Object,Object[])
     */
    public TreeModelEvent(Object source, TreePath path)
    {
        super(source);
        this.path = path;
        this.childIndices = new int[0];
    }

    /**
     * For all events, except treeStructureChanged,
     * returns the parent of the changed nodes.
     * For treeStructureChanged events, returns the ancestor of the
     * structure that has changed. This and
     * <code>getChildIndices</code> are used to get a list of the effected
     * nodes.
     * <p>
     * The one exception to this is a treeNodesChanged event that is to
     * identify the root, in which case this will return the root
     * and <code>getChildIndices</code> will return null.
     *
     * @return the TreePath used in identifying the changed nodes.
     * @see TreePath#getLastPathComponent
     */
    public TreePath getTreePath() { return path; }

    /**
     * Convenience method to get the array of objects from the TreePath
     * instance that this event wraps.
     *
     * @return an array of Objects, where the first Object is the one
     *         stored at the root and the last object is the one
     *         stored at the node identified by the path
     */
    public Object[] getPath() {
        if(path != null)
            return path.getPath();
        return null;
    }

    /**
     * Returns the objects that are children of the node identified by
     * <code>getPath</code> at the locations specified by
     * <code>getChildIndices</code>. If this is a removal event the
     * returned objects are no longer children of the parent node.
     *
     * @return an array of Object containing the children specified by
     *         the event
     * @see #getPath
     * @see #getChildIndices
     */
    public Object[] getChildren() {
        if(children != null) {
            int            cCount = children.length;
            Object[]       retChildren = new Object[cCount];

            System.arraycopy(children, 0, retChildren, 0, cCount);
            return retChildren;
        }
        return null;
    }

    /**
     * Returns the values of the child indexes. If this is a removal event
     * the indexes point to locations in the initial list where items
     * were removed. If it is an insert, the indices point to locations
     * in the final list where the items were added. For node changes,
     * the indices point to the locations of the modified nodes.
     *
     * @return an array of <code>int</code> containing index locations for
     *         the children specified by the event
     */
    public int[] getChildIndices() {
        if(childIndices != null) {
            int            cCount = childIndices.length;
            int[]          retArray = new int[cCount];

            System.arraycopy(childIndices, 0, retArray, 0, cCount);
            return retArray;
        }
        return null;
    }

    /**
     * Returns a string that displays and identifies this object's
     * properties.
     *
     * @return a String representation of this object
     */
    public String toString() {
        StringBuffer   retBuffer = new StringBuffer();

        retBuffer.append(getClass().getName() + " " +
                         Integer.toString(hashCode()));
        if(path != null)
            retBuffer.append(" path " + path);
        if(childIndices != null) {
            retBuffer.append(" indices [ ");
            for(int counter = 0; counter < childIndices.length; counter++)
                retBuffer.append(Integer.toString(childIndices[counter])+ " ");
            retBuffer.append("]");
        }
        if(children != null) {
            retBuffer.append(" children [ ");
            for(int counter = 0; counter < children.length; counter++)
                retBuffer.append(children[counter] + " ");
            retBuffer.append("]");
        }
        return retBuffer.toString();
    }
}
