KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > view > ContextTreeView


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 package org.openide.explorer.view;
20
21 import org.openide.explorer.*;
22 import org.openide.explorer.ExplorerManager.Provider;
23 import org.openide.nodes.Node;
24 import org.openide.nodes.Node.Property;
25
26 import java.awt.*;
27
28 import java.beans.*;
29 import java.util.logging.Logger JavaDoc;
30
31 import javax.swing.*;
32 import javax.swing.tree.*;
33
34
35 /** A view displaying tree of {@link Node}s but not showing its leaf nodes.
36  * Works well together (e.g. sharing one {@link ExplorerManager}) with {@link ListView}.
37  *
38  * <p>
39  * This class is a <q>view</q>
40  * to use it properly you need to add it into a component which implements
41  * {@link Provider}. Good examples of that can be found
42  * in {@link ExplorerUtils}. Then just use
43  * {@link Provider#getExplorerManager} call to get the {@link ExplorerManager}
44  * and control its state.
45  * </p>
46  * <p>
47  * There can be multiple <q>views</q> under one container implementing {@link Provider}. Select from
48  * range of predefined ones or write your own:
49  * </p>
50  * <ul>
51  * <li>{@link org.openide.explorer.view.BeanTreeView} - shows a tree of nodes</li>
52  * <li>{@link org.openide.explorer.view.ContextTreeView} - shows a tree of nodes without leaf nodes</li>
53  * <li>{@link org.openide.explorer.view.ListView} - shows a list of nodes</li>
54  * <li>{@link org.openide.explorer.view.IconView} - shows a rows of nodes with bigger icons</li>
55  * <li>{@link org.openide.explorer.view.ChoiceView} - creates a combo box based on the explored nodes</li>
56  * <li>{@link org.openide.explorer.view.TreeTableView} - shows tree of nodes together with a set of their {@link Property}</li>
57  * <li>{@link org.openide.explorer.view.MenuView} - can create a {@link JMenu} structure based on structure of {@link Node}s</li>
58  * </ul>
59  * <p>
60  * All of these views use {@link ExplorerManager#find} to walk up the AWT hierarchy and locate the
61  * {@link ExplorerManager} to use as a controler. They attach as listeners to
62  * it and also call its setter methods to update the shared state based on the
63  * user action. Not all views make sence together, but for example
64  * {@link org.openide.explorer.view.ContextTreeView} and {@link org.openide.explorer.view.ListView} were designed to complement
65  * themselves and behaves like windows explorer. The {@link org.openide.explorer.propertysheet.PropertySheetView}
66  * for example should be able to work with any other view.
67  * </p>
68  *
69  * @author Petr Hamernik
70  */

71 public class ContextTreeView extends TreeView {
72     /** generated Serialized Version UID */
73     static final long serialVersionUID = -8282594827988436813L;
74     /** logger to find out why the ContextTreeView tests fail so randomly */
75     static final Logger JavaDoc LOG = Logger.getLogger(ContextTreeView.class.getName());
76
77     /** Constructor.
78     */

79     public ContextTreeView() {
80         tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
81     }
82
83     /* @return true if this TreeView accept the selected beans.
84     */

85     protected boolean selectionAccept(Node[] nodes) {
86         if (nodes.length == 0) {
87             return true;
88         }
89
90         Node parent = nodes[0].getParentNode();
91
92         for (int i = 1; i < nodes.length; i++) {
93             if (nodes[i].getParentNode() != parent) {
94                 return false;
95             }
96         }
97
98         return true;
99     }
100
101     /* Called whenever the value of the selection changes.
102     * @param listSelectionEvent the event that characterizes the change.
103     */

104     protected void selectionChanged(Node[] nodes, ExplorerManager man)
105     throws PropertyVetoException {
106         if (nodes.length > 0) {
107             man.setExploredContext(nodes[0]);
108         }
109
110         man.setSelectedNodes(nodes);
111     }
112
113     /** Expand the given path and makes it visible.
114     * @param path the path
115     */

116     protected void showPath(TreePath path) {
117         tree.makeVisible(path);
118
119         Rectangle rect = tree.getPathBounds(path);
120
121         if (rect != null) {
122             rect.width += rect.x;
123             rect.x = 0;
124             tree.scrollRectToVisible(rect);
125         }
126
127         tree.setSelectionPath(path);
128     }
129
130     /** Shows selection to reflect the current state of the selection in the explorer.
131     *
132     * @param paths array of paths that should be selected
133     */

134     protected void showSelection(TreePath[] paths) {
135         if (paths.length == 0) {
136             tree.setSelectionPaths(new TreePath[0]);
137         } else {
138             tree.setSelectionPath(paths[0].getParentPath());
139         }
140     }
141
142     /** Permit use of explored contexts.
143     *
144     * @return <code>true</code> always
145     */

146     protected boolean useExploredContextMenu() {
147         return true;
148     }
149
150     /** Create model.
151     */

152     protected NodeTreeModel createModel() {
153         return new NodeContextModel();
154     }
155
156     /** Excludes leafs from the model.
157      */

158     static final class NodeContextModel extends NodeTreeModel {
159         //
160
// Event filtering
161
//
162
private int[] newIndices;
163         private Object JavaDoc[] newChildren;
164
165         public java.lang.Object JavaDoc getChild(java.lang.Object JavaDoc parent, int index) {
166             int superCnt = super.getChildCount(parent);
167             int myCnt = 0;
168
169             for (int i = 0; i < superCnt; i++) {
170                 Object JavaDoc origChild = super.getChild(parent, i);
171                 Node n = Visualizer.findNode(origChild);
172
173                 if (!n.isLeaf()) {
174                     if (myCnt++ == index) {
175                         return origChild;
176                     }
177                 }
178             }
179
180             return null;
181         }
182
183         public int getChildCount(java.lang.Object JavaDoc parent) {
184             int superCnt = super.getChildCount(parent);
185             int myCnt = 0;
186
187             for (int i = 0; i < superCnt; i++) {
188                 Node n = Visualizer.findNode(super.getChild(parent, i));
189
190                 if (!n.isLeaf()) {
191                     myCnt++;
192                 }
193             }
194
195             return myCnt;
196         }
197
198         public int getIndexOfChild(java.lang.Object JavaDoc parent, java.lang.Object JavaDoc child) {
199             int superCnt = super.getChildCount(parent);
200             int myCnt = 0;
201
202             for (int i = 0; i < superCnt; i++) {
203                 Object JavaDoc origChild = super.getChild(parent, i);
204
205                 if (child.equals(origChild)) {
206                     return myCnt;
207                 }
208
209                 Node n = Visualizer.findNode(origChild);
210
211                 if (!n.isLeaf()) {
212                     myCnt++;
213                 }
214             }
215
216             return -1;
217         }
218
219         public boolean isLeaf(java.lang.Object JavaDoc node) {
220             return false;
221         }
222
223         /** Filters given childIndices and children to contain only non-leafs
224          * return true if there is still something changed.
225          */

226         private boolean filterEvent(Object JavaDoc[] path, int[] childIndices, Object JavaDoc[] children) {
227             assert (childIndices != null) && (children != null) : " ch: " + children + " indices: " + childIndices; // NOI18N
228
assert children.length == childIndices.length : "They should be the same: " + children.length + " == " +
229             childIndices.length; // NOI18N
230
assert newChildren == null : "Children should be cleared: " + newChildren; // NOI18N
231
assert newIndices == null : "indices should be cleared: " + newIndices; // NOI18N
232
assert path.length > 0 : "Path has to be greater than zero " + path.length; // NOI18N
233

234             VisualizerNode parent = (VisualizerNode) path[path.length - 1];
235
236             int[] filter = new int[childIndices.length];
237             int accepted = 0;
238
239             for (int i = 0; i < childIndices.length; i++) {
240                 VisualizerNode n = (VisualizerNode) children[i];
241
242                 if (!n.isLeaf()) {
243                     filter[accepted++] = i;
244                 }
245             }
246
247             if (accepted == 0) {
248                 return false;
249             }
250
251             newIndices = new int[accepted];
252             newChildren = new Object JavaDoc[accepted];
253
254             for (int i = 0; i < accepted; i++) {
255                 newChildren[i] = children[filter[i]];
256                 newIndices[i] = getIndexOfChild(parent, newChildren[i]);
257             }
258
259             return true;
260         }
261
262         /** Filters given childIndices and children to contain only non-leafs
263          * return true if there is still something changed.
264          */

265         private boolean removalEvent(Object JavaDoc[] path, int[] childIndices, Object JavaDoc[] children) {
266             assert (childIndices != null) && (children != null) : " ch: " + children + " indices: " + childIndices; // NOI18N
267
assert children.length == childIndices.length : "They should be the same: " + children.length + " == " +
268             childIndices.length; // NOI18N
269
assert newChildren == null : "Children should be cleared: " + newChildren; // NOI18N
270
assert newIndices == null : "indices should be cleared: " + newIndices; // NOI18N
271
assert path.length > 0 : "Path has to be greater than zero " + path.length; // NOI18N
272

273             VisualizerNode parent = (VisualizerNode) path[path.length - 1];
274
275             int[] filter = new int[childIndices.length];
276             int accepted = 0;
277
278             for (int i = 0; i < childIndices.length; i++) {
279                 VisualizerNode n = (VisualizerNode) children[i];
280
281                 if (!n.isLeaf()) {
282                     filter[accepted++] = i;
283                 }
284             }
285
286             if (accepted == 0) {
287                 return false;
288             }
289
290             newIndices = new int[accepted];
291             newChildren = new Object JavaDoc[accepted];
292
293             int size = getChildCount(parent);
294             int index = 0;
295             int myPos = 0;
296             int actualI = 0;
297             int i = 0;
298
299             for (int pos = 0; pos < accepted;) {
300                 if (childIndices[index] <= i) {
301                     VisualizerNode n = (VisualizerNode) children[index];
302
303                     if (!n.isLeaf()) {
304                         newIndices[pos] = myPos++;
305                         newChildren[pos] = n;
306                         pos++;
307                     }
308
309                     index++;
310                 } else {
311                     VisualizerNode n = (VisualizerNode) getChild(parent, actualI++);
312
313                     if ((n != null) && !n.isLeaf()) {
314                         myPos++;
315                     }
316                 }
317
318                 i++;
319             }
320
321             return true;
322         }
323
324         /* sends childIndices and children == null, no tranformation
325         protected void fireTreeStructureChanged (Object source, Object[] path, int[] childIndices, Object[] children) {
326             if (!filterEvent (childIndices, children)) return;
327             super.fireTreeStructureChanged(source, path, newIndices, newChildren);
328             newIndices = null;
329             newChildren = null;
330         }
331          */

332         protected void fireTreeNodesRemoved(Object JavaDoc source, Object JavaDoc[] path, int[] childIndices, Object JavaDoc[] children) {
333             LOG.fine("fireTreeNodesRemoved"); // NOI18N
334
if (!removalEvent(path, childIndices, children)) {
335                 LOG.fine("fireTreeNodesRemoved - exit"); // NOI18N
336
return;
337             }
338
339             super.fireTreeNodesRemoved(source, path, newIndices, newChildren);
340             newIndices = null;
341             newChildren = null;
342             LOG.fine("fireTreeNodesRemoved - end"); // NOI18N
343
}
344
345         protected void fireTreeNodesInserted(Object JavaDoc source, Object JavaDoc[] path, int[] childIndices, Object JavaDoc[] children) {
346             LOG.fine("fireTreeNodesInserted"); // NOI18N
347
if (!filterEvent(path, childIndices, children)) {
348                 LOG.fine("fireTreeNodesInserted - exit"); // NOI18N
349
return;
350             }
351
352             super.fireTreeNodesInserted(source, path, newIndices, newChildren);
353             newIndices = null;
354             newChildren = null;
355             LOG.fine("fireTreeNodesInserted - end"); // NOI18N
356
}
357
358         protected void fireTreeNodesChanged(Object JavaDoc source, Object JavaDoc[] path, int[] childIndices, Object JavaDoc[] children) {
359             LOG.fine("fireTreeNodesChanged"); // NOI18N
360
if (!filterEvent(path, childIndices, children)) {
361                 LOG.fine("fireTreeNodesChanged - exit"); // NOI18N
362
return;
363             }
364
365             super.fireTreeNodesChanged(source, path, newIndices, newChildren);
366             newIndices = null;
367             newChildren = null;
368             LOG.fine("fireTreeNodesChanged - end"); // NOI18N
369
}
370     }
371      // end of NodeContextModel
372
}
373
Popular Tags