3.5.4.3. 基础操作

BaseAction 是所有操作实现的基类。当声明式创建操作不能满足需求时,建议从这个类派生自定义操作。

在创建自定义操作类时,应该实现 actionPerform() 方法并将操作标识符传递给 BaseAction 构造函数。可以重写任何属性的 getter 方法: getCaption()getDescription()getIcon()getShortcut()isEnabled()isVisible()isPrimary()。除了 getCaption() 方法之外,这些方法的标准实现返回由 setter 方法设置的值。如果操作名称未通过 setCaption() 方法显式设置,则它使用操作标识符作为键从与操作类包对应的本地化消息包中检索消息。如果没有带有这种键的消息,则返回键本身,即操作标识符。

或者,可以使用流式 API 设置属性并提供 lambda 表达式来处理操作:请参阅 withXYZ() 方法。

BaseAction 可以根据用户权限和当前上下文更改其 enabledvisible 属性。

如果满足以下条件,则 BaseAction 是可见的:

  • setVisible(false) 方法没有被调用;

  • 此操作没有 hide UI 权限;

如果满足以下条件,则该操作被启用:

  • setEnabled(false) 方法没有被调用;

  • 此操作没有 hide 或只读 UI 权限;

  • isPermitted() 方法返回 true。

  • isApplicable() 方法返回 true。

用法示例:

  • Button 操作:

    @Inject
    private Notifications notifications;
    @Inject
    private Button helloBtn;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        helloBtn.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();
            }
        });
        // OR
        helloBtn.setAction(new BaseAction("hello")
                .withPrimary(true)
                .withHandler(e ->
                        notifications.create()
                                .withCaption("Hello!")
                                .withType(Notifications.NotificationType.TRAY)
                                .show()));
    }

    在这个例子中,helloBtn 按钮标题将被设置为位于消息包中的带有 hello 键的字符串。可以重写 getCaption() 操作方法以不同的方式初始化按钮名称。

  • 以编程方式创建PickerField的操作:

    @Inject
    private UiComponents uiComponents;
    @Inject
    private Notifications notifications;
    @Inject
    private MessageBundle messageBundle;
    @Inject
    private HBoxLayout box;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        PickerField pickerField = uiComponents.create(PickerField.NAME);
    
        pickerField.addAction(new BaseAction("hello") {
            @Override
            public String getCaption() {
                return null;
            }
    
            @Override
            public String getDescription() {
                return messageBundle.getMessage("helloDescription");
            }
    
            @Override
            public String getIcon() {
                return "icons/hello.png";
            }
    
            @Override
            public void actionPerform(Component component) {
                notifications.create()
                        .withCaption("Hello!")
                        .withType(Notifications.NotificationType.TRAY)
                        .show();
            }
        });
        // OR
        pickerField.addAction(new BaseAction("hello")
                .withCaption(null)
                .withDescription(messageBundle.getMessage("helloDescription"))
                .withIcon("icons/ok.png")
                .withHandler(e ->
                        notifications.create()
                                .withCaption("Hello!")
                                .withType(Notifications.NotificationType.TRAY)
                                .show()));
        box.add(pickerField);
    }

    在此示例中,匿名 BaseAction 派生类用于设置选择器字段按钮的操作。不显示按钮标题,而是在光标悬停在按钮时弹出的带有描述的图标。

  • Table操作:

    @Inject
    private Notifications notifications;
    @Inject
    private Table<Customer> table;
    @Inject
    private Security security;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        table.addAction(new HelloAction());
    }
    
    private class HelloAction extends BaseAction {
    
        public HelloAction() {
            super("hello");
        }
    
        @Override
        public void actionPerform(Component component) {
            notifications.create()
                    .withCaption("Hello " + table.getSingleSelected())
                    .withType(Notifications.NotificationType.TRAY)
                    .show();
        }
    
        @Override
        protected boolean isPermitted() {
            return security.isSpecificPermitted("myapp.allow-greeting");
        }
    
        @Override
        public boolean isApplicable() {
            return table != null && table.getSelected().size() == 1;
        }
    }

    在此示例中,声明了 HelloAction 类,它的实例被添加到表格的操作列表中。对具有 myapp.allow-greeting 安全权限的用户启用该操作且仅在只选择了表格中的一行时启用。后面这个选中一行启用能有效,是因为 BaseAction 的 target 属性会在操作添加到 ListComponent 的继承者(Table 或者 Tree)时被自动设置。

  • 如果需要一个在选择一行或多行时启用的操作,请使用 BaseAction 的子类 - ItemTrackingAction,它添加了 isApplicable() 方法的默认实现:

    @Inject
    private Table table;
    @Inject
    private Notifications notifications;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        table.addAction(new ItemTrackingAction("hello") {
            @Override
            public void actionPerform(Component component) {
                notifications.create()
                        .withCaption("Hello " + table.getSelected().iterator().next())
                        .withType(Notifications.NotificationType.TRAY)
                        .show();
            }
        });
    }