namespace WallstopStudios.DataVisualizer.Editor.Extensions { using System; using System.Collections.Generic; using Styles; using UnityEngine; using UnityEngine.UIElements; internal static class UIExtensions { private static readonly string PlaceholderTextFieldClass = TextField.ussClassName + "__placeholder"; /// /// Sets up placeholder text to show when the TextField's text is empty. /// WARNING: Should only be called once. /// /// Target TextField. /// Text to use as a placeholder. /// If true, will set the text in the TextField to the empty string. public static void SetPlaceholderText( this TextField textField, string placeholder, bool clearExistingText = true ) { if (clearExistingText) { textField.value = string.Empty; } IVisualElementScheduledItem blinkSchedule = null; OnFocusOut(); textField.RegisterCallback(_ => OnFocusIn()); textField.RegisterCallback(_ => OnFocusOut()); return; void OnFocusIn() { if (string.Equals(textField.value, placeholder, StringComparison.Ordinal)) { textField.SetValueWithoutNotify(string.Empty); } textField.RemoveFromClassList(PlaceholderTextFieldClass); blinkSchedule?.Pause(); bool shouldRenderCursor = true; blinkSchedule = textField .schedule.Execute(() => { textField.EnableInClassList( StyleConstants.TransparentCursorClass, shouldRenderCursor ); textField.EnableInClassList( StyleConstants.StyledCursorClass, !shouldRenderCursor ); shouldRenderCursor = !shouldRenderCursor; }) .Every(StyleConstants.CursorBlinkRateMilliseconds); } void OnFocusOut() { textField.SetValueWithoutNotify(placeholder); textField.AddToClassList(PlaceholderTextFieldClass); blinkSchedule?.Pause(); blinkSchedule = null; textField.EnableInClassList(StyleConstants.TransparentCursorClass, false); textField.EnableInClassList(StyleConstants.StyledCursorClass, true); } } public static IEnumerable IterateChildrenRecursively( this VisualElement element ) { foreach (VisualElement child in element.Children()) { yield return child; foreach (VisualElement grandChild in IterateChildrenRecursively(child)) { yield return grandChild; } } } } }