diff --git a/src/Ursa/Controls/Dialog/CustomDialogControl.cs b/src/Ursa/Controls/Dialog/CustomDialogControl.cs index d2145c9..9836d66 100644 --- a/src/Ursa/Controls/Dialog/CustomDialogControl.cs +++ b/src/Ursa/Controls/Dialog/CustomDialogControl.cs @@ -3,28 +3,19 @@ using Irihi.Avalonia.Shared.Contracts; namespace Ursa.Controls; -public class CustomDialogControl: DialogControlBase +public class CustomDialogControl : DialogControlBase { - internal bool IsCloseButtonVisible { get; set; } - protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); - if (_closeButton is not null) - { - _closeButton.IsVisible = IsCloseButtonVisible; - } + if (_closeButton is not null) _closeButton.IsVisible = IsCloseButtonVisible ?? true; } public override void Close() { if (DataContext is IDialogContext context) - { context.Close(); - } else - { OnElementClosing(this, null); - } } } \ No newline at end of file diff --git a/src/Ursa/Controls/Dialog/DefaultDialogControl.cs b/src/Ursa/Controls/Dialog/DefaultDialogControl.cs index 5f0c685..6a44668 100644 --- a/src/Ursa/Controls/Dialog/DefaultDialogControl.cs +++ b/src/Ursa/Controls/Dialog/DefaultDialogControl.cs @@ -12,20 +12,30 @@ namespace Ursa.Controls; [TemplatePart(PART_CancelButton, typeof(Button))] [TemplatePart(PART_YesButton, typeof(Button))] [TemplatePart(PART_NoButton, typeof(Button))] -public class DefaultDialogControl: DialogControlBase +public class DefaultDialogControl : DialogControlBase { public const string PART_OKButton = "PART_OKButton"; public const string PART_CancelButton = "PART_CancelButton"; public const string PART_YesButton = "PART_YesButton"; public const string PART_NoButton = "PART_NoButton"; - - private Button? _okButton; + + public static readonly StyledProperty TitleProperty = + AvaloniaProperty.Register( + nameof(Title)); + + public static readonly StyledProperty ButtonsProperty = + AvaloniaProperty.Register( + nameof(Buttons)); + + public static readonly StyledProperty ModeProperty = + AvaloniaProperty.Register( + nameof(Mode)); + private Button? _cancelButton; - private Button? _yesButton; private Button? _noButton; - - public static readonly StyledProperty TitleProperty = AvaloniaProperty.Register( - nameof(Title)); + + private Button? _okButton; + private Button? _yesButton; public string? Title { @@ -33,24 +43,18 @@ public class DefaultDialogControl: DialogControlBase set => SetValue(TitleProperty, value); } - public static readonly StyledProperty ButtonsProperty = AvaloniaProperty.Register( - nameof(Buttons)); - public DialogButton Buttons { get => GetValue(ButtonsProperty); set => SetValue(ButtonsProperty, value); } - public static readonly StyledProperty ModeProperty = AvaloniaProperty.Register( - nameof(Mode)); - public DialogMode Mode { get => GetValue(ModeProperty); set => SetValue(ModeProperty, value); } - + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -62,56 +66,48 @@ public class DefaultDialogControl: DialogControlBase Button.ClickEvent.AddHandler(DefaultButtonsClose, _okButton, _cancelButton, _yesButton, _noButton); SetButtonVisibility(); } - - + + private void SetButtonVisibility() { - bool isCloseButtonVisible = DataContext is IDialogContext || Buttons != DialogButton.YesNo; - Button.IsVisibleProperty.SetValue(isCloseButtonVisible, _closeButton); + var isCloseButtonVisible = + IsCloseButtonVisible ?? (DataContext is IDialogContext || Buttons != DialogButton.YesNo); + IsVisibleProperty.SetValue(isCloseButtonVisible, _closeButton); switch (Buttons) { case DialogButton.None: - Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton, _yesButton, _noButton); + IsVisibleProperty.SetValue(false, _okButton, _cancelButton, _yesButton, _noButton); break; case DialogButton.OK: - Button.IsVisibleProperty.SetValue(true, _okButton); - Button.IsVisibleProperty.SetValue(false, _cancelButton, _yesButton, _noButton); + IsVisibleProperty.SetValue(true, _okButton); + IsVisibleProperty.SetValue(false, _cancelButton, _yesButton, _noButton); break; case DialogButton.OKCancel: - Button.IsVisibleProperty.SetValue(true, _okButton, _cancelButton); - Button.IsVisibleProperty.SetValue(false, _yesButton, _noButton); + IsVisibleProperty.SetValue(true, _okButton, _cancelButton); + IsVisibleProperty.SetValue(false, _yesButton, _noButton); break; case DialogButton.YesNo: - Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton); - Button.IsVisibleProperty.SetValue(true, _yesButton, _noButton); + IsVisibleProperty.SetValue(false, _okButton, _cancelButton); + IsVisibleProperty.SetValue(true, _yesButton, _noButton); break; case DialogButton.YesNoCancel: - Button.IsVisibleProperty.SetValue(false, _okButton); - Button.IsVisibleProperty.SetValue(true, _cancelButton, _yesButton, _noButton); + IsVisibleProperty.SetValue(false, _okButton); + IsVisibleProperty.SetValue(true, _cancelButton, _yesButton, _noButton); break; } } - + private void DefaultButtonsClose(object? sender, RoutedEventArgs args) { if (sender is Button button) { if (button == _okButton) - { OnElementClosing(this, DialogResult.OK); - } else if (button == _cancelButton) - { OnElementClosing(this, DialogResult.Cancel); - } else if (button == _yesButton) - { OnElementClosing(this, DialogResult.Yes); - } - else if (button == _noButton) - { - OnElementClosing(this, DialogResult.No); - } + else if (button == _noButton) OnElementClosing(this, DialogResult.No); } } @@ -123,7 +119,7 @@ public class DefaultDialogControl: DialogControlBase } else { - DialogResult result = Buttons switch + var result = Buttons switch { DialogButton.None => DialogResult.None, DialogButton.OK => DialogResult.OK, diff --git a/src/Ursa/Controls/Dialog/DefaultDialogWindow.cs b/src/Ursa/Controls/Dialog/DefaultDialogWindow.cs index 67ed3ff..c94ae91 100644 --- a/src/Ursa/Controls/Dialog/DefaultDialogWindow.cs +++ b/src/Ursa/Controls/Dialog/DefaultDialogWindow.cs @@ -12,22 +12,27 @@ namespace Ursa.Controls; [TemplatePart(PART_NoButton, typeof(Button))] [TemplatePart(PART_OKButton, typeof(Button))] [TemplatePart(PART_CancelButton, typeof(Button))] -public class DefaultDialogWindow: DialogWindow +public class DefaultDialogWindow : DialogWindow { - protected override Type StyleKeyOverride { get; } = typeof(DefaultDialogWindow); - public const string PART_YesButton = "PART_YesButton"; public const string PART_NoButton = "PART_NoButton"; public const string PART_OKButton = "PART_OKButton"; public const string PART_CancelButton = "PART_CancelButton"; - - private Button? _yesButton; + + public static readonly StyledProperty ButtonsProperty = + AvaloniaProperty.Register( + nameof(Buttons)); + + public static readonly StyledProperty ModeProperty = + AvaloniaProperty.Register( + nameof(Mode)); + + private Button? _cancelButton; private Button? _noButton; private Button? _okButton; - private Button? _cancelButton; - public static readonly StyledProperty ButtonsProperty = AvaloniaProperty.Register( - nameof(Buttons)); + private Button? _yesButton; + protected override Type StyleKeyOverride { get; } = typeof(DefaultDialogWindow); public DialogButton Buttons { @@ -35,15 +40,12 @@ public class DefaultDialogWindow: DialogWindow set => SetValue(ButtonsProperty, value); } - public static readonly StyledProperty ModeProperty = AvaloniaProperty.Register( - nameof(Mode)); - public DialogMode Mode { get => GetValue(ModeProperty); set => SetValue(ModeProperty, value); } - + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -59,69 +61,43 @@ public class DefaultDialogWindow: DialogWindow private void OnDefaultClose(object? sender, RoutedEventArgs e) { if (Equals(sender, _yesButton)) - { Close(DialogResult.Yes); - return; - } - if(Equals(sender, _noButton)) - { + else if (Equals(sender, _noButton)) Close(DialogResult.No); - return; - } - if(Equals(sender, _okButton)) - { + else if (Equals(sender, _okButton)) Close(DialogResult.OK); - return; - } - if(Equals(sender, _cancelButton)) - { + else if (Equals(sender, _cancelButton)) Close(DialogResult.Cancel); - } } private void SetButtonVisibility() { - bool closeButtonVisible = DataContext is IDialogContext || Buttons != DialogButton.YesNo; - SetVisibility(_closeButton, closeButtonVisible); + var closeButtonVisible = + IsCloseButtonVisible ?? (DataContext is IDialogContext || Buttons != DialogButton.YesNo); + IsVisibleProperty.SetValue(closeButtonVisible, _closeButton); switch (Buttons) { case DialogButton.None: - SetVisibility(_okButton, false); - SetVisibility(_cancelButton, false); - SetVisibility(_yesButton, false); - SetVisibility(_noButton, false); + IsVisibleProperty.SetValue(false, _okButton, _cancelButton, _yesButton, _noButton); break; case DialogButton.OK: - SetVisibility(_okButton, true); - SetVisibility(_cancelButton, false); - SetVisibility(_yesButton, false); - SetVisibility(_noButton, false); + IsVisibleProperty.SetValue(true, _okButton); + IsVisibleProperty.SetValue(false, _cancelButton, _yesButton, _noButton); break; case DialogButton.OKCancel: - SetVisibility(_okButton, true); - SetVisibility(_cancelButton, true); - SetVisibility(_yesButton, false); - SetVisibility(_noButton, false); + IsVisibleProperty.SetValue(true, _okButton, _cancelButton); + IsVisibleProperty.SetValue(false, _yesButton, _noButton); break; case DialogButton.YesNo: - SetVisibility(_okButton, false); - SetVisibility(_cancelButton, false); - SetVisibility(_yesButton, true); - SetVisibility(_noButton, true); + IsVisibleProperty.SetValue(false, _okButton, _cancelButton); + IsVisibleProperty.SetValue(true, _yesButton, _noButton); break; case DialogButton.YesNoCancel: - SetVisibility(_okButton, false); - SetVisibility(_cancelButton, true); - SetVisibility(_yesButton, true); - SetVisibility(_noButton, true); + IsVisibleProperty.SetValue(false, _okButton); + IsVisibleProperty.SetValue(true, _cancelButton, _yesButton, _noButton); break; } } - - private void SetVisibility(Button? button, bool visible) - { - if (button is not null) button.IsVisible = visible; - } protected override void OnCloseButtonClicked(object? sender, RoutedEventArgs args) { @@ -131,7 +107,7 @@ public class DefaultDialogWindow: DialogWindow } else { - DialogResult result = Buttons switch + var result = Buttons switch { DialogButton.None => DialogResult.None, DialogButton.OK => DialogResult.OK, diff --git a/src/Ursa/Controls/Dialog/DialogControlBase.cs b/src/Ursa/Controls/Dialog/DialogControlBase.cs index 1e3e2fd..8bde726 100644 --- a/src/Ursa/Controls/Dialog/DialogControlBase.cs +++ b/src/Ursa/Controls/Dialog/DialogControlBase.cs @@ -20,6 +20,22 @@ public abstract class DialogControlBase : OverlayFeedbackElement public const string PC_Modal = ":modal"; public const string PC_FullScreen = ":full-screen"; + public static readonly DirectProperty IsFullScreenProperty = + AvaloniaProperty.RegisterDirect( + nameof(IsFullScreen), o => o.IsFullScreen, (o, v) => o.IsFullScreen = v); + + protected internal Button? _closeButton; + + private bool _isFullScreen; + private Panel? _titleArea; + + static DialogControlBase() + { + CanDragMoveProperty.Changed.AddClassHandler(OnCanDragMoveChanged); + CanCloseProperty.Changed.AddClassHandler(OnCanCloseChanged); + IsFullScreenProperty.AffectsPseudoClass(PC_FullScreen); + } + internal HorizontalPosition HorizontalAnchor { get; set; } = HorizontalPosition.Center; internal VerticalPosition VerticalAnchor { get; set; } = VerticalPosition.Center; internal HorizontalPosition ActualHorizontalAnchor { get; set; } @@ -29,11 +45,7 @@ public abstract class DialogControlBase : OverlayFeedbackElement internal double? HorizontalOffsetRatio { get; set; } internal double? VerticalOffsetRatio { get; set; } internal bool CanLightDismiss { get; set; } - - private bool _isFullScreen; - - public static readonly DirectProperty IsFullScreenProperty = AvaloniaProperty.RegisterDirect( - nameof(IsFullScreen), o => o.IsFullScreen, (o, v) => o.IsFullScreen = v); + internal bool? IsCloseButtonVisible { get; set; } public bool IsFullScreen { @@ -41,113 +53,6 @@ public abstract class DialogControlBase : OverlayFeedbackElement set => SetAndRaise(IsFullScreenProperty, ref _isFullScreen, value); } - 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); - IsFullScreenProperty.AffectsPseudoClass(PC_FullScreen); - } - - - protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { @@ -188,10 +93,107 @@ public abstract class DialogControlBase : OverlayFeedbackElement e.Source = this; } - private void OnCloseButtonClick(object? sender, RoutedEventArgs args) => Close(); + private void OnCloseButtonClick(object? sender, RoutedEventArgs args) + { + Close(); + } internal void SetAsModal(bool modal) { PseudoClasses.Set(PC_Modal, modal); } + + #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) + { + return 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) + { + return 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 } \ No newline at end of file diff --git a/src/Ursa/Controls/Dialog/DialogWindow.cs b/src/Ursa/Controls/Dialog/DialogWindow.cs index fabf85b..603496f 100644 --- a/src/Ursa/Controls/Dialog/DialogWindow.cs +++ b/src/Ursa/Controls/Dialog/DialogWindow.cs @@ -11,33 +11,29 @@ namespace Ursa.Controls; [TemplatePart(PART_CloseButton, typeof(Button))] [TemplatePart(PART_TitleArea, typeof(Panel))] -public class DialogWindow: Window +public class DialogWindow : Window { public const string PART_CloseButton = "PART_CloseButton"; public const string PART_TitleArea = "PART_TitleArea"; - protected override Type StyleKeyOverride { get; } = typeof(DialogWindow); protected internal Button? _closeButton; private Panel? _titleArea; - - internal bool IsCloseButtonVisible { get; set; } static DialogWindow() { - DataContextProperty.Changed.AddClassHandler((o, e) => o.OnDataContextChange(e)); + DataContextProperty.Changed.AddClassHandler((window, e) => + window.OnDataContextChange(e)); } - + + protected override Type StyleKeyOverride { get; } = typeof(DialogWindow); + + internal bool? IsCloseButtonVisible { get; set; } + private void OnDataContextChange(AvaloniaPropertyChangedEventArgs args) { - if (args.OldValue.Value is IDialogContext oldContext) - { - oldContext.RequestClose-= OnContextRequestClose; - } + if (args.OldValue.Value is IDialogContext oldContext) oldContext.RequestClose -= OnContextRequestClose; - if (args.NewValue.Value is IDialogContext newContext) - { - newContext.RequestClose += OnContextRequestClose; - } + if (args.NewValue.Value is IDialogContext newContext) newContext.RequestClose += OnContextRequestClose; } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) @@ -46,11 +42,10 @@ public class DialogWindow: Window Button.ClickEvent.RemoveHandler(OnCloseButtonClicked, _closeButton); _titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed); _closeButton = e.NameScope.Find