Browse Source

Expose menu item toggle state to automation (#21541)

* Implement IToggleProvider on MenuItemAutomationPeer

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
pull/21551/head
Jumar Macato 4 months ago
committed by GitHub
parent
commit
a932c75dbb
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 55
      src/Avalonia.Controls/Automation/Peers/MenuItemAutomationPeer.cs
  2. 95
      tests/Avalonia.Controls.UnitTests/Automation/MenuItemAutomationPeerTests.cs

55
src/Avalonia.Controls/Automation/Peers/MenuItemAutomationPeer.cs

@ -1,17 +1,42 @@
using Avalonia.Controls;
using System;
using Avalonia.Automation.Provider;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
namespace Avalonia.Automation.Peers
{
public class MenuItemAutomationPeer : ControlAutomationPeer
public class MenuItemAutomationPeer : ControlAutomationPeer, IToggleProvider
{
public MenuItemAutomationPeer(MenuItem owner)
: base(owner)
{
: base(owner)
{
owner.PropertyChanged += OwnerPropertyChanged;
}
public new MenuItem Owner => (MenuItem)base.Owner;
ToggleState IToggleProvider.ToggleState
=> Owner.IsChecked ? ToggleState.On : ToggleState.Off;
void IToggleProvider.Toggle()
{
EnsureEnabled();
if (Owner.HasSubMenu)
return;
switch (Owner.ToggleType)
{
case MenuItemToggleType.CheckBox:
Owner.SetCurrentValue(MenuItem.IsCheckedProperty, !Owner.IsChecked);
break;
case MenuItemToggleType.Radio:
if (!Owner.IsChecked)
Owner.SetCurrentValue(MenuItem.IsCheckedProperty, true);
break;
}
}
protected override string? GetAccessKeyCore()
{
var result = base.GetAccessKeyCore();
@ -55,5 +80,27 @@ namespace Avalonia.Automation.Peers
return result;
}
protected override object? GetProviderCore(Type providerType)
{
if (providerType == typeof(IToggleProvider) && Owner.ToggleType == MenuItemToggleType.None)
return null;
return base.GetProviderCore(providerType);
}
private void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == MenuItem.IsCheckedProperty && Owner.ToggleType != MenuItemToggleType.None)
{
RaisePropertyChangedEvent(
TogglePatternIdentifiers.ToggleStateProperty,
ToState(e.GetOldValue<bool>()),
ToState(e.GetNewValue<bool>()));
}
}
private static ToggleState ToState(bool value)
=> value ? ToggleState.On : ToggleState.Off;
}
}

95
tests/Avalonia.Controls.UnitTests/Automation/MenuItemAutomationPeerTests.cs

@ -0,0 +1,95 @@
using Avalonia.Automation;
using Avalonia.Automation.Peers;
using Avalonia.Automation.Provider;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests.Automation;
public class MenuItemAutomationPeerTests : ScopedTestBase
{
private static IToggleProvider GetProvider(MenuItem menuItem)
{
var provider = ControlAutomationPeer.CreatePeerForElement(menuItem).GetProvider<IToggleProvider>();
Assert.NotNull(provider);
return provider;
}
[Fact]
public void Toggle_Provider_Is_Not_Exposed_When_ToggleType_None()
{
var peer = ControlAutomationPeer.CreatePeerForElement(new MenuItem());
Assert.Null(peer.GetProvider<IToggleProvider>());
}
[Theory]
[InlineData(MenuItemToggleType.CheckBox)]
[InlineData(MenuItemToggleType.Radio)]
public void Toggle_Provider_Is_Exposed_For_Checkable_Items(MenuItemToggleType toggleType)
{
var peer = ControlAutomationPeer.CreatePeerForElement(new MenuItem { ToggleType = toggleType });
Assert.NotNull(peer.GetProvider<IToggleProvider>());
}
[Fact]
public void ToggleState_Reflects_IsChecked()
{
var menuItem = new MenuItem { ToggleType = MenuItemToggleType.CheckBox };
var provider = GetProvider(menuItem);
Assert.Equal(ToggleState.Off, provider.ToggleState);
menuItem.IsChecked = true;
Assert.Equal(ToggleState.On, provider.ToggleState);
}
[Fact]
public void Toggle_Flips_CheckBox_Item()
{
var menuItem = new MenuItem { ToggleType = MenuItemToggleType.CheckBox };
var provider = GetProvider(menuItem);
provider.Toggle();
Assert.True(menuItem.IsChecked);
provider.Toggle();
Assert.False(menuItem.IsChecked);
}
[Fact]
public void Toggle_Checks_But_Does_Not_Uncheck_Radio_Item()
{
var menuItem = new MenuItem { ToggleType = MenuItemToggleType.Radio };
var provider = GetProvider(menuItem);
provider.Toggle();
Assert.True(menuItem.IsChecked);
provider.Toggle();
Assert.True(menuItem.IsChecked);
}
[Fact]
public void Toggle_Raises_ToggleState_PropertyChanged()
{
var menuItem = new MenuItem { ToggleType = MenuItemToggleType.CheckBox };
var peer = ControlAutomationPeer.CreatePeerForElement(menuItem);
var provider = GetProvider(menuItem);
var raised = 0;
peer.PropertyChanged += (_, e) =>
{
if (e.Property == TogglePatternIdentifiers.ToggleStateProperty)
{
Assert.Equal(ToggleState.Off, e.OldValue);
Assert.Equal(ToggleState.On, e.NewValue);
raised++;
}
};
provider.Toggle();
Assert.Equal(1, raised);
}
}
Loading…
Cancel
Save