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