using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.LogicalTree; using Irihi.Avalonia.Shared.Helpers; using Ursa.Common; using Ursa.Controls.OverlayShared; using Ursa.EventArgs; namespace Ursa.Controls; [TemplatePart(PART_CloseButton, typeof(Button))] [TemplatePart(PART_TitleArea, typeof(Panel))] [PseudoClasses(PC_Modal)] public abstract class DialogControlBase : OverlayFeedbackElement { public const string PART_CloseButton = "PART_CloseButton"; public const string PART_TitleArea = "PART_TitleArea"; public const string PC_Modal = ":modal"; internal HorizontalPosition HorizontalAnchor { get; set; } = HorizontalPosition.Center; internal VerticalPosition VerticalAnchor { get; set; } = VerticalPosition.Center; internal HorizontalPosition ActualHorizontalAnchor { get; set; } internal VerticalPosition ActualVerticalAnchor { get; set; } internal double? HorizontalOffset { get; set; } internal double? VerticalOffset { get; set; } internal double? HorizontalOffsetRatio { get; set; } internal double? VerticalOffsetRatio { get; set; } internal bool CanClickOnMaskToClose { get; set; } internal bool CanLightDismiss { get; set; } internal bool CanDragMove { get; set; } protected internal Button? _closeButton; private Panel? _titleArea; #region Layer Management public static readonly RoutedEvent LayerChangedEvent = RoutedEvent.Register( nameof(LayerChanged), RoutingStrategies.Bubble); public event EventHandler LayerChanged { add => AddHandler(LayerChangedEvent, value); remove => RemoveHandler(LayerChangedEvent, value); } public void UpdateLayer(object? o) { if (o is DialogLayerChangeType t) { RaiseEvent(new DialogLayerChangeEventArgs(LayerChangedEvent, t)); } } #endregion #region DragMove AttachedPropert public static readonly AttachedProperty CanDragMoveProperty = AvaloniaProperty.RegisterAttached("CanDragMove"); public static void SetCanDragMove(InputElement obj, bool value) => obj.SetValue(CanDragMoveProperty, value); public static bool GetCanDragMove(InputElement obj) => obj.GetValue(CanDragMoveProperty); private static void OnCanDragMoveChanged(InputElement arg1, AvaloniaPropertyChangedEventArgs arg2) { if (arg2.NewValue.Value) { arg1.AddHandler(PointerPressedEvent, OnPointerPressed, RoutingStrategies.Bubble); arg1.AddHandler(PointerMovedEvent, OnPointerMoved, RoutingStrategies.Bubble); arg1.AddHandler(PointerReleasedEvent, OnPointerReleased, RoutingStrategies.Bubble); } else { arg1.RemoveHandler(PointerPressedEvent, OnPointerPressed); arg1.RemoveHandler(PointerMovedEvent, OnPointerMoved); arg1.RemoveHandler(PointerReleasedEvent, OnPointerReleased); } void OnPointerPressed(InputElement sender, PointerPressedEventArgs e) { if (sender.FindLogicalAncestorOfType() is { } dialog) { e.Source = dialog; } } void OnPointerMoved(InputElement sender, PointerEventArgs e) { if (sender.FindLogicalAncestorOfType() is { } dialog) { e.Source = dialog; } } void OnPointerReleased(InputElement sender, PointerReleasedEventArgs e) { if (sender.FindLogicalAncestorOfType() is { } dialog) { e.Source = dialog; } } } #endregion #region Close AttachedProperty public static readonly AttachedProperty CanCloseProperty = AvaloniaProperty.RegisterAttached("CanClose"); public static void SetCanClose(InputElement obj, bool value) => obj.SetValue(CanCloseProperty, value); public static bool GetCanClose(InputElement obj) => obj.GetValue(CanCloseProperty); private static void OnCanCloseChanged(InputElement arg1, AvaloniaPropertyChangedEventArgs arg2) { if (arg2.NewValue.Value) { arg1.AddHandler(PointerPressedEvent, OnPointerPressed, RoutingStrategies.Bubble); } void OnPointerPressed(InputElement sender, PointerPressedEventArgs e) { if (sender.FindLogicalAncestorOfType() is { } dialog) { dialog.Close(); } } } #endregion static DialogControlBase() { CanDragMoveProperty.Changed.AddClassHandler(OnCanDragMoveChanged); CanCloseProperty.Changed.AddClassHandler(OnCanCloseChanged); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); _titleArea = e.NameScope.Find(PART_TitleArea); if (CanDragMove) { _titleArea?.RemoveHandler(PointerMovedEvent, OnTitlePointerMove); _titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed); _titleArea?.RemoveHandler(PointerReleasedEvent, OnTitlePointerRelease); _titleArea?.AddHandler(PointerMovedEvent, OnTitlePointerMove, RoutingStrategies.Bubble); _titleArea?.AddHandler(PointerPressedEvent, OnTitlePointerPressed, RoutingStrategies.Bubble); _titleArea?.AddHandler(PointerReleasedEvent, OnTitlePointerRelease, RoutingStrategies.Bubble); } else { if (_titleArea is not null) _titleArea.IsHitTestVisible = false; } Button.ClickEvent.RemoveHandler(OnCloseButtonClick, _closeButton); _closeButton = e.NameScope.Find