/*
* AbstractTreeModel.java
*
* Created on August 11, 2004, 5:36 PM
*/
package org.owasp.webscarab.util.swing;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeModel;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.EventListenerList;
/** Support for generic dynamically changing TreeModels.
*/
public abstract class AbstractTreeModel implements TreeModel {
protected EventListenerList listeners;
protected AbstractTreeModel() {
listeners = new EventListenerList();
}
public int getIndexOfChild(Object parent, Object child) {
for (int count = getChildCount(parent), i = 0; i < count; i++)
if (getChild(parent, i).equals(child))
return i;
return -1;
}
/** Call when there is a new root, which may be null, i.e. not existent. */
protected void fireNewRoot() {
Object[] pairs = listeners.getListenerList();
Object root = getRoot();
/* Undocumented. I think it is the only reasonable/possible solution
to use use null as path if there is no root. TreeModels without
root aren't important anyway, since JTree doesn't support them (yet).
*/
TreePath path = (root != null) ? new TreePath(root) : null;
TreeModelEvent e = null;
for (int i = pairs.length - 2; i >= 0; i -= 2) {
if (pairs[i] == TreeModelListener.class) {
if (e == null)
e = new TreeModelEvent(this, path, null, null);
((TreeModelListener)pairs[i + 1]).treeStructureChanged(e);
}
}
}
/** Call when everything but the root has changed. Only may be called
* when the root is not null. Otherwise there isn't a structure to have
* changed.
*/
protected void fireStructureChanged() {
fireTreeStructureChanged(new TreePath(getRoot()));
}
/** Call when a node has changed its leaf state. */
protected void firePathLeafStateChanged(TreePath path) {
fireTreeStructureChanged(path);
}
/** Call when the tree structure below the path has completely changed. */
protected void fireTreeStructureChanged(TreePath parentPath) {
Object[] pairs = listeners.getListenerList();
TreeModelEvent e = null;
for (int i = pairs.length - 2; i >= 0; i -= 2) {
if (pairs[i] == TreeModelListener.class) {
if (e == null)
e = new TreeModelEvent(this, parentPath, null, null);
((TreeModelListener)pairs[i + 1]).treeStructureChanged(e);
}
}
}
/** Call when the path itself has changed, but no structure changes
* have occurred.
*/
protected void firePathChanged(TreePath path) {
Object node = path.getLastPathComponent();
TreePath parentPath = path.getParentPath();
if (parentPath == null)
fireChildrenChanged(path, null, null);
else {
Object parent = parentPath.getLastPathComponent();
fireChildChanged(parentPath, getIndexOfChild(parent, node), node);
}
}
protected void fireChildAdded(TreePath parentPath, int index, Object child) {
fireChildrenAdded(parentPath, new int[] {index}, new Object[] {child});
}
protected void fireChildChanged(TreePath parentPath, int index, Object child) {
fireChildrenChanged(parentPath, new int[] {index}, new Object[] {child});
}
protected void fireChildRemoved(TreePath parentPath, int index, Object child) {
fireChildrenRemoved(parentPath, new int[] {index}, new Object[] {child});
}
protected void fireChildrenAdded(TreePath parentPath, int[] indices, Object[] children) {
Object[] pairs = listeners.getListenerList();
TreeModelEvent e = null;
for (int i = pairs.length - 2; i >= 0; i -= 2) {
if (pairs[i] == TreeModelListener.class) {
if (e == null)
e = new TreeModelEvent(this, parentPath, indices, children);
((TreeModelListener)pairs[i + 1]).treeNodesInserted(e);
}
}
}
protected void fireChildrenChanged(TreePath parentPath, int[] indices, Object[] children) {
Object[] pairs = listeners.getListenerList();
TreeModelEvent e = null;
for (int i = pairs.length - 2; i >= 0; i -= 2) {
if (pairs[i] == TreeModelListener.class) {
if (e == null)
e = new TreeModelEvent(this, parentPath, indices, children);
((TreeModelListener)pairs[i + 1]).treeNodesChanged(e);
}
}
}
protected void fireChildrenRemoved(TreePath parentPath, int[] indices, Object[] children) {
Object[] pairs = listeners.getListenerList();
TreeModelEvent e = null;
for (int i = pairs.length - 2; i >= 0; i -= 2) {
if (pairs[i] == TreeModelListener.class) {
if (e == null)
e = new TreeModelEvent(this, parentPath, indices, children);
((TreeModelListener)pairs[i + 1]).treeNodesRemoved(e);
}
}
}
protected Object clone()
throws CloneNotSupportedException {
AbstractTreeModel clone = (AbstractTreeModel)super.clone();
clone.listeners = new EventListenerList();
return clone;
}
public void addTreeModelListener(TreeModelListener l) {
listeners.add(TreeModelListener.class, l);
}
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(TreeModelListener.class, l);
}
}