using System; using JetBrains.Annotations; using Unity.Cloud.Collaborate.Assets; using Unity.Cloud.Collaborate.UserInterface; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; namespace Unity.Cloud.Collaborate.Components { // Hopefully these features will eventually be in the default TextField eventually. internal class BetterTextField : TextField { /// /// USS class name of elements of this type. /// public const string UssClassName = "unity-better-text-field"; /// /// USS class name of placeholder elements of this type. /// public const string PlaceholderUssClassName = UssClassName + "__placeholder"; static readonly string k_StylePath = $"{CollaborateWindow.StylePath}/{nameof(BetterTextField)}.uss"; readonly Label m_PlaceholderLabel; /// /// Notify external subscribers that value of text property changed. /// public Action OnValueChangedHandler; public BetterTextField() { AddToClassList(UssClassName); styleSheets.Add(AssetDatabase.LoadAssetAtPath(k_StylePath)); // Add and configure placeholder m_PlaceholderLabel = new Label { pickingMode = PickingMode.Ignore }; m_PlaceholderLabel.AddToClassList(PlaceholderUssClassName); Add(m_PlaceholderLabel); RegisterCallback(e => HidePlaceholder()); RegisterCallback(e => { if (string.IsNullOrEmpty(text)) { ShowPlaceholder(); } }); this.RegisterValueChangedCallback(e => OnValueChangedHandler?.Invoke(e.newValue)); } void UpdatePlaceholderVisibility() { if (string.IsNullOrEmpty(value)) { // Value can be set before the focus control is initialised. if (focusController?.focusedElement != this) { ShowPlaceholder(); } } else { HidePlaceholder(); } } void HidePlaceholder() { m_PlaceholderLabel?.AddToClassList(UiConstants.ussHidden); } void ShowPlaceholder() { m_PlaceholderLabel?.RemoveFromClassList(UiConstants.ussHidden); } public override string value { get => base.value; set { // Catch case of value being set programatically. base.value = value; UpdatePlaceholderVisibility(); } } public string Placeholder { get => m_PlaceholderLabel.text; set => m_PlaceholderLabel.text = value; } public override void SetValueWithoutNotify(string newValue) { base.SetValueWithoutNotify(newValue); UpdatePlaceholderVisibility(); } [UsedImplicitly] public new class UxmlFactory : UxmlFactory { } public new class UxmlTraits : TextField.UxmlTraits { readonly UxmlStringAttributeDescription m_Hint = new UxmlStringAttributeDescription { name = "placeholder" }; public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) { base.Init(ve, bag, cc); var field = (BetterTextField)ve; field.Placeholder = m_Hint.GetValueFromBag(bag, cc); } } } }