PendingChangesTreeView.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Linq;
  4. using UnityEditor.IMGUI.Controls;
  5. using UnityEngine;
  6. using Codice.Client.BaseCommands;
  7. using Codice.Client.Common;
  8. using Codice.CM.Common;
  9. using PlasticGui;
  10. using PlasticGui.WorkspaceWindow.PendingChanges;
  11. using Unity.PlasticSCM.Editor.AssetUtils;
  12. using Unity.PlasticSCM.Editor.UI;
  13. using Unity.PlasticSCM.Editor.UI.Tree;
  14. using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
  15. using Unity.PlasticSCM.Editor.AssetsOverlays;
  16. namespace Unity.PlasticSCM.Editor.Views.PendingChanges
  17. {
  18. internal class PendingChangesTreeView : TreeView
  19. {
  20. internal PendingChangesTreeView(
  21. WorkspaceInfo wkInfo,
  22. bool isGluonMode,
  23. PendingChangesTreeHeaderState headerState,
  24. List<string> columnNames,
  25. PendingChangesViewMenu menu,
  26. IAssetStatusCache assetStatusCache)
  27. : base(new TreeViewState())
  28. {
  29. mWkInfo = wkInfo;
  30. mIsGluonMode = isGluonMode;
  31. mColumnNames = columnNames;
  32. mMenu = menu;
  33. mAssetStatusCache = assetStatusCache;
  34. mPendingChangesTree = new UnityPendingChangesTree();
  35. multiColumnHeader = new PendingChangesMultiColumnHeader(
  36. headerState, mPendingChangesTree);
  37. multiColumnHeader.canSort = true;
  38. multiColumnHeader.sortingChanged += SortingChanged;
  39. customFoldoutYOffset = UnityConstants.TREEVIEW_FOLDOUT_Y_OFFSET;
  40. rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
  41. showAlternatingRowBackgrounds = false;
  42. mCooldownFilterAction = new CooldownWindowDelayer(
  43. DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
  44. }
  45. protected override void SelectionChanged(IList<int> selectedIds)
  46. {
  47. if (mIsSelectionChangedEventDisabled)
  48. return;
  49. List<UnityEngine.Object> assets = new List<UnityEngine.Object>();
  50. foreach (ChangeInfo changeInfo in GetSelectedChanges(false))
  51. {
  52. UnityEngine.Object asset = LoadAsset.FromChangeInfo(changeInfo);
  53. if (asset == null)
  54. continue;
  55. assets.Add(asset);
  56. }
  57. UnityEditor.Selection.objects = assets.ToArray();
  58. }
  59. public override IList<TreeViewItem> GetRows()
  60. {
  61. return mRows;
  62. }
  63. public override void OnGUI(Rect rect)
  64. {
  65. base.OnGUI(rect);
  66. Event e = Event.current;
  67. if (e.type != EventType.KeyDown)
  68. return;
  69. bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
  70. if (isProcessed)
  71. e.Use();
  72. }
  73. protected override bool CanChangeExpandedState(TreeViewItem item)
  74. {
  75. return item is ChangeCategoryTreeViewItem;
  76. }
  77. protected override TreeViewItem BuildRoot()
  78. {
  79. return new TreeViewItem(0, -1, string.Empty);
  80. }
  81. protected override IList<TreeViewItem> BuildRows(TreeViewItem rootItem)
  82. {
  83. try
  84. {
  85. RegenerateRows(
  86. mPendingChangesTree, mTreeViewItemIds, this,
  87. rootItem, mRows, mExpandCategories);
  88. }
  89. finally
  90. {
  91. mExpandCategories = false;
  92. }
  93. return mRows;
  94. }
  95. protected override void CommandEventHandling()
  96. {
  97. // NOTE - empty override to prevent crash when pressing ctrl-a in the treeview
  98. }
  99. protected override void SearchChanged(string newSearch)
  100. {
  101. mCooldownFilterAction.Ping();
  102. }
  103. protected override void ContextClickedItem(int id)
  104. {
  105. mMenu.Popup();
  106. Repaint();
  107. }
  108. protected override void RowGUI(RowGUIArgs args)
  109. {
  110. DrawTreeViewItem.InitializeStyles();
  111. if (args.item is ChangeCategoryTreeViewItem)
  112. {
  113. CategoryTreeViewItemGUI(
  114. args.rowRect, rowHeight,
  115. (ChangeCategoryTreeViewItem)args.item,
  116. args.selected, args.focused);
  117. return;
  118. }
  119. if (args.item is ChangeTreeViewItem)
  120. {
  121. ChangeTreeViewItemGUI(
  122. mWkInfo.ClientPath,
  123. mIsGluonMode,
  124. mAssetStatusCache,
  125. this,
  126. mPendingChangesTree,
  127. (ChangeTreeViewItem)args.item,
  128. args);
  129. return;
  130. }
  131. base.RowGUI(args);
  132. }
  133. internal void BuildModel(
  134. PlasticGui.WorkspaceWindow.PendingChanges.PendingChanges pendingChanges,
  135. CheckedStateManager checkedStateManager)
  136. {
  137. mTreeViewItemIds.Clear();
  138. mPendingChangesTree.BuildChangeCategories(
  139. mWkInfo.ClientPath, pendingChanges, checkedStateManager);
  140. }
  141. internal void Refilter()
  142. {
  143. Filter filter = new Filter(searchString);
  144. mPendingChangesTree.Filter(filter, mColumnNames);
  145. mExpandCategories = true;
  146. }
  147. internal void Sort()
  148. {
  149. int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
  150. bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
  151. mPendingChangesTree.Sort(
  152. mColumnNames[sortedColumnIdx],
  153. sortAscending);
  154. }
  155. internal SelectedChangesGroupInfo GetSelectedChangesGroupInfo()
  156. {
  157. SelectedChangesGroupInfo result = new SelectedChangesGroupInfo();
  158. IList<int> selectedIds = GetSelection();
  159. if (selectedIds.Count == 0)
  160. return result;
  161. foreach (KeyValuePair<PendingChangeInfo, int> item
  162. in mTreeViewItemIds.GetInfoItems())
  163. {
  164. if (!selectedIds.Contains(item.Value))
  165. continue;
  166. ChangeInfo changeInfo = item.Key.ChangeInfo;
  167. result.SelectedCount++;
  168. result.IsAnyDirectorySelected |= changeInfo.IsDirectory;
  169. result.IsAnyPrivateSelected |= !ChangeInfoType.IsControlled(changeInfo);
  170. result.IsAnyControlledSelected |= ChangeInfoType.IsControlled(changeInfo);
  171. result.IsAnyLocalChangeSelected |= ChangeInfoType.IsLocalChange(changeInfo);
  172. result.FilterInfo.IsAnyIgnoredSelected |= ChangeInfoType.IsIgnored(changeInfo);
  173. result.FilterInfo.IsAnyHiddenChangedSelected |= ChangeInfoType.IsHiddenChanged(changeInfo);
  174. string wkRelativePath = InternalNames.RootDir +
  175. WorkspacePath.GetWorkspaceRelativePath(
  176. mWkInfo.ClientPath, changeInfo.GetFullPath());
  177. if (result.SelectedCount == 1)
  178. {
  179. result.FilterInfo.CommonName = Path.GetFileName(changeInfo.GetFullPath());
  180. result.FilterInfo.CommonExtension = changeInfo.GetExtension();
  181. result.FilterInfo.CommonFullPath = wkRelativePath;
  182. continue;
  183. }
  184. if (result.FilterInfo.CommonName != Path.GetFileName(changeInfo.GetFullPath()))
  185. result.FilterInfo.CommonName = null;
  186. if (result.FilterInfo.CommonExtension != changeInfo.GetExtension())
  187. result.FilterInfo.CommonExtension = null;
  188. if (result.FilterInfo.CommonFullPath != wkRelativePath)
  189. result.FilterInfo.CommonFullPath = null;
  190. }
  191. return result;
  192. }
  193. internal bool GetSelectedPathsToDelete(
  194. out List<string> privateDirectories,
  195. out List<string> privateFiles)
  196. {
  197. privateDirectories = new List<string>();
  198. privateFiles = new List<string>();
  199. List<ChangeInfo> dirChanges = new List<ChangeInfo>();
  200. List<ChangeInfo> fileChanges = new List<ChangeInfo>();
  201. IList<int> selectedIds = GetSelection();
  202. if (selectedIds.Count == 0)
  203. return false;
  204. foreach (KeyValuePair<PendingChangeInfo, int> item
  205. in mTreeViewItemIds.GetInfoItems())
  206. {
  207. if (!selectedIds.Contains(item.Value))
  208. continue;
  209. ChangeInfo changeInfo = item.Key.ChangeInfo;
  210. if (ChangeInfoType.IsControlled(changeInfo))
  211. continue;
  212. if (changeInfo.IsDirectory)
  213. {
  214. dirChanges.Add(changeInfo);
  215. continue;
  216. }
  217. fileChanges.Add(changeInfo);
  218. }
  219. mPendingChangesTree.FillWithMeta(fileChanges);
  220. mPendingChangesTree.FillWithMeta(dirChanges);
  221. privateDirectories = dirChanges.Select(
  222. d => d.GetFullPath()).ToList();
  223. privateFiles = fileChanges.Select(
  224. f => f.GetFullPath()).ToList();
  225. return true;
  226. }
  227. internal void GetCheckedChanges(
  228. bool bExcludePrivates,
  229. out List<ChangeInfo> changes,
  230. out List<ChangeInfo> dependenciesCandidates)
  231. {
  232. mPendingChangesTree.GetCheckedChanges(
  233. bExcludePrivates, out changes, out dependenciesCandidates);
  234. }
  235. internal List<ChangeInfo> GetAllChanges()
  236. {
  237. List<ChangeInfo> result = new List<ChangeInfo>();
  238. foreach (PendingChangeCategory category in mPendingChangesTree.GetNodes())
  239. {
  240. foreach (PendingChangeInfo change in category.GetCurrentChanges())
  241. result.Add(change.ChangeInfo);
  242. }
  243. mPendingChangesTree.FillWithMeta(result);
  244. return result;
  245. }
  246. internal ChangeInfo GetMetaChange(ChangeInfo change)
  247. {
  248. if (change == null)
  249. return null;
  250. return mPendingChangesTree.GetMetaChange(change);
  251. }
  252. internal List<ChangeInfo> GetDependenciesCandidates(
  253. List<ChangeInfo> selectedChanges, bool bExcludePrivates)
  254. {
  255. return mPendingChangesTree.GetDependenciesCandidates(
  256. selectedChanges, bExcludePrivates);
  257. }
  258. internal List<ChangeInfo> GetSelectedChanges(bool includeMetaFiles)
  259. {
  260. List<ChangeInfo> result = new List<ChangeInfo>();
  261. IList<int> selectedIds = GetSelection();
  262. if (selectedIds.Count == 0)
  263. return result;
  264. foreach (KeyValuePair<PendingChangeInfo, int> item
  265. in mTreeViewItemIds.GetInfoItems())
  266. {
  267. if (!selectedIds.Contains(item.Value))
  268. continue;
  269. result.Add(item.Key.ChangeInfo);
  270. }
  271. if (includeMetaFiles)
  272. mPendingChangesTree.FillWithMeta(result);
  273. return result;
  274. }
  275. internal bool SelectionHasMeta()
  276. {
  277. ChangeInfo selectedChangeInfo = GetSelectedRow();
  278. if (selectedChangeInfo == null)
  279. return false;
  280. return mPendingChangesTree.HasMeta(selectedChangeInfo);
  281. }
  282. internal ChangeInfo GetSelectedRow()
  283. {
  284. IList<int> selectedIds = GetSelection();
  285. if (selectedIds.Count == 0)
  286. return null;
  287. int selectedId = selectedIds[0];
  288. foreach (KeyValuePair<PendingChangeInfo, int> item
  289. in mTreeViewItemIds.GetInfoItems())
  290. {
  291. if (selectedId == item.Value)
  292. return item.Key.ChangeInfo;
  293. }
  294. return null;
  295. }
  296. internal ChangeInfo GetNearestAddedChange()
  297. {
  298. IList<int> selectedIds = GetSelection();
  299. if (selectedIds.Count == 0)
  300. return null;
  301. int id = selectedIds[0];
  302. IList<TreeViewItem> treeViewItems =
  303. FindRows(new List<int>() { id });
  304. if (treeViewItems.Count == 0)
  305. return null;
  306. PendingChangeInfo changeInfo =
  307. ((ChangeTreeViewItem)treeViewItems[0]).ChangeInfo;
  308. PendingChangeCategory category =
  309. (PendingChangeCategory)changeInfo.GetParent();
  310. int itemIndex = category.GetChildPosition(changeInfo);
  311. ChangeInfo result = GetNextExistingAddedItem(category, itemIndex);
  312. if (result != null)
  313. return result;
  314. return GetPreviousExistingAddedItem(category, itemIndex);
  315. }
  316. internal void SelectFirstPendingChangeOnTree()
  317. {
  318. int treeIdFirstItem = GetTreeIdFirstItem();
  319. if (treeIdFirstItem == -1)
  320. return;
  321. mIsSelectionChangedEventDisabled = true;
  322. try
  323. {
  324. TableViewOperations.SetSelectionAndScroll(
  325. this, new List<int> { treeIdFirstItem });
  326. }
  327. finally
  328. {
  329. mIsSelectionChangedEventDisabled = false;
  330. }
  331. }
  332. internal void SelectPreviouslySelectedPendingChanges(
  333. List<ChangeInfo> changesToSelect)
  334. {
  335. List<int> idsToSelect = new List<int>();
  336. foreach (ChangeInfo change in changesToSelect)
  337. {
  338. int changeId = GetTreeIdForItem(change);
  339. if (changeId == -1)
  340. continue;
  341. idsToSelect.Add(changeId);
  342. }
  343. mIsSelectionChangedEventDisabled = true;
  344. try
  345. {
  346. TableViewOperations.SetSelectionAndScroll(
  347. this, idsToSelect);
  348. }
  349. finally
  350. {
  351. mIsSelectionChangedEventDisabled = false;
  352. }
  353. }
  354. internal int GetSelectedItemCount()
  355. {
  356. List<PendingChangeCategory> categories = mPendingChangesTree.GetNodes();
  357. if (categories == null)
  358. return 0;
  359. int checkedCount = 0;
  360. foreach (PendingChangeCategory category in categories)
  361. {
  362. checkedCount += category.GetCheckedChangesCount();
  363. }
  364. return checkedCount;
  365. }
  366. internal int GetTotalItemCount()
  367. {
  368. List<PendingChangeCategory> categories = mPendingChangesTree.GetNodes();
  369. if (categories == null)
  370. return 0;
  371. int totalCount = 0;
  372. foreach (PendingChangeCategory category in categories)
  373. {
  374. totalCount += category.GetChildrenCount();
  375. }
  376. return totalCount;
  377. }
  378. ChangeInfo GetNextExistingAddedItem(
  379. PendingChangeCategory addedCategory, int targetAddedItemIndex)
  380. {
  381. int addedItemsCount = addedCategory.GetChildrenCount();
  382. for (int i = targetAddedItemIndex + 1; i < addedItemsCount; i++)
  383. {
  384. ChangeInfo currentChangeInfo = GetExistingAddedItem(addedCategory, i);
  385. if (currentChangeInfo != null)
  386. return currentChangeInfo;
  387. }
  388. return null;
  389. }
  390. ChangeInfo GetPreviousExistingAddedItem(
  391. PendingChangeCategory addedCategory, int targetAddedItemIndex)
  392. {
  393. for (int i = targetAddedItemIndex - 1; i >= 0; i--)
  394. {
  395. ChangeInfo currentChangeInfo = GetExistingAddedItem(addedCategory, i);
  396. if (currentChangeInfo != null)
  397. return currentChangeInfo;
  398. }
  399. return null;
  400. }
  401. ChangeInfo GetExistingAddedItem(
  402. PendingChangeCategory addedCategory, int addedItemIndex)
  403. {
  404. ChangeInfo currentChangeInfo = ((PendingChangeInfo)addedCategory.
  405. GetChild(addedItemIndex)).ChangeInfo;
  406. if (Directory.Exists(currentChangeInfo.Path) ||
  407. File.Exists(currentChangeInfo.Path))
  408. return currentChangeInfo;
  409. return null;
  410. }
  411. int GetTreeIdFirstItem()
  412. {
  413. List<PendingChangeCategory> categories = mPendingChangesTree.GetNodes();
  414. if (categories == null)
  415. return -1;
  416. if (categories.Count == 0)
  417. return -1;
  418. List<PendingChangeInfo> changes = categories[0].GetCurrentChanges();
  419. if (changes.Count == 0)
  420. return -1;
  421. int changeId;
  422. if (mTreeViewItemIds.TryGetInfoItemId(changes[0], out changeId))
  423. return changeId;
  424. return -1;
  425. }
  426. int GetTreeIdForItem(ChangeInfo change)
  427. {
  428. foreach (KeyValuePair<PendingChangeInfo, int> item in mTreeViewItemIds.GetInfoItems())
  429. {
  430. ChangeInfo changeInfo = item.Key.ChangeInfo;
  431. if (changeInfo.ChangeTypes != change.ChangeTypes)
  432. continue;
  433. if (changeInfo.GetFullPath() != change.GetFullPath())
  434. continue;
  435. return item.Value;
  436. }
  437. return -1;
  438. }
  439. void DelayedSearchChanged()
  440. {
  441. Refilter();
  442. Sort();
  443. Reload();
  444. TableViewOperations.ScrollToSelection(this);
  445. }
  446. void SortingChanged(MultiColumnHeader multiColumnHeader)
  447. {
  448. Sort();
  449. Reload();
  450. }
  451. static void CategoryTreeViewItemGUI(
  452. Rect rowRect,
  453. float rowHeight,
  454. ChangeCategoryTreeViewItem item,
  455. bool isSelected,
  456. bool isFocused)
  457. {
  458. Texture icon = GetCategoryIcon(item.Category);
  459. string label = item.Category.GetHeaderText();
  460. bool wasChecked = item.Category.IsChecked();
  461. bool hadCheckedChildren = item.Category.GetCheckedChangesCount() > 0;
  462. bool isChecked = DrawTreeViewItem.ForCheckableCategoryItem(
  463. rowRect, rowHeight, item.depth, icon, label,
  464. isSelected, isFocused, wasChecked, hadCheckedChildren);
  465. if (!wasChecked && isChecked)
  466. {
  467. item.Category.UpdateCheckedState(true);
  468. return;
  469. }
  470. if (wasChecked && !isChecked)
  471. {
  472. item.Category.UpdateCheckedState(false);
  473. return;
  474. }
  475. }
  476. static void ChangeTreeViewItemGUI(
  477. string wkPath,
  478. bool isGluonMode,
  479. IAssetStatusCache assetStatusCache,
  480. PendingChangesTreeView treeView,
  481. UnityPendingChangesTree pendingChangesTree,
  482. ChangeTreeViewItem item,
  483. RowGUIArgs args)
  484. {
  485. for (int visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++)
  486. {
  487. Rect cellRect = args.GetCellRect(visibleColumnIdx);
  488. PendingChangesTreeColumn column =
  489. (PendingChangesTreeColumn)args.GetColumn(visibleColumnIdx);
  490. ChangeTreeViewItemCellGUI(
  491. isGluonMode,
  492. assetStatusCache,
  493. cellRect,
  494. treeView.rowHeight,
  495. treeView,
  496. pendingChangesTree,
  497. item,
  498. column,
  499. args.selected,
  500. args.focused);
  501. }
  502. }
  503. static void ChangeTreeViewItemCellGUI(
  504. bool isGluonMode,
  505. IAssetStatusCache assetStatusCache,
  506. Rect rect,
  507. float rowHeight,
  508. PendingChangesTreeView treeView,
  509. UnityPendingChangesTree pendingChangesTree,
  510. ChangeTreeViewItem item,
  511. PendingChangesTreeColumn column,
  512. bool isSelected,
  513. bool isFocused)
  514. {
  515. PendingChangeInfo changeInfo = item.ChangeInfo;
  516. string label = changeInfo.GetColumnText(
  517. PendingChangesTreeHeaderState.GetColumnName(column));
  518. if (column == PendingChangesTreeColumn.Item)
  519. {
  520. if (pendingChangesTree.HasMeta(changeInfo.ChangeInfo))
  521. label = string.Concat(label, UnityConstants.TREEVIEW_META_LABEL);
  522. Texture icon = GetIcon(changeInfo);
  523. bool isConflicted = IsConflicted(
  524. isGluonMode, assetStatusCache,
  525. changeInfo.ChangeInfo.GetFullPath());
  526. GetChangesOverlayIcon.Data overlayIconData =
  527. GetChangesOverlayIcon.ForPendingChange(
  528. changeInfo.ChangeInfo, isConflicted);
  529. bool wasChecked = changeInfo.IsChecked();
  530. bool isChecked = DrawTreeViewItem.ForCheckableItemCell(
  531. rect, rowHeight, item.depth,
  532. icon, overlayIconData, label,
  533. isSelected, isFocused, false,
  534. wasChecked);
  535. changeInfo.UpdateCheckedState(isChecked);
  536. if (wasChecked != isChecked)
  537. UpdateCheckStateForSelection(treeView, item);
  538. return;
  539. }
  540. if (column == PendingChangesTreeColumn.Size)
  541. {
  542. DrawTreeViewItem.ForSecondaryLabelRightAligned(
  543. rect, label, isSelected, isFocused, false);
  544. return;
  545. }
  546. DrawTreeViewItem.ForSecondaryLabel(
  547. rect, label, isSelected, isFocused, false);
  548. }
  549. static void UpdateCheckStateForSelection(
  550. PendingChangesTreeView treeView,
  551. ChangeTreeViewItem senderTreeViewItem)
  552. {
  553. IList<int> selectedIds = treeView.GetSelection();
  554. if (selectedIds.Count <= 1)
  555. return;
  556. if (!selectedIds.Contains(senderTreeViewItem.id))
  557. return;
  558. bool isChecked = senderTreeViewItem.ChangeInfo.IsChecked();
  559. foreach (TreeViewItem treeViewItem in treeView.FindRows(selectedIds))
  560. {
  561. if (treeViewItem is ChangeCategoryTreeViewItem)
  562. {
  563. ((ChangeCategoryTreeViewItem)treeViewItem).Category
  564. .UpdateCheckedState(isChecked);
  565. continue;
  566. }
  567. ((ChangeTreeViewItem)treeViewItem).ChangeInfo
  568. .UpdateCheckedState(isChecked);
  569. }
  570. }
  571. static void RegenerateRows(
  572. UnityPendingChangesTree pendingChangesTree,
  573. TreeViewItemIds<PendingChangeCategory, PendingChangeInfo> treeViewItemIds,
  574. PendingChangesTreeView treeView,
  575. TreeViewItem rootItem,
  576. List<TreeViewItem> rows,
  577. bool expandCategories)
  578. {
  579. ClearRows(rootItem, rows);
  580. List<PendingChangeCategory> categories = pendingChangesTree.GetNodes();
  581. if (categories == null)
  582. return;
  583. foreach (PendingChangeCategory category in categories)
  584. {
  585. int categoryId;
  586. if (!treeViewItemIds.TryGetCategoryItemId(category, out categoryId))
  587. categoryId = treeViewItemIds.AddCategoryItem(category);
  588. ChangeCategoryTreeViewItem categoryTreeViewItem =
  589. new ChangeCategoryTreeViewItem(categoryId, category);
  590. rootItem.AddChild(categoryTreeViewItem);
  591. rows.Add(categoryTreeViewItem);
  592. if (!expandCategories &&
  593. !treeView.IsExpanded(categoryTreeViewItem.id))
  594. continue;
  595. foreach (PendingChangeInfo change in category.GetCurrentChanges())
  596. {
  597. int changeId;
  598. if (!treeViewItemIds.TryGetInfoItemId(change, out changeId))
  599. changeId = treeViewItemIds.AddInfoItem(change);
  600. TreeViewItem changeTreeViewItem =
  601. new ChangeTreeViewItem(changeId, change);
  602. categoryTreeViewItem.AddChild(changeTreeViewItem);
  603. rows.Add(changeTreeViewItem);
  604. }
  605. }
  606. if (!expandCategories)
  607. return;
  608. treeView.state.expandedIDs = treeViewItemIds.GetCategoryIds();
  609. }
  610. static void ClearRows(
  611. TreeViewItem rootItem,
  612. List<TreeViewItem> rows)
  613. {
  614. if (rootItem.hasChildren)
  615. rootItem.children.Clear();
  616. rows.Clear();
  617. }
  618. static Texture GetCategoryIcon(PendingChangeCategory category)
  619. {
  620. switch (category.Type)
  621. {
  622. case PendingChangeCategoryType.Added:
  623. return Images.GetImage(Images.Name.IconAdded);
  624. case PendingChangeCategoryType.Changed:
  625. return Images.GetImage(Images.Name.IconChanged);
  626. case PendingChangeCategoryType.Deleted:
  627. return Images.GetImage(Images.Name.IconDeleted);
  628. case PendingChangeCategoryType.Moved:
  629. return Images.GetImage(Images.Name.IconMoved);
  630. default:
  631. return null;
  632. }
  633. }
  634. static Texture GetIcon(PendingChangeInfo change)
  635. {
  636. if (change.ChangeInfo.IsDirectory)
  637. return Images.GetDirectoryIcon();
  638. string fullPath = change.ChangeInfo.GetFullPath();
  639. return Images.GetFileIcon(fullPath);
  640. }
  641. static bool IsConflicted(
  642. bool isGluonMode,
  643. IAssetStatusCache assetStatusCache,
  644. string fullPath)
  645. {
  646. if (!isGluonMode)
  647. return false;
  648. return ClassifyAssetStatus.IsConflicted(
  649. assetStatusCache.GetStatusForPath(fullPath));
  650. }
  651. bool mExpandCategories;
  652. bool mIsSelectionChangedEventDisabled;
  653. TreeViewItemIds<PendingChangeCategory, PendingChangeInfo> mTreeViewItemIds =
  654. new TreeViewItemIds<PendingChangeCategory, PendingChangeInfo>();
  655. List<TreeViewItem> mRows = new List<TreeViewItem>();
  656. UnityPendingChangesTree mPendingChangesTree;
  657. CooldownWindowDelayer mCooldownFilterAction;
  658. readonly PendingChangesViewMenu mMenu;
  659. readonly IAssetStatusCache mAssetStatusCache;
  660. readonly List<string> mColumnNames;
  661. readonly bool mIsGluonMode;
  662. readonly WorkspaceInfo mWkInfo;
  663. }
  664. }