feat: OverlayDialogHost remake: support host with same id in different toplevel. support modal status propagation.
This commit is contained in:
@@ -20,7 +20,13 @@
|
||||
<converters:IconNameToPathConverter x:Key="IconConverter" />
|
||||
</UserControl.Resources>
|
||||
<Panel>
|
||||
<Panel.Styles>
|
||||
<Style Selector="Grid.Blur">
|
||||
<Setter Property="Effect" Value="blur(10)"></Setter>
|
||||
</Style>
|
||||
</Panel.Styles>
|
||||
<Grid
|
||||
Classes.Blur="{Binding $parent[u:UrsaWindow].(u:OverlayDialogHost.IsInModalStatus)}"
|
||||
ColumnDefinitions="Auto, *" >
|
||||
<Border
|
||||
Padding="8 4"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<Setter Property="FontFamily" Value="{DynamicResource DefaultFontFamily}" />
|
||||
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="-1" />
|
||||
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True" />
|
||||
<Setter Property="u:OverlayDialogHost.IsModalStatusScope" Value="True"/>
|
||||
<Setter Property="SystemDecorations">
|
||||
<OnPlatform>
|
||||
<OnPlatform.Default>
|
||||
|
||||
@@ -46,4 +46,8 @@ public class OverlayDialogOptions
|
||||
public bool ShowCloseButton { get; set; } = true;
|
||||
public bool CanLightDismiss { get; set; }
|
||||
public bool CanDragMove { get; set; } = true;
|
||||
/// <summary>
|
||||
/// The hash code of the top level dialog host. This is used to identify the dialog host if there are multiple dialog hosts with the same id. If this is not provided, the dialog will be added to the first dialog host with the same id.
|
||||
/// </summary>
|
||||
public int? TopLevelHashCode { get; set; }
|
||||
}
|
||||
@@ -11,7 +11,7 @@ public static class OverlayDialog
|
||||
OverlayDialogOptions? options = null)
|
||||
where TView : Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
@@ -25,7 +25,7 @@ public static class OverlayDialog
|
||||
public static void Show(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
@@ -39,7 +39,7 @@ public static class OverlayDialog
|
||||
|
||||
public static void Show(object? vm, string? hostId = null, OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl();
|
||||
@@ -57,7 +57,7 @@ public static class OverlayDialog
|
||||
OverlayDialogOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
@@ -71,7 +71,7 @@ public static class OverlayDialog
|
||||
public static void ShowCustom(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
@@ -85,7 +85,7 @@ public static class OverlayDialog
|
||||
public static void ShowCustom(object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
@@ -103,7 +103,7 @@ public static class OverlayDialog
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
@@ -118,7 +118,7 @@ public static class OverlayDialog
|
||||
public static Task<DialogResult> ShowModal(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
@@ -134,7 +134,7 @@ public static class OverlayDialog
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
@@ -149,7 +149,7 @@ public static class OverlayDialog
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
@@ -164,7 +164,7 @@ public static class OverlayDialog
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
@@ -227,7 +227,7 @@ public static class OverlayDialog
|
||||
|
||||
internal static T? Recall<T>(string? hostId) where T: Control
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, null);
|
||||
if (host is null) return null;
|
||||
var item = host.Recall<T>();
|
||||
return item;
|
||||
|
||||
@@ -8,14 +8,14 @@ namespace Ursa.Controls;
|
||||
public static class Drawer
|
||||
{
|
||||
public static void Show<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
where TView : Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
var drawer = new DefaultDrawerControl
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
@@ -24,12 +24,12 @@ public static class Drawer
|
||||
public static void Show(Control control, object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
var drawer = new DefaultDrawerControl
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
@@ -37,29 +37,30 @@ public static class Drawer
|
||||
|
||||
public static void Show(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
if (view is null) view = new ContentControl { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
var drawer = new DefaultDrawerControl
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
|
||||
public static Task<DialogResult> ShowModal<TView, TViewModel>(TViewModel vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
where TView : Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var drawer = new DefaultDrawerControl()
|
||||
var drawer = new DefaultDrawerControl
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
@@ -69,12 +70,12 @@ public static class Drawer
|
||||
public static Task<DialogResult> ShowModal(Control control, object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var drawer = new DefaultDrawerControl()
|
||||
var drawer = new DefaultDrawerControl
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
@@ -83,110 +84,114 @@ public static class Drawer
|
||||
|
||||
public static Task<DialogResult> ShowModal(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
if (view is null) view = new ContentControl { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
var drawer = new DefaultDrawerControl
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static void ShowCustom<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
|
||||
public static void ShowCustom<TView, TViewModel>(TViewModel vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
where TView : Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var dialog = new CustomDrawerControl()
|
||||
var dialog = new CustomDrawerControl
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
}
|
||||
|
||||
|
||||
public static void ShowCustom(Control control, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var dialog = new CustomDrawerControl()
|
||||
var dialog = new CustomDrawerControl
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
}
|
||||
|
||||
|
||||
public static void ShowCustom(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
if (view is null) view = new ContentControl { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var dialog = new CustomDrawerControl()
|
||||
var dialog = new CustomDrawerControl
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TView, TViewModel, TResult>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TView, TViewModel, TResult>(TViewModel vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
where TView : Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var dialog = new CustomDrawerControl()
|
||||
var dialog = new CustomDrawerControl
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(Control control, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(Control control, object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var dialog = new CustomDrawerControl()
|
||||
var dialog = new CustomDrawerControl
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, options?.TopLevelHashCode);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
if (view is null) view = new ContentControl { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var dialog = new CustomDrawerControl()
|
||||
var dialog = new CustomDrawerControl
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
DataContext = vm
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
|
||||
private static void ConfigureCustomDrawer(CustomDrawerControl drawer, DrawerOptions? options)
|
||||
{
|
||||
options ??= DrawerOptions.Default;
|
||||
@@ -198,13 +203,14 @@ public static class Drawer
|
||||
drawer.MinWidth = options.MinWidth ?? 0.0;
|
||||
drawer.MaxWidth = options.MaxWidth ?? double.PositiveInfinity;
|
||||
}
|
||||
|
||||
if (options.Position is Position.Top or Position.Bottom)
|
||||
{
|
||||
drawer.MinHeight = options.MinHeight ?? 0.0;
|
||||
drawer.MaxHeight = options.MaxHeight ?? double.PositiveInfinity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void ConfigureDefaultDrawer(DefaultDrawerControl drawer, DrawerOptions? options)
|
||||
{
|
||||
options ??= DrawerOptions.Default;
|
||||
@@ -218,6 +224,7 @@ public static class Drawer
|
||||
drawer.MinWidth = options.MinWidth ?? 0.0;
|
||||
drawer.MaxWidth = options.MaxWidth ?? double.PositiveInfinity;
|
||||
}
|
||||
|
||||
if (options.Position is Position.Top or Position.Bottom)
|
||||
{
|
||||
drawer.MinHeight = options.MinHeight ?? 0.0;
|
||||
|
||||
@@ -15,4 +15,8 @@ public class DrawerOptions
|
||||
public DialogButton Buttons { get; set; } = DialogButton.OKCancel;
|
||||
public string? Title { get; set; }
|
||||
public bool ShowCloseButton { get; set; } = true;
|
||||
/// <summary>
|
||||
/// The hash code of the top level dialog host. This is used to identify the dialog host if there are multiple dialog hosts with the same id. If this is not provided, the dialog will be added to the first dialog host with the same id.
|
||||
/// </summary>
|
||||
public int? TopLevelHashCode { get; set; }
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public static class MessageBox
|
||||
{
|
||||
public static async Task<MessageBoxResult> ShowAsync(
|
||||
string message,
|
||||
string message,
|
||||
string? title = null,
|
||||
MessageBoxIcon icon = MessageBoxIcon.None,
|
||||
MessageBoxButton button = MessageBoxButton.OKCancel)
|
||||
@@ -18,33 +16,25 @@ public static class MessageBox
|
||||
{
|
||||
Content = message,
|
||||
Title = title,
|
||||
MessageIcon = icon,
|
||||
MessageIcon = icon
|
||||
};
|
||||
var lifetime = Application.Current?.ApplicationLifetime;
|
||||
if (lifetime is IClassicDesktopStyleApplicationLifetime classLifetime)
|
||||
{
|
||||
var main = classLifetime.MainWindow;
|
||||
if (main is null)
|
||||
{
|
||||
messageWindow.Show();
|
||||
return MessageBoxResult.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await messageWindow.ShowDialog<MessageBoxResult>(main);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (lifetime is not IClassicDesktopStyleApplicationLifetime classLifetime) return MessageBoxResult.None;
|
||||
var main = classLifetime.MainWindow;
|
||||
if (main is null)
|
||||
{
|
||||
messageWindow.Show();
|
||||
return MessageBoxResult.None;
|
||||
}
|
||||
|
||||
var result = await messageWindow.ShowDialog<MessageBoxResult>(main);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static async Task<MessageBoxResult> ShowAsync(
|
||||
Window owner,
|
||||
string message,
|
||||
string title,
|
||||
string message,
|
||||
string title,
|
||||
MessageBoxIcon icon = MessageBoxIcon.None,
|
||||
MessageBoxButton button = MessageBoxButton.OKCancel)
|
||||
{
|
||||
@@ -52,7 +42,7 @@ public static class MessageBox
|
||||
{
|
||||
Content = message,
|
||||
Title = title,
|
||||
MessageIcon = icon,
|
||||
MessageIcon = icon
|
||||
};
|
||||
var result = await messageWindow.ShowDialog<MessageBoxResult>(owner);
|
||||
return result;
|
||||
@@ -63,16 +53,17 @@ public static class MessageBox
|
||||
string? title = null,
|
||||
string? hostId = null,
|
||||
MessageBoxIcon icon = MessageBoxIcon.None,
|
||||
MessageBoxButton button = MessageBoxButton.OKCancel)
|
||||
MessageBoxButton button = MessageBoxButton.OKCancel,
|
||||
int? toplevelHashCode = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
var host = OverlayDialogManager.GetHost(hostId, toplevelHashCode);
|
||||
if (host is null) return MessageBoxResult.None;
|
||||
var messageControl = new MessageBoxControl()
|
||||
var messageControl = new MessageBoxControl
|
||||
{
|
||||
Content = message,
|
||||
Title = title,
|
||||
Buttons = button,
|
||||
MessageIcon = icon,
|
||||
MessageIcon = icon
|
||||
};
|
||||
host.AddModalDialog(messageControl);
|
||||
var result = await messageControl.ShowAsync<MessageBoxResult>();
|
||||
|
||||
@@ -129,7 +129,7 @@ public partial class OverlayDialogHost
|
||||
if (layer.Modal)
|
||||
{
|
||||
_modalCount--;
|
||||
HasModal = _modalCount > 0;
|
||||
IsInModalStatus = _modalCount > 0;
|
||||
if (!IsAnimationDisabled)
|
||||
{
|
||||
await _maskDisappearAnimation.RunAsync(layer.Mask);
|
||||
@@ -170,7 +170,7 @@ public partial class OverlayDialogHost
|
||||
_maskAppearAnimation.RunAsync(mask);
|
||||
}
|
||||
_modalCount++;
|
||||
HasModal = _modalCount > 0;
|
||||
IsInModalStatus = _modalCount > 0;
|
||||
control.IsClosed = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public partial class OverlayDialogHost
|
||||
control.Arrange(new Rect(control.DesiredSize));
|
||||
SetDrawerPosition(control);
|
||||
_modalCount++;
|
||||
HasModal = _modalCount > 0;
|
||||
IsInModalStatus = _modalCount > 0;
|
||||
control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDrawerControlClosing);
|
||||
var animation = CreateAnimation(control.Bounds.Size, control.Position);
|
||||
if (IsAnimationDisabled)
|
||||
@@ -162,7 +162,7 @@ public partial class OverlayDialogHost
|
||||
if (layer.Mask is not null)
|
||||
{
|
||||
_modalCount--;
|
||||
HasModal = _modalCount > 0;
|
||||
IsInModalStatus = _modalCount > 0;
|
||||
layer.Mask.RemoveHandler(PointerPressedEvent, ClickMaskToCloseDialog);
|
||||
if (!IsAnimationDisabled)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,8 @@ using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Ursa.Controls.OverlayShared;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.VisualTree;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Irihi.Avalonia.Shared.Shapes;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
@@ -32,18 +34,35 @@ public partial class OverlayDialogHost: Canvas
|
||||
}
|
||||
|
||||
private int _modalCount = 0;
|
||||
|
||||
|
||||
|
||||
public static readonly DirectProperty<OverlayDialogHost, bool> HasModalProperty = AvaloniaProperty.RegisterDirect<OverlayDialogHost, bool>(
|
||||
nameof(HasModal), o => o.HasModal);
|
||||
private bool _hasModal;
|
||||
[Obsolete("Use IsInModalStatus")]
|
||||
public bool HasModal
|
||||
{
|
||||
get => _hasModal;
|
||||
private set => SetAndRaise(HasModalProperty, ref _hasModal, value);
|
||||
}
|
||||
|
||||
public static readonly AttachedProperty<bool> IsModalStatusScopeProperty =
|
||||
AvaloniaProperty.RegisterAttached<OverlayDialogHost, Control, bool>("IsModalStatusScope");
|
||||
|
||||
public static void SetIsModalStatusScope(Control obj, bool value) => obj.SetValue(IsModalStatusScopeProperty, value);
|
||||
internal static bool GetIsModalStatusScope(Control obj) => obj.GetValue(IsModalStatusScopeProperty);
|
||||
|
||||
public static readonly AttachedProperty<bool> IsInModalStatusProperty =
|
||||
AvaloniaProperty.RegisterAttached<OverlayDialogHost, Control, bool>(nameof(IsInModalStatus));
|
||||
|
||||
internal static void SetIsInModalStatus(Control obj, bool value) => obj.SetValue(IsInModalStatusProperty, value);
|
||||
public static bool GetIsInModalStatus(Control obj) => obj.GetValue(IsInModalStatusProperty);
|
||||
|
||||
public bool IsInModalStatus
|
||||
{
|
||||
get => GetValue(IsInModalStatusProperty);
|
||||
set => SetValue(IsInModalStatusProperty, value);
|
||||
}
|
||||
|
||||
public bool IsAnimationDisabled { get; set; }
|
||||
|
||||
static OverlayDialogHost()
|
||||
@@ -51,6 +70,11 @@ public partial class OverlayDialogHost: Canvas
|
||||
ClipToBoundsProperty.OverrideDefaultValue<OverlayDialogHost>(true);
|
||||
_maskAppearAnimation = CreateOpacityAnimation(true);
|
||||
_maskDisappearAnimation = CreateOpacityAnimation(false);
|
||||
// This is only a temporary solution, will be removed in release candidate mode.
|
||||
IsInModalStatusProperty.Changed.AddClassHandler<OverlayDialogHost, bool>((host, args) =>
|
||||
{
|
||||
host.HasModal = args.NewValue.Value;
|
||||
});
|
||||
}
|
||||
|
||||
private static Animation CreateOpacityAnimation(bool appear)
|
||||
@@ -116,11 +140,18 @@ public partial class OverlayDialogHost: Canvas
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IDisposable? _modalStatusSubscription;
|
||||
protected sealed override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
OverlayDialogManager.RegisterHost(this, HostId);
|
||||
var hash = TopLevel.GetTopLevel(this)?.GetHashCode();
|
||||
var modalHost = this.GetVisualAncestors().OfType<Control>().FirstOrDefault(GetIsModalStatusScope);
|
||||
if (modalHost is not null)
|
||||
{
|
||||
_modalStatusSubscription = this.GetObservable(IsInModalStatusProperty)
|
||||
.Subscribe(a => OverlayDialogHost.SetIsInModalStatus(modalHost, a));
|
||||
}
|
||||
OverlayDialogManager.RegisterHost(this, HostId, hash);
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
@@ -129,7 +160,9 @@ public partial class OverlayDialogHost: Canvas
|
||||
{
|
||||
_layers[0].Element.Close();
|
||||
}
|
||||
OverlayDialogManager.UnregisterHost(HostId);
|
||||
_modalStatusSubscription?.Dispose();
|
||||
var hash = TopLevel.GetTopLevel(this)?.GetHashCode();
|
||||
OverlayDialogManager.UnregisterHost(HostId, hash);
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,41 +2,27 @@ using System.Collections.Concurrent;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
internal record struct HostKey(string? Id, int? Hash);
|
||||
|
||||
internal static class OverlayDialogManager
|
||||
{
|
||||
private static OverlayDialogHost? _defaultHost;
|
||||
private static readonly ConcurrentDictionary<string, OverlayDialogHost> Hosts = new();
|
||||
private static readonly ConcurrentDictionary<HostKey, OverlayDialogHost> Hosts = new();
|
||||
|
||||
public static void RegisterHost(OverlayDialogHost host, string? id)
|
||||
public static void RegisterHost(OverlayDialogHost host, string? id, int? hash)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
if (_defaultHost != null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot register multiple OverlayDialogHost with empty HostId");
|
||||
}
|
||||
_defaultHost = host;
|
||||
return;
|
||||
}
|
||||
Hosts.TryAdd(id, host);
|
||||
Hosts.TryAdd(new HostKey(id, hash), host);
|
||||
}
|
||||
|
||||
public static void UnregisterHost(string? id)
|
||||
public static void UnregisterHost(string? id, int? hash)
|
||||
{
|
||||
if (id is null)
|
||||
{
|
||||
_defaultHost = null;
|
||||
return;
|
||||
}
|
||||
Hosts.TryRemove(id, out _);
|
||||
Hosts.TryRemove(new HostKey(id, hash), out _);
|
||||
}
|
||||
|
||||
public static OverlayDialogHost? GetHost(string? id)
|
||||
public static OverlayDialogHost? GetHost(string? id, int? hash)
|
||||
{
|
||||
if (id is null)
|
||||
{
|
||||
return _defaultHost;
|
||||
}
|
||||
return Hosts.TryGetValue(id, out var host) ? host : null;
|
||||
HostKey? key = hash is null ? Hosts.Keys.Where(k => k.Id == id).ToArray().FirstOrDefault() : Hosts.Keys.FirstOrDefault(k => k.Id == id && k.Hash == hash);
|
||||
if (key is null) return null;
|
||||
return Hosts.TryGetValue(key.Value, out var host) ? host : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user