Skip to content

Commit

Permalink
feat: Implement ToggleSwitchAutomationPeer
Browse files Browse the repository at this point in the history
  • Loading branch information
morning4coffe-dev authored and MartinZikmund committed Jun 17, 2024
1 parent db69ab1 commit 3f72be5
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 46 deletions.
141 changes: 111 additions & 30 deletions src/Uno.UI/UI/Xaml/Automation/Peers/ToggleSwitchAutomationPeer.cs
Original file line number Diff line number Diff line change
@@ -1,53 +1,134 @@
using Microsoft.UI.Xaml.Controls;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
// MUX Reference TreeViewListAutomationPeer.cpp, tag winui3/release/1.4.2

using DirectUI;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;
using static Microsoft/* UWP don't rename */.UI.Xaml.Controls._Tracing;

namespace Microsoft.UI.Xaml.Automation.Peers
namespace Microsoft.UI.Xaml.Automation.Peers;

/// <summary>
/// Exposes ToggleSwitch types to Microsoft UI Automation.
/// </summary>
public partial class ToggleSwitchAutomationPeer : FrameworkElementAutomationPeer, Provider.IToggleProvider
{
/// <summary>
/// Exposes ToggleSwitch types to Microsoft UI Automation.
/// Initializes a new instance of the ToggleSwitchAutomationPeer class.
/// </summary>
public partial class ToggleSwitchAutomationPeer : FrameworkElementAutomationPeer, Provider.IToggleProvider
/// <param name="owner"></param>
public ToggleSwitchAutomationPeer(ToggleSwitch owner) : base(owner)
{
}

protected override object GetPatternCore(PatternInterface patternInterface)
{
/// <summary>
/// Initializes a new instance of the ToggleSwitchAutomationPeer class.
/// </summary>
/// <param name="owner"></param>
public ToggleSwitchAutomationPeer(ToggleSwitch owner) : base(owner)
if (patternInterface == PatternInterface.Toggle)
{
return this;
}
else
{
return base.GetPatternCore(patternInterface);
}
}

protected override string GetClassNameCore() => "ToggleSwitch";
protected override string GetClassNameCore() => nameof(ToggleSwitch);

protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Button;
protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Button;

/// <summary>
/// Gets the toggle state of the control.
/// </summary>
public ToggleState ToggleState => ((ToggleSwitch)Owner).IsOn ? ToggleState.On : ToggleState.Off;
protected override string GetLocalizedControlTypeCore() =>
DXamlCore.GetCurrentNoCreate()?.GetLocalizedResourceString(nameof(ToggleSwitch)) ?? base.GetLocalizedControlTypeCore();

/// <summary>
/// Cycles through the toggle states of a control.
/// </summary>
public void Toggle()
protected override string GetNameCore()
{
// If the control has an explicitly set UIA Name, use that
// Otherwise we construct a Name from the Header text and the On/OffContent
var baseName = base.GetNameCore();
if (!string.IsNullOrEmpty(baseName))
{
return baseName;
}
else
{
if (IsEnabled())
if (Owner is not ToggleSwitch owner)
{
((ToggleSwitch)Owner).AutomationPeerToggle();
return string.Empty;
}
}

internal void RaiseToggleStatePropertyChangedEvent(object pOldValue, object pNewValue)
{
var oldValue = ToggleButtonAutomationPeer.ConvertToToggleState(pOldValue);
var newValue = ToggleButtonAutomationPeer.ConvertToToggleState(pNewValue);
var headerText = owner.Header?.ToString() ?? string.Empty;
var onOffContentText = string.Empty;

MUX_ASSERT(oldValue != ToggleState.Indeterminate);
MUX_ASSERT(newValue != ToggleState.Indeterminate);
if (owner.IsOn)
{
// We only want to include the OnContent if custom content has been provided.
// The default value of OnContent is the string "On", but including this in the UIA Name adds no value, since this information is
// already included in the ToggleState. Narrator reads out both the ToggleState and the Name (We don't want it to read "On On ToggleSwitch").
if (owner.OnContent is { } onContent)
{
onOffContentText = onContent.ToString() ?? string.Empty;
}
}
else
{
// As above, we only include custom OffContent.
if (owner.OffContent is { } offContent)
{
onOffContentText = offContent.ToString() ?? string.Empty;
}
}

if (oldValue != newValue)
if (!string.IsNullOrEmpty(headerText) && !string.IsNullOrEmpty(onOffContentText))
{
// Return the header text followed by the on/off content separated by a space:
return $"{headerText} {onOffContentText}";
}
else if (!string.IsNullOrEmpty(headerText))
{
return headerText;
}
else
{
RaisePropertyChangedEvent(TogglePatternIdentifiers.ToggleStateProperty, oldValue, newValue);
// onOffContentText might be empty, but that's ok.
return onOffContentText;
}
}
}

protected override Point GetClickablePointCore()
{
var owner = Owner as ToggleSwitch;
return owner.AutomationGetClickablePoint();
}

/// <summary>
/// Gets the toggle state of the control.
/// </summary>
public ToggleState ToggleState => ((ToggleSwitch)Owner).IsOn ? ToggleState.On : ToggleState.Off;

/// <summary>
/// Cycles through the toggle states of a control.
/// </summary>
public void Toggle()
{
if (IsEnabled())
{
((ToggleSwitch)Owner).AutomationPeerToggle();
}
}

internal void RaiseToggleStatePropertyChangedEvent(object pOldValue, object pNewValue)
{
var oldValue = ToggleButtonAutomationPeer.ConvertToToggleState(pOldValue);
var newValue = ToggleButtonAutomationPeer.ConvertToToggleState(pNewValue);

MUX_ASSERT(oldValue != ToggleState.Indeterminate);
MUX_ASSERT(newValue != ToggleState.Indeterminate);

if (oldValue != newValue)
{
RaisePropertyChangedEvent(TogglePatternIdentifiers.ToggleStateProperty, oldValue, newValue);
}
}
}
33 changes: 17 additions & 16 deletions src/Uno.UI/UI/Xaml/Controls/ToggleSwitch/ToggleSwitch.mux.cs
Original file line number Diff line number Diff line change
Expand Up @@ -358,22 +358,23 @@ private void AutomationToggleSwitchOnToggle()
}
#endif

//private void
//AutomationGetClickablePoint(
// _Out_ wf.Point* result)
//{
// auto clickableElement =
// _tpThumb ?
// static_cast<UIElement*>(_tpThumb.Cast<Thumb>()) :
// static_cast<UIElement*>(this);

// XPOINTF point;
// static_cast<CUIElement*>(clickableElement.GetHandle()).GetClickablePointRasterizedClient(&point));

// *result = { point.x, point.y };

// return S_OK;
//}
public Point AutomationGetClickablePoint()
{
//UNO TODO: Implement AutomationGetClickablePoint on ToggleSwitch
return new Point();

// auto clickableElement =
// _tpThumb ?
// static_cast<UIElement*>(_tpThumb.Cast<Thumb>()) :
// static_cast<UIElement*>(this);

// XPOINTF point;
// static_cast<CUIElement*>(clickableElement.GetHandle()).GetClickablePointRasterizedClient(&point));

// *result = { point.x, point.y };

// return S_OK;
}

protected override AutomationPeer OnCreateAutomationPeer() =>
new ToggleSwitchAutomationPeer(this);
Expand Down

0 comments on commit 3f72be5

Please sign in to comment.