1 19 package org.openide.windows; 20 21 import org.openide.nodes.Node; 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.AbstractLookup; 27 import org.openide.util.lookup.Lookups; 28 import org.openide.util.lookup.ProxyLookup; 29 30 import java.util.ArrayList ; 31 import java.util.Collection ; 32 import java.util.Collections ; 33 import java.util.HashMap ; 34 import java.util.IdentityHashMap ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.Map ; 38 import java.util.Set ; 39 import java.util.WeakHashMap ; 40 41 42 53 final class DefaultTopComponentLookup extends ProxyLookup implements LookupListener { 54 private static final Object PRESENT = new Object (); 55 56 57 private TopComponent tc; 58 59 60 private LookupListener listener; 61 62 63 private Map <Lookup,Lookup.Result> attachedTo; 64 65 66 private Lookup actionMap; 67 68 71 public DefaultTopComponentLookup(TopComponent tc) { 72 super(); 73 74 this.tc = tc; 75 this.listener = (LookupListener) WeakListeners.create(LookupListener.class, this, null); 76 this.actionMap = Lookups.singleton(new DelegateActionMap(tc)); 77 78 updateLookups(tc.getActivatedNodes()); 79 } 80 81 84 public void updateLookups(Node[] arr) { 85 if (arr == null) { 86 AbstractLookup.Content c = new AbstractLookup.Content(); 87 AbstractLookup l = new AbstractLookup(c); 88 c.addPair(new NoNodesPair()); 89 setLookups(new Lookup[] { l, actionMap }); 90 91 return; 92 } 93 94 Lookup[] lookups = new Lookup[arr.length]; 95 96 Map <Lookup,Lookup.Result> copy; 97 98 synchronized (this) { 99 if (attachedTo == null) { 100 copy = Collections.emptyMap(); 101 } else { 102 copy = new HashMap <Lookup,Lookup.Result>(attachedTo); 103 } 104 } 105 106 for (int i = 0; i < arr.length; i++) { 107 lookups[i] = arr[i].getLookup(); 108 109 if (copy != null) { 110 copy.remove(arr[i]); 112 } 113 } 114 115 for (Iterator <Lookup.Result> it = copy.values().iterator(); it.hasNext();) { 116 Lookup.Result res = it.next(); 117 res.removeLookupListener(listener); 118 } 119 120 synchronized (this) { 121 attachedTo = null; 122 } 123 124 setLookups(new Lookup[] { new NoNodeLookup(new ProxyLookup(lookups), arr), Lookups.fixed((Object [])arr), actionMap, }); 125 } 126 127 128 public void resultChanged(LookupEvent ev) { 129 updateLookups(tc.getActivatedNodes()); 130 } 131 132 136 private static boolean isNodeQuery(Class <?> c) { 137 return Node.class.isAssignableFrom(c) || c.isAssignableFrom(Node.class); 138 } 139 140 protected synchronized void beforeLookup(Template<?> t) { 141 if ((attachedTo == null) && isNodeQuery(t.getType())) { 142 Lookup[] arr = getLookups(); 143 144 attachedTo = new WeakHashMap <Lookup,Lookup.Result>(arr.length * 2); 145 146 for (int i = 0; i < (arr.length - 2); i++) { 147 Lookup.Result<?> res = arr[i].lookup(t); 148 res.addLookupListener(listener); 149 attachedTo.put(arr[i], res); 150 } 151 } 152 } 153 154 private static final class NoNodesPair extends AbstractLookup.Pair { 155 public NoNodesPair() { 156 } 157 158 protected boolean creatorOf(Object obj) { 159 return false; 160 } 161 162 public String getDisplayName() { 163 return getId(); 164 } 165 166 public String getId() { 167 return "none"; } 169 170 public Object getInstance() { 171 return null; 172 } 173 174 public Class getType() { 175 return org.openide.nodes.Node.class; 176 } 177 178 protected boolean instanceOf(Class c) { 179 return Node.class.isAssignableFrom(c); 180 } 181 } 182 184 186 190 private static final class NoNodeLookup extends Lookup { 191 private final Lookup delegate; 192 private final Map <Object ,Object > verboten; 193 194 public NoNodeLookup(Lookup del, Object [] exclude) { 195 delegate = del; 196 verboten = new IdentityHashMap <Object ,Object >(); 197 198 for (int i = 0; i < exclude.length; verboten.put(exclude[i++], PRESENT)) 199 ; 200 } 201 202 public <T> T lookup(Class <T> clazz) { 203 if (clazz == Node.class) { 204 return null; 205 } else { 206 T o = delegate.lookup(clazz); 207 208 if (verboten.containsKey(o)) { 209 for( T o2 : lookupAll(clazz) ) { 211 212 if (!verboten.containsKey(o2)) { 213 return o2; 215 } 216 } 217 218 return null; 220 } else { 221 return o; 222 } 223 } 224 } 225 226 @SuppressWarnings ("unchecked") 227 public <T> Lookup.Result<T> lookup(Lookup.Template<T> template) { 228 if (template.getType() == Node.class) { 229 return Lookup.EMPTY.lookup(new Lookup.Template(Node.class)); 230 } else { 231 return new ExclusionResult<T>(delegate.lookup(template), verboten); 232 } 233 } 234 235 238 private static final class ExclusionResult<T> extends Lookup.Result<T> implements LookupListener { 239 private final Lookup.Result<T> delegate; 240 private final Map <Object ,Object > verboten; 241 private final List <LookupListener> listeners = new ArrayList <LookupListener>(); 242 243 public ExclusionResult(Lookup.Result<T> delegate, Map <Object ,Object > verboten) { 244 this.delegate = delegate; 245 this.verboten = verboten; 246 } 247 248 public Collection <? extends T> allInstances() { 249 Collection <? extends T> c = delegate.allInstances(); 250 List <T> ret = new ArrayList <T>(c.size()); 252 for (Iterator <? extends T> it = c.iterator(); it.hasNext();) { 253 T o = it.next(); 254 255 if (!verboten.containsKey(o)) { 256 ret.add(o); 257 } 258 } 259 260 return ret; 261 } 262 263 public Set <Class <? extends T>> allClasses() { 264 return delegate.allClasses(); } 266 267 public Collection <? extends Lookup.Item<T>> allItems() { 268 Collection <? extends Lookup.Item<T>> c = delegate.allItems(); 269 List <Lookup.Item<T>> ret = new ArrayList <Lookup.Item<T>>(c.size()); 271 for (Iterator <? extends Lookup.Item<T>> it = c.iterator(); it.hasNext();) { 272 Lookup.Item<T> i = it.next(); 273 274 if (!verboten.containsKey(i.getInstance())) { 275 ret.add(i); 276 } 277 } 278 279 return ret; 280 } 281 282 public void addLookupListener(LookupListener l) { 283 synchronized (listeners) { 284 if (listeners.isEmpty()) { 285 delegate.addLookupListener(this); 286 } 287 288 listeners.add(l); 289 } 290 } 291 292 public void removeLookupListener(LookupListener l) { 293 synchronized (listeners) { 294 listeners.remove(l); 295 296 if (listeners.isEmpty()) { 297 delegate.removeLookupListener(this); 298 } 299 } 300 } 301 302 public void resultChanged(LookupEvent ev) { 303 LookupEvent ev2 = new LookupEvent(this); 304 LookupListener[] ls; 305 306 synchronized (listeners) { 307 ls = (LookupListener[]) listeners.toArray(new LookupListener[listeners.size()]); 308 } 309 310 for (int i = 0; i < ls.length; i++) { 311 ls[i].resultChanged(ev2); 312 } 313 } 314 } 315 } 316 } 317 | Popular Tags |