| 1 | using CascadeIDE.Cockpit.Cds; |
| 2 | using CascadeIDE.Features.UiChrome; |
| 3 | using CascadeIDE.Services.Presentation; |
| 4 | |
| 5 | namespace CascadeIDE.ViewModels; |
| 6 | |
| 7 | /// <summary>ADR 0017: строка <c>presentation</c> и второй <c>TopLevel</c> — <see cref="Views.MfdHostWindow"/> с полным вторичным контуром (п. 8).</summary> |
| 8 | public partial class MainWindowViewModel |
| 9 | { |
| 10 | /// <summary>Строка <c>presentation</c> с учётом оверлеев — та же, что уходит в <see cref="PresentationParse"/>.</summary> |
| 11 | public string EffectivePresentationLine => _settings.GetEffectivePresentationLine(); |
| 12 | |
| 13 | /// <summary>Успешный разбор <see cref="CascadeIdeSettings.GetEffectivePresentationLine"/> (может быть пустой список экранов).</summary> |
| 14 | public PresentationParseResult PresentationParse => _presentationParse; |
| 15 | |
| 16 | /// <summary> |
| 17 | /// Колонки рабочей строки <c>MainGrid</c> (строка для Avalonia <c>ColumnDefinitions</c>). |
| 18 | /// При заданных весах якорей в <c>presentation</c> — доли <c>*</c> по ADR 0017; иначе дефолт <see cref="PresentationMainGridColumnDefinitions.Default"/>. |
| 19 | /// </summary> |
| 20 | public string MainGridColumnDefinitions => MainGridLayoutFrame.ColumnDefinitions; |
| 21 | |
| 22 | /// <summary>Кадр геометрии P/F/M для строки <c>MainGrid</c> (v1: колонка, число зон, нормализованные доли).</summary> |
| 23 | public PresentationMainGridLayoutFrame MainGridLayoutFrame |
| 24 | { |
| 25 | get |
| 26 | { |
| 27 | if (IsCompactPresentationTier) |
| 28 | { |
| 29 | return PresentationCompactMainGridLayoutBuilder.BuildWithRightChromeWidth( |
| 30 | CompactRightChromeColumnPixelWidth, |
| 31 | UiWorkspaceLayoutRuntimeMetrics.MfdRegionCollapsedWidthPixels); |
| 32 | } |
| 33 | |
| 34 | if (UsesUltrawideCockpitLayout) |
| 35 | { |
| 36 | return PresentationUltrawideCockpitLayoutBuilder.Build( |
| 37 | _presentationMonitorSnapshot.PrimaryWorkingAreaWidthPx, |
| 38 | _settings.Display.Presentation.CockpitMinAnchorWidthPx, |
| 39 | _suppressPfdColumnForPfdHostWindow, |
| 40 | _suppressMfdColumnForMfdHostWindow); |
| 41 | } |
| 42 | |
| 43 | return PresentationMainGridLayoutFrameBuilder.Build( |
| 44 | _presentationParse, |
| 45 | _presentationDedicatedMfdSecondScreen, |
| 46 | _suppressMfdColumnForMfdHostWindow, |
| 47 | _presentationTripleOneAnchorPerZone, |
| 48 | _suppressPfdColumnForPfdHostWindow, |
| 49 | PresentationLayoutAnalyzer.GetMainWindowPresentationScreenIndexOrDefault(_presentationParse)); |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | /// <summary> |
| 54 | /// Пресет требует развернуть главное окно на весь экран при старте — см. |
| 55 | /// <see cref="PresentationLayoutAnalyzer.ShouldMaximizeMainWindowAtStartup"/>. |
| 56 | /// </summary> |
| 57 | public bool PresentationRequestsMainWindowMaximized => |
| 58 | _presentationParse.IsSuccess |
| 59 | && PresentationLayoutAnalyzer.ShouldMaximizeMainWindowAtStartup(_presentationParse.Screens); |
| 60 | |
| 61 | /// <summary>Пресет «первый экран — PFD+Forward без MFD, второй — только MFD».</summary> |
| 62 | public bool PresentationRequestsDedicatedMfdSecondScreen => _presentationDedicatedMfdSecondScreen; |
| 63 | |
| 64 | /// <summary>Три дисплея: по одному якорю — <c>(P) (F) (M)</c> в любом порядке групп (ADR 0017).</summary> |
| 65 | public bool PresentationRequestsTriplePfdForwardMfd => _presentationTripleOneAnchorPerZone; |
| 66 | |
| 67 | /// <summary>Пресет «три экрана по одной зоне» — требуются отдельные хосты PFD и MFD вместе с main (ADR 0017).</summary> |
| 68 | public bool PresentationRequestsPfdHostWindow => _presentationTripleOneAnchorPerZone; |
| 69 | |
| 70 | /// <summary>Пресет с выносом MFD на отдельный <c>TopLevel</c> (два или три дисплея по строке <c>presentation</c>).</summary> |
| 71 | public bool PresentationRequestsMfdHostWindow => _presentationMfdHostTopology; |
| 72 | |
| 73 | /// <summary>Пресет <c>(xP+yM)(F)</c> / <c>(F)(xP+yM)</c> — отдельное окно сплита P+M (ADR 0017).</summary> |
| 74 | public bool PresentationRequestsPmSplitHostWindow => _presentationPmHostTopology; |
| 75 | |
| 76 | /// <summary> |
| 77 | /// Индекс дисплея для окна сплита P+M в порядке <see cref="PresentationMonitorTopology.OrderScreensForPresentation"/>. |
| 78 | /// </summary> |
| 79 | public int? PmSplitHostPresentationScreenIndex => |
| 80 | _presentationParse.IsSuccess |
| 81 | && PresentationLayoutAnalyzer.TryGetPmSplitHostPresentationScreenIndex(_presentationParse.Screens, out var idx) |
| 82 | ? idx |
| 83 | : null; |
| 84 | |
| 85 | /// <summary>Индекс группы <c>presentation</c> для главного окна (лобовое); для <c>(xP+yM)(F)</c> — экран с <c>F</c>.</summary> |
| 86 | public int MainWindowPresentationScreenIndex => |
| 87 | PresentationLayoutAnalyzer.GetMainWindowPresentationScreenIndexOrDefault(_presentationParse); |
| 88 | |
| 89 | /// <summary>Колонки <c>Grid</c> окна сплита P+M (строка для <c>ColumnDefinitions.Parse</c>).</summary> |
| 90 | public string PmSplitHostColumnDefinitions => |
| 91 | _presentationParse.IsSuccess && PmSplitHostPresentationScreenIndex is int pmIdx |
| 92 | ? PresentationPmSplitHostColumnBuilder.Build(_presentationParse, pmIdx) |
| 93 | : PresentationPmSplitHostColumnBuilder.Build(_presentationParse, 0); |
| 94 | |
| 95 | /// <summary>Строка <c>presentation</c> задаёт <c>(xP+yM)(F)</c> — выровнять главное окно по экрану с <c>F</c> (см. <see cref="MainWindowPresentationScreenIndex"/>).</summary> |
| 96 | public bool PresentationRequestsPmSplitMainWindowScreenPlacement => _presentationPmForwardTwoScreen; |
| 97 | |
| 98 | /// <summary>Открывать <see cref="Views.PmSplitHostWindow"/> при старте при подходящей топологии.</summary> |
| 99 | public bool OpenPmSplitHostWindowOnStartup => _settings.OpenPmSplitHostWindowOnStartup; |
| 100 | |
| 101 | /// <summary> |
| 102 | /// Индекс физического дисплея для <see cref="Views.MfdHostWindow"/> в порядке |
| 103 | /// <see cref="PresentationMonitorTopology.OrderScreensForPresentation"/>; <c>null</c> если строка не задаёт семантику хоста. |
| 104 | /// </summary> |
| 105 | public int? MfdHostPresentationScreenIndex => |
| 106 | _presentationParse.IsSuccess |
| 107 | && PresentationLayoutAnalyzer.TryGetMfdHostPresentationScreenIndex(_presentationParse.Screens, out var idx) |
| 108 | ? idx |
| 109 | : null; |
| 110 | |
| 111 | /// <summary> |
| 112 | /// Индекс дисплея для <see cref="Views.PfdHostWindow"/> в порядке |
| 113 | /// <see cref="PresentationMonitorTopology.OrderScreensForPresentation"/>; <c>null</c> если строка не задаёт семантику хоста. |
| 114 | /// </summary> |
| 115 | public int? PfdHostPresentationScreenIndex => |
| 116 | _presentationParse.IsSuccess |
| 117 | && PresentationLayoutAnalyzer.TryGetPfdHostPresentationScreenIndex(_presentationParse.Screens, out var pIdx) |
| 118 | ? pIdx |
| 119 | : null; |
| 120 | |
| 121 | /// <summary>Открывать окно-хост Mfd при старте (если есть ≥2 мониторов и пресет подходит).</summary> |
| 122 | public bool OpenMfdHostWindowOnStartup => |
| 123 | IsCockpitPresentationTier && _settings.OpenMfdHostWindowOnStartup; |
| 124 | |
| 125 | /// <summary>Открывать окно-хост Pfd при старте (если мониторов достаточно и пресет тройной).</summary> |
| 126 | public bool OpenPfdHostWindowOnStartup => |
| 127 | IsCockpitPresentationTier && _settings.OpenPfdHostWindowOnStartup; |
| 128 | |
| 129 | /// <summary>Окна <c>PfdHostWindow</c>/<c>MfdHostWindow</c> на своём дисплее — максимизировать (иначе размер по рабочей области).</summary> |
| 130 | public bool MaximizePresentationHostWindowsOnDedicatedScreens => |
| 131 | _settings.MaximizePresentationHostWindowsOnDedicatedScreens; |
| 132 | |
| 133 | /// <summary>Окно-хост Mfd открыло полный вторичный контур — колонка Mfd в главном окне скрыта (см. <see cref="SetMfdHostWindowShellOpen"/>).</summary> |
| 134 | public bool IsMfdHostWindowShellOpen => _suppressMfdColumnForMfdHostWindow; |
| 135 | |
| 136 | /// <summary>Окно-хост Pfd открыто — колонка Pfd в главном окне скрыта (см. <see cref="SetPfdHostWindowShellOpen"/>).</summary> |
| 137 | public bool IsPfdHostWindowShellOpen => _suppressPfdColumnForPfdHostWindow; |
| 138 | } |
| 139 | |