001    package ui.model;
002    
003    import javax.swing.tree.*;
004    import javax.swing.event.*;
005    
006    /**
007     * @version 1.2 10/27/98
008     * An abstract implementation of the TreeTableModel interface, handling the list
009     * of listeners.
010     * @author Philip Milne
011     */
012    public abstract class AbstractTreeTableModel implements TreeTableModel {
013        protected Object root;
014        protected EventListenerList listenerList = new EventListenerList();
015    
016        public AbstractTreeTableModel(Object root) {
017            this.root = root;
018        }
019    
020        //
021        // Default implmentations for methods in the TreeModel interface.
022        //
023        public Object getRoot() {
024            return root;
025        }
026    
027        public boolean isLeaf(Object node) {
028            return getChildCount(node) == 0;
029        }
030    
031        public void valueForPathChanged(TreePath path, Object newValue) {}
032    
033        // This is not called in the JTree's default mode: use a naive implementation.
034        public int getIndexOfChild(Object parent, Object child) {
035            for (int i = 0; i < getChildCount(parent); i++) {
036                if (getChild(parent, i).equals(child)) {
037                    return i;
038                }
039            }
040            return -1;
041        }
042    
043        public void addTreeModelListener(TreeModelListener l) {
044            listenerList.add(TreeModelListener.class, l);
045        }
046    
047        public void removeTreeModelListener(TreeModelListener l) {
048            listenerList.remove(TreeModelListener.class, l);
049        }
050    
051        /*
052         * Notify all listeners that have registered interest for
053         * notification on this event type.  The event instance
054         * is lazily created using the parameters passed into
055         * the fire method.
056         * @see EventListenerList
057         */
058        protected void fireTreeNodesChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
059            Object[] listeners = listenerList.getListenerList();  // Guaranteed to return a non-null array
060            TreeModelEvent e = null;
061            // Process the listeners last to first, notifying
062            // those that are interested in this event
063            for (int i = listeners.length-2; i>=0; i-=2) {
064                if (listeners[i]==TreeModelListener.class) {
065                    // Lazily create the event:
066                    if (e == null) e = new TreeModelEvent(source, path, childIndices, children);
067                    ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
068                }
069            }
070        }
071    
072        protected void fireTreeNodesInserted(Object source, Object[] path, int[] childIndices, Object[] children) {
073            Object[] listeners = listenerList.getListenerList();
074            TreeModelEvent e = null;
075            for (int i = listeners.length-2; i>=0; i-=2) {
076                if (listeners[i]==TreeModelListener.class) {
077                    if (e == null) e = new TreeModelEvent(source, path, childIndices, children);
078                    ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
079                }
080            }
081        }
082    
083        protected void fireTreeNodesRemoved(Object source, Object[] path, int[] childIndices, Object[] children) {
084            Object[] listeners = listenerList.getListenerList();
085            TreeModelEvent e = null;
086            for (int i = listeners.length-2; i>=0; i-=2) {
087                if (listeners[i]==TreeModelListener.class) {
088                    if (e == null) e = new TreeModelEvent(source, path, childIndices, children);
089                    ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
090                }
091            }
092        }
093    
094        protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
095            Object[] listeners = listenerList.getListenerList();
096            TreeModelEvent e = null;
097            for (int i = listeners.length-2; i>=0; i-=2) {
098                if (listeners[i]==TreeModelListener.class) {
099                    if (e == null) e = new TreeModelEvent(source, path, childIndices, children);
100                    ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
101                }
102            }
103        }
104    
105        //
106        // Default impelmentations for methods in the TreeTableModel interface.
107        //
108        public Class getColumnClass(int column) { return Object.class; }
109    
110       /** By default, make the column with the Tree in it the only editable one.
111        *  Making this column editable causes the JTable to forward mouse
112        *  and keyboard events in the Tree column to the underlying JTree.
113        */
114        public boolean isCellEditable(Object node, int column) {
115             return getColumnClass(column) == TreeTableModel.class;
116        }
117    
118        public void setValueAt(Object aValue, Object node, int column) {}
119    
120    
121        // Left to be implemented in the subclass:
122        /*
123         *   public Object getChild(Object parent, int index)
124         *   public int getChildCount(Object parent)
125         *   public int getColumnCount()
126         *   public String getColumnName(Object node, int column)
127         *   public Object getValueAt(Object node, int column)
128         */
129    }