SearchBar.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. using System.Threading;
  3. using JetBrains.Annotations;
  4. using Unity.Cloud.Collaborate.Assets;
  5. using Unity.Cloud.Collaborate.UserInterface;
  6. using UnityEditor;
  7. using UnityEditor.UIElements;
  8. using UnityEngine;
  9. using UnityEngine.UIElements;
  10. namespace Unity.Cloud.Collaborate.Components
  11. {
  12. class SearchBar : VisualElement
  13. {
  14. public const string UssClassName = "unity-search-bar";
  15. public const string SearchFieldUssClassName = UssClassName + "__search-field";
  16. public const string PlaceholderUssClassName = UssClassName + "__placeholder";
  17. static readonly string k_StylePath = $"{CollaborateWindow.StylePath}/{nameof(SearchBar)}.uss";
  18. public const int timeoutMilliseconds = 1000;
  19. readonly ToolbarSearchField m_SearchField;
  20. readonly Label m_Placeholder;
  21. string m_LatestSearchValue;
  22. bool m_SearchEventFlag;
  23. readonly Timer m_SearchEventTimer;
  24. bool m_Focused;
  25. public event Action<string> Search = delegate { };
  26. public SearchBar() : this(null)
  27. {
  28. }
  29. public SearchBar([CanBeNull] Action<string> searchEvent = null)
  30. {
  31. // Setup delayed search event to throttle requests.
  32. m_SearchEventTimer = new Timer(_ => EditorApplication.delayCall += () =>
  33. {
  34. m_SearchEventFlag = false;
  35. Search(m_LatestSearchValue);
  36. });
  37. AddToClassList(UssClassName);
  38. styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>(k_StylePath));
  39. m_SearchField = new ToolbarSearchField();
  40. m_Placeholder = new Label { text = StringAssets.search, pickingMode = PickingMode.Ignore };
  41. m_SearchField.AddToClassList(SearchFieldUssClassName);
  42. m_Placeholder.AddToClassList(PlaceholderUssClassName);
  43. Add(m_SearchField);
  44. Add(m_Placeholder);
  45. // Setup search event
  46. if (searchEvent != null)
  47. {
  48. Search += searchEvent;
  49. }
  50. // Setup events to hide/show placeholder.
  51. var textField = m_SearchField.Q<TextField>(className: ToolbarSearchField.textUssClassName);
  52. textField.RegisterCallback<FocusInEvent>(e =>
  53. {
  54. m_Focused = true;
  55. UpdatePlaceholderVisibility();
  56. });
  57. textField.RegisterCallback<FocusOutEvent>(e =>
  58. {
  59. m_Focused = false;
  60. UpdatePlaceholderVisibility();
  61. });
  62. m_SearchField.RegisterValueChangedCallback(SearchEventThrottle);
  63. // Set initial placeholder hide/show status.
  64. ShowPlaceholder();
  65. }
  66. void SearchEventThrottle(ChangeEvent<string> evt)
  67. {
  68. UpdatePlaceholderVisibility();
  69. m_LatestSearchValue = evt.newValue;
  70. if (m_SearchEventFlag) return;
  71. m_SearchEventFlag = true;
  72. m_SearchEventTimer.Change(timeoutMilliseconds, Timeout.Infinite);
  73. }
  74. public string Value
  75. {
  76. get => m_SearchField.value;
  77. set
  78. {
  79. m_SearchField.value = value;
  80. UpdatePlaceholderVisibility();
  81. }
  82. }
  83. public void SetValueWithoutNotify(string value)
  84. {
  85. m_SearchField.SetValueWithoutNotify(value);
  86. UpdatePlaceholderVisibility();
  87. }
  88. void UpdatePlaceholderVisibility()
  89. {
  90. if (string.IsNullOrEmpty(m_SearchField.value) && !m_Focused)
  91. {
  92. ShowPlaceholder();
  93. }
  94. else
  95. {
  96. HidePlaceholder();
  97. }
  98. }
  99. void HidePlaceholder()
  100. {
  101. m_Placeholder.AddToClassList(UiConstants.ussHidden);
  102. }
  103. void ShowPlaceholder()
  104. {
  105. m_Placeholder.RemoveFromClassList(UiConstants.ussHidden);
  106. }
  107. [UsedImplicitly]
  108. public new class UxmlFactory : UxmlFactory<SearchBar> { }
  109. }
  110. }