using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.Input; using Avalonia.Media; using Ursa.Controls.OverlayShared; using Avalonia.Layout; namespace Ursa.Controls; public partial class OverlayDialogHost: Canvas { private readonly List _dialogs = new(); private readonly List _modalDialogs = new(); private readonly List _masks = new(); public string? HostId { get; set; } public DataTemplates DialogDataTemplates { get; set; } = new DataTemplates(); public static readonly StyledProperty OverlayMaskBrushProperty = AvaloniaProperty.Register( nameof(OverlayMaskBrush)); public IBrush? OverlayMaskBrush { get => GetValue(OverlayMaskBrushProperty); set => SetValue(OverlayMaskBrushProperty, value); } private Border CreateOverlayMask(bool canCloseOnClick) { Border border = new() { HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch, Width = this.Bounds.Width, Height = this.Bounds.Height, [!BackgroundProperty] = this[!OverlayMaskBrushProperty], IsVisible = true, }; if (canCloseOnClick) { border.AddHandler(PointerReleasedEvent, ClickBorderToCloseDialog); } return border; } private void ClickBorderToCloseDialog(object sender, PointerReleasedEventArgs e) { if (sender is Border border) { int i = _masks.IndexOf(border); if (_modalDialogs[i] is { } dialog) { dialog.Close(); border.RemoveHandler(PointerReleasedEvent, ClickBorderToCloseDialog); } } } protected sealed override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { base.OnAttachedToVisualTree(e); OverlayDialogManager.RegisterHost(this, HostId); } protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) { OverlayDialogManager.UnregisterHost(HostId); base.OnDetachedFromVisualTree(e); } protected sealed override void OnSizeChanged(SizeChangedEventArgs e) { base.OnSizeChanged(e); for (int i = 0; i < _masks.Count; i++) { _masks[i].Width = this.Bounds.Width; _masks[i].Height = this.Bounds.Height; } var oldSize = e.PreviousSize; var newSize = e.NewSize; foreach (var dialog in _dialogs) { if (dialog is DialogControlBase c) { ResetDialogPosition(c, oldSize, newSize); } } foreach (var modalDialog in _modalDialogs) { if (modalDialog is DialogControlBase c) { ResetDialogPosition(c, oldSize, newSize); } } } private void ResetZIndices() { int index = 0; for ( int i = 0; i< _dialogs.Count; i++) { _dialogs[i].ZIndex = index; index++; } for(int i = 0; i< _masks.Count; i++) { _masks[i].ZIndex = index; index++; (_modalDialogs[i] as Control)!.ZIndex = index; index++; } } internal IDataTemplate? GetDataTemplate(object? o) { if (o is null) return null; IDataTemplate? result = null; var templates = this.DialogDataTemplates; result = templates.FirstOrDefault(a => a.Match(o)); if (result != null) return result; var keys = this.Resources.Keys; foreach (var key in keys) { if (Resources.TryGetValue(key, out var value) && value is IDataTemplate t) { result = t; break; } } return result; } }