package com.sun.swingx.treetable;
/*
* Copyright 1997-1999 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
* DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR
* RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR
* ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
* FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
* SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
* THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or
* maintenance of any nuclear facility.
*/
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;
/**
* @version 1.2 10/27/98
* An abstract implementation of the TreeTableModel interface,
* handling the list of listeners.
* @author Philip Milne
*/
public abstract class AbstractTreeTableModel implements TreeTableModel {
protected Object root;
protected EventListenerList listenerList = new EventListenerList();
public AbstractTreeTableModel(Object root) {
this.root = root;
}
//
// Default implementations for methods in the TreeModel interface.
//
public Object getRoot() {
return root;
}
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
public String getColumnName(int column) {
//Copied from AbstractTableModel.
//Should use same defaults when possible.
String result = "";
for (; column >= 0; column = column / 26 - 1) {
result = (char) ((char) (column % 26) + 'A') + result;
}
return result;
}
public void valueForPathChanged(TreePath path, Object newValue) {}
// This is not called in the JTree's default mode:
// use a naive implementation.
public int getIndexOfChild(Object parent, Object child) {
for (int i = 0; i < getChildCount(parent); i++) {
if (getChild(parent, i).equals(child)) {
return i;
}
}
return -1;
}
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
/*
* Notifies all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeNodesChanged(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
}
}
}
/*
* Notifies all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeNodesInserted(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
}
}
}
/*
* Notifies all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeNodesRemoved(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
}
}
}
/*
* Notifies all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeStructureChanged(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
}
}
}
/**
* From DefaultTreeModel
* @param source
* @param path
*/
protected void fireTreeStructureChanged(Object source, TreePath path) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path);
((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
}
}
}
/**
* Invoke this method if you've totally changed the children of
* node and its childrens children... This will post a
* treeStructureChanged event.
*/
public void nodeStructureChanged(TreeTableNode node) {
if(node != null) {
fireTreeStructureChanged(this, getPathToRoot(node), null, null);
}
}
/**
* Gets the path from the root to the specified node.
*
* @param aNode
* the node to query
* @return an array of {@code TreeTableNode}s, where
* {@code arr[0].equals(getRoot())} and
* {@code arr[arr.length - 1].equals(aNode)}, or an empty array if
* the node is not found.
* @throws NullPointerException
* if {@code aNode} is {@code null}
*/
public TreeTableNode[] getPathToRoot(TreeTableNode aNode) {
List<TreeTableNode> path = new ArrayList<TreeTableNode>();
TreeTableNode node = aNode;
while (node != root) {
path.add(0, node);
node = (TreeTableNode) node.getParent();
}
if (node == root) {
path.add(0, node);
}
return path.toArray(new TreeTableNode[0]);
}
//
// Default impelmentations for methods in the TreeTableModel interface.
//
public Class getColumnClass(int column) { return column==0?TreeTableModel.class:Object.class; }
/** By default, make the column with the Tree in it the only editable one.
* Making this column editable causes the JTable to forward mouse
* and keyboard events in the Tree column to the underlying JTree.
*/
public boolean isCellEditable(Object node, int column) {
return getColumnClass(column) == TreeTableModel.class;
}
public void setValueAt(Object aValue, Object node, int column) {}
// Left to be implemented in the subclass:
/*
* public Object getChild(Object parent, int index)
* public int getChildCount(Object parent)
* public int getColumnCount()
* public String getColumnName(Object node, int column)
* public Object getValueAt(Object node, int column)
*/
}