1 19 package org.openide.util.actions; 20 21 import org.openide.nodes.Node; 22 import org.openide.nodes.NodeAdapter; 23 import org.openide.nodes.NodeListener; 24 import org.openide.util.Lookup; 25 import org.openide.util.Mutex; 26 27 import java.beans.PropertyChangeEvent ; 28 29 import java.lang.ref.*; 30 31 import java.util.*; 32 33 34 39 public abstract class CookieAction extends NodeAction { 40 41 private static final String PROP_COOKIES = "cookies"; 43 45 public static final int MODE_ONE = 0x01; 46 47 50 public static final int MODE_SOME = 0x02; 51 52 54 public static final int MODE_ALL = 0x04; 55 56 58 public static final int MODE_EXACTLY_ONE = 0x08; 59 60 62 public static final int MODE_ANY = 0x07; 63 64 private static final long serialVersionUID = 6031319415908298424L; 66 private CookiesChangeListener listener = new CookiesChangeListener(this); 67 68 72 protected abstract int mode(); 73 74 79 protected abstract Class <?>[] cookieClasses(); 81 84 private Class <?>[] getCookies() { 85 Class [] ret = (Class []) getProperty(PROP_COOKIES); 86 87 if (ret != null) { 88 return ret; 89 } 90 91 ret = cookieClasses(); 92 putProperty(PROP_COOKIES, ret); 93 94 return ret; 95 } 96 97 105 protected boolean enable(Node[] activatedNodes) { 106 if (activatedNodes.length == 0) { 107 return false; 108 } 109 110 listener.setNodes(activatedNodes); 112 113 return doEnable(activatedNodes); 115 } 116 117 118 public javax.swing.Action createContextAwareInstance(Lookup actionContext) { 119 return new CookieDelegateAction(this, actionContext); 120 } 121 122 123 boolean doEnable(Node[] activatedNodes) { 124 int supported = resolveSupported(activatedNodes); 125 126 if (supported == 0) { 127 return false; 128 } 129 130 int mode = mode(); 131 132 return 133 ((mode & MODE_ONE) != 0) || (((mode & MODE_ALL) != 0) && (supported == activatedNodes.length)) || 135 (((mode & MODE_EXACTLY_ONE) != 0) && (activatedNodes.length == 1)) || 136 (((mode & MODE_SOME) != 0) && (supported < activatedNodes.length)); 137 } 138 139 145 private int resolveSupported(Node[] activatedNodes) { 146 int ret = 0; 147 148 Class <?>[] cookies = getCookies(); 149 150 for (Node n : activatedNodes) { 151 for (Class <?> cookie : cookies) { 152 @SuppressWarnings ("unchecked") 154 Lookup.Template<?> templ = new Lookup.Template(cookie); 155 if (n.getLookup().lookupItem(templ) != null) { 156 ret++; 157 158 break; 159 } 160 } 161 } 162 163 return ret; 164 } 165 166 168 private static final class CookiesChangeListener extends NodeAdapter { 169 170 private org.openide.nodes.NodeListener listener; 171 172 173 private List<Reference<Node>> nodes; 174 175 176 private Reference<CookieAction> action; 177 178 180 public CookiesChangeListener(CookieAction a) { 181 listener = org.openide.nodes.NodeOp.weakNodeListener(this, null); 182 action = new WeakReference<CookieAction>(a); 183 } 184 185 186 void setNodes(Node[] newNodes) { 187 List<Reference<Node>> nodes2 = this.nodes; 189 190 if (nodes2 != null) { 191 detachListeners(nodes2); 192 } 193 194 nodes = null; 195 196 if (newNodes != null) { 198 nodes = new ArrayList<Reference<Node>>(newNodes.length); 199 200 for (int i = 0; i < newNodes.length; i++) 201 nodes.add(new WeakReference<Node>(newNodes[i])); 202 203 attachListeners(nodes); 204 } 205 } 206 207 208 void detachListeners(List<Reference<Node>> nodes) { 209 Iterator<Reference<Node>> it = nodes.iterator(); 210 211 while (it.hasNext()) { 212 Node node = it.next().get(); 213 214 if (node != null) { 215 node.removeNodeListener(listener); 216 } 217 } 218 } 219 220 221 void attachListeners(List<Reference<Node>> nodes) { 222 Iterator<Reference<Node>> it = nodes.iterator(); 223 224 while (it.hasNext()) { 225 Node node = it.next().get(); 226 227 if (node != null) { 228 node.addNodeListener(listener); 229 } 230 } 231 } 232 233 235 public void propertyChange(PropertyChangeEvent ev) { 236 if (!Node.PROP_COOKIE.equals(ev.getPropertyName())) { 238 return; 239 } 240 241 final CookieAction a = action.get(); 243 244 if (a == null) { 245 return; 246 } 247 248 List<Reference<Node>> _nodes = this.nodes; 249 250 if (_nodes != null) { 251 ArrayList<Node> nonNullNodes = new ArrayList<Node>(_nodes.size()); 252 Iterator<Reference<Node>> it = _nodes.iterator(); 253 254 while (it.hasNext()) { 255 Node node = it.next().get(); 256 257 if (node != null) { 258 nonNullNodes.add(node); 259 } else { 260 return; 262 } 263 } 264 265 final Node[] nodes2 = new Node[nonNullNodes.size()]; 266 nonNullNodes.toArray(nodes2); 267 268 Mutex.EVENT.writeAccess( 269 new Runnable () { 270 public void run() { 271 a.setEnabled(a.enable(nodes2)); 272 } 273 } 274 ); 275 } 276 } 277 278 protected void finalize() { 279 detachListeners(nodes); 280 } 281 } 282 284 288 final static class CookieDelegateAction extends org.openide.util.actions.NodeAction.DelegateAction 289 implements org.openide.nodes.NodeListener, Runnable { 290 291 private org.openide.nodes.NodeListener listener; 292 293 294 private List<Reference<Node>> nodes; 295 296 public CookieDelegateAction(CookieAction a, Lookup actionContext) { 297 super(a, actionContext); 298 listener = org.openide.nodes.NodeOp.weakNodeListener(this, null); 299 setNodes(nodes()); 300 } 301 302 public void resultChanged(org.openide.util.LookupEvent ev) { 303 setNodes(nodes()); 304 superResultChanged(ev); 305 } 306 307 private void superResultChanged(org.openide.util.LookupEvent ev) { 308 super.resultChanged(ev); 309 } 310 311 public void childrenAdded(org.openide.nodes.NodeMemberEvent ev) { 312 } 313 314 public void childrenRemoved(org.openide.nodes.NodeMemberEvent ev) { 315 } 316 317 public void childrenReordered(org.openide.nodes.NodeReorderEvent ev) { 318 } 319 320 public void nodeDestroyed(org.openide.nodes.NodeEvent ev) { 321 } 322 323 public void propertyChange(PropertyChangeEvent ev) { 324 if (!Node.PROP_COOKIE.equals(ev.getPropertyName())) { 326 return; 327 } 328 329 Mutex.EVENT.readAccess(this); 331 } 332 333 public void run() { 334 superResultChanged(null); 335 } 336 337 338 private void setNodes(org.openide.nodes.Node[] newNodes) { 339 detachListeners(nodes); 341 342 if (newNodes != null) { 344 nodes = new ArrayList<Reference<Node>>(newNodes.length); 345 346 for (int i = 0; i < newNodes.length; i++) 347 nodes.add(new WeakReference<Node>(newNodes[i])); 348 } 349 350 attachListeners(nodes); 352 } 353 354 355 private void detachListeners(List<Reference<Node>> nodes) { 356 if (nodes != null) { 357 Iterator<Reference<Node>> it = nodes.iterator(); 358 359 while (it.hasNext()) { 360 Node node = it.next().get(); 361 362 if (node != null) { 363 node.removeNodeListener(listener); 364 } 365 } 366 } 367 } 368 369 370 private void attachListeners(List<Reference<Node>> nodes) { 371 if (nodes != null) { 372 Iterator<Reference<Node>> it = nodes.iterator(); 373 374 while (it.hasNext()) { 375 Node node = it.next().get(); 376 377 if (node != null) { 378 node.addNodeListener(listener); 379 } 380 } 381 } 382 } 383 384 protected void finalize() { 385 detachListeners(nodes); 386 } 387 } 388 } 390 | Popular Tags |