ch.randelshofer.quaqua.filechooser.SubtreeTreeModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Quaqua Show documentation
Show all versions of Quaqua Show documentation
A Mavenisation of the Quaqua Mac OSX Swing Look and Feel (Java library)
Quaqua Look and Feel (C) 2003-2010, Werner Randelshofer.
Mavenisation by Matt Gumbley, DevZendo.org - for problems with
Mavenisation, see Matt; for issues with Quaqua, see the Quaqua home page.
For full license details, see http://randelshofer.ch/quaqua/license.html
The newest version!
/*
* @(#)SubtreeTreeModel.java
*
* Copyright (c) 2004-2010 Werner Randelshofer, Immensee, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package ch.randelshofer.quaqua.filechooser;
import java.beans.*;
import java.util.*;
import javax.swing.event.*;
import javax.swing.tree.*;
/**
* SubtreeTreeModel.
*
* @author Werner Randelshofer
* @version $Id: SubtreeTreeModel.java 363 2010-11-21 17:41:04Z wrandelshofer $
*/
public class SubtreeTreeModel implements TreeModel, TreeModelListener {
/** We store all our listeners here. */
protected EventListenerList listenerList = new EventListenerList();
protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
private TreeModel target;
private Object subtreeRoot;
private Object[] rootPath;
/** Creates a new instance. */
public SubtreeTreeModel(TreeModel target) {
this.target = target;
this.subtreeRoot = target.getRoot();
this.rootPath = new Object[]{subtreeRoot};
target.addTreeModelListener(this);
}
public void setPathToRoot(TreePath newValue) {
setPathToRoot(newValue.getPath());
}
/*
* Note: For efficiency reasons this method stores the passed in array
* internally without copying it. Do not modify the array after
* invoking this method.
*/
public void setPathToRoot(Object[] newValue) {
Object[] oldValue = this.rootPath;
if (!Arrays.equals(oldValue, newValue)) {
this.rootPath = newValue;
this.subtreeRoot = newValue[newValue.length - 1];
changeSupport.firePropertyChange("rootPath", oldValue, newValue);
fireTreeStructureChanged(subtreeRoot, new Object[]{rootPath[rootPath.length - 1]});
}
}
public TreePath getPathToRoot() {
return new TreePath(rootPath);
}
public Object getChild(Object parent, int index) {
return target.getChild(parent, index);
}
public int getChildCount(Object parent) {
return target.getChildCount(parent);
}
public int getIndexOfChild(Object parent, Object child) {
return target.getIndexOfChild(parent, child);
}
public Object getRoot() {
return subtreeRoot;
}
public boolean isLeaf(Object node) {
return node!=getRoot()&&target.isLeaf(node);
}
public TreePath toFullPath(TreePath subtreePath) {
return subtreePath == null ? new TreePath(rootPath) : new TreePath(toFullPath(subtreePath.getPath()));
}
public Object[] toFullPath(Object[] subtreePath) {
/*
if (subtreeRoot != target.getRoot()) {
Object[] components = new Object[rootPath.length + subtreePath.length - 1];
System.arraycopy(rootPath, 0, components, 0, rootPath.length);
System.arraycopy(subtreePath, 1, components, rootPath.length, subtreePath.length - 1);
return components;
} else {
return subtreePath;
}*/
LinkedList list = new LinkedList(Arrays.asList(subtreePath));
if (subtreePath.length > 0) {
TreeNode node = (TreeNode) subtreePath[0];
while ((node = node.getParent()) != null) {
list.addFirst(node);
}
}
return list.toArray();
}
public void valueForPathChanged(TreePath path, Object newValue) {
target.valueForPathChanged(toFullPath(path), newValue);
}
//
// Events
//
/**
* Adds a listener for the TreeModelEvent posted after the tree changes.
*
* @see #removeTreeModelListener
* @param l the listener to add
*/
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
/**
* Removes a listener previously added with addTreeModelListener().
*
* @see #addTreeModelListener
* @param l the listener to remove
*/
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
/**
* Adds a property change listener.
*/
public void addPropertyChangeListener(PropertyChangeListener l) {
changeSupport.addPropertyChangeListener(l);
}
/**
* Removes a property change listener.
*/
public void removePropertyChangeListener(PropertyChangeListener l) {
changeSupport.removePropertyChangeListener(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.
*
* @param source the node being changed
* @param path the path to the root node
* @param childIndices the indices of the changed elements
* @param children the changed elements
* @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.
*
* @param source the node where new elements are being inserted
* @param path the path to the root node
* @param childIndices the indices of the new elements
* @param children the new elements
* @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.
*
* @param source the node where elements are being removed
* @param path the path to the root node
* @param childIndices the indices of the removed elements
* @param children the removed elements
* @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.
*
* @param source the node where the tree model has changed
* @param path the path to the root node
* @see EventListenerList
*/
protected void fireTreeStructureChanged(Object source, Object[] 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);
}
}
}
/*
* 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.
*
* @param source the node where the tree model has changed
* @param path the path to the root node
* @see EventListenerList
*/
private 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);
}
}
}
/**
* Returns true, if the specified path if a descendant
* path of the path to root of this subtree model.
*/
public boolean isDescendant(Object[] fullpath) {
if (fullpath.length >= rootPath.length) {
for (int i = 0; i < rootPath.length; i++) {
if (rootPath[i] != fullpath[i]) {
return false;
}
}
return true;
}
return false;
}
public Object[] toSubPath(Object[] fullPath) {
if (isDescendant(fullPath)) {
Object[] subtreePath = new Object[fullPath.length - rootPath.length + 1];
System.arraycopy(fullPath, rootPath.length - 1, subtreePath, 0, subtreePath.length);
return subtreePath;
} else {
return null;
}
}
/**
* Returns true, if the specified path if a descendant
* path of the path to root of this subtree model.
*/
public boolean isDescendant(TreePath fullpath) {
if (fullpath.getPathCount() >= rootPath.length) {
for (int i = 0; i < rootPath.length; i++) {
if (rootPath[i] != fullpath.getPathComponent(i)) {
return false;
}
}
return true;
}
return false;
}
public TreePath toSubPath(TreePath fullPath) {
Object[] subPath = toSubPath(fullPath.getPath());
return (subPath == null) ? null : new TreePath(subPath);
}
public void treeNodesChanged(TreeModelEvent event) {
Object[] subtreePath = toSubPath(event.getPath());
if (subtreePath != null) {
fireTreeNodesChanged(event.getSource(), subtreePath, event.getChildIndices(), event.getChildren());
}
}
public void treeNodesInserted(TreeModelEvent event) {
Object[] subtreePath = toSubPath(event.getPath());
if (subtreePath != null) {
fireTreeNodesInserted(event.getSource(), subtreePath, event.getChildIndices(), event.getChildren());
}
}
public void treeNodesRemoved(TreeModelEvent event) {
// XXX - We should check here if the rootPath was removed !!!
Object[] subtreePath = toSubPath(event.getPath());
if (subtreePath != null) {
fireTreeNodesRemoved(event.getSource(), subtreePath, event.getChildIndices(), event.getChildren());
}
}
public void treeStructureChanged(TreeModelEvent event) {
// XXX - We should check here if the rootPath still exists !!!
Object[] subtreePath = toSubPath(event.getPath());
if (subtreePath != null) {
fireTreeStructureChanged(event.getSource(), subtreePath);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy