Browse Source

Merge pull request #3828 from MarchingCube/refactor-show-dialog

Remove Window.ShowDialog variant that takes IWindowImpl.
pull/3837/head
Dariusz Komosiński 6 years ago
committed by GitHub
parent
commit
cb582095e4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
  2. 6
      src/Avalonia.Controls/SystemDialog.cs
  3. 28
      src/Avalonia.Controls/Window.cs
  4. 4
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  5. 12
      src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
  6. 20
      src/Avalonia.Native/SystemDialogs.cs
  7. 14
      src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs
  8. 9
      src/Windows/Avalonia.Win32/SystemDialogImpl.cs
  9. 8
      tests/Avalonia.Controls.UnitTests/WindowTests.cs

5
src/Avalonia.Controls/Platform/ISystemDialogImpl.cs

@ -1,5 +1,4 @@
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Controls.Platform
{
@ -14,8 +13,8 @@ namespace Avalonia.Controls.Platform
/// <param name="dialog">The details of the file dialog to show.</param>
/// <param name="parent">The parent window.</param>
/// <returns>A task returning the selected filenames.</returns>
Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent);
Task<string[]> ShowFileDialogAsync(FileDialog dialog, Window parent);
Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent);
Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent);
}
}

6
src/Avalonia.Controls/SystemDialog.cs

@ -32,7 +32,7 @@ namespace Avalonia.Controls
if(parent == null)
throw new ArgumentNullException(nameof(parent));
return ((await AvaloniaLocator.Current.GetService<ISystemDialogImpl>()
.ShowFileDialogAsync(this, parent?.PlatformImpl)) ??
.ShowFileDialogAsync(this, parent)) ??
Array.Empty<string>()).FirstOrDefault();
}
}
@ -45,7 +45,7 @@ namespace Avalonia.Controls
{
if(parent == null)
throw new ArgumentNullException(nameof(parent));
return AvaloniaLocator.Current.GetService<ISystemDialogImpl>().ShowFileDialogAsync(this, parent?.PlatformImpl);
return AvaloniaLocator.Current.GetService<ISystemDialogImpl>().ShowFileDialogAsync(this, parent);
}
}
@ -61,7 +61,7 @@ namespace Avalonia.Controls
{
if(parent == null)
throw new ArgumentNullException(nameof(parent));
return AvaloniaLocator.Current.GetService<ISystemDialogImpl>().ShowFolderDialogAsync(this, parent?.PlatformImpl);
return AvaloniaLocator.Current.GetService<ISystemDialogImpl>().ShowFolderDialogAsync(this, parent);
}
}

28
src/Avalonia.Controls/Window.cs

@ -484,22 +484,12 @@ namespace Avalonia.Controls
/// <returns>.
/// A task that can be used to retrieve the result of the dialog when it closes.
/// </returns>
public Task<TResult> ShowDialog<TResult>(Window owner) => ShowDialog<TResult>(owner.PlatformImpl);
/// <summary>
/// Shows the window as a dialog.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the dialog.
/// </typeparam>
/// <param name="owner">The dialog's owner window.</param>
/// <returns>.
/// A task that can be used to retrieve the result of the dialog when it closes.
/// </returns>
public Task<TResult> ShowDialog<TResult>(IWindowImpl owner)
public Task<TResult> ShowDialog<TResult>(Window owner)
{
if (owner == null)
{
throw new ArgumentNullException(nameof(owner));
}
if (IsVisible)
{
@ -516,23 +506,25 @@ namespace Avalonia.Controls
using (BeginAutoSizing())
{
PlatformImpl?.ShowDialog(owner);
PlatformImpl?.ShowDialog(owner.PlatformImpl);
Renderer?.Start();
Observable.FromEventPattern<EventHandler, EventArgs>(
x => this.Closed += x,
x => this.Closed -= x)
x => Closed += x,
x => Closed -= x)
.Take(1)
.Subscribe(_ =>
{
owner.Activate();
result.SetResult((TResult)(_dialogResult ?? default(TResult)));
});
OnOpened(EventArgs.Empty);
}
SetWindowStartupLocation(owner);
SetWindowStartupLocation(owner.PlatformImpl);
return result.Task;
}

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

@ -166,10 +166,10 @@ namespace Avalonia.DesignerSupport.Remote
class SystemDialogsStub : ISystemDialogImpl
{
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent) =>
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, Window parent) =>
Task.FromResult((string[])null);
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) =>
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent) =>
Task.FromResult((string)null);
}

12
src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs

@ -1,19 +1,15 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Dialogs;
using Avalonia.Platform;
namespace Avalonia.Dialogs
{
public static class ManagedFileDialogExtensions
{
class ManagedSystemDialogImpl<T> : ISystemDialogImpl where T : Window, new()
private class ManagedSystemDialogImpl<T> : ISystemDialogImpl where T : Window, new()
{
async Task<string[]> Show(SystemDialog d, IWindowImpl parent)
async Task<string[]> Show(SystemDialog d, Window parent)
{
var model = new ManagedFileChooserViewModel((FileSystemDialog)d);
@ -39,12 +35,12 @@ namespace Avalonia.Dialogs
return result;
}
public async Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
public async Task<string[]> ShowFileDialogAsync(FileDialog dialog, Window parent)
{
return await Show(dialog, parent);
}
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent)
{
return (await Show(dialog, parent))?.FirstOrDefault();
}

20
src/Avalonia.Native/SystemDialogs.cs

@ -5,7 +5,6 @@ using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Native.Interop;
using Avalonia.Platform;
namespace Avalonia.Native
{
@ -18,13 +17,15 @@ namespace Avalonia.Native
_native = native;
}
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, Window parent)
{
var events = new SystemDialogEvents();
var nativeParent = GetNativeWindow(parent);
if (dialog is OpenFileDialog ofd)
{
_native.OpenFileDialog((parent as WindowImpl)?.Native,
_native.OpenFileDialog(nativeParent,
events, ofd.AllowMultiple,
ofd.Title ?? "",
ofd.InitialDirectory ?? "",
@ -33,7 +34,7 @@ namespace Avalonia.Native
}
else
{
_native.SaveFileDialog((parent as WindowImpl)?.Native,
_native.SaveFileDialog(nativeParent,
events,
dialog.Title ?? "",
dialog.InitialDirectory ?? "",
@ -44,14 +45,21 @@ namespace Avalonia.Native
return events.Task.ContinueWith(t => { events.Dispose(); return t.Result; });
}
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent)
{
var events = new SystemDialogEvents();
_native.SelectFolderDialog((parent as WindowImpl)?.Native, events, dialog.Title ?? "", dialog.InitialDirectory ?? "");
var nativeParent = GetNativeWindow(parent);
_native.SelectFolderDialog(nativeParent, events, dialog.Title ?? "", dialog.InitialDirectory ?? "");
return events.Task.ContinueWith(t => { events.Dispose(); return t.Result.FirstOrDefault(); });
}
private IAvnWindow GetNativeWindow(Window window)
{
return (window?.PlatformImpl as WindowImpl)?.Native;
}
}
public class SystemDialogEvents : CallbackBase, IAvnSystemDialogEvents

14
src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs

@ -102,23 +102,29 @@ namespace Avalonia.X11.NativeDialogs
return tcs.Task;
}
public async Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
public async Task<string[]> ShowFileDialogAsync(FileDialog dialog, Window parent)
{
await EnsureInitialized();
var platformImpl = parent?.PlatformImpl;
return await await RunOnGlibThread(
() => ShowDialog(dialog.Title, parent,
() => ShowDialog(dialog.Title, platformImpl,
dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save,
(dialog as OpenFileDialog)?.AllowMultiple ?? false,
Path.Combine(string.IsNullOrEmpty(dialog.InitialDirectory) ? "" : dialog.InitialDirectory,
string.IsNullOrEmpty(dialog.InitialFileName) ? "" : dialog.InitialFileName), dialog.Filters));
}
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent)
{
await EnsureInitialized();
var platformImpl = parent?.PlatformImpl;
return await await RunOnGlibThread(async () =>
{
var res = await ShowDialog(dialog.Title, parent,
var res = await ShowDialog(dialog.Title, platformImpl,
GtkFileChooserAction.SelectFolder, false, dialog.InitialDirectory, null);
return res?.FirstOrDefault();
});

9
src/Windows/Avalonia.Win32/SystemDialogImpl.cs

@ -5,7 +5,6 @@ using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32
@ -16,9 +15,9 @@ namespace Avalonia.Win32
private const UnmanagedMethods.FOS DefaultDialogOptions = UnmanagedMethods.FOS.FOS_FORCEFILESYSTEM | UnmanagedMethods.FOS.FOS_NOVALIDATE |
UnmanagedMethods.FOS.FOS_NOTESTFILECREATE | UnmanagedMethods.FOS.FOS_DONTADDTORECENT;
public unsafe Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
public unsafe Task<string[]> ShowFileDialogAsync(FileDialog dialog, Window parent)
{
var hWnd = parent?.Handle?.Handle ?? IntPtr.Zero;
var hWnd = parent?.PlatformImpl?.Handle?.Handle ?? IntPtr.Zero;
return Task.Factory.StartNew(() =>
{
var result = Array.Empty<string>();
@ -98,13 +97,13 @@ namespace Avalonia.Win32
});
}
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent)
{
return Task.Factory.StartNew(() =>
{
string result = string.Empty;
var hWnd = parent?.Handle?.Handle ?? IntPtr.Zero;
var hWnd = parent?.PlatformImpl?.Handle?.Handle ?? IntPtr.Zero;
Guid clsid = UnmanagedMethods.ShellIds.OpenFileDialog;
Guid iid = UnmanagedMethods.ShellIds.IFileDialog;

8
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -156,7 +156,7 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = Mock.Of<IWindowImpl>();
var parent = Mock.Of<Window>();
var renderer = new Mock<IRenderer>();
var target = new Window(CreateImpl(renderer));
@ -171,7 +171,7 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = Mock.Of<IWindowImpl>();
var parent = Mock.Of<Window>();
var target = new Window();
var raised = false;
@ -203,7 +203,7 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Mock<IWindowImpl>();
var parent = new Mock<Window>();
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed);
windowImpl.Setup(x => x.Scaling).Returns(1);
@ -242,7 +242,7 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Mock<IWindowImpl>();
var parent = new Mock<Window>();
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed);
windowImpl.Setup(x => x.Scaling).Returns(1);

Loading…
Cancel
Save