// Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using System.Collections.Generic; using System.Linq; namespace Perspex.Input { /// /// Defines extensions for the interface. /// public static class InputExtensions { /// /// Returns the active input elements at a point on an . /// /// The element to test. /// The point on . /// /// The active input elements found at the point, ordered topmost first. /// public static IEnumerable GetInputElementsAt(this IInputElement element, Point p) { Contract.Requires(element != null); if (element.Bounds.Contains(p) && element.IsVisible && element.IsHitTestVisible && element.IsEnabledCore) { p -= element.Bounds.Position; if (element.VisualChildren.Any()) { foreach (var child in ZSort(element.VisualChildren.OfType())) { foreach (var result in child.GetInputElementsAt(p)) { yield return result; } } } yield return element; } } /// /// Returns the topmost active input element at a point on an . /// /// The element to test. /// The point on . /// The topmost at the specified position. public static IInputElement InputHitTest(this IInputElement element, Point p) { return element.GetInputElementsAt(p).FirstOrDefault(); } private static IEnumerable ZSort(IEnumerable elements) { return elements .Select((element, index) => new ZOrderElement { Element = element, Index = index, ZIndex = element.ZIndex, }) .OrderBy(x => x, null) .Select(x => x.Element); } private class ZOrderElement : IComparable { public IInputElement Element { get; set; } public int Index { get; set; } public int ZIndex { get; set; } public int CompareTo(ZOrderElement other) { var z = other.ZIndex - ZIndex; if (z != 0) { return z; } else { return other.Index - Index; } } } } }