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。

用法示例:

  1. @Inject
  2. private Notifications notifications;
  3. @Inject
  4. private Button helloBtn;
  5. @Subscribe
  6. protected void onInit(InitEvent event) {
  7. helloBtn.setAction(new BaseAction("hello") {
  8. @Override
  9. public boolean isPrimary() {
  10. return true;
  11. }
  12. @Override
  13. public void actionPerform(Component component) {
  14. notifications.create()
  15. .withCaption("Hello!")
  16. .withType(Notifications.NotificationType.TRAY)
  17. .show();
  18. }
  19. });
  20. // OR
  21. helloBtn.setAction(new BaseAction("hello")
  22. .withPrimary(true)
  23. .withHandler(e ->
  24. notifications.create()
  25. .withCaption("Hello!")
  26. .withType(Notifications.NotificationType.TRAY)
  27. .show()));
  28. }

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

  1. @Inject
  2. private UiComponents uiComponents;
  3. @Inject
  4. private Notifications notifications;
  5. @Inject
  6. private MessageBundle messageBundle;
  7. @Inject
  8. private HBoxLayout box;
  9. @Subscribe
  10. protected void onInit(InitEvent event) {
  11. PickerField pickerField = uiComponents.create(PickerField.NAME);
  12. pickerField.addAction(new BaseAction("hello") {
  13. @Override
  14. public String getCaption() {
  15. return null;
  16. }
  17. @Override
  18. public String getDescription() {
  19. return messageBundle.getMessage("helloDescription");
  20. }
  21. @Override
  22. public String getIcon() {
  23. return "icons/hello.png";
  24. }
  25. @Override
  26. public void actionPerform(Component component) {
  27. notifications.create()
  28. .withCaption("Hello!")
  29. .withType(Notifications.NotificationType.TRAY)
  30. .show();
  31. }
  32. });
  33. // OR
  34. pickerField.addAction(new BaseAction("hello")
  35. .withCaption(null)
  36. .withDescription(messageBundle.getMessage("helloDescription"))
  37. .withIcon("icons/ok.png")
  38. .withHandler(e ->
  39. notifications.create()
  40. .withCaption("Hello!")
  41. .withType(Notifications.NotificationType.TRAY)
  42. .show()));
  43. box.add(pickerField);
  44. }

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

  1. @Inject
  2. private Notifications notifications;
  3. @Inject
  4. private Table<Customer> table;
  5. @Inject
  6. private Security security;
  7. @Subscribe
  8. protected void onInit(InitEvent event) {
  9. table.addAction(new HelloAction());
  10. }
  11. private class HelloAction extends BaseAction {
  12. public HelloAction() {
  13. super("hello");
  14. }
  15. @Override
  16. public void actionPerform(Component component) {
  17. notifications.create()
  18. .withCaption("Hello " + table.getSingleSelected())
  19. .withType(Notifications.NotificationType.TRAY)
  20. .show();
  21. }
  22. @Override
  23. protected boolean isPermitted() {
  24. return security.isSpecificPermitted("myapp.allow-greeting");
  25. }
  26. @Override
  27. public boolean isApplicable() {
  28. return table != null && table.getSelected().size() == 1;
  29. }
  30. }

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

  • 如果需要一个在选择一行或多行时启用的操作,请使用 BaseAction 的子类 - ItemTrackingAction,它添加了 isApplicable() 方法的默认实现:
  1. @Inject
  2. private Table table;
  3. @Inject
  4. private Notifications notifications;
  5. @Subscribe
  6. protected void onInit(InitEvent event) {
  7. table.addAction(new ItemTrackingAction("hello") {
  8. @Override
  9. public void actionPerform(Component component) {
  10. notifications.create()
  11. .withCaption("Hello " + table.getSelected().iterator().next())
  12. .withType(Notifications.NotificationType.TRAY)
  13. .show();
  14. }
  15. });
  16. }