| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.spi.actions; |
| |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.util.Collection; |
| import java.util.LinkedList; |
| import java.util.List; |
| import javax.swing.Action; |
| import org.openide.util.Lookup; |
| import org.openide.util.lookup.ProxyLookup; |
| |
| /** |
| * A ContextAction which looks for a specific subclass of Lookup.Provider |
| * in the selection, and then delegates to another ContextAction for that |
| * type. |
| * <p/> |
| * This class can be used to do multiple levels of indirection, simply |
| * by passing another instance of IndirectAction to the constructor. |
| * Say that you want to write an action that operates on the |
| * ClassPathProvider of the Project which the selected Node belongs to. |
| * This can be written quite simply: |
| * <pre> |
| * ContextAction<ClassPathProvider> theRealAction = new MyContextAction(); |
| * Action theGlobalAction = new IndirectAction<Node>(Project.class, new IndirectAction(ClassPathProvider.class, theRealAction)); |
| * </pre> |
| * <p/> |
| * |
| * @param <T> The type of Lookup.Provider to look for in the lookup. |
| * @param <R> The type that the passed ContextAction is interested in |
| * @author Tim Boudreau |
| */ |
| final class IndirectAction<T extends Lookup.Provider, R> extends ContextAction<T> { |
| final ContextAction<R> delegate; |
| private final PCL pcl = new PCL(); |
| private final boolean all; |
| |
| /** |
| * Create a new IndirectAction. |
| * |
| * @param toLookupType The type of Lookup.Provider to find in the |
| * selection |
| * @param delegate The action that will look in those Lookup.Providers |
| * lookups |
| */ |
| public IndirectAction(Class<T> toLookupType, ContextAction<R> delegate, boolean all) { |
| super(toLookupType); |
| this.delegate = delegate; |
| this.all = all; |
| } |
| |
| @Override |
| void internalAddNotify() { |
| super.internalAddNotify(); |
| delegate.addPropertyChangeListener(pcl); |
| } |
| |
| @Override |
| void internalRemoveNotify() { |
| super.internalRemoveNotify(); |
| delegate.removePropertyChangeListener(pcl); |
| } |
| |
| @Override |
| public Object getValue(String key) { |
| Object result = super.getValue(key); |
| if (result == null) { |
| result = delegate.getValue(key); |
| } |
| return result; |
| } |
| |
| private Lookup delegateLookup(Collection<? extends T> targets) { |
| List<Lookup> lookups = new LinkedList<Lookup>(); |
| for (Lookup.Provider provider : targets) { |
| Lookup lkp = provider.getLookup(); |
| if (all && lkp.lookupResult(delegate.type).allItems().size() == 0) { |
| return Lookup.EMPTY; |
| } |
| lookups.add(provider.getLookup()); |
| } |
| Lookup proxy = new ProxyLookup(lookups.toArray(new Lookup[0])); |
| return proxy; |
| } |
| |
| @Override |
| protected void actionPerformed(Collection<? extends T> targets) { |
| Action delegateStub = delegate.createContextAwareInstance(delegateLookup(targets)); |
| delegateStub.actionPerformed(null); |
| } |
| |
| @Override |
| protected boolean isEnabled(Collection<? extends T> targets) { |
| Action delegateStub = delegate.createContextAwareInstance(delegateLookup(targets)); |
| return delegateStub.isEnabled(); |
| } |
| |
| @Override |
| public boolean equals (Object o) { |
| return o != null && o.getClass() == IndirectAction.class && delegate.equals(((IndirectAction) o).delegate); |
| } |
| |
| /** |
| * Returns getClass().hashCode(); |
| * @return The hash code of this type. |
| */ |
| @Override |
| public int hashCode() { |
| return delegate.hashCode(); |
| } |
| |
| private final class PCL implements PropertyChangeListener { |
| |
| public void propertyChange(PropertyChangeEvent evt) { |
| firePropertyChange(evt.getPropertyName(), evt.getOldValue(), |
| evt.getNewValue()); |
| } |
| } |
| } |