feat: clean up code, allow empty host, simplify z index calculation.
This commit is contained in:
@@ -40,6 +40,6 @@ public partial class DialogWithActionViewModel: ObservableObject, IDialogContext
|
|||||||
|
|
||||||
private async Task ShowDialog()
|
private async Task ShowDialog()
|
||||||
{
|
{
|
||||||
await DialogBox.ShowOverlayModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(new DialogWithActionViewModel(), "GlobalHost");
|
await OverlayDialog.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(new DialogWithActionViewModel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,25 +45,25 @@ public class DialogDemoViewModel: ObservableObject
|
|||||||
|
|
||||||
private void ShowGlobalOverlayDialog()
|
private void ShowGlobalOverlayDialog()
|
||||||
{
|
{
|
||||||
DialogBox.ShowOverlay<DialogWithAction, DialogWithActionViewModel>(new DialogWithActionViewModel(), "GlobalHost");
|
OverlayDialog.Show<DialogWithAction, DialogWithActionViewModel>(new DialogWithActionViewModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ShowGlobalModalDialog()
|
private async Task ShowGlobalModalDialog()
|
||||||
{
|
{
|
||||||
var result = await DialogBox.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(DialogViewModel);
|
var result = await Dialog.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(DialogViewModel);
|
||||||
Result = result;
|
Result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ShowGlobalOverlayModalDialog()
|
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()
|
private async Task ShowLocalOverlayModalDialog()
|
||||||
{
|
{
|
||||||
var vm = new DialogWithActionViewModel();
|
var vm = new DialogWithActionViewModel();
|
||||||
var result = await DialogBox.ShowOverlayModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(
|
var result = await OverlayDialog.ShowModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(
|
||||||
DialogViewModel, "LocalHost", new DialogOptions(){ ExtendToClientArea = true });
|
DialogViewModel, new DialogOptions() { ExtendToClientArea = true }, "LocalHost");
|
||||||
Result = result;
|
Result = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
<converters:ViewLocator />
|
<converters:ViewLocator />
|
||||||
</ContentControl.ContentTemplate>
|
</ContentControl.ContentTemplate>
|
||||||
</ContentControl>
|
</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>
|
</Grid>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -6,39 +6,34 @@ using Avalonia.Media;
|
|||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
public static class DialogBox
|
public static class Dialog
|
||||||
{
|
{
|
||||||
public static async Task<TResult?> ShowModalAsync<TView, TViewModel, TResult>(TViewModel vm)
|
public static async Task<TResult?> ShowModalAsync<TView, TViewModel, TResult>(TViewModel vm)
|
||||||
where TView : Control, new()
|
where TView : Control, new()
|
||||||
{
|
{
|
||||||
var window = new DialogWindow()
|
|
||||||
{
|
|
||||||
Content = new TView(),
|
|
||||||
DataContext = vm,
|
|
||||||
};
|
|
||||||
var lifetime = Application.Current?.ApplicationLifetime;
|
var lifetime = Application.Current?.ApplicationLifetime;
|
||||||
if (lifetime is IClassicDesktopStyleApplicationLifetime classLifetime)
|
if (lifetime is IClassicDesktopStyleApplicationLifetime classLifetime)
|
||||||
{
|
{
|
||||||
var main = classLifetime.MainWindow;
|
var window = new DialogWindow
|
||||||
if (main is null)
|
{
|
||||||
|
Content = new TView { DataContext = vm },
|
||||||
|
DataContext = vm,
|
||||||
|
};
|
||||||
|
if (classLifetime.MainWindow is not { } main)
|
||||||
{
|
{
|
||||||
window.Show();
|
window.Show();
|
||||||
return default(TResult);
|
return default;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var result = await window.ShowDialog<TResult>(main);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
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
|
public static async Task<TResult> ShowModalAsync<TView, TViewModel, TResult>(Window owner, TViewModel? vm)
|
||||||
TView: Control, new()
|
where TView: Control, new()
|
||||||
{
|
{
|
||||||
var window = new DialogWindow
|
var window = new DialogWindow
|
||||||
{
|
{
|
||||||
@@ -47,9 +42,11 @@ public static class DialogBox
|
|||||||
};
|
};
|
||||||
return await window.ShowDialog<TResult>(owner);
|
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()
|
where TView : Control, new()
|
||||||
{
|
{
|
||||||
var t = new DialogControl()
|
var t = new DialogControl()
|
||||||
@@ -62,8 +59,7 @@ public static class DialogBox
|
|||||||
return t.ShowAsync<TResult>();
|
return t.ShowAsync<TResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<TResult> ShowOverlayModalAsync<TView, TViewModel, TResult>(TViewModel vm, string hostId,
|
public static Task<TResult> ShowModalAsync<TView, TViewModel, TResult>(TViewModel vm, DialogOptions options, string? hostId = null)
|
||||||
DialogOptions options)
|
|
||||||
where TView : Control, new()
|
where TView : Control, new()
|
||||||
{
|
{
|
||||||
var t = new DialogControl()
|
var t = new DialogControl()
|
||||||
@@ -78,7 +74,7 @@ public static class DialogBox
|
|||||||
return t.ShowAsync<TResult>();
|
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()
|
where TView: Control, new()
|
||||||
{
|
{
|
||||||
var t = new DialogControl()
|
var t = new DialogControl()
|
||||||
@@ -90,7 +86,7 @@ public static class DialogBox
|
|||||||
host?.AddDialog(t);
|
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()
|
where TView: Control, new()
|
||||||
{
|
{
|
||||||
var t = new DialogControl()
|
var t = new DialogControl()
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
using System.Collections.Specialized;
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
|
||||||
using Avalonia.Controls.Shapes;
|
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Utilities;
|
using Avalonia.Utilities;
|
||||||
using Avalonia.VisualTree;
|
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
@@ -53,7 +49,7 @@ public class OverlayDialogHost : Canvas
|
|||||||
for (int i = 0; i < _masks.Count; i++)
|
for (int i = 0; i < _masks.Count; i++)
|
||||||
{
|
{
|
||||||
_masks[i].Width = this.Bounds.Width;
|
_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);
|
this.Children.Add(control);
|
||||||
_dialogs.Add(control);
|
_dialogs.Add(control);
|
||||||
control.ZIndex = Children.Last().ZIndex + 1;
|
|
||||||
control.OnClose += OnDialogClose;
|
control.OnClose += OnDialogClose;
|
||||||
control.OnLayerChange += OnDialogLayerChange;
|
control.OnLayerChange += OnDialogLayerChange;
|
||||||
|
ResetZIndices();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDialogClose(object sender, object? e)
|
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)
|
internal void AddModalDialog(DialogControl control)
|
||||||
{
|
{
|
||||||
var mask = CreateOverlayMask();
|
var mask = CreateOverlayMask();
|
||||||
_masks.Add(mask);
|
_masks.Add(mask);
|
||||||
_modalDialogs.Add(control);
|
_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++)
|
for (int i = 0; i < _masks.Count-1; i++)
|
||||||
{
|
{
|
||||||
_masks[i].Opacity = 0.5;
|
_masks[i].Opacity = 0.5;
|
||||||
}
|
}
|
||||||
|
ResetZIndices();
|
||||||
this.Children.Add(mask);
|
this.Children.Add(mask);
|
||||||
this.Children.Add(control);
|
this.Children.Add(control);
|
||||||
control.OnClose += OnDialogClose;
|
control.OnClose += OnDialogClose;
|
||||||
control.OnLayerChange += OnDialogLayerChange;
|
control.OnLayerChange += OnDialogLayerChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle dialog layer change event
|
||||||
private void OnDialogLayerChange(object sender, DialogLayerChangeEventArgs e)
|
private void OnDialogLayerChange(object sender, DialogLayerChangeEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is not DialogControl control)
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,20 +4,39 @@ namespace Ursa.Controls;
|
|||||||
|
|
||||||
internal static class OverlayDialogManager
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user