Browse Source

Allow Windows to be shown as dialogs.

pull/39/head
Steven Kirk 11 years ago
parent
commit
af3697b907
  1. 11
      Gtk/Perspex.Gtk/WindowImpl.cs
  2. 2
      Perspex.Controls/Platform/ITopLevelImpl.cs
  3. 5
      Perspex.Controls/Platform/IWindowImpl.cs
  4. 17
      Perspex.Controls/TopLevel.cs
  5. 41
      Perspex.Controls/Window.cs
  6. 39
      TestApplication/Program.cs
  7. 9
      Windows/Perspex.Win32/Interop/UnmanagedMethods.cs
  8. 51
      Windows/Perspex.Win32/WindowImpl.cs

11
Gtk/Perspex.Gtk/WindowImpl.cs

@ -7,6 +7,7 @@
namespace Perspex.Gtk
{
using System;
using System.Threading.Tasks;
using Perspex.Controls;
using Perspex.Input.Raw;
using Perspex.Platform;
@ -79,6 +80,16 @@ namespace Perspex.Gtk
this.Title = title;
}
public IDisposable ShowDialog()
{
throw new NotImplementedException();
}
void ITopLevelImpl.Activate()
{
this.Activate();
}
protected override bool OnButtonPressEvent(Gdk.EventButton evnt)
{
var e = new RawMouseEventArgs(

2
Perspex.Controls/Platform/ITopLevelImpl.cs

@ -29,6 +29,8 @@ namespace Perspex.Platform
Action<Size> Resized { get; set; }
void Activate();
void Invalidate(Rect rect);
void SetOwner(TopLevel owner);

5
Perspex.Controls/Platform/IWindowImpl.cs

@ -6,7 +6,8 @@
namespace Perspex.Platform
{
using Perspex.Controls;
using System;
using System.Threading.Tasks;
public interface IWindowImpl : ITopLevelImpl
{
@ -14,6 +15,8 @@ namespace Perspex.Platform
void Show();
IDisposable ShowDialog();
void Hide();
}
}

17
Perspex.Controls/TopLevel.cs

@ -24,6 +24,9 @@ namespace Perspex.Controls
public static readonly PerspexProperty<Size> ClientSizeProperty =
PerspexProperty.Register<TopLevel, Size>("ClientSize");
public static readonly PerspexProperty<bool> IsActiveProperty =
PerspexProperty.Register<Window, bool>("IsActive");
private Dispatcher dispatcher;
private IRenderManager renderManager;
@ -113,6 +116,12 @@ namespace Perspex.Controls
set { this.SetValue(ClientSizeProperty, value); }
}
public bool IsActive
{
get { return this.GetValue(IsActiveProperty); }
private set { this.SetValue(IsActiveProperty, value); }
}
public ILayoutManager LayoutManager
{
get;
@ -140,6 +149,11 @@ namespace Perspex.Controls
return this.PlatformImpl.PointToScreen(p);
}
public void Activate()
{
this.PlatformImpl.Activate();
}
protected IDisposable BeginAutoSizing()
{
this.autoSizing = true;
@ -174,6 +188,7 @@ namespace Perspex.Controls
}
FocusManager.Instance.SetFocusScope(this);
this.IsActive = true;
}
private void HandleClosed()
@ -186,6 +201,8 @@ namespace Perspex.Controls
private void HandleDeactivated()
{
this.IsActive = false;
if (this.Deactivated != null)
{
this.Deactivated(this, EventArgs.Empty);

41
Perspex.Controls/Window.cs

@ -7,6 +7,8 @@
namespace Perspex.Controls
{
using System;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Perspex.Media;
using Perspex.Platform;
using Perspex.Styling;
@ -17,6 +19,8 @@ namespace Perspex.Controls
public static readonly PerspexProperty<string> TitleProperty =
PerspexProperty.Register<Window, string>("Title", "Window");
private object dialogResult;
static Window()
{
BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White);
@ -43,6 +47,17 @@ namespace Perspex.Controls
get { return typeof(Window); }
}
public void Close()
{
this.PlatformImpl.Dispose();
}
public void Close(object dialogResult)
{
this.dialogResult = dialogResult;
this.Close();
}
public void Hide()
{
using (this.BeginAutoSizing())
@ -60,5 +75,31 @@ namespace Perspex.Controls
this.PlatformImpl.Show();
}
}
public Task ShowDialog()
{
return this.ShowDialog<object>();
}
public Task<TResult> ShowDialog<TResult>()
{
this.ExecuteLayoutPass();
using (this.BeginAutoSizing())
{
var modal = this.PlatformImpl.ShowDialog();
var result = new TaskCompletionSource<TResult>();
Observable.FromEventPattern(this, nameof(Closed))
.Take(1)
.Subscribe(_ =>
{
modal.Dispose();
result.SetResult((TResult)this.dialogResult);
});
return result.Task;
}
}
}
}

39
TestApplication/Program.cs

@ -11,12 +11,11 @@ using Perspex.Layout;
using Perspex.Media;
using Perspex.Media.Imaging;
using Perspex.Rendering;
using Perspex.Styling;
using Perspex.Threading;
#if PERSPEX_GTK
using Perspex.Gtk;
#else
using Perspex.Win32;
using ReactiveUI;
#endif
using Splat;
@ -189,7 +188,10 @@ namespace TestApplication
private static TabItem ButtonsTab()
{
return new TabItem
var showDialog = ReactiveCommand.Create();
Button showDialogButton;
var result = new TabItem
{
Header = "Buttons",
Content = new StackPanel
@ -201,10 +203,11 @@ namespace TestApplication
MinWidth = 120,
Children = new Controls
{
new Button
(showDialogButton = new Button
{
Content = "Button",
},
Command = showDialog,
}),
new Button
{
Content = "Button",
@ -246,6 +249,31 @@ namespace TestApplication
}
},
};
showDialog.Subscribe(async _ =>
{
var close = ReactiveCommand.Create();
var dialog = new Window
{
Content = new StackPanel
{
Width = 200,
Height = 200,
Children = new Controls
{
new Button { Content = "Yes", Command = close, CommandParameter = "Yes" },
new Button { Content = "No", Command = close, CommandParameter = "No" },
}
}
};
close.Subscribe(x => dialog.Close(x));
showDialogButton.Content = await dialog.ShowDialog<string>();
});
return result;
}
private static TabItem TextTab()
@ -582,6 +610,5 @@ namespace TestApplication
return result;
}
}
}

9
Windows/Perspex.Win32/Interop/UnmanagedMethods.cs

@ -516,6 +516,9 @@ namespace Perspex.Win32.Interop
[DllImport("user32.dll", SetLastError = true)]
public static extern bool DestroyWindow(IntPtr hwnd);
[DllImport("user32.dll")]
public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
[DllImport("user32.dll")]
public static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT lpPaint);
@ -558,6 +561,9 @@ namespace Perspex.Win32.Interop
[DllImport("user32.dll")]
public static extern bool InvalidateRect(IntPtr hWnd, ref RECT lpRect, bool bErase);
[DllImport("user32.dll")]
public static extern bool IsWindowEnabled(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool KillTimer(IntPtr hWnd, IntPtr uIDEvent);
@ -579,6 +585,9 @@ namespace Perspex.Win32.Interop
[DllImport("user32.dll")]
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr SetCapture(IntPtr hWnd);

51
Windows/Perspex.Win32/WindowImpl.cs

@ -7,9 +7,14 @@
namespace Perspex.Win32
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Perspex.Controls;
using Perspex.Input.Raw;
using Perspex.Platform;
@ -18,6 +23,8 @@ namespace Perspex.Win32
public class WindowImpl : IWindowImpl
{
private static List<WindowImpl> instances = new List<WindowImpl>();
private UnmanagedMethods.WndProc wndProcDelegate;
private string className;
@ -31,6 +38,7 @@ namespace Perspex.Win32
public WindowImpl()
{
this.CreateWindow();
instances.Add(this);
}
public Action Activated { get; set; }
@ -83,6 +91,17 @@ namespace Perspex.Win32
private set;
}
public bool IsEnabled
{
get { return UnmanagedMethods.IsWindowEnabled(this.hwnd); }
set { UnmanagedMethods.EnableWindow(this.hwnd, value); }
}
public void Activate()
{
UnmanagedMethods.SetActiveWindow(this.hwnd);
}
public IPopupImpl CreatePopup()
{
return new PopupImpl();
@ -90,6 +109,7 @@ namespace Perspex.Win32
public void Dispose()
{
instances.Remove(this);
UnmanagedMethods.DestroyWindow(this.hwnd);
}
@ -133,6 +153,37 @@ namespace Perspex.Win32
UnmanagedMethods.ShowWindow(this.hwnd, UnmanagedMethods.ShowWindowCommand.Normal);
}
public virtual IDisposable ShowDialog()
{
var disabled = instances.Where(x => x != this && x.IsEnabled).ToList();
TopLevel activated = null;
foreach (var window in disabled)
{
if (window.owner.IsActive)
{
activated = window.owner;
}
window.IsEnabled = false;
}
this.Show();
return Disposable.Create(() =>
{
foreach (var window in disabled)
{
window.IsEnabled = true;
}
if (activated != null)
{
activated.Activate();
}
});
}
protected virtual IntPtr CreateWindowOverride(ushort atom)
{
return UnmanagedMethods.CreateWindowEx(

Loading…
Cancel
Save