Reference: Action Annotation
This wiki page provides reference material for the @Action annotation of SAF. The page is broken down by topic. When possible, a list or table of available options for the topic is provided.
- 1 Reference: Action Annotation
- 1.1 Action Key/Name
- 1.1.1 What is it?
- 1.1.2 Where is it used?
- 1.2 Action Blocking Scope
- 1.2.1 Use
- 1.2.2 Custom Input Blocking
- 1.3 Action Enabled and Selected Properties
- 1.4 ResourceMap Properties
- 1.4.1 Notes
- 1.5 Action Method Parameters
- 1.6 Action Method Return Types
Action Key/Name
The terms key and name both represent the topic discussed here. This document will use key since this term cannot be confused with the Action.NAME property.
What is it?
This key of an Action is, by default, the name of the method upon which the @Action annotation is placed. This can be overridden by defining a value for the name parameter in the @Action annotation.
@Action(name="customName")
public void doThisRightHere() {
// actionPerformed code
}
In the above example, an Action will be created with the key "customName". It will call doThisRightHere() when an event is fired to it. If the name="customName" parameter had not been entered in the annotation, the key of the Action would have been "doThisRightHere".
Where is it used?
The key of an Action is used primarily in two ways. First, it is used in the Action's ResourceBundle to define resources for the Action. If the key of the Action is "name", then a resource entry defining an icon for the Action, for example, would be:
name.Action.icon = myIconFileName.png
Secondly, it is used to retrieve the Action from an ActionMap. Once again, if the key of the Action is "name", then the following code would retrieve it from an ApplicationActionMap:
Application.getInstance().getContext().getActionMap(mySwingComponent).get("name");
Action Blocking Scope
The following table lists the blocking scope values that can be used for the block parameter of the @Action annotation.
| Scope Value | Blocking Target | What Happens |
|---|---|---|
| Task.BlockingScope.NONE | Nothing | No input is blocked. |
| Task.BlockingScope.ACTION | The Action | The Action is disabled while the Task runs. |
| Task.BlockingScope.COMPONENT | The source component of the ActionEvent. | The source of the ActionEvent (e.g. the JButton to which the Action is set) is disabled while the Task runs. |
| Task.BlockingScope.WINDOW | The RootPaneContainer ancestor of the component. | The RootPaneContainer (e.g. JFrame, JWindow, JDialog, JInternalFrame, JApplet), in which the source component is a child, is disabled while the Task runs. This is accomplished by setting a glass pane over the Window that consumes all inputs, disabling the Window's menu bar, and displaying a JDialog with a busy message. |
| Task.BlockingScope.APPLICATION | Same behavior as Task.BlockingScope.WINDOW | Same behavior as Task.BlockingScope.WINDOW |
Use
To set the BlockingScope of an Action, use the block parameter of the @Action annotation. The following creates an Action with the Task.BlockingScope.COMPONENT scope:
@Action(block = Task.BlockingScope.COMPONENT)
public Task doMyTask() {
return new MyTask()
}
The BlockScope of an Action is only relevant if the Action method returns an instance of Task, as done in the above example. If the Action method does not return a Task, this parameter is ignored. Also note: input is only blocked during execution of the Task, not during execution of the code in the Action method.
For more information about return types of Action methods, see below.
Custom Input Blocking
The information in the "What Happens" column of the table above describes the behavior of the default input blocker, which is always used when no other InputBlocker is set. If you want to customize the behavior of input blocking, you can create a subclass of Task.InputBlocker, and set the Task's InputBlocker before returning it in the Action method, as in the following example:
@Action(block = Task.BlockingScope.COMPONENT)
public Task doMyTask() {
Task task = new MyTask();
task.setInputBlocker(createCustomInputBlocker(task));
return task
}
In the above case, instead of using an instance of DefaultInputBlocker, the custom InputBlocker will be used.
Action Enabled and Selected Properties
If you bind the enabled or selected state of an Action to a bean property using the enabledProperty and/or selectedProperty parameters of the @Action annotation, the class in which you define the Action method must have the appropriate methods. These include add, remove, and get PropertyChangeListener methods, as well as an is method for the property. The absence of a set method for the property will not cause an error in SAF, but by beans convention, it should exist.
ResourceMap Properties
The following table lists the Action resource properties recognized by SAF, and it also explains to what type of object the text value will be converted. Note that in the following table, "name" is used as a place holder for the key of the Action.
| ResourceBundle Key | Swing Action Keys Affected | Resource Converted To |
|---|---|---|
| name.Action.text | Action.NAME Action.MNEMONIC_KEY Action.DISPLAYED_MNEMONIC_INDEX_KEY | String |
| name.Action.mnemonic | Action.MNEMONIC_KEY | Integer (KeyCode) |
| name.Action.displayedMnemonicIndex | Action.DISPLAYED_MNEMONIC_INDEX_KEY | Integer |
| name.Action.accelerator | Action.ACCELERATOR_KEY | KeyStroke |
| name.Action.icon | Action.SMALL_ICON Action.LARGE_ICON_KEY | Icon |
| name.Action.smallIcon | Action.SMALL_ICON | Icon |
| name.Action.largeIcon | Action.LARGE_ICON_KEY | Icon |
| name.Action.shortDescription | Action.SHORT_DESCRIPTION | String |
| name.Action.longDescription | Action.LONG_DESCRIPTION | String |
| name.Action.command | Action.ACTION_COMMAND_KEY | String |
Notes
- General
- If none of name.Action.text, name.Action.icon, name.Action.smallIcon, and name.Action.largeIcon are defined in the Action's ResourceBundle, the key of the Action will be entered as the value for Action.NAME.
- name.Action.text
- If the resource's value contains an "&" or an "_", it's assumed to mark the following character as the mnemonic. If name.Action.mnemonic and/or name.Action.displayedMnemonic resources are also defined in the ResourceBundle (this should rarely be necessary), they'll override the mnemonic specified with the name.Action.text marker character. At one point in time, there was an idea to allow the character marking the mnemonic to be customized instead of having to use "&" or "_". This idea was never implemented.
- name.Action.icon
- Initializes both the small and large icon with its value. If name.Action.smallIcon and/or name.Action.largeIcon are also defined in the ResourceBundle, these values will override the value of name.Action.icon.
- name.Action.displayedMnemonicIndexKey
- The constant Action.DISPLAYED_MNEMONIC_INDEX has only existed since Java SE 6. If the key is present in the ResourceBundle, its value will be put into the ApplicationAction regardless of the Java version, but it may have no effect on components in versions prior to 6.
- Small vs. Large Icons in Swing
- If you specify only one of the two icon sizes, that icon will be used for both JButton instances and JMenuItem instances. If you specify both, however, the large icon will be used by JButton components, and the small icon will be used in JMenuItem components.
- Long vs. Short Descriptions in Swing
- The long description is not used by any of the standard Swing components. The short description is used as the tool tip text.
Action Method Parameters
The method used to define the Action can have the following types of parameters. The table explains which values will be passed for each type of parameter. Duplicates of the same type of parameter will have the same values. Parameters of classes other than those in the following table will cause an exception to be thrown when an event is fired to the Action.
| Parameter Class | Value Passed |
|---|---|
| ActionEvent.class | The ActionEvent object for the event. |
| Action.class | The ApplicationAction instance being acted upon. |
| ActionMap.class | The ApplicationActionMap that contains the Action. |
| ResourceMap.class | The ResourceMap of the ActionMap, and thus the ResourceMap of the Action |
| ApplicationContext.class | The ApplicationContext holding the ActionMap. |
| Application.class | The Application of the ApplicationContext. |
The following, for example, is therefore a valid method for the @Action annotation:
@Action
public void myAction(ActionEvent e, Action a, ActionMap am, ResourceMap rm,
ApplicationContext c, Application app) {
// actionPerformed code
}
If, for example, a parameter String s were added to the method parameters, an IllegalArgumentException would be thrown whenever the Action was acted upon.
Custom ApplicationActions
Currently there is no easy way of making the @Action annotation create a custom subclass of ApplicationAction. We'll hopefully resolve this issue as soon as possible. When we do, it should be known that the @Action annotation has a nested annotation called @Action.Parameter. It has one parameter, value, and is meant to be used in the following fashion:
@Action
public void myAction(
ActionEvent e,
ApplicationContext c,
@Action.Parameter(value="first")String s1,
@Action.Parameter(value="second")String s2) {
// actionPerformed code
}
Currently, with an ApplicationAction, the above ApplicationAction would throw an exception when acted upon. That is because when it tries to determine what value to pass for String s1 and String s2, it does not recognize the parameter type. The idea behind the @Action.Parameter annotation is that subclasses of ApplicationAction could customize the way parameter values are chosen, and the value of the value parameter of the @Action.Parameter annotation would provide information about what value should be passed to the Action method for that parameter.
Action Method Return Types
It should be known that the method used to define an ApplicationAction can have any return type, including void. For instance, the following is acceptable:
@Action
public Calendar myAction() {
// actionPerformed code
return Calendar.getInstance();
}
When the Action is performed (i.e. when an ActionEvent is fired to it), the code will execute and the Calendar instance will be returned. Nothing is done with the returned Calendar instance. The same is true for instances of all types, with the exception of one...
- Task Return Types
- The only special case that will affect the way the Action is fired is if the return type is an instance of Task. If the method returns a non-null object that is an instance of Task, and the ApplicationAction has no proxy Action, the following will happen...
- The contents of the Action method are run on the Event Dispatch Thread, and a Task instance is returned.
- If the Task has no InputBlocker (i.e. its InputBlock is null), the Action will set its InputBlocker to be the InputBlocker of the Task.
- The TaskService of the ApplicationContext will be called to execute the Task.





