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; не раздувать число отдельных полос без нужды.