暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PendingChangesTreeView.cs 31KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Linq;
  4. using UnityEditor;
  5. using UnityEditor.IMGUI.Controls;
  6. using UnityEngine;
  7. using Codice.Client.BaseCommands;
  8. using Codice.CM.Common;
  9. using PlasticGui;
  10. using PlasticGui.WorkspaceWindow.PendingChanges;
  11. using PlasticGui.WorkspaceWindow.PendingChanges.Changelists;
  12. using Unity.PlasticSCM.Editor.AssetUtils;
  13. using Unity.PlasticSCM.Editor.UI;
  14. using Unity.PlasticSCM.Editor.UI.Tree;
  15. using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
  16. using Unity.PlasticSCM.Editor.AssetsOverlays;
  17. namespace Unity.PlasticSCM.Editor.Views.PendingChanges
  18. {
  19. internal class PendingChangesTreeView : TreeView
  20. {
  21. internal PendingChangesTreeView(
  22. WorkspaceInfo wkInfo,
  23. bool isGluonMode,
  24. PendingChangesTreeHeaderState headerState,
  25. List<string> columnNames,
  26. PendingChangesViewMenu menu,
  27. IAssetStatusCache assetStatusCache)
  28. : base(new TreeViewState())
  29. {
  30. mWkInfo = wkInfo;
  31. mIsGluonMode = isGluonMode;
  32. mColumnNames = columnNames;
  33. mHeaderState = headerState;
  34. mMenu = menu;
  35. mAssetStatusCache = assetStatusCache;
  36. mPendingChangesTree = new UnityPendingChangesTree();
  37. multiColumnHeader = new PendingChangesMultiColumnHeader(
  38. this,
  39. headerState,
  40. mPendingChangesTree);
  41. multiColumnHeader.canSort = true;
  42. multiColumnHeader.sortingChanged += SortingChanged;
  43. customFoldoutYOffset = UnityConstants.TREEVIEW_FOLDOUT_Y_OFFSET;
  44. rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
  45. showAlternatingRowBackgrounds = false;
  46. mCooldownFilterAction = new CooldownWindowDelayer(
  47. DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
  48. }
  49. protected override void SingleClickedItem(int id)
  50. {
  51. SelectionChanged(new [] { id });
  52. }
  53. protected override void SelectionChanged(IList<int> selectedIds)
  54. {
  55. mHeaderState.UpdateItemColumnHeader(this);
  56. if (mIsSelectionChangedEventDisabled)
  57. return;
  58. List<UnityEngine.Object> assets = new List<UnityEngine.Object>();
  59. foreach (ChangeInfo changeInfo in GetSelectedChanges(false))
  60. {
  61. UnityEngine.Object asset = LoadAsset.FromChangeInfo(changeInfo);
  62. if (asset == null)
  63. continue;
  64. assets.Add(asset);
  65. }
  66. UnityEditor.Selection.objects = assets.ToArray();
  67. if (assets.Count == 1)
  68. EditorGUIUtility.PingObject(assets[0]);
  69. }
  70. protected void SelectionChanged()
  71. {
  72. SelectionChanged(GetSelection());
  73. }
  74. public override IList<TreeViewItem> GetRows()
  75. {
  76. return mRows;
  77. }
  78. public override void OnGUI(Rect rect)
  79. {
  80. MultiColumnHeader.DefaultStyles.background =
  81. UnityStyles.Tree.Columns;
  82. try
  83. {
  84. base.OnGUI(rect);
  85. if (!base.HasFocus())
  86. return;
  87. Event e = Event.current;
  88. if (e.type != EventType.KeyDown)
  89. return;
  90. bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
  91. if (isProcessed)
  92. e.Use();
  93. }
  94. finally
  95. {
  96. MultiColumnHeader.DefaultStyles.background =
  97. UnityStyles.PendingChangesTab.DefaultMultiColumHeader;
  98. }
  99. }
  100. protected override bool CanChangeExpandedState(TreeViewItem item)
  101. {
  102. return item is ChangeCategoryTreeViewItem || item is ChangelistTreeViewItem;
  103. }
  104. protected override TreeViewItem BuildRoot()
  105. {
  106. return new TreeViewItem(0, -1, string.Empty);
  107. }
  108. protected override IList<TreeViewItem> BuildRows(TreeViewItem rootItem)
  109. {
  110. try
  111. {
  112. RegenerateRows(
  113. mPendingChangesTree, mTreeViewItemIds, this,
  114. rootItem, mRows, mExpandCategories);
  115. }
  116. finally
  117. {
  118. mExpandCategories = false;
  119. }
  120. return mRows;
  121. }
  122. protected override void CommandEventHandling()
  123. {
  124. // NOTE - empty override to prevent crash when pressing ctrl-a in the treeview
  125. }
  126. protected override void SearchChanged(string newSearch)
  127. {
  128. mCooldownFilterAction.Ping();
  129. }
  130. protected override void ContextClickedItem(int id)
  131. {
  132. mMenu.Popup();
  133. Repaint();
  134. }
  135. protected override void BeforeRowsGUI()
  136. {
  137. int firstRowVisible;
  138. int lastRowVisible;
  139. GetFirstAndLastVisibleRows(out firstRowVisible, out lastRowVisible);
  140. GUI.DrawTexture(new Rect(0,
  141. firstRowVisible * rowHeight,
  142. GetRowRect(0).width,
  143. (lastRowVisible * rowHeight) + 1000),
  144. Images.GetTreeviewBackgroundTexture());
  145. DrawTreeViewItem.InitializeStyles();
  146. base.BeforeRowsGUI();
  147. }
  148. protected override void RowGUI(RowGUIArgs args)
  149. {
  150. if (args.item is ChangelistTreeViewItem)
  151. {
  152. ChangelistTreeViewItemGUI(
  153. this,
  154. args.rowRect, rowHeight,
  155. (ChangelistTreeViewItem)args.item,
  156. args.selected, args.focused);
  157. return;
  158. }
  159. if (args.item is ChangeCategoryTreeViewItem)
  160. {
  161. CategoryTreeViewItemGUI(
  162. this,
  163. args.rowRect, rowHeight,
  164. (ChangeCategoryTreeViewItem)args.item,
  165. args.selected, args.focused);
  166. return;
  167. }
  168. if (args.item is ChangeTreeViewItem)
  169. {
  170. ChangeTreeViewItemGUI(
  171. mWkInfo.ClientPath,
  172. mIsGluonMode,
  173. mAssetStatusCache,
  174. this,
  175. mPendingChangesTree,
  176. (ChangeTreeViewItem)args.item,
  177. args);
  178. return;
  179. }
  180. base.RowGUI(args);
  181. }
  182. internal void BuildModel(List<ChangeInfo> changes, PendingChangesViewCheckedStateManager checkedStateManager)
  183. {
  184. mTreeViewItemIds.Clear();
  185. mPendingChangesTree.BuildChangeCategories(
  186. mWkInfo,
  187. changes,
  188. checkedStateManager);
  189. }
  190. internal ChangeInfo GetChangedForMoved(ChangeInfo moved)
  191. {
  192. return mPendingChangesTree.GetChangedForMoved(moved);
  193. }
  194. internal void Refilter()
  195. {
  196. Filter filter = new Filter(searchString);
  197. mPendingChangesTree.Filter(filter, mColumnNames);
  198. mExpandCategories = true;
  199. }
  200. internal void Sort()
  201. {
  202. int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
  203. bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
  204. mPendingChangesTree.Sort(
  205. mColumnNames[sortedColumnIdx],
  206. sortAscending);
  207. }
  208. internal bool GetSelectedPathsToDelete(
  209. out List<string> privateDirectories,
  210. out List<string> privateFiles)
  211. {
  212. privateDirectories = new List<string>();
  213. privateFiles = new List<string>();
  214. List<ChangeInfo> dirChanges = new List<ChangeInfo>();
  215. List<ChangeInfo> fileChanges = new List<ChangeInfo>();
  216. IList<int> selectedIds = GetSelection();
  217. if (selectedIds.Count == 0)
  218. return false;
  219. foreach (KeyValuePair<PendingChangeInfo, int> item
  220. in mTreeViewItemIds.GetInfoItems())
  221. {
  222. if (!selectedIds.Contains(item.Value))
  223. continue;
  224. ChangeInfo changeInfo = item.Key.ChangeInfo;
  225. if (ChangeInfoType.IsControlled(changeInfo))
  226. continue;
  227. if (changeInfo.IsDirectory)
  228. {
  229. dirChanges.Add(changeInfo);
  230. }
  231. else
  232. {
  233. fileChanges.Add(changeInfo);
  234. }
  235. ChangeInfo metaChangeInfo = mPendingChangesTree.GetMetaChange(changeInfo);
  236. if (metaChangeInfo != null)
  237. {
  238. fileChanges.Add(metaChangeInfo);
  239. }
  240. }
  241. privateDirectories = dirChanges.Select(
  242. d => d.GetFullPath()).ToList();
  243. privateFiles = fileChanges.Select(
  244. f => f.GetFullPath()).ToList();
  245. return true;
  246. }
  247. internal void GetCheckedChanges(
  248. List<ChangelistNode> selectedChangelists,
  249. bool bExcludePrivates,
  250. out List<ChangeInfo> changes,
  251. out List<ChangeInfo> dependenciesCandidates)
  252. {
  253. mPendingChangesTree.GetCheckedChanges(
  254. selectedChangelists,
  255. bExcludePrivates,
  256. out changes,
  257. out dependenciesCandidates);
  258. }
  259. internal List<ChangeInfo> GetAllChanges()
  260. {
  261. return mPendingChangesTree.GetAllChanges();
  262. }
  263. internal ChangeInfo GetMetaChange(ChangeInfo change)
  264. {
  265. if (change == null)
  266. return null;
  267. return mPendingChangesTree.GetMetaChange(change);
  268. }
  269. internal List<ChangeInfo> GetDependenciesCandidates(
  270. List<ChangeInfo> selectedChanges, bool bExcludePrivates)
  271. {
  272. return mPendingChangesTree.GetDependenciesCandidates(
  273. selectedChanges, bExcludePrivates);
  274. }
  275. internal List<IPlasticTreeNode> GetSelectedNodes()
  276. {
  277. List<IPlasticTreeNode> result = new List<IPlasticTreeNode>();
  278. IList<int> selectedIds = GetSelection();
  279. if (selectedIds.Count == 0)
  280. return result;
  281. foreach (KeyValuePair<IPlasticTreeNode, int> item
  282. in mTreeViewItemIds.GetCategoryItems())
  283. {
  284. if (!selectedIds.Contains(item.Value))
  285. continue;
  286. result.Add(item.Key);
  287. }
  288. foreach (KeyValuePair<PendingChangeInfo, int> item
  289. in mTreeViewItemIds.GetInfoItems())
  290. {
  291. if (!selectedIds.Contains(item.Value))
  292. continue;
  293. result.Add(item.Key);
  294. }
  295. return result;
  296. }
  297. internal List<ChangeInfo> GetSelectedChanges(bool includeMetaFiles)
  298. {
  299. List<ChangeInfo> result = new List<ChangeInfo>();
  300. IList<int> selectedIds = GetSelection();
  301. if (selectedIds.Count == 0)
  302. return result;
  303. foreach (KeyValuePair<PendingChangeInfo, int> item
  304. in mTreeViewItemIds.GetInfoItems())
  305. {
  306. if (!selectedIds.Contains(item.Value))
  307. continue;
  308. result.Add(item.Key.ChangeInfo);
  309. }
  310. if (includeMetaFiles)
  311. mPendingChangesTree.FillWithMeta(result);
  312. return result;
  313. }
  314. internal List<PendingChangeInfo> GetSelectedPendingChangeInfos()
  315. {
  316. List<PendingChangeInfo> result = new List<PendingChangeInfo>();
  317. IList<int> selectedIds = GetSelection();
  318. if (selectedIds.Count == 0)
  319. return result;
  320. foreach (KeyValuePair<PendingChangeInfo, int> item
  321. in mTreeViewItemIds.GetInfoItems())
  322. {
  323. if (!selectedIds.Contains(item.Value))
  324. continue;
  325. result.Add(item.Key);
  326. }
  327. return result;
  328. }
  329. internal List<ChangelistNode> GetSelectedChangelistNodes()
  330. {
  331. List<ChangelistNode> result = new List<ChangelistNode>();
  332. IList<int> selectedIds = GetSelection();
  333. if (selectedIds.Count == 0)
  334. return result;
  335. foreach (KeyValuePair<IPlasticTreeNode, int> item
  336. in mTreeViewItemIds.GetCategoryItems())
  337. {
  338. if (!selectedIds.Contains(item.Value))
  339. continue;
  340. if (item.Key is ChangelistNode)
  341. result.Add((ChangelistNode)item.Key);
  342. }
  343. return result;
  344. }
  345. internal bool SelectionHasMeta()
  346. {
  347. ChangeInfo selectedChangeInfo = GetSelectedRow();
  348. if (selectedChangeInfo == null)
  349. return false;
  350. return mPendingChangesTree.HasMeta(selectedChangeInfo);
  351. }
  352. internal ChangeInfo GetSelectedRow()
  353. {
  354. IList<int> selectedIds = GetSelection();
  355. if (selectedIds.Count == 0)
  356. return null;
  357. int selectedId = selectedIds[0];
  358. foreach (KeyValuePair<PendingChangeInfo, int> item
  359. in mTreeViewItemIds.GetInfoItems())
  360. {
  361. if (selectedId == item.Value)
  362. return item.Key.ChangeInfo;
  363. }
  364. return null;
  365. }
  366. internal ChangeInfo GetNearestAddedChange()
  367. {
  368. IList<int> selectedIds = GetSelection();
  369. if (selectedIds.Count == 0)
  370. return null;
  371. int id = selectedIds[0];
  372. IList<TreeViewItem> treeViewItems =
  373. FindRows(new List<int>() { id });
  374. if (treeViewItems.Count == 0)
  375. return null;
  376. PendingChangeInfo changeInfo =
  377. ((ChangeTreeViewItem)treeViewItems[0]).ChangeInfo;
  378. PendingChangeCategory category =
  379. (PendingChangeCategory)((IPlasticTreeNode)changeInfo).GetParent();
  380. int itemIndex = category.GetChildPosition(changeInfo);
  381. ChangeInfo result = GetNextExistingAddedItem(category, itemIndex);
  382. if (result != null)
  383. return result;
  384. return GetPreviousExistingAddedItem(category, itemIndex);
  385. }
  386. internal void SelectFirstPendingChangeOnTree()
  387. {
  388. int treeIdFirstItem = GetTreeIdFirstItem();
  389. if (treeIdFirstItem == -1)
  390. return;
  391. mIsSelectionChangedEventDisabled = true;
  392. try
  393. {
  394. TableViewOperations.SetSelectionAndScroll(
  395. this, new List<int> { treeIdFirstItem });
  396. }
  397. finally
  398. {
  399. mIsSelectionChangedEventDisabled = false;
  400. }
  401. }
  402. internal void SelectPreviouslySelectedPendingChanges(
  403. List<ChangeInfo> changesToSelect)
  404. {
  405. List<int> idsToSelect = new List<int>();
  406. foreach (ChangeInfo change in changesToSelect)
  407. {
  408. int changeId = GetTreeIdForItem(change);
  409. if (changeId == -1)
  410. continue;
  411. idsToSelect.Add(changeId);
  412. }
  413. mIsSelectionChangedEventDisabled = true;
  414. try
  415. {
  416. TableViewOperations.SetSelectionAndScroll(
  417. this, idsToSelect);
  418. }
  419. finally
  420. {
  421. mIsSelectionChangedEventDisabled = false;
  422. }
  423. }
  424. internal int GetCheckedItemCount()
  425. {
  426. return CheckableItems.GetCheckedChildNodeCount(mPendingChangesTree.GetNodes());
  427. }
  428. internal int GetTotalItemCount()
  429. {
  430. return CheckableItems.GetTotalChildNodeCount(mPendingChangesTree.GetNodes());
  431. }
  432. ChangeInfo GetNextExistingAddedItem(
  433. PendingChangeCategory addedCategory, int targetAddedItemIndex)
  434. {
  435. int addedItemsCount = addedCategory.GetChildrenCount();
  436. for (int i = targetAddedItemIndex + 1; i < addedItemsCount; i++)
  437. {
  438. ChangeInfo currentChangeInfo = GetExistingAddedItem(addedCategory, i);
  439. if (currentChangeInfo != null)
  440. return currentChangeInfo;
  441. }
  442. return null;
  443. }
  444. ChangeInfo GetPreviousExistingAddedItem(
  445. PendingChangeCategory addedCategory, int targetAddedItemIndex)
  446. {
  447. for (int i = targetAddedItemIndex - 1; i >= 0; i--)
  448. {
  449. ChangeInfo currentChangeInfo = GetExistingAddedItem(addedCategory, i);
  450. if (currentChangeInfo != null)
  451. return currentChangeInfo;
  452. }
  453. return null;
  454. }
  455. ChangeInfo GetExistingAddedItem(
  456. PendingChangeCategory addedCategory, int addedItemIndex)
  457. {
  458. ChangeInfo currentChangeInfo = ((PendingChangeInfo)((IPendingChangesNode)addedCategory)
  459. .GetCurrentChanges()[addedItemIndex]).ChangeInfo;
  460. if (Directory.Exists(currentChangeInfo.Path) ||
  461. File.Exists(currentChangeInfo.Path))
  462. return currentChangeInfo;
  463. return null;
  464. }
  465. int GetTreeIdFirstItem()
  466. {
  467. PendingChangeInfo firstChange = mPendingChangesTree.GetFirstPendingChange();
  468. if (firstChange == null)
  469. return -1;
  470. int changeId;
  471. if (mTreeViewItemIds.TryGetInfoItemId(firstChange, out changeId))
  472. return changeId;
  473. return -1;
  474. }
  475. int GetTreeIdForItem(ChangeInfo change)
  476. {
  477. foreach (KeyValuePair<PendingChangeInfo, int> item in mTreeViewItemIds.GetInfoItems())
  478. {
  479. ChangeInfo changeInfo = item.Key.ChangeInfo;
  480. if (changeInfo.ChangeTypes != change.ChangeTypes)
  481. continue;
  482. if (changeInfo.GetFullPath() != change.GetFullPath())
  483. continue;
  484. return item.Value;
  485. }
  486. return -1;
  487. }
  488. void DelayedSearchChanged()
  489. {
  490. Refilter();
  491. Sort();
  492. Reload();
  493. TableViewOperations.ScrollToSelection(this);
  494. }
  495. void SortingChanged(MultiColumnHeader multiColumnHeader)
  496. {
  497. Sort();
  498. Reload();
  499. }
  500. static void ChangelistTreeViewItemGUI(
  501. PendingChangesTreeView treeView,
  502. Rect rowRect,
  503. float rowHeight,
  504. ChangelistTreeViewItem item,
  505. bool isSelected,
  506. bool isFocused)
  507. {
  508. string label = item.Changelist.ChangelistInfo.Name;
  509. string secondaryLabel = item.Changelist.ChangelistInfo.Description;
  510. bool wasChecked = CheckableItems.GetIsCheckedValue(item.Changelist) ?? false;
  511. bool hadCheckedChildren =
  512. ((ICheckablePlasticTreeCategoryGroup)item.Changelist).GetCheckedCategoriesCount() > 0;
  513. bool hadPartiallyCheckedChildren =
  514. ((ICheckablePlasticTreeCategoryGroup)item.Changelist).GetPartiallyCheckedCategoriesCount() > 0;
  515. bool isChecked = DrawTreeViewItem.ForCheckableCategoryItem(
  516. rowRect,
  517. rowHeight,
  518. item.depth,
  519. label,
  520. secondaryLabel,
  521. isSelected,
  522. isFocused,
  523. wasChecked,
  524. hadCheckedChildren,
  525. hadPartiallyCheckedChildren);
  526. if (wasChecked != isChecked)
  527. {
  528. CheckableItems.SetCheckedValue(item.Changelist, isChecked);
  529. treeView.SelectionChanged();
  530. }
  531. }
  532. static void CategoryTreeViewItemGUI(
  533. PendingChangesTreeView treeView,
  534. Rect rowRect,
  535. float rowHeight,
  536. ChangeCategoryTreeViewItem item,
  537. bool isSelected,
  538. bool isFocused)
  539. {
  540. string label = item.Category.CategoryName;
  541. string secondaryLabel = item.Category.GetCheckedChangesText();
  542. bool wasChecked = CheckableItems.GetIsCheckedValueForCategory(item.Category) ?? false;
  543. bool hadCheckedChildren =
  544. ((ICheckablePlasticTreeCategory)item.Category).GetCheckedChangesCount() > 0;
  545. bool isChecked = DrawTreeViewItem.ForCheckableCategoryItem(
  546. rowRect,
  547. rowHeight,
  548. item.depth,
  549. label,
  550. secondaryLabel,
  551. isSelected,
  552. isFocused,
  553. wasChecked,
  554. hadCheckedChildren,
  555. false);
  556. if (wasChecked != isChecked)
  557. {
  558. CheckableItems.SetCheckedValue(item.Category, isChecked);
  559. treeView.SelectionChanged();
  560. }
  561. }
  562. static void ChangeTreeViewItemGUI(
  563. string wkPath,
  564. bool isGluonMode,
  565. IAssetStatusCache assetStatusCache,
  566. PendingChangesTreeView treeView,
  567. UnityPendingChangesTree pendingChangesTree,
  568. ChangeTreeViewItem item,
  569. RowGUIArgs args)
  570. {
  571. for (int visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++)
  572. {
  573. Rect cellRect = args.GetCellRect(visibleColumnIdx);
  574. PendingChangesTreeColumn column =
  575. (PendingChangesTreeColumn)args.GetColumn(visibleColumnIdx);
  576. ChangeTreeViewItemCellGUI(
  577. isGluonMode,
  578. assetStatusCache,
  579. cellRect,
  580. treeView.rowHeight,
  581. treeView,
  582. pendingChangesTree,
  583. item,
  584. column,
  585. args.selected,
  586. args.focused);
  587. }
  588. }
  589. static void ChangeTreeViewItemCellGUI(
  590. bool isGluonMode,
  591. IAssetStatusCache assetStatusCache,
  592. Rect rect,
  593. float rowHeight,
  594. PendingChangesTreeView treeView,
  595. UnityPendingChangesTree pendingChangesTree,
  596. ChangeTreeViewItem item,
  597. PendingChangesTreeColumn column,
  598. bool isSelected,
  599. bool isFocused)
  600. {
  601. PendingChangeInfo changeInfo = item.ChangeInfo;
  602. string label = changeInfo.GetColumnText(
  603. PendingChangesTreeHeaderState.GetColumnName(column));
  604. DefaultStyles.label.fontSize = UnityConstants.PENDING_CHANGES_FONT_SIZE;
  605. if (column == PendingChangesTreeColumn.Item)
  606. {
  607. if (pendingChangesTree.HasMeta(changeInfo.ChangeInfo))
  608. label = string.Concat(label, UnityConstants.TREEVIEW_META_LABEL);
  609. Texture icon = GetIcon(changeInfo);
  610. bool isConflicted = IsConflicted(
  611. isGluonMode, assetStatusCache,
  612. changeInfo.ChangeInfo.GetFullPath());
  613. Texture overlayIcon =
  614. GetChangesOverlayIcon.ForPendingChange(
  615. changeInfo.ChangeInfo, isConflicted);
  616. bool wasChecked = ((ICheckablePlasticTreeNode)changeInfo).IsChecked() ?? false;
  617. bool isChecked = DrawTreeViewItem.ForCheckableItemCell(
  618. rect, rowHeight, item.depth,
  619. icon, overlayIcon, label,
  620. isSelected, isFocused, false,
  621. wasChecked);
  622. ((ICheckablePlasticTreeNode)changeInfo).UpdateCheckedState(isChecked);
  623. if (wasChecked != isChecked)
  624. {
  625. UpdateCheckStateForSelection(treeView, item);
  626. treeView.SelectionChanged();
  627. }
  628. return;
  629. }
  630. if (column == PendingChangesTreeColumn.Size)
  631. {
  632. DrawTreeViewItem.ForSecondaryLabelRightAligned(
  633. rect, label, isSelected, isFocused, false);
  634. return;
  635. }
  636. DrawTreeViewItem.ForSecondaryLabel(
  637. rect, label, isSelected, isFocused, false);
  638. }
  639. static void UpdateCheckStateForSelection(
  640. PendingChangesTreeView treeView,
  641. ChangeTreeViewItem senderTreeViewItem)
  642. {
  643. IList<int> selectedIds = treeView.GetSelection();
  644. if (selectedIds.Count <= 1)
  645. return;
  646. if (!selectedIds.Contains(senderTreeViewItem.id))
  647. return;
  648. bool isChecked = ((ICheckablePlasticTreeNode)senderTreeViewItem.ChangeInfo).IsChecked() ?? false;
  649. foreach (TreeViewItem treeViewItem in treeView.FindRows(selectedIds))
  650. {
  651. if (treeViewItem is ChangeCategoryTreeViewItem)
  652. {
  653. ((ICheckablePlasticTreeCategory)((ChangeCategoryTreeViewItem)treeViewItem)
  654. .Category).UpdateCheckedState(isChecked);
  655. continue;
  656. }
  657. ((ICheckablePlasticTreeNode)((ChangeTreeViewItem)treeViewItem)
  658. .ChangeInfo).UpdateCheckedState(isChecked);
  659. }
  660. }
  661. static void RegenerateRows(
  662. UnityPendingChangesTree pendingChangesTree,
  663. TreeViewItemIds<IPlasticTreeNode, PendingChangeInfo> treeViewItemIds,
  664. PendingChangesTreeView treeView,
  665. TreeViewItem rootItem,
  666. List<TreeViewItem> rows,
  667. bool expandCategories)
  668. {
  669. ClearRows(rootItem, rows);
  670. IEnumerable<IPlasticTreeNode> nodes = pendingChangesTree.GetNodes();
  671. if (nodes == null)
  672. return;
  673. foreach (IPlasticTreeNode node in nodes)
  674. {
  675. if (node is ChangelistNode)
  676. {
  677. AddChangelistNode(
  678. (ChangelistNode)node,
  679. treeViewItemIds,
  680. treeView,
  681. rootItem,
  682. rows,
  683. expandCategories);
  684. continue;
  685. }
  686. if (node is PendingChangeCategory)
  687. AddPendingChangeCategory(
  688. (PendingChangeCategory)node,
  689. treeViewItemIds,
  690. treeView,
  691. rootItem,
  692. rows,
  693. expandCategories,
  694. 0);
  695. }
  696. if (!expandCategories)
  697. return;
  698. treeView.state.expandedIDs = treeViewItemIds.GetCategoryIds();
  699. }
  700. static void AddChangelistNode(
  701. ChangelistNode changelist,
  702. TreeViewItemIds<IPlasticTreeNode, PendingChangeInfo> treeViewItemIds,
  703. PendingChangesTreeView treeView,
  704. TreeViewItem rootItem,
  705. List<TreeViewItem> rows,
  706. bool expandCategories)
  707. {
  708. int changelistCategoryId;
  709. if (!treeViewItemIds.TryGetCategoryItemId(changelist, out changelistCategoryId))
  710. changelistCategoryId = treeViewItemIds.AddCategoryItem(changelist);
  711. ChangelistTreeViewItem changelistTreeViewItem =
  712. new ChangelistTreeViewItem(changelistCategoryId, changelist);
  713. rootItem.AddChild(changelistTreeViewItem);
  714. rows.Add(changelistTreeViewItem);
  715. if (!expandCategories &&
  716. !treeView.IsExpanded(changelistTreeViewItem.id))
  717. return;
  718. IEnumerable<IPlasticTreeNode> categories = ((IPlasticTreeNode)changelist).GetChildren();
  719. foreach (IPlasticTreeNode category in categories)
  720. {
  721. AddPendingChangeCategory(
  722. (PendingChangeCategory)category,
  723. treeViewItemIds,
  724. treeView,
  725. changelistTreeViewItem,
  726. rows,
  727. expandCategories,
  728. 1);
  729. }
  730. }
  731. static void AddPendingChangeCategory(
  732. PendingChangeCategory category,
  733. TreeViewItemIds<IPlasticTreeNode, PendingChangeInfo> treeViewItemIds,
  734. PendingChangesTreeView treeView,
  735. TreeViewItem rootItem,
  736. List<TreeViewItem> rows,
  737. bool expandCategories,
  738. int depth)
  739. {
  740. int categoryId;
  741. if (!treeViewItemIds.TryGetCategoryItemId(category, out categoryId))
  742. categoryId = treeViewItemIds.AddCategoryItem(category);
  743. ChangeCategoryTreeViewItem categoryTreeViewItem =
  744. new ChangeCategoryTreeViewItem(categoryId, category, depth);
  745. rootItem.AddChild(categoryTreeViewItem);
  746. rows.Add(categoryTreeViewItem);
  747. if (!expandCategories &&
  748. !treeView.IsExpanded(categoryTreeViewItem.id))
  749. return;
  750. foreach (PendingChangeInfo change in ((IPendingChangesNode)category).GetCurrentChanges())
  751. {
  752. int changeId;
  753. if (!treeViewItemIds.TryGetInfoItemId(change, out changeId))
  754. changeId = treeViewItemIds.AddInfoItem(change);
  755. TreeViewItem changeTreeViewItem =
  756. new ChangeTreeViewItem(changeId, change, depth + 1);
  757. categoryTreeViewItem.AddChild(changeTreeViewItem);
  758. rows.Add(changeTreeViewItem);
  759. }
  760. }
  761. static void ClearRows(
  762. TreeViewItem rootItem,
  763. List<TreeViewItem> rows)
  764. {
  765. if (rootItem.hasChildren)
  766. rootItem.children.Clear();
  767. rows.Clear();
  768. }
  769. static Texture GetIcon(PendingChangeInfo change)
  770. {
  771. if (change.ChangeInfo.IsDirectory)
  772. return Images.GetDirectoryIcon();
  773. string fullPath = change.ChangeInfo.GetFullPath();
  774. return Images.GetFileIcon(fullPath);
  775. }
  776. static bool IsConflicted(
  777. bool isGluonMode,
  778. IAssetStatusCache assetStatusCache,
  779. string fullPath)
  780. {
  781. if (!isGluonMode)
  782. return false;
  783. return ClassifyAssetStatus.IsConflicted(
  784. assetStatusCache.GetStatus(fullPath));
  785. }
  786. bool mExpandCategories;
  787. bool mIsSelectionChangedEventDisabled;
  788. TreeViewItemIds<IPlasticTreeNode, PendingChangeInfo> mTreeViewItemIds =
  789. new TreeViewItemIds<IPlasticTreeNode, PendingChangeInfo>();
  790. List<TreeViewItem> mRows = new List<TreeViewItem>();
  791. UnityPendingChangesTree mPendingChangesTree;
  792. CooldownWindowDelayer mCooldownFilterAction;
  793. readonly PendingChangesTreeHeaderState mHeaderState;
  794. readonly PendingChangesViewMenu mMenu;
  795. readonly IAssetStatusCache mAssetStatusCache;
  796. readonly List<string> mColumnNames;
  797. readonly bool mIsGluonMode;
  798. readonly WorkspaceInfo mWkInfo;
  799. }
  800. }