feat: clean up code, allow empty host, simplify z index calculation.

This commit is contained in:
rabbitism
2024-01-24 01:27:47 +08:00
parent e06d6ffb25
commit 9441d7577e
6 changed files with 81 additions and 54 deletions

View File

@@ -40,6 +40,6 @@ public partial class DialogWithActionViewModel: ObservableObject, IDialogContext
private async Task ShowDialog()
{
await DialogBox.ShowOverlayModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(new DialogWithActionViewModel(), "GlobalHost");
await OverlayDialog.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(new DialogWithActionViewModel());
}
}

View File

@@ -45,25 +45,25 @@ public class DialogDemoViewModel: ObservableObject
private void ShowGlobalOverlayDialog()
{
DialogBox.ShowOverlay<DialogWithAction, DialogWithActionViewModel>(new DialogWithActionViewModel(), "GlobalHost");
OverlayDialog.Show<DialogWithAction, DialogWithActionViewModel>(new DialogWithActionViewModel());
}
private async Task ShowGlobalModalDialog()
{
var result = await DialogBox.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(DialogViewModel);
var result = await Dialog.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(DialogViewModel);
Result = result;
}
private async Task ShowGlobalOverlayModalDialog()
{
Result = await DialogBox.ShowOverlayModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(DialogViewModel, "GlobalHost");
Result = await OverlayDialog.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(DialogViewModel);
}
private async Task ShowLocalOverlayModalDialog()
{
var vm = new DialogWithActionViewModel();
var result = await DialogBox.ShowOverlayModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(
DialogViewModel, "LocalHost", new DialogOptions(){ ExtendToClientArea = true });
var result = await OverlayDialog.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(
DialogViewModel, new DialogOptions() { ExtendToClientArea = true }, "LocalHost");
Result = result;
}
}

View File

@@ -80,7 +80,7 @@
<converters:ViewLocator />
</ContentControl.ContentTemplate>
</ContentControl>
<u:OverlayDialogHost Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" HostId="GlobalHost" />
<u:OverlayDialogHost Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
</Grid>
</UserControl>

View File

@@ -6,39 +6,34 @@ using Avalonia.Media;
namespace Ursa.Controls;
public static class DialogBox
public static class Dialog
{
public static async Task<TResult?> ShowModalAsync<TView, TViewModel, TResult>(TViewModel vm)
where TView : Control, new()
{
var window = new DialogWindow()
{
Content = new TView(),
DataContext = vm,
};
var lifetime = Application.Current?.ApplicationLifetime;
if (lifetime is IClassicDesktopStyleApplicationLifetime classLifetime)
{
var main = classLifetime.MainWindow;
if (main is null)
var window = new DialogWindow
{
Content = new TView { DataContext = vm },
DataContext = vm,
};
if (classLifetime.MainWindow is not { } main)
{
window.Show();
return default(TResult);
}
else
{
var result = await window.ShowDialog<TResult>(main);
return result;
return default;
}
var result = await window.ShowDialog<TResult>(main);
return result;
}
else
{
return default(TResult);
}
return default(TResult);
}
public static async Task<TResult> ShowModalAsync<TView, TViewModel, TResult>(Window owner, TViewModel vm) where
TView: Control, new()
public static async Task<TResult> ShowModalAsync<TView, TViewModel, TResult>(Window owner, TViewModel? vm)
where TView: Control, new()
{
var window = new DialogWindow
{
@@ -47,9 +42,11 @@ public static class DialogBox
};
return await window.ShowDialog<TResult>(owner);
}
}
public static Task<TResult> ShowOverlayModalAsync<TView, TViewModel, TResult>(TViewModel vm, string hostId)
public static class OverlayDialog
{
public static Task<TResult> ShowModalAsync<TView, TViewModel, TResult>(TViewModel vm, string? hostId = null)
where TView : Control, new()
{
var t = new DialogControl()
@@ -62,8 +59,7 @@ public static class DialogBox
return t.ShowAsync<TResult>();
}
public static Task<TResult> ShowOverlayModalAsync<TView, TViewModel, TResult>(TViewModel vm, string hostId,
DialogOptions options)
public static Task<TResult> ShowModalAsync<TView, TViewModel, TResult>(TViewModel vm, DialogOptions options, string? hostId = null)
where TView : Control, new()
{
var t = new DialogControl()
@@ -78,7 +74,7 @@ public static class DialogBox
return t.ShowAsync<TResult>();
}
public static void ShowOverlay<TView, TViewModel>(TViewModel vm, string hostId)
public static void Show<TView, TViewModel>(TViewModel vm, string? hostId = null)
where TView: Control, new()
{
var t = new DialogControl()
@@ -90,7 +86,7 @@ public static class DialogBox
host?.AddDialog(t);
}
public static void ShowOverlay<TView, TViewModel>(TViewModel vm, string hostId, DialogOptions options)
public static void Show<TView, TViewModel>(TViewModel vm, DialogOptions options, string? hostId)
where TView: Control, new()
{
var t = new DialogControl()

View File

@@ -1,13 +1,9 @@
using System.Collections.Specialized;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace Ursa.Controls;
@@ -53,7 +49,7 @@ public class OverlayDialogHost : Canvas
for (int i = 0; i < _masks.Count; i++)
{
_masks[i].Width = this.Bounds.Width;
_masks[i].Width = this.Bounds.Height;
_masks[i].Height = this.Bounds.Height;
}
}
@@ -94,9 +90,9 @@ public class OverlayDialogHost : Canvas
{
this.Children.Add(control);
_dialogs.Add(control);
control.ZIndex = Children.Last().ZIndex + 1;
control.OnClose += OnDialogClose;
control.OnLayerChange += OnDialogLayerChange;
ResetZIndices();
}
private void OnDialogClose(object sender, object? e)
@@ -124,32 +120,31 @@ public class OverlayDialogHost : Canvas
}
}
}
ResetZIndices();
}
}
/// <summary>
/// Add a dialog as a modal dialog to the host
/// </summary>
/// <param name="control"></param>
internal void AddModalDialog(DialogControl control)
{
var mask = CreateOverlayMask();
_masks.Add(mask);
_modalDialogs.Add(control);
int start = _dialogs.LastOrDefault()?.ZIndex ?? 1;
for (int i = 0; i < _masks.Count; i += 1)
{
_masks[i].ZIndex = start + 2 * i;
_modalDialogs[i].ZIndex = start + 2 * i + 1;
}
for (int i = 0; i < _masks.Count-1; i++)
{
_masks[i].Opacity = 0.5;
}
ResetZIndices();
this.Children.Add(mask);
this.Children.Add(control);
control.OnClose += OnDialogClose;
control.OnLayerChange += OnDialogLayerChange;
}
// Handle dialog layer change event
private void OnDialogLayerChange(object sender, DialogLayerChangeEventArgs e)
{
if (sender is not DialogControl control)
@@ -188,4 +183,21 @@ public class OverlayDialogHost : Canvas
}
}
private void ResetZIndices()
{
int index = 0;
for ( int i = 0; i< _dialogs.Count; i++)
{
_dialogs[i].ZIndex = index;
index++;
}
for(int i = 0; i< _masks.Count; i++)
{
_masks[i].ZIndex = index;
index++;
_modalDialogs[i].ZIndex = index;
index++;
}
}
}

View File

@@ -4,20 +4,39 @@ namespace Ursa.Controls;
internal static class OverlayDialogManager
{
private static ConcurrentDictionary<string, OverlayDialogHost> _hosts = new();
private static OverlayDialogHost? _defaultHost;
private static readonly ConcurrentDictionary<string, OverlayDialogHost> Hosts = new();
public static void RegisterOverlayDialogHost(OverlayDialogHost host, string id)
public static void RegisterOverlayDialogHost(OverlayDialogHost host, string? id)
{
_hosts.TryAdd(id, host);
if (id == null)
{
if (_defaultHost != null)
{
throw new InvalidOperationException("Cannot register multiple OverlayDialogHost with empty HostId");
}
_defaultHost = host;
return;
}
Hosts.TryAdd(id, host);
}
public static void UnregisterOverlayDialogHost(string id)
public static void UnregisterOverlayDialogHost(string? id)
{
_hosts.TryRemove(id, out _);
if (id is null)
{
_defaultHost = null;
return;
}
Hosts.TryRemove(id, out _);
}
public static OverlayDialogHost? GetOverlayDialogHost(string id)
public static OverlayDialogHost? GetOverlayDialogHost(string? id)
{
return _hosts.TryGetValue(id, out var host) ? host : null;
if (id is null)
{
return _defaultHost;
}
return Hosts.TryGetValue(id, out var host) ? host : null;
}
}