KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > DefaultEMLookup


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;
20
21 import org.openide.nodes.*;
22 import org.openide.util.Lookup;
23 import org.openide.util.LookupEvent;
24 import org.openide.util.LookupListener;
25 import org.openide.util.WeakListeners;
26 import org.openide.util.lookup.Lookups;
27 import org.openide.util.lookup.ProxyLookup;
28
29 import java.beans.*;
30
31 import java.util.*;
32
33
34 /**
35  * Contents of the lookup for a ExplorerManager, is copied
36  * from org.openide.windows.DefaultTopComponentLookup and shares
37  * its test. If updating, please update both.
38  * @author Jaroslav Tulach
39  */

40 final class DefaultEMLookup extends ProxyLookup implements LookupListener, PropertyChangeListener {
41     private static final Object JavaDoc PRESENT = new Object JavaDoc();
42
43     /** component to work with */
44     private ExplorerManager tc;
45
46     /** lookup listener that is attached to all subnodes */
47     private LookupListener listener;
48
49     /** Map of (Node -> node Lookup.Result) the above lookup listener is attached to */
50     private Map<Lookup, Lookup.Result> attachedTo;
51
52     /** action map for the top component */
53     private Lookup actionMap;
54
55     /** Creates the lookup.
56      * @param tc component to work on
57      * @param map action map to add to the lookup
58     */

59     public DefaultEMLookup(ExplorerManager tc, javax.swing.ActionMap JavaDoc map) {
60         super();
61
62         this.tc = tc;
63         this.listener = WeakListeners.create(LookupListener.class, this, null);
64         this.actionMap = Lookups.singleton(map);
65
66         tc.addPropertyChangeListener(WeakListeners.propertyChange(this, tc));
67
68         updateLookups(tc.getSelectedNodes());
69     }
70
71     /** Extracts activated nodes from a top component and
72      * returns their lookups.
73      */

74     public void updateLookups(Node[] arr) {
75         if (arr == null) {
76             arr = new Node[0];
77         }
78
79         Lookup[] lookups = new Lookup[arr.length];
80
81         Map<Lookup, Lookup.Result> copy;
82
83         synchronized (this) {
84             if (attachedTo == null) {
85                 copy = Collections.<Lookup, Lookup.Result>emptyMap();
86             } else {
87                 copy = new HashMap<Lookup, Lookup.Result>(attachedTo);
88             }
89         }
90
91         for (int i = 0; i < arr.length; i++) {
92             lookups[i] = arr[i].getLookup();
93
94             if (copy != null) {
95                 // node arr[i] remains there, so do not remove it
96
copy.remove(arr[i]);
97             }
98         }
99
100         for (Iterator<Lookup.Result> it = copy.values().iterator(); it.hasNext();) {
101             Lookup.Result res = it.next();
102             res.removeLookupListener(listener);
103         }
104
105         synchronized (this) {
106             attachedTo = null;
107         }
108
109         setLookups(new Lookup[] { new NoNodeLookup(new ProxyLookup(lookups), arr), Lookups.fixed((Object JavaDoc[])arr), actionMap, });
110     }
111
112     /** Change in one of the lookups we delegate to */
113     public void resultChanged(LookupEvent ev) {
114         updateLookups(tc.getSelectedNodes());
115     }
116
117     /** Finds out whether a query for a class can be influenced
118      * by a state of the "nodes" lookup and whether we should
119      * initialize listening
120      */

121     private static boolean isNodeQuery(Class JavaDoc<?> c) {
122         return Node.class.isAssignableFrom(c) || c.isAssignableFrom(Node.class);
123     }
124
125     protected synchronized void beforeLookup(Template<?> t) {
126         if ((attachedTo == null) && isNodeQuery(t.getType())) {
127             Lookup[] arr = getLookups();
128
129             attachedTo = new WeakHashMap<Lookup, Lookup.Result>(arr.length * 2);
130
131             for (int i = 0; i < (arr.length - 2); i++) {
132                 Lookup.Result res = arr[i].lookup(t);
133                 res.addLookupListener(listener);
134                 attachedTo.put(arr[i], res);
135             }
136         }
137     }
138
139     public void propertyChange(PropertyChangeEvent evt) {
140         if (ExplorerManager.PROP_SELECTED_NODES == evt.getPropertyName()) {
141             updateLookups((Node[]) evt.getNewValue());
142         }
143     }
144
145     /**
146      * A proxying Lookup impl which yields no results when queried for Node,
147      * and will never return any of the listed objects.
148      */

149     private static final class NoNodeLookup extends Lookup {
150         private final Lookup delegate;
151         private final Map<Node, Object JavaDoc> verboten;
152
153         public NoNodeLookup(Lookup del, Node[] exclude) {
154             delegate = del;
155             verboten = new IdentityHashMap<Node, Object JavaDoc>();
156
157             for (int i = 0; i < exclude.length; verboten.put(exclude[i++], PRESENT))
158                 ;
159         }
160
161         public <T> T lookup(Class JavaDoc<T> clazz) {
162             if (clazz == Node.class) {
163                 return null;
164             } else {
165                 T o = delegate.lookup(clazz);
166
167                 if (verboten.containsKey(o)) {
168                     // There might be another one of the same class.
169
Iterator<? extends T> it = lookup(new Lookup.Template<T>(clazz)).allInstances().iterator();
170
171                     while (it.hasNext()) {
172                         T o2 = it.next();
173
174                         if (!verboten.containsKey(o2)) {
175                             // OK, use this one.
176
return o2;
177                         }
178                     }
179
180                     // All such instances were excluded.
181
return null;
182                 } else {
183                     return o;
184                 }
185             }
186         }
187
188         public <T> Lookup.Result<T> lookup(Lookup.Template<T> template) {
189             Class JavaDoc<T> clz = template.getType();
190             if (clz == Node.class) {
191                 return Lookup.EMPTY.lookup(new Lookup.Template<T>(clz));
192             } else {
193                 return new ExclusionResult<T>(delegate.lookup(template), verboten);
194             }
195         }
196
197         /**
198          * A lookup result excluding some instances.
199          */

200         private static final class ExclusionResult<T> extends Lookup.Result<T> implements LookupListener {
201             private final Lookup.Result<T> delegate;
202             private final Map<Node, Object JavaDoc> verboten;
203             private final List<LookupListener> listeners = new ArrayList<LookupListener>();
204
205             public ExclusionResult(Lookup.Result<T> delegate, Map<Node, Object JavaDoc> verboten) {
206                 this.delegate = delegate;
207                 this.verboten = verboten;
208             }
209
210             public Collection<? extends T> allInstances() {
211                 Collection<? extends T> c = delegate.allInstances();
212                 List<T> ret = new ArrayList<T>(c.size()); // upper bound
213

214                 for (T o: c) {
215                     if (!verboten.containsKey(o)) {
216                         ret.add(o);
217                     }
218                 }
219
220                 return ret;
221             }
222
223             public Set<Class JavaDoc<? extends T>> allClasses() {
224                 return delegate.allClasses(); // close enough
225
}
226
227             public Collection<? extends Item<T>> allItems() {
228                 Collection<? extends Item<T>> c = delegate.allItems();
229                 List<Item<T>> ret = new ArrayList<Item<T>>(c.size()); // upper bound
230

231                 for (Lookup.Item<T> i : c) {
232
233                     if (!verboten.containsKey(i.getInstance())) {
234                         ret.add(i);
235                     }
236                 }
237
238                 return ret;
239             }
240
241             public void addLookupListener(LookupListener l) {
242                 synchronized (listeners) {
243                     if (listeners.isEmpty()) {
244                         delegate.addLookupListener(this);
245                     }
246
247                     listeners.add(l);
248                 }
249             }
250
251             public void removeLookupListener(LookupListener l) {
252                 synchronized (listeners) {
253                     listeners.remove(l);
254
255                     if (listeners.isEmpty()) {
256                         delegate.removeLookupListener(this);
257                     }
258                 }
259             }
260
261             public void resultChanged(LookupEvent ev) {
262                 LookupEvent ev2 = new LookupEvent(this);
263                 LookupListener[] ls;
264
265                 synchronized (listeners) {
266                     ls = listeners.toArray(new LookupListener[listeners.size()]);
267                 }
268
269                 for (int i = 0; i < ls.length; i++) {
270                     ls[i].resultChanged(ev2);
271                 }
272             }
273         }
274     }
275      // end of NoNodeLookup
276
}
277
Popular Tags