using Lattice.Core.Abstractions; using Lattice.Core.Models; using Lattice.Core.Models.Enums; using Microsoft.UI.Composition.SystemBackdrops; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; namespace Lattice.Studio.Controls; /// /// Основная оболочка приложения в стиле Visual Studio 2026. /// Обеспечивает интеграцию нативного заголовка, системы докинга и контекстных команд. /// public sealed partial class LatticeStudioShell : UserControl { private ILayoutService? _layoutService; private IContextService? _contextService; private IEnumerable? _allActions; #region Dependency Properties (Слоты кастомизации) public string Title { get => (string)GetValue(TitleProperty); set => SetValue(TitleProperty, value); } public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(LatticeStudioShell), new PropertyMetadata("Lattice IDE")); public string Subtitle { get => (string)GetValue(SubtitleProperty); set => SetValue(SubtitleProperty, value); } public static readonly DependencyProperty SubtitleProperty = DependencyProperty.Register(nameof(Subtitle), typeof(string), typeof(LatticeStudioShell), new PropertyMetadata(string.Empty)); public IconSource TitleBarIcon { get => (IconSource)GetValue(TitleBarIconProperty); set => SetValue(TitleBarIconProperty, value); } public static readonly DependencyProperty TitleBarIconProperty = DependencyProperty.Register(nameof(TitleBarIcon), typeof(IconSource), typeof(LatticeStudioShell), new PropertyMetadata(null)); public object MenuContent { get => GetValue(MenuContentProperty); set => SetValue(MenuContentProperty, value); } public static readonly DependencyProperty MenuContentProperty = DependencyProperty.Register(nameof(MenuContent), typeof(object), typeof(LatticeStudioShell), new PropertyMetadata(null)); public object StatusContent { get => GetValue(StatusContentProperty); set => SetValue(StatusContentProperty, value); } public static readonly DependencyProperty StatusContentProperty = DependencyProperty.Register(nameof(StatusContent), typeof(object), typeof(LatticeStudioShell), new PropertyMetadata(null)); #endregion public LatticeStudioShell() { this.InitializeComponent(); } /// /// Инициализирует оболочку Studio и связывает её с сервисами Lattice.Core. /// /// Экземпляр ILayoutService для управления окнами. /// Экземпляр IContextService для управления кнопками тулбара. /// Полный список определений команд (ActionDefinition). public void Initialize(ILayoutService layoutService, IContextService contextService, IEnumerable actions) { _layoutService = layoutService; _contextService = contextService; _allActions = actions; // Связываем визуальный хост докинга с логическим движком MainDockHost.Service = _layoutService; // Подписываемся на смену контекста (вызывается при переключении вкладок в Lattice.UI) _contextService.ContextChanged += (s, newContext) => { // Обновляем тулбар в потоке пользовательского интерфейса this.DispatcherQueue.TryEnqueue(() => { StudioToolbar.UpdateItems(_allActions, newContext); }); }; // Начальная инициализация тулбара текущим контекстом StudioToolbar.UpdateItems(_allActions, _contextService.CurrentContext); } /// /// Настраивает интеграцию с нативным окном Windows 11 (TitleBar и Backdrop). /// Вызывается из MainWindow приложения. /// /// Текущее окно WinUI 3. public void SetupWindow(Window window) { // 1. Расширяем контент в область заголовка (Windowing SDK 1.8) window.ExtendsContentIntoTitleBar = true; // 2. Указываем нативный TitleBar для управления перетаскиванием окна if (AppTitleBar != null) { window.SetTitleBar(AppTitleBar); } // 3. Применяем Mica Alt для фона в стиле Visual Studio 2026 window.SystemBackdrop = new MicaBackdrop() { Kind = MicaKind.BaseAlt }; } /// /// Подключает сервис уведомлений к оболочке. /// public void InitializeNotifications(INotificationService notificationService) { notificationService.NotificationReceived += (s, e) => { this.DispatcherQueue.TryEnqueue(() => { var infoBar = new InfoBar { Message = e.Message, Severity = MapSeverity(e.Severity), IsOpen = true, Style = (Style)Application.Current.Resources["LatticeNotificationStyle"] }; // Автоматическое закрытие if (e.DurationSeconds > 0) { var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(e.DurationSeconds) }; timer.Tick += (st, et) => { infoBar.IsOpen = false; timer.Stop(); }; timer.Start(); } // Удаление из памяти после закрытия infoBar.CloseButtonClick += (sender, args) => NotificationArea.Children.Remove(infoBar); NotificationArea.Children.Insert(0, infoBar); // Новые сверху }); }; } private InfoBarSeverity MapSeverity(NotificationSeverity severity) => severity switch { NotificationSeverity.Error => InfoBarSeverity.Error, NotificationSeverity.Warning => InfoBarSeverity.Warning, NotificationSeverity.Success => InfoBarSeverity.Success, _ => InfoBarSeverity.Informational }; }