feat: WIP dialog window.

This commit is contained in:
rabbitism
2024-01-21 23:40:06 +08:00
parent a0598b6a47
commit 2c361f9f3c
9 changed files with 193 additions and 19 deletions

View File

@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Shapes;
using Avalonia.Media;
@@ -7,18 +8,46 @@ namespace Ursa.Controls;
public static class DialogBox
{
public static async Task ShowAsync()
public static async Task<TResult?> ShowAsync<TView, TViewModel, TResult>(TViewModel vm) where TView : Control, new()
{
return;
var window = new DialogWindow()
{
Content = new TView()
{
DataContext = vm,
},
DataContext = vm,
};
var lifetime = Application.Current?.ApplicationLifetime;
if (lifetime is IClassicDesktopStyleApplicationLifetime classLifetime)
{
var main = classLifetime.MainWindow;
if (main is null)
{
window.Show();
return default(TResult);
}
else
{
var result = await window.ShowDialog<TResult>(main);
return result;
}
}
else
{
return default(TResult);
}
}
public static async Task ShowAsync<TView, TViewModel>(TViewModel vm)
where TView: Control, new()
where TViewModel: new()
public static async Task<TResult> ShowAsync<TView, TViewModel, TResult>(Window owner, TViewModel vm) where
TView: Control, new()
{
TView t = new TView();
t.DataContext = vm;
var window = new DialogWindow();
window.Content = new TView();
window.DataContext = vm;
return await window.ShowDialog<TResult>(owner);
}
public static async Task<object?> ShowOverlayAsync<TView, TViewModel>(TViewModel vm, string hostId)
where TView : Control, new()

View File

@@ -1,8 +1,27 @@
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
namespace Ursa.Controls;
[TemplatePart(PART_CloseButton, typeof(Button))]
public class DialogControl: ContentControl
{
public const string PART_CloseButton = "PART_CloseButton";
private Button? _closeButton;
public event EventHandler OnClose;
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
}
public void Show()
{
}
}

View File

@@ -0,0 +1,30 @@
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
namespace Ursa.Controls;
[TemplatePart(PART_CloseButton, typeof(Button))]
public class DialogWindow: Window
{
public const string PART_CloseButton = "PART_CloseButton";
protected override Type StyleKeyOverride { get; } = typeof(DialogWindow);
private Button? _closeButton;
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
if (_closeButton != null)
{
_closeButton.Click += (sender, args) =>
{
Close();
};
}
}
}

View File

@@ -2,5 +2,6 @@ namespace Ursa.Controls;
public interface IDialogContext
{
object Close();
T? Close<T>();
}

View File

@@ -1,14 +1,26 @@
using System.Collections.Specialized;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace Ursa.Controls;
namespace Ursa.Controls;
public class OverlayDialogHost: Canvas
{
private readonly List<DialogControl> _dialogs = new();
private readonly List<DialogControl> _modalDialogs = new();
private Rectangle _overlayMask = new()
{
Fill = new SolidColorBrush(new Color(1, 0, 0, 0)),
[Rectangle.ZIndexProperty] = 0,
};
public static readonly StyledProperty<string> HostIdProperty = AvaloniaProperty.Register<OverlayDialogHost, string>(
nameof(HostId));
@@ -39,13 +51,18 @@ public class OverlayDialogHost: Canvas
{
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
var parent = item.FindAncestorOfType<DialogControl>();
if (parent is null)
{
return;
}
var p = e.GetPosition(this);
var left= p.X - _lastPoint.X;
var top = p.Y - _lastPoint.Y;
left = MathUtilities.Clamp(left, 0, Bounds.Width - item.Bounds.Width);
top = MathUtilities.Clamp(top, 0, Bounds.Height - item.Bounds.Height);
Canvas.SetLeft(item, left);
Canvas.SetTop(item, top);
left = MathUtilities.Clamp(left, 0, Bounds.Width - parent.Bounds.Width);
top = MathUtilities.Clamp(top, 0, Bounds.Height - parent.Bounds.Height);
Canvas.SetLeft(parent, left);
Canvas.SetTop(parent, top);
}
}
}
@@ -55,7 +72,22 @@ public class OverlayDialogHost: Canvas
base.OnPointerPressed(e);
if (e.Source is Control item)
{
_lastPoint = e.GetPosition(item);
var parent = item.FindAncestorOfType<DialogControl>();
if (parent is null)
{
return;
}
_lastPoint = e.GetPosition(parent);
}
}
public void AddDialog(DialogControl control)
{
this.Children.Add(control);
}
public void AddModalDialog(DialogControl control)
{
this.Children.Add(control);
}
}