/// <summary>Gets the nearest focusable element below this.</summary> /// <returns>The nearest focusable element below. Null if there is none.</returns> public HtmlElement GetFocusableBelow() { // Has the element defined something specific? HtmlElement target = GetFocusableOverride("down"); if (target != null) { // Yep, it did! return(target); } // Distance of the nearest element (set when nearest is first set): float nearestDistance = 0f; // The current nearest element: HtmlElement nearest = null; // Grab my computed style: ComputedStyle computed = Style.Computed; // Get hold of the iterator (so we can safely skip child elements): NodeIterator allElements = document.allNodes; // Grab my x position: float myX = computed.GetMidpointX(); // Grab the midpoint of this element on Y: float myY = computed.GetMidpointY(); // For each element in the dom that is focusable and below this.. foreach (Node node in allElements) { HtmlElement element = node as HtmlElement; if (element == null) { continue; } if (element != this && element.IsBelow(myY) && element.focusable) { // We have an element below. // Check if it is closer than the current result. // If it is, it's the current result. // Is it nearer? float distance = element.DistanceFromFast(myX, myY); // Is it the first we've found, or is it nearer? if (nearest == null || distance < nearestDistance) { nearest = element; nearestDistance = distance; } // Make sure we don't now iterate its kids: allElements.SkipChildren = true; } } return(nearest); }
/// <summary>Finds the distance on both axis of the given point from this elements midpoint. Then, it divides /// the x result by the y result giving a ratio of 'verticalness' of the distance. This is used by focus graphs, as it can /// be used to perceive how upward or how downward an element is.</summary> private float VerticalDistanceRatio(float x, float y) { ComputedStyle computed = Style.Computed; // Find the distance along both axis: x -= computed.GetMidpointX(); y -= computed.GetMidpointY(); if (x < 0f) { x = -x; } if (y < 0f) { y = -y; } if (y == 0f) { // Horizontal line - it's not vertical at all! return(float.MaxValue); } return(x / y); }
/// <summary>Gets a relative 2D distance of this elements midpoint from the given point. /// The value returned is a fast distance used for comparison only. Use DistanceFrom for the correct distance.</summary> /// <param name="x">The x coordinate to check from.</param> /// <param name="y">The y coordinate to check from.</param> public float DistanceFromFast(float x, float y) { ComputedStyle computed = Style.Computed; x -= computed.GetMidpointX(); y -= computed.GetMidpointY(); return((x * x) + (y * y)); }
/// <summary>Finds out the distance in pixels on the x and y axis the given point is away from this elements midpoint.</summary> /// <param name="x">The x coordinate to check from.</param> /// <param name="y">The y coordinate to check from.</param> /// <returns>The distance on each axis from the given point as a vector.</returns> public Vector2 AxisDistanceFrom(float x, float y) { ComputedStyle computed = Style.Computed; x -= computed.GetMidpointX(); y -= computed.GetMidpointY(); if (x < 0f) { x = -x; } if (y < 0f) { y = -y; } return(new Vector2(x, y)); }
/// <summary>Gets the nearest focusable element below this.</summary> /// <returns>The nearest focusable element below. Null if there is none.</returns> public Element GetFocusableBelow() { // Has the element defined something specific? Element target = GetFocusableOverride("down"); if (target != null) { // Yep, it did! return(target); } // Distance of the nearest element (set when nearest is first set): float nearestDistance = 0f; // The current nearest element: Element nearest = null; // Grab my computed style: ComputedStyle computed = Style.Computed; // Get hold of the iterator (so we can safely skip child elements): DocumentElements allElements = Document.allElements; // Grab my x position: float myX = computed.GetMidpointX(); // Grab the midpoint of this element on Y: float myY = computed.GetMidpointY(); // For each element in the dom that is focusable and below this.. foreach (Element element in allElements) { if (element != this && element.IsBelow(computed) && element.focusable) { // We have an element below. // Check if it is closer than the current result. // If it is, it's the current result. // Is it nearer? float distance = element.DistanceFromFast(myX, myY); // Next, weight the distance by it's verticalness - that's by how much above/below the element actually looks. float verticalness = element.VerticalDistanceRatio(myX, myY); if (verticalness < 0.01f) { verticalness = 0.01f; } distance *= verticalness; // Is it the first we've found, or is it nearer? if (nearest == null || distance < nearestDistance) { nearest = element; nearestDistance = distance; } // Make sure we don't now iterate its kids: allElements.SkipChildren = true; } } return(nearest); }