001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.xslt.tmap.multiview.source;
020:
021: import java.beans.PropertyChangeEvent;
022: import java.beans.PropertyChangeListener;
023: import org.openide.nodes.Node;
024: import org.openide.util.Lookup;
025: import org.openide.util.lookup.Lookups;
026: import org.openide.util.lookup.ProxyLookup;
027:
028: /**
029: * A ProxyLookup that changes the last delegate lookup to not return instances
030: * of Node.class depending on changes to the "activatedNodes" property. The
031: * value of this is that the delegate lookup comes from a DataObject Node
032: * delegate, which presumably provides cookies such as SaveCookie. But we
033: * do not want the Node delegate to return instances of Node via its Lookup
034: * (specifically the Node delegate itself).
035: *
036: * <p>Usage, from within a <code>TopComponent</code> constructor:</p>
037: *
038: * <pre>
039: * SourceCookieProxyLookup cpl = new SourceCookieProxyLookup(new Lookup[] {
040: * lookup1,
041: * lookup2,
042: * // The Node delegate Lookup must be the last one in the list
043: * // for the CookieProxyLookup to work properly.
044: * delegate.getLookup(),
045: * }, delegate);
046: * associateLookup(cpl);
047: * addPropertyChangeListener("activatedNodes", cpl);
048: * </pre>
049: *
050: * @author Vitaly Bychkov
051: * @author Nathan Fiedler
052: * @version 1.0
053: */
054: public class SourceCookieProxyLookup extends ProxyLookup implements
055: PropertyChangeListener {
056:
057: /** Lookups excluding activated nodes and their lookups . */
058: private Lookup[] lookups;
059: /** The Node to which we delegate lookup for cookies. */
060: private Node delegate;
061: /** Signal that we are processing a property change event. */
062: private boolean propertyChanging;
063:
064: /**
065: * Creates a new instance of CookieProxyLookup.
066: *
067: * @param lookups the Lookup instances to which we proxy.
068: * @param delegate the Node delegate from which cookies come.
069: */
070: public SourceCookieProxyLookup(Lookup[] lookups, Node delegate) {
071: super ();
072: this .lookups = lookups;
073: this .delegate = delegate;
074: setLookups(new Lookup[] { new ProxyLookup(lookups),
075: delegate.getLookup(), Lookups.singleton(delegate) });
076: }
077:
078: public synchronized void propertyChange(PropertyChangeEvent event) {
079: if (propertyChanging) {
080: // Avoid an infinite loop whereby changing the lookup contents
081: // causes the activated nodes to change, which calls us again.
082: return;
083: }
084: propertyChanging = true;
085: try {
086: Node[] newNodes = (Node[]) event.getNewValue();
087: if (newNodes == null || newNodes.length == 0) {
088: setLookups(new Lookup[] { new ProxyLookup(lookups),
089: new NoNodeLookup(delegate.getLookup()),
090: Lookups.singleton(delegate) });
091: } else {
092: Lookup[] newNodeLookups = new Lookup[newNodes.length];
093: for (int i = 0; i < newNodes.length; i++) {
094: newNodeLookups[i] = new NoNodeLookup(newNodes[i]
095: .getLookup());
096: }
097: setLookups(new Lookup[] { new ProxyLookup(lookups),
098: new ProxyLookup(newNodeLookups),
099: Lookups.fixed(newNodes) });
100: }
101: } finally {
102: propertyChanging = false;
103: }
104: }
105:
106: /*
107: * Lookup that excludes nodes. Needed for use with instanceof in the
108: * property change listener.
109: */
110: private static class NoNodeLookup extends Lookup {
111:
112: private final Lookup delegate;
113:
114: public NoNodeLookup(Lookup delegate) {
115: this .delegate = delegate;
116: }
117:
118: @Override
119: public <T> T lookup(Class<T> clazz) {
120: return (clazz == Node.class) ? null : delegate
121: .lookup(clazz);
122: }
123:
124: @Override
125: public <T> Result<T> lookup(Template<T> template) {
126: if (template.getType() == Node.class) {
127: return Lookup.EMPTY.lookup(template);
128: }
129: return delegate.lookup(template);
130: }
131: }
132: }
|