/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.openide.actions;
import java.beans.PropertyChangeListener;
import javax.swing.event.*;
import org.openide.DialogDisplayer;
import org.openide.util.datatransfer.NewType;
import org.openide.util.HelpCtx;
import org.openide.util.actions.*;
import org.openide.awt.*;
import org.openide.nodes.Node;
import org.openide.NotifyDescriptor;
import org.openide.explorer.ExplorerManager;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
/** Creates a new child of the activated node, if appropriate.
* @see Node#getNewTypes
*
* @author Petr Hamernik, Ian Formanek
*/
public final class NewAction extends NodeAction {
/** generated Serialized Version UID */
static final long serialVersionUID = 5569219524388004456L;
/** Imlementation of ActSubMenuInt */
private static ActSubMenuModel model = new ActSubMenuModel(null);
protected void performAction (Node[] activatedNodes) {
performAction (activatedNodes, 0);
}
/** Performs action on index and nodes.
*/
private static void performAction (Node[] activatedNodes, int indx) {
NewType[] types = getNewTypes (activatedNodes);
if (types.length <= indx) {
return;
}
performAction (activatedNodes, types[indx]);
}
/** Performs action on given type
*/
private static void performAction (Node[] activatedNodes, NewType type) {
PasteAction.NodeSelector sel = null;
try {
ExplorerManager em = PasteAction.findExplorerManager();
if (em != null) {
sel = new PasteAction.NodeSelector (em, activatedNodes);
}
type.create();
} catch (java.io.IOException e) {
DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(e.getMessage(), NotifyDescriptor.ERROR_MESSAGE));
} finally {
if (sel != null) {
sel.select ();
}
}
}
/** Getter for array of activated new types.
*/
private static NewType[] getNewTypes () {
return getNewTypes (
WindowManager.getDefault().getRegistry ().getCurrentNodes ()
);
}
/** Getter for array of activated new types.
*/
private static NewType[] getNewTypes (Node[] activatedNodes) {
if (activatedNodes == null || activatedNodes.length != 1) {
return new NewType[0];
} else {
return activatedNodes[0].getNewTypes ();
}
}
protected boolean enable (Node[] activatedNodes) {
NewType[] types = getNewTypes ();
// notify listeners
Object[] listeners = model.getListenerList();
if (listeners.length > 0) {
ChangeEvent ev = new ChangeEvent (model);
for (int i = listeners.length-1; i>=0; i-=2) {
((ChangeListener)listeners[i]).stateChanged (ev);
}
}
return (types.length > 0);
}
/* Human presentable name of the action. This should be
* presented as an item in a menu.
* @return the name of the action
*/
public String getName() {
return createName(getNewTypes());
}
/* Help context where to find more about the action.
* @return the help context for this action
*/
public HelpCtx getHelpCtx() {
return new HelpCtx (NewAction.class);
}
/* Icon resource.
* @return name of resource for icon
*/
protected String iconResource () {
return "org/openide/resources/actions/new.gif"; // NOI18N
}
/* Returns a JMenuItem that presents the Action, that implements this
* interface, in a MenuBar.
* @return the JMenuItem representation for the Action
*/
public javax.swing.JMenuItem getMenuPresenter() {
return new Actions.SubMenu(this, model, false);
}
/* Returns a JMenuItem that presents the Action, that implements this
* interface, in a PopuMenu.
* @return the JMenuItem representation for the Action
*/
public javax.swing.JMenuItem getPopupPresenter() {
return new Actions.SubMenu(this, model, true);
}
/** Overrides superclass method. */
public javax.swing.Action createContextAwareInstance(Lookup actionContext) {
return new DelegateAction(this, actionContext);
}
/** Utility method, creates name for action depending on specified new types. */
private static String createName(NewType[] newTypes) {
if ((newTypes != null) && (newTypes.length == 1)) {
return NbBundle.getMessage(NewAction.class, "NewArg", newTypes[0].getName());
} else {
return NbBundle.getMessage(NewAction.class, "New");
}
}
/** Implementation of ActSubMenuInt */
private static class ActSubMenuModel extends EventListenerList implements Actions.SubMenuModel {
static final long serialVersionUID =-4273674308662494596L;
/** lookup to read the new types from or null if they whould be taken
* directly from top component's selected nodes
*/
private Lookup lookup;
ActSubMenuModel (Lookup lookup) {
this.lookup = lookup;
}
private NewType[] newTypes () {
if (lookup != null) {
java.util.Collection c = lookup.lookup (
new Lookup.Template (Node.class)
).allItems ();
if (c.size () == 1) {
java.util.Iterator it = c.iterator();
while (it.hasNext()) {
Lookup.Item item = (Lookup.Item)it.next ();
Node n = (Node)item.getInstance();
if (n != null) {
return n.getNewTypes();
}
}
}
}
return getNewTypes ();
}
public int getCount() {
return newTypes ().length;
}
public String getLabel(int index) {
NewType[] newTypes = newTypes();
if (newTypes.length <= index)
return null;
else
return newTypes[index].getName();
}
public HelpCtx getHelpCtx (int index) {
NewType[] newTypes = newTypes();
if (newTypes.length <= index)
return null;
else
return newTypes[index].getHelpCtx();
}
public void performActionAt(int index) {
NewType[] nt = newTypes ();
if (nt.length < index) {
return;
}
Node[] arr;
if (lookup != null) {
arr = (Node[])lookup.lookup (new Lookup.Template (Node.class)).allInstances ().toArray (new Node[0]);
} else {
arr = WindowManager.getDefault().getRegistry ().getCurrentNodes ();
}
performAction (arr, nt[index]);
}
/** Adds change listener for changes of the model.
*/
public void addChangeListener (ChangeListener l) {
add (ChangeListener.class, l);
}
/** Removes change listener for changes of the model.
*/
public void removeChangeListener (ChangeListener l) {
remove (ChangeListener.class, l);
}
} // end of ActSubMenuModel
/** A delegate action that is usually associated with a specific lookup and
* extract the nodes it operates on from it. Otherwise it delegates to the
* regular NodeAction.
*/
private static final class DelegateAction extends Object
implements javax.swing.Action,
Presenter.Menu, Presenter.Popup {
/** Action to delegate to. */
private final NodeAction delegate;
/** Associated model to use. */
private final ActSubMenuModel model;
public DelegateAction (NodeAction a, Lookup actionContext) {
this.delegate = a;
this.model = new ActSubMenuModel(actionContext);
}
/** Overrides superclass method, adds delegate description. */
public String toString() {
return super.toString() + "[delegate=" + delegate + "]"; // NOI18N
}
/** Invoked when an action occurs.
*/
public void actionPerformed(java.awt.event.ActionEvent e) {
model.performActionAt(0);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
public void putValue(String key, Object o) {}
public Object getValue(String key) {
if(javax.swing.Action.NAME.equals(key)) {
// #30266 Name of action depends on new types.
return createName(model.newTypes());
} else {
return delegate.getValue(key);
}
}
public boolean isEnabled() {
return model.getCount() > 0;
}
public void setEnabled(boolean b) {
}
public javax.swing.JMenuItem getMenuPresenter() {
return new Actions.SubMenu(this, model, false);
}
public javax.swing.JMenuItem getPopupPresenter() {
return new Actions.SubMenu(this, model, true);
}
} // end of DelegateAction
}