/// <summary> /// Returns the element in the specified direction. /// </summary> /// <param name="direction">Indicates the direction in which to navigate.</param> /// <returns>Returns the element in the specified direction.</returns> internal override UiaCore.IRawElementProviderFragment?FragmentNavigate(UiaCore.NavigateDirection direction) { switch (direction) { case UiaCore.NavigateDirection.Parent: return(Parent); case UiaCore.NavigateDirection.NextSibling: case UiaCore.NavigateDirection.PreviousSibling: int index = GetChildFragmentIndex(); if (index == -1) { Debug.Fail("No item matched the index?"); return(null); } AccessibleObject?sibling = null; index += direction == UiaCore.NavigateDirection.NextSibling ? 1 : -1; int itemsCount = GetChildFragmentCount(); if (index >= 0 && index < itemsCount) { sibling = GetChildFragment(index, direction); } return(sibling); } return(base.FragmentNavigate(direction)); }
public override AccessibleObject?GetChild(int index) { if (index < GetChildCount()) { int selectedCellsCount = -1; for (int i = 1; i < _owningDataGridViewRow.AccessibilityObject.GetChildCount(); i++) { AccessibleObject?child = _owningDataGridViewRow.AccessibilityObject.GetChild(i); if (child is not null && (child.State & AccessibleStates.Selected) == AccessibleStates.Selected) { selectedCellsCount++; } if (selectedCellsCount == index) { return(child); } } Debug.Assert(false, "we should have found already the selected cell"); return(null); } else { return(null); } }
/// <summary> /// Return the child object at the given screen coordinates. /// </summary> /// <param name="x">X coordinate.</param> /// <param name="y">Y coordinate.</param> /// <returns>The accessible object of corresponding element in the provided coordinates.</returns> internal override UiaCore.IRawElementProviderFragment ElementProviderFromPoint(double x, double y) { AccessibleObject?element = HitTest((int)x, (int)y); if (element != null) { return(element); } return(base.ElementProviderFromPoint(x, y)); }
/// <summary> /// Gets the child control index. /// </summary> /// <param name="controlAccessibleObject">The control accessible object which index should be found.</param> /// <returns>The child accessible index or -1 if not found.</returns> internal int GetChildFragmentIndex(AccessibleObject controlAccessibleObject) { int childFragmentCount = GetChildFragmentCount(); for (int i = 0; i < childFragmentCount; i++) { AccessibleObject?childFragment = GetChildFragment(i); if (childFragment == controlAccessibleObject) { return(i); } } return(-1); }
internal override int GetChildIndex(AccessibleObject?child) { if (child is null || !_owningListView.SupportsListViewSubItems || child == _owningItem.SubItems[0].AccessibilityObject || child is not ListViewSubItem.ListViewSubItemAccessibleObject subItemAccessibleObject || subItemAccessibleObject.OwningSubItem is null) { return(-1); } int index = _owningItem.SubItems.IndexOf(subItemAccessibleObject.OwningSubItem); return(index == -1 || index > GetLastChildIndex() ? -1 : index); }
public async Task ListView_Tile_SubItem_FragmentNavigate_Sibling_ReturnsNull_For_SmallSizeAsync() { await RunTestAsync((form, listView) => { InitializeTileList(listView, columnCount: 5, subItemsCount: 5, tileSize: new Size(50, 40)); AccessibleObject?accessibleObject = listView.Items[0].SubItems[1].AccessibilityObject; IRawElementProviderFragment?nextAccessibleObject = accessibleObject?.FragmentNavigate(NavigateDirection.NextSibling); IRawElementProviderFragment?previousAccessibleObject = accessibleObject?.FragmentNavigate(NavigateDirection.PreviousSibling); Assert.Null(nextAccessibleObject); Assert.Null(previousAccessibleObject); return(Task.CompletedTask); }); }
/// <summary> /// Return the child object at the given screen coordinates. /// </summary> /// <param name="x">X coordinate.</param> /// <param name="y">Y coordinate.</param> /// <returns>The accessible object of corresponding element in the provided coordinates.</returns> internal override UiaCore.IRawElementProviderFragment ElementProviderFromPoint(double x, double y) { if (!_owningListBox.IsHandleCreated) { return(base.ElementProviderFromPoint(x, y)); } AccessibleObject?element = HitTest((int)x, (int)y); if (element != null) { return(element); } return(base.ElementProviderFromPoint(x, y)); }
public async Task ListView_Tile_FragmentNavigate_WorksExpectedAsync(int columnCount, int subItemsCount, int width, int height, int itemIndex, int subItemIndex, int direction) { await RunTestAsync((form, listView) => { InitializeTileList(listView, columnCount, subItemsCount, tileSize: new Size(width, height)); Application.DoEvents(); AccessibleObject accessibleObject = listView.Items[0].AccessibilityObject; IRawElementProviderFragment?actualAccessibleObject = accessibleObject.FragmentNavigate((NavigateDirection)direction); AccessibleObject?expectedAccessibleObject = listView.Items[itemIndex].SubItems[subItemIndex].AccessibilityObject; Assert.Equal(expectedAccessibleObject, actualAccessibleObject); return(Task.CompletedTask); }); }
public override int GetChildCount() { int selectedCellsCount = 0; // start the enumeration from 1, because the first acc obj in the data grid view row is the row header cell for (int i = 1; i < _owningDataGridViewRow.AccessibilityObject.GetChildCount(); i++) { AccessibleObject?child = _owningDataGridViewRow.AccessibilityObject.GetChild(i); if (child is not null && (child.State & AccessibleStates.Selected) == AccessibleStates.Selected) { selectedCellsCount++; } } return(selectedCellsCount); }
internal override int GetChildIndex(AccessibleObject?child) { if (child is null || !_owningListView.SupportsListViewSubItems || child is not ListViewSubItem.ListViewSubItemAccessibleObject subItemAccessibleObject) { return(InvalidIndex); } if (subItemAccessibleObject.OwningSubItem is null) { return(GetFakeSubItemIndex(subItemAccessibleObject)); } int index = _owningItem.SubItems.IndexOf(subItemAccessibleObject.OwningSubItem); return(index > _owningListView.Columns.Count - 1 ? InvalidIndex : index); }
public CalendarChildAccessibleObject?GetFromPoint(MCHITTESTINFO hitTestInfo) { switch ((MCHT)hitTestInfo.uHit) { case MCHT.CALENDARDAY: case MCHT.CALENDARWEEKNUM: case MCHT.CALENDARDATE: AccessibleObject?rowAccessibleObject = _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, hitTestInfo.iRow); if (rowAccessibleObject is null) { return(null); } return(_calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, rowAccessibleObject, hitTestInfo.iCol)); } return(this); }
public async Task ListView_Tile_SubItem_FragmentNavigate_NextSibling_ReturnsExpectedAsync() { await RunTestAsync((form, listView) => { InitializeTileList(listView, columnCount: 4, subItemsCount: 4, tileSize: new Size(100, 100)); Application.DoEvents(); AccessibleObject?accessibleObject1 = listView.Items[0].SubItems[1].AccessibilityObject; AccessibleObject?accessibleObject2 = (AccessibleObject?)accessibleObject1?.FragmentNavigate(NavigateDirection.NextSibling); AccessibleObject?accessibleObject3 = (AccessibleObject?)accessibleObject2?.FragmentNavigate(NavigateDirection.NextSibling); AccessibleObject?accessibleObject4 = (AccessibleObject?)accessibleObject3?.FragmentNavigate(NavigateDirection.NextSibling); Assert.Equal(listView.Items[0].SubItems[2].AccessibilityObject, accessibleObject2); Assert.Equal(listView.Items[0].SubItems[3].AccessibilityObject, accessibleObject3); Assert.Null(accessibleObject4); return(Task.CompletedTask); }); }
internal override int GetChildIndex(AccessibleObject?child) { if (child is null || !_owningListView.IsHandleCreated || !_owningListView.GroupsDisplayed) { return(InvalidIndex); } IReadOnlyList <ListViewItem> visibleItems = GetVisibleItems(); for (int i = 0; i < visibleItems.Count; i++) { if (visibleItems[i].AccessibilityObject == child) { return(i); } } return(InvalidIndex); }
internal override UiaCore.IRawElementProviderSimple[] GetSelection() { if (!_owningComboBox.IsHandleCreated) { return(Array.Empty <UiaCore.IRawElementProviderSimple>()); } int selectedIndex = _owningComboBox.SelectedIndex; AccessibleObject?itemAccessibleObject = GetChildFragment(selectedIndex); if (itemAccessibleObject != null) { return(new UiaCore.IRawElementProviderSimple[] { itemAccessibleObject }); } return(Array.Empty <UiaCore.IRawElementProviderSimple>()); }
internal unsafe override void SelectItem() { if (_owningPropertyGrid is null || !_owningPropertyGrid.IsHandleCreated) { return; } bool initialState = _owningPropertyGridToolStripButton.Checked; _owningPropertyGridToolStripButton.PerformClick(); // This code is required to simulate the behavior in 4.7.1. When we call "Toggle" method on an already // checked button, the focus switches to the ToolStrip. If the button was not checked before the call, // then the focus is switched to the table with properties. AccessibleObject?focusedAccessibleObject = initialState ? _owningPropertyGridToolStripButton.Parent?.AccessibilityObject : _owningPropertyGridToolStripButton._owningPropertyGrid.GridViewAccessibleObject.GetFocused(); focusedAccessibleObject?.RaiseAutomationEvent(UiaCore.UIA.AutomationFocusChangedEventId); }
public override AccessibleObject?Navigate(AccessibleNavigation navigationDirection) { if (Owner is null) { throw new InvalidOperationException(SR.DataGridViewCellAccessibleObject_OwnerNotSet); } if (Owner.OwningColumn is null || Owner.DataGridView is null) { return(null); } switch (navigationDirection) { case AccessibleNavigation.Right: return(Owner.DataGridView.RightToLeft == RightToLeft.No ? NavigateForward() : NavigateBackward()); case AccessibleNavigation.Next: return(NavigateForward()); case AccessibleNavigation.Left: return(Owner.DataGridView.RightToLeft == RightToLeft.No ? NavigateBackward() : NavigateForward()); case AccessibleNavigation.Previous: return(NavigateBackward()); case AccessibleNavigation.FirstChild: // return the top left header cell accessible object return(Parent?.GetChild(0)); case AccessibleNavigation.LastChild: // return the last column header cell in the top row header accessible object AccessibleObject?topRowHeaderAccessibleObject = Parent; return(topRowHeaderAccessibleObject?.GetChild(topRowHeaderAccessibleObject.GetChildCount() - 1)); default: return(null); } }
public async Task ListView_Tile_SubItem_HitTest_ReturnExpectedAsync() { await RunTestAsync((form, listView) => { InitializeTileList(listView, columnCount: 3, subItemsCount: 2, tileSize: new Size(100, 100)); Application.DoEvents(); AccessibleObject?expectedAccessibleItem1 = listView.Items[0].SubItems[1].AccessibilityObject; AccessibleObject?expectedAccessibleItem2 = listView.Items[0].SubItems[2].AccessibilityObject; AccessibleObject actualAccessibleItem1 = HitTest(GetSubItemLocation(0, 1)); AccessibleObject actualAccessibleItem2 = HitTest(GetSubItemLocation(0, 2)); Assert.Equal(expectedAccessibleItem1, actualAccessibleItem1); Assert.Equal(expectedAccessibleItem2, actualAccessibleItem2); AccessibleObject HitTest(Point point) => listView.AccessibilityObject.HitTest(point.X, point.Y) !; Point GetSubItemLocation(int itemIndex, int subItemIndex) => listView.PointToScreen(listView.GetSubItemRect(itemIndex, subItemIndex, ItemBoundsPortion.Label).Location); return(Task.CompletedTask); }); }
internal override int GetChildIndex(AccessibleObject?child) => - 1;
/// <summary> /// Perform custom navigation between parent/child/sibling accessible objects, /// using tab index order as the guide, rather than letting the system default /// behavior do navigation based on z-order. /// /// For a container control and its child controls, the accessible object tree /// looks like this... /// /// [client area of container] /// [non-client area of child #1] /// [random non-client elements] /// [client area of child #1] /// [random non-client elements] /// [non-client area of child #2] /// [random non-client elements] /// [client area of child #2] /// [random non-client elements] /// [non-client area of child #3] /// [random non-client elements] /// [client area of child #3] /// [random non-client elements] /// /// We need to intercept first-child / last-child navigation from the container's /// client object, and next-sibling / previous-sibling navigation from each child's /// non-client object. All other navigation operations must be allowed to fall back /// on the system's default behavior (provided by OLEACC.DLL). /// /// When combined with the re-ordering behavior of GetSysChildOrder() above, this /// allows us to present the end user with the illusion of accessible objects in /// tab index order, even though the system behavior only supports z-order. /// </summary> internal override bool GetSysChild(AccessibleNavigation navdir, out AccessibleObject?accessibleObject) { // Clear the out parameter accessibleObject = null; // Get the owning control's parent, if it has one Control parentControl = Owner.ParentInternal; // ctrls[index] will indicate the control at the destination of this navigation operation int index = -1; Control[]? ctrls = null; // Now handle any 'appropriate' navigation requests... switch (navdir) { case AccessibleNavigation.FirstChild: if (IsClientObject) { ctrls = Owner.GetChildControlsInTabOrder(true); index = 0; } break; case AccessibleNavigation.LastChild: if (IsClientObject) { ctrls = Owner.GetChildControlsInTabOrder(true); index = ctrls.Length - 1; } break; case AccessibleNavigation.Previous: if (IsNonClientObject && parentControl is not null) { ctrls = parentControl.GetChildControlsInTabOrder(true); index = Array.IndexOf(ctrls, Owner); if (index != -1) { --index; } } break; case AccessibleNavigation.Next: if (IsNonClientObject && parentControl is not null) { ctrls = parentControl.GetChildControlsInTabOrder(true); index = Array.IndexOf(ctrls, Owner); if (index != -1) { ++index; } } break; } // Unsupported navigation operation for this object, or unexpected error. // Return false to force fall back on default system navigation behavior. if (ctrls is null || ctrls.Length == 0) { return(false); } // If ctrls[index] is a valid control, return its non-client accessible object. // If index is invalid, return null pointer meaning "end of list reached". if (index >= 0 && index < ctrls.Length) { accessibleObject = ctrls[index].NcAccessibilityObject; } // Return true to use the found accessible object and block default system behavior return(true); }
internal override int GetChildIndex(AccessibleObject?child) => child is TreeNodeAccessibleObject node ? node.Index : -1;
/// <summary> /// Sets the parent accessible object for the node which can be added or removed to/from hierarchy nodes. /// </summary> /// <param name="parent">The parent accessible object.</param> internal override void SetParent(AccessibleObject?parent) { _parentAccessibleObject = parent; }