Browse Source

Merge pull request #1383 from CommonGuy/closing-event

Closing event #1252
pull/1453/head
Steven Kirk 9 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 /// Enables or disables the taskbar icon
/// </summary> /// </summary>
void ShowTaskbarIcon(bool value); 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.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using System.ComponentModel;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -129,6 +130,7 @@ namespace Avalonia.Controls
public Window(IWindowImpl impl) public Window(IWindowImpl impl)
: base(impl) : base(impl)
{ {
impl.Closing = HandleClosing;
_maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size); _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
Screens = new Screens(PlatformImpl?.Screen); Screens = new Screens(PlatformImpl?.Screen);
} }
@ -230,20 +232,23 @@ namespace Avalonia.Controls
/// <inheritdoc/> /// <inheritdoc/>
Type IStyleable.StyleKey => typeof(Window); Type IStyleable.StyleKey => typeof(Window);
/// <summary>
/// Fired before a window is closed.
/// </summary>
public event EventHandler<CancelEventArgs> Closing;
/// <summary> /// <summary>
/// Closes the window. /// Closes the window.
/// </summary> /// </summary>
public void Close() public void Close()
{ {
s_windows.Remove(this); Close(false);
PlatformImpl?.Dispose();
IsVisible = false;
} }
protected override void HandleApplicationExiting() protected override void HandleApplicationExiting()
{ {
base.HandleApplicationExiting(); base.HandleApplicationExiting();
Close(); Close(true);
} }
/// <summary> /// <summary>
@ -258,7 +263,35 @@ namespace Avalonia.Controls
public void Close(object dialogResult) public void Close(object dialogResult)
{ {
_dialogResult = 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> /// <summary>

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

@ -39,6 +39,7 @@ namespace Avalonia.DesignerSupport.Remote
public Action<Point> PositionChanged { get; set; } public Action<Point> PositionChanged { get; set; }
public Action Deactivated { get; set; } public Action Deactivated { get; set; }
public Action Activated { get; set; } public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public IPlatformHandle Handle { get; } public IPlatformHandle Handle { get; }
public WindowState WindowState { get; set; } public WindowState WindowState { get; set; }
public Size MaxClientSize { get; } = new Size(4096, 4096); 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<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; } public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; } public Action<double> ScalingChanged { get; set; }
public Func<bool> Closing { get; set; }
public Action Closed { get; set; } public Action Closed { get; set; }
public IMouseDevice MouseDevice { get; } = new MouseDevice(); public IMouseDevice MouseDevice { get; } = new MouseDevice();
public Point Position { get; set; } 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-press-event", OnKeyEvent);
ConnectEvent("key-release-event", OnKeyEvent); ConnectEvent("key-release-event", OnKeyEvent);
ConnectEvent("leave-notify-event", OnLeaveNotifyEvent); ConnectEvent("leave-notify-event", OnLeaveNotifyEvent);
ConnectEvent("delete-event", OnClosingEvent);
Connect<Native.D.signal_generic>("destroy", OnDestroy); Connect<Native.D.signal_generic>("destroy", OnDestroy);
Native.GtkWidgetRealize(gtkWidget); Native.GtkWidgetRealize(gtkWidget);
GdkWindowHandle = this.Handle.Handle; GdkWindowHandle = this.Handle.Handle;
@ -125,6 +126,12 @@ namespace Avalonia.Gtk3
return rv; 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) private unsafe bool OnButton(IntPtr w, IntPtr ev, IntPtr userdata)
{ {
var evnt = (GdkEventButton*)ev; var evnt = (GdkEventButton*)ev;
@ -343,6 +350,7 @@ namespace Avalonia.Gtk3
string IPlatformHandle.HandleDescriptor => "HWND"; string IPlatformHandle.HandleDescriptor => "HWND";
public Action Activated { get; set; } public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public Action Closed { get; set; } public Action Closed { get; set; }
public Action Deactivated { get; set; } public Action Deactivated { get; set; }
public Action<RawInputEventArgs> Input { 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 Avalonia.Platform;
using MonoMac.AppKit; using MonoMac.AppKit;
using MonoMac.CoreGraphics; using MonoMac.CoreGraphics;
using MonoMac.Foundation;
using MonoMac.ObjCRuntime; using MonoMac.ObjCRuntime;
namespace Avalonia.MonoMac namespace Avalonia.MonoMac
@ -69,6 +70,12 @@ namespace Avalonia.MonoMac
_impl.PositionChanged?.Invoke(_impl.Position); _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) public override void WillClose(global::MonoMac.Foundation.NSNotification notification)
{ {
_impl.Window.Dispose(); _impl.Window.Dispose();
@ -107,6 +114,7 @@ namespace Avalonia.MonoMac
public Action<Point> PositionChanged { get; set; } public Action<Point> PositionChanged { get; set; }
public Action Deactivated { get; set; } public Action Deactivated { get; set; }
public Action Activated { get; set; } public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public override Size ClientSize => Window.ContentRectFor(Window.Frame).Size.ToAvaloniaSize(); 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 Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public Action Closed { get; set; } public Action Closed { get; set; }
public Action Deactivated { get; set; } public Action Deactivated { get; set; }
@ -431,6 +433,14 @@ namespace Avalonia.Win32
return IntPtr.Zero; return IntPtr.Zero;
case UnmanagedMethods.WindowsMessage.WM_CLOSE:
bool? preventClosing = Closing?.Invoke();
if (preventClosing == true)
{
return IntPtr.Zero;
}
break;
case UnmanagedMethods.WindowsMessage.WM_DESTROY: case UnmanagedMethods.WindowsMessage.WM_DESTROY:
//Window doesn't exist anymore //Window doesn't exist anymore
_hwnd = IntPtr.Zero; _hwnd = IntPtr.Zero;

Loading…
Cancel
Save