diff --git a/demo/Ursa.Demo/Dialogs/DialogWithActionViewModel.cs b/demo/Ursa.Demo/Dialogs/DialogWithActionViewModel.cs index f846146..87aa3b4 100644 --- a/demo/Ursa.Demo/Dialogs/DialogWithActionViewModel.cs +++ b/demo/Ursa.Demo/Dialogs/DialogWithActionViewModel.cs @@ -40,6 +40,6 @@ public partial class DialogWithActionViewModel: ObservableObject, IDialogContext private async Task ShowDialog() { - await DialogBox.ShowOverlayModalAsync(new DialogWithActionViewModel(), "GlobalHost"); + await OverlayDialog.ShowModalAsync(new DialogWithActionViewModel()); } } \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/DialogDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/DialogDemoViewModel.cs index 342ab0a..b1758dd 100644 --- a/demo/Ursa.Demo/ViewModels/DialogDemoViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/DialogDemoViewModel.cs @@ -45,25 +45,25 @@ public class DialogDemoViewModel: ObservableObject private void ShowGlobalOverlayDialog() { - DialogBox.ShowOverlay(new DialogWithActionViewModel(), "GlobalHost"); + OverlayDialog.Show(new DialogWithActionViewModel()); } private async Task ShowGlobalModalDialog() { - var result = await DialogBox.ShowModalAsync(DialogViewModel); + var result = await Dialog.ShowModalAsync(DialogViewModel); Result = result; } private async Task ShowGlobalOverlayModalDialog() { - Result = await DialogBox.ShowOverlayModalAsync(DialogViewModel, "GlobalHost"); + Result = await OverlayDialog.ShowModalAsync(DialogViewModel); } private async Task ShowLocalOverlayModalDialog() { var vm = new DialogWithActionViewModel(); - var result = await DialogBox.ShowOverlayModalAsync( - DialogViewModel, "LocalHost", new DialogOptions(){ ExtendToClientArea = true }); + var result = await OverlayDialog.ShowModalAsync( + DialogViewModel, new DialogOptions() { ExtendToClientArea = true }, "LocalHost"); Result = result; } } \ No newline at end of file diff --git a/demo/Ursa.Demo/Views/MainView.axaml b/demo/Ursa.Demo/Views/MainView.axaml index b6f6bb6..2a5bce2 100644 --- a/demo/Ursa.Demo/Views/MainView.axaml +++ b/demo/Ursa.Demo/Views/MainView.axaml @@ -80,7 +80,7 @@ - + diff --git a/src/Ursa/Controls/Dialog/DialogBox.cs b/src/Ursa/Controls/Dialog/Dialog.cs similarity index 69% rename from src/Ursa/Controls/Dialog/DialogBox.cs rename to src/Ursa/Controls/Dialog/Dialog.cs index fe27fa7..a293f4d 100644 --- a/src/Ursa/Controls/Dialog/DialogBox.cs +++ b/src/Ursa/Controls/Dialog/Dialog.cs @@ -6,39 +6,34 @@ using Avalonia.Media; namespace Ursa.Controls; -public static class DialogBox +public static class Dialog { public static async Task ShowModalAsync(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(main); - return result; + return default; } + var result = await window.ShowDialog(main); + return result; } - else - { - return default(TResult); - } + + return default(TResult); } - public static async Task ShowModalAsync(Window owner, TViewModel vm) where - TView: Control, new() + public static async Task ShowModalAsync(Window owner, TViewModel? vm) + where TView: Control, new() { var window = new DialogWindow { @@ -47,9 +42,11 @@ public static class DialogBox }; return await window.ShowDialog(owner); } - +} - public static Task ShowOverlayModalAsync(TViewModel vm, string hostId) +public static class OverlayDialog +{ + public static Task ShowModalAsync(TViewModel vm, string? hostId = null) where TView : Control, new() { var t = new DialogControl() @@ -62,8 +59,7 @@ public static class DialogBox return t.ShowAsync(); } - public static Task ShowOverlayModalAsync(TViewModel vm, string hostId, - DialogOptions options) + public static Task ShowModalAsync(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(); } - public static void ShowOverlay(TViewModel vm, string hostId) + public static void Show(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(TViewModel vm, string hostId, DialogOptions options) + public static void Show(TViewModel vm, DialogOptions options, string? hostId) where TView: Control, new() { var t = new DialogControl() diff --git a/src/Ursa/Controls/Dialog/OverlayDialogHost.cs b/src/Ursa/Controls/Dialog/OverlayDialogHost.cs index edb928e..3cba9b6 100644 --- a/src/Ursa/Controls/Dialog/OverlayDialogHost.cs +++ b/src/Ursa/Controls/Dialog/OverlayDialogHost.cs @@ -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(); } } + /// + /// Add a dialog as a modal dialog to the host + /// + /// 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++; + } + } } \ No newline at end of file diff --git a/src/Ursa/Controls/Dialog/OverlayDialogManager.cs b/src/Ursa/Controls/Dialog/OverlayDialogManager.cs index 1dc1480..1a0a0c0 100644 --- a/src/Ursa/Controls/Dialog/OverlayDialogManager.cs +++ b/src/Ursa/Controls/Dialog/OverlayDialogManager.cs @@ -4,20 +4,39 @@ namespace Ursa.Controls; internal static class OverlayDialogManager { - private static ConcurrentDictionary _hosts = new(); + private static OverlayDialogHost? _defaultHost; + private static readonly ConcurrentDictionary 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; } } \ No newline at end of file