Синтаксис дескрипторов
Это основная справочная глава. Она охватывает XML‑элементы, систему типов, работу наследования и переопределения, а также каталог атрибутов, которые можно задать на дескрипторе.
1 Структура документа
Каждый файл дескриптора — это XML‑документ с корневым элементом <SCCollection>. Внутри
него размещаются пространства имён, включения, объявления типов и объявления свойств.
<?xml version="1.0" encoding="UTF-8" ?>
<SCCollection>
<SCNameSpace ID="Operations">
<SCInclude>$(SUPPLEMENT_FOLDER)\CommonTypes.xml</SCInclude>
<SCType ID="TFoo" type="ComplexType"> ... </SCType>
</SCNameSpace>
</SCCollection>
Структурные элементы:
| Элемент | Назначение |
|---|---|
SCCollection |
Корень документа. Присутствует всегда. |
SCNameSpace |
Открывает пространство имён (ID="Operations", "Machines", …). Всё внутри объявляется в этом пространстве. Может быть вложенным. |
SCInclude |
Подключает другой файл в этом месте. Поддерживает Optional="True" и маски. |
SCType |
Объявляет тип (переиспользуемый дескриптор) — или, будучи вложенным в другой тип, объявляет его член. Главный рабочий элемент. |
SCProperty |
Объявляет именованное глобальное свойство — одиночное значение/объект на уровне пространства имён (см. §6). |
Файлы вне какого‑либо <SCNameSpace> вносятся в то пространство имён, в которое их
включают — поэтому у CommonTypes.xml нет собственного пространства
имён: он включается во многие.
2 SCType — рабочая лошадка
SCType выполняет двойную роль в зависимости от того, где он появляется.
На верхнем уровне (или прямо внутри пространства имён) он объявляет тип — именованный переиспользуемый шаблон:
<SCType ID="T2DPoint" Caption="Point" type="ComplexType">
<SCType ID="X" Caption="X" type="Double" DefaultValue="0" DimensionKind="Linear"/>
<SCType ID="Y" Caption="Y" type="Double" DefaultValue="0" DimensionKind="Linear"/>
</SCType>
ID — имя типа; type указывает его базу (здесь встроенный ComplexType). Вложенные
элементы <SCType> объявляют члены типа.
Вложенный в другой тип <SCType> объявляет новый член охватывающего типа. ID члена —
это его имя внутри родителя, а type — тип значения члена, который может быть встроенным
типом или любым ранее объявленным типом:
<SCType ID="TSTFaceMillingOp" type="TSTMillOp">
<!-- член с именем MillingType, ранее объявленного типа TMillMode -->
<SCType ID="MillingType" type="TMillMode" Caption="Milling type"/>
</SCType>
Итого: ID + type = «создать нечто с именем ID, имеющее тип type», независимо от
того, является ли это «нечто» типом верхнего уровня или членом составного типа.
3 Система типов
3.1 Встроенные (примитивные) типы
Атрибут type принимает следующие встроенные имена (регистр не важен — Double и double
это одно и то же):
Встроенный type |
Хранит | Примечания |
|---|---|---|
Boolean |
True / False |
|
Integer |
целое число | |
Double |
вещественное число | Используйте DimensionKind для работы с единицами |
String |
текст | |
Enumerated |
один вариант из фиксированного списка | Варианты — дочерние SCType с type="none" |
ComplexType |
запись из именованных членов | Потомки — это члены |
Array |
список однотипных элементов | Единственный потомок задаёт шаблон элемента; см. §5 |
none (или None) |
ничего | Используется для вариантов перечислений, разделителей и чисто интерфейсных заглушек |
Всё, что не входит в эти имена, трактуется как ссылка на ранее объявленный тип — именно так работают композиция и наследование.
3.2 Перечисления
Перечисление перечисляет свои варианты как дочерние SCType с type="none". DefaultValue
перечисления — это ID варианта по умолчанию.
<SCType ID="TXYZCoordinate" Caption="XYZ Coordinate" type="Enumerated" DefaultValue="CoordX">
<SCType ID="CoordAuto" Caption="Auto" type="none"/>
<SCType ID="CoordX" Caption="X" type="none"/>
<SCType ID="CoordY" Caption="Y" type="none"/>
<SCType ID="CoordZ" Caption="Z" type="none"/>
</SCType>
(реальный пример: CommonTypes.xml)
Хранимое значение свойства‑перечисления — это ID варианта (например, CoordX), а не
его подпись. Каждый вариант может нести собственные метаданные (Caption, ImageFile,
Priority, правило Visible, …).
3.3 Составные типы
ComplexType — это запись: её дочерние SCType являются её полями. Составные типы могут
вкладываться произвольно и переиспользоваться как тип других членов.
<SCType ID="TColor" Caption="Color" type="ComplexType">
<SCType ID="R" type="Double" DefaultValue="0.5"/>
<SCType ID="G" type="Double" DefaultValue="0.5"/>
<SCType ID="B" type="Double" DefaultValue="0.5"/>
</SCType>
В инспекторе TColor отображается как образец цвета с диалогом выбора, а не как три числовые
строки — см. §3.4.
3.4 Типы с особым поведением
Несколько часто используемых типов объявлены в CommonTypes.xml как
тонкие псевдонимы базового типа — вы ссылаетесь на них по имени, как на любой объявленный
тип, — но каждый добавляет к базе дополнительное поведение при сериализации или в инспекторе.
Объявляйте член одним из них, когда нужно такое поведение:
| Тип | База | Что добавляет |
|---|---|---|
TranslatableString |
String |
Его значение попадает в подсистему локализации и может быть переведено. По умолчанию локализуются только Caption узлов; используйте этот тип, когда нужно, чтобы переводилось и значение строки (обычно значение по умолчанию). |
CDATAString |
String |
Сериализуется внутри секции CDATA, поэтому значение может содержать символы, иначе запрещённые в XML, — что позволяет сохранить исходное форматирование, например переносы строк и табуляции. |
FileName |
String |
Хранит путь к файлу. При сохранении/загрузке путь автоматически преобразуется между абсолютной и относительной формой и с использованием файловых переменных, например $(SUPPLEMENT_FOLDER). В инспекторе предлагает стандартный диалог открытия файла; атрибут Filter (вида Caption (*.ext)\|mask1;mask2) ограничивает этот диалог выбранными типами файлов. |
DynamicArray |
Array |
Ведёт себя как Array (§5), но в инспекторе показывает количество элементов в собственном поле значения строки и позволяет пользователю менять его, добавляя или удаляя дочерние элементы на лету. |
TColor |
ComplexType |
Цветовое значение (R/G/B, §3.3), отображаемое в инспекторе как образец цвета с диалогом выбора цвета. |
(реальный пример: CommonTypes.xml. Фильтр диалога для FileName —
поле постпроцессора станка — в
Machines/AbstractMachine.xml:
Filter="Postprocessors (*.sppx, *.dll)|*.sppx;*.dll".)
4 Наследование и переопределение
4.1 Наследование типа
Чтобы основать новый тип на существующем, укажите существующий тип в type. Новый тип
начинается со всех членов базы и затем добавляет члены, которые вы объявляете:
<SCType ID="T3DPoint" Caption="Point" type="T2DPoint">
<!-- наследует X и Y из T2DPoint, добавляет Z -->
<SCType ID="Z" type="Double" DefaultValue="0" DimensionKind="Linear"/>
</SCType>
(реальный пример: CommonTypes.xml)
Цепочки наследования могут быть длинными. Конкретная операция, например, наследуется от
семейства абстрактных операций (TSTFaceMillingOp → TSTMillOp → … → TOperationDescriptor).
4.2 Переопределение унаследованного члена
Внутри тела типа можно написать две разные вещи, и различие между ними принципиально:
<SCType ID="Name" type="...">— объявляет новый член с именемName.<Name ... />— переопределяет унаследованный член с именемName. Тег и есть имя члена; вы не повторяетеtype, а лишь заново указываете атрибуты, которые хотите изменить.
<SCType ID="ZCleanup" type="TZCleanup" Caption="Cleanup height">
<!-- переопределяем значения по умолчанию унаследованных членов: -->
<Enabled DefaultValue="True"/>
<Height DefaultValue="2"/>
</SCType>
(реальный пример: Operations/MillOperations/FaceMillingOp.xml)
Переопределения могут затрагивать вложенные члены и даже варианты перечислений. Шаблон
<EnumItem Visible="True"/> снова включает вариант, скрытый базовым типом:
<CirclesDivision DefaultValue="Halves">
<AbsQuadrants Visible="True"/> <!-- показать вариант, скрытый базой -->
<AbsHalves Visible="True"/>
</CirclesDivision>
(реальный пример: Machines/AbstractMachine.xml)
4.3 Значения по умолчанию: метрика и дюймы
Числовые свойства могут объявлять два значения по умолчанию: DefaultValue для метрической
системы и InchDefaultValue для дюймовой. Система выбирает нужное в соответствии с активной
системой единиц — это независимые значения, а не автоматический пересчёт единиц, поэтому
задавайте каждое разумным круглым числом.
<SCType ID="Outer" type="Double" DefaultValue="0.02" InchDefaultValue="0.001"
DimensionKind="Linear"/>
(реальный пример: Operations/AbstractOP.xml)
5 Массивы
Array (или предопределённый DynamicArray) хранит переменное число элементов одного типа.
Шаблон элемента объявляется как единственный потомок массива:
<SCType ID="TStringList" Caption="List of strings" type="Array">
<SCType ID="L" Caption="Line" type="String" DefaultValue=""/>
</SCType>
Для массивов, элементам которых нужна устойчивая идентичность (чтобы приложение могло
сопоставлять элементы между правками), задайте в CollectionKeyField имя члена, хранящего
ключ:
<SCType ID="List" type="Array" CollectionKeyField="Name">
<SCType ID="Script" type="TScript"/>
</SCType>
(реальный пример: Operations/AbstractOP.xml)
Внутри элемента массива текущий индекс доступен выражениям через Attribute(ItemIndex), что
удобно для автонумеруемых подписей (см. язык выражений):
<SCType ID="J23ValuePair" Caption="Point [Attribute(ItemIndex)]" type="TJ23ValuePair"/>
6 SCProperty — глобальные именованные свойства
Если SCType объявляет шаблоны, то SCProperty объявляет именованное глобальное
свойство: одиночное адресуемое значение или объект на уровне пространства имён. Они работают
как общие константы/объекты, на которые выражения в других местах могут ссылаться по имени.
<SCProperty ID="MetricMeasurementsSystem" type="TMeasurementsSystem">
<LinearUnits DefaultValue="Millimeters"/>
<CuttingSpeedUnits DefaultValue="MetersPerMinute"/>
</SCProperty>
<!-- вычисляемая глобальная строка, берущая значение из другого глобального свойства -->
<SCProperty ID="LinearUnits$" type="String"
DefaultValue="[CurrentMeasurementsSystem.LinearUnits.EnumValue.Attribute(Caption)]"/>
(реальный пример: CommonTypes.xml)
Соглашение об именовании с
$. Завершающий$вIDсвойства (например,LinearUnits$) — это соглашение, помечающее производное строковое свойство для отображения.$— просто часть имени; для парсера он не имеет особого значения.
7 Файловые переменные
Ссылки на файлы — как цели <SCInclude>, так и атрибуты вроде ImageFile, Icon,
SPPFile — используют подстановки $(VARIABLE) вместо абсолютных путей. Они разрешаются во
время выполнения относительно установки и профиля пользователя.
| Переменная | Во что разрешается (обычно) |
|---|---|
$(SUPPLEMENT_FOLDER) |
<корень установки>\Supplement |
$(MACHINES_FOLDER) |
пользовательская …\Machines |
$(SCHEMAS_FOLDER) |
$(MACHINES_FOLDER)\Schemas |
$(OPERATIONS_FOLDER) |
пользовательская …\Operations |
$(LOCAL_OPERATIONS_FOLDER) |
локальная папка операций пользователя |
$(COMMON_CONTAINERS_FOLDER) |
общая папка контейнеров/расширений |
$(PROGRAM_PERSONAL) |
пользовательские данные программы |
Всегда используйте эти переменные вместо жёстко прописанных путей, чтобы ваши файлы продолжали работать независимо от того, куда установлен продукт и какой профиль пользователя активен.
8 Каталог атрибутов
Атрибуты, заданные на SCType / SCProperty, делятся на две группы. Небольшой набор
основных атрибутов понимает сам загрузчик дескрипторов; всё остальное — потребительские
атрибуты, которые переносятся вместе с дескриптором и интерпретируются интерфейсом, движком
или конкретным презентером. С точки зрения автора и те, и другие — «просто атрибуты»; таблица
ниже поясняет назначение каждого.
Логические атрибуты принимают буквальный текст True / False (регистр не важен).
8.1 Идентичность и тип
| Атрибут | Значение | Смысл |
|---|---|---|
ID |
имя | Имя члена/типа. Обязательно в объявлениях. |
type / Type |
имя типа | Тип значения — встроенный или ранее объявленный тип. |
Caption |
строка / выражение | Человекочитаемая подпись, показываемая в интерфейсе. Может вычисляться. |
Version |
целое | Версия схемы типа; увеличивайте её при изменении структуры, чтобы старые сохранённые данные мигрировали. |
Obsolete |
лог. | Помечает член как устаревший; сохраняется для совместимости, обычно скрыт. |
8.2 Значения и единицы
| Атрибут | Значение | Смысл |
|---|---|---|
DefaultValue |
литерал / выражение | Значение по умолчанию (метрика). Для перечислений — ID варианта по умолчанию. |
InchDefaultValue |
литерал / выражение | Значение по умолчанию при активной дюймовой системе единиц. |
DimensionKind |
см. ниже | Физическая размерность числового значения, чтобы интерфейс показывал единицы и корректно пересчитывал. |
UnitsChar |
строка / выражение | Явная подпись единицы для отображения (например, ml/s или [TimeUnits_Sec$]). |
Значения DimensionKind: None, Linear, InverseLinear, Angular, Feedrate,
CuttingSpeed, Revolution. Используйте None для безразмерных чисел и компонентов
направления; Linear для расстояний; Angular для углов.
8.3 Состояние и поведение
| Атрибут | Значение | Смысл |
|---|---|---|
Enabled |
лог. / выражение | Активно/редактируемо ли свойство. False делает его серым (недоступным). |
Visible |
лог. / выражение | Показывается ли строка. Управляйте этим из других свойств для динамических форм. |
ReadOnly |
лог. | Значение показывается, но не редактируется. |
EnabledValue |
имя члена | Для логического члена‑«переключателя»: указывает соседний член, который он включает при значении true (используется с Compact). |
IsStructural |
лог. | Изменение этого значения меняет структуру объекта (вызывает перестроение, а не простое обновление значения). |
IsDynamic |
лог. | Подпись/иконка члена вычисляется для каждого экземпляра (например, элементы массива, которые сами себя именуют). |
8.4 Отображение и группировка
| Атрибут | Значение | Смысл |
|---|---|---|
Category |
id категории | Назначает свойство в категорию/вкладку инспектора (например, TPropertiesCategoryList.Feeds). |
Parent |
имя члена | Переподчиняет эту строку другому члену в дереве инспектора, независимо от порядка объявления. |
Priority / Order |
целое | Порядок сортировки строки внутри её группы/категории в инспекторе (бóльший Priority всплывает выше). Для размещения в меню новой операции используйте MultiGroup + OrderInGroup (см. Дескрипторы операций). |
Expanded |
лог. | Развёрнута ли составная строка изначально в дереве. |
Compact |
лог. | Сворачивает составной тип в одну строку инспектора (см. §9). |
Transparent |
лог. | Сам контейнер не показывается; видны только его потомки (чисто группирующая обёртка). |
Text |
строка / выражение | Сводный текст, показываемый для свёрнутой составной строки. |
ImageFile |
путь | Иконка строки (используйте файловую переменную $(…)). |
8.5 Редакторы / презентеры
Эти атрибуты подключают к свойству специализированный редактор или отрисовщик. Значение — зарегистрированное имя презентера, предоставляемого приложением; вы ссылаетесь на него, но не определяете его.
| Атрибут | Смысл |
|---|---|
EnumPresenter |
Пользовательский выпадающий список/селектор для строки (выбор инструмента, выбор магазина, …). |
BtnPresenter |
Отображает строку как кнопку действия (например, «Нажмите, чтобы вычислить»). |
VisPresenter / CaptionPresenter |
Пользовательский отрисовщик значения/подписи. |
IsRadioEdit / RadioEditValue |
Объединяет перечисление с соседними членами‑значениями в одну строку (см. §9). |
Filter / CustomDialogID |
Для свойств с именем файла: фильтр файлового диалога / пользовательский диалог. |
8.6 Массивы и интеграция
| Атрибут | Смысл |
|---|---|
CollectionKeyField |
Член, однозначно идентифицирующий элемент массива. |
CollectionValueField |
Член, хранящий полезное значение элемента. |
Optional |
На <SCInclude>: загружать только если файл существует. |
ClassName / ClassGUID / InterfaceName / InterfaceGUID |
Привязывают свойство к COM‑объекту/интерфейсу, который приложение для него создаёт. Продвинутое; редко нужно в рукописных дескрипторах. |
Неизвестные атрибуты сохраняются, а не отвергаются. Если вы зададите атрибут, который загрузчик не распознаёт, он сохраняется на дескрипторе и доступен потребителям и API. Это сделано намеренно — именно так презентеры получают свои параметры (например,
AxisIdx,HolderType). Это также означает, что опечатка в имени известного атрибута проходит молча, поэтому перепроверяйте написание и регистр.
9 Строки Compact и radio-edit
В реальных дескрипторах постоянно встречаются два приёма отображения; их стоит понять, потому что они меняют то, как несколько членов отображаются в одной строке инспектора.
Compact
Compact="True" на составном типе сворачивает его в одну строку инспектора: первый
видимый потомок поднимается рядом с подписью родителя. Классическая форма — флаг Enabled
плюс значение, которое он включает, связанные через EnabledValue:
<SCType ID="SmoothCorners" type="ComplexType" Compact="True">
<SCType ID="Enabled" type="Boolean" DefaultValue="True" EnabledValue="Radius"/>
<SCType ID="Radius" type="TPercentageValue" Visible="False">
<PercentValue DefaultValue="25"/>
</SCType>
</SCType>
(реальный пример: Operations/MillOperations/FaceMillingOp.xml)
Пользователь видит одну строку «Smooth corners» с флажком и значением.
Radio edit
IsRadioEdit="True" на перечислении объединяет его с соседними членами‑значениями в одну
строку, где выбор перечисления определяет, какой сосед активен. Каждый вариант перечисления
указывает на своего соседа через RadioEditValue:
<SCType ID="ReferenceType" type="Enumerated" IsRadioEdit="True">
<SCType ID="Angle" Caption="(degrees)" type="none" RadioEditValue="Angle"/>
<SCType ID="Linear" Caption="[LinearUnits$]" type="none" RadioEditValue="Linear"/>
</SCType>
<SCType ID="Angle" type="Double" DefaultValue="5" Visible="False" DimensionKind="Angular"/>
<SCType ID="Linear" type="Double" DefaultValue="50" Visible="False" DimensionKind="Linear"/>
(реальный пример: Machines/AbstractMachine.xml)
Далее: Язык выражений