1 /*
2 * %W% %E%
3 *
4 * Copyright 1997, 1998 Sun Microsystems, Inc. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
8 * conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Redistribution in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials
16 * provided with the distribution.
17 *
18 * Neither the name of Sun Microsystems, Inc. or the names of
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * This software is provided "AS IS," without a warranty of any
23 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
24 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
26 * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
27 * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR
28 * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR
29 * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
30 * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
31 * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
32 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
33 * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
34 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
35 *
36 * You acknowledge that this software is not designed, licensed or
37 * intended for use in the design, construction, operation or
38 * maintenance of any nuclear facility.
39 */
40
41 package uk.ac.rdg.resc.jstyx.client.browser;
42
43 import javax.swing.tree.*;
44 import javax.swing.event.*;
45
46 /***
47 * An abstract implementation of the TreeTableModel interface, handling
48 * the list of listeners.
49 *
50 * @version %I% %G%
51 *
52 * @author Philip Milne
53 */
54
55 public abstract class AbstractTreeTableModel implements TreeTableModel
56 {
57 protected Object root;
58 protected EventListenerList listenerList = new EventListenerList();
59
60 /***
61 * Constructs the AbstractTreeTableModel. Must call setRoot() after this
62 * to set the root of the tree.
63 */
64 public AbstractTreeTableModel()
65 {
66 }
67
68 //
69 // Default implmentations for methods in the TreeModel interface.
70 //
71
72 public Object getRoot()
73 {
74 return root;
75 }
76
77 public void setRoot(Object root)
78 {
79 this.root = root;
80 }
81
82 public boolean isLeaf(Object node)
83 {
84 return getChildCount(node) == 0;
85 }
86
87 public void valueForPathChanged(TreePath path, Object newValue)
88 {}
89
90 // This is not called in the JTree's default mode: use a naive implementation.
91 public int getIndexOfChild(Object parent, Object child)
92 {
93 for (int i = 0; i < getChildCount(parent); i++)
94 {
95 if (getChild(parent, i).equals(child))
96 {
97 return i;
98 }
99 }
100 return -1;
101 }
102
103 public void addTreeModelListener(TreeModelListener l)
104 {
105 listenerList.add(TreeModelListener.class, l);
106 }
107
108 public void removeTreeModelListener(TreeModelListener l)
109 {
110 listenerList.remove(TreeModelListener.class, l);
111 }
112
113 /*
114 * Notify all listeners that have registered interest for
115 * notification on this event type. The event instance
116 * is lazily created using the parameters passed into
117 * the fire method.
118 * @see EventListenerList
119 */
120 protected void fireTreeNodesChanged(Object source, Object[] path,
121 int[] childIndices,
122 Object[] children)
123 {
124 // Guaranteed to return a non-null array
125 Object[] listeners = listenerList.getListenerList();
126 TreeModelEvent e = null;
127 // Process the listeners last to first, notifying
128 // those that are interested in this event
129 for (int i = listeners.length-2; i>=0; i-=2)
130 {
131 if (listeners[i]==TreeModelListener.class)
132 {
133 // Lazily create the event:
134 if (e == null)
135 e = new TreeModelEvent(source, path,
136 childIndices, children);
137 ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
138 }
139 }
140 }
141
142 /*
143 * Notify all listeners that have registered interest for
144 * notification on this event type. The event instance
145 * is lazily created using the parameters passed into
146 * the fire method.
147 * @see EventListenerList
148 */
149 protected void fireTreeNodesInserted(Object source, Object[] path,
150 int[] childIndices,
151 Object[] children)
152 {
153 // Guaranteed to return a non-null array
154 Object[] listeners = listenerList.getListenerList();
155 TreeModelEvent e = null;
156 // Process the listeners last to first, notifying
157 // those that are interested in this event
158 for (int i = listeners.length-2; i>=0; i-=2)
159 {
160 if (listeners[i]==TreeModelListener.class)
161 {
162 // Lazily create the event:
163 if (e == null)
164 e = new TreeModelEvent(source, path,
165 childIndices, children);
166 ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
167 }
168 }
169 }
170
171 /*
172 * Notify all listeners that have registered interest for
173 * notification on this event type. The event instance
174 * is lazily created using the parameters passed into
175 * the fire method.
176 * @see EventListenerList
177 */
178 protected void fireTreeNodesRemoved(Object source, Object[] path,
179 int[] childIndices,
180 Object[] children)
181 {
182 // Guaranteed to return a non-null array
183 Object[] listeners = listenerList.getListenerList();
184 TreeModelEvent e = null;
185 // Process the listeners last to first, notifying
186 // those that are interested in this event
187 for (int i = listeners.length-2; i>=0; i-=2)
188 {
189 if (listeners[i]==TreeModelListener.class)
190 {
191 // Lazily create the event:
192 if (e == null)
193 e = new TreeModelEvent(source, path,
194 childIndices, children);
195 ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
196 }
197 }
198 }
199
200 /*
201 * Notify all listeners that have registered interest for
202 * notification on this event type. The event instance
203 * is lazily created using the parameters passed into
204 * the fire method.
205 * @see EventListenerList
206 */
207 protected void fireTreeStructureChanged(Object source, Object[] path,
208 int[] childIndices,
209 Object[] children)
210 {
211 // Guaranteed to return a non-null array
212 Object[] listeners = listenerList.getListenerList();
213 TreeModelEvent e = null;
214 // Process the listeners last to first, notifying
215 // those that are interested in this event
216 for (int i = listeners.length-2; i>=0; i-=2)
217 {
218 if (listeners[i]==TreeModelListener.class)
219 {
220 // Lazily create the event:
221 if (e == null)
222 e = new TreeModelEvent(source, path,
223 childIndices, children);
224 ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
225 }
226 }
227 }
228
229 //
230 // Default impelmentations for methods in the TreeTableModel interface.
231 //
232
233 public Class getColumnClass(int column)
234 { return Object.class; }
235
236 /*** By default, make the column with the Tree in it the only editable one.
237 * Making this column editable causes the JTable to forward mouse
238 * and keyboard events in the Tree column to the underlying JTree.
239 */
240 public boolean isCellEditable(Object node, int column)
241 {
242 return getColumnClass(column) == TreeTableModel.class;
243 }
244
245 public void setValueAt(Object aValue, Object node, int column)
246 {}
247
248
249 // Left to be implemented in the subclass:
250
251 /*
252 * public Object getChild(Object parent, int index)
253 * public int getChildCount(Object parent)
254 * public int getColumnCount()
255 * public String getColumnName(Object node, int column)
256 * public Object getValueAt(Object node, int column)
257 */
258
259 }
260