Browse Source

Merge pull request #1383 from CommonGuy/closing-event

Closing event #1252
pull/1453/head
Steven Kirk 8 years ago
committed by GitHub
parent
commit
3077d8bf18
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  2. 43
      src/Avalonia.Controls/Window.cs
  3. 1
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  4. 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  5. 8
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  6. 8
      src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs
  7. 10
      src/Windows/Avalonia.Win32/WindowImpl.cs

6
src/Avalonia.Controls/Platform/IWindowImpl.cs

@ -44,5 +44,11 @@ namespace Avalonia.Platform
/// Enables or disables the taskbar icon
/// </summary>
void ShowTaskbarIcon(bool value);
/// <summary>
/// Gets or sets a method called before the underlying implementation is destroyed.
/// Return true to prevent the underlying implementation from closing.
/// </summary>
Func<bool> Closing { get; set; }
}
}

43
src/Avalonia.Controls/Window.cs

@ -13,6 +13,7 @@ using Avalonia.Styling;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using System.ComponentModel;
namespace Avalonia.Controls
{
@ -129,6 +130,7 @@ namespace Avalonia.Controls
public Window(IWindowImpl impl)
: base(impl)
{
impl.Closing = HandleClosing;
_maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
Screens = new Screens(PlatformImpl?.Screen);
}
@ -230,20 +232,23 @@ namespace Avalonia.Controls
/// <inheritdoc/>
Type IStyleable.StyleKey => typeof(Window);
/// <summary>
/// Fired before a window is closed.
/// </summary>
public event EventHandler<CancelEventArgs> Closing;
/// <summary>
/// Closes the window.
/// </summary>
public void Close()
{
s_windows.Remove(this);
PlatformImpl?.Dispose();
IsVisible = false;
Close(false);
}
protected override void HandleApplicationExiting()
{
base.HandleApplicationExiting();
Close();
Close(true);
}
/// <summary>
@ -258,7 +263,35 @@ namespace Avalonia.Controls
public void Close(object dialogResult)
{
_dialogResult = dialogResult;
Close();
Close(false);
}
internal void Close(bool ignoreCancel)
{
var cancelClosing = false;
try
{
cancelClosing = HandleClosing();
}
finally
{
if (ignoreCancel || !cancelClosing)
{
s_windows.Remove(this);
PlatformImpl?.Dispose();
IsVisible = false;
}
}
}
/// <summary>
/// Handles a closing notification from <see cref="IWindowImpl.Closing"/>.
/// </summary>
protected virtual bool HandleClosing()
{
var args = new CancelEventArgs();
Closing?.Invoke(this, args);
return args.Cancel;
}
/// <summary>

1
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -39,6 +39,7 @@ namespace Avalonia.DesignerSupport.Remote
public Action<Point> PositionChanged { get; set; }
public Action Deactivated { get; set; }
public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public IPlatformHandle Handle { get; }
public WindowState WindowState { get; set; }
public Size MaxClientSize { get; } = new Size(4096, 4096);

1
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -26,6 +26,7 @@ namespace Avalonia.DesignerSupport.Remote
public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public Func<bool> Closing { get; set; }
public Action Closed { get; set; }
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public Point Position { get; set; }

8
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@ -54,6 +54,7 @@ namespace Avalonia.Gtk3
ConnectEvent("key-press-event", OnKeyEvent);
ConnectEvent("key-release-event", OnKeyEvent);
ConnectEvent("leave-notify-event", OnLeaveNotifyEvent);
ConnectEvent("delete-event", OnClosingEvent);
Connect<Native.D.signal_generic>("destroy", OnDestroy);
Native.GtkWidgetRealize(gtkWidget);
GdkWindowHandle = this.Handle.Handle;
@ -125,6 +126,12 @@ namespace Avalonia.Gtk3
return rv;
}
private unsafe bool OnClosingEvent(IntPtr w, IntPtr ev, IntPtr userdata)
{
bool? preventClosing = Closing?.Invoke();
return preventClosing ?? false;
}
private unsafe bool OnButton(IntPtr w, IntPtr ev, IntPtr userdata)
{
var evnt = (GdkEventButton*)ev;
@ -343,6 +350,7 @@ namespace Avalonia.Gtk3
string IPlatformHandle.HandleDescriptor => "HWND";
public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public Action Closed { get; set; }
public Action Deactivated { get; set; }
public Action<RawInputEventArgs> Input { get; set; }

8
src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs

@ -4,6 +4,7 @@ using Avalonia.Input.Raw;
using Avalonia.Platform;
using MonoMac.AppKit;
using MonoMac.CoreGraphics;
using MonoMac.Foundation;
using MonoMac.ObjCRuntime;
namespace Avalonia.MonoMac
@ -69,6 +70,12 @@ namespace Avalonia.MonoMac
_impl.PositionChanged?.Invoke(_impl.Position);
}
public override bool WindowShouldClose(NSObject sender)
{
bool? preventClose = _impl.Closing?.Invoke();
return preventClose != true;
}
public override void WillClose(global::MonoMac.Foundation.NSNotification notification)
{
_impl.Window.Dispose();
@ -107,6 +114,7 @@ namespace Avalonia.MonoMac
public Action<Point> PositionChanged { get; set; }
public Action Deactivated { get; set; }
public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public override Size ClientSize => Window.ContentRectFor(Window.Frame).Size.ToAvaloniaSize();

10
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -56,6 +56,8 @@ namespace Avalonia.Win32
public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public Action Closed { get; set; }
public Action Deactivated { get; set; }
@ -431,6 +433,14 @@ namespace Avalonia.Win32
return IntPtr.Zero;
case UnmanagedMethods.WindowsMessage.WM_CLOSE:
bool? preventClosing = Closing?.Invoke();
if (preventClosing == true)
{
return IntPtr.Zero;
}
break;
case UnmanagedMethods.WindowsMessage.WM_DESTROY:
//Window doesn't exist anymore
_hwnd = IntPtr.Zero;

Loading…
Cancel
Save