Диалоги

Интерфейс Dialogs разработан для отображения стандартных диалоговых окон. Диалоговое окно - это небольшое всплывающее окно, которое можно использовать для представления информации и элементов пользовательского интерфейса.

Методы createMessageDialog(), createOptionDialog() и createInputDialog() - это точки входа в fluent API, который позволяет создавать и отображать диалоговые окна.

Диалог сообщения

Диалога сообщения отображает сообщение пользователю.

message dialog

В следующем примере диалог сообщения отображается при нажатии кнопки пользователем:

@Autowired
private Dialogs dialogs;

@Subscribe("messageDialogButton")
public void onHelloButtonClick(ClickEvent<Button> event) {
    dialogs.createMessageDialog()
            .withHeader("Success") (1)
            .withText("Invitation sent successfully") (2)
            .open();
}
1 Добавляет заголовок диалога.
2 Добавляет текстовое сообщение для отображения в диалоге.

Форматирование текста

Форматирование текста доступно с использованием HTML - диалог может отображать HTML-контент с помощью метода withContent(). HTML-фрагмент должен быть инкапсулирован в компоненте:

@Autowired
private Dialogs dialogs;

Html htmlContent = new Html("<p>Here starts a paragraph. A new line starts after this.<br />" +
        "<b>This text is bold.</b> <i>This text is italic.</i></p>");

@Subscribe("htmlContentButton")
public void onHtmlContentButtonClick(ClickEvent<Button> event) {
    dialogs.createMessageDialog()
            .withHeader("HTML Formatting")
            .withContent(htmlContent)
            .open();
}

Внешний вид

Следующие методы позволяют настраивать внешний вид и поведение диалога сообщения:

  • withModal() - если передано значение false, диалоговое окно отображается как немодальное, что позволяет пользователям взаимодействовать с другими частями приложения. По умолчанию диалоги модальные.

  • withCloseOnOutsideClick() - если диалог модальный и передано значение true, то пользователь может закрыть диалог, кликнув в окне приложения за пределами диалога.

  • withWidth(), withHeight() - устанавливают размер диалога.

Например:

@Autowired
private Dialogs dialogs;

@Subscribe("customDialogButton")
public void onSanitizeButtonClick(ClickEvent<Button> event) {
    dialogs.createMessageDialog()
            .withHeader("Information")
            .withText("This is a custom dialog")
            .withCloseOnOutsideClick(true)
            .withWidth("600px")
            .withHeight("200px")
            .open();
}

Диалог с вариантами

Диалог с вариантами отображает сообщение и набор кнопок для выбора пользователем.

option dialog

Используйте метод withActions() для предоставления действий, каждое из которых представлено кнопкой в диалоге. Например:

@Autowired
private Dialogs dialogs;

@Subscribe("selectOptionButton")
public void onSelectOptionButtonClick(ClickEvent<Button> event) {
    dialogs.createOptionDialog()
            .withHeader("Please confirm")
            .withText("Do you really want to add a customer?")
            .withActions(
                    new DialogAction(DialogAction.Type.YES)
                            .withHandler(e -> addCustomer()), (1)
                    new DialogAction(DialogAction.Type.NO)
            )
            .open();
}
1 Если пользователь нажмет "Yes", диалог закроется и вызовется метод addCustomer().

Базовый класс DialogAction предназначен для создания действий со стандартными именами и значками. Поддерживаются пять типов действий, определенных перечислением DialogAction.Type: OK, CANCEL, YES, NO, CLOSE. Названия кнопок извлекаются из пакета сообщений.

Диалог фоновой задачи

Диалог фоновой задачи обеспечивает удобный для пользователя опыт для длительных задач, где пользователь может отслеживать прогресс и отменять операцию при необходимости.

Для получения дополнительной информации о механизме фоновых задач, посетите статью Фоновые Задачи.
backgroundtask dialog

Чтобы настроить диалог, передайте в него объект фоновой задачи:

@Autowired
private Dialogs dialogs;

@Subscribe(id = "backgroundTaskButton", subject = "singleClickListener")
public void onBackgroundTaskClick(final ClickEvent<JmixButton> event) {
    dialogs.createBackgroundTaskDialog(new SampleTask(15, this, 10)) (1)
            .withHeader("Background task running")
            .withText("Please wait until the task is complete")
            .withTotal(10) (2)
            .withCancelAllowed(true) (3)
            .open();
}

protected class SampleTask extends BackgroundTask<Integer, Void> {
    int count;
    public SampleTask(long timeoutSeconds, View<?> view, int count) {
        super(timeoutSeconds, view);
        this.count = count;
    }

    @Override
    public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
        for (int i = 1; i < count + 1; i++) {
            Thread.sleep(1000);
            taskLifeCycle.publish(i);
        }
        return null;
    }
}
1 Передайте объект фоновой задачи в диалог.
2 Установите количество секций в индикаторе прогресса в соответствии с количеством задач.
3 Разрешить пользователю прерывать задачу.

Диалог ввода

Диалог ввода - универсальный инструмент, который позволяет создавать формы ввода с использованием API и часто позволяет избежать создания экранов для ввода тривиальных данных. Он позволяет вводить значения разных типов, выполнять проверку ввода и предоставлять различные действия, доступные для выбора пользователем.

input dialog

Рассмотрим некоторые примеры.

Стандартные параметры

Используйте метод withParameters() для добавления параметров, каждый из которых будет представлен полем ввода в диалоге. Следующий пример создает диалоговое окно ввода с параметрами стандартных типов и стандартными действиями OK/Cancel:

@Autowired
private Dialogs dialogs;

@Subscribe("standardParametersButton")
public void onStandardParametersButtonClick(ClickEvent<Button> event) {
    dialogs.createInputDialog(this)
            .withHeader("Enter values")
            .withParameters(
                    stringParameter("name").withLabel("Name").withRequired(true), (1)
                    intParameter("amount").withLabel("Amount").withDefaultValue(1), (2)
                    entityParameter("user", User.class).withLabel("User"), (3)
                    enumParameter("status", OnboardingStatus.class).withLabel("Status") (4)
            )
            .withActions(DialogActions.OK_CANCEL) (5)
            .withCloseListener(closeEvent -> {
                if (closeEvent.closedWith(DialogOutcome.OK)) { (6)
                    String name = closeEvent.getValue("name"); (7)
                    int amount = closeEvent.getValue("amount");
                    User user = closeEvent.getValue("user");
                    OnboardingStatus status = closeEvent.getValue("status");
                    // process entered values...
                }
            })
            .open();

}
1 Указывает обязательный строковый параметр.
2 Указывает целочисленный параметр с значением по умолчанию.
3 Указывает параметр-сущность.
4 Указывает параметр-перечисление.
5 Указывает стандартные действия OK/Cancel, представленные кнопками внизу диалога.
6 В обработчике закрытия можно проверить, какое действие выбрал пользователь.
7 Событие закрытия содержит введенные значения, которые можно получить с использованием идентификаторов параметров.

Пользовательские параметры

Следующий пример иллюстрирует создание пользовательского параметра, который позволяет пользователю выбрать значение из выпадающего списка:

@Autowired
private Dialogs dialogs;

@Autowired
private DataManager dataManager;
@Autowired
private UiComponents uiComponents;

@Subscribe("customParameterButton")
public void onCustomParameterButtonClick(ClickEvent<Button> event) {
    dialogs.createInputDialog(this)
            .withHeader("Enter values")
            .withParameters(
                    stringParameter("name").withLabel("Name").withRequired(true),
                    intParameter("amount").withLabel("Amount").withDefaultValue(1),
                    parameter("user") (1)
                            .withLabel("User")
                            .withField(() -> {
                                EntityComboBox<User> field = uiComponents.create(EntityComboBox.class); (2)
                                field.setItems(dataManager.load(User.class).all().list()); (3)
                                field.setWidthFull();
                                return field;
                            }),
                    enumParameter("status", OnboardingStatus.class).withLabel("Status")
            )
            .withActions(DialogActions.OK_CANCEL).withCloseListener(closeEvent -> {
                if (closeEvent.closedWith(DialogOutcome.OK)) {
                    String name = closeEvent.getValue("name");
                    int amount = closeEvent.getValue("amount");
                    User user = closeEvent.getValue("user");
                    OnboardingStatus status = closeEvent.getValue("status");
                    // process entered values...
                }
            })
            .open();
}
1 Указывает пользовательский параметр.
2 Создает выпадающий список внутри поля пользовательского параметра.
3 Загружает список вариантов в выпадающий список.

Пользовательский валидатор

Диалог ввода поддерживает базовую проверку: он может проверять тип введенных значений и что обязательное поле не пусто. Кроме того, вы можете добавить более общие пользовательские валидаторы.

Следующий пример добавляет валидатор, проверяющий, что хотя бы один параметр введен:

@Autowired
private Dialogs dialogs;

@Subscribe("validationButton")
public void onValidationButtonClick(ClickEvent<Button> event) {
    dialogs.createInputDialog(this)
            .withHeader("Enter at least one value")
            .withParameters(
                    stringParameter("name").withLabel("Name").withRequired(true),
                    entityParameter("User", User.class).withLabel("User")
            )
            .withValidator(context -> { (1)
                String name = context.getValue("name"); (2)
                User user = context.getValue("user");
                if (Strings.isNullOrEmpty(name) && user == null) {
                    return ValidationErrors.of("Enter name or select a customer"); (3)
                }
                return ValidationErrors.none();
            })
            .withActions(DialogActions.OK_CANCEL)
            .withCloseListener(closeEvent -> {
                if (closeEvent.closedWith(DialogOutcome.OK)) {
                    String name = closeEvent.getValue("name");
                    User user = closeEvent.getValue("user");
                    // process entered values...
                }
            })
            .open();
}
1 Пользовательский валидатор, добавляющий логику для обеспечения ввода хотя бы одного параметра.
2 В валидаторе можно получить значения параметров из объекта контекста.
3 Валидатор возвращает ошибки валидации, если параметры не введены.