1 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 40 final class DefaultEMLookup extends ProxyLookup implements LookupListener, PropertyChangeListener { 41 private static final Object PRESENT = new Object (); 42 43 44 private ExplorerManager tc; 45 46 47 private LookupListener listener; 48 49 50 private Map<Lookup, Lookup.Result> attachedTo; 51 52 53 private Lookup actionMap; 54 55 59 public DefaultEMLookup(ExplorerManager tc, javax.swing.ActionMap 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 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 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 [])arr), actionMap, }); 110 } 111 112 113 public void resultChanged(LookupEvent ev) { 114 updateLookups(tc.getSelectedNodes()); 115 } 116 117 121 private static boolean isNodeQuery(Class <?> 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 149 private static final class NoNodeLookup extends Lookup { 150 private final Lookup delegate; 151 private final Map<Node, Object > verboten; 152 153 public NoNodeLookup(Lookup del, Node[] exclude) { 154 delegate = del; 155 verboten = new IdentityHashMap<Node, Object >(); 156 157 for (int i = 0; i < exclude.length; verboten.put(exclude[i++], PRESENT)) 158 ; 159 } 160 161 public <T> T lookup(Class <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 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 return o2; 177 } 178 } 179 180 return null; 182 } else { 183 return o; 184 } 185 } 186 } 187 188 public <T> Lookup.Result<T> lookup(Lookup.Template<T> template) { 189 Class <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 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 > verboten; 203 private final List<LookupListener> listeners = new ArrayList<LookupListener>(); 204 205 public ExclusionResult(Lookup.Result<T> delegate, Map<Node, Object > 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()); 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 <? extends T>> allClasses() { 224 return delegate.allClasses(); } 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()); 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 } 277 | Popular Tags |