KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > tasklist > usertasks > treetable > AdvancedTreeTableNode


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.tasklist.usertasks.treetable;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Comparator JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import javax.swing.SwingUtilities JavaDoc;
28
29 /**
30  * This "advanced" class provides filtering and sorting of nodes
31  *
32  * T - type of the object in this node
33  */

34 public abstract class AdvancedTreeTableNode<T>
35         extends AbstractTreeTableNode {
36     protected FilterIntf filter;
37     protected Comparator JavaDoc<AdvancedTreeTableNode> comparator;
38     protected DefaultTreeTableModel model;
39     protected T object;
40     
41     /**
42      * Creates a new instance of AdvancedTreeTableNode
43      *
44      * @param model tree table model this node belongs to
45      * @param parent parent of this node or null if this node is a root
46      * @param object object associated with this node
47      */

48     public AdvancedTreeTableNode(DefaultTreeTableModel model,
49         TreeTableNode parent, T object) {
50         super(parent);
51         this.model = model;
52         this.object = object;
53     }
54
55     /**
56      * Returns object associated with this node
57      *
58      * @return object
59      */

60     public T getObject() {
61         return object;
62     }
63     
64     /**
65      * Finds a child with the specified user object
66      *
67      * @param obj user object
68      * @return found node index or -1
69      */

70     public int getIndexOfObject(Object JavaDoc obj) {
71         AdvancedTreeTableNode[] ch = (AdvancedTreeTableNode[]) getChildren();
72         for (int i = 0; i < ch.length; i++) {
73             if (ch[i].getObject() == obj)
74                 return i;
75         }
76         return -1;
77     }
78
79     /**
80      * Sets new comparator or null. This comparator will compare child nodes.
81      *
82      * @param comparator new comparator
83      */

84     public void setComparator(Comparator JavaDoc<AdvancedTreeTableNode> comparator) {
85         if (this.comparator == comparator)
86             return;
87         
88         this.comparator = comparator;
89         
90         if (this.children != null) {
91             if (this.comparator != null) {
92                 Arrays.sort((AdvancedTreeTableNode[]) children,
93                         this.comparator);
94             } else {
95                 AdvancedTreeTableNode[] newch =
96                     new AdvancedTreeTableNode[children.length];
97                 Iterator JavaDoc<?> it = this.getChildrenObjectsIterator();
98                 int i = 0;
99                 while (it.hasNext()) {
100                     int index = getIndexOfObject(it.next());
101                     if (index >= 0)
102                         newch[i++] = (AdvancedTreeTableNode) children[index];
103                 }
104                 children = newch;
105             }
106             model.fireTreeStructureChanged(model, getPathToRoot());
107             for (int i = 0; i < children.length; i++) {
108                 ((AdvancedTreeTableNode<?>) children[i]).
109                         setComparator(comparator);
110             }
111         }
112     }
113     
114     /**
115      * Gets a comparator
116      *
117      * @return comparator or null
118      */

119     public Comparator JavaDoc<AdvancedTreeTableNode> getComparator() {
120         return comparator;
121     }
122     
123     /**
124      * Gets a filter. You should not call getFilter().accept().
125      * Use AdvancedTreeTableNode.accept() instead
126      *
127      * @return filter or null
128      */

129     public FilterIntf getFilter() {
130         return filter;
131     }
132
133     /**
134      * Sets new filter
135      *
136      * @param filter new filter or null
137      */

138     public void setFilter(FilterIntf filter) {
139         this.filter = filter;
140         this.children = null;
141     }
142     
143     /**
144      * Iterator over the objects of children nodes. The filter should not
145      * be yet applied.
146      *
147      * @return the iterator
148      */

149     public abstract Iterator JavaDoc<?> getChildrenObjectsIterator();
150     
151     /**
152      * Creates a children node
153      *
154      * @param child child's object
155      */

156     public abstract AdvancedTreeTableNode<?> createChildNode(Object JavaDoc child);
157     
158     /**
159      * Filtering
160      *
161      * @param child a child object
162      */

163     public boolean accept(Object JavaDoc child) {
164         if (getFilter() != null)
165             return getFilter().accept(child);
166         else
167             return true;
168     }
169     
170     protected void loadChildren() {
171         List JavaDoc<Object JavaDoc> ch = new ArrayList JavaDoc<Object JavaDoc>();
172         Iterator JavaDoc<?> it = getChildrenObjectsIterator();
173         while (it.hasNext()) {
174             ch.add(it.next());
175         }
176         
177         // filtering
178
if (getFilter() != null) {
179             it = ch.iterator();
180             while (it.hasNext()) {
181                 if (!accept(it.next()))
182                     it.remove();
183             }
184         }
185         
186         children = new AdvancedTreeTableNode[ch.size()];
187         for (int i = 0; i < ch.size(); i++) {
188             children[i] = createChildNode(ch.get(i));
189         }
190
191         // sorting
192
if (getComparator() != null)
193             Arrays.sort((AdvancedTreeTableNode[]) children, getComparator());
194     }
195
196     public void refreshChildren() {
197         if (children != null) {
198             for (int i = 0; i < children.length; i++) {
199                 ((AdvancedTreeTableNode) children[i]).destroy();
200             }
201             this.children = null;
202         }
203         model.fireTreeStructureChanged(model, this.getPathToRoot());
204     }
205
206     /**
207      * Will be called after removing the node from the hierarchy
208      */

209     public void destroy() {
210         this.parent = null;
211         if (children != null) {
212             for (int i = 0; i < children.length; i++) {
213                 ((AdvancedTreeTableNode) children[i]).destroy();
214             }
215         }
216     }
217     
218     /**
219      * Fires the appropriate events if the children under this node
220      * were reordered.
221      */

222     protected void fireChildObjectsReordered() {
223         if (children != null) {
224             if (this.comparator == null) {
225                 AdvancedTreeTableNode[] newch =
226                     new AdvancedTreeTableNode[children.length];
227                 Iterator JavaDoc<?> it = this.getChildrenObjectsIterator();
228                 int i = 0;
229                 while (it.hasNext()) {
230                     int index = getIndexOfObject(it.next());
231                     if (index >= 0)
232                         newch[i++] = (AdvancedTreeTableNode) children[index];
233                 }
234                 children = newch;
235                 model.fireTreeStructureChanged(model, getPathToRoot());
236             }
237         }
238     }
239     
240     /**
241      * Fires the appropriate events if a child object was removed
242      *
243      * @param obj one of the child nodes objects
244      */

245     protected void fireChildObjectRemoved(Object JavaDoc obj) {
246         if (children != null) {
247             int ind = getIndexOfObject(obj);
248             if (ind >= 0) {
249                 AdvancedTreeTableNode rem =
250                     (AdvancedTreeTableNode) children[ind];
251                 AdvancedTreeTableNode[] newChildren =
252                     new AdvancedTreeTableNode[children.length - 1];
253                 System.arraycopy(children, 0, newChildren, 0, ind);
254                 System.arraycopy(children, ind + 1, newChildren,
255                     ind, children.length - ind - 1);
256                 rem.destroy();
257                 children = newChildren;
258                 model.fireTreeNodesRemoved(model,
259                     getPathToRoot(),
260                     new int[] {ind}, new Object JavaDoc[] {rem});
261             }
262         }
263     }
264     
265     /**
266      * Fires the appropriate events if a child object was added
267      *
268      * @param obj new child nodes object
269      */

270     protected void fireChildObjectAdded(Object JavaDoc obj) {
271         if (children != null) {
272             if (!accept(obj))
273                 return;
274             
275             AdvancedTreeTableNode cn = createChildNode(obj);
276             
277             int index;
278             if (getComparator() != null) {
279                 index = Arrays.binarySearch(
280                         (AdvancedTreeTableNode[]) children, cn, getComparator());
281                 if (index < 0)
282                     index = -(index + 1);
283             } else {
284                 index = -1;
285                 Iterator JavaDoc<?> it = getChildrenObjectsIterator();
286                 while (it.hasNext()) {
287                     Object JavaDoc next = it.next();
288                     if (!accept(next))
289                         continue;
290                     index++;
291                     if (next == obj)
292                         break;
293                 }
294             }
295             
296             AdvancedTreeTableNode[] newch =
297                 new AdvancedTreeTableNode[children.length + 1];
298             System.arraycopy(children, 0, newch, 0, index);
299             newch[index] = cn;
300             System.arraycopy(children, index, newch, index + 1,
301                 children.length - index);
302             this.children = newch;
303             model.fireTreeNodesInserted(model, getPathToRoot(),
304                 new int[] {index}, new Object JavaDoc[] {cn});
305         }
306     }
307     
308     /**
309      * Fires the appropriate events if the object in this node has changed.
310      * WARNING: This method could only be called from the Swing Event Thread!
311      */

312     @SuppressWarnings JavaDoc("unchecked")
313     protected void fireObjectChanged() {
314         // TreeNode is not generic => SuppressWarnings
315
AdvancedTreeTableNode parent =
316                 (AdvancedTreeTableNode) getParent();
317         TreeTableNode[] path = parent.getPathToRoot();
318
319         assert parent.getIndex(this) != -1 : "parent=" + parent + // NOI18N
320
" this=" + this + // NOI18N
321
" parent.getChildCount=" + parent.getChildCount() + // NOI18N
322
" parent.getChild(0)=" + parent.getChildAt(0); // NOI18N
323
model.fireTreeNodesChanged(model, path,
324             new int[] {parent.getIndex(this)}, new Object JavaDoc[] {this});
325             
326         parent.childNodeChanged(this);
327     }
328     
329     /**
330      * This method will be called to notify this node that a child node's
331      * object has changed and the node should be probably removed
332      * according to the current filter
333      *
334      * @param child changed child node
335      */

336     protected void childNodeChanged(AdvancedTreeTableNode<?> child) {
337         if (getFilter() != null) {
338             if (!accept(child.getObject())) {
339                 // this call is not really the right one here.
340
// The object was not removed. The current filter just
341
// does not accept it.
342
fireChildObjectRemoved(child.getObject());
343             }
344         }
345     }
346
347     public boolean isLeaf() {
348         return getChildren().length == 0;
349     }
350 }
351
Popular Tags