# Выборка Выборка определяет правило получения, отображение данных и обеспечивает взаимодействие с пользователем. Выборки содержат основную часть интерактивной бизнес логики. Выборка определяет: - Способ получения данных - Способ отображения данных пользователю - Бизнес логику обработки пользовательских действий Выборка может создаваться от класса с использованием кодо-генерации или вручную. Пользовательский интерфейс приложения является совокупностью экземпляров отображений выборок. ## Отображения Отображение – группирует бизнес логику выборки в зависимости от способа представления данных. Стандартные отображения для класса: - `Default` – отображение по умолчанию \ В данном отображении определена функциональность общая для данных выборки. Остальные отображения выборки обычно наследуют это отображение. - `List` – отображение для списка объектов класса - `Card` – отображение для карточки объекта - и т.д. ## Отношение экземпляров выборок Экземпляры выборок, открытые в приложении, связаны друг с другом в отношении `мастер-деталь`. Это означает, что одна выборка всегда является подчиненной к другой выборке. Подчиненная выборка имеет доступ к параметрам и данным мастер выборки. Корнем выборок экземпляра приложения – является выборка главного меню. Все остальные выборки являются подчиненными к ней. Выборка являющаяся корнем формы имеет доступ к данным главного меню. Экземпляры выборок внутри формы также выстраиваются в иерархии `мастер-деталь`, в соответствии с бизнес логикой отображения. ![](../img/sel_tree.png) ## Доступность параметров главных выборок в подчиненных выборках Получение значения параметра осуществляется с помощью метода `getVar()` и преобразованием результата к нужному типу. Иерархическая структура создаваемых объектов (выборок) позволяет обеспечивать доступность и передачу параметров по отношению «мастер-деталь», а также производить автоматическое обновление при изменении используемых параметров. Параметры экземпляров выборок – это, прежде всего, атрибуты (поля) их датасета. Также это могут быть дополнительно созданные параметры, или специальные параметры фреймов. Параметры мастер-выборок автоматически становятся доступны в детальных выборках. При этом, главная выборка является общим, наиболее высокоуровневым мастером, поэтому в ней имеет смысл создавать наиболее общие параметры, используемые всем приложением. Обращение к параметру непосредственного мастера осуществляется прибавлением к имени параметра префикса `super$`. При этом, если необходимо обратиться к параметру мастер-выборки своей собственной мастер-выборки (т.е. перепрыгнуть через один экземпляр выборки), необходимо использовать префикс `super$super$`. В случае, если при любом из обращений к параметру он не будет найден, произойдет автоматический поиск параметра по дереву отношений "мастер-деталь" выборок вплоть до тех пор, пока мы не найдем этот параметр, или не дойдем до главной выборки приложений. Поэтому, при создании глобальных параметров на уровне главной выборки приложения, для них имеет смысл давать уникальное имя, а затем обращаться к ним из любого места приложения используя один единственный префикс `super$`. Пример получения строкового параметра из мастер-выборки: ```scala getVar("super$sCaption").asNString ``` ## Передача параметров в выборку При открытии выборки, в нее можно передать карту с дополнительными параметрами, используя метод `params()`. Пример кода: ```scala Bs_GoodsAvi.defCard.newForm().params(Map(CardRep.IdItemSharp -> idvGds, CardRep.EditingType -> EditingType.edit)).open() ``` В случае такой передачи параметров, они становятся доступны в открытом отображении. ## Открытие выборок в различных режимах При открытии выборки в любом из режимов: - newForm().open() - newForm().openModal() - newForm().openLookup() необходимо учитывать, что родителем для открывшейся выборки будет являться ***_MainMenu, а сама открывшаяся выборка будет главной формой (selection.isMainOnForm = true). Поэтому открывать выборки, в которых установлены зависимости от параметров (`"super$..."`) родительской выборки, без самой родительской выборки нельзя, тк никаким способом в открывающуюся выборку не получится передать подобные параметры. ## Разметка выборки Фреймворк использует систему декларативной разметки выборок. Это позволяет ускорить разработку визуальных форм т.к. разработчику не требуется заниматься низкоуровневым программированием. Разметка выборки задает правила отображения данных выборки и ее дочерних элементов в `xml` файле, с расширение `.avm.xml`. Ключевые элементы разметки: - Отображения - Компоновка формы - Фрейм \ Задает тип представляемых данных (список, дерево и тд.) - Атрибуты - Операции - Фильтры ### Разметка карточки. Контейнеры Существует два режима разметки отображения: 1. Разметка на основе настроек атрибутов - старый режим разметки, основанный на порядковом номере и поле `isLastInLine` атрибутов. 2. Разметка на основе контейнеров - новый режим, основанный на разметке с помощью контейнеров, указанных внутри тэга ``````. \ Разметка атрибутов может быть задана с помощью следующих контейнеров: - *hBox* горизонтальный контейнер: объекты внутри располагаются друг за другом горизонтально. - *vBox* - вертикальный контейнер: объекты внутри располагаются друг за другом вертикально. - *vGroup* - группа объединения: по сути тот же вертикальный контейнер, но визуально обводит содержимое рамкой и может иметь наименование. - *vSection* - сворачиваемая секция: вертикальный контейнер, который имеет наименование и функцию сворачивания, которая скрывает содержимое. Можно указать, как по умолчанию будет отображаться секция - свернутой или развернутой. Контейнеры могут быть вложены друг в друга. Пример разметки с помощью контейнеров: ```scala ``` ![](../img/repMarkupExample.jpg) ### Использование шаблонов в разметке. Файлы разметки поддерживают язык шаблонов [Thymeleaf](https://www.thymeleaf.org). Шаблоны позволяют вставлять в выборку повторно используемые фрагменты. К примеру использовать общий фильтр в разных отображениях. Для использование шаблонов языка шаблонов необходимо подключить в выборку пространство имен: `xmlns:th="http://www.global-system.ru/xsd/global3-view-template-1.0"` ### Наследование разметки Для наследования разметки другой выборки необходимо: 1. Подключить пространство имен языка шаблонов 2. Добавить к тегу view указание о наследовании другой разметки `th:extends="Some_Other.avm.xml"` Полный пример xml с наследованием: ```xml ``` Алгоритм наследования выборки: 1. При отсутствие скопировать отображения предка в наследника \ Копирование происходит в случаи если в наследники нет данного отображения 2. Произвести наследование отображений \ Наследование производится в случаи если и в предке и в потомке есть отображение с тем же именем. 3. Выполнить оставшиеся команды языка разметки Алгоритм наследования отображений: 1. При отсутствие скопировать - levelGroups - bandGroups - layout - filter 2. Добавить отсутствующие атрибуты 3. Добавить отсутствующие операции ## Операции Выборка взаимодействует с программным окружением системы с помощью операций. Операция – это некая обработка того или иного события, вызванного пользователем или каким-то процессом. Операции бывают служебными, выполняя логику обработки событий, или пользовательскими, срабатывающими в результате явного действия пользователя. ### Классификация операций - *Базовые операции* \ Операции, предназначенные для работы с набором данных. Они отвечают за добавление, удаление, обновление записей, получения данных, навигацию по датасету и т.п. Эти операции, как правило, уже определены на уровне базовых выборок-предков. Некоторые из этих операций срабатывают автоматически на выполнение определенных пользовательских действий (`BeforeEdit` при начале редактирования, `AfterEdit` при завершении, `CheckWorkAbility` при перемещении с записи на запись) - *Служебные операции* \ Операции, выполняющие строго определенные вспомогательные действия - *Системные операции* \ Операции, создающиеся автоматически - *Сеттеры* \ Операции предназначены для изменения значений атрибутов (полей) выборки. При вводе значения в какое-то поле формы вызывается связанная с данным полем операция (сеттер), которая по умолчанию вызывает серверные методы изменения значений атрибутов класса. Сеттеры для атрибутов класса создаются автоматически. - *Операции фильтров* \ Операции, необходимые для работы с фильтрами. - *Пользовательские операции* Операции, создаваемые разработчиком самостоятельно и позволяющие осуществлять любой набор необходимых операций, не только осуществляемых над данными, но и являющихся целиком клиентскими (например, вызов другой формы, сообщения и т.п.). ### Базовые операции выборки С точки зрения автоматического срабатывания операций на различные системные действия, ключевым параметром операций является их системное имя. Базовые и служебные операции выборки имеют предопределенные системные имена. #### onRefresh Операция, загружающая данные в датасет. При повторном вызове производит обновление всего набора данных (`refresh`). #### onRefreshItem Операция обновления одной (текущей) записи. #### onRefreshExt Операция с дополнительным запросом к базе для получения полей-заголовков ссылочных объектов. Вызывается только для объектных запросов в onRefresh/onRefreshItem. \ Для использования в запросе атрибутов класса необходимо передать их в блоке `with`. При этом обязательно для НЕ `Long` атрибутов нужно явно указывать тип в аннотации `/*@...*/`: \ - Для `Varchar` атрибутов - "String", "NString" или "varchar", например - `/*@NString*/` - Для `Number` атрибутов - "Number", например - `/*@Number*/` В противном случае атрибуты попытаются преобразоваться к `bigint` типу. #### beforeEdit Операция, выполняемая перед началом редактирования записи для выполнения подготовительных действий перед началом редактирования. Автоматически выполняется в момент начала внесения изменений в объект. #### afterEdit Операция финальной проверки ввода записи. Срабатывает автоматически при попытке перейти с отредактированной записи на другую запись выборки или при закрытии выборки. #### insert Операция вставки новой записи в выборку. #### delete Операция удаления записи. #### checkWorkAbility Операция, предназначенная для осуществления проверок изменения состояния операций выборок, доступности редактирования ее атрибутов. Вызывается автоматически при переходе с записи на запись, при открытии выборки, а также после выполнения операции, для которой выставлен флаг "выполнять операцию применимости после выполнения операции". #### onLoadMeta Операция, срабатывающая при загрузке метаданных. Т.к. метаданные загружаются только один раз, при первом открытии экземпляра выборки на фрейме, то и данная операция срабатывает только один раз. #### onUnloadMeta Операция, срабатывающая при выгрузке метаданных. #### beforeOpen Операция, срабатывающая перед открытием выборки. Данная операция рекомендуется для создания дополнительных параметров, используемых в выборке. #### afterOpen Операция, срабатывающая сразу после открытия выборки. Необходимо использовать для переопределения наименований столбцов выборки и т.д. #### onShow Операция, срабатывающая сразу после того, как отрисован интерфейс формы и были созданы элементы формы. #### onControllerCreated Операция, срабатывающая сразу после того, был создан фрейм отображения выборки. Эта операция аналогична OnShow, но срабатывает в том числе и при открытии интерфейсных элементов формы, которые были скрыты при открытии формы (например, закладки, которые не были первыми в перечне закладок). ### Служебные операции выборки #### saveForm Операция сохраняет данные формы. #### cancelForm Операция отменяет изменения на форме. #### closeFormOk Операция закрытия формы с подтверждением выбора #### closeFormCancel Операция закрытия формы по кнопке "Выход" или по кнопке закрытия окна "крестик" #### beforeCloseForm Операция срабатывает перед закрытием формы. #### afterCloseForm Операция срабатывает после закрытия формы. #### onCloseFormQuery Операция вызывается в начале процесса закрытия формы и позволяет отменить закрытие. ### Предопределенные операции выборок #### applyUniFilter Операция применяет настроенные условия фильтрации, выполняется перезапрос данных с наложенными условиями фильтрации. #### resetUniFilter Операция отменяет все наложенные на выборку фильтры #### clearUniFilter Операция отчищает все условия фильтрации. #### showAuditObject Операция вызывает окно аудита выполняемых пользователями действий в БД, с наложенным фильтром по текущему объекту. #### showAboutObject Операция открывает окно системной информации об объекте. #### copyObject Операция копирования объекта #### cardEdit Операция открытия объекта в карточке, предварительно запросив, какую использовать выборку и отображение. #### allowEdit Разрешение/запрещение редактирования объектов в списке. По умолчанию операция доступна для редактируемых списков. #### showTab Операция открытия/закрытия детальной части ### Сеттеры изменения атрибутов Операции установки значений атрибутов (так называемые сеттеры) используются для того, чтобы установить определенное значение в поле записи объекта, соответствующее его типу. Имя сеттера состоит из префикса `set` и имени атрибута `attributeName`: `setattributeName`. ### Специальные операции контролов #### onFocusedFieldChanged Это специальная операция, срабатывающая после перехода фокуса ввода в списке или дереве с одного столбца на другой, а также при переходе с контрола на контрол в карточке или панели фильтров. #### onFocusedCellChanged Это специальная операция, срабатывающая после перехода фокуса ввода в списке с одной ячейки на другую. #### onFrameActivated Специальная операция, срабатывающая при переходе фокуса ввода в грид, дерево, карточку. ### Способы визуализации операций Существует 3 основных способа визуального отображения операций: - На тулбаре фрейма - В выпадающем (контекстном) списке (popup меню) - В качестве пункта главного меню (доступно только для выборок приложений главного меню) Для настройки отображения операции каждым из способов существует собственная настройка при помощи соответствующих свойств операции. ## Диалоги Диалоги позволяют задавать вопросы пользователю и получать от него ответы на эти вопросы. Для доступа к методам диалогов используется специальный объект `ru.bitec.app.gtk.gl.Dialogs`, который доступен в `Avi` через переменную `dialogs`. Кроме стандартных диалогов, есть возможность открыть форму в режиме выбора (`openLookup`) и после обработать выбранное пользователем значение, что так же из себя представляет специализированный вид диалогов. ### Стандартные диалоги #### showMessage Выводит на экран текст в модальном окне. Пример использования: ```scala dialogs.showMessage("Текст, который увидит пользователь") ``` #### showMsgDialog Открывает диалог указанного типа с сообщением и указанным перечнем кнопок. Возможные типы диалогов см. в `ru.bitec.app.gtk.gl.msgdlg.MsgDlg` Возможные типы кнопок см. в `ru.bitec.app.gtk.gl.msgdlgbutton.MsgDlgButton`g Пример использования: ```scala val dlgRes = dialogs.showMsgDialog( //тип диалога "Подтверждение" MsgDlg.confirmation, //текст диалога "Включить автонумерацию?", //список кнопок: Да, Нет List(MsgDlgButton.yes,MsgDlgButton.no) ) if (dlgRes == MsgDlgButton.yes) { //обработка нажатия на кнопку "Да" } else if (dlgRes == MsgDlgButton.no) { //обработка нажатия на кнопку "Нет" } ``` #### showButtonsDialog Открывает диалог с произвольными кнопками. Позволяет формировать диалоги, кнопки которых будут не из перечня стандартных кнопок. Пример использования: ```scala dialogs.showButtonsDialog( caption = "", text = "Удалить форму или убрать ссылку на вид отчетности?", colCount = 2, buttons = List(List("Удалить"), List("Убрать ссылку")), imageCollectionName = "ToolBarPrimaryHot", focusButtonNumber = 0L ) match { case 0L => //обработка нажатия кнопки "Удалить" case 1L => //обработка нажатия кнопки "Убрать ссылку" } ``` #### showPromptDialog Открывает диалог с запросом ввода строки. Пример использования: ```scala val svDialogRes = dialogs.showPromptDialog("Заголовок окна", "Текст диалога", "Значение по умолчанию").ns if (svDialogRes.isNotNullOrEmpty) { //обработка введенного значения } ``` #### showConfirmDialog Открывает диалог с типом "Подтверждение" и кнопками "Да" и "Нет" Пример использования: ```scala val dialogRes = dialogs.showConfirmDialog("Текст диалога") if (dialogRes){ //обработка случая, когда пользователь нажал "Да" } ``` #### showInfoForm Отображает информационное сообщение с переданным текстом, без возможности его закрытия пользователем. Скрывается при вызове метода `hideInfoForm`. Применяется, когда в бизнес-логике выполняется продолжительная задача, и требуется проинформировать пользователя об ее выполнении. Пример использования: ```scala dialogs.showInfoForm("Внимание, идет загрузка Госреестра типов СИ") try { //продолжительное действие thisApi().download() } finally { dialogs.hideInfoForm() } ``` #### hideInfoForm Скрывает информационное сообщение, см. описание метода `showInfoForm` #### withInfoForm Метод включает в себя открытие информационного окна, и его закрытие после завершение выполнения переданной функции. Пример из описания метода `showInfoForm`, можно переписать используя этот метод: ```scala dialogs.withInfoForm("Внимание, идет загрузка Госреестра типов СИ") { //продолжительное действие thisApi().download() } ``` #### showEditPaintStyleDialog Вызывает диалог настройки стилей раскраски текстовых полей. ### Форма в режиме выбора значения Одной из типичных задач является предложить выбрать пользователю какой-либо объект и затем сделать обработку его выбора. Например, чаще всего ссылочные поля открывают для выбора список объектов ссылочного класса, а после выбора пользователем значения устанавливают его в текущей форме. Для реализации такого типа диалогов используется синтаксис открытия формы в режиме `openLookup`. Пример открытия формы и обработки выбора пользователя: ```scala //создаем новую форму val data = Btk_ClassAvi.listForChoose().newForm() //указываем список полей, которые требуется получить из формы .results("id" :: "sCaption" :: Nil) //открываем форму в режиме выбора .openLookup() //проверяем, что пользователь подтвердил выбор if (data.getLookupResult eq LookupResult.ok) { //получаем значение первого поля из списка results val id = data.getData(1, 0) //получаем значение второго поля из списка results val sCaption = data.getData(1, 1) } ``` #### Выбор нескольких строк (мультиселект) Для того, чтобы в форме в режиме выбора пользователь мог выбрать несколько строк используется опция `useMultiSelect`. Пример открытия формы в режиме мультиселекта и обработка выбранных значений: ```scala //создаем новую форму val data = Btk_ClassAvi.listForChoose().newForm() //указываем список полей, которые требуется получить из формы .results("id" :: "sCaption" :: Nil) //указываем возможность выбора нескольких строк .useMultiSelect //открываем форму в режиме выбора .openLookup() //проверяем, что пользователь подтвердил выбор if (data.getLookupResult eq LookupResult.ok) { //цикл по выбранным строкам for (i <- 1 to data.size) { //получаем значение первого поля из списка results для строки i val id = data.getData(i, 0) //получаем значение второго поля из списка results для строки i val sCaption = data.getData(i, 1) } } ``` ## Фрейм Фреймы — это средство представления информации в выборке. Существующие фреймы по способу представления информации можно разделить на несколько видов: - для отображения информации в виде карточки объекта - для отображения списка объектов в табличной форме - для отображения списка объектов в виде древовидной структуры - для отображения инфографики - специализированные (для отображения графической информации, доступа к файлам и т.д.) ### Основные типы фреймов #### grid Фрейм для вывода списка объектов класса в табличной форме ![](../img/frame/grid.png) #### tree Фрейм для вывода списка объектов класса в древовидной форме ![](../img/frame/tree.png) #### card Фрейм для вывода всех атрибутов конкретного объекта (Карточка) ![](../img/frame/card.png) #### tab Фрейм с закладками. Выборка фрейма является источником списка закладок. Так же, закладки могут быть указаны статически, в xml-разметке. #### memo Фрейм для ввода большого количества текстовой информации (Memo) ![](../img/frame/memo.png) #### html Фрейм, отображающий HTML ![](../img/frame/html.png) #### image Изображение ![](../img/frame/image.png) #### gantt Фрейм, для построения диаграмм Ганта. ![](../img/frame/gantt.png) #### olap Фрейм для построения сводных (OLAP) таблиц #### bpmn Фрейм редактора диаграмм бизнес-процессов. Поддерживает диаграммы BPMN версии 2.0 ![](../img/frame/bpmn.png) #### gridPanel Позволяет размещать детальные фреймы в виде таблицы, для указания ширины и высоты ячеек которой можно использовать как абсолютные, так и относительные величины. ![](../img/frame/gridPanel.png) ### Основные типы редакторов #### button Редактор - Кнопка. При нажатии выполнится сеттер соответствующего атрибута. ![](../img/editor/button.png) #### buttonsEdit Редактор в строке с произвольными кнопками. Если ни одной кнопки для отображения не задано, по умолчанию будет отображена кнопка lookup. ![](../img/editor/buttonsEdit.png) #### calendar Редактор - Календарь. ![](../img/editor/calendar.png) #### check Редактор - Чекбокс (Галка). ![](../img/editor/check.png) #### colorPick Редактор - Выбор цвета. ![](../img/editor/colorPick.png) #### combo Редактор - Фиксированный выпадающий список. #### currency Денежный редактор. ![](../img/editor/currency.png) #### datePick Редактор даты. ![](../img/editor/datePick.png) #### dateTimePick Редактор даты и времени. ![](../img/editor/dateTimePick.png) #### edit Однострочный редактор текста. ![](../img/editor/edit.png) #### editButton Редактор: Редактор в строке с кнопкой. ![](../img/editor/editButton.png) #### hotKey Редактор ввода комбинации горячих клавиш. #### hyperLink Редактор адреса эл.почты и гипер-ссылок. ![](../img/editor/hyperLink.png) #### icon Редактор - изображение. Используется для списка и дерева. Отображает изображение из коллекции изображений. ![](../img/editor/icon.png) #### lookup Редактор - Выпадающий список по запросу. Источником элементов могут являться: выборка или SQL-запрос, указанные в свойствах. ![](../img/editor/lookup.png) #### memo Многострочный редактор. Предназначен для редактирования многострочных текстовых значений без разметки. ![](../img/editor/memo.png) #### tagLookup Редактор - Выпадающий список по запросу с возможностью множественного выбора. ![](../img/editor/tagLookup.png) #### timePick Редактор времени. ![](../img/editor/timePick.png) #### editPassword Редактор ввода пароля. ![](../img/editor/editPassword.png) #### imageCollection Редактор - выпадающий список изображений. ![](../img/editor/imageCollection.png) ## Мультиселект Мультиселект - возможность выбрать несколько строк в списках или деревьях. Для включения мультиселекта в отображении укажите в теге `grid` или `tree` свойство `isMultiSelectEnabled="true"`. Пример разметки: ```xml ``` Пример обработки выделенных строк пользователем и получения значений атрибутов этих строк: ```scala //цикл по выделенным строкам for (i <- 0 until selection.selectedRecordsCount()) { //получение значения поля с типом NLong val id = NLong.fromAny(selection.selectedValueByName("id", i)) //получение значения поля с типом NNumber val nOrder = NNumber.fromAny(selection.selectedValueByName("nOrder", i)) //получение значения поля с типом NGid val gid = NGid(selection.selectedValueByName("gid", i).asInstanceOf[String]) //получение значения поля с типом NString val sCaption = selection.selectedValueByName("sCaption", i).asInstanceOf[String].ns //получение значения поля с типом NDate val dDate = NDate(selection.selectedValueByName("dDate", i).asInstanceOf[JDate]) } ``` ~~~{note} Для формы в режиме выбора мультиселект регулируется опцией `useMultiSelect` при создании формы. Подробнее в главе `Диалоги` ~~~ ## Настройка стилей Стиль - набор свойств, включающий в себя: - `Color` - Цвет заднего фона в формате `$00BBGGRR` или Global константой цвета. - `FontColor` - Цвет шрифта в формате `$00BBGGRR` или Global константой цвета. - `FontSize` - Размер шрифта натуральным числом. - `FontItalic` - Курсив. Значение `0` - нет курсива, `1` - есть курсив. - `FontBold` - Жирность. Значение `0` - не жирный шрифт, `1` - жирный шрифт. - `FontUnderLine` - Подчеркивание. Значение `0` - нет подчёркивания шрифта, `1` - есть подчёркивание шрифта. - `FontStrikeOut` - Перечеркивание. Значение `0` - нет перечеркивания шрифта, `1` - есть перечеркивание шрифта. Стиль задаётся строкой формата: ```scala "param1=value1;param2=value2;param3=value3;...;paramn=valuen" ``` Пресеты стилей хранятся в классе `Btk_Registry`, их можно использовать для типовых задач. Стили можно применять в отображении к строкам и столбцам. ### Применение стиля к строке Чтобы применить стиль к строке, нужно в теге `representation` присвоить свойству `rowStyleAttr` имя атрибута, в котором будет храниться либо готовая строка со стилем, либо системное имя пресета. ```xml ``` ![](../img/StyleToRow.png) ### Применение стиля к столбцу Чтобы применить стиль к столбцу, нужно в теге `attr` создать тег `style` и в нём использовать либо свойство `name`, либо `attr`. В свойстве `name` указывается непосредственно строка стиля или системное имя пресета, в `attr` указывается атрибут, где хранится либо строка, либо системное имя. ```xml