diff --git a/src/de/javagl/treetable/AbstractTreeTableModel.java b/src/de/javagl/treetable/AbstractTreeTableModel.java index 312071118..760d0237f 100644 --- a/src/de/javagl/treetable/AbstractTreeTableModel.java +++ b/src/de/javagl/treetable/AbstractTreeTableModel.java @@ -1 +1,258 @@ -/* * www.javagl.de - JTreeTable * * Copyright (c) 2016 Marco Hutter - http://www.javagl.de * * This library is based on the code from the article "Creating TreeTables" * by Sun Microsystems (now known as Oracle). * * The original copyright header: * * Copyright 1998 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. * * - Redistributions 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 nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package de.javagl.treetable; import javax.swing.tree.*; import javax.swing.event.*; /** * An abstract implementation of the TreeTableModel interface, handling the list * of listeners.
*
* Note: In order to actually display the JTree in one column of the * JTreeTable, implementors of this class have to return the * TreeTableModel.class as the respective column class * in their implementation of the {@link #getColumnClass(int)} method: *

 * public Class<?> getColumnClass(int column)
 * {
 *     if (column == columnThatShouldContainTheTree)
 *     {
 *         return TreeTableModel.class;
 *     }
 *     // Return other types as desired:
 *     return Object.class;
 * }
 * 
*/ public abstract class AbstractTreeTableModel implements TreeTableModel { /** * The root node of the tree */ protected Object root; /** * The TreeModelListeners that will be notified about modifications */ private final EventListenerList listenerList = new EventListenerList(); /** * Default constructor * * @param root The root node of the tree */ protected AbstractTreeTableModel(Object root) { this.root = root; } @Override public Object getRoot() { return root; } @Override public boolean isLeaf(Object node) { return getChildCount(node) == 0; } @Override public void valueForPathChanged(TreePath path, Object newValue) { // Empty default implementation } @Override 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; } @Override public void addTreeModelListener(TreeModelListener l) { listenerList.add(TreeModelListener.class, l); } @Override public void removeTreeModelListener(TreeModelListener l) { listenerList.remove(TreeModelListener.class, l); } /** * Notify 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 source of the event * @param path The tree path * @param childIndices The child indices * @param children The children */ protected final void fireTreeNodesChanged( Object source, Object[] path, int[] childIndices, Object[] children) { Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == TreeModelListener.class) { if (e == null) { e = new TreeModelEvent( source, path, childIndices, children); } ((TreeModelListener) listeners[i + 1]).treeNodesChanged(e); } } } /** * Notify 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 source of the event * @param path The tree path * @param childIndices The child indices * @param children The children */ protected final void fireTreeNodesInserted( Object source, Object[] path, int[] childIndices, Object[] children) { Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == TreeModelListener.class) { if (e == null) { e = new TreeModelEvent( source, path, childIndices, children); } ((TreeModelListener) listeners[i + 1]).treeNodesInserted(e); } } } /** * Notify 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 source of the event * @param path The tree path * @param childIndices The child indices * @param children The children */ protected final void fireTreeNodesRemoved( Object source, Object[] path, int[] childIndices, Object[] children) { Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == TreeModelListener.class) { if (e == null) { e = new TreeModelEvent( source, path, childIndices, children); } ((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e); } } } /** * Notify 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 source of the event * @param path The tree path * @param childIndices The child indices * @param children The children */ protected final void fireTreeStructureChanged( Object source, Object[] path, int[] childIndices, Object[] children) { Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == TreeModelListener.class) { if (e == null) { e = new TreeModelEvent( source, path, childIndices, children); } ((TreeModelListener) listeners[i + 1]).treeStructureChanged(e); } } } @Override public boolean isCellEditable(Object node, int column) { return getColumnClass(column) == TreeTableModel.class; } @Override public void setValueAt(Object aValue, Object node, int column) { // Empty default implementation } } \ No newline at end of file +/* + * www.javagl.de - JTreeTable + * + * Copyright (c) 2016 Marco Hutter - http://www.javagl.de + * + * This library is based on the code from the article "Creating TreeTables" + * by Sun Microsystems (now known as Oracle). + * + * The original copyright header: + * + * Copyright 1998 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. + * + * - Redistributions 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 nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package de.javagl.treetable; + +import javax.swing.tree.*; +import javax.swing.event.*; + +/** + * An abstract implementation of the TreeTableModel interface, handling the list + * of listeners.
+ *
+ * Note: In order to actually display the JTree in one column of the + * JTreeTable, implementors of this class have to return the + * TreeTableModel.class as the respective column class + * in their implementation of the {@link #getColumnClass(int)} method: + *

+ * public Class<?> getColumnClass(int column)
+ * {
+ *     if (column == columnThatShouldContainTheTree)
+ *     {
+ *         return TreeTableModel.class;
+ *     }
+ *     // Return other types as desired:
+ *     return Object.class;
+ * }
+ * 
+ */ +public abstract class AbstractTreeTableModel implements TreeTableModel +{ + /** + * The root node of the tree + */ + protected Object root; + + /** + * The TreeModelListeners that will be notified about modifications + */ + private final EventListenerList listenerList = new EventListenerList(); + + /** + * Default constructor + * + * @param root The root node of the tree + */ + protected AbstractTreeTableModel(Object root) + { + this.root = root; + } + + @Override + public Object getRoot() + { + return root; + } + + @Override + public boolean isLeaf(Object node) + { + return getChildCount(node) == 0; + } + + @Override + public void valueForPathChanged(TreePath path, Object newValue) + { + // Empty default implementation + } + + @Override + 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; + } + + @Override + public void addTreeModelListener(TreeModelListener l) + { + listenerList.add(TreeModelListener.class, l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) + { + listenerList.remove(TreeModelListener.class, l); + } + + /** + * Notify 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 source of the event + * @param path The tree path + * @param childIndices The child indices + * @param children The children + */ + protected final void fireTreeNodesChanged( + Object source, Object[] path, int[] childIndices, Object[] children) + { + Object[] listeners = listenerList.getListenerList(); + TreeModelEvent e = null; + for (int i = listeners.length - 2; i >= 0; i -= 2) + { + if (listeners[i] == TreeModelListener.class) + { + if (e == null) + { + e = new TreeModelEvent( + source, path, childIndices, children); + } + ((TreeModelListener) listeners[i + 1]).treeNodesChanged(e); + } + } + } + + /** + * Notify 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 source of the event + * @param path The tree path + * @param childIndices The child indices + * @param children The children + */ + protected final void fireTreeNodesInserted( + Object source, Object[] path, int[] childIndices, Object[] children) + { + Object[] listeners = listenerList.getListenerList(); + TreeModelEvent e = null; + for (int i = listeners.length - 2; i >= 0; i -= 2) + { + if (listeners[i] == TreeModelListener.class) + { + if (e == null) + { + e = new TreeModelEvent( + source, path, childIndices, children); + } + ((TreeModelListener) listeners[i + 1]).treeNodesInserted(e); + } + } + } + + /** + * Notify 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 source of the event + * @param path The tree path + * @param childIndices The child indices + * @param children The children + */ + protected final void fireTreeNodesRemoved( + Object source, Object[] path, int[] childIndices, Object[] children) + { + Object[] listeners = listenerList.getListenerList(); + TreeModelEvent e = null; + for (int i = listeners.length - 2; i >= 0; i -= 2) + { + if (listeners[i] == TreeModelListener.class) + { + if (e == null) + { + e = new TreeModelEvent( + source, path, childIndices, children); + } + ((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e); + } + } + } + + /** + * Notify 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 source of the event + * @param path The tree path + * @param childIndices The child indices + * @param children The children + */ + protected final void fireTreeStructureChanged( + Object source, Object[] path, int[] childIndices, Object[] children) + { + Object[] listeners = listenerList.getListenerList(); + TreeModelEvent e = null; + for (int i = listeners.length - 2; i >= 0; i -= 2) + { + if (listeners[i] == TreeModelListener.class) + { + if (e == null) + { + e = new TreeModelEvent( + source, path, childIndices, children); + } + ((TreeModelListener) listeners[i + 1]).treeStructureChanged(e); + } + } + } + + @Override + public boolean isCellEditable(Object node, int column) + { + return getColumnClass(column) == TreeTableModel.class; + } + + @Override + public void setValueAt(Object aValue, Object node, int column) + { + // Empty default implementation + } + +}