| 1 | using CascadeIDE.Cockpit.Cds; |
| 2 | using CascadeIDE.Models; |
| 3 | using CascadeIDE.Services.Presentation; |
| 4 | |
| 5 | namespace CascadeIDE.Cockpit.Composition.Shell; |
| 6 | |
| 7 | /// <summary> |
| 8 | /// Композитор <b>оболочки</b> главного окна (ADR 0036 п.3): из intent + CDS policy + топологии хоста MFD |
| 9 | /// получает видимость колонок и ширину региона MFD в <c>MainGrid</c> (не дерево контролов, не данные каналов). |
| 10 | /// Полный кадр для хоста (колонки + инструменты слотов) — <c>MainWindowHostSurfaceCompositor</c> в <c>Cockpit/Composition/HostSurface</c>. |
| 11 | /// </summary> |
| 12 | public static class MainWindowShellSurfaceCompositor |
| 13 | { |
| 14 | public static MainWindowShellSurfaceComposition Compose(in MainWindowShellSurfaceCompositionInput input) |
| 15 | { |
| 16 | if (input.EffectivePresentationTier == PresentationTierKind.Compact) |
| 17 | return ComposeCompact(input); |
| 18 | |
| 19 | return ComposeCockpit(input); |
| 20 | } |
| 21 | |
| 22 | private static MainWindowShellSurfaceComposition ComposeCompact(in MainWindowShellSurfaceCompositionInput input) |
| 23 | { |
| 24 | var presentation = input.DisplaySettings.Presentation; |
| 25 | var placement = presentation.CompactIntercomPlacement?.Trim() ?? "side"; |
| 26 | var sideIntercom = !string.Equals(placement, "bottom", StringComparison.OrdinalIgnoreCase); |
| 27 | var chatExpanded = input.IntentChatPanelExpanded && !input.SuppressMfdColumnForMfdHostWindow; |
| 28 | var intercomAuxVisible = sideIntercom && chatExpanded; |
| 29 | var intercomBottomVisible = !sideIntercom && chatExpanded; |
| 30 | |
| 31 | var intercomWidth = intercomAuxVisible |
| 32 | ? Math.Max( |
| 33 | input.CollapsedMfdWidthPixels, |
| 34 | presentation.CompactAuxiliaryPanelWidthPx) |
| 35 | : 0; |
| 36 | |
| 37 | var pfdRightVisible = input.IntentSolutionExplorerVisible |
| 38 | && !input.SuppressPfdColumnForPfdHostWindow; |
| 39 | var pfdRightWidth = pfdRightVisible |
| 40 | ? CompactIdeLayoutMetrics.PfdRightColumnWidthPixels |
| 41 | : 0; |
| 42 | |
| 43 | var rightChromeWidth = Math.Max(intercomWidth, pfdRightWidth); |
| 44 | |
| 45 | return new MainWindowShellSurfaceComposition( |
| 46 | PfdSurfaceVisible: false, |
| 47 | MfdSurfaceExpanded: input.IntentChatPanelExpanded, |
| 48 | MfdColumnVisibleInMainGrid: false, |
| 49 | MfdColumnPixelWidthInMainGrid: 0, |
| 50 | CompactIdeLayout: true, |
| 51 | IntercomAuxColumnVisible: intercomAuxVisible, |
| 52 | IntercomAuxColumnPixelWidth: intercomWidth, |
| 53 | IntercomBottomDockVisible: intercomBottomVisible, |
| 54 | IntercomBottomDockHeightPx: presentation.CompactIntercomBottomDockHeightPx, |
| 55 | PfdRightColumnVisible: pfdRightVisible, |
| 56 | PfdRightColumnPixelWidth: pfdRightWidth, |
| 57 | CompactRightChromeColumnVisible: intercomAuxVisible || pfdRightVisible, |
| 58 | CompactRightChromeColumnPixelWidth: rightChromeWidth, |
| 59 | MfdBottomDockHeightPx: presentation.CompactMfdBottomDockHeightPx); |
| 60 | } |
| 61 | |
| 62 | private static MainWindowShellSurfaceComposition ComposeCockpit(in MainWindowShellSurfaceCompositionInput input) |
| 63 | { |
| 64 | var tier = input.EffectivePresentationTier; |
| 65 | var presentationSpecifiesScreens = input.PresentationParse.IsSuccess && input.PresentationParse.Screens.Count > 0; |
| 66 | var pfdRequiredOnMain = !presentationSpecifiesScreens |
| 67 | || CockpitPresentationLayoutPolicy.RequiresPfdRegionInMainWindow(input.PresentationParse, tier); |
| 68 | var pfdCoerced = CockpitPresentationLayoutPolicy.CoercePfdRegionExpanded( |
| 69 | input.PresentationParse, |
| 70 | tier, |
| 71 | input.IntentSolutionExplorerVisible); |
| 72 | var pfdVisible = pfdRequiredOnMain && pfdCoerced && !input.SuppressPfdColumnForPfdHostWindow; |
| 73 | |
| 74 | var mfdRequiredOnMain = !presentationSpecifiesScreens |
| 75 | || CockpitPresentationLayoutPolicy.RequiresMfdRegionInMainWindow(input.PresentationParse, tier); |
| 76 | var mfdExpanded = CockpitPresentationLayoutPolicy.CoerceMfdRegionExpanded( |
| 77 | input.PresentationParse, |
| 78 | tier, |
| 79 | input.IntentChatPanelExpanded); |
| 80 | |
| 81 | var mfdColumnInMain = mfdRequiredOnMain && !input.SuppressMfdColumnForMfdHostWindow && mfdExpanded; |
| 82 | |
| 83 | var width = mfdColumnInMain |
| 84 | ? (mfdExpanded ? input.ExpandedMfdWidthPixels : input.CollapsedMfdWidthPixels) |
| 85 | : 0; |
| 86 | |
| 87 | return new MainWindowShellSurfaceComposition( |
| 88 | PfdSurfaceVisible: pfdVisible, |
| 89 | MfdSurfaceExpanded: mfdExpanded, |
| 90 | MfdColumnVisibleInMainGrid: mfdColumnInMain, |
| 91 | MfdColumnPixelWidthInMainGrid: width); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | /// <summary>Вход композитора: intent пользователя, пресет, подавление колонок PFD/MFD в main при открытых хостах, числа ширин из UI-режима.</summary> |
| 96 | public readonly record struct MainWindowShellSurfaceCompositionInput( |
| 97 | PresentationParseResult PresentationParse, |
| 98 | bool IntentSolutionExplorerVisible, |
| 99 | bool IntentChatPanelExpanded, |
| 100 | bool SuppressPfdColumnForPfdHostWindow, |
| 101 | bool SuppressMfdColumnForMfdHostWindow, |
| 102 | int ExpandedMfdWidthPixels, |
| 103 | int CollapsedMfdWidthPixels, |
| 104 | DisplaySettings DisplaySettings, |
| 105 | string SafetyLevel, |
| 106 | PresentationTierKind EffectivePresentationTier = PresentationTierKind.Cockpit); |
| 107 | |
| 108 | /// <summary>Результат: что отдать слою поверхности (привязки VM / code-behind) для колонок PFD/MFD.</summary> |
| 109 | public readonly record struct MainWindowShellSurfaceComposition( |
| 110 | bool PfdSurfaceVisible, |
| 111 | bool MfdSurfaceExpanded, |
| 112 | bool MfdColumnVisibleInMainGrid, |
| 113 | int MfdColumnPixelWidthInMainGrid, |
| 114 | bool CompactIdeLayout = false, |
| 115 | bool IntercomAuxColumnVisible = false, |
| 116 | int IntercomAuxColumnPixelWidth = 0, |
| 117 | bool IntercomBottomDockVisible = false, |
| 118 | int IntercomBottomDockHeightPx = CompactIdeLayoutMetrics.IntercomBottomDockDefaultHeightPixels, |
| 119 | bool PfdRightColumnVisible = false, |
| 120 | int PfdRightColumnPixelWidth = 0, |
| 121 | bool CompactRightChromeColumnVisible = false, |
| 122 | int CompactRightChromeColumnPixelWidth = 0, |
| 123 | int MfdBottomDockHeightPx = 220); |
| 124 | |