Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  
  /*
   * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. Use is
   * subject to license terms.
   */ 
  
  package org.jdesktop.application;
  
The javax.swing.Action class used to implement the @Action annotation. This class is typically not instantiated directly, it's created as a side effect of constructing an ApplicationActionMap:
 public class MyActions {
     @Action public void anAction() { }  // an @Action named "anAction"
 }
 ApplicationContext ac = ApplicationContext.getInstance();
 ActionMap actionMap = ac.getActionMap(new MyActions());
 myButton.setAction(actionMap.get("anAction"));
 

When an ApplicationAction is constructed, it initializes all of its properties from the specified ResourceMap. Resource names must match the @Action's name, which is the name of the corresponding method, or the value of the optional @Action name parameter. To initialize the text and shortDescription properties of the action named "anAction" in the previous example, one would define two resources:

 anAction.Action.text = Button/Menu/etc label text for anAction
 anAction.Action.shortDescription = Tooltip text for anAction
 

A complete description of the mapping between resources and Action properties can be found in the ApplicationAction ApplicationAction(org.jdesktop.application.ApplicationActionMap,org.jdesktop.application.ResourceMap,java.lang.String,java.lang.reflect.Method,java.lang.String,java.lang.String,org.jdesktop.application.Task.BlockingScope) documentation.

An ApplicationAction's enabled and selected properties can be delegated to boolean properties of the Actions class, by specifying the corresponding property names. This can be done with the @Action annotation, e.g.:

 public class MyActions {
     @Action(enabledProperty = "anActionEnabled")
     public void anAction() { } 
     public boolean isAnActionEnabled() {
         // will fire PropertyChange when anActionEnabled changes 
         return anActionEnabled;
     }
 }
 
If the MyActions class supports PropertyChange events, then then ApplicationAction will track the state of the specified property ("anActionEnabled" in this case) with a PropertyChangeListener.

ApplicationActions can automatically block the GUI while the actionPerformed method is running, depending on the value of block annotation parameter. For example, if the value of block is Task.BlockingScope.ACTION, then the action will be disabled while the actionPerformed method runs.

An ApplicationAction can have a proxy Action, i.e. another Action that provides the actionPerformed method, the enabled/selected properties, and values for the Action's long and short descriptions. If the proxy property is set, this ApplicationAction tracks all of the aforementioned properties, and the actionPerformed method just calls the proxy's actionPerformed method. If a proxySource is specified, then it becomes the source of the ActionEvent that's passed to the proxy actionPerformed method. Proxy action dispatching is as simple as this:

 public void actionPerformed(ActionEvent actionEvent) {
     javax.swing.Action proxy = getProxy();
     if (proxy != null) {
         actionEvent.setSource(getProxySource());
         proxy.actionPerformed(actionEvent);
     }
     // ....
 }
 

Author(s):
Hans Muller (Hans.Muller@Sun.COM)
See also:
ApplicationContext.getActionMap(java.lang.Object)
ResourceMap
public class ApplicationAction extends AbstractAction {
    private static final Logger logger = Logger.getLogger(ApplicationAction.class.getName());
    private final ApplicationActionMap appAM;
    private final ResourceMap resourceMap;
    private final String actionName;        // see getName()
    private final Method actionMethod;      // The @Action method
    private final String enabledProperty;   // names a bound appAM.getActionsClass() property
    private final Method isEnabledMethod;   // Method object for is/getEnabledProperty
    private final Method setEnabledMethod;  // Method object for setEnabledProperty
    private final String selectedProperty;  // names a bound appAM.getActionsClass() property
    private final Method isSelectedMethod;  // Method object for is/getSelectedProperty
    private final Method setSelectedMethod// Method object for setSelectedProperty
    private final Task.BlockingScope block;
    private javax.swing.Action proxy = null;
    private Object proxySource = null;
    private PropertyChangeListener proxyPCL = null;

    
Construct an ApplicationAction that implements an @Action.

If a ResourceMap is provided, then all of the Action properties are initialized with the values of resources whose key begins with baseName. ResourceMap keys are created by appending an @Action resource name, like "Action.shortDescription" to the @Action's baseName For example, Given an @Action defined like this:

 @Action void actionBaseName() { } 
 

Then the shortDescription resource key would be actionBaseName.Action.shortDescription, as in:

 actionBaseName.Action.shortDescription = Do perform some action
 

The complete set of @Action resources is:

 Action.icon
 Action.text
 Action.shortDescription
 Action.longDescription
 Action.smallIcon
 Action.largeIcon
 Action.command
 Action.accelerator
 Action.mnemonic
 Action.displayedMnemonicIndex
 

A few the resources are handled specially:

  • Action.text
    Used to initialize the Action properties with keys Action.NAME, Action.MNEMONIC_KEY and Action.DISPLAYED_MNEMONIC_INDEX. If the resources's value contains an "&" or an "_" it's assumed to mark the following character as the mnemonic. If Action.mnemonic/Action.displayedMnemonic resources are also defined (an odd case), they'll override the mnemonic specfied with the Action.text marker character.
  • Action.icon
    Used to initialize both ACTION.SMALL_ICON,LARGE_ICON. If Action.smallIcon or Action.largeIcon resources are also defined they'll override the value defined for Action.icon.
  • Action.displayedMnemonicIndexKey
    The corresponding javax.swing.Action constant is only defined in Java SE 6. We'll set the Action property in Java SE 5 too.

Parameters:
appAM the ApplicationActionMap this action is being constructed for.
resourceMap initial Action properties are loaded from this ResourceMap.
baseName the name of the @Action
actionMethod unless a proxy is specified, actionPerformed calls this method.
enabledProperty name of the enabled property.
selectedProperty name of the selected property.
block how much of the GUI to block while this action executes.
See also:
getName()
ApplicationActionMap.getActionsClass()
ApplicationActionMap.getActionsObject()
			     ResourceMap resourceMap,
			     String baseName,
			     Method actionMethod
			     String enabledProperty
			     String selectedProperty,
			     Task.BlockingScope block) {
	if (appAM == null) {
	    throw new IllegalArgumentException("null appAM");
	}
	if (baseName == null) {
	    throw new IllegalArgumentException("null baseName");
	}
	this. = appAM;
	this. = resourceMap;
	this. = baseName;
	this. = actionMethod;
	this. = enabledProperty;
	this. = selectedProperty;
	this. = block;
	/* If enabledProperty is specified, lookup up the is/set methods and
	 * verify that the former exists.
	 */
	if (enabledProperty != null) {
	     = propertySetMethod(enabledPropertyboolean.class);
	     = propertyGetMethod(enabledProperty);
	    if ( == null) {
                throw newNoSuchPropertyException(enabledProperty);
	    }
	}
	else {
	    this. = null;
	    this. = null;
	}
	/* If selectedProperty is specified, lookup up the is/set methods and
	 * verify that the former exists.
	 */
	if (selectedProperty != null) {
	     = propertySetMethod(selectedPropertyboolean.class);
	     = propertyGetMethod(selectedProperty);
	    if ( == null) {
                throw newNoSuchPropertyException(selectedProperty);
	    }
            super.putValue(.);
	}
	else {
	    this. = null;
	    this. = null;
	}
	if (resourceMap != null) {
	    initActionProperties(resourceMapbaseName);
	}
    }
    /* Shorter convenience constructor used to create ProxyActions, 
     * see ApplicationActionMap.addProxyAction().
     */
    ApplicationAction(ApplicationActionMap appAMResourceMap resourceMapString actionName) {
	this(appAMresourceMapactionNamenullnullnull..);
    }
        String actionsClassName = .getActionsClass().getName();
        String msg = String.format("no property named %s in %s"propertyNameactionsClassName);
        return new IllegalArgumentException(msg);
    }

    
The name of the @Action enabledProperty whose value is returned by isEnabled, or null.

Returns:
the name of the enabledProperty or null.
See also:
isEnabled()
	return 
    }
    
    
The name of the @Action selectedProperty whose value is returned by isSelected, or null.

Returns:
the name of the selectedProperty or null.
See also:
isSelected()
        return 
    }


    
Return the proxy for this action or null.

    public javax.swing.Action getProxy() { 
	return ;
    }

    
Set the proxy for this action. If the proxy is non-null then we delegate/track the following:
  • actionPerformed
    Our actionPerformed method calls the delegate's after the ActionEvent source to be the value of getProxySource
  • shortDescription
    If the proxy's shortDescription, i.e. the value for key SHORT_DESCRIPTION is not null, then set this action's shortDescription. Most Swing components use the shortDescription to initialize their tooltip.
  • longDescription
    If the proxy's longDescription, i.e. the value for key LONG_DESCRIPTION is not null, then set this action's longDescription.

    public void setProxy(javax.swing.Action proxy) { 
	javax.swing.Action oldProxy = this.;
	this. = proxy;
	if (oldProxy != null) {
	     = null;
	}
	if (this. != null) {
	     = new ProxyPCL();
	}
	else if (oldProxy != null) {
	    setEnabled(false);
            setSelected(false);
	}
	firePropertyChange("proxy"oldProxythis.);
    }

    
Return the value that becomes the ActionEvent source before the ActionEvent is passed along to the proxy Action.

Returns:
the value of the proxySource property.
See also:
getProxy()
setProxySource(java.lang.Object)
java.util.EventObject.getSource()
    public Object getProxySource() { 
	return 
    }

    
Set the value that becomes the ActionEvent source before the ActionEvent is passed along to the proxy Action.

Parameters:
source the ActionEvent source/
See also:
getProxy()
getProxySource()
java.awt.AWTEvent.setSource(java.lang.Object)
    public void setProxySource(Object source) {
	Object oldValue = this.;
	this. = source;
	firePropertyChange("proxySource"oldValuethis.);
    }
    private void  maybePutDescriptionValue(String keyjavax.swing.Action proxy) {
	Object s = proxy.getValue(key);
	if (s instanceof String) {
	    putValue(key, (String)s);
	}
    }
    private void updateProxyProperties() {
	javax.swing.Action proxy = getProxy();
	if (proxy != null) {
	    setEnabled(proxy.isEnabled());
            Object s = proxy.getValue();
	    setSelected((s instanceof Boolean) && ((Boolean)s).booleanValue());
	}
    }
    /* This PCL is added to the proxy action, i.e. getProxy().  We
     * track the following properties of the proxy action we're bound to:
     * enabled, selected, longDescription, shortDescription.  We only
     * mirror the description properties if they're non-null.
     */
    private class ProxyPCL implements PropertyChangeListener {
	    String propertyName = e.getPropertyName();
	    if ((propertyName == null) || 
                "enabled".equals(propertyName) ||
		"selected".equals(propertyName) ||
	    }
	}
    }    
    /* The corresponding javax.swing.Action constants are only 
     * defined in Mustang (1.6), see 
     * http://download.java.net/jdk6/docs/api/javax/swing/Action.html
     */
    private static final String SELECTED_KEY = "SwingSelectedKey";
    private static final String DISPLAYED_MNEMONIC_INDEX_KEY = "SwingDisplayedMnemonicIndexKey";
    private static final String LARGE_ICON_KEY = "SwingLargeIconKey";
    /* Init all of the javax.swing.Action properties for the @Action
     * named actionName.  
     */
    private void initActionProperties(ResourceMap resourceMapString baseName) {
	boolean iconOrNameSpecified = false;  // true if Action's icon/name properties set
	String typedName = null;
	// Action.text => Action.NAME,MNEMONIC_KEY,DISPLAYED_MNEMONIC_INDEX_KEY
	String text = resourceMap.getString(baseName + ".Action.text");
	if (text != null) {
            MnemonicText.configure(thistext);
	    iconOrNameSpecified = true;
	}
	// Action.mnemonic => Action.MNEMONIC_KEY
	Integer mnemonic = resourceMap.getKeyCode(baseName + ".Action.mnemonic");
	if (mnemonic != null) {
	    putValue(...mnemonic);
	}
	// Action.mnemonic => Action.DISPLAYED_MNEMONIC_INDEX_KEY
	Integer index = resourceMap.getInteger(baseName + ".Action.displayedMnemonicIndex");
	if (index != null) {
	}
	// Action.accelerator => Action.ACCELERATOR_KEY
	KeyStroke key = resourceMap.getKeyStroke(baseName + ".Action.accelerator");
	if (key != null) {
	}
	// Action.icon => Action.SMALL_ICON,LARGE_ICON_KEY
	Icon icon = resourceMap.getIcon(baseName + ".Action.icon");
	if (icon != null) {
	    putValue(icon);
	    iconOrNameSpecified = true;
	}
	// Action.smallIcon => Action.SMALL_ICON
	Icon smallIcon = resourceMap.getIcon(baseName + ".Action.smallIcon");
	if (smallIcon != null) {
	    putValue(...smallIcon);
	    iconOrNameSpecified = true;
	}
	// Action.largeIcon => Action.LARGE_ICON
	Icon largeIcon = resourceMap.getIcon(baseName + ".Action.largeIcon");
	if (largeIcon != null) {
	    putValue(largeIcon);
	    iconOrNameSpecified = true;
	}
	// Action.shortDescription => Action.SHORT_DESCRIPTION
		 resourceMap.getString(baseName + ".Action.shortDescription"));
	// Action.longDescription => Action.LONG_DESCRIPTION
		 resourceMap.getString(baseName + ".Action.longDescription"));
	// Action.command => Action.ACTION_COMMAND_KEY
		 resourceMap.getString(baseName + ".Action.command"));
	// If no visual was defined for this Action, i.e. no text
	// and no icon, then we default Action.NAME
	if (!iconOrNameSpecified) {
	}
    }
    private String propertyMethodName(String prefixString propertyName) {
	return prefix + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
    }
    private Method propertyGetMethod(String propertyName) {
	String[] getMethodNames = {
	    propertyMethodName("is"propertyName),
	    propertyMethodName("get"propertyName)
	};
	Class actionsClass = .getActionsClass();
	for (String name : getMethodNames) {
	    try {
		return actionsClass.getMethod(name);
	    }
	    catch(NoSuchMethodException ignore) { }
	}
	return null;
    }
    private Method propertySetMethod(String propertyNameClass type) {
	Class actionsClass = .getActionsClass();
	try {
	    return actionsClass.getMethod(propertyMethodName("set"propertyName), type);
	}
	catch(NoSuchMethodException ignore) { 
	    return null;
	}
    }

    
The name of this Action. This string begins with the name the corresponding @Action method (unless the name @Action parameter was specified).

This name is used as a prefix to look up action resources, and the ApplicationContext Framework uses it as the key for this Action in ApplicationActionMaps.

Note: this property should not confused with the javax.swing.Action.NAME key. That key is actually used to initialize the text properties of Swing components, which is why we call the corresponding ApplicationAction resource "Action.text", as in:

 
 myCloseButton.Action.text = Close 
 

Returns:
the (read-only) value of the name property
    public String getName() {
	return ;
    }

    
The resourceMap for this Action.

Returns:
the (read-only) value of the resourceMap property
    public ResourceMap getResourceMap() {
        return ;
    }


    
Provides parameter values to @Action methods. By default, parameter values are selected based exclusively on their type:
Parameter TypeParameter Value
ActionEventactionEvent
javax.swing.Actionthis ApplicationAction object
ActionMapthe ActionMap that contains this Action
ResourceMapthe ResourceMap of the the ActionMap that contains this Action
ApplicationContextthe value of ApplicationContext.getInstance()

ApplicationAction subclasses may also select values based on the value of the Action.Parameter annotation, which is passed along as the pKey argument to this method:

 @Action public void doAction(@Action.Parameter("myKey") String myParameter) {
    // The value of myParameter is computed by:
    // getActionArgument(String.class, "myKey", actionEvent)
 }
 

If pType and pKey aren't recognized, this method calls actionFailed(java.awt.event.ActionEvent,java.lang.Exception) with an IllegalArgumentException.

Parameters:
pType parameter type
pKey the value of the @Action.Parameter annotation
actionEvent the ActionEvent that trigged this Action
    protected Object getActionArgument(Class pTypeString pKeyActionEvent actionEvent) {
	Object argument = null;
	if (pType == ActionEvent.class) {
	    argument = actionEvent;
	}
	else if (pType == javax.swing.Action.class) {
	    argument =  this;
	}
	else if (pType == ActionMap.class) {
	    argument = ;
	}
	else if (pType == ResourceMap.class) {
	    argument = ;
	}
	else if (pType == ApplicationContext.class) {
	    argument = .getContext();
	}
	else if (pType == Application.class) {
	    argument = .getContext().getApplication();
	}
	else {
	    Exception e = new IllegalArgumentException("unrecognized @Action method parameter");
	    actionFailed(actionEvente);
	}
	return argument;
    }
    private Task.InputBlocker createInputBlocker(Task taskActionEvent event) {
        Object target = event.getSource();
        if ( == ..) {
            target = this;
        }
        return new DefaultInputBlocker(tasktargetthis);
    }
    private void noProxyActionPerformed(ActionEvent actionEvent) {
	Object taskObject = null;
	/* Create the arguments array for actionMethod by 
	 * calling getActionArgument() for each parameter.
	 */
	Object[] arguments = new Object[pTypes.length];
	for(int i = 0; i < pTypes.lengthi++) {
	    String pKey = null;
	    for(Annotation pAnnotation : allPAnnotations[i]) {
		if (pAnnotation instanceof Action.Parameter) {
		    pKey = ((Action.Parameter)pAnnotation).value();
		    break;
		}
	    }
	    arguments[i] = getActionArgument(pTypes[i], pKeyactionEvent);
	}
	/* Call target.actionMethod(arguments).  If the return value
	 * is a Task, then execute it.
	 */
	try {
	    Object target = .getActionsObject();
	    taskObject = .invoke(targetarguments);
	}
	catch (Exception e) {
	    actionFailed(actionEvente);
	}
	if (taskObject instanceof Task) {
	    Task task = (Task)taskObject;
            if (task.getInputBlocker() == null) {
                task.setInputBlocker(createInputBlocker(taskactionEvent));
            }
	    ctx.getTaskService().execute(task);
	}
    }

    
This method implements this Action's behavior.

If there's a proxy Action then call its actionPerformed method. Otherwise, call the @Action method with parameter values provided by getActionArgument(). If anything goes wrong call actionFailed().

    public void actionPerformed(ActionEvent actionEvent) {
	javax.swing.Action proxy = getProxy();
	if (proxy != null) {
	    actionEvent.setSource(getProxySource());
	    proxy.actionPerformed(actionEvent);
	}
	else if ( != null) {
	    noProxyActionPerformed(actionEvent);    
	}
    }

    
If the proxy action is null and enabledProperty was specified, then return the value of the enabled property's is/get method applied to our ApplicationActionMap's actionsObject. Otherwise return the value of this Action's enabled property.

    @Override  public boolean isEnabled() {
	if ((getProxy() != null) || ( == null)) {
	    return super.isEnabled();
	}
	else {
	    try {
		return (Boolean)b;
	    }
	    catch (Exception e) {
                throw newInvokeError(e);
	    }
	}
    }

    
If the proxy action is null and enabledProperty was specified, then set the value of the enabled property by invoking the corresponding set method on our ApplicationActionMap's actionsObject. Otherwise set the value of this Action's enabled property.

    @Override public void setEnabled(boolean enabled) {
	if ((getProxy() != null) || ( == null)) {
	    super.setEnabled(enabled);
	}
	else {
	    try {
	    }
	    catch (Exception e) {
                throw newInvokeError(eenabled);
	    }
	}
    }

    
If the proxy action is null and selectedProperty was specified, then return the value of the selected property's is/get method applied to our ApplicationActionMap's actionsObject. Otherwise return the value of this Action's enabled property.

Returns:
true if this Action's JToggleButton is selected
See also:
setProxy(javax.swing.Action)
setSelected(boolean)
ApplicationActionMap.getActionsObject()
    public boolean isSelected() {
	if ((getProxy() != null) || ( == null)) {
            Object v = getValue();
            return (v instanceof Boolean) ? ((Boolean)v).booleanValue() : false;
	}
	else {
	    try {
		return (Boolean)b;
	    }
	    catch (Exception e) {
                throw newInvokeError(e);
	    }
	}
    }

    
If the proxy action is null and selectedProperty was specified, then set the value of the selected property by invoking the corresponding set method on our ApplicationActionMap's actionsObject. Otherwise set the value of this Action's selected property.

Parameters:
selected this Action's JToggleButton's value
See also:
setProxy(javax.swing.Action)
isSelected()
ApplicationActionMap.getActionsObject()
    public void setSelected(boolean selected) {
	if ((getProxy() != null) || ( == null)) {
            super.putValue(, Boolean.valueOf(selected));
	}
	else {
	    try {
                super.putValue(, Boolean.valueOf(selected));
                if (selected != isSelected()) {
                    .invoke(.getActionsObject(), selected);
                }
	    }
	    catch (Exception e) {
                throw newInvokeError(eselected);
	    }
	}
    }

    
Keeps the @Action selectedProperty in sync when the value of key is Action.SELECTED_KEY.

Parameters:
key
value
    public void putValue(String keyObject value) {
        if (.equals(key) && (value instanceof Boolean)) {
            setSelected((Boolean)value);
        }
        else {
            super.putValue(keyvalue);
        }
    }
    /* Throw an Error because invoking Method m on the actionsObject,
     * with the specified arguments, failed.
     */
    private Error newInvokeError(Method mException eObject... args) {
        String argsString = (args.length == 0) ? "" : args[0].toString();
        for(int i = 1; i < args.lengthi++) {
            argsString += ", " + args[i];
        }
        String actionsClassName = .getActionsObject().getClass().getName();
        String msg = String.format("%s.%s(%s) failed"actionsClassNamemargsString);
        return new Error(msge);
    }
    /* Forward the @Action class's PropertyChangeEvent e to this
     * Action's PropertyChangeListeners using actionPropertyName instead
     * the original @Action class's property name.  This method is used
     * by ApplicationActionMap#ActionsPCL to forward @Action 
     * enabledProperty and selectedProperty changes.
     */
    void forwardPropertyChangeEvent(PropertyChangeEvent eString actionPropertyName) {
        if ("selected".equals(actionPropertyName) && (e.getNewValue() instanceof Boolean)) {
            putValue(, (Boolean)e.getNewValue());
        }
	firePropertyChange(actionPropertyNamee.getOldValue(), e.getNewValue());
    }
    /* Log enough output for a developer to figure out 
     * what went wrong.
     */
    private void actionFailed(ActionEvent actionEventException e) {
	// TBD Log an error
	// e.printStackTrace();
	throw new Error(e);
    }

    
Returns a string representation of this ApplicationAction that should be useful for debugging. If the action is enabled it's name is enclosed by parentheses; if it's selected then a "+" appears after the name. If the action will appear with a text label, then that's included too. If the action has a proxy, then we append the string for the proxy action.

Returns:
A string representation of this ApplicationAction
    public String toString() {
        StringBuilder sb = new StringBuilder();
	sb.append(" ");
	boolean enabled = isEnabled();
	if (!enabled) { sb.append("(");	}
	Object selectedValue = getValue();
	if (selectedValue instanceof Boolean) {
	    if (((Boolean)selectedValue).booleanValue()) {
		sb.append("+");
	    }
	}
	if (!enabled) { sb.append(")");	}
	Object nameValue = getValue(...); // [getName()].Action.text
	if (nameValue instanceof String) {
	    sb.append(" \"");
	    sb.append((String)nameValue);
	    sb.append("\"");
	}
	if ( != null) {
	    sb.append(" Proxy for: ");
	    sb.append(.toString());
	}
	return sb.toString();
    }
New to GrepCode? Check out our FAQ X