/* * DefaultTreeSelectionModel.java -- Copyright (C) 2002, 2004 Free Software * Foundation, Inc. * * This file is part of GNU Classpath. * * GNU Classpath is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2, or (at your option) any later version. * * GNU Classpath 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 for more * details. * * You should have received a copy of the GNU General Public License along with * GNU Classpath; see the file COPYING. If not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Linking this library statically or dynamically with other modules is making a * combined work based on this library. Thus, the terms and conditions of the * GNU General Public License cover the whole combination. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent modules, and * to copy and distribute the resulting executable under terms of your choice, * provided that you also meet, for each linked independent module, the terms * and conditions of the license of that module. An independent module is a * module which is not derived from or based on this library. If you modify this * library, you may extend this exception to your version of the library, but * you are not obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package javax.swing.tree; import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.EventListener; import java.util.Vector; import javax.swing.DefaultListSelectionModel; import javax.swing.event.EventListenerList; import javax.swing.event.SwingPropertyChangeSupport; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; /** * DefaultTreeSelectionModel * * @author Andrew Selkirk */ public class DefaultTreeSelectionModel implements Cloneable, Serializable, TreeSelectionModel { static final long serialVersionUID = 3288129636638950196L; /** * SELECTION_MODE_PROPERTY */ public static final String SELECTION_MODE_PROPERTY = "selectionMode"; /** * Our Swing property change support. */ protected SwingPropertyChangeSupport changeSupport; /** * The current selection. */ protected TreePath[] selection; /** * Our TreeSelectionListeners. */ protected EventListenerList listenerList; /** * The current RowMapper. */ protected transient RowMapper rowMapper; /** * The current listSelectionModel. */ protected DefaultListSelectionModel listSelectionModel; /** * The current selection mode. */ protected int selectionMode; /** * The path that has been added last. */ protected TreePath leadPath; /** * The index of the last added path. */ protected int leadIndex; /** * The row of the last added path according to the RowMapper. */ protected int leadRow; /** * Constructs a new DefaultTreeSelectionModel. */ public DefaultTreeSelectionModel() { setSelectionMode(DISCONTIGUOUS_TREE_SELECTION); listenerList = new EventListenerList(); } /** * Creates a clone of this DefaultTreeSelectionModel with the same * selection. * * @exception CloneNotSupportedException should not be thrown here * * @return a clone of this DefaultTreeSelectionModel */ public Object clone() throws CloneNotSupportedException { return null; // TODO } /** * Returns a string that shows this object's properties. * * @return a string that shows this object's properties */ public String toString() { return null; // TODO } /** * writeObject * * @param value0 TODO * @exception IOException TODO */ private void writeObject(ObjectOutputStream value0) throws IOException { // TODO } /** * readObject * * @param value0 TODO * @exception IOException TODO * @exception ClassNotFoundException TODO */ private void readObject(ObjectInputStream value0) throws IOException, ClassNotFoundException { // TODO } /** * Sets the RowMapper that should be used to map between paths and their * rows. * * @param rowMapper the RowMapper to set * * @see {@link RowMapper */ public void setRowMapper(RowMapper value0) { // TODO } /** * Returns the RowMapper that is currently used to map between paths and * their rows. * * @return the current RowMapper * * @see {@link RowMapper */ public RowMapper getRowMapper() { return rowMapper; } /** * Sets the current selection mode. Possible values are * {@link #SINGLE_TREE_SELECTION}, {@link CONTIGUOUS_TREE_SELECTION} and * {@link #DISCONTIGUOUS_TREE_SELECTION}. * * @param mode the selection mode to be set * * @see {@link #getSelectionMode} * @see {@link #SINGLE_TREE_SELECTION} * @see {@link #CONTIGUOUS_TREE_SELECTION} * @see {@link #DISCONTIGUOUS_TREE_SELECTION} */ public void setSelectionMode(int mode) { selectionMode = mode; } /** * Returns the current selection mode. * * @return the current selection mode * * @see {@link #setSelectionMode} * @see {@link #SINGLE_TREE_SELECTION} * @see {@link #CONTIGUOUS_TREE_SELECTION} * @see {@link #DISCONTIGUOUS_TREE_SELECTION} */ public int getSelectionMode() { return selectionMode; } /** * Sets this path as the only selection. * * If this changes the selection the registered TreeSelectionListeners are * notified. * * @param path the path to set as selection */ public void setSelectionPath(TreePath path) { selection = new TreePath[] { path }; } /** * Sets the paths as selection. This method checks for duplicates and * removes them. * * If this changes the selection the registered TreeSelectionListeners are * notified. * * @param paths the paths to set as selection */ public void setSelectionPaths(TreePath[] value0) { // TODO } /** * Adds a path to the list of selected paths. This method checks if the path * is already selected and doesn't add the same path twice. * * If this changes the selection the registered TreeSelectionListeners are * notified. * * @param path the path to add to the selection */ public void addSelectionPath(TreePath value0) { if (!isPathSelected(value0)) { if (isSelectionEmpty()) setSelectionPath(value0); else { TreePath[] temp = new TreePath[selection.length + 1]; System.arraycopy(selection, 0, temp, 0, selection.length); temp[temp.length - 1] = value0; selection = new TreePath[temp.length]; System.arraycopy(temp, 0, selection, 0, temp.length); } fireValueChanged(new TreeSelectionEvent(this, value0, true, leadPath, value0)); } } /** * Adds the paths to the list of selected paths. This method checks if the * paths are already selected and doesn't add the same path twice. * * If this changes the selection the registered TreeSelectionListeners are * notified. * * @param paths the paths to add to the selection */ public void addSelectionPaths(TreePath[] value0) { TreePath v0 = null; for (int i = 0; i < value0.length; i++) { v0 = value0[i]; if (!isPathSelected(v0)) { if (isSelectionEmpty()) setSelectionPath(v0); else { TreePath[] temp = new TreePath[selection.length + 1]; System.arraycopy(selection, 0, temp, 0, selection.length); temp[temp.length - 1] = v0; selection = new TreePath[temp.length]; System.arraycopy(temp, 0, selection, 0, temp.length); } fireValueChanged(new TreeSelectionEvent(this, v0, true, leadPath, value0[0])); } } } /** * Removes the path from the selection. * * If this changes the selection the registered TreeSelectionListeners are * notified. * * @param path the path to remove */ public void removeSelectionPath(TreePath value0) { int index = -1; if (isPathSelected(value0)) { for (int i = 0; i < selection.length; i++) { if (selection[i].equals(value0)) { index = i; break; } } TreePath[] temp = new TreePath[selection.length - 1]; System.arraycopy(selection, 0, temp, 0, index); System.arraycopy(selection, index + 1, temp, index, selection.length - index - 1); selection = new TreePath[temp.length]; System.arraycopy(temp, 0, selection, 0, temp.length); fireValueChanged(new TreeSelectionEvent(this, value0, false, leadPath, value0)); } } /** * Removes the paths from the selection. * * If this changes the selection the registered TreeSelectionListeners are * notified. * * @param paths the path to remove */ public void removeSelectionPaths(TreePath[] value0) { int index = -1; TreePath v0 = null; for (int i = 0; i < value0.length; i++) { v0 = value0[i]; if (isPathSelected(v0)) { for (int x = 0; x < selection.length; x++) { if (selection[i].equals(v0)) { index = x; break; } } TreePath[] temp = new TreePath[selection.length - 1]; System.arraycopy(selection, 0, temp, 0, index); System.arraycopy(selection, index + 1, temp, index, selection.length - index - 1); selection = new TreePath[temp.length]; System.arraycopy(temp, 0, selection, 0, temp.length); fireValueChanged(new TreeSelectionEvent(this, v0, false, leadPath, value0[0])); } } } /** * Returns the first path in the selection. This is especially useful when * the selectionMode is {@link #SINGLE_TREE_SELECTION}. * * @return the first path in the selection */ public TreePath getSelectionPath() { if ((selection == null) || (selection.length == 0)) return null; else return selection[0]; } /** * Returns the complete selection. * * @return the complete selection */ public TreePath[] getSelectionPaths() { return selection; } /** * Returns the number of paths in the selection. * * @return the number of paths in the selection */ public int getSelectionCount() { if (selection == null) return 0; else return selection.length; } /** * Checks if a given path is in the selection. * * @param path the path to check * * @return true if the path is in the selection, * false otherwise */ public boolean isPathSelected(TreePath value0) { if (selection == null) return false; for (int i = 0; i < selection.length; i++) { if (selection[i].equals(value0)) return true; } return false; } /** * Checks if the selection is empty. * * @return true if the selection is empty, false * otherwise */ public boolean isSelectionEmpty() { return ((selection == null) || (selection.length == 0)); } /** * Removes all paths from the selection. */ public void clearSelection() { selection = null; } /** * Adds a TreeSelectionListener object to this model. * * @param listener the listener to add */ public void addTreeSelectionListener(TreeSelectionListener listener) { listenerList.add(TreeSelectionListener.class, listener); } /** * Removes a TreeSelectionListener object from this model. * * @param listener the listener to remove */ public void removeTreeSelectionListener(TreeSelectionListener listener) { listenerList.remove(TreeSelectionListener.class, listener); } /** * Returns all TreeSelectionListener added to this model. * * @return an array of listeners * * @since 1.4 */ public TreeSelectionListener[] getTreeSelectionListeners() { return (TreeSelectionListener[]) getListeners(TreeSelectionListener.class); } /** * fireValueChanged * * @param event the event to fire. */ protected void fireValueChanged(TreeSelectionEvent event) { TreeSelectionListener[] listeners = getTreeSelectionListeners(); for (int i = 0; i < listeners.length; ++i) listeners[i].valueChanged(event); } /** * Returns all added listeners of a special type. * * @param listenerType the listener type * * @return an array of listeners * * @since 1.3 */ public EventListener[] getListeners(Class listenerType) { return listenerList.getListeners(listenerType); } /** * Returns the currently selected rows. * * @return the currently selected rows */ public int[] getSelectionRows() { if (rowMapper == null) return null; else return rowMapper.getRowsForPaths(selection); } /** * Returns the smallest row index from the selection. * * @return the smallest row index from the selection */ public int getMinSelectionRow() { if ((rowMapper == null) || (selection == null) || (selection.length == 0)) return -1; else { int[] rows = rowMapper.getRowsForPaths(selection); int minRow = Integer.MAX_VALUE; for (int index = 0; index < rows.length; index++) minRow = Math.min(minRow, rows[index]); return minRow; } } /** * Returns the largest row index from the selection. * * @return the largest row index from the selection */ public int getMaxSelectionRow() { if ((rowMapper == null) || (selection == null) || (selection.length == 0)) return -1; else { int[] rows = rowMapper.getRowsForPaths(selection); int maxRow = -1; for (int index = 0; index < rows.length; index++) maxRow = Math.max(maxRow, rows[index]); return maxRow; } } /** * Checks if a particular row is selected. * * @param row the index of the row to check * * @return true if the row is in this selection, * false otherwise */ public boolean isRowSelected(int value0) { return false; // TODO } /** * Updates the mappings from TreePaths to row indices. */ public void resetRowSelection() { // TODO } /** * getLeadSelectionRow * * @return int */ public int getLeadSelectionRow() { if ((rowMapper == null) || (leadPath == null)) return -1; else return rowMapper.getRowsForPaths(new TreePath[] { leadPath })[0]; } /** * getLeadSelectionPath * * @return TreePath */ public TreePath getLeadSelectionPath() { return leadPath; } /** * Adds a PropertyChangeListener object to this model. * * @param listener the listener to add. */ public void addPropertyChangeListener(PropertyChangeListener listener) { changeSupport.addPropertyChangeListener(listener); } /** * Removes a PropertyChangeListener object from this model. * * @param listener the listener to remove. */ public void removePropertyChangeListener(PropertyChangeListener listener) { changeSupport.removePropertyChangeListener(listener); } /** * Returns all added PropertyChangeListener objects. * * @return an array of listeners. * * @since 1.4 */ public PropertyChangeListener[] getPropertyChangeListeners() { return changeSupport.getPropertyChangeListeners(); } /** * Makes sure the currently selected paths are valid according to the * current selectionMode. * * If the selectionMode is set to {@link CONTIGUOUS_TREE_SELECTION} and the * selection isn't contiguous then the selection is reset to the first set * of contguous paths. * * If the selectionMode is set to {@link SINGLE_TREE_SELECTION} and the * selection has more than one path, the selection is reset to the contain * only the first path. */ protected void insureRowContinuity() { // TODO } /** * Returns true if the paths are contiguous or we have no * RowMapper assigned. * * @param paths the paths to check for continuity * @return true if the paths are contiguous or we have no * RowMapper assigned */ protected boolean arePathsContiguous(TreePath[] value0) { return false; // TODO } /** * Checks if the paths can be added. This returns true if: *