Browse Source

Fix events for ContextMenu and Popup.

pull/2749/head
Dariusz Komosinski 7 years ago
parent
commit
3c787b3d4d
  1. 38
      src/Avalonia.Controls/ContextMenu.cs
  2. 46
      src/Avalonia.Controls/Menu.cs
  3. 4
      src/Avalonia.Controls/MenuBase.cs
  4. 35
      src/Avalonia.Controls/Primitives/Popup.cs
  5. 54
      tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
  6. 48
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

38
src/Avalonia.Controls/ContextMenu.cs

@ -7,6 +7,7 @@ using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
namespace Avalonia.Controls
@ -90,9 +91,14 @@ namespace Avalonia.Controls
/// <param name="control">The control.</param>
public void Open(Control control)
{
if (IsOpen)
{
return;
}
if (_popup == null)
{
_popup = new Popup()
_popup = new Popup
{
PlacementMode = PlacementMode.Pointer,
PlacementTarget = control,
@ -107,7 +113,14 @@ namespace Avalonia.Controls
((ISetLogicalParent)_popup).SetParent(control);
_popup.Child = this;
_popup.IsOpen = true;
IsOpen = true;
RaiseEvent(new RoutedEventArgs
{
RoutedEvent = MenuOpenedEvent,
Source = this,
});
}
/// <summary>
@ -115,13 +128,15 @@ namespace Avalonia.Controls
/// </summary>
public override void Close()
{
if (!IsOpen)
{
return;
}
if (_popup != null && _popup.IsVisible)
{
_popup.IsOpen = false;
}
SelectedIndex = -1;
IsOpen = false;
}
protected override IItemContainerGenerator CreateItemContainerGenerator()
@ -129,6 +144,18 @@ namespace Avalonia.Controls
return new MenuItemContainerGenerator(this);
}
private void CloseCore()
{
SelectedIndex = -1;
IsOpen = false;
RaiseEvent(new RoutedEventArgs
{
RoutedEvent = MenuClosedEvent,
Source = this,
});
}
private void PopupOpened(object sender, EventArgs e)
{
Focus();
@ -145,8 +172,7 @@ namespace Avalonia.Controls
i.IsSubMenuOpen = false;
}
contextMenu.IsOpen = false;
contextMenu.SelectedIndex = -1;
contextMenu.CloseCore();
}
}

46
src/Avalonia.Controls/Menu.cs

@ -40,37 +40,41 @@ namespace Avalonia.Controls
/// <inheritdoc/>
public override void Close()
{
if (IsOpen)
if (!IsOpen)
{
foreach (var i in ((IMenu)this).SubItems)
{
i.Close();
}
IsOpen = false;
SelectedIndex = -1;
return;
}
RaiseEvent(new RoutedEventArgs
{
RoutedEvent = MenuClosedEvent,
Source = this,
});
foreach (var i in ((IMenu)this).SubItems)
{
i.Close();
}
IsOpen = false;
SelectedIndex = -1;
RaiseEvent(new RoutedEventArgs
{
RoutedEvent = MenuClosedEvent,
Source = this,
});
}
/// <inheritdoc/>
public override void Open()
{
if (!IsOpen)
if (IsOpen)
{
IsOpen = true;
RaiseEvent(new RoutedEventArgs
{
RoutedEvent = MenuOpenedEvent,
Source = this,
});
return;
}
IsOpen = true;
RaiseEvent(new RoutedEventArgs
{
RoutedEvent = MenuOpenedEvent,
Source = this,
});
}
/// <inheritdoc/>

4
src/Avalonia.Controls/MenuBase.cs

@ -31,13 +31,13 @@ namespace Avalonia.Controls
/// Defines the <see cref="MenuOpened"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> MenuOpenedEvent =
RoutedEvent.Register<MenuItem, RoutedEventArgs>(nameof(MenuOpened), RoutingStrategies.Bubble);
RoutedEvent.Register<MenuBase, RoutedEventArgs>(nameof(MenuOpened), RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="MenuClosed"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> MenuClosedEvent =
RoutedEvent.Register<MenuItem, RoutedEventArgs>(nameof(MenuClosed), RoutingStrategies.Bubble);
RoutedEvent.Register<MenuBase, RoutedEventArgs>(nameof(MenuClosed), RoutingStrategies.Bubble);
private bool _isOpen;

35
src/Avalonia.Controls/Primitives/Popup.cs

@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Diagnostics;
using System.Linq;
using Avalonia.Input;
using Avalonia.Input.Raw;
@ -270,9 +271,10 @@ namespace Avalonia.Controls.Primitives
_popupRoot.SnapInsideScreenEdges();
}
_ignoreIsOpenChanged = true;
IsOpen = true;
_ignoreIsOpenChanged = false;
using (BeginIgnoringIsOpen())
{
IsOpen = true;
}
Opened?.Invoke(this, EventArgs.Empty);
}
@ -305,7 +307,11 @@ namespace Avalonia.Controls.Primitives
_popupRoot.Hide();
}
IsOpen = false;
using (BeginIgnoringIsOpen())
{
IsOpen = false;
}
Closed?.Invoke(this, EventArgs.Empty);
}
@ -467,5 +473,26 @@ namespace Avalonia.Controls.Primitives
Close();
}
}
private IgnoreIsOpenScope BeginIgnoringIsOpen()
{
return new IgnoreIsOpenScope(this);
}
private readonly struct IgnoreIsOpenScope : IDisposable
{
private readonly Popup _owner;
public IgnoreIsOpenScope(Popup owner)
{
_owner = owner;
_owner._ignoreIsOpenChanged = true;
}
public void Dispose()
{
_owner._ignoreIsOpenChanged = false;
}
}
}
}

54
tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs

@ -16,6 +16,60 @@ namespace Avalonia.Controls.UnitTests
private Mock<IPopupImpl> popupImpl;
private MouseTestHelper _mouse = new MouseTestHelper();
[Fact]
public void Opening_Raises_Single_Opened_Event()
{
using (Application())
{
var sut = new ContextMenu();
var target = new Panel
{
ContextMenu = sut
};
new Window { Content = target };
int openedCount = 0;
sut.MenuOpened += (sender, args) =>
{
openedCount++;
};
sut.Open(null);
Assert.Equal(1, openedCount);
}
}
[Fact]
public void Closing_Raises_Single_Closed_Event()
{
using (Application())
{
var sut = new ContextMenu();
var target = new Panel
{
ContextMenu = sut
};
new Window { Content = target };
sut.Open(null);
int closedCount = 0;
sut.MenuClosed += (sender, args) =>
{
closedCount++;
};
sut.Close();
Assert.Equal(1, closedCount);
}
}
[Fact]
public void Clicking_On_Control_Toggles_ContextMenu()
{

48
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -3,6 +3,7 @@
using System;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using Moq;
using Avalonia.Controls.Presenters;
@ -185,6 +186,53 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
}
[Fact]
public void Popup_Open_Should_Raise_Single_Opened_Event()
{
using (CreateServices())
{
var window = new Window();
var target = new Popup();
window.Content = target;
int openedCount = 0;
target.Opened += (sender, args) =>
{
openedCount++;
};
target.Open();
Assert.Equal(1, openedCount);
}
}
[Fact]
public void Popup_Close_Should_Raise_Single_Closed_Event()
{
using (CreateServices())
{
var window = new Window();
var target = new Popup();
window.Content = target;
target.Open();
int closedCount = 0;
target.Closed += (sender, args) =>
{
closedCount++;
};
target.Close();
Assert.Equal(1, closedCount);
}
}
[Fact]
public void PopupRoot_Should_Have_Template_Applied()
{

Loading…
Cancel
Save