События формы
Во время работы приложения для каждой формы существует набор событий, которые возникают в результате определенных действий пользователя:
Глобальные
QUERYCLOSE
- пользователь пытается закрыть форму, нажав на соответствующую кнопку в заголовке формы.QUERYOK
- пользователь пытается закрыть модальную форму двойным нажатием по какой-либо строке в таблице.SCHEDULE
- планировщик, выполняющий какое-либо действие на форме.
Для объектов на форме
CHANGE
- пользователь изменил текущее значение объекта.
Для свойств или действий на форме
CHANGE
- пользователь инициировал изменение свойства или вызов действия.CHANGEWYS
- пользователь инициировал WYSIWYG изменение свойства при помощи операции PASTE или специального механизма вводаGROUPCHANGE
- пользователь инициировал изменение свойства для всех объектов в таблицеEDIT
- пользователь инициировал редактирование объектаCONTEXTMENU
- пользователь выбрал в контекстном меню свойства (действия) на форме заданный пункт
Также есть несколько так называемых производных событий, которые являются не более чем синтаксическим сахаром, но при этом позволяют эффективнее решать типовые задачи, возникающие при работе с формами:
Глобальные
INIT
- возникает непосредственно сразу после открытия формы.APPLY
- возникает в момент сохранения сессии формы в базу данных (внутри транзакции, в самом ее начале, до выполнения обработок глобальных событий).APPLY BEFORE
- возникает сразу перед сохранением сессии формы в базу данных (до старта транзакции).APPLY AFTER
- возникает сразу после успешного сохранения сессии формы в базу данных (после окончания транзакции).CANCEL
- возникает в момент отмены изменений сессии формы.CLOSE
- возникает в момент выполнения действияSystem.formClose
.DROP
- возникает в момент выполнения действияSystem.formDrop
.
Если форма является собственником сессии (а значит при выполнении действия System.formOk
сессия формы сохраняется):
OK
,OK BEFORE
,OK AFTER
- возникает при выполнении действияSystem.formOk
, в моменты аналогичные соответствующим моментам для событияAPPLY
(то есть внутри, до и после транзакции) . При этом обработкиOK
иOK BEFORE
выполняются до выполнения обработокAPPLY
иAPPLY BEFORE
, аOK AFTER
- послеAPPLY AFTER
.
Если форма не является собственником сессии:
OK
- возникает при выполнения действияSystem.formOk
Если обработки OK BEFORE
и OK AFTER
заданы, но форма не является собственником сессии - эти обработки все равно выполняются, соответственно, до и после обработки события OK
.
Если по окончанию выполнения обработок события с постфиксом BEFORE
значение свойства System.applyCanceled
равняется TRUE
, дальнейшее выполнение действия, которое привело к возникновению этого события, останавливается (к примеру, для APPLY BEFORE
сохранение сессии прерывается, как если бы нарушилось одно из существующих в системе ограничений).
В оставшейся части раздела поведение свойств и действий абсолютно одинаково, поэтому дальше будем использовать только термин свойство (для действий поведение абсолютно идентично).
Разработчик может подключить выполнение одного или нескольких действий (обработок) при возникновении любого описанного выше события. В текущей реализации, обработок глобальных событий и событий объектов на форме может быть несколько (то есть при задании, обработки добавляются в соответствующий список), а обработка событий свойств может быть только одна (то есть при задании, обработка замещает предыдущую).
Для свойств существует возможность задать обработки их событий сразу для для всей логики. Тогда эти обработки автоматически будут подключены для всех форм, где эти свойства будут отображаться.
Также для каждого свойства можно задать комбинацию клавиш на клавиатуре, при нажатии которых будет инициировано событие CHANGE
этого свойства. Если на форме одной комбинации клавиш соответствует несколько свойств, то событие будет инициировано только для свойства, компонент которого будет ближайшим к текущему активному компоненту в иерархии компонент.
Обработки по умолчанию
Для некоторых событий платформа автоматически создает обработки по умолчанию:
-
QUERYCLOSE
Вызывает действие
System.formClose
-
QUERYOK
Вызывает действие
System.formOk
-
CHANGE
У пользователя запрашивается объект класса значения редактируемого свойства, после чего в это свойство записывается полученный объект. Если свойство не изменяемое, будет автоматическ и вызван механизм фильтрации по данному свойству (или по заданному при помощи соответствующей опции свойству).
-
GROUPCHANGE
Вызывает обработку события
CHANGE
для всех объектов, которые удовлетворяют условия фильтров группы объектов, в которой отображается редактируемое свойство.
Если в обработках событий свойств используется (в том числе неявно) оператор запроса значения, то обработки по умолчанию могут создаваться по другому.
Для запроса объекта у пользователя в создаваемых обработках в зависимости от типа класса используются следующие операторы:
- Встроенные классы - оператор ввода примитива.
- Пользовательские классы - оператор открытия формы выбора этого класса.
Стандартные обработки
Для свойств и действий на форме также есть возможность задать следующие стандартные обработки событий изменений (CHANGE
, CHANGEWYS
, GROUPCHANGE
, EDIT
):
- Только для чтения (
READONLY
) - если свойство отображается в таблице, обработка будет аналогична обработкеCHANGE
по умолчанию в случае, когда свойство не изменяемое (то есть будет вызван механизм фильтрации). Если свойство отображается не в таблице, никаких действий произведено не будет. Также эту опцию можно сделать условной (READONLYIF
) (то есть редактировать, только если значение некоторого свойства будет неNULL
). - Селектор (
SELECTOR
) - при попытке изменения будет вызван диалог, в котором пользователю будет предложено изменить текущее значение объекта.
Язык
Для задания обработок событий формы используется опция ON
в инструкции FORM
(блок событий, блок свойств и действий, блок объектов), а также в опциях свойств.
Примеры
showImpossibleMessage() { MESSAGE 'It\'s impossible'; };
posted = DATA BOOLEAN (Invoice);
FORM invoice 'Инвойс' // создаем форму по редактированию инвойса
OBJECTS i = Invoice PANEL // создаем объект класса инвойс
// ... задаем остальное поведение формы
EVENTS
// указываем, что при нажатии пользователем OK должно выполняться действия,
// которое выполнит действия по "проведению" данного инвойса
ON OK { posted(i) <- TRUE; },
// по нажатию кнопки formDrop выдаем сообщение, что такого не может быть, так как эта кнопка
// по умолчанию будет показываться только в форме по выбору инвойса, а эта форма по сути
// является формой редактирования инвойса
ON DROP showImpossibleMessage()
;
CLASS Shift;
currentShift = DATA Shift();
CLASS Cashier;
currentCashier = DATA Cashier();
CLASS Receipt;
shift = DATA Shift (Receipt);
cashier = DATA Cashier (Receipt);
FORM POS 'POS' // объявляем форму для продажи товара покупателю в торговом зале
OBJECTS r = Receipt PANEL // добавляем объект, в котором будет храниться текущий чек
// ... объявляем поведение формы
;
createReceipt () {
NEW r = Receipt {
shift(r) <- currentShift();
cashier(r) <- currentCashier();
SEEK POS.r = r;
}
}
// добавляем свойство через расширение формы, чтобы можно было сделать SEEK к уже созданному объекту на форме
EXTEND FORM POS
EVENTS
// при открытии формы выполняем действие по созданию нового чека, которое заполняет смену,
// кассира и прочую информацию
ON INIT createReceipt()
;