using System.Reactive.Linq; using System.Runtime.InteropServices; using Avalonia; using Avalonia.Controls; namespace InkForge.Desktop.Services; public class TopLevels { public static readonly AttachedProperty RegisterProperty = AvaloniaProperty.RegisterAttached("Register"); private static readonly Dictionary RegistrationMapper = []; public static TopLevel? ActiveTopLevel { get; private set; } static TopLevels() { RegisterProperty.Changed.AddClassHandler(RegisterChanged); WindowBase.IsActiveProperty.Changed.Subscribe(WindowActiveChanged); } public static object? GetRegister(AvaloniaObject element) { return element.GetValue(RegisterProperty); } public static TopLevel? GetTopLevelForContext(object context) { return TopLevel.GetTopLevel(GetVisualForContext(context)); } public static Visual? GetVisualForContext(object context) { return RegistrationMapper.TryGetValue(context, out var result) ? result : null; } public static void SetRegister(AvaloniaObject element, object value) { element.SetValue(RegisterProperty, value); } private static void RegisterChanged(Visual sender, AvaloniaPropertyChangedEventArgs e) { ArgumentNullException.ThrowIfNull(sender); // Unregister any old registered context if (e.OldValue != null) { RegistrationMapper.Remove(e.OldValue); } // Register any new context if (e.NewValue != null) { CollectionsMarshal.GetValueRefOrAddDefault(RegistrationMapper, e.NewValue, out _) = sender; } } private static void WindowActiveChanged(AvaloniaPropertyChangedEventArgs e) { ActiveTopLevel = (e.GetOldAndNewValue(), e.Sender) switch { ((false, true), TopLevel topLevel) => topLevel, ((true, false), { } topLevel) when topLevel == ActiveTopLevel => null, _ => ActiveTopLevel, }; } }