diff --git a/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridAutomationPeer.cs b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridAutomationPeer.cs new file mode 100644 index 00000000..39148c55 --- /dev/null +++ b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridAutomationPeer.cs @@ -0,0 +1,18 @@ +using Avalonia.Automation.Peers; + +namespace Avalonia.Controls.Automation.Peers; + +public class TreeDataGridAutomationPeer : ControlAutomationPeer +{ + public TreeDataGridAutomationPeer(TreeDataGrid owner) + : base(owner) + { + } + + public new TreeDataGrid Owner => (TreeDataGrid)base.Owner; + + protected override AutomationControlType GetAutomationControlTypeCore() + { + return AutomationControlType.DataGrid; + } +} diff --git a/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridCellAutomationPeer.cs b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridCellAutomationPeer.cs new file mode 100644 index 00000000..8a11eef6 --- /dev/null +++ b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridCellAutomationPeer.cs @@ -0,0 +1,39 @@ +using Avalonia.Automation.Peers; +using Avalonia.Controls.Primitives; + +namespace Avalonia.Controls.Automation.Peers; + +public class TreeDataGridCellAutomationPeer : ControlAutomationPeer +{ + public TreeDataGridCellAutomationPeer(TreeDataGridCell owner) + : base(owner) + { + } + + public new TreeDataGridCell Owner => (TreeDataGridCell)base.Owner; + + protected override AutomationControlType GetAutomationControlTypeCore() + { + return AutomationControlType.Custom; + } + + protected override bool IsContentElementCore() => true; + + protected override bool IsControlElementCore() => true; + + protected override string? GetNameCore() + { + var name = base.GetNameCore(); + if (!string.IsNullOrEmpty(name)) + { + return name; + } + + return Owner switch + { + TreeDataGridTextCell textCell => textCell.Value, + TreeDataGridTemplateCell templateCell => templateCell.Content?.ToString(), + _ => Owner.Model?.ToString() + }; + } +} diff --git a/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridColumnHeaderAutomationPeer.cs b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridColumnHeaderAutomationPeer.cs new file mode 100644 index 00000000..7ccc4b91 --- /dev/null +++ b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridColumnHeaderAutomationPeer.cs @@ -0,0 +1,23 @@ +using Avalonia.Automation.Peers; +using Avalonia.Controls.Primitives; + +namespace Avalonia.Controls.Automation.Peers; + +public class TreeDataGridColumnHeaderAutomationPeer : ContentControlAutomationPeer +{ + public TreeDataGridColumnHeaderAutomationPeer(TreeDataGridColumnHeader owner) + : base(owner) + { + } + + public new TreeDataGridColumnHeader Owner => (TreeDataGridColumnHeader)base.Owner; + + protected override AutomationControlType GetAutomationControlTypeCore() + { + return AutomationControlType.HeaderItem; + } + + protected override bool IsContentElementCore() => false; + + protected override bool IsControlElementCore() => true; +} diff --git a/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridColumnHeadersPresenterAutomationPeer.cs b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridColumnHeadersPresenterAutomationPeer.cs new file mode 100644 index 00000000..54821cad --- /dev/null +++ b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridColumnHeadersPresenterAutomationPeer.cs @@ -0,0 +1,23 @@ +using Avalonia.Automation.Peers; +using Avalonia.Controls.Primitives; + +namespace Avalonia.Controls.Automation.Peers; + +public class TreeDataGridColumnHeadersPresenterAutomationPeer : ControlAutomationPeer +{ + public TreeDataGridColumnHeadersPresenterAutomationPeer(TreeDataGridColumnHeadersPresenter owner) + : base(owner) + { + } + + public new TreeDataGridColumnHeadersPresenter Owner => (TreeDataGridColumnHeadersPresenter)base.Owner; + + protected override AutomationControlType GetAutomationControlTypeCore() + { + return AutomationControlType.Header; + } + + protected override bool IsContentElementCore() => false; + + protected override bool IsControlElementCore() => true; +} diff --git a/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridRowAutomationPeer.cs b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridRowAutomationPeer.cs new file mode 100644 index 00000000..abe5538e --- /dev/null +++ b/src/Avalonia.Controls.TreeDataGrid/Automation/Peers/TreeDataGridRowAutomationPeer.cs @@ -0,0 +1,61 @@ +using System; +using Avalonia.Automation.Peers; +using Avalonia.Automation.Provider; +using Avalonia.Controls.Models.TreeDataGrid; +using Avalonia.Controls.Primitives; + +namespace Avalonia.Controls.Automation.Peers; + +public class TreeDataGridRowAutomationPeer : ControlAutomationPeer, IToggleProvider, IValueProvider +{ + public TreeDataGridRowAutomationPeer(TreeDataGridRow owner) + : base(owner) + { + } + + public new TreeDataGridRow Owner => (TreeDataGridRow)base.Owner; + + public ToggleState ToggleState + { + get + { + if (Owner.DataContext is IExpander expander) + { + return expander.IsExpanded ? ToggleState.On : ToggleState.Off; + } + return ToggleState.Indeterminate; + } + } + + public bool IsReadOnly => true; + + public string? Value + { + get + { + return Owner.Model?.ToString(); + } + } + + protected override AutomationControlType GetAutomationControlTypeCore() + { + return AutomationControlType.TreeItem; + } + + protected override bool IsContentElementCore() => true; + + protected override bool IsControlElementCore() => true; + + public void Toggle() + { + if (Owner.DataContext is IExpander expander) + { + expander.IsExpanded = !expander.IsExpanded; + } + } + + public void SetValue(string? value) + { + throw new InvalidOperationException("TreeDataGrid rows are read-only."); + } +} diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs index 63e2f5ca..fd0618cb 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs @@ -1,5 +1,7 @@ using System; using System.ComponentModel; +using Avalonia.Automation.Peers; +using Avalonia.Controls.Automation.Peers; using Avalonia.Controls.Metadata; using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Selection; @@ -74,6 +76,11 @@ public virtual void Unrealize() Model = null; } + protected override AutomationPeer OnCreateAutomationPeer() + { + return new TreeDataGridCellAutomationPeer(this); + } + protected internal void BeginEdit() { if (!IsEditing) diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs index 8098a82a..42237aa6 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs @@ -1,5 +1,7 @@ using System; using System.ComponentModel; +using Avalonia.Automation.Peers; +using Avalonia.Controls.Automation.Peers; using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Input; using Avalonia.Utilities; @@ -81,6 +83,11 @@ public void Unrealize() UpdatePropertiesFromModel(); } + protected override AutomationPeer OnCreateAutomationPeer() + { + return new TreeDataGridColumnHeaderAutomationPeer(this); + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeadersPresenter.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeadersPresenter.cs index 085dcaba..fe5480ea 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeadersPresenter.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeadersPresenter.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Avalonia.Automation.Peers; +using Avalonia.Controls.Automation.Peers; using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Layout; using Avalonia.LogicalTree; @@ -12,6 +14,11 @@ public class TreeDataGridColumnHeadersPresenter : TreeDataGridColumnarPresenterB protected override Orientation Orientation => Orientation.Horizontal; + protected override AutomationPeer OnCreateAutomationPeer() + { + return new TreeDataGridColumnHeadersPresenterAutomationPeer(this); + } + protected override Size ArrangeOverride(Size finalSize) { (Items as IColumns)?.CommitActualWidths(); diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs index c9ad891a..f4bb95be 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs @@ -1,5 +1,7 @@ using System; using System.Text; +using Avalonia.Automation.Peers; +using Avalonia.Controls.Automation.Peers; using Avalonia.Controls.Metadata; using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Selection; @@ -112,6 +114,11 @@ public void Unrealize() CellsPresenter?.Unrealize(); } + protected override AutomationPeer OnCreateAutomationPeer() + { + return new TreeDataGridRowAutomationPeer(this); + } + protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { _treeDataGrid = this.FindLogicalAncestorOfType(); diff --git a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs index 1a8728a6..0a6f0232 100644 --- a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs +++ b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs @@ -2,6 +2,8 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Avalonia.Automation.Peers; +using Avalonia.Controls.Automation.Peers; using Avalonia.Controls.Documents; using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Primitives; @@ -310,6 +312,11 @@ public bool QueryCancelSelection() return e.Cancel; } + protected override AutomationPeer OnCreateAutomationPeer() + { + return new TreeDataGridAutomationPeer(this); + } + protected virtual TreeDataGridElementFactory CreateDefaultElementFactory() => new TreeDataGridElementFactory(); protected override void OnApplyTemplate(TemplateAppliedEventArgs e)