3.5.4.3. BaseAction
BaseAction
- базовый класс реализации действий. От него рекомендуется наследовать собственные нестандартные действия, если возможностей декларативного создания действий не хватает.
При создании конкретного класса действия необходимо определить метод actionPerform()
и передать в конструктор BaseAction
идентификатор действия. Можно также переопределить любые методы получения свойств действия: getCaption()
, getDescription()
, getIcon()
, getShortcut()
, isEnabled()
, isVisible()
, isPrimary()
. Стандартные реализации этих методов возвращают значения, установленные соответствующими set-методами. Исключение составляет метод getCaption()
: если название действия явно не установлено методом setCaption()
, то он обращается в пакет локализованных сообщений с именем, соответствующим пакету класса действия, и возвращает сообщение с ключом, равным идентификатору действия. Если сообщения с таким ключом нет, то возвращается сам ключ, то есть идентификатор действия.
В качестве альтернативы переопределению методов можно использовать fluent interface для установки свойств и lambda expression для предоставления кода обработки действия: см. методы withXYZ()
.
BaseAction
может изменять свои свойства enabled
и visible
в соответствии с разрешениями пользователя и текущим контекстом.
BaseAction
видим (visible), если:
-
метод
setVisible(false)
не вызывался; -
для действия не установлено UI разрешение
hide
.
Действие разрешено (enabled), если:
-
метод
setEnabled(false)
не вызывался; -
для действия не установлено UI разрешений
hide
илиread-only
; -
метод
isPermitted()
возвращает true; -
метод
isApplicable()
возвращает true.
Примеры использования:
-
Действие кнопки:
@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
используется для задания действия кнопки поля выбора. Заголовок кнопки не отображается, вместо него используется значок и описание, всплывающее при наведении курсора мыши. -
Действие таблицы:
@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
, и только когда выбрана одна строка таблицы. Последнее условие реализуется с помощью свойства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(); } }); }