Please see org.openide.options for the relevant classes.


Options API

What are Options?

NetBeans system options are groupings of user-settable properties which a module author desires to make available for two purposes: allowing a user to view and modify the existing settings pertaining to a module; and allowing NetBeans to store these options to disk when it needs to, in a centralized operation (so that it is easy for an administrator to see where all NetBeans settings reside).

Options installed into the system are automatically saved to disk when changed.

Creating a System Option

Creating a new system option is generally quite easy. In simple cases, the entire source for a system option can fit on one page.

Creating the singleton class

First you must subclass SystemOption (or one of its subclasses). The option class should be a singleton, i.e. it does not need any per-instance state; all variable members can be static. You should create one static member (typically) for each property that you want to provide, and also give it a sensible default value. Regardless, the option should have a default constructor so that it can be instantiated.

Note that all property values must be serializable!

Conventionally, option class names are based on the module providing them, and ought to end in Settings: e.g., MyModuleSettings. This does not affect display, however; every option must implement SystemOption.displayName() to provide a reasonable name to present to users in the Control Panel.

If it makes other code in the module more convenient, you may want to have a static "get the default" method in the option which returns the singleton of the option - but this is in no way required. Keeping the singleton as a static variable in any class is discouraged as it forces the system to load the stored option's settings as soon as that class is resolved, when otherwise loading the settings might never have been required.

Providing getters and setters for properties

First of all, it is a good idea to make static variables containing the event name of each property you are exposing, e.g.:
/** Property name for foreground color of my module, of type {@link Color}. */
public static final String PROPERTY_FOREGROUND = "foreground";
Doing so makes it possible for other components to listen to changes in the option object.

Then, a nonstatic getter/setter pair should be provided for each property, which should update the static class-wide state. For this purpose, it is possible to manually keep static variables with the current state, and manually fire property change events; but it is more convenient to use the automatically-managed state provided by SharedClassObject:

public Color getForeground () {
  // Retrieves from class-wide state:
  return (Color) getProperty (PROPERTY_FOREGROUND);
public void setForeground (Color fg) {
  // make sure it is sane...
  if (fg == null) throw new NullPointerException ();
  // Stores in class-wide state and fires property changes if needed:
  putProperty (PROPERTY_FOREGROUND, fg, true);
Note that getProperty and putProperty automatically provide sufficient synchronization for the option as well.

Note: when using these methods, your getters and setters will not be called during project save and restore; instead, the actual property value you stored will be serialized and deserialized. This is convenient for some purposes, e.g. you may make a property of declared type ServiceType (and have a pleasant default property editor) while actually storing the correct ServiceType.Handle in the project. However, it can be dangerous in some cases, e.g. if you are associating some sort of runtime service configuration with the property which you need the setter to immediately modify: your setter will not be used at project restore time. To make sure the setter is used, just manually store the property without using putProperty.

Providing more advanced bean info

By default, JavaBeans introspection is used to find the properties associated with a system option, and to read and write them. You may want to have more control over this process. If so, you should create a valid BeanInfo class for the option. The easiest way to do this is of course to create a class named e.g. MyModuleSettingsBeanInfo.

You might want to do this because:

If any property may take one of a set of possible values, then you of course should make public constants representing these values, and provide e.g. a tagged property editor.

Making an option cluster

If ContextSystemOption is used as the superclass, then there will appear in the Control Panel one master option (possibly having some properties, possibly not) with a group of children beneath it. Such an option should be written like a regular one, but each child should also be a valid system option in its own right, and they should be added to the parent (e.g. in the parent's constructor) using ContextSystemOption.addOption(...).

Such a cluster should be used for any system options for which one property list would be unwieldy; or if it makes sense to have multiple and separate customizer components.

Vetoable options

The superclass VetoSystemOption may be used for any option which desired that some or all of its properties be constrained by listeners - i.e. if it might be impossible for a property to be changed in a certain way when in use by a certain other part of the module.

When such a property is set, it should fire its change using VetoSystemOption.fireVetoableChange(...) and be prepared to revoke the change if a veto occurs.

Option installation

Options can be installed via module manifest, but are better installed as settings using the Services API.

Accessing Existing System Options

For the most part, options and their properties are only accessed directly from within the module providing them; in this case, a new instance or a cached default instance of the option is made available to other classes in the module. These other components should attach change listeners to it so that they may be kept in synch with changes made by the user in the Control Panel.

If it necessary to access some other option, you may use:

OtherOption oo = (OtherOption) SystemOption.findObject(OtherOption.class, true);
You may also use this method to obtain the default instance for local use.

UML class diagram

options UML