|
|
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
using System.Linq;
|
|
|
using System.Reactive.Disposables;
|
|
|
+using Avalonia.Controls.Presenters;
|
|
|
using Avalonia.Data;
|
|
|
using Avalonia.Input;
|
|
|
using Avalonia.Input.Raw;
|
|
|
@@ -79,9 +80,10 @@ namespace Avalonia.Controls.Primitives
|
|
|
AvaloniaProperty.Register<Popup, bool>(nameof(Topmost));
|
|
|
|
|
|
private bool _isOpen;
|
|
|
- private IPopupHost _popupRoot;
|
|
|
+ private IPopupHost _popupHost;
|
|
|
private TopLevel _topLevel;
|
|
|
private IDisposable _nonClientListener;
|
|
|
+ private IDisposable _presenterSubscription;
|
|
|
bool _ignoreIsOpenChanged = false;
|
|
|
private List<IDisposable> _bindings = new List<IDisposable>();
|
|
|
|
|
|
@@ -110,7 +112,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
/// </summary>
|
|
|
public event EventHandler Opened;
|
|
|
|
|
|
- public IPopupHost Host => _popupRoot;
|
|
|
+ public IPopupHost Host => _popupHost;
|
|
|
|
|
|
/// <summary>
|
|
|
/// Gets or sets the control to display in the popup.
|
|
|
@@ -209,7 +211,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
/// <summary>
|
|
|
/// Gets the root of the popup window.
|
|
|
/// </summary>
|
|
|
- IVisual IVisualTreeHost.Root => _popupRoot?.VisualRoot;
|
|
|
+ IVisual IVisualTreeHost.Root => _popupHost?.VisualRoot;
|
|
|
|
|
|
/// <summary>
|
|
|
/// Opens the popup.
|
|
|
@@ -232,17 +234,16 @@ namespace Avalonia.Controls.Primitives
|
|
|
"Attempted to open a popup not attached to a TopLevel");
|
|
|
}
|
|
|
|
|
|
- _popupRoot = PopupHost.CreatePopupHost(placementTarget, DependencyResolver);
|
|
|
+ _popupHost = PopupHost.CreatePopupHost(placementTarget, DependencyResolver);
|
|
|
|
|
|
- _bindings.Add(_popupRoot.BindConstraints(this, WidthProperty, MinWidthProperty, MaxWidthProperty,
|
|
|
+ _bindings.Add(_popupHost.BindConstraints(this, WidthProperty, MinWidthProperty, MaxWidthProperty,
|
|
|
HeightProperty, MinHeightProperty, MaxHeightProperty, TopmostProperty));
|
|
|
|
|
|
- _popupRoot.SetContent(Child);
|
|
|
-
|
|
|
- ((ISetLogicalParent)_popupRoot).SetParent(this);
|
|
|
-
|
|
|
- _popupRoot.ConfigurePosition(placementTarget,
|
|
|
+ _popupHost.SetContent(Child);
|
|
|
+ ((ISetLogicalParent)_popupHost).SetParent(this);
|
|
|
+ _popupHost.ConfigurePosition(placementTarget,
|
|
|
PlacementMode, new Point(HorizontalOffset, VerticalOffset));
|
|
|
+ _popupHost.TemplateApplied += RootTemplateApplied;
|
|
|
|
|
|
var window = _topLevel as Window;
|
|
|
if (window != null)
|
|
|
@@ -261,7 +262,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
_nonClientListener = InputManager.Instance?.Process.Subscribe(ListenForNonClientClick);
|
|
|
|
|
|
|
|
|
- _popupRoot.Show();
|
|
|
+ _popupHost.Show();
|
|
|
|
|
|
using (BeginIgnoringIsOpen())
|
|
|
{
|
|
|
@@ -276,6 +277,13 @@ namespace Avalonia.Controls.Primitives
|
|
|
/// </summary>
|
|
|
public void Close()
|
|
|
{
|
|
|
+ if (_popupHost != null)
|
|
|
+ {
|
|
|
+ _popupHost.TemplateApplied -= RootTemplateApplied;
|
|
|
+ }
|
|
|
+
|
|
|
+ _presenterSubscription?.Dispose();
|
|
|
+
|
|
|
CloseCurrent();
|
|
|
using (BeginIgnoringIsOpen())
|
|
|
{
|
|
|
@@ -284,6 +292,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
|
|
|
Closed?.Invoke(this, EventArgs.Empty);
|
|
|
}
|
|
|
+
|
|
|
void CloseCurrent()
|
|
|
{
|
|
|
if (_topLevel != null)
|
|
|
@@ -305,16 +314,16 @@ namespace Avalonia.Controls.Primitives
|
|
|
|
|
|
_topLevel = null;
|
|
|
}
|
|
|
- if (_popupRoot != null)
|
|
|
+ if (_popupHost != null)
|
|
|
{
|
|
|
foreach(var b in _bindings)
|
|
|
b.Dispose();
|
|
|
_bindings.Clear();
|
|
|
- _popupRoot.SetContent(null);
|
|
|
- _popupRoot.Hide();
|
|
|
- ((ISetLogicalParent)_popupRoot).SetParent(null);
|
|
|
- _popupRoot.Dispose();
|
|
|
- _popupRoot = null;
|
|
|
+ _popupHost.SetContent(null);
|
|
|
+ _popupHost.Hide();
|
|
|
+ ((ISetLogicalParent)_popupHost).SetParent(null);
|
|
|
+ _popupHost.Dispose();
|
|
|
+ _popupHost = null;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
@@ -395,17 +404,61 @@ namespace Avalonia.Controls.Primitives
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void RootTemplateApplied(object sender, TemplateAppliedEventArgs e)
|
|
|
+ {
|
|
|
+ _popupHost.TemplateApplied -= RootTemplateApplied;
|
|
|
+
|
|
|
+ if (_presenterSubscription != null)
|
|
|
+ {
|
|
|
+ _presenterSubscription.Dispose();
|
|
|
+ _presenterSubscription = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // If the Popup appears in a control template, then the child controls
|
|
|
+ // that appear in the popup host need to have their TemplatedParent
|
|
|
+ // properties set.
|
|
|
+ if (TemplatedParent != null)
|
|
|
+ {
|
|
|
+ _popupHost.Presenter?.ApplyTemplate();
|
|
|
+ _popupHost.Presenter?.GetObservable(ContentPresenter.ChildProperty)
|
|
|
+ .Subscribe(SetTemplatedParentAndApplyChildTemplates);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void SetTemplatedParentAndApplyChildTemplates(IControl control)
|
|
|
+ {
|
|
|
+ if (control != null)
|
|
|
+ {
|
|
|
+ var templatedParent = TemplatedParent;
|
|
|
+
|
|
|
+ if (control.TemplatedParent == null)
|
|
|
+ {
|
|
|
+ control.SetValue(TemplatedParentProperty, templatedParent);
|
|
|
+ }
|
|
|
+
|
|
|
+ control.ApplyTemplate();
|
|
|
+
|
|
|
+ if (!(control is IPresenter) && control.TemplatedParent == templatedParent)
|
|
|
+ {
|
|
|
+ foreach (IControl child in control.GetVisualChildren())
|
|
|
+ {
|
|
|
+ SetTemplatedParentAndApplyChildTemplates(child);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private bool IsChildOrThis(IVisual child)
|
|
|
{
|
|
|
- return ((IVisual)_popupRoot)?.FindCommonVisualAncestor(child) == _popupRoot;
|
|
|
+ return ((IVisual)_popupHost)?.FindCommonVisualAncestor(child) == _popupHost;
|
|
|
}
|
|
|
|
|
|
public bool IsInsidePopup(IVisual visual)
|
|
|
{
|
|
|
- return ((IVisual)_popupRoot)?.FindCommonVisualAncestor(visual) == _popupRoot;
|
|
|
+ return ((IVisual)_popupHost)?.FindCommonVisualAncestor(visual) == _popupHost;
|
|
|
}
|
|
|
|
|
|
- public bool IsPointerOverPopup => ((IInputElement)_popupRoot).IsPointerOver;
|
|
|
+ public bool IsPointerOverPopup => ((IInputElement)_popupHost).IsPointerOver;
|
|
|
|
|
|
private void WindowDeactivated(object sender, EventArgs e)
|
|
|
{
|