forked from Unity-Technologies/UnityCsReference
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTreeViewDataSource.cs
More file actions
408 lines (343 loc) · 12.6 KB
/
Copy pathTreeViewDataSource.cs
File metadata and controls
408 lines (343 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditorInternal;
namespace UnityEditor.IMGUI.Controls
{
// TreeViewDataSource is a base abstract class for a data source for a TreeView.
// Usage:
// Override FetchData () and build the entire tree with m_RootItem as root.
// Configure showRootItem and rootIsCollapsable as wanted
//
// Note: if dealing with very large trees use LazyTreeViewDataSource instead: it assumes that tree only contains visible items.
internal abstract class TreeViewDataSource : ITreeViewDataSource
{
protected readonly TreeViewController m_TreeView; // TreeView using this data source
protected TreeViewItem m_RootItem;
protected IList<TreeViewItem> m_Rows;
protected bool m_NeedRefreshRows = true;
protected TreeViewItem m_FakeItem;
public bool showRootItem { get; set; }
public bool rootIsCollapsable { get; set; }
public bool alwaysAddFirstItemToSearchResult { get; set; } // is only used in searches when showRootItem is false. It Doesn't make sense for visible roots
public TreeViewItem root { get { return m_RootItem; } }
public System.Action onVisibleRowsChanged;
protected List<int> expandedIDs
{
get {return m_TreeView.state.expandedIDs; }
set { m_TreeView.state.expandedIDs = value; }
}
public TreeViewDataSource(TreeViewController treeView)
{
m_TreeView = treeView;
showRootItem = true;
rootIsCollapsable = false;
m_RootItem = null;
onVisibleRowsChanged = null;
}
virtual public void OnInitialize()
{
}
// Implement this function and build entire tree with m_RootItem as root
public abstract void FetchData();
public virtual void ReloadData()
{
m_FakeItem = null;
FetchData();
}
virtual public TreeViewItem FindItem(int id)
{
return TreeViewUtility.FindItem(id, m_RootItem);
}
virtual public bool IsRevealed(int id)
{
IList<TreeViewItem> rows = GetRows();
return TreeViewController.GetIndexOfID(rows, id) >= 0;
}
virtual public void RevealItem(int id)
{
if (IsRevealed(id))
return;
// Reveal (expand parents up to root)
TreeViewItem item = FindItem(id);
if (item != null)
{
TreeViewItem parent = item.parent;
while (parent != null)
{
SetExpanded(parent, true);
parent = parent.parent;
}
}
}
virtual public void RevealItems(int[] ids)
{
HashSet<int> expandedSet = new HashSet<int>(expandedIDs);
int orgSize = expandedSet.Count;
// Add all parents above id
foreach (var id in ids)
{
if (IsRevealed(id))
continue;
// Reveal (expand parents up to root)
TreeViewItem item = FindItem(id);
if (item != null)
{
TreeViewItem parent = item.parent;
while (parent != null)
{
expandedSet.Add(parent.id);
parent = parent.parent;
}
}
}
if (orgSize != expandedSet.Count)
{
// Bulk set expanded ids (is sorted in SetExpandedIDs)
SetExpandedIDs(expandedSet.ToArray());
// Refresh immediately if any Item was expanded
if (m_NeedRefreshRows)
FetchData();
}
}
virtual public void OnSearchChanged()
{
m_NeedRefreshRows = true;
}
//----------------------------
// Visible Item section
protected void GetVisibleItemsRecursive(TreeViewItem item, IList<TreeViewItem> items)
{
if (item != m_RootItem || showRootItem)
items.Add(item);
if (item.hasChildren && IsExpanded(item))
foreach (TreeViewItem child in item.children)
GetVisibleItemsRecursive(child, items);
}
protected void SearchRecursive(TreeViewItem item, string search, IList<TreeViewItem> searchResult)
{
if (item.displayName.ToLower().Contains(search))
searchResult.Add(item);
if (item.children != null)
foreach (TreeViewItem child in item.children)
SearchRecursive(child, search, searchResult);
}
virtual protected List<TreeViewItem> ExpandedRows(TreeViewItem root)
{
var result = new List<TreeViewItem>();
GetVisibleItemsRecursive(m_RootItem, result);
return result;
}
// Searches the current tree by displayName.
virtual protected List<TreeViewItem> Search(TreeViewItem root, string search)
{
var result = new List<TreeViewItem>();
if (showRootItem)
{
SearchRecursive(root, search, result);
result.Sort(new TreeViewItemAlphaNumericSort());
}
else
{
int startIndex = alwaysAddFirstItemToSearchResult ? 1 : 0;
if (root.hasChildren)
{
for (int i = startIndex; i < root.children.Count; ++i)
{
SearchRecursive(root.children[i], search, result);
}
result.Sort(new TreeViewItemAlphaNumericSort());
if (alwaysAddFirstItemToSearchResult)
result.Insert(0, root.children[0]);
}
}
return result;
}
virtual public int rowCount
{
get
{
return GetRows().Count;
}
}
virtual public int GetRow(int id)
{
var rows = GetRows();
for (int row = 0; row < rows.Count; ++row)
{
if (rows[row].id == id)
return row;
}
return -1;
}
virtual public TreeViewItem GetItem(int row)
{
return GetRows()[row];
}
// Get the flattend tree of visible items.
virtual public IList<TreeViewItem> GetRows()
{
InitIfNeeded();
return m_Rows;
}
virtual public void InitIfNeeded()
{
// Cached for large trees...
if (m_Rows == null || m_NeedRefreshRows)
{
if (m_RootItem != null)
{
if (m_TreeView.isSearching)
m_Rows = Search(m_RootItem, m_TreeView.searchString.ToLower());
else
m_Rows = ExpandedRows(m_RootItem);
}
else
{
Debug.LogError("TreeView root item is null. Ensure that your TreeViewDataSource sets up at least a root item.");
m_Rows = new List<TreeViewItem>();
}
m_NeedRefreshRows = false;
// TODO: This should be named something like: 'onVisibleRowsReloaded'
if (onVisibleRowsChanged != null)
onVisibleRowsChanged();
// Expanded state has changed ensure that we repaint
m_TreeView.Repaint();
}
}
public bool isInitialized
{
get { return m_RootItem != null && m_Rows != null; }
}
//----------------------------
// Expanded/collapsed section
virtual public int[] GetExpandedIDs()
{
return expandedIDs.ToArray();
}
virtual public void SetExpandedIDs(int[] ids)
{
expandedIDs = new List<int>(ids);
expandedIDs.Sort();
m_NeedRefreshRows = true;
OnExpandedStateChanged();
}
virtual public bool IsExpanded(int id)
{
return expandedIDs.BinarySearch(id) >= 0;
}
virtual public bool SetExpanded(int id, bool expand)
{
bool expanded = IsExpanded(id);
if (expand != expanded)
{
if (expand)
{
System.Diagnostics.Debug.Assert(!expandedIDs.Contains(id));
expandedIDs.Add(id);
expandedIDs.Sort();
}
else
{
expandedIDs.Remove(id);
}
m_NeedRefreshRows = true;
OnExpandedStateChanged();
return true;
}
return false;
}
virtual public void SetExpandedWithChildren(int id, bool expand)
{
SetExpandedWithChildren(FindItem(id), expand);
}
virtual public void SetExpandedWithChildren(TreeViewItem fromItem, bool expand)
{
if (fromItem == null)
{
Debug.LogError("item is null");
return;
}
HashSet<int> parents = new HashSet<int>();
TreeViewUtility.GetParentsBelowItem(fromItem, parents);
// Get existing expanded in hashset
HashSet<int> oldExpandedSet = new HashSet<int>(expandedIDs);
if (expand)
oldExpandedSet.UnionWith(parents);
else
oldExpandedSet.ExceptWith(parents);
// Bulk set expanded ids (is sorted in SetExpandedIDs)
SetExpandedIDs(oldExpandedSet.ToArray());
}
virtual public void SetExpanded(TreeViewItem item, bool expand)
{
SetExpanded(item.id, expand);
}
virtual public bool IsExpanded(TreeViewItem item)
{
return IsExpanded(item.id);
}
virtual public bool IsExpandable(TreeViewItem item)
{
// Ignore expansion (foldout arrow) when showing search results
if (m_TreeView.isSearching)
return false;
return item.hasChildren;
}
virtual public bool CanBeMultiSelected(TreeViewItem item)
{
return true;
}
virtual public bool CanBeParent(TreeViewItem item)
{
return true;
}
virtual public List<int> GetNewSelection(TreeViewItem clickedItem, TreeViewSelectState selectState)
{
// Get ids from items
var visibleRows = GetRows();
List<int> allIDs = new List<int>(visibleRows.Count);
for (int i = 0; i < visibleRows.Count; ++i)
allIDs.Add(visibleRows[i].id);
bool allowMultiselection = CanBeMultiSelected(clickedItem);
return InternalEditorUtility.GetNewSelection(clickedItem.id, allIDs, selectState.selectedIDs, selectState.lastClickedID, selectState.keepMultiSelection, selectState.useShiftAsActionKey, allowMultiselection);
}
virtual public void OnExpandedStateChanged()
{
if (m_TreeView.expandedStateChanged != null)
m_TreeView.expandedStateChanged();
}
//----------------------------
// Renaming section
virtual public bool IsRenamingItemAllowed(TreeViewItem item)
{
return true;
}
//----------------------------
// Insert tempoary Item section
// Fake Item should be inserted into the m_VisibleRows (not the tree itself).
virtual public void InsertFakeItem(int id, int parentID, string name, Texture2D icon)
{
Debug.LogError("InsertFakeItem missing implementation");
}
virtual public bool HasFakeItem()
{
return m_FakeItem != null;
}
virtual public void RemoveFakeItem()
{
if (!HasFakeItem())
return;
var visibleRows = GetRows();
int index = TreeViewController.GetIndexOfID(visibleRows, m_FakeItem.id);
if (index != -1)
{
visibleRows.RemoveAt(index);
}
m_FakeItem = null;
}
}
}