A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3
4using UnityEngine;
5using UnityEditor;
6using UnityEditor.IMGUI.Controls;
7
8using Codice.CM.Common;
9using PlasticGui;
10using PlasticGui.WorkspaceWindow.QueryViews;
11using Unity.PlasticSCM.Editor.UI;
12using Unity.PlasticSCM.Editor.UI.Avatar;
13using Unity.PlasticSCM.Editor.UI.Tree;
14
15namespace Unity.PlasticSCM.Editor.Views.Changesets
16{
17 internal class ChangesetsListView : PlasticTreeView
18 {
19 internal GenericMenu Menu { get { return mMenu.Menu; } }
20
21 internal ChangesetsListView(
22 ChangesetsListHeaderState headerState,
23 List<string> columnNames,
24 ChangesetsViewMenu menu,
25 Action sizeChangedAction,
26 Action selectionChangedAction,
27 Action doubleClickAction)
28 {
29 mColumnNames = columnNames;
30 mMenu = menu;
31 mSizeChangedAction = sizeChangedAction;
32 mSelectionChangedAction = selectionChangedAction;
33 mDoubleClickAction = doubleClickAction;
34
35 multiColumnHeader = new MultiColumnHeader(headerState);
36 multiColumnHeader.canSort = true;
37 multiColumnHeader.sortingChanged += SortingChanged;
38
39 mCooldownFilterAction = new CooldownWindowDelayer(
40 DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
41
42 mCooldownSelectionAction = new CooldownWindowDelayer(
43 DelayedSelectionChanged, UnityConstants.SELECTION_DELAYED_INPUT_ACTION_INTERVAL);
44 }
45
46 protected override void SelectionChanged(IList<int> selectedIds)
47 {
48 mCooldownSelectionAction.Ping();
49 }
50
51 internal void SetLoadedChangesetId(long loadedChangesetId)
52 {
53 mLoadedChangesetId = loadedChangesetId;
54 }
55
56 protected override IList<TreeViewItem> BuildRows(
57 TreeViewItem rootItem)
58 {
59 if (mQueryResult == null)
60 {
61 ClearRows(rootItem, mRows);
62
63 return mRows;
64 }
65
66 RegenerateRows(
67 mListViewItemIds,
68 mQueryResult.GetObjects(),
69 rootItem, mRows);
70
71 return mRows;
72 }
73
74 protected override void SearchChanged(string newSearch)
75 {
76 mCooldownFilterAction.Ping();
77 }
78
79 protected override void ContextClickedItem(int id)
80 {
81 mMenu.Popup();
82 Repaint();
83 }
84
85 public override void OnGUI(Rect rect)
86 {
87 if (Event.current.type == EventType.Layout)
88 {
89 if (IsSizeChanged(treeViewRect, mLastRect))
90 mSizeChangedAction();
91 }
92
93 mLastRect = treeViewRect;
94
95 base.OnGUI(rect);
96
97 Event e = Event.current;
98
99 if (e.type != EventType.KeyDown)
100 return;
101
102 bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
103
104 if (isProcessed)
105 e.Use();
106 }
107
108 protected override void RowGUI(RowGUIArgs args)
109 {
110 if (args.item is ChangesetListViewItem)
111 {
112 ChangesetListViewItem changesetListViewItem = (ChangesetListViewItem)args.item;
113 ChangesetInfo changesetInfo = (ChangesetInfo)changesetListViewItem.ObjectInfo;
114
115 ChangesetsListViewItemGUI(
116 mQueryResult,
117 rowHeight,
118 changesetListViewItem,
119 args,
120 changesetInfo.ChangesetId == mLoadedChangesetId,
121 Repaint);
122 return;
123 }
124
125 base.RowGUI(args);
126 }
127
128 protected override void DoubleClickedItem(int id)
129 {
130 if (GetSelection().Count != 1)
131 return;
132
133 mDoubleClickAction();
134 }
135
136 internal void BuildModel(
137 ViewQueryResult queryResult,
138 long loadedChangesetId)
139 {
140 mListViewItemIds.Clear();
141
142 mQueryResult = queryResult;
143 mLoadedChangesetId = loadedChangesetId;
144 }
145
146 internal void Refilter()
147 {
148 if (mQueryResult == null)
149 return;
150
151 Filter filter = new Filter(searchString);
152 mQueryResult.ApplyFilter(filter, mColumnNames);
153 }
154
155 internal void Sort()
156 {
157 if (mQueryResult == null)
158 return;
159
160 int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
161 bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
162
163 mQueryResult.Sort(
164 mColumnNames[sortedColumnIdx],
165 sortAscending);
166 }
167
168 internal List<RepositorySpec> GetSelectedRepositories()
169 {
170 List<RepositorySpec> result = new List<RepositorySpec>();
171
172 IList<int> selectedIds = GetSelection();
173
174 if (selectedIds.Count == 0)
175 return result;
176
177 foreach (KeyValuePair<object, int> item
178 in mListViewItemIds.GetInfoItems())
179 {
180 if (!selectedIds.Contains(item.Value))
181 continue;
182
183 RepositorySpec repSpec =
184 mQueryResult.GetRepositorySpec(item.Key);
185 result.Add(repSpec);
186 }
187
188 return result;
189 }
190
191 internal List<RepObjectInfo> GetSelectedRepObjectInfos()
192 {
193 List<RepObjectInfo> result = new List<RepObjectInfo>();
194
195 IList<int> selectedIds = GetSelection();
196
197 if (selectedIds.Count == 0)
198 return result;
199
200 foreach (KeyValuePair<object, int> item
201 in mListViewItemIds.GetInfoItems())
202 {
203 if (!selectedIds.Contains(item.Value))
204 continue;
205
206 RepObjectInfo repObjectInfo =
207 mQueryResult.GetRepObjectInfo(item.Key);
208 result.Add(repObjectInfo);
209 }
210
211 return result;
212 }
213
214 internal void SelectRepObjectInfos(
215 List<RepObjectInfo> repObjectsToSelect)
216 {
217 List<int> idsToSelect = new List<int>();
218
219 foreach (RepObjectInfo repObjectInfo in repObjectsToSelect)
220 {
221 int repObjectInfoId = GetTreeIdForItem(repObjectInfo);
222
223 if (repObjectInfoId == -1)
224 continue;
225
226 idsToSelect.Add(repObjectInfoId);
227 }
228
229 TableViewOperations.SetSelectionAndScroll(this, idsToSelect);
230 }
231
232 int GetTreeIdForItem(RepObjectInfo repObjectInfo)
233 {
234 foreach (KeyValuePair<object, int> item in mListViewItemIds.GetInfoItems())
235 {
236 RepObjectInfo currentRepObjectInfo =
237 mQueryResult.GetRepObjectInfo(item.Key);
238
239 if (!currentRepObjectInfo.Equals(repObjectInfo))
240 continue;
241
242 if (!currentRepObjectInfo.GUID.Equals(repObjectInfo.GUID))
243 continue;
244
245 return item.Value;
246 }
247
248 return -1;
249 }
250
251 void DelayedSearchChanged()
252 {
253 Refilter();
254
255 Sort();
256
257 Reload();
258
259 TableViewOperations.ScrollToSelection(this);
260 }
261
262 void DelayedSelectionChanged()
263 {
264 if (!HasSelection())
265 return;
266
267 mSelectionChangedAction();
268 }
269
270 void SortingChanged(MultiColumnHeader multiColumnHeader)
271 {
272 Sort();
273
274 Reload();
275 }
276
277 static void RegenerateRows(
278 ListViewItemIds<object> listViewItemIds,
279 List<object> objectInfos,
280 TreeViewItem rootItem,
281 List<TreeViewItem> rows)
282 {
283 ClearRows(rootItem, rows);
284
285 if (objectInfos.Count == 0)
286 return;
287
288 foreach (object objectInfo in objectInfos)
289 {
290 int objectId;
291 if (!listViewItemIds.TryGetInfoItemId(objectInfo, out objectId))
292 objectId = listViewItemIds.AddInfoItem(objectInfo);
293
294 ChangesetListViewItem changesetListViewItem =
295 new ChangesetListViewItem(objectId, objectInfo);
296
297 rootItem.AddChild(changesetListViewItem);
298 rows.Add(changesetListViewItem);
299 }
300 }
301
302 static void ClearRows(
303 TreeViewItem rootItem,
304 List<TreeViewItem> rows)
305 {
306 if (rootItem.hasChildren)
307 rootItem.children.Clear();
308
309 rows.Clear();
310 }
311
312 static void ChangesetsListViewItemGUI(
313 ViewQueryResult queryResult,
314 float rowHeight,
315 ChangesetListViewItem item,
316 RowGUIArgs args,
317 bool isBoldText,
318 Action avatarLoadedAction)
319 {
320 for (int visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++)
321 {
322 Rect cellRect = args.GetCellRect(visibleColumnIdx);
323
324 if (visibleColumnIdx == 0)
325 {
326 cellRect.x += UnityConstants.FIRST_COLUMN_WITHOUT_ICON_INDENT;
327 cellRect.width -= UnityConstants.FIRST_COLUMN_WITHOUT_ICON_INDENT;
328 }
329
330 ChangesetsListColumn column =
331 (ChangesetsListColumn)args.GetColumn(visibleColumnIdx);
332
333 ChangesetsListViewItemCellGUI(
334 cellRect,
335 rowHeight,
336 queryResult,
337 item,
338 column,
339 avatarLoadedAction,
340 args.selected,
341 args.focused,
342 isBoldText);
343 }
344 }
345
346 static void ChangesetsListViewItemCellGUI(
347 Rect rect,
348 float rowHeight,
349 ViewQueryResult queryResult,
350 ChangesetListViewItem item,
351 ChangesetsListColumn column,
352 Action avatarLoadedAction,
353 bool isSelected,
354 bool isFocused,
355 bool isBoldText)
356 {
357 string columnText = RepObjectInfoView.GetColumnText(
358 queryResult.GetRepositorySpec(item.ObjectInfo),
359 queryResult.GetRepObjectInfo(item.ObjectInfo),
360 ChangesetsListHeaderState.GetColumnName(column));
361
362 if (column == ChangesetsListColumn.CreatedBy)
363 {
364 DrawTreeViewItem.ForItemCell(
365 rect,
366 rowHeight,
367 -1,
368 GetAvatar.ForEmail(columnText, avatarLoadedAction),
369 null,
370 columnText,
371 isSelected,
372 isFocused,
373 isBoldText,
374 false);
375 return;
376 }
377
378
379 if (column == ChangesetsListColumn.Branch ||
380 column == ChangesetsListColumn.Repository ||
381 column == ChangesetsListColumn.Guid)
382 {
383 DrawTreeViewItem.ForSecondaryLabel(
384 rect, columnText, isSelected, isFocused, isBoldText);
385 return;
386 }
387
388 DrawTreeViewItem.ForLabel(
389 rect, columnText, isSelected, isFocused, isBoldText);
390 }
391
392 static bool IsSizeChanged(
393 Rect currentRect, Rect lastRect)
394 {
395 if (currentRect.width != lastRect.width)
396 return true;
397
398 if (currentRect.height != lastRect.height)
399 return true;
400
401 return false;
402 }
403
404 Rect mLastRect;
405
406 ListViewItemIds<object> mListViewItemIds = new ListViewItemIds<object>();
407
408 ViewQueryResult mQueryResult;
409 long mLoadedChangesetId;
410
411 readonly CooldownWindowDelayer mCooldownFilterAction;
412 readonly CooldownWindowDelayer mCooldownSelectionAction;
413 readonly Action mDoubleClickAction;
414 readonly Action mSelectionChangedAction;
415 readonly Action mSizeChangedAction;
416 readonly ChangesetsViewMenu mMenu;
417 readonly List<string> mColumnNames;
418 }
419}