1/*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.swing.event;
27
28import java.util.EventObject;
29import javax.swing.tree.TreePath;
30
31/**
32 * An event that characterizes a change in the current
33 * selection.  The change is based on any number of paths.
34 * TreeSelectionListeners will generally query the source of
35 * the event for the new selected status of each potentially
36 * changed row.
37 * <p>
38 * <strong>Warning:</strong>
39 * Serialized objects of this class will not be compatible with
40 * future Swing releases. The current serialization support is
41 * appropriate for short term storage or RMI between applications running
42 * the same version of Swing.  As of 1.4, support for long term storage
43 * of all JavaBeans&trade;
44 * has been added to the <code>java.beans</code> package.
45 * Please see {@link java.beans.XMLEncoder}.
46 *
47 * @see TreeSelectionListener
48 * @see javax.swing.tree.TreeSelectionModel
49 *
50 * @author Scott Violet
51 */
52@SuppressWarnings("serial") // Same-version serialization only
53public class TreeSelectionEvent extends EventObject
54{
55    /** Paths this event represents. */
56    protected TreePath[]     paths;
57    /** For each path identifies if that path is in fact new. */
58    protected boolean[]       areNew;
59    /** leadSelectionPath before the paths changed, may be null. */
60    protected TreePath        oldLeadSelectionPath;
61    /** leadSelectionPath after the paths changed, may be null. */
62    protected TreePath        newLeadSelectionPath;
63
64    /**
65      * Represents a change in the selection of a {@code TreeSelectionModel}.
66      * {@code paths} identifies the paths that have been either added or
67      * removed from the selection.
68      *
69      * @param source source of event
70      * @param paths the paths that have changed in the selection
71      * @param areNew a {@code boolean} array indicating whether the paths in
72      *               {@code paths} are new to the selection
73      * @param oldLeadSelectionPath the previous lead selection path
74      * @param newLeadSelectionPath the new lead selection path
75      */
76    public TreeSelectionEvent(Object source, TreePath[] paths,
77                              boolean[] areNew, TreePath oldLeadSelectionPath,
78                              TreePath newLeadSelectionPath)
79    {
80        super(source);
81        this.paths = paths;
82        this.areNew = areNew;
83        this.oldLeadSelectionPath = oldLeadSelectionPath;
84        this.newLeadSelectionPath = newLeadSelectionPath;
85    }
86
87    /**
88      * Represents a change in the selection of a {@code TreeSelectionModel}.
89      * {@code path} identifies the path that has been either added or
90      * removed from the selection.
91      *
92      * @param source source of event
93      * @param path the path that has changed in the selection
94      * @param isNew whether or not the path is new to the selection, false
95      *              means path was removed from the selection.
96      * @param oldLeadSelectionPath the previous lead selection path
97      * @param newLeadSelectionPath the new lead selection path
98      */
99    public TreeSelectionEvent(Object source, TreePath path, boolean isNew,
100                              TreePath oldLeadSelectionPath,
101                              TreePath newLeadSelectionPath)
102    {
103        super(source);
104        paths = new TreePath[1];
105        paths[0] = path;
106        areNew = new boolean[1];
107        areNew[0] = isNew;
108        this.oldLeadSelectionPath = oldLeadSelectionPath;
109        this.newLeadSelectionPath = newLeadSelectionPath;
110    }
111
112    /**
113      * Returns the paths that have been added or removed from the selection.
114      *
115      * @return copy of the array of {@code TreePath} obects for this event.
116      */
117    public TreePath[] getPaths()
118    {
119        int                  numPaths;
120        TreePath[]          retPaths;
121
122        numPaths = paths.length;
123        retPaths = new TreePath[numPaths];
124        System.arraycopy(paths, 0, retPaths, 0, numPaths);
125        return retPaths;
126    }
127
128    /**
129      * Returns the first path element.
130      *
131      * @return the first {@code TreePath} element represented by this event
132      */
133    public TreePath getPath()
134    {
135        return paths[0];
136    }
137
138    /**
139     * Returns whether the path identified by {@code getPath} was
140     * added to the selection.  A return value of {@code true}
141     * indicates the path identified by {@code getPath} was added to
142     * the selection. A return value of {@code false} indicates {@code
143     * getPath} was selected, but is no longer selected.
144     *
145     * @return {@code true} if {@code getPath} was added to the selection,
146     *         {@code false} otherwise
147     */
148    public boolean isAddedPath() {
149        return areNew[0];
150    }
151
152    /**
153     * Returns whether the specified path was added to the selection.
154     * A return value of {@code true} indicates the path identified by
155     * {@code path} was added to the selection. A return value of
156     * {@code false} indicates {@code path} is no longer selected. This method
157     * is only valid for the paths returned from {@code getPaths()}; invoking
158     * with a path not included in {@code getPaths()} throws an
159     * {@code IllegalArgumentException}.
160     *
161     * @param path the path to test
162     * @return {@code true} if {@code path} was added to the selection,
163     *         {@code false} otherwise
164     * @throws IllegalArgumentException if {@code path} is not contained
165     *         in {@code getPaths}
166     * @see #getPaths
167     */
168    public boolean isAddedPath(TreePath path) {
169        for(int counter = paths.length - 1; counter >= 0; counter--)
170            if(paths[counter].equals(path))
171                return areNew[counter];
172        throw new IllegalArgumentException("path is not a path identified by the TreeSelectionEvent");
173    }
174
175    /**
176     * Returns whether the path at {@code getPaths()[index]} was added
177     * to the selection.  A return value of {@code true} indicates the
178     * path was added to the selection. A return value of {@code false}
179     * indicates the path is no longer selected.
180     *
181     * @param index the index of the path to test
182     * @return {@code true} if the path was added to the selection,
183     *         {@code false} otherwise
184     * @throws IllegalArgumentException if index is outside the range of
185     *         {@code getPaths}
186     * @see #getPaths
187     *
188     * @since 1.3
189     */
190    public boolean isAddedPath(int index) {
191        if (paths == null || index < 0 || index >= paths.length) {
192            throw new IllegalArgumentException("index is beyond range of added paths identified by TreeSelectionEvent");
193        }
194        return areNew[index];
195    }
196
197    /**
198     * Returns the path that was previously the lead path.
199     *
200     * @return a {@code TreePath} containing the old lead selection path
201     */
202    public TreePath getOldLeadSelectionPath() {
203        return oldLeadSelectionPath;
204    }
205
206    /**
207     * Returns the current lead path.
208     *
209     * @return a {@code TreePath} containing the new lead selection path
210     */
211    public TreePath getNewLeadSelectionPath() {
212        return newLeadSelectionPath;
213    }
214
215    /**
216     * Returns a copy of the receiver, but with the source being newSource.
217     *
218     * @param newSource source of event
219     * @return an {@code Object} which is a copy of this event with the source
220     *         being the {@code newSource} provided
221     */
222    public Object cloneWithSource(Object newSource) {
223      // Fix for IE bug - crashing
224      return new TreeSelectionEvent(newSource, paths, areNew,
225                                    oldLeadSelectionPath,
226                                    newLeadSelectionPath);
227    }
228}
229