// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.VisualTree { using System; using System.Collections.Generic; using System.Linq; /// /// Provides extension methods for working with visual tree. /// public static class VisualExtensions { /// /// Enumerates the ancestors of an in the visual tree. /// /// The visual. /// The visual's ancestors. public static IEnumerable GetVisualAncestors(this IVisual visual) { Contract.Requires(visual != null); visual = visual.VisualParent; while (visual != null) { yield return visual; visual = visual.VisualParent; } } /// /// Enumerates an and its ancestors in the visual tree. /// /// The visual. /// The visual and its ancestors. public static IEnumerable GetSelfAndVisualAncestors(this IVisual visual) { yield return visual; foreach (var ancestor in visual.GetVisualAncestors()) { yield return ancestor; } } /// /// Gets the first visual in the visual tree whose bounds contain a point. /// /// The root visual to test. /// The point. /// The visuals at the requested point. public static IVisual GetVisualAt(this IVisual visual, Point p) { Contract.Requires(visual != null); return visual.GetVisualsAt(p).FirstOrDefault(); } /// /// Enumerates the visuals in the visual tree whose bounds contain a point. /// /// The root visual to test. /// The point. /// The visuals at the requested point. public static IEnumerable GetVisualsAt(this IVisual visual, Point p) { Contract.Requires(visual != null); if (visual.Bounds.Contains(p)) { p -= visual.Bounds.Position; if (visual.VisualChildren.Any()) { foreach (IVisual child in visual.VisualChildren) { foreach (IVisual v in child.GetVisualsAt(p)) { yield return v; } } } yield return visual; } } /// /// Enumerates the children of an in the visual tree. /// /// The visual. /// The visual children. public static IEnumerable GetVisualChildren(this IVisual visual) { return visual.VisualChildren; } /// /// Enumerates the descendents of an in the visual tree. /// /// The visual. /// The visual's ancestors. public static IEnumerable GetVisualDescendents(this IVisual visual) { foreach (IVisual child in visual.VisualChildren) { yield return child; foreach (IVisual descendent in child.GetVisualDescendents()) { yield return descendent; } } } /// /// Enumerates an and its descendents in the visual tree. /// /// The visual. /// The visual and its ancestors. public static IEnumerable GetSelfAndVisualDescendents(this IVisual visual) { yield return visual; foreach (var ancestor in visual.GetVisualDescendents()) { yield return ancestor; } } /// /// Gets the visual parent of an . /// /// The visual. /// The parent, or null if the visual is unparented. public static IVisual GetVisualParent(this IVisual visual) { return visual.VisualParent; } /// /// Gets the visual parent of an . /// /// The type of the visual parent. /// The visual. /// /// The parent, or null if the visual is unparented or its parent is not of type . /// public static T GetVisualParent(this IVisual visual) where T : class { return visual.VisualParent as T; } /// /// Gets the root visual for an . /// /// The visual. /// /// The root visual or null if the visual is not rooted. /// public static IVisual GetVisualRoot(this IVisual visual) { Contract.Requires(visual != null); var parent = visual.VisualParent; while (parent != null) { visual = parent; parent = visual.VisualParent; } return visual; } /// /// Tests whether an is an ancestor of another visual. /// /// The visual. /// The potential descendent. /// /// True if is an ancestor of ; /// otherwise false. /// public static bool IsVisualAncestorOf(this IVisual visual, IVisual target) { return target.GetVisualAncestors().Any(x => x == visual); } } }