Перейти к содержанию

ADR 0064: Виды индикаторов deck — визуальный язык, отрисовка и семантическая палитра

Статус: Accepted
Дата: 2026-04-19

Связанные ADR

ADR Роль
0063 § типы DeckPrimitiveKind, Presence / Dark Cockpit
0055 Стадия Render pipeline
0021 Dark Cockpit
0046 Инварианты layout
0066 Палитра кабины vs хром IDE

Резюме

  • Виды индикаторов deck: единая отрисовка + семантическая палитра.
  • DeckPrimitiveKind — каталог видов; без лишнего архитектурного слоя.

Код: Cockpit/PrimitivesKit/ — annunciator, лампы, токены semantic map.


Контекст

В 0063 § типы индикаторов зафиксирована продуктовая таксономия видов индикаторов: Lamp, Bar, Sign, Readout и т.д. — форма сигнала в ячейке deck или фрагменте Skia-инструмента.

Параллельно в коде и разговорах смешиваются разные смыслы (раньше их связывали со словом «примитив»):

  1. Вид индикатора — что показать оператору на уровне смысла: «лампа такого класса», «полоса отклонения», «краткая маркировка».
  2. Операции низкоуровневой графики — линия, заливка, FormattedText в DrawingContext / команды Skia.
  3. Токены сцены / метрики — viewport, шаг сетки, отступы целого инструмента (например semantic map); это не строка в DeckPrimitiveKind, а общие константы компоновки.

Без явного разделения команды и фичи дублируют цвета и геометрию в XAML, в VM и в отрисовке: внимание уходит на соревнование оттенков и «новогоднюю ёлку», а не на задачу и иерархию состояний (0021 §6). Нужен норматив: один визуальный язык на вид индикатора и одна библиотека отрисовки, которая его реализует.


Решение

1) Виды индикаторов — высокоуровневые и с единым графическим воплощением

Вид индикатора в смысле 0063 — это атомарный glance: данные для UI формулируются как какой вид (DeckPrimitiveKind и профиль состояния) плюс минимальная полезная нагрузка (текст легенды, уровень серьёзности, число для readout и т.д.), а не как «нарисуй прямоугольник #rrggbb».

Инвариант: для каждого сочетания вид индикатора + семантика состояния (например Lamp + «ок / предупреждение / недоступно») в продукте существует ровно одно согласованное графическое воплощение в кабине (форма, толщина рамки, типографика подписи, семантический цвет — см. п. 3). Произвольное умножение вариантов «на вкус разработчика экрана» не допускается: иначе оператор тратит внимание на стиль, а не на состояние.

Фичи и deck-композиторы передают в библиотеку отрисовки семантику вида, а не набор низкоуровневых операций графики.

2) Библиотека отрисовки видов индикаторов (общий контур с 0055)

Чтобы инвариант из п. 1 соблюдался в коде, используется общая библиотека отрисовки (в репозитории — Cockpit/PrimitivesKit/ и стадия Render по 0055):

  • для каждого поддерживаемого вида (или узкого семейства, например annunciator Lamp) — одна реализация «как нарисовать»: функции/типы, принимающие DrawingContext (и при необходимости границы), без дублирования логики в контролах и инструментах;
  • для Skia-пайплайна тот же контракт мыслится как набор инструкций отрисовки той же семантики, без копипасты цветов и метрик из Avalonia-XAML.

Граница: библиотека отрисовки не подменяет композитор инструмента (Intent → Declutter → Layout) и не задаёт бизнес-логику; она только реализует согласованный вид по входным семантическим параметрам.

Имя папки PrimitivesKit — собирательное; см. лексикон и п. 4 про метрики целой сцены.

3) Единый цветовой язык (семантическая палитра)

Цвет в кабине для индикаторов deck и инструментов читается как смысл (уровень готовности, серьёзность отклонения, информационность), а не как украшение.

Инварианты:

  • палитра задаётся семантическими ролями (например «штатно», «внимание», «инфо», «недоступно»), а не произвольными hex в каждой фиче;
  • согласование с Dark Cockpit (0021, 0063 § Presence): в норме не размножать яркие пиксели и анимацию «для красоты»;
  • при необходимости a11y (не только цвет) — расширения той же семантики (иконка, штриховка), а не отдельная «вторая палитра» без правил.

Конкретные значения токенов могут жить в теме/ресурсах, но маппинг «роль → отображение» остаётся единым и согласованным с слоем из п. 2. Соответствие EICAS W/C/A бытовым «Error / Warning / Information» и AnnunciatorLampLevel — таблица в 0021 §5.

4) Вид индикатора vs токены целой сцены

Вид индикатора и граница с инструментом — см. 0063 § примитив vs инструмент (термин «примитив» там — исторический заголовок раздела; по смыслу это вид индикатора vs инструмент).

Метрики / токены компоновки (viewport инструмента, шаг уровней графа, паддинги сцены) — не виды индикаторов deck; в коде допустимы имена вроде layout tokens, instrument geometry, чтобы не путать с DeckPrimitiveKind.


Не-цели (текущая фаза)

  • Зафиксировать полный публичный контракт API отрисовки для сторонних плагинов (0063 открытые вопросы).
  • Вынести всю палитру кабины в один TOML без стабилизации темы.
  • Запретить исключения: локальные эксперименты за флагом возможны, но не задают второй «канон» без пересмотра ADR.

Последствия

  • Продуктовые обсуждения и ревью опираются на цепочку: вид индикатораединая отрисовка (п. 2) → композиция в инструменте/deck — без лишнего промежуточного «слоя» в архитектуре.
  • Дублирование цветов/геометрии ламп, readout и т.д. считается техническим долгом, пока не перенесено в библиотеку п. 2 и не привязано к палитре п. 3.
  • В тексте предпочтительны вид индикатора / форма сигнала; слово «примитив» — только при ссылке на имя DeckPrimitiveKind или цитировании старых разделов 0063.

Альтернативы (кратко)

Вариант Минус
Только гайдлайны в Markdown без ADR Нет стабильной ссылки в архитектурной политике
Один огромный «theme.json на всё» без слоя отрисовки Семантика размазывается по биндингам, палитра расползается
Запретить любые числа вне PrimitivesKit Жёстко для прототипов; достаточно явного разделения п. 4