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

ADR 0012: Плавающий и отцепляемый хром workspace (к нижней зоне и ситуационной осведомлённости)

Статус: Accepted (направление; объём v1 и конкретные контролы — по итерациям)
Дата: 2026-04-02

Связанные ADR

ADR Роль
0011 осведомлённость без раздувания низа
0010 пресеты и workspace.toml
0006 границы VM/UI
0013 см. [раздел «Разделение с 0013»](#scope-split-0013

Разделение с 0013

  • 0012 (этот ADR) — размещение и плавающий хром workspace.
  • 0013 — поверхность команд: как пользователь вызывает действия и как обеспечивается discoverability без раздувания toolbar.

Контекст

Flight (актуально): длинные потоки терминала, сборки и Git — страницы колонки MFD (MfdShellPageStack внутри MfdShellView, регион для снимков MfdContourStackHost). Ниже — описание исторического макета с полной шириной нижней зоны для той же продуктовой боли (бюджет высоты vs редактор).

В старой топологии нижняя часть главного окна была задана жёсткой сеткой MainWindow: строка с полосой IDE Health (сводка сборки/тестов/отладки/git — канал IDE Health), сплиттер и BottomPanelView (терминал, сборка, отладка, git и т.д.) занимали один вертикальный слой (MainGrid row 5, внутренние строки Auto / сплиттер / *). Полоса IDE Health (IdeHealthStripView) физически над вкладками низа и не плавает — она привязана к той же колоночной разметке, что и рабочая область.

Следствие: любой ситуационный или короткий UI (статус, полоса IDE Health, будущая компактная полоска отладки из 0011) оказывается в одном бюджете высоты с длинным выводом (лог, терминал). Поднять низ, чтобы что-то увидеть, — значит отдать пиксели редактору; это уже зафиксировано как продуктовая боль.

Отдельно: в разметке документов явно заложено одно окно доков без floating (DocumentsDockView — комментарий в XAML). Это не тот же класс задач, что хром вокруг редактора; смешивать в одном решении опасно по объёму.

Верхняя полоса команд (toolbar: «Открыть решение» и соседние действия) сейчас длинная и смешанная по смыслу — та же перегрузка фиксированного хрома, что и низ, только по горизонтали: много кнопок в одной линейке без явного разделения по задачам.

Решение

1. Направление продукта: переносить вторичный и ситуационный хром workspace к модели плавающих / отцепляемых панелей (в смысле: не обязаны жить в фиксированной строке MainGrid и конкурировать с высотой редактора). Пользователь может держать полоску у края экрана, на втором мониторе или поверх — в пределах реализуемой модели окна (см. п. 3).

2. Первые кандидаты на вынос из жёсткой нижней колонки (приоритет): - IDE Health (IdeHealthStripView и логически родственное «узкое» состояние), в старом макете застрявшие над BottomPanelView в одной нижней ячейке. - Далее — компактные полоски состояния (в т.ч. отладка из 0011), чтобы не дублировать их только в нижнем доке.

3. Механика (направление, не привязка к одному контролу Avalonia в этом ADR): - допустимы внутренние плавающие слои (overlay, Popup, панель с drag в клиентской области) и/или отдельные окна (Window / tool-window стиль) — выбор по итерации: доступность, мультимонитор, Alt+Tab, сохранение позиций. - Сохранение геометрии новых плавающих элементов — в общем потоке настроек workspace (0010: глобальные метрики и при необходимости расширение), без отдельного «тихого» хранилища только для одной полоски, если можно унифицировать.

4. Что остаётся привязанным к доку в v1 направления: длинный поток вывода (терминал, журнал сборки, развёрнутый список locals/stack) — разумный дом для нижней панели с вкладками; цель ADR — не уничтожить её, а не заставлять короткий статус и полосу IDE Health обязательно делить с ней одну ось высоты.

5. Документы (редакторы) как floating MDI: вне объёма этого ADR. Отдельное обсуждение/ADR, если появится продуктовая необходимость; текущий комментарий в XAML остаётся фактом до тех пор.

6. Связь с режимами UI: пресеты режимов (0010) могут задавать видимость и слот плавающего хрома (например в Debug показывать полоску отладки по умолчанию, в Focus — свернуть полосу IDE Health в иконку), не переписывая всю схему MainGrid под каждый режим.

7. Панели инструментов (toolbars): верхняя и прочие полосы с кнопками — тот же класс разгрузки, что и плавающий хром: скрываемость (целиком полосу или по группам/категориям), разбиение по категориям (например: файл/решение, сборка, отладка, вид, агент — состав групп уточняется по UX), вместо одной длинной смешанной линейки. Видимость групп может пересекаться с режимами UI (0010). Пока toolbars живут внутри MainWindow, для MCP это то же дерево — паритет без расширения контракта; отдельное окно только под toolbar — по тем же правилам, что в разделе «Связь с MCP». Сколько команд держать на полосе и как обеспечивать discoverability (палитра; ситуационные чеклисты — 0014) — см. 0013, не дублировать здесь.

Связь с MCP и корнем UI (агент)

Паритет человек/агент для автоматизируемого UI (0002) здесь не оспаривается: отдельное окно не «освобождает» от доступа агента — наоборот, требует довести контракт до нескольких корней, иначе паритет нарушен.

Снимок лэйаута ide_get_ui_layout строится по всем окнам верхнего уровня процесса: JSON с массивом windows (у каждого элемента role, window_type, title, is_active, root — дерево контролов с bounds относительно этого окна). Второй TopLevel под зону Mfd (MfdHostWindow, role = mfd_host) и прочие Window входят в ответ. Действия по имени контрола (ide_set_control_text, ide_click_control, ide_set_focus, ide_get_control_appearance и т.д.) ищут имя сначала в главном окне, затем в остальных — паритет с человеком, который видит оба экрана.

Варианты п. 3:

  • Плавающий хром внутри клиентской области (overlay, Popup, drag в пределах MainWindow) — то же дерево внутри соответствующего root.
  • Вынесение хрома в отдельное окно — удобно для мультимонитора и Alt+Tab; дерево этого окна попадает в ide_get_ui_layout как отдельный элемент windows[]. Уточнения контракта при новых типах окон — см. 0008 (контракт, тесты).

Это не запрещает отдельные окна в продукте и не отменяет п. 5 (floating MDI доков — отдельная тема).

Последствия

  • Потребуется миграция лэйаута: вынести часть содержимого из вложенной сетки row 5 в отдельный слой или окно, не ломая биндинги VM и единый слой отладки (0002).
  • При выборе отдельного окна для хрома — базовый мульти-TopLevel в MCP (ide_get_ui_layout, поиск контрола по имени по всем окнам) уже есть; новые сценарии могут потребовать уточнения контракта в scope поставки вместе с фичей (см. «Связь с MCP», 0008).
  • Тесты и MCP, которые опираются на имена регионов / скриншоты UI, могут потребовать обновления при смене дерева визуального дерева.
  • Документация для пользователя (позже): как «прикрепить обратно», где сохраняется позиция.

Отклонённые альтернативы (как финальное состояние)

  • Оставить весь хром навсегда в фиксированной нижней сетке — отклонено как противоречащее цели осведомлённости без постоянной потери высоты редактора (0011).
  • Сразу сделать floating всё, включая доки — отклонено как слишком дорого и не требуется для решения конфликта «полоска vs лог».

Обсуждение (открытые вопросы для следующих итераций)

  • Overlay vs отдельное окно для первой полоски: что даёт меньше сюрпризов на Windows с несколькими мониторами; при отдельном окне дерево уже видно в ide_get_ui_layout, остаётся продуктовый выбор и при необходимости точечные доп. поля в контракте.
  • Один универсальный «контейнер для плавающих островов» vs отдельные окна на каждый тип хрома.
  • Как не размножить дубли IDE Health (полоска в Power и узкий режим) — одна модель данных, разные представления.
  • Toolbar: состав категорий и что по умолчанию видно в Power / Focus / Debug; не раздувать число отдельных полос без нужды.