KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > search > ResultTreeModel


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.search;
21
22 import java.awt.EventQueue JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.List JavaDoc;
25 import javax.swing.event.TreeModelEvent JavaDoc;
26 import javax.swing.event.TreeModelListener JavaDoc;
27 import javax.swing.tree.TreeModel JavaDoc;
28 import javax.swing.tree.TreePath JavaDoc;
29 import org.openide.nodes.Node;
30
31 /**
32  *
33  *
34  * @author Marian Petras
35  */

36 final class ResultTreeModel implements TreeModel JavaDoc {
37     
38     /** */
39     final ResultModel resultModel;
40     /** */
41     private final TreePath JavaDoc rootPath;
42     /** */
43     private String JavaDoc rootDisplayName;
44     /** */
45     private boolean selected = true;
46     /** */
47     private int objectsCount;
48     /** */
49     private List JavaDoc<TreeModelListener JavaDoc> treeModelListeners;
50     
51     /**
52      *
53      * @param resultModel result model, or {@code null} for empty tree model
54      */

55     ResultTreeModel(ResultModel resultModel) {
56         this.resultModel = resultModel;
57         this.rootPath = new TreePath JavaDoc(this);
58         
59         if (resultModel != null) {
60             resultModel.setObserver(this);
61         }
62     }
63
64     public Object JavaDoc getRoot() {
65         return this;
66     }
67     
68     public Object JavaDoc getChild(Object JavaDoc parent, int index) {
69         assert EventQueue.isDispatchThread();
70         
71         if ((resultModel == null) || (index < 0)) {
72             return null;
73         }
74         
75         Object JavaDoc ret;
76         if (parent == getRoot()) {
77             if (index >= objectsCount) {
78                 ret = null;
79             } else {
80                 try {
81                     //PENDING - threading:
82
ret = resultModel.matchingObjects.get(index);
83                 } catch (ArrayIndexOutOfBoundsException JavaDoc ex) {
84                     assert false;
85                     ret = null;
86                 }
87             }
88         } else if (parent.getClass() == MatchingObject.class) {
89             if (!resultModel.canHaveDetails()) {
90                 ret = null;
91             } else {
92                 MatchingObject matchingObject = (MatchingObject) parent;
93                 Node[] detailNodes
94                         = resultModel.searchAndReplace
95                           ? resultModel.fullTextSearchType.getDetails(
96                                                     matchingObject.object)
97                           : resultModel.getDetails(matchingObject);
98                 if ((detailNodes == null) || (index >= detailNodes.length)) {
99                     ret = null;
100                 } else {
101                     ret = detailNodes[index];
102                 }
103             }
104         } else { //detail node
105
ret = null;
106         }
107         return ret;
108     }
109     
110     public int getChildCount(Object JavaDoc parent) {
111         assert EventQueue.isDispatchThread();
112         
113         if (resultModel == null) {
114             return 0;
115         }
116         
117         int ret;
118         if (parent == getRoot()) {
119             ret = objectsCount;
120         } else if (parent.getClass() == MatchingObject.class) {
121             if (resultModel.searchAndReplace) {
122                 ret = resultModel.fullTextSearchType.getDetailsCount(
123                                             ((MatchingObject) parent).object);
124             } else if (resultModel.canHaveDetails() == Boolean.FALSE) {
125                 ret = 0;
126             } else {
127                 ret = resultModel.getDetailsCount((MatchingObject) parent);
128             }
129         } else { //detail node
130
ret = 0;
131         }
132         return ret;
133     }
134
135     public boolean isLeaf(Object JavaDoc node) {
136         assert EventQueue.isDispatchThread();
137         
138         boolean ret;
139         if (node == getRoot()) {
140             ret = false;
141         } else if (node.getClass() == MatchingObject.class) {
142             Boolean JavaDoc hasDetails = resultModel.canHaveDetails();
143             if (hasDetails != null) {
144                 ret = !hasDetails.booleanValue();
145             } else {
146                 ret = !resultModel.hasDetails((MatchingObject) node);
147             }
148         } else { //detail node
149
ret = true;
150         }
151         return ret;
152     }
153
154     public void valueForPathChanged(TreePath JavaDoc path, Object JavaDoc newValue) {
155         assert EventQueue.isDispatchThread();
156         
157         /* This should never be called. None of the nodes is editable. */
158         assert false;
159     }
160
161     public int getIndexOfChild(Object JavaDoc parent, Object JavaDoc child) {
162         assert EventQueue.isDispatchThread();
163         
164         if ((resultModel == null) || (parent == null) || (child == null)) {
165             return -1;
166         }
167         
168         int ret;
169         if (parent == getRoot()) {
170             ret = (child.getClass() == MatchingObject.class)
171                   ? resultModel.matchingObjects.indexOf(child)
172                   : -1;
173         } else {
174             ret = -1;
175             if ((parent.getClass() == MatchingObject.class)
176                     && resultModel.canHaveDetails()
177                     && (child instanceof Node)) {
178                 MatchingObject matchingObject = (MatchingObject) parent;
179                 Node[] detailNodes
180                         = resultModel.searchAndReplace
181                           ? resultModel.fullTextSearchType.getDetails(
182                                         matchingObject.object)
183                           : resultModel.getDetails(matchingObject);
184                 if (detailNodes != null) {
185                     for (int i = 0; i < detailNodes.length; i++) {
186                         if (detailNodes[i].equals(child)) {
187                             ret = i;
188                             break;
189                         }
190                     }
191                 }
192             }
193         }
194         return ret;
195     }
196
197     public void addTreeModelListener(TreeModelListener JavaDoc l) {
198         assert EventQueue.isDispatchThread();
199         
200         if (l == null) {
201             throw new IllegalArgumentException JavaDoc("null"); //NOI18N
202
}
203         
204         if (treeModelListeners == null) {
205             treeModelListeners = new ArrayList JavaDoc<TreeModelListener JavaDoc>(4);
206         }
207         treeModelListeners.add(l);
208     }
209
210     public void removeTreeModelListener(TreeModelListener JavaDoc l) {
211         assert EventQueue.isDispatchThread();
212         
213         if (l == null) {
214             throw new IllegalArgumentException JavaDoc("null"); //NOI18N
215
}
216         
217         if (treeModelListeners != null) {
218             treeModelListeners.remove(l);
219         }
220     }
221     
222     /**
223      */

224     void objectFound(MatchingObject object, int objectIndex) {
225         if (resultModel == null) {
226             throw new IllegalStateException JavaDoc("resultModel is null"); //NOI18N
227
}
228         new Task(object, objectIndex).run();//fireNodeAdded(objectIndex, object);
229
}
230     
231     /**
232      */

233     void objectBecameInvalid(MatchingObject object) {
234         if (resultModel == null) {
235             throw new IllegalStateException JavaDoc("resultModel is null"); //NOI18N
236
}
237         new Task(object).run();
238     }
239     
240     /**
241      */

242     String JavaDoc getRootDisplayName() {
243         assert EventQueue.isDispatchThread();
244         
245         return rootDisplayName;
246     }
247     
248     /** */
249     void setRootDisplayName(String JavaDoc displayName) {
250         assert EventQueue.isDispatchThread();
251         
252         this.rootDisplayName = displayName;
253         UPDATE_NAME_TASK.run(); //fireRootNodeChanged();
254
}
255     
256     /**
257      */

258     boolean isSelected() {
259         return selected;
260     }
261     
262     /**
263      */

264     void setSelected(boolean selected) {
265         if (selected == this.selected) {
266             return;
267         }
268         
269         this.selected = selected;
270     }
271     
272     private final Task UPDATE_NAME_TASK = new Task();
273     /**
274      * Single class for sending various asynchronous tasks to the event queue.
275      */

276     private final class Task implements Runnable JavaDoc {
277         private final MatchingObject foundObject;
278         private final int foundObjectIndex;
279         private Task() {
280             this.foundObject = null;
281             this.foundObjectIndex = -1;
282         }
283         private Task(MatchingObject object) {
284             this.foundObject = object;
285             this.foundObjectIndex = -1;
286         }
287         private Task(MatchingObject foundObject, int foundObjectIndex) {
288             assert (foundObject != null) && (foundObjectIndex >= 0);
289             this.foundObject = foundObject;
290             this.foundObjectIndex = foundObjectIndex;
291         }
292         public void run() {
293             if (!EventQueue.isDispatchThread()) {
294                 EventQueue.invokeLater(this);
295                 return;
296             }
297             
298             assert EventQueue.isDispatchThread();
299             if (foundObject != null) {
300                 if (foundObjectIndex != -1) {
301                     objectsCount++;
302                     fireNodeAdded(foundObjectIndex, foundObject);
303                 } else {
304                     fireNodeChanged(foundObject);
305                 }
306             } else {
307                 fireRootNodeChanged();
308             }
309         }
310     }
311     
312     /**
313      */

314     private void fireNodeAdded(int index, MatchingObject object) {
315         assert EventQueue.isDispatchThread();
316         
317         if ((treeModelListeners == null) || treeModelListeners.isEmpty()) {
318             return;
319         }
320         
321         TreeModelEvent JavaDoc event = new TreeModelEvent JavaDoc(this,
322                                                   rootPath,
323                                                   new int[] { index },
324                                                   new Object JavaDoc[] { object });
325         for (TreeModelListener JavaDoc l : treeModelListeners) {
326             l.treeNodesInserted(event);
327         }
328     }
329     
330     /**
331      */

332     private void fireNodeChanged(MatchingObject object) {
333         assert EventQueue.isDispatchThread();
334         
335         if ((treeModelListeners == null) || treeModelListeners.isEmpty()) {
336             return;
337         }
338         
339         TreePath JavaDoc path = rootPath.pathByAddingChild(object);
340         TreeModelEvent JavaDoc event = new TreeModelEvent JavaDoc(this, path);
341         for (TreeModelListener JavaDoc l : treeModelListeners) {
342             l.treeStructureChanged(event);
343         }
344     }
345
346     /**
347      */

348     void fireRootNodeChanged() {
349         assert EventQueue.isDispatchThread();
350         
351         if ((treeModelListeners == null) || treeModelListeners.isEmpty()) {
352             return;
353         }
354         
355         TreeModelEvent JavaDoc event = new TreeModelEvent JavaDoc(this, rootPath, null, null);
356         for (TreeModelListener JavaDoc l : treeModelListeners) {
357             l.treeNodesChanged(event);
358         }
359     }
360     
361     /**
362      */

363     void fireFileNodesSelectionChanged(int[] indices,
364                                        MatchingObject[] matchingObjects) {
365         assert EventQueue.isDispatchThread();
366         assert matchingObjects != null;
367         assert indices != null;
368         assert matchingObjects.length == indices.length;
369         
370         if ((treeModelListeners == null) || treeModelListeners.isEmpty()) {
371             return;
372         }
373
374         TreeModelEvent JavaDoc event = new TreeModelEvent JavaDoc(this,
375                                                   rootPath,
376                                                   indices,
377                                                   matchingObjects);
378         for (TreeModelListener JavaDoc l : treeModelListeners) {
379             l.treeNodesChanged(event);
380         }
381     }
382     
383     /**
384      * Notifies the listeners that selection of the given
385      * {@code MatchingObject}'s has changed.
386      *
387      * @param matchingObj object's whose node's selection has changed
388      * @param includingSubnodes whether listeners should be notified also
389      * about change of the node's children's
390      * selection
391      * @see MatchingObj#markChildrenSelectionDirty()
392      */

393     void fireFileNodeSelectionChanged(MatchingObject matchingObj,
394                                       boolean includingSubnodes) {
395         assert EventQueue.isDispatchThread();
396         
397         if ((treeModelListeners == null) || treeModelListeners.isEmpty()) {
398             return;
399         }
400
401         final int index = resultModel.matchingObjects.indexOf(matchingObj);
402         
403         /* Notify that the file node itself has changed... */
404         TreeModelEvent JavaDoc event = new TreeModelEvent JavaDoc(this,
405                                                   rootPath,
406                                                   new int[] { index },
407                                                   new Object JavaDoc[] { matchingObj });
408         for (TreeModelListener JavaDoc l : treeModelListeners) {
409             l.treeNodesChanged(event);
410         }
411         
412         if (includingSubnodes) {
413             /* ... and also all its children need to be updated: */
414             fireFileNodeChildrenSelectionChanged(matchingObj);
415         }
416     }
417     
418     /**
419      */

420     void fireFileNodeChildrenSelectionChanged(MatchingObject matchingObj) {
421         Node[] children = resultModel.fullTextSearchType
422                           .getDetails(matchingObj.object);
423         int[] indices = new int[children.length];
424         for (int i = 0; i < indices.length; i++) {
425             indices[i] = i;
426         }
427         final TreeModelEvent JavaDoc event = new TreeModelEvent JavaDoc(
428                                         this,
429                                         new Object JavaDoc[] { getRoot(), matchingObj },
430                                         indices,
431                                         children);
432         for (TreeModelListener JavaDoc l : treeModelListeners) {
433             l.treeNodesChanged(event);
434         }
435     }
436     
437     /**
438      */

439     void fireDetailNodeSelectionChanged(MatchingObject matchingObj,
440                                         int index) {
441         assert EventQueue.isDispatchThread();
442         
443         if ((treeModelListeners == null) || treeModelListeners.isEmpty()) {
444             return;
445         }
446
447         int[] changedIndices = new int[] { index };
448         Node[] detailNodes = resultModel.fullTextSearchType
449                              .getDetails(matchingObj.object);
450         Node[] changedNodes = (detailNodes.length == 1)
451                               ? detailNodes
452                               : new Node[] { detailNodes[index] };
453         TreeModelEvent JavaDoc event = new TreeModelEvent JavaDoc(
454                                         this,
455                                         new Object JavaDoc[] { getRoot(), matchingObj },
456                                         changedIndices,
457                                         changedNodes);
458         for (TreeModelListener JavaDoc l : treeModelListeners) {
459             l.treeNodesChanged(event);
460         }
461     }
462     
463     /** Returns display name of the root node.
464      * @return display name of the root node.
465      */

466     public String JavaDoc toString() {
467         return super.toString() + "[" + rootDisplayName + "]"; // NOI18N
468
}
469 }
470
Popular Tags