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;
}
}
}
}