A game about forced loneliness, made by TACStudios
1// UITK TreeView is not supported in earlier versions
2// Therefore the UITK version of the InputActionAsset Editor is not available on earlier Editor versions either.
3#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
4using System;
5using System.Threading.Tasks;
6using UnityEditor;
7using UnityEngine.InputSystem.Editor;
8using UnityEngine.UIElements;
9
10namespace UnityEngine.InputSystem.Editor
11{
12 /// <summary>
13 /// A visual element that supports renaming of items.
14 /// </summary>
15 internal class InputActionMapsTreeViewItem : VisualElement
16 {
17 public EventCallback<string> EditTextFinishedCallback;
18
19 private const string kRenameTextField = "rename-text-field";
20 public event EventCallback<string> EditTextFinished;
21 public Action<ContextualMenuPopulateEvent> OnContextualMenuPopulateEvent;
22
23 // for testing purposes to know if the item is focused to accept input
24 internal bool IsFocused { get; private set; } = false;
25
26 private bool m_IsEditing;
27 private static InputActionMapsTreeViewItem s_EditingItem = null;
28
29 public InputActionMapsTreeViewItem()
30 {
31 var template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
32 InputActionsEditorConstants.PackagePath +
33 InputActionsEditorConstants.ResourcesPath +
34 InputActionsEditorConstants.InputActionMapsTreeViewItemUxml);
35 template.CloneTree(this);
36
37 focusable = true;
38 delegatesFocus = false;
39
40 renameTextfield.selectAllOnFocus = true;
41 renameTextfield.selectAllOnMouseUp = false;
42
43 RegisterCallback<MouseDownEvent>(OnMouseDownEventForRename);
44 renameTextfield.RegisterCallback<FocusInEvent>(e => IsFocused = true);
45 renameTextfield.RegisterCallback<FocusOutEvent>(e => { OnEditTextFinished(); IsFocused = false; });
46 _ = new ContextualMenuManipulator(menuBuilder =>
47 {
48 OnContextualMenuPopulateEvent?.Invoke(menuBuilder);
49 })
50 { target = this };
51 }
52
53 public Label label => this.Q<Label>();
54 private TextField renameTextfield => this.Q<TextField>(kRenameTextField);
55
56
57 public void UnregisterInputField()
58 {
59 renameTextfield.SetEnabled(false);
60 renameTextfield.selectAllOnFocus = false;
61 UnregisterCallback<MouseDownEvent>(OnMouseDownEventForRename);
62 renameTextfield.UnregisterCallback<FocusOutEvent>(e => OnEditTextFinished());
63 }
64
65 private double lastSingleClick;
66 private static InputActionMapsTreeViewItem selected;
67
68 private void OnMouseDownEventForRename(MouseDownEvent e)
69 {
70 if (e.clickCount != 1 || e.button != (int)MouseButton.LeftMouse || e.target == null)
71 return;
72 var now = EditorApplication.timeSinceStartup;
73 if (selected == this && now - lastSingleClick < 3)
74 {
75 FocusOnRenameTextField();
76 e.StopImmediatePropagation();
77 lastSingleClick = 0;
78 return;
79 }
80 lastSingleClick = now;
81 selected = this;
82 }
83
84 public void Reset()
85 {
86 if (m_IsEditing)
87 {
88 lastSingleClick = 0;
89 delegatesFocus = false;
90
91 renameTextfield.AddToClassList(InputActionsEditorConstants.HiddenStyleClassName);
92 label.RemoveFromClassList(InputActionsEditorConstants.HiddenStyleClassName);
93 s_EditingItem = null;
94 m_IsEditing = false;
95 }
96 EditTextFinished = null;
97 }
98
99 public void FocusOnRenameTextField()
100 {
101 if (m_IsEditing)
102 return;
103 delegatesFocus = true;
104
105 renameTextfield.SetValueWithoutNotify(label.text);
106 renameTextfield.RemoveFromClassList(InputActionsEditorConstants.HiddenStyleClassName);
107 label?.AddToClassList(InputActionsEditorConstants.HiddenStyleClassName);
108
109 //a bit hacky - e.StopImmediatePropagation() for events does not work like expected on ListViewItems or TreeViewItems because
110 //the listView/treeView reclaims the focus - this is a workaround with less overhead than rewriting the events
111 schedule.Execute(() => renameTextfield.Q<TextField>().Focus()).StartingIn(120);
112 renameTextfield.SelectAll();
113
114 s_EditingItem = this;
115 m_IsEditing = true;
116 }
117
118 public static void CancelRename()
119 {
120 s_EditingItem?.OnEditTextFinished();
121 }
122
123 private void OnEditTextFinished()
124 {
125 if (!m_IsEditing)
126 return;
127 lastSingleClick = 0;
128 delegatesFocus = false;
129
130 renameTextfield.AddToClassList(InputActionsEditorConstants.HiddenStyleClassName);
131 label.RemoveFromClassList(InputActionsEditorConstants.HiddenStyleClassName);
132 s_EditingItem = null;
133 m_IsEditing = false;
134
135 var text = renameTextfield.text?.Trim();
136 if (string.IsNullOrEmpty(text))
137 {
138 renameTextfield.schedule.Execute(() => renameTextfield.SetValueWithoutNotify(text));
139 return;
140 }
141
142 EditTextFinished?.Invoke(text);
143 }
144 }
145}
146#endif