Merge pull request #647 from irihitech/ursa_host
Make UrsaWindow/UrsaView's built in OverlayDialogHost part of logical tree.
This commit is contained in:
@@ -38,7 +38,7 @@
|
|||||||
IsVisible="{TemplateBinding IsTitleBarVisible}"
|
IsVisible="{TemplateBinding IsTitleBarVisible}"
|
||||||
Content="{TemplateBinding RightContent}" />
|
Content="{TemplateBinding RightContent}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<u:OverlayDialogHost IsModalStatusReporter="True" />
|
<u:OverlayDialogHost Name="{x:Static u:UrsaView.PART_DialogHost}" IsModalStatusReporter="True" />
|
||||||
</Panel>
|
</Panel>
|
||||||
</Panel>
|
</Panel>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
|
|||||||
@@ -74,7 +74,10 @@
|
|||||||
RightContent="{Binding $parent[u:UrsaWindow].RightContent}" />
|
RightContent="{Binding $parent[u:UrsaWindow].RightContent}" />
|
||||||
<VisualLayerManager>
|
<VisualLayerManager>
|
||||||
<Panel>
|
<Panel>
|
||||||
<u:OverlayDialogHost IsModalStatusReporter="True" IsTopLevel="True" />
|
<u:OverlayDialogHost
|
||||||
|
Name="{x:Static u:UrsaWindow.PART_DialogHost}"
|
||||||
|
IsModalStatusReporter="True"
|
||||||
|
IsTopLevel="True" />
|
||||||
<u:WindowResizer
|
<u:WindowResizer
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
|
|||||||
@@ -1,55 +1,103 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ursa window is designed to
|
/// Represents a custom content control with additional properties for managing a title bar and related content.
|
||||||
|
/// This control can be used as the top level container for platforms without windowing toplevel support.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UrsaView: ContentControl
|
public class UrsaView : ContentControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the dialog host part in the control template.
|
||||||
|
/// </summary>
|
||||||
|
public const string PART_DialogHost = "PART_DialogHost";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the visibility of the title bar.
|
||||||
|
/// </summary>
|
||||||
public static readonly StyledProperty<bool> IsTitleBarVisibleProperty =
|
public static readonly StyledProperty<bool> IsTitleBarVisibleProperty =
|
||||||
UrsaWindow.IsTitleBarVisibleProperty.AddOwner<UrsaView>();
|
UrsaWindow.IsTitleBarVisibleProperty.AddOwner<UrsaView>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the content on the left side of the control.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<object?> LeftContentProperty =
|
||||||
|
UrsaWindow.LeftContentProperty.AddOwner<UrsaView>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the content on the right side of the control.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<object?> RightContentProperty =
|
||||||
|
UrsaWindow.RightContentProperty.AddOwner<UrsaView>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the content of the title bar.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<object?> TitleBarContentProperty =
|
||||||
|
UrsaWindow.TitleBarContentProperty.AddOwner<UrsaView>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the margin of the title bar.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<Thickness> TitleBarMarginProperty =
|
||||||
|
UrsaWindow.TitleBarMarginProperty.AddOwner<UrsaView>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the title bar is visible.
|
||||||
|
/// </summary>
|
||||||
public bool IsTitleBarVisible
|
public bool IsTitleBarVisible
|
||||||
{
|
{
|
||||||
get => GetValue(IsTitleBarVisibleProperty);
|
get => GetValue(IsTitleBarVisibleProperty);
|
||||||
set => SetValue(IsTitleBarVisibleProperty, value);
|
set => SetValue(IsTitleBarVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> LeftContentProperty =
|
/// <summary>
|
||||||
UrsaWindow.LeftContentProperty.AddOwner<UrsaView>();
|
/// Gets or sets the content on the left side of the control.
|
||||||
|
/// </summary>
|
||||||
public object? LeftContent
|
public object? LeftContent
|
||||||
{
|
{
|
||||||
get => GetValue(LeftContentProperty);
|
get => GetValue(LeftContentProperty);
|
||||||
set => SetValue(LeftContentProperty, value);
|
set => SetValue(LeftContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> RightContentProperty =
|
/// <summary>
|
||||||
UrsaWindow.RightContentProperty.AddOwner<UrsaView>();
|
/// Gets or sets the content on the right side of the control.
|
||||||
|
/// </summary>
|
||||||
public object? RightContent
|
public object? RightContent
|
||||||
{
|
{
|
||||||
get => GetValue(RightContentProperty);
|
get => GetValue(RightContentProperty);
|
||||||
set => SetValue(RightContentProperty, value);
|
set => SetValue(RightContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> TitleBarContentProperty =
|
/// <summary>
|
||||||
UrsaWindow.TitleBarContentProperty.AddOwner<UrsaView>();
|
/// Gets or sets the content of the title bar.
|
||||||
|
/// </summary>
|
||||||
public object? TitleBarContent
|
public object? TitleBarContent
|
||||||
{
|
{
|
||||||
get => GetValue(TitleBarContentProperty);
|
get => GetValue(TitleBarContentProperty);
|
||||||
set => SetValue(TitleBarContentProperty, value);
|
set => SetValue(TitleBarContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<Thickness> TitleBarMarginProperty =
|
/// <summary>
|
||||||
UrsaWindow.TitleBarMarginProperty.AddOwner<UrsaView>();
|
/// Gets or sets the margin of the title bar.
|
||||||
|
/// </summary>
|
||||||
public Thickness TitleBarMargin
|
public Thickness TitleBarMargin
|
||||||
{
|
{
|
||||||
get => GetValue(TitleBarMarginProperty);
|
get => GetValue(TitleBarMarginProperty);
|
||||||
set => SetValue(TitleBarMarginProperty, value);
|
set => SetValue(TitleBarMarginProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the control template and initializes the dialog host if present.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">The event arguments containing the template information.</param>
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(e);
|
||||||
|
var host = e.NameScope.Find<OverlayDialogHost>(PART_DialogHost);
|
||||||
|
if (host is not null) LogicalChildren.Add(host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,112 +1,205 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ursa Window is an advanced Window control that provides a lot of features and customization options.
|
/// Ursa Window is an advanced Window control that provides a lot of features and customization options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UrsaWindow: Window
|
public class UrsaWindow : Window
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the dialog host part in the control template.
|
||||||
|
/// </summary>
|
||||||
|
public const string PART_DialogHost = "PART_DialogHost";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the visibility of the full-screen button.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsFullScreenButtonVisibleProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, bool>(
|
||||||
|
nameof(IsFullScreenButtonVisible));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the visibility of the minimize button.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsMinimizeButtonVisibleProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, bool>(
|
||||||
|
nameof(IsMinimizeButtonVisible), true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the visibility of the restore button.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsRestoreButtonVisibleProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, bool>(
|
||||||
|
nameof(IsRestoreButtonVisible), true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the visibility of the close button.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsCloseButtonVisibleProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, bool>(
|
||||||
|
nameof(IsCloseButtonVisible), true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the visibility of the title bar.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsTitleBarVisibleProperty = AvaloniaProperty.Register<UrsaWindow, bool>(
|
||||||
|
nameof(IsTitleBarVisible), true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the visibility of the managed resizer.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsManagedResizerVisibleProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, bool>(
|
||||||
|
nameof(IsManagedResizerVisible));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the content of the title bar.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<object?> TitleBarContentProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, object?>(
|
||||||
|
nameof(TitleBarContent));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the content on the left side of the window.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<object?> LeftContentProperty = AvaloniaProperty.Register<UrsaWindow, object?>(
|
||||||
|
nameof(LeftContent));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the content on the right side of the window.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<object?> RightContentProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, object?>(
|
||||||
|
nameof(RightContent));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the margin of the title bar.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<Thickness> TitleBarMarginProperty =
|
||||||
|
AvaloniaProperty.Register<UrsaWindow, Thickness>(
|
||||||
|
nameof(TitleBarMargin));
|
||||||
|
|
||||||
|
private bool _canClose;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the style key override for the control.
|
||||||
|
/// </summary>
|
||||||
protected override Type StyleKeyOverride => typeof(UrsaWindow);
|
protected override Type StyleKeyOverride => typeof(UrsaWindow);
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsFullScreenButtonVisibleProperty = AvaloniaProperty.Register<UrsaWindow, bool>(
|
/// <summary>
|
||||||
nameof(IsFullScreenButtonVisible));
|
/// Gets or sets a value indicating whether the full-screen button is visible.
|
||||||
|
/// </summary>
|
||||||
public bool IsFullScreenButtonVisible
|
public bool IsFullScreenButtonVisible
|
||||||
{
|
{
|
||||||
get => GetValue(IsFullScreenButtonVisibleProperty);
|
get => GetValue(IsFullScreenButtonVisibleProperty);
|
||||||
set => SetValue(IsFullScreenButtonVisibleProperty, value);
|
set => SetValue(IsFullScreenButtonVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsMinimizeButtonVisibleProperty = AvaloniaProperty.Register<UrsaWindow, bool>(
|
/// <summary>
|
||||||
nameof(IsMinimizeButtonVisible), true);
|
/// Gets or sets a value indicating whether the minimize button is visible.
|
||||||
|
/// </summary>
|
||||||
public bool IsMinimizeButtonVisible
|
public bool IsMinimizeButtonVisible
|
||||||
{
|
{
|
||||||
get => GetValue(IsMinimizeButtonVisibleProperty);
|
get => GetValue(IsMinimizeButtonVisibleProperty);
|
||||||
set => SetValue(IsMinimizeButtonVisibleProperty, value);
|
set => SetValue(IsMinimizeButtonVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsRestoreButtonVisibleProperty = AvaloniaProperty.Register<UrsaWindow, bool>(
|
/// <summary>
|
||||||
nameof(IsRestoreButtonVisible), true);
|
/// Gets or sets a value indicating whether the restore button is visible.
|
||||||
|
/// </summary>
|
||||||
public bool IsRestoreButtonVisible
|
public bool IsRestoreButtonVisible
|
||||||
{
|
{
|
||||||
get => GetValue(IsRestoreButtonVisibleProperty);
|
get => GetValue(IsRestoreButtonVisibleProperty);
|
||||||
set => SetValue(IsRestoreButtonVisibleProperty, value);
|
set => SetValue(IsRestoreButtonVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsCloseButtonVisibleProperty = AvaloniaProperty.Register<UrsaWindow, bool>(
|
/// <summary>
|
||||||
nameof(IsCloseButtonVisible), true);
|
/// Gets or sets a value indicating whether the close button is visible.
|
||||||
|
/// </summary>
|
||||||
public bool IsCloseButtonVisible
|
public bool IsCloseButtonVisible
|
||||||
{
|
{
|
||||||
get => GetValue(IsCloseButtonVisibleProperty);
|
get => GetValue(IsCloseButtonVisibleProperty);
|
||||||
set => SetValue(IsCloseButtonVisibleProperty, value);
|
set => SetValue(IsCloseButtonVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsTitleBarVisibleProperty = AvaloniaProperty.Register<UrsaWindow, bool>(
|
/// <summary>
|
||||||
nameof(IsTitleBarVisible), true);
|
/// Gets or sets a value indicating whether the title bar is visible.
|
||||||
|
/// </summary>
|
||||||
public bool IsTitleBarVisible
|
public bool IsTitleBarVisible
|
||||||
{
|
{
|
||||||
get => GetValue(IsTitleBarVisibleProperty);
|
get => GetValue(IsTitleBarVisibleProperty);
|
||||||
set => SetValue(IsTitleBarVisibleProperty, value);
|
set => SetValue(IsTitleBarVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsManagedResizerVisibleProperty = AvaloniaProperty.Register<UrsaWindow, bool>(
|
/// <summary>
|
||||||
nameof(IsManagedResizerVisible));
|
/// Gets or sets a value indicating whether the managed resizer is visible.
|
||||||
|
/// </summary>
|
||||||
public bool IsManagedResizerVisible
|
public bool IsManagedResizerVisible
|
||||||
{
|
{
|
||||||
get => GetValue(IsManagedResizerVisibleProperty);
|
get => GetValue(IsManagedResizerVisibleProperty);
|
||||||
set => SetValue(IsManagedResizerVisibleProperty, value);
|
set => SetValue(IsManagedResizerVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> TitleBarContentProperty = AvaloniaProperty.Register<UrsaWindow, object?>(
|
/// <summary>
|
||||||
nameof(TitleBarContent));
|
/// Gets or sets the content of the title bar.
|
||||||
|
/// </summary>
|
||||||
public object? TitleBarContent
|
public object? TitleBarContent
|
||||||
{
|
{
|
||||||
get => GetValue(TitleBarContentProperty);
|
get => GetValue(TitleBarContentProperty);
|
||||||
set => SetValue(TitleBarContentProperty, value);
|
set => SetValue(TitleBarContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> LeftContentProperty = AvaloniaProperty.Register<UrsaWindow, object?>(
|
/// <summary>
|
||||||
nameof(LeftContent));
|
/// Gets or sets the content on the left side of the window.
|
||||||
|
/// </summary>
|
||||||
public object? LeftContent
|
public object? LeftContent
|
||||||
{
|
{
|
||||||
get => GetValue(LeftContentProperty);
|
get => GetValue(LeftContentProperty);
|
||||||
set => SetValue(LeftContentProperty, value);
|
set => SetValue(LeftContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> RightContentProperty = AvaloniaProperty.Register<UrsaWindow, object?>(
|
/// <summary>
|
||||||
nameof(RightContent));
|
/// Gets or sets the content on the right side of the window.
|
||||||
|
/// </summary>
|
||||||
public object? RightContent
|
public object? RightContent
|
||||||
{
|
{
|
||||||
get => GetValue(RightContentProperty);
|
get => GetValue(RightContentProperty);
|
||||||
set => SetValue(RightContentProperty, value);
|
set => SetValue(RightContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<Thickness> TitleBarMarginProperty = AvaloniaProperty.Register<UrsaWindow, Thickness>(
|
/// <summary>
|
||||||
nameof(TitleBarMargin));
|
/// Gets or sets the margin of the title bar.
|
||||||
|
/// </summary>
|
||||||
public Thickness TitleBarMargin
|
public Thickness TitleBarMargin
|
||||||
{
|
{
|
||||||
get => GetValue(TitleBarMarginProperty);
|
get => GetValue(TitleBarMarginProperty);
|
||||||
set => SetValue(TitleBarMarginProperty, value);
|
set => SetValue(TitleBarMarginProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(e);
|
||||||
|
var host = e.NameScope.Find<OverlayDialogHost>(PART_DialogHost);
|
||||||
|
if (host is not null) LogicalChildren.Add(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the window can close.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task that resolves to true if the window can close; otherwise, false.</returns>
|
||||||
protected virtual async Task<bool> CanClose()
|
protected virtual async Task<bool> CanClose()
|
||||||
{
|
{
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _canClose = false;
|
/// <summary>
|
||||||
|
/// Handles the window closing event and determines whether the window should close.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">The event arguments for the closing event.</param>
|
||||||
protected override async void OnClosing(WindowClosingEventArgs e)
|
protected override async void OnClosing(WindowClosingEventArgs e)
|
||||||
{
|
{
|
||||||
VerifyAccess();
|
VerifyAccess();
|
||||||
|
|||||||
Reference in New Issue
Block a user