Fixing issue 3206: Label control accessibility reworking (#3208)

* Moving LabelAccessibleObject to a separate file. Adding unit tests.
* Ensuring Label supports UIA providers.
This commit is contained in:
Mikhail Lipin 2020-07-06 12:28:22 +03:00 коммит произвёл GitHub
Родитель f1a55bb2ca
Коммит 6f85a5d9c7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 100 добавлений и 82 удалений

Просмотреть файл

@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using static Interop;
namespace System.Windows.Forms
{
public partial class Label
{
internal class LabelAccessibleObject : ControlAccessibleObject
{
private readonly Label _owningLabel;
public LabelAccessibleObject(Label owner) : base(owner)
{
_owningLabel = owner;
}
public override AccessibleRole Role
{
get
{
AccessibleRole role = _owningLabel.AccessibleRole;
if (role != AccessibleRole.Default)
{
return role;
}
return AccessibleRole.StaticText;
}
}
internal override object? GetPropertyValue(UiaCore.UIA propertyID)
=> propertyID switch
{
UiaCore.UIA.NamePropertyId => Name,
UiaCore.UIA.AutomationIdPropertyId => _owningLabel.Name,
UiaCore.UIA.ControlTypePropertyId => UiaCore.UIA.TextControlTypeId,
_ => base.GetPropertyValue(propertyID)
};
}
}
}

Просмотреть файл

@ -26,7 +26,7 @@ namespace System.Windows.Forms
[ToolboxItem("System.Windows.Forms.Design.AutoSizeToolboxItem," + AssemblyRef.SystemDesign)]
[SRDescription(nameof(SR.DescriptionLabel))]
// If not for FormatControl, we could inherit from ButtonBase and get foreground images for free.
public class Label : Control, IAutomationLiveRegion
public partial class Label : Control, IAutomationLiveRegion
{
private static readonly object EVENT_TEXTALIGNCHANGED = new object();
@ -1635,98 +1635,63 @@ namespace System.Windows.Forms
}
}
internal class LabelAccessibleObject : ControlAccessibleObject
/// <summary>
/// Override ImageList.Indexer to support Label's ImageList semantics.
/// </summary>
internal class LabelImageIndexer : ImageList.Indexer
{
public LabelAccessibleObject(Label owner) : base(owner)
private readonly Label owner;
private bool useIntegerIndex = true;
public LabelImageIndexer(Label owner)
{
this.owner = owner;
}
public override AccessibleRole Role
public override ImageList ImageList
{
get { return owner?.ImageList; }
set { Debug.Assert(false, "Setting the image list in this class is not supported"); }
}
public override string Key
{
get => base.Key;
set
{
base.Key = value;
useIntegerIndex = false;
}
}
public override int Index
{
get => base.Index;
set
{
base.Index = value;
useIntegerIndex = true;
}
}
public override int ActualIndex
{
get
{
AccessibleRole role = Owner.AccessibleRole;
if (role != AccessibleRole.Default)
if (useIntegerIndex)
{
return role;
// The behavior of label is to return the last item in the Images collection
// if the index is currently set higher than the count.
return (Index < ImageList.Images.Count) ? Index : ImageList.Images.Count - 1;
}
return AccessibleRole.StaticText;
else if (ImageList != null)
{
return ImageList.Images.IndexOfKey(Key);
}
return -1;
}
}
internal override bool IsIAccessibleExSupported() => true;
internal override object GetPropertyValue(UiaCore.UIA propertyID)
{
switch (propertyID)
{
case UiaCore.UIA.NamePropertyId:
return Name;
case UiaCore.UIA.ControlTypePropertyId:
return UiaCore.UIA.TextControlTypeId;
}
return base.GetPropertyValue(propertyID);
}
}
}
/// <summary>
/// Override ImageList.Indexer to support Label's ImageList semantics.
/// </summary>
internal class LabelImageIndexer : ImageList.Indexer
{
private readonly Label owner;
private bool useIntegerIndex = true;
public LabelImageIndexer(Label owner)
{
this.owner = owner;
}
public override ImageList ImageList
{
get { return owner?.ImageList; }
set { Debug.Assert(false, "Setting the image list in this class is not supported"); }
}
public override string Key
{
get => base.Key;
set
{
base.Key = value;
useIntegerIndex = false;
}
}
public override int Index
{
get => base.Index;
set
{
base.Index = value;
useIntegerIndex = true;
}
}
public override int ActualIndex
{
get
{
if (useIntegerIndex)
{
// The behavior of label is to return the last item in the Images collection
// if the index is currently set higher than the count.
return (Index < ImageList.Images.Count) ? Index : ImageList.Images.Count - 1;
}
else if (ImageList != null)
{
return ImageList.Images.IndexOfKey(Key);
}
return -1;
}
}
}
}

Просмотреть файл

@ -216,6 +216,13 @@ namespace System.Windows.Forms.Tests
Assert.Equal(-1, control.ImageIndex);
}
[WinFormsFact]
public void Label_SupportsUiaProviders_returns_true()
{
using var label = new Label();
Assert.True(label.SupportsUiaProviders);
}
public class SubLabel : Label
{
public new bool CanEnableIme => base.CanEnableIme;