Browse Source

Merge pull request #3833 from MarchingCube/window-ownership

Allow for showing child windows
pull/4138/head
danwalmsley 6 years ago
committed by GitHub
parent
commit
8e698562a4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      samples/ControlCatalog/Pages/DialogsPage.xaml
  2. 15
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  3. 85
      src/Avalonia.Controls/Window.cs

2
samples/ControlCatalog/Pages/DialogsPage.xaml

@ -11,5 +11,7 @@
<Button Name="DecoratedWindowDialog">Decorated window (dialog)</Button> <Button Name="DecoratedWindowDialog">Decorated window (dialog)</Button>
<Button Name="Dialog">Dialog</Button> <Button Name="Dialog">Dialog</Button>
<Button Name="DialogNoTaskbar">Dialog (No taskbar icon)</Button> <Button Name="DialogNoTaskbar">Dialog (No taskbar icon)</Button>
<Button Name="OwnedWindow">Owned window</Button>
<Button Name="OwnedWindowNoTaskbar">Owned window (No taskbar icon)</Button>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

15
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@ -93,6 +93,21 @@ namespace ControlCatalog.Pages
window.ShowInTaskbar = false; window.ShowInTaskbar = false;
window.ShowDialog(GetWindow()); window.ShowDialog(GetWindow());
}; };
this.FindControl<Button>("OwnedWindow").Click += delegate
{
var window = CreateSampleWindow();
window.Show(GetWindow());
};
this.FindControl<Button>("OwnedWindowNoTaskbar").Click += delegate
{
var window = CreateSampleWindow();
window.ShowInTaskbar = false;
window.Show(GetWindow());
};
} }
private Window CreateSampleWindow() private Window CreateSampleWindow()

85
src/Avalonia.Controls/Window.cs

@ -69,7 +69,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot
{ {
private List<Window> _children = new List<Window>(); private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>();
/// <summary> /// <summary>
/// Defines the <see cref="SizeToContent"/> property. /// Defines the <see cref="SizeToContent"/> property.
@ -373,7 +373,7 @@ namespace Avalonia.Controls
private void CloseInternal() private void CloseInternal()
{ {
foreach (var child in _children.ToList()) foreach (var (child, _) in _children.ToList())
{ {
// if we HandleClosing() before then there will be no children. // if we HandleClosing() before then there will be no children.
child.CloseInternal(); child.CloseInternal();
@ -396,7 +396,7 @@ namespace Avalonia.Controls
{ {
bool canClose = true; bool canClose = true;
foreach (var child in _children.ToList()) foreach (var (child, _) in _children.ToList())
{ {
if (!child.HandleClosing()) if (!child.HandleClosing())
{ {
@ -469,6 +469,28 @@ namespace Avalonia.Controls
/// The window has already been closed. /// The window has already been closed.
/// </exception> /// </exception>
public override void Show() public override void Show()
{
ShowCore(null);
}
/// <summary>
/// Shows the window as a child of <paramref name="parent"/>.
/// </summary>
/// <param name="parent">Window that will be a parent of the shown window.</param>
/// <exception cref="InvalidOperationException">
/// The window has already been closed.
/// </exception>
public void Show(Window parent)
{
if (parent is null)
{
throw new ArgumentNullException(nameof(parent), "Showing a child window requires valid parent.");
}
ShowCore(parent);
}
private void ShowCore(Window parent)
{ {
if (PlatformImpl == null) if (PlatformImpl == null)
{ {
@ -480,7 +502,7 @@ namespace Avalonia.Controls
return; return;
} }
this.RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); RaiseEvent(new RoutedEventArgs(WindowOpenedEvent));
EnsureInitialized(); EnsureInitialized();
IsVisible = true; IsVisible = true;
@ -501,6 +523,14 @@ namespace Avalonia.Controls
using (BeginAutoSizing()) using (BeginAutoSizing())
{ {
if (parent != null)
{
PlatformImpl?.SetParent(parent.PlatformImpl);
}
Owner = parent;
parent?.AddChild(this, false);
PlatformImpl?.Show(); PlatformImpl?.Show();
Renderer?.Start(); Renderer?.Start();
} }
@ -568,9 +598,9 @@ namespace Avalonia.Controls
using (BeginAutoSizing()) using (BeginAutoSizing())
{ {
PlatformImpl.SetParent(owner.PlatformImpl); PlatformImpl?.SetParent(owner.PlatformImpl);
Owner = owner; Owner = owner;
owner.AddChild(this); owner.AddChild(this, true);
PlatformImpl?.Show(); PlatformImpl?.Show();
Renderer?.Start(); Renderer?.Start();
@ -595,28 +625,57 @@ namespace Avalonia.Controls
private void UpdateEnabled() private void UpdateEnabled()
{ {
PlatformImpl.SetEnabled(_children.Count == 0); bool isEnabled = true;
foreach (var (_, isDialog) in _children)
{
if (isDialog)
{
isEnabled = false;
break;
}
}
PlatformImpl.SetEnabled(isEnabled);
} }
private void AddChild(Window window) private void AddChild(Window window, bool isDialog)
{ {
_children.Add(window); _children.Add((window, isDialog));
UpdateEnabled(); UpdateEnabled();
} }
private void RemoveChild(Window window) private void RemoveChild(Window window)
{ {
_children.Remove(window); for (int i = _children.Count - 1; i >= 0; i--)
{
var (child, _) = _children[i];
if (ReferenceEquals(child, window))
{
_children.RemoveAt(i);
}
}
UpdateEnabled(); UpdateEnabled();
} }
private void OnGotInputWhenDisabled() private void OnGotInputWhenDisabled()
{ {
var firstChild = _children.FirstOrDefault(); Window firstDialogChild = null;
foreach (var (child, isDialog) in _children)
{
if (isDialog)
{
firstDialogChild = child;
break;
}
}
if (firstChild != null) if (firstDialogChild != null)
{ {
firstChild.OnGotInputWhenDisabled(); firstDialogChild.OnGotInputWhenDisabled();
} }
else else
{ {

Loading…
Cancel
Save