Geertjan's Blog

  • September 27, 2010

Enabling an Action on Object State

Geertjan Wielenga
Product Manager
Let's say you need a (1) menu item in the right-click popup menu of a node and a (2) toolbar button in the main toolbar to be enabled/disabled based on the current state of an object.

Below is a case in point. We have a vehicle console that has an "Install Vehicle" action. That action applies to the underlying "Vehicle" object, which is wrapped in a BeanNode, "VehicleNode". The "Vehicle" object has two booleans, among other things. The booleans, "standby" and "available", need to both be true, otherwise the "Install Vehicle" action should not be available to the end user.

That's a sensible scenario. You only want to let the user install a vehicle if the vehicle is actually available and it is on standby, whatever those two terms mean (i.e., "physically available", plus "ready to roll", maybe). So, below, you can see in the Properties window that the ship is available and on standby, hence the "Install Vehicle" action is enabled and the "Install Vehicle" toolbar button is enabled.

In this case, however, the vehicle is available, but not on standby, hence it cannot be installed:

As a small variation on the above, here the menu item in the popup is not simply disabled, but completely removed:

How to achieve the above? Here:

public class InstallVehicleAction extends AbstractAction
implements ContextAwareAction, LookupListener, Presenter.Toolbar {
private Lookup.Result result;
private JButton toolbarBtn;
public InstallVehicleAction() {
public InstallVehicleAction(Lookup context) {
super("Install Vehicle...",
new ImageIcon(ImageUtilities.loadImage("/org/vehicle/actions/Orange Ball.png")));
//Get the Vehicle from the Lookup:
result = context.lookupResult(Vehicle.class);
resultChanged(new LookupEvent(result));
//Use this to completely remove the menu when disabled:
// putValue(DynamicMenuContent.HIDE_WHEN_DISABLED, true);
public void actionPerformed(ActionEvent e) {
if (null != result && 0 < result.allInstances().size()) {
Vehicle v = result.allInstances().iterator().next();
if (null != v) {
//Do something to install the vehicle...
new NotifyDescriptor.Message("Installed: " + v.getVehicleName()));
public Action createContextAwareInstance(Lookup context) {
return new InstallVehicleAction(context);
//This comes from the Toolbar.Presenter, which we need
//to access the toolbar button so that we can enable/disable it,
//note that below it is disabled by default,
//enabled only in the ResultChanged:
public Component getToolbarPresenter() {
if (null == toolbarBtn) {
toolbarBtn = new JButton(this);
return toolbarBtn;
public void resultChanged(LookupEvent arg0) {
//Enable the action and the button
//based on current availability & standby:
if (result.allInstances().size() > 0) {
Vehicle v = result.allInstances().iterator().next();
setEnabled(v.isAvailable() && v.isStandby());
if (null != toolbarBtn) {
toolbarBtn.setEnabled(v.isAvailable() && v.isStandby());
//Activate the VehicleView window, to make it the current window,
//so that a change in the Properties window causes an immediate
//update of the menu item and toolbar button:
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
public void run() {
TopComponent tc = WindowManager.getDefault().findTopComponent("VehicleView");

Complete code sample: http://blogs.sun.com/geertjan/resource/VehicleConsole.zip

Join the discussion

Comments ( 2 )
  • Sizzle Tuesday, January 25, 2011

    The link for the complete code sample resulted in a 404. Friendly FYI :)

  • Geertjan Wielenga Tuesday, January 25, 2011

    Yeah, had to remove some downloads, space for uploads is full in my blog. Drop me an e-mail at geertjan . wielenga @ oracle . com if you need something referenced here.

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