Skip to end of metadata
Go to start of metadata

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

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

Каждый компонент должен иметь свое уникальное имя в рамках формы

Контейнеры

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

  • Вертикальный контейнер (CONTAINERV) - все потомки располагаются сверху вниз.
  • Горизонтальный контейнер (CONTAINERH) - все потомки располагаются слева направо.
  • Панель закладок (TABBED) - в любой момент времени показывается ровно один потомок, который определяет пользователь путем выбора соответствующий закладки.
  • Колоночный контейнер (COLUMNS) - компоненты располагаются в фиксированном количестве колонок. При добавлении потомок помещается в первую колонку с минимальным количеством компонент. По сути заполнение идет сначала слева направо, затем, когда количество колонок достигает заданного, начинается новый ряд, который располагается относительно предыдущих сверху вниз, затем расположение опять идет слева направо и так далее. 
  • Вертикальный сплиттер (SPLITV) - может быть использован только в случае, если у контейнера ровно два потомка. В этом случае они располагаются сверху вниз, при этом пользователь может сам менять, какое пространство отдавать каждому из них.
  • Горизонтальный сплиттер (SPLITH) - аналогичен вертикальному сплиттеру, только потомки располагаются слева направо.
  • Прокручиваемый контейнер (SCROLL) - может быть использован только в случае, если у контейнера ровно один потомок. Этот единственный компонент занимает в контейнере все необходимое ему пространство, и если его не хватает появляется полоса прокрутки.

В будущих версиях последние три вида контейнеров (SPLITV, SPLITH, SCROLL) будут признаны устаревшими, и заменены на соответствующие опции split и scroll в вертикальных и горизонтальных контейнерах.

По умолчанию, любой создаваемый контейнер имеет тип вертикальный контейнер.

Если в какой-то момент времени выполнения у контейнера потомки отсутствуют или являются невидимыми, то он автоматически скрывается. В свою очередь, если какой-то компонент не является потомком ни одного контейнера, то он также не будет показан на форме.

Базовые компоненты

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

Группы объектов / деревья:

  • Таблица / Дерево (GRID) - компонент, состоящий из рядов и колонок, в котором рядам соответствуют наборы объектов соответствующей группы объектов, а колонкам - свойства и действия.
  • Системный тулбар (TOOLBARSYSTEM) - панель, состоящая из кнопок, при помощи которых пользователь может проводить различные системные действия над рядами в таблице. Автоматически прячется, если таблица становится невидимой.
  • Пользовательский фильтр (USERFILTER) - компонент, при помощи которого пользователь может создавать и применять собственные фильтры к таблице.

Группы фильтров

  • Группа фильтров (FILTERGROUP) - компонент, при помощи которого пользователь может активировать необходимые ему фильтры в группах фильтров формы.

Свойства / Действия

  • Панель свойства (PROPERTY) - компонент, которые отображает заголовок и текущее значение свойства. Заголовок может быть как слева от ячейки значения, так и сверху. Не показывается, если свойство отображается в таблицу.

Размеры и расположение компонент

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

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

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

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

  • Динамическое - все компоненты располагаются друг за другом, в порядке их добавления в контейнер. При этом, для каждого компонента можно задать коэффициент расширения (flex). В этом случае оставшееся в контейнере пространство (то есть за вычетом базовых размеров всех внутренних компонент) делится между всеми компонентами пропорционально их коэффициентам расширения.
  • Статическое - для каждого компонента задается выравнивание (alignment) - В начале (START), По центру (CENTER), В конце (END), и Растянуть (STRETCH). В первых трех случаях компонент в качестве окончательного размера получает свой базовый размер, и располагается в соответствии с указанным типом выравнивания (то есть в начале, по центру или в конце). Если же в качестве типа выравнивания используется Растянуть, окончательным размером компонента будет размер верхнего контейнера (но не меньше базового размера), а располагаться он будет ровно по центру. 

    К примеру, в случае вертикального верхнего контейнера, если для компонента задано выравнивание В начале, то он будет располагаться в контейнере максимально слева, а если Растянуть - то компонент займет все пространство от левой до правой границы.

Данный алгоритм расположения компонент является частным случаем CSS Flexible Box Layout (а в веб-клиенте при помощи него и реализуется). Так, к примеру, коэффициенту расширения соответствует свойство CSS flex-grow, а базовому размеру - flex-basis.

Колоночный контейнер свое статическое (горизонтальное) направление разбивает на N одинаковых частей (где N - количество колонок), после чего каждая из частей располагает свои компоненты, как если бы эта часть была отдельным вертикальным контейнером.

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

Расположение свойств в таблице (а точнее колонок, которые отображают их значения) происходит аналогично, как если бы таблица была горизонтальным контейнером, а колонки таблицы - внутренними компонентами этого контейнера. 

Так как в текущей реализации для расположения колонок внутри таблицы в Web клиенте используется механизм CSS Table Layout Fixed (а его возможности существенно ограничены), для свойств, отображающихся в таблице, коэффициент расширения может быть равен либо 0, либо базовому размеру.

Расположение заголовка и ячейки значения внутри панели свойства происходит аналогично, как если бы панель была контейнером (горизонтальным - если заголовок слева, вертикальным - если сверху), в котором у ячейки значения коэффициент расширения равен 1, у заголовка равен 0, а выравнивания обоих равны STRETCH. 

Размеры ячеек значений свойств

При отображении свойств можно явно задавать как размеры всего контейнера (вместе с заголовком, если свойство находится в панели), так и размеры непосредственно ячейки значения. Для этого к названию размера необходимо добавить префикс value - например valueWidth). Также, стоит отметить, что именно эти размеры (то есть ячейки значения, а не всего контейнера) используются при определении ширин колонок, если свойство отображается в таблице.

Для ячеек значений свойств также существует возможность задать базовую ширину не в пикселях, а при помощи некоторого значения-образца (widthValue). В этом случае платформа сама с учетом используемых шрифта / маски / локали пользователя вычисляет и устанавливает ширину в пикселях, таким образом, чтобы пользователю было видно в точности заданное значение-образец (ни больше, ни меньше). Предполагается, что значение-образец должно быть либо строкой, либо его класс должен совпадать с классом значения свойства.

Кроме того, ширину ячейки значения можно задавать в символах (charWidth), что эквивалентно тому, как если бы значение-образец было строкой и состояло из заданного количества нулей.

В последних двух случаях (то есть при задании ширины в виде значения-образца или в символах), если класс значения свойства при вводе подразумевает наличие справа кнопки (например, таким классом является DATE), то к ширине ячейки значения свойства дополнительно добавляется ширина этой кнопки (21 пиксель).

Размеры и расположение по умолчанию

По умолчанию, коэффициент расширения и выравнивание для компонент определяются следующим образом:

КомпонентКоэффициент расширенияВыравнивание
Таблица / Дерево1STRETCH
Компонент внутри прокручиваемых контейнеров, сплиттеров и панели закладок1STRETCH
Панель свойства внутри горизонтального контейнера или свойство в таблице. При этом значения свойства являются объектами встроенных классов динамической длины (то есть строки и числа)Ширина ячейки значенияSTART
Панель свойства внутри вертикального контейнера. При этом значения свойства являются объектами встроенных классов динамической длины (то есть строки и числа)0STRETCH
Все остальные0START

Базовый размер контейнера (за исключением панели закладок) по умолчанию равен сумме базовых размеров всех его потомков для динамического направления, и максимуму - для статического направления. Базовая высота панели закладок равна сумме базовой высоты ее текущей вкладки и высоты панели заголовков вкладок, базовая ширина при этом совпадает с базовой шириной текущей вкладки.

Базовая ширина таблиц / деревьев по умолчанию равна 130 пикселям, высота - 70. Базовый размер панели свойства определяется аналогично, как если бы панель была контейнером (горизонтальным - если заголовок слева, вертикальным - если сверху), состоящим из заголовка и ячейки значения. Базовый размер остальных базовых компонент (а также заголовка в панели свойства) определяется таким образом, чтобы вместить весь содержащийся в них текст.

Размеры ячеек значений свойств

Для определения ширины ячейки значения свойства по умолчанию используются следующие формулы:

Класс значения свойстваВ чем определяется ширинаШирина / Значение
СтрокиВ символах
IF length <= 12
	result = length
ELSE IF length = INFINITE
	result = 15
ELSE 
    result = 12 + (length - 12) ^ 0.7
ЧислаВ символах
IF length <= 6
	result = length
ELSE IF this = DOUBLE
    result = 10
ELSE 
    result = MIN(6 + (length - 6) ^ 0.7, 10)

Где length = integerPart + precision

COLORВ пикселях40
Файлы и ссылки на файлыВ пикселях18
BOOLEANВ пикселях25
DATEЗначение-образец1991_11_21
DATETIMEЗначение-образец1991_11_21_10:55:55
TIMEЗначение-образец10:55:55
Пользовательские классыВ символах7

Высота ячейки значения свойства по умолчанию равна высоте используемого шрифта, за исключением свойств, значения, которых принадлежат классу TEXT (в этом случае высота равна четырехкратной высоте шрифта).

Размер окна

Если форма открывается в режиме окна, у нее нет верхнего контейнера, соответственно для этого окна необходимо определить его первоначальный размер. Этот размер определяется аналогично базовому размеру по умолчанию, с той лишь разницей, что для таблиц / деревьев, размер по умолчанию определяется не как константа (по умолчанию - 130,70), а таким образом чтобы вместить все ее содержимое (по аналогии с механизмом автоматического определения размера), но не меньше чем 130 по ширине и 140 по высоте.

Дизайн по умолчанию

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

Автоматический дизайн формируется следующим образом:

  • BOX - содержит все компоненты данной формы. Вертикальный контейнер. Коэффициент расширения - 1, выравнивание - STRETCH.
    • PANEL - содержит компоненты свойств, которые отображаются в представлении PANEL и для которых группа отображения не определена (у свойства нет параметров). Внутренняя структура и расположение аналогичны соответствующему контейнеру для группы объектов. 
      • GROUP...
    • OBJECTS - содержит все компоненты, которые создаются для групп объектов / деревьев данной формы. Вертикальный контейнер. Коэффициент расширения - 1, выравнивание - STRETCH.
      • BOX(<группа объектов / дерево>) - содержит все компоненты данной группы объектов. Вертикальный контейнер. Коэффициент расширения - 1, выравнивание - STRETCH.
        • GRIDBOX(<группа объектов / дерево>) - содержит таблицу / дерево. Горизонтальный контейнер. Коэффициент расширения - 1, выравнивание - STRETCH.
          • GRID(<группа объектов / дерево>) - базовый компонент Таблица.
        • TOOLBARBOX(<группа объектов / дерево>) - содержит все составные части тулбара (отвечающие за расположение внутри тулбара). Горизонтальный контейнер. Выравнивание - STRETCH
          • TOOLBARLEFT(<группа объектов / дерево>) - левая часть тулбара. Горизонтальный контейнер. Выравнивание - CENTER.
            • TOOLBARSYSTEM(<группа объектов / дерево>) - базовый компонент Системный тулбар. Выравнивание - CENTER.
          • TOOLBARRIGHT(<группа объектов / дерево>) - правая часть тулбара. Горизонтальный контейнер. Коэффициент расширения - 1, выравнивание - CENTER.
            • FILTERGROUPS(<группа фильтров>) - содержит все компоненты, которые создаются для групп фильтров соответствующей группы объектов. Горизонтальный контейнер. Выравнивание - CENTER.
              • FILTERGROUP - базовый компонент Группа фильтров. Выравнивание - CENTER.
            • TOOLBAR(<группа объектов / дерево>) - содержит компоненты свойств, которые отображаются в представлении TOOLBAR и группа отображения которых равна заданной. Горизонтальный контейнер. Выравнивание - CENTER.
              • PROPERTY(<свойство>) - базовый компонент Панель свойства.
        • USERFILTER(<группа объектов / дерево>) - базовый компонент Пользовательский фильтр. Выравнивание - STRETCH.
        • PANEL(<группа объектов / дерево>) - содержит компоненты свойств, которые отображаются в представлении PANEL. Вертикальный контейнер. Выравнивание - STRETCH. Если некоторые свойства принадлежат группам, для которых необходимо создание отдельных контейнеров, то для них создается соответствующая иерархия контейнеров и в нее помещаются компоненты этих свойств:
          • GROUP(<группа свойств>,<группа объектов / дерево>) - содержит компоненты свойств, которые принадлежат заданным группе объектов и группе свойств (или не принадлежат никакой группе свойств, в этом случае группа свойств не указывается, например GROUP(,a)). Колоночный контейнер.
            • PROPERTY(<свойство>) - базовый компонент Панель свойства.
    • TOOLBARBOX - содержит компоненты свойств, которые отображаются в представлении TOOLBAR и для которых группа отображения не определена (например у свойства нет параметров). Внутренняя структура и расположение аналогичны соответствующему контейнеру для группы объектов (за исключением FILTERGROUPS, который не имеет смысла, когда группа объектов не определена, и соответственно в этом контейнере отсутствуют).
      • TOOLBARLEFT, TOOLBARRIGHT, TOOLBAR...

Пример дизайна по умолчанию

1
2
3
4
5
6
7
  
FORM myForm 'myForm'
    OBJECTS myObject = myClass
    PROPERTIES(myObject) myProperty1, myProperty2 PANEL
    FILTERGROUP myFilter
        FILTER 'myFilter' myProperty1(myObject)
;

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


Язык

Для управления дизайном формы предназначена инструкция DESIGN.

Примеры

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 DESIGN order { // настраиваем дизайн формы, начиная с дизайна по умолчанию
    // отмечаем, что все изменения иерархии будут происходит для самого верхнего контейнера 
    NEW orderPane FIRST { // создаем новый контейнер самым первым перед системными кнопками, в который положим два контейнера - шапка и спецификации
        fill = 1; // указываем, что контейнер должен занимать все доступное ему место
        type = SPLITV; // указываем, что контейнер будет вертикальным сплиттером
        MOVE BOX(o) { // переносим в новый контейнер все, что касается объекта o
            PANEL(o) { // настроим как отображаются свойства в панели объекта o
                type = CONTAINERV; // делаем, чтобы все потомки шли сверху вниз
                NEW headerRow1 { // создаем контейнер - первый ряд
                    type = CONTAINERH;
                    MOVE PROPERTY(date(o)) { // переносим свойство даты заказа
                        caption = 'Дата редактируемого заказа'; // "перегружаем" заголовок свойства в дизайне формы (вместо стандартного)
                        toolTip = 'Введите сюда дату, когда был сделан заказ'; //задаем подсказку для свойства дата заказа
                        background = #00FFFF; // делаем фон красным
                    }
                    MOVE PROPERTY(time(o)) { // переносим свойство времени заказа
                        foreground = #FF00FF; // делаем цвет зеленым
                    }
                    MOVE PROPERTY(number(o)) { // переносим свойство номер заказа
                        charWidth = 5; // ставим, что пользователю желательно должно показываться 5 символов
                    }
                    MOVE PROPERTY(series(o)); // переносим свойство серия заказа
                }
                NEW headerRow2 {
                    type = CONTAINERV; // потомки - сверху вниз
                }
                MOVE PROPERTY(note(o));
            }
              
            size = (400, 300); //указываем, что контейнер o.box должен иметь базовый размер 400x300 пикселей
        }
        NEW detailPane { // создаем контейнер, в котором будут хранится различные спецификации по заказу
            type = TABBED; // помечаем, что этот контейнер должен быть панелью закладок, где закладками являются его потомки
            MOVE BOX(d) { // добавляем контейнер с строками заказа как одну из закладок верхней панели
                caption = 'Строки'; // задаем заголовок панели закладки
                PROPERTY(index(d)) { focusable = FALSE; } // делаем, чтобы колонка с номером строки никогда не могла иметь фокус
                GRID(d) {
                    defaultComponent = TRUE; // делаем, чтобы по умолчанию фокус при открытии формы устанавливался на таблицу строк
                }
            }
            MOVE BOX(s) { // добавляем контейнер с итогами по sku как одну из закладок detailPane
                caption = 'Подбор';
            }
        }
    }
}
  
// разбиваем определение формы на две инструкции (вторую инструкцию можно перенести в другой модуль)
DESIGN order {
    REMOVE TOOLBARLEFT; // убираем из иерархии контейнер с кнопками печати и экспорта в xls, тем самым делая их невидимыми
}

На выходе получаем следующую форму :

  • No labels