BaseAction

BaseAction is a base class for action implementation. It is recommended to derive custom actions from it when declarative action creation functionality is insufficient.

When creating a custom action class, you should implement the actionPerform() method and pass the action identifier to the BaseAction constructor. You can override any property getters: getCaption(), getDescription(), getIcon(), getShortcut(), isEnabled(), isVisible(), isPrimary(). Standard implementations of these methods return values set by setter methods, except the getCaption() method. If the action name is not explicitly set by setCaption() method, it retrieves a message using action identifier as key from the localized message pack corresponding to the action class package. If there is no message with such key, then the key itself, that is, the action identifier is returned.

Alternatively, you can use the fluent API for setting properties and providing a lambda expression for handling the action: see withXYZ() methods.

BaseAction can change its enabled and visible properties depending on user permissions and current context.

BaseAction is visible if the following conditions are met:

  • setVisible(false) method was not called;

  • there is no "hide" UI permission for this action.

The action is enabled if the following conditions are met:

  • setEnabled(false) method was not called;

  • there are no "hide" or "read-only" UI permissions for this action;

  • isPermitted() method returns true;

  • isApplicable() method returns true;

  • all EnabledRules (if any) return true.

Usage examples:

Button action

@Autowired
private Notifications notifications;
@Autowired
private Button sayHelloBtn;
@Autowired
private Button sayGoodbyeBtn;

@Subscribe
public void onInit(InitEvent event) {
    sayHelloBtn.setAction(new BaseAction("hello") {
        @Override
        public boolean isPrimary() {
            return true;
        }

        @Override
        public void actionPerform(Component component) {
            notifications.create()
                    .withCaption("Hello!")
                    .withType(Notifications.NotificationType.TRAY)
                    .show();
        }
    });

    sayGoodbyeBtn.setAction(new BaseAction("goodbye")
            .withPrimary(true)
            .withHandler(e ->
                    notifications.create()
                            .withCaption("Goodbye!")
                            .withType(Notifications.NotificationType.TRAY)
                            .show()));
}

In this example, the sayHelloBtn button caption will be set to the string located in the message pack with the hello key. You can override the getCaption() action method to initialize the button name differently.

ValuePicker action

Action of a programmatically created ValuePicker:

@Autowired
protected Notifications notifications;
@Autowired
private UiComponents uiComponents;
@Autowired
private MessageBundle messageBundle;
@Autowired
private VBoxLayout vBox;
@Subscribe
protected void onInit(InitEvent event) {
    ValuePicker valueField = uiComponents.create(ValuePicker.NAME);

    valueField.addAction(new BaseAction("hello") {
        @Override
        public String getCaption() {
            return null;
        }

        @Override
        public String getDescription() {
            return messageBundle.getMessage("helloDescription");
        }

        @Override
        public String getIcon() {
            return JmixIcon.HANDSHAKE_O.source();
        }

        @Override
        public void actionPerform(Component component) {
            notifications.create()
                    .withCaption("Hello!")
                    .withType(Notifications.NotificationType.TRAY)
                    .show();
        }
    });
    valueField.addAction(new BaseAction("goodbye")
            .withCaption(null)
            .withDescription(messageBundle.getMessage("goodbyeDescription"))
            .withIcon(JmixIcon.HAND_PAPER_O.source())
            .withHandler(e ->
                    notifications.create()
                            .withCaption("Goodbye!")
                            .withType(Notifications.NotificationType.TRAY)
                            .show()));
    vBox.add(valueField);
}

In this example, an anonymous BaseAction derived class is used to set the actions of the value picker buttons. The button’s caption is not displayed, as an icon with a description, which pops up when hovering mouse cursor, is used instead.

Table action

@Autowired
private Table<Customer> customersTable;
@Autowired
private Notifications notifications;

@Subscribe
public void onInit(InitEvent event) {
    customersTable.addAction(new AboutSingleAction());
}

private class AboutSingleAction extends BaseAction {

    public AboutSingleAction() {
        super("aboutSingle");
    }

    @Nullable
    @Override
    public String getCaption() {
        return "About Single";
    }

    @Override
    public void actionPerform(Component component) {
        notifications.create()
                .withCaption("Hello " + customersTable.getSingleSelected())
                .withType(Notifications.NotificationType.TRAY)
                .show();
    }

    @Override
    public boolean isApplicable() {
        return customersTable != null && customersTable.getSelected().size() == 1;
    }
}

In this example, the AboutSingleAction class is declared, and its instance is added to the table’s actions list. The action is enabled when a single table row is selected. The latter is possible because BaseAction’s target property is automatically assigned to the action when it is added to a ListComponent descendant (Table or Tree).

Using ItemTrackingAction

If you need an action, which becomes enabled when one or more table rows are selected, use BaseAction’s descendant - ItemTrackingAction, which adds default implementation of isApplicable() method:

@Autowired
private Table<Customer> customersTable;
@Autowired
private Notifications notifications;

@Subscribe
public void onInit(InitEvent event) {
    customersTable.addAction(new ItemTrackingAction("about") {
        @Nullable
        @Override
        public String getCaption() {
            return "About";
        }

        @Override
        public void actionPerform(Component component) {
            notifications.create()
                    .withCaption("Hello " + customersTable.getSelected().iterator().next())
                    .withType(Notifications.NotificationType.TRAY)
                    .show();
        }
    });
}