操作基类
BaseAction
是所有操作基类。当 声明式创建操作 不能满足需求时,建议从这个类派生自定义操作。
在创建自定义操作类时,应该实现 actionPerform()
方法并将操作标识符传递给 BaseAction
构造函数。可以重写任何属性的 getter 方法:getCaption()
、getDescription()
、getIcon()
、getShortcut()
、isEnabled()
、isVisible()
、isPrimary()
。除了 getCaption()
方法之外,这些方法的标准实现返回由 setter 方法设置的值。如果操作名称未通过 setCaption()
方法显式设置,则它使用操作标识符作为键值从与操作类包对应的本地化消息包中检索消息。如果没有带有这种键值的消息,则返回键值本身,即操作标识符。
或者,可以使用流式 API 设置属性并提供 lambda 表达式来处理操作:请参阅 with…
开头的方法。
BaseAction
可以根据用户 权限 和当前上下文更改其 enabled
和 visible
属性。
如果满足以下条件,则 BaseAction
是可见的:
-
setVisible(false)
方法没有被调用; -
此操作没有 “hide(隐藏)” UI 权限;
如果满足以下条件,则该操作被启用:
-
setEnabled(false)
方法没有被调用; -
此操作没有 “hide(隐藏)” 或 “read-only(只读)” UI 权限;
-
isPermitted()
方法返回true
。 -
isApplicable()
方法返回true
。 -
所有
EnabledRules
(如果有的话)返回true
。
用例:
Button 操作
@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()));
}
在这个例子中,sayHelloBtn
按钮标题将被设置为位于消息包中 hello
键的字符串。可以重写 getCaption()
操作方法以不同的方式初始化按钮名称。
ValuePicker 操作
以编程方式创建 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);
}
在此示例中,匿名 BaseAction
派生类用于设置值选择器按钮的操作。不显示按钮标题,而是在光标悬停在按钮时弹出的带有描述的图标。
Table 操作
@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;
}
}
在此示例中,声明了 AboutSingleAction
类,操作实例添加到表格的操作列表中。选择表格中的一行时启用该操作。这个行为能有效,是因为 BaseAction 的 target
属性会在操作添加到 ListComponent
的继承者(Table
或者 Tree
)时被自动设置。
使用 ItemTrackingAction
如果需要一个在选择一行或多行时启用的操作,请使用 BaseAction 的子类 - ItemTrackingAction
,它添加了 isApplicable()
方法的默认实现:
@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();
}
});
}