# Мастер пользовательского ввода
Мастер пользовательского ввода представляет собой базовый механизм создания или изменения/настройки объектов в системе как для пользователя системы, так и для прикладного разработчика.

Включает в себя:

 - [Интерфейс настройки мастеров и их шагов](#интерфейс-настройки-мастеров);
 - [Интерфейс запущенного мастера](#интерфейс-мастера);
 - [Scala API](#scala-api) - позволяет прикладным разработчикам иметь доступ к параметрам мастера;
 - [Jexl API](#jexl-api) - позволяет получить доступ к параметрам мастера и контексту выборок через jexl-скрипты, закреплённые за каждым шагом, а также управлять переходами между ними.

## Интерфейс настройки мастеров
Открыть список мастеров можно через:

`Настройка системы \ Настройки и сервисы > Мастеры пользовательского ввода`

![](../img/wizard_list.png)

```{note}
При добавлении нового шага нумерация происходит автоматически по порядку, начиная с 10-ти с шагом 10.

Также первый добавленный шаг будет помечен как "Начальный шаг".
```

## Интерфейс мастера
Представляет собой модальное окно, в верхней части которого расположены операции мастера, а в нижней отображается выборка, настроенная на данном шаге. Первым отображается тот шаг, у которого активен признак "Начальный шаг".

![](../img/wizard_main.png)

Операции мастера:

 - "Предыдущий шаг" (зелёная стрелка влево) - осуществляет выполнение [скрипта на переход назад](#cкрипт-на-переход-назад) и переключение на предыдущий шаг;
 - "Следующий шаг" (зелёная стрелка вправо) - осуществляет выполнение [скрипта на переход вперёд](#cкрипт-на-переход-вперёд), вызов операции `afterEdit` у текущего шага и переключение на следующий шаг;
 - "Выход" - Осуществляет выполнение [скрипта на досрочный выход](#cкрипт-на-досрочный-выход-из-шага) и закрытие мастера.

## Scala API
Scala API реализуется через библиотечный класс `Btk_WizardLib` и позволяет получать/устанавливать значения параметров мастера.

```{attention}
`Btk_WizardLib` работает в контексте основной выборки мастера - `Btk_WizardAvi#Card_WizardHeader`.
```
### Получение значений
```
Btk_WizardLib().getParam(name: String): Any
```
Возвращает значение параметра `name`.

### Установка значений
```
Btk_WizardLib().setParam(name: String, value: Any)
```
Устанавливает параметру `name` значение `value`.

### Пример
Запишем в параметры мастера значение поля `sCode` выбранной строки.
```
val svCode = getSelfVar("sCode").asNString

Btk_WizardLib().setParam("sCode", svCode)
```

```{note}
Так же для работы с параметрами существуют методы `getJParams(): JObject` и `setJParams(params: JObject)`.
Они позволяют соответственно получить и установить значение json-а с параметрами мастера целиком.
```

## Jexl API
Jexl API реализует интерфейс [работы со значениями параметров](#работа-с-параметрами) мастера и [данных в контексте выборки](#работа-с-выборкой) через jexl-скрипты, настраиваемые на каждом шаге. Так же этот интерфейс позволяет [управлять переходами между шагами](#переопределение-перехода-между-шагами) мастера.

Доступные для настройки скрипты:

 - [Cкрипт на вход в шаг (before)](#cкрипт-на-вход-в-шаг);
 - [Cкрипт на переход вперёд (forward)](#cкрипт-на-переход-вперёд);
 - [Cкрипт на переход назад (back)](#cкрипт-на-переход-назад);
 - [Cкрипт на досрочный выход из шага (exit)](#cкрипт-на-досрочный-выход-из-шага).

### Работа с параметрами
Через скрипты также можно работать с параметрами мастера - получать их и устанавливать.

```{note}
Работа с параметрами происходит через jexl-контекст ``ctx``. Также скрипт получает значение ``formResult``, которое равняется:
- **`"Ok"`** - при выходе из мастера с сохранением изменений;
- **`"Cancel"`** - при выходе из мастера без сохранения изменений;  
- **`"None"`** - при переходе между шагами мастера.
```

За установку значений отвечает метод `setParam(String, Any)`:
```
ctx.setParam('some_int_param', 1024);
```
За получение значений отвечает метод `getParam(String) -> Any`:
```
ctx.getParam('some_int_param'); // вернёт 1024
```

```{note}
Так же для работы с параметрами существуют методы `getJParams(): JObject` и `setJParams(params: JObject)`.
Их функционал аналогичен одноимённым библиотечным методам. 
```

### Работа с выборкой
Данные скрипты выполняются в контексте выборки шага, поэтому нам доступны такие методы как `setVar`,  `getVar` и т.д.
```{note}
Вызов методов, доступных для работы с данными выборки шага, осуществляется без префикса `ctx`.
```
```{attention}
Обратите внимание, что cкрипт на **вход в шаг** работает ТОЛЬКО В КОНТЕКСТЕ МАСТЕРА! Соответственно, доступа к данным выборки шага у него нет.
```

### Переопределение перехода между шагами
По умолчанию переход между шагами идёт в порядке, определённом значением номера шага - от меньшего к большему.

```{note}
Переопределение шагов происходит через jexl-контекст `ctx`.
```

Установить значение шага на переход вперёд можно методом `setStepForward(String)`:
```
ctx.setStepForward('20');
```

Установить значение шага на переход назад можно методом `setStepBack(String)`:
```
ctx.setStepBack(null);
```

Так же можно получить значения шагов на данном этапе:
```
// значение текущего шага
ctx.getStep();  

// значение предыдущего шага
ctx.getPrevStep();

// значение шага на переход назад
ctx.getStepBack();

// значение шага на переход вперёд
ctx.getStepForward();
```

```{attention}
Методы для работы с шагами для удобства принимают/возвращают строковое значение номера шага.
```

### Cкрипт на вход в шаг
Запускается перед запуском каждого шага. 

```{note}
Если на данном этапе переопределить значение следующего шага на `null`, то стрелка перехода вперёд будет недоступна. Аналогично можно поступить и с шагом назад.
```

### Cкрипт на переход вперёд
Запускается при выполнении операции "Далее". 

```{note}
Если на данном этапе переопределить значение следующего шага на `null`, то будет вызвана логика на досрочный выход из шага.
Так же будет осуществлена попытка вызвать метод `afterEdit()` у детальной выборки. 
```

### Cкрипт на переход назад
Запускается при выполнении операции "Назад".

```{note}
Если на данном этапе переопределить значение шага на переход назад на `null`, то будет вызвана логика на досрочный выход из шага.
```

### Cкрипт на досрочный выход из шага
Запускается на операцию "Выход" и следует перед к закрытием формы.

## Запуск мастера
Чтобы запустить мастер, нажмите операцию **"Запустить мастер"** в интерфейсе настройки мастеров.

Чтобы запустить мастер программно, вызовите метод: `Btk_WizardLib().launch(idpWizard: NLong, firstStepParams: Map[String, Any])`
- `idpWizard`       - идентификатор мастера;
- `firstStepParams` - карта параметров для первого шага мастера.
  Эти параметры будут переданы выборке первого шага мастера при запуске мастера.

```{note}
Вместо `Map[String, Any]` можно также передать `JObject`.
```

## Методы регистрации мастера и его шагов
### Регистрация мастера
```
Btk_WizardApi().register(
                          spCode: NString,
                          spCaption: NString,
                          spModule: NString,
                          spDescription: NString,
                          dpExpireDate: NDate
                        ): ApiRop
```
- `spCode` - уникальный код мастера;
- `spCaption` - наименование;
- `spModule` - код системного модуля;
- `spDescription` - описание (не обязательный атрибут);
- `dpExpireDate` - дата окончания использования (не обязательный атрибут).

Возвращает `Btk_WizardApi#ApiRop`.

```{note}
Вместо кода системного модуля можно также передать его идентификатор.
```

### Регистрация шага мастера
```
Btk_WizardStepApi().register(
                              ropParent: Btk_WizardApi#ApiRop,
                              spCaption: NString,
                              spSelection: NString,
                              spRepresentation: NString,
                              npOrder: NNumber = None.nn,
                              bpStart: NNumber = None.nn,
                              spDescription: NString = None.ns,
                              spScriptBefore: NString = None.ns,
                              spScriptForward: NString = None.ns,
                              spScriptBack: NString = None.ns,
                              spScriptExit: NString = None.ns,
                          ): ApiRop
```
- `ropParent` - роп мастера;
- `spCaption` - наименование;
- `spSelection` - имя выборки;
- `spRepresentation` - имя отображения;
- `npOrder` - порядковый номер \
   Если передано пустое значение, присвоится автоматически;
- `bpStart` - флаг, является ли шаг начальным \
   Если передано пустое значение, для первого шага значение будет 1, для последующих - 0;
- `spDescription` - описание;
- `spScriptBefore` - скрипт на вход в шаг;
- `spScriptForward` - скрипт на переход вперёд;
- `spScriptBack` - скрипт на переход назад;
- `spScriptExit` - скрипт на досрочный выход.

Возвращает `Btk_WizardStepApi#ApiRop`.

```{attention}
Если переданный `npOrder` уже существует для данного `ropParent`, то будет изменена существующая запись, а не создана новая.
```

### Пример регистрации
```
def regWizard(): Unit = {
  // регистрируем мастер
  val rvMaster = Btk_WizardApi().register(
    spCode = "createSomeObject",
    spCaption = "Создание некого объекта",
    spModule = "bs",
    spDescription = None.ns,
    dpExpireDate = None.nd
  )

  // регистрируем шаги
  Btk_WizardStepApi().register(
    ropParent = rvMaster,
    spCaption = "Шаг 1",
    spSelection = "gtk-Btk_UserAvi",
    spRepresentation = "List",
    spScriptExit = "dialogs.showMessage('Досрочный выход из шага 1');"
  )

  // регистрируем шаги
  Btk_WizardStepApi().register(
    ropParent = rvMaster,
    spCaption = "Шаг 2",
    spSelection = "gtk-ru.bitec.app.wf.Wf_DirAvi",
    spRepresentation = "Tree",
    spScriptBefore = "ctx.setStepBack(null);",
    spScriptExit = "dialogs.showMessage('Конец');"
  )
}
```