diff --git a/src/AtomUI.Controls/Dialog/Dialog.StaticAPI.cs b/src/AtomUI.Controls/Dialog/Dialog.StaticAPI.cs index 077b0229c..32c39c8a5 100644 --- a/src/AtomUI.Controls/Dialog/Dialog.StaticAPI.cs +++ b/src/AtomUI.Controls/Dialog/Dialog.StaticAPI.cs @@ -21,7 +21,7 @@ public partial class Dialog public static object? ShowDialog(Control content, object? dataContext = null, DialogOptions? options = null, TopLevel? topLevel = null) { var dialogManager = FindDialogManager(topLevel); - var dialog = CreateDialog(content, dataContext, options); + var dialog = CreateDialog(content, dataContext, options); dialogManager.Children.Add(dialog); var result = dialog.Open(); dialogManager.Children.Remove(dialog); @@ -71,6 +71,12 @@ public partial class Dialog VerticalStartupLocation = options?.VerticalStartupLocation ?? DialogVerticalAnchor.Custom, Content = content, DataContext = dataContext, + Width = options?.Width ?? Double.NaN, + Height = options?.Height ?? Double.NaN, + MinWidth = options?.MinWidth ?? 0d, + MinHeight = options?.MinHeight ?? 0d, + MaxWidth = options?.MaxWidth ?? Double.PositiveInfinity, + MaxHeight = options?.MaxHeight ?? Double.PositiveInfinity }; return dialog; } diff --git a/src/AtomUI.Controls/Dialog/DialogOptions.cs b/src/AtomUI.Controls/Dialog/DialogOptions.cs index 05e47614e..2304d74a3 100644 --- a/src/AtomUI.Controls/Dialog/DialogOptions.cs +++ b/src/AtomUI.Controls/Dialog/DialogOptions.cs @@ -12,6 +12,13 @@ public record DialogOptions public bool IsResizable { get; init; } = false; public bool IsClosable { get; init; } = true; public bool IsMaximizable { get; init; } = false; + + public double MaxHeight { get; init; } = double.PositiveInfinity; + public double MaxWidth { get; init; } = double.PositiveInfinity; + public double MinHeight { get; init; } = 0d; + public double MinWidth { get; init; } = 0d; + public double Width { get; init; } = double.NaN; + public double Height { get; init; } = double.NaN; /// /// 仅仅对 Window Host 类型的弹窗有效 diff --git a/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHeader.cs b/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHeader.cs index 6c955c7aa..b23f26313 100644 --- a/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHeader.cs +++ b/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHeader.cs @@ -8,6 +8,7 @@ using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; +using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Metadata; @@ -134,6 +135,7 @@ internal class OverlayDialogHeader : TemplatedControl, IMotionAwareControl internal event EventHandler? CloseRequest; internal event EventHandler? MaximizeRequest; internal event EventHandler? NormalizeRequest; + internal event EventHandler? Pressed; #endregion @@ -154,11 +156,6 @@ internal class OverlayDialogHeader : TemplatedControl, IMotionAwareControl PseudoClasses.Set(StdPseudoClass.Normal, x == OverlayDialogState.Normal); PseudoClasses.Set(StdPseudoClass.Maximized, x == OverlayDialogState.Maximized); }), - // window.GetObservable(WindowBase.IsActiveProperty).Subscribe(isActivated => - // { - // PseudoClasses.Set(StdPseudoClass.Active, isActivated); - // IsActivated = isActivated; - // }) }; } } @@ -194,7 +191,13 @@ internal class OverlayDialogHeader : TemplatedControl, IMotionAwareControl } } } - + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + base.OnPointerPressed(e); + Pressed?.Invoke(this, EventArgs.Empty); + } + private void HandleCloseButtonClicked(object? sender, RoutedEventArgs e) { CloseRequest?.Invoke(this, EventArgs.Empty); diff --git a/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHost.cs b/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHost.cs index 038df1fbe..a5d13d25d 100644 --- a/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHost.cs +++ b/src/AtomUI.Controls/Dialog/OverlayHost/OverlayDialogHost.cs @@ -176,6 +176,8 @@ internal class OverlayDialogHost : ContentControl, #endregion + internal event EventHandler? HeaderPressed; + #region 内部属性定义 internal static readonly DirectProperty IsDraggingProperty = @@ -577,6 +579,10 @@ internal class OverlayDialogHost : ContentControl, if (_header != null) { _header.SetCurrentValue(OverlayDialogHeader.IsDialogMaximizedProperty, WindowState == OverlayDialogState.Maximized); + _header.Pressed += (sender, args) => + { + HeaderPressed?.Invoke(this, EventArgs.Empty); + }; } if (_buttonBox != null) { @@ -895,4 +901,10 @@ internal class OverlayDialogHost : ContentControl, Transitions = null; } } + + internal void NotifyChangeZIndex(int zindex) + { + _dialogMask.SetCurrentValue(OverlayDialogMask.ZIndexProperty, zindex - 1); + SetCurrentValue(ZIndexProperty, zindex); + } } \ No newline at end of file diff --git a/src/AtomUI.Controls/Dialog/Themes/OverlayDialogHostTheme.axaml b/src/AtomUI.Controls/Dialog/Themes/OverlayDialogHostTheme.axaml index cf2b47ba7..b1d089193 100644 --- a/src/AtomUI.Controls/Dialog/Themes/OverlayDialogHostTheme.axaml +++ b/src/AtomUI.Controls/Dialog/Themes/OverlayDialogHostTheme.axaml @@ -66,6 +66,7 @@ + diff --git a/src/AtomUI.Controls/Primitives/DialogLayer.cs b/src/AtomUI.Controls/Primitives/DialogLayer.cs index bfb1c52ef..735a5e9f2 100644 --- a/src/AtomUI.Controls/Primitives/DialogLayer.cs +++ b/src/AtomUI.Controls/Primitives/DialogLayer.cs @@ -1,10 +1,11 @@ +using System.Collections.Specialized; using Avalonia; using Avalonia.Controls; using Avalonia.VisualTree; namespace AtomUI.Controls.Primitives; -public class DialogLayer : Canvas +internal class DialogLayer : Canvas { protected override bool BypassFlowDirectionPolicies => true; @@ -14,6 +15,58 @@ public class DialogLayer : Canvas { ClipToBoundsProperty.OverrideDefaultValue(true); } + + public DialogLayer() + { + Children.CollectionChanged += HandleDialogChanged; + } + + private void HandleDialogChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action == NotifyCollectionChangedAction.Add) + { + if (e.NewItems != null) + { + foreach (Control child in e.NewItems) + { + if (child is OverlayDialogHost overlayDialogHost) + { + overlayDialogHost.HeaderPressed += HandleOverlayDialogClicked; + } + } + } + } + else if (e.Action == NotifyCollectionChangedAction.Remove) + { + if (e.OldItems != null) + { + foreach (Control child in e.OldItems) + { + if (child is OverlayDialogHost overlayDialogHost) + { + overlayDialogHost.HeaderPressed -= HandleOverlayDialogClicked; + } + } + } + } + } + + private void HandleOverlayDialogClicked(object? sender, EventArgs e) + { + var maxZIndex = 0; + foreach (Control child in Children) + { + if (child is OverlayDialogHost overlayDialogHost) + { + maxZIndex = Math.Max(maxZIndex, overlayDialogHost.ZIndex); + } + } + + if (sender is OverlayDialogHost clickedOverlayDialogHost) + { + clickedOverlayDialogHost.NotifyChangeZIndex(maxZIndex + 2); + } + } public static DialogLayer? GetDialogLayer(Visual visual) { diff --git a/src/AtomUI.Controls/Primitives/VisualLayerManager.cs b/src/AtomUI.Controls/Primitives/VisualLayerManager.cs index 5146cf572..04a55a05c 100644 --- a/src/AtomUI.Controls/Primitives/VisualLayerManager.cs +++ b/src/AtomUI.Controls/Primitives/VisualLayerManager.cs @@ -19,7 +19,7 @@ public class VisualLayerManager : AvaloniaVisualLayerManager return null; } - public DialogLayer DialogLayer + internal DialogLayer DialogLayer { get { diff --git a/src/AtomUI.Controls/Spin/SpinIndicator.cs b/src/AtomUI.Controls/Spin/SpinIndicator.cs index 18ed1b202..30bdeadad 100644 --- a/src/AtomUI.Controls/Spin/SpinIndicator.cs +++ b/src/AtomUI.Controls/Spin/SpinIndicator.cs @@ -1,5 +1,8 @@ -using AtomUI.Controls.Themes; +using AtomUI.Controls.DesignTokens; +using AtomUI.Controls.Themes; +using AtomUI.IconPkg; using AtomUI.Theme; +using AtomUI.Theme.Styling; using AtomUI.Theme.Utils; using AtomUI.Utils; using Avalonia; @@ -128,6 +131,7 @@ public class SpinIndicator : TemplatedControl, public SpinIndicator() { this.RegisterResources(); + ConfigureInstanceStyles(); } protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) @@ -255,4 +259,41 @@ public class SpinIndicator : TemplatedControl, context.DrawEllipse(DotBgBrush, null, itemRect); } } + + private void ConfigureInstanceStyles() + { + { + var middleStyle = new Style(x => + x.PropertyEquals(SizeTypeProperty, SizeType.Middle)); + var iconStyle = new Style(x => + x.Nesting().Descendant().OfType().Name(SpinThemeConstants.CustomIndicatorPresenterPart).Child() + .OfType()); + iconStyle.Add(Icon.WidthProperty, SpinTokenKey.IndicatorSize); + iconStyle.Add(Icon.HeightProperty, SpinTokenKey.IndicatorSize); + middleStyle.Add(iconStyle); + Styles.Add(middleStyle); + } + { + var smallStyle = new Style(x => + x.PropertyEquals(SizeTypeProperty, SizeType.Small)); + var iconStyle = new Style(x => + x.Nesting().Descendant().OfType().Name(SpinThemeConstants.CustomIndicatorPresenterPart).Child() + .OfType()); + iconStyle.Add(Icon.WidthProperty, SpinTokenKey.IndicatorSizeSM); + iconStyle.Add(Icon.HeightProperty, SpinTokenKey.IndicatorSizeSM); + smallStyle.Add(iconStyle); + Styles.Add(smallStyle); + } + { + var largeStyle = new Style(x => + x.PropertyEquals(SizeTypeProperty, SizeType.Large)); + var iconStyle = new Style(x => + x.Nesting().Descendant().OfType().Name(SpinThemeConstants.CustomIndicatorPresenterPart).Child() + .OfType()); + iconStyle.Add(Icon.WidthProperty, SpinTokenKey.IndicatorSizeLG); + iconStyle.Add(Icon.HeightProperty, SpinTokenKey.IndicatorSizeLG); + largeStyle.Add(iconStyle); + Styles.Add(largeStyle); + } + } } \ No newline at end of file