using System.Diagnostics.CodeAnalysis; using System.Numerics; using Content.Client.Guidebook.Controls; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; namespace Content.Client.UserInterface.ControlExtensions; public static class ControlExtension { public static List GetControlOfType(this Control parent) where T : Control { return parent.GetControlOfType(typeof(T).Name, false); } public static List GetControlOfType(this Control parent, string childType) where T : Control { return parent.GetControlOfType(childType, false); } public static List GetControlOfType(this Control parent, bool fullTreeSearch) where T : Control { return parent.GetControlOfType(typeof(T).Name, fullTreeSearch); } public static List GetControlOfType(this Control parent, string childType, bool fullTreeSearch) where T : Control { List controlList = new List(); foreach (var child in parent.Children) { var isType = child.GetType().Name == childType; var hasChildren = child.ChildCount > 0; var searchDeeper = hasChildren && !isType; if (isType) { controlList.Add((T) child); } if (fullTreeSearch || searchDeeper) { controlList.AddRange(child.GetControlOfType(childType, fullTreeSearch)); } } return controlList; } public static List GetSearchableControls(this Control parent, bool fullTreeSearch = false) { List controlList = new List(); foreach (var child in parent.Children) { var hasChildren = child.ChildCount > 0; var searchDeeper = hasChildren && child is not ISearchableControl; if (child is ISearchableControl searchableChild) { controlList.Add(searchableChild); } if (fullTreeSearch || searchDeeper) { controlList.AddRange(child.GetSearchableControls(fullTreeSearch)); } } return controlList; } /// /// Search the control’s tree for a parent node of type T /// E.g. to find the control implementing some event handling interface. /// public static bool TryGetParentHandler(this Control child, [NotNullWhen(true)] out T? result) { for (var control = child; control is not null; control = control.Parent) { if (control is not T handler) continue; result = handler; return true; } result = default; return false; } /// /// Find the control’s offset relative to its closest ScrollContainer /// Returns null if the control is not in the tree or not visible. /// public static Vector2? GetControlScrollPosition(this Control child) { if (!child.VisibleInTree) return null; var position = new Vector2(); var control = child; while (control is not null) { // The scroll container's direct child is re-positioned while scrolling, // so we need to ignore its position. if (control.Parent is ScrollContainer) break; position += control.Position; control = control.Parent; } return position; } public static bool ChildrenContainText(this Control parent, string search) { var labels = parent.GetControlOfType