X

Geertjan's Blog

  • April 14, 2011

org.openide.actions.NewAction

Geertjan Wielenga
Product Manager
The "org.openide.actions.NewAction" provides out-of-the-box UI for creating subnodes. Just add it to the list of Actions defined for your Node (i.e., its context actions) and you're good to go:
@Override
public Action[] getActions(boolean context) {
return new Action[]{SystemAction.get(NewAction.class)};
}

Read the sources of "NewAction" and you'll find it is a "NodeAction" that is enabled under a very specific condition:

@Override
protected boolean enable(Node[] activatedNodes) {
NewType[] types = getNewTypes();
model.cs.fireChange();
return (types.length > 0);
}

So, if there are one or more "NewType" objects available, then the "NewAction" will be enabled.

Fortunately, the "Node" class gives you a method where you can create "NewType" objects, i.e., "getNewTypes", which returns an array of "NewType" objects. Here's an example:

@Messages({
"LBL_NewProp=System Property",
"LBL_NewProp_dialog=Create New Property",
"MSG_NewProp_dialog_key=New property name:",
"MSG_NewProp_dialog_value=New property value:"})
@Override
public NewType[] getNewTypes() {
return new NewType[]{new NewType() {
@Override
public String getName() {
return LBL_NewProp();
}
@Override
public void create() throws IOException {
NotifyDescriptor.InputLine msg = new NotifyDescriptor.InputLine(LBL_NewProp_dialog(), MSG_NewProp_dialog_key());
DialogDisplayer.getDefault().notify(msg);
String key = msg.getInputText();
if ("".equals(key)) {
return;
}
msg = new NotifyDescriptor.InputLine(MSG_NewProp_dialog_value(), MSG_NewProp_dialog_key());
DialogDisplayer.getDefault().notify(msg);
String value = msg.getInputText();
System.setProperty(key, value);
PropertiesNotifier.changed();
}
}};
}

Run the above and you see this:

What if you had multiple "NewType" objects in the array, i.e., you want to let the user create different types of subnodes? Then the "NewAction" will automatically have a submenu structure, as shown below:

So, when you combine "NewAction" with "NewType", you have an infrastructure for creating new subnodes.

Join the discussion

Comments ( 1 )
  • Ernest Friday, April 15, 2011

    We may want to make the types of new objects that can be created and the way they are created dependent on what is in the Lookup of the Node having the set of new types (thus, context-sensitive), and register them declaratively (this could be done via iterating over Lookups.forPath("my/type/of/node/newtypes").lookupAll(NewType.class) in getNewTypes() of the node.

    However, in this case, as the NewTypes would have no-arg constructors, I don't see how such context could be transferred directly. Would it be necessary to register instances of something resembling

    interface NewTypeFactory {

    NewType create(Lookup context);

    }

    in the layer to obtain this effect?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.