ext/Aga.Controls/Tree/TreeViewAdv.Accessibility.cs (248 lines of code) (raw):

/* * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; version 2 of the * License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ using System; using System.Drawing; using System.Text; using System.Windows.Forms; using Aga.Controls.Tree.NodeControls; namespace Aga.Controls.Tree { public partial class TreeViewAdv { protected override AccessibleObject CreateAccessibilityInstance() { return new TreeViewAdvAccessibleObject(this); } /// <summary> /// Represents the tree control itself. /// </summary> public class TreeViewAdvAccessibleObject : Control.ControlAccessibleObject { private TreeViewAdv treeView; public TreeViewAdvAccessibleObject(TreeViewAdv owner) : base(owner) { treeView = owner; } public override AccessibleRole Role { get { return AccessibleRole.Outline; } } public override string Name { get { return treeView.Name; } } /// <summary> /// Returns the node under the mouse pointer. /// </summary> /// <param name="x">X screen coordinate.</param> /// <param name="y">Y screen coordinate.</param> /// <returns>The node under the mouse pointer.</returns> public override AccessibleObject HitTest(int x, int y) { TreeNodeAdv node = treeView.GetNodeAt(treeView.PointToClient(new Point(x, y))); if (node != null) return new AdvNodeAccessibleObject(node, null, this); if (treeView.RectangleToScreen(treeView.ClientRectangle).Contains(x, y)) return this; return null; } /// <summary> /// Returns a child node. /// </summary> /// <param name="index">The index of the child node.</param> /// <returns>The child node.</returns> public override AccessibleObject GetChild(int index) { return new AdvNodeAccessibleObject(treeView.Root.Nodes[index], null, this); } /// <summary> /// Returns the number of children. /// </summary> /// <returns>The number of children in the tree root.</returns> public override int GetChildCount() { return treeView.Root.Nodes.Count; } } /// <summary> /// Accessibility representation of a node in the treeview. /// </summary> public class AdvNodeAccessibleObject : AccessibleObject { TreeNodeAdv node; AdvNodeAccessibleObject parent; TreeViewAdvAccessibleObject owner; public AdvNodeAccessibleObject(TreeNodeAdv advNode, AdvNodeAccessibleObject parent, TreeViewAdvAccessibleObject owner) : base() { node = advNode; this.parent = parent; this.owner = owner; } /// <summary> /// The bounding rectangle in screen coordinates. /// </summary> public override Rectangle Bounds { get { if (!node.IsVisible) return Rectangle.Empty; Rectangle bounds = node.Tree.GetNodeBounds(node); Point p = node.Tree.ScrollPosition; int colHeaderY = node.Tree.UseColumns ? node.Tree.ColumnHeaderHeight : 0; bounds.Offset(-p.X, -p.Y * node.Tree.RowHeight + colHeaderY); return node.Tree.RectangleToScreen(bounds); } } /// <summary> /// The name of the default action. /// </summary> public override string DefaultAction { get { return node.IsExpanded ? "Collapse" : "Expand"; } } /// <summary> /// Performs the default action, which is either collapsing or expand the tree node /// </summary> public override void DoDefaultAction() { if (node.IsExpanded) node.Collapse(); else node.Expand(); } /// <summary> /// Either selects or focuses the tree node. /// </summary> /// <param name="flags">either select or focus.</param> public override void Select(AccessibleSelection flags) { if ((flags & AccessibleSelection.TakeSelection) > 0) node.Tree.SelectedNode = node; else if ((flags & AccessibleSelection.TakeFocus) > 0) { TreeNodeAdv parent = node.Parent; while (parent != null) { if (!parent.IsExpanded) parent.Expand(); parent = parent.Parent; } node.Tree.ScrollTo(node); node.Tree.Focus(); } } /// <summary> /// This does nothing because it is done by the tree. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public override AccessibleObject HitTest(int x, int y) { return null; } /// <summary> /// The name is the first node control value which returns a string. /// </summary> public override string Name { get { foreach (NodeControlInfo info in node.Tree.GetNodeControls(node)) { BindableControl ctrl = info.Control as BindableControl; if (ctrl != null) { string val = ctrl.GetValue(node) as string; if (val != null) return val; } } return null; } } /// <summary> /// A number of state flags /// The Checked state uses the value of the first checkbox it finds. /// </summary> public override AccessibleStates State { get { AccessibleStates states = AccessibleStates.Selectable; if (node.IsExpanded) states |= AccessibleStates.Expanded; else states |= AccessibleStates.Collapsed; Rectangle treeRect = node.Tree.ClientRectangle; treeRect.Offset(node.Tree.PointToScreen(Point.Empty)); if (!node.IsVisible || !treeRect.IntersectsWith(Bounds) || treeRect.IsEmpty) states |= AccessibleStates.Invisible; if (node.IsSelected) states |= AccessibleStates.Selected; foreach (NodeControlInfo info in node.Tree.GetNodeControls(node)) { NodeCheckBox cb = info.Control as NodeCheckBox; if (cb != null) { if (((CheckState)cb.GetValue(node)) == CheckState.Checked) states |= AccessibleStates.Checked; } } return states; } } public override AccessibleRole Role { get { return AccessibleRole.OutlineItem; } } /// <summary> /// Returns both child nodes and table cells, if available. /// </summary> /// <param name="index"></param> /// <returns></returns> public override AccessibleObject GetChild(int index) { int ctrlCount = node.Tree.Columns.Count; if (index < ctrlCount) return new AdvNodeCellAccessibleObject(node, index, this); return new AdvNodeAccessibleObject(node.Nodes[index - ctrlCount], this, owner); } public override int GetChildCount() { return node.Nodes.Count + node.Tree.Columns.Count; } public override AccessibleObject Parent { get { if (node.Parent != node.Tree.Root) return parent != null ? parent : new AdvNodeAccessibleObject(node.Parent, null, owner); return owner; } } } public class AdvNodeCellAccessibleObject : AccessibleObject { TreeNodeAdv node; AdvNodeAccessibleObject parent; int colIndex; public AdvNodeCellAccessibleObject(TreeNodeAdv advNode, int colIndex, AdvNodeAccessibleObject parent) : base() { this.node = advNode; this.colIndex = colIndex; this.parent = parent; } public override Rectangle Bounds { get { if (!node.IsVisible) return Rectangle.Empty; Rectangle colBounds = node.Tree.GetColumnBounds(colIndex); Rectangle nodeBounds = node.Tree.GetNodeBounds(node); Rectangle bounds = new Rectangle(colBounds.X, nodeBounds.Y, colBounds.Width, nodeBounds.Height); Point p = node.Tree.ScrollPosition; int colHeaderY = node.Tree.UseColumns ? node.Tree.ColumnHeaderHeight : 0; bounds.Offset(-p.X, -p.Y * node.Tree.RowHeight + colHeaderY); return node.Tree.RectangleToScreen(bounds); } } public override AccessibleRole Role { get { return AccessibleRole.Cell; } } public override string Name { get { string header = node.Tree.Columns[colIndex].Header; if (string.IsNullOrEmpty(header)) header = "Column" + colIndex; return header; } } /// <summary> /// The cell value is the contents of all node control values belonging to the column the cell is in. /// </summary> public override string Value { get { StringBuilder sb = new StringBuilder(); foreach (NodeControlInfo info in node.Tree.GetNodeControls(node)) { BindableControl ctrl = info.Control as BindableControl; if (ctrl != null && ctrl.ParentColumn != null && ctrl.ParentColumn.Index == colIndex) { object val = ctrl.GetValue(node); if (val != null) sb.AppendLine(val.ToString()); } } return sb.ToString().Trim(); } } public override AccessibleObject Parent { get { return parent; } } /// <summary> /// This does nothing because it is done by the tree. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public override AccessibleObject HitTest(int x, int y) { return null; } } } }