/// <summary> /// Puts focus to some other block. /// </summary> /// <returns>true if successful, false if the method had no effect</returns> /// <remarks>Normally called before deleting a block.</remarks> public bool RemoveFocus(MoveFocusDirection direction) { Block neighbour = null; if (direction == MoveFocusDirection.SelectPrev || direction == MoveFocusDirection.SelectPrevInChain) { if (direction == MoveFocusDirection.SelectPrev) { neighbour = this.FindPrevFocusableBlock(); } else { neighbour = this.FindPrevFocusableBlockInChain(); } if (neighbour == null) { // if there is no prev block, // try to select next block neighbour = this.FindNextFocusableBlock(); } } else if (direction == MoveFocusDirection.SelectNext || direction == MoveFocusDirection.SelectNextInChain) { if (direction == MoveFocusDirection.SelectNext) { neighbour = this.FindNextFocusableBlock(); } else { neighbour = this.FindNextFocusableBlockInChain(); } if (neighbour == null) { // if there is no next block, // try to select previous block neighbour = this.FindPrevFocusableBlock(); } } if (neighbour == null) { // if toRemoveFocusFrom is the only block, // try to select parent neighbour = this.FindNearestFocusableParent(); } if (neighbour != null) { // if found someone, select it neighbour.SetFocus(); } return(neighbour != null); }
protected bool AlignedPanelMoveFocus1(MoveFocusDirection direction) { FrameworkElement currentElement = GetFocusedElementOrChild(); if (currentElement == null) { return(false); } RectangleF currentFocusRect = currentElement.ActualBounds; ICollection <FrameworkElement> focusableChildren = new List <FrameworkElement>(); AlignedPanelAddPotentialFocusNeighbors(currentFocusRect, focusableChildren, true); // Check child controls if (focusableChildren.Count == 0) { return(false); } FrameworkElement nextElement = FindNextFocusElement(focusableChildren, currentFocusRect, direction); return(nextElement != null && nextElement.TrySetFocus(true)); }
/// <summary> /// Moves the focus from the currently focused element in the screen to our last child in the given /// direction. For example if <c>direction == MoveFocusDirection.Up</c>, this method tries to focus the /// topmost child. /// </summary> /// <param name="direction">Direction to move the focus.</param> /// <returns><c>true</c>, if the focus could be moved to the desired child, else <c>false</c>.</returns> protected bool MoveFocusN(MoveFocusDirection direction) { FrameworkElement currentElement = GetFocusedElementOrChild(); if (currentElement == null) return false; ICollection<FrameworkElement> focusableChildren = GetFEChildren(); if (focusableChildren.Count == 0) return false; FrameworkElement nextElement; while ((nextElement = FindNextFocusElement(focusableChildren, currentElement.ActualBounds, direction)) != null) currentElement = nextElement; return currentElement.TrySetFocus(true); }
/// <summary> /// Moves the focus from the currently focused element in the screen to the first child element in the given /// direction. /// </summary> /// <param name="direction">Direction to move the focus.</param> /// <returns><c>true</c>, if the focus could be moved to the desired child, else <c>false</c>.</returns> protected bool MoveFocus1(MoveFocusDirection direction) { FrameworkElement currentElement = GetFocusedElementOrChild(); if (currentElement == null) return false; FrameworkElement nextElement = PredictFocus(currentElement.ActualBounds, direction); if (nextElement == null) return false; return nextElement.TrySetFocus(true); }
/// <summary> /// Searches through a collection of elements to find the best matching next focus element. /// </summary> /// <param name="potentialNextFocusElements">Collection of elements to search.</param> /// <param name="currentFocusRect">Bounds of the element which currently has focus.</param> /// <param name="dir">Direction to move the focus.</param> /// <returns>Next focusable element in the given <paramref name="dir"/> or <c>null</c>, if the given /// <paramref name="potentialNextFocusElements"/> don't contain a focusable element in the given direction.</returns> protected static FrameworkElement FindNextFocusElement(IEnumerable<FrameworkElement> potentialNextFocusElements, RectangleF? currentFocusRect, MoveFocusDirection dir) { FrameworkElement bestMatch = null; float bestDistance = float.MaxValue; float bestCenterDistance = float.MaxValue; float bestTopOrLeftDifference = float.MaxValue; if (!currentFocusRect.HasValue) return null; foreach (FrameworkElement child in potentialNextFocusElements) { float topOrLeftDifference; if ((dir == MoveFocusDirection.Up && child.LocatedAbove(currentFocusRect.Value, out topOrLeftDifference)) || (dir == MoveFocusDirection.Down && child.LocatedBelow(currentFocusRect.Value, out topOrLeftDifference)) || (dir == MoveFocusDirection.Left && child.LocatedLeftOf(currentFocusRect.Value, out topOrLeftDifference)) || (dir == MoveFocusDirection.Right && child.LocatedRightOf(currentFocusRect.Value, out topOrLeftDifference))) { // Calculate and compare distances of all matches float centerDistance = CenterDistance(child.ActualBounds, currentFocusRect.Value); if (centerDistance == 0) // If the child's center is exactly the center of the currently focused element, // it won't be used as next focus element continue; float distance = BorderDistance(child.ActualBounds, currentFocusRect.Value); if (bestMatch == null || (distance < bestDistance && topOrLeftDifference < 0) || (topOrLeftDifference < bestTopOrLeftDifference && (distance == bestDistance || bestTopOrLeftDifference >= 0)) /*|| topOrLeftDifference == bestTopOrLeftDifference && centerDistance < bestCenterDistance*/) { bestMatch = child; bestDistance = distance; bestCenterDistance = centerDistance; bestTopOrLeftDifference = topOrLeftDifference; } } } return bestMatch; }
/// <summary> /// Predicts the next control located inside this element which is positioned in the specified direction /// <paramref name="dir"/> to the specified <paramref name="currentFocusRect"/> and /// which is able to get the focus. /// This method will search the control tree down starting with this element as root element. /// This method is only able to find focusable elements which are located at least one element outside the visible /// range (see <see cref="AddPotentialFocusableElements"/>). /// </summary> /// <param name="currentFocusRect">The borders of the currently focused control.</param> /// <param name="dir">Direction, the result control should be positioned relative to the /// currently focused control.</param> /// <returns>Framework element which should get the focus, or <c>null</c>, if this control /// tree doesn't contain an appropriate control. The returned control will be /// visible, focusable and enabled.</returns> public virtual FrameworkElement PredictFocus(RectangleF? currentFocusRect, MoveFocusDirection dir) { if (!IsVisible || !IsEnabled) return null; ICollection<FrameworkElement> focusableChildren = new List<FrameworkElement>(); AddPotentialFocusableElements(currentFocusRect, focusableChildren); // Check child controls if (focusableChildren.Count == 0) return null; if (!currentFocusRect.HasValue) return focusableChildren.First(); FrameworkElement result = FindNextFocusElement(focusableChildren, currentFocusRect, dir); if (result != null) return result; return null; }
protected bool AlignedPanelMoveFocus1(MoveFocusDirection direction) { FrameworkElement currentElement = GetFocusedElementOrChild(); if (currentElement == null) return false; RectangleF currentFocusRect = currentElement.ActualBounds; ICollection<FrameworkElement> focusableChildren = new List<FrameworkElement>(); AlignedPanelAddPotentialFocusNeighbors(currentFocusRect, focusableChildren, true); // Check child controls if (focusableChildren.Count == 0) return false; FrameworkElement nextElement = FindNextFocusElement(focusableChildren, currentFocusRect, direction); return nextElement != null && nextElement.TrySetFocus(true); }
/// <summary> /// Puts focus to some other block. /// </summary> /// <returns>true if successful, false if the method had no effect</returns> /// <remarks>Normally called before deleting a block.</remarks> public bool RemoveFocus(MoveFocusDirection direction) { Block neighbour = null; if (direction == MoveFocusDirection.SelectPrev || direction == MoveFocusDirection.SelectPrevInChain) { if (direction == MoveFocusDirection.SelectPrev) { neighbour = this.FindPrevFocusableBlock(); } else { neighbour = this.FindPrevFocusableBlockInChain(); } if (neighbour == null) { // if there is no prev block, // try to select next block neighbour = this.FindNextFocusableBlock(); } } else if (direction == MoveFocusDirection.SelectNext || direction == MoveFocusDirection.SelectNextInChain) { if (direction == MoveFocusDirection.SelectNext) { neighbour = this.FindNextFocusableBlock(); } else { neighbour = this.FindNextFocusableBlockInChain(); } if (neighbour == null) { // if there is no next block, // try to select previous block neighbour = this.FindPrevFocusableBlock(); } } if (neighbour == null) { // if toRemoveFocusFrom is the only block, // try to select parent neighbour = this.FindNearestFocusableParent(); } if (neighbour != null) { // if found someone, select it neighbour.SetFocus(); } return neighbour != null; }