mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-29 07:16:33 +08:00
Add ZIndex manage support for DialogLayer
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 仅仅对 Window Host 类型的弹窗有效
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -176,6 +176,8 @@ internal class OverlayDialogHost : ContentControl,
|
||||
|
||||
#endregion
|
||||
|
||||
internal event EventHandler? HeaderPressed;
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly DirectProperty<OverlayDialogHost, bool> 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);
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@
|
||||
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:DialogTokenKey.HeaderMarginBottom}}" />
|
||||
</Style>
|
||||
|
||||
|
||||
<Style Selector="^ /template/ Border#ShadowFrame">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static atom:DialogTokenKey.ContentBg}}" />
|
||||
</Style>
|
||||
|
||||
@@ -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<DialogLayer>(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)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ public class VisualLayerManager : AvaloniaVisualLayerManager
|
||||
return null;
|
||||
}
|
||||
|
||||
public DialogLayer DialogLayer
|
||||
internal DialogLayer DialogLayer
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -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<ContentPresenter>().Name(SpinThemeConstants.CustomIndicatorPresenterPart).Child()
|
||||
.OfType<Icon>());
|
||||
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<ContentPresenter>().Name(SpinThemeConstants.CustomIndicatorPresenterPart).Child()
|
||||
.OfType<Icon>());
|
||||
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<ContentPresenter>().Name(SpinThemeConstants.CustomIndicatorPresenterPart).Child()
|
||||
.OfType<Icon>());
|
||||
iconStyle.Add(Icon.WidthProperty, SpinTokenKey.IndicatorSizeLG);
|
||||
iconStyle.Add(Icon.HeightProperty, SpinTokenKey.IndicatorSizeLG);
|
||||
largeStyle.Add(iconStyle);
|
||||
Styles.Add(largeStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user