using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; using Codice.CM.Common; using PlasticGui; using PlasticGui.WorkspaceWindow.History; using Unity.PlasticSCM.Editor.UI; using Unity.PlasticSCM.Editor.UI.Avatar; using Unity.PlasticSCM.Editor.UI.Tree; using Time = Codice.Client.Common.Time; #if UNITY_6000_2_OR_NEWER using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem; #endif namespace Unity.PlasticSCM.Editor.Views.History { internal class HistoryListView : PlasticTreeView { internal GenericMenu Menu { get { return mMenu.Menu; } } internal HistoryListView( string wkPath, HistoryListHeaderState headerState, HistoryListViewMenu menu, List columnNames, Action doubleClickAction, Action> afterItemsChangedAction) { mWkPath = wkPath; mMenu = menu; mColumnNames = columnNames; mDoubleClickAction = doubleClickAction; mAfterItemsChangedAction = afterItemsChangedAction; multiColumnHeader = new MultiColumnHeader(headerState); multiColumnHeader.canSort = true; multiColumnHeader.sortingChanged += SortingChanged; mDelayedFilterAction = new DelayedActionBySecondsRunner( DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL); } public override void OnGUI(Rect rect) { base.OnGUI(rect); if (!HasKeyboardFocus()) return; Event e = Event.current; if (e.type != EventType.KeyDown) return; bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e); if (isProcessed) e.Use(); } protected override IList BuildRows( TreeViewItem rootItem) { if (mRevisionsList == null) { ClearRows(rootItem, mRows); return mRows; } RegenerateRows( mListViewItemIds, mRevisionsList, rootItem, mRows); return mRows; } protected override void SearchChanged(string newSearch) { mDelayedFilterAction.Run(); } protected override void ContextClickedItem(int id) { mMenu.Popup(); Repaint(); } protected override void RowGUI(RowGUIArgs args) { if (args.item is HistoryListViewItem) { HistoryListViewItem historyListViewItem = (HistoryListViewItem)args.item; HistoryListViewItemGUI( mWkPath, mRepSpec, rowHeight, historyListViewItem, args, mLoadedRevisionId == historyListViewItem.Revision.Id, Repaint); return; } base.RowGUI(args); } protected override void DoubleClickedItem(int id) { mDoubleClickAction(); } internal void BuildModel( RepositorySpec repSpec, HistoryRevisionList historyRevisionList, long loadedRevisionId) { mListViewItemIds.Clear(); mRepSpec = repSpec; mRevisionsList = historyRevisionList; mLoadedRevisionId = loadedRevisionId; } internal void Refilter() { if (mRevisionsList == null) return; Filter filter = new Filter(searchString); mRevisionsList.Filter(filter, mColumnNames, null, null); mAfterItemsChangedAction(mRevisionsList.GetRevisions()); } internal void Sort() { if (mRevisionsList == null) return; int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex; bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx); mRevisionsList.Sort( mColumnNames[sortedColumnIdx], sortAscending); } internal long GetLoadedRevisionId() { return mLoadedRevisionId; } internal List GetSelectedRepObjectInfos() { List result = new List(); IList selectedIds = GetSelection(); if (selectedIds.Count == 0) return result; foreach (KeyValuePair item in mListViewItemIds.GetInfoItems()) { if (!selectedIds.Contains(item.Value)) continue; result.Add(item.Key); } return result; } internal List GetAllRepObjectInfos() { List result = new List(); foreach (KeyValuePair item in mListViewItemIds.GetInfoItems()) { result.Add(item.Key); } return result; } internal List GetSelectedHistoryRevisions() { return GetSelectedRepObjectInfos().OfType().ToList(); } internal long GetSelectedChangesetId() { List repObjectInfos = GetSelectedRepObjectInfos(); foreach (RepObjectInfo info in repObjectInfos) { if (info is HistoryRevision) return ((HistoryRevision)info).ChangeSet; if (info is MoveRealizationInfo) return ((MoveRealizationInfo)info).DstDirRev.Changeset; if (info is RemovedRealizationInfo) return ((RemovedRealizationInfo)info).DirRev.Changeset; } return -1; } internal void SelectRepObjectInfos( List repObjectsToSelect) { List idsToSelect = new List(); foreach (RepObjectInfo repObjectInfo in repObjectsToSelect) { int repObjectInfoId = GetTreeIdForItem(repObjectInfo); if (repObjectInfoId == -1) continue; idsToSelect.Add(repObjectInfoId); } TableViewOperations.SetSelectionAndScroll(this, idsToSelect); } int GetTreeIdForItem(RepObjectInfo currentRepObjectInfo) { foreach (KeyValuePair item in mListViewItemIds.GetInfoItems()) { if (!currentRepObjectInfo.Equals(item.Key)) continue; if (!currentRepObjectInfo.GUID.Equals(item.Key.GUID)) continue; return item.Value; } return -1; } void DelayedSearchChanged() { Refilter(); Sort(); Reload(); TableViewOperations.ScrollToSelection(this); } void SortingChanged(MultiColumnHeader multiColumnHeader) { Sort(); Reload(); } static void RegenerateRows( ListViewItemIds listViewItemIds, HistoryRevisionList revisions, TreeViewItem rootItem, List rows) { ClearRows(rootItem, rows); if (revisions.GetCount() == 0) return; foreach (RepObjectInfo objectInfo in revisions.GetRevisions()) { int objectId; if (!listViewItemIds.TryGetInfoItemId(objectInfo, out objectId)) objectId = listViewItemIds.AddInfoItem(objectInfo); HistoryListViewItem changesetListViewItem = new HistoryListViewItem(objectId, objectInfo); rootItem.AddChild(changesetListViewItem); rows.Add(changesetListViewItem); } } static void ClearRows( TreeViewItem rootItem, List rows) { if (rootItem.hasChildren) rootItem.children.Clear(); rows.Clear(); } static void HistoryListViewItemGUI( string wkPath, RepositorySpec repSpec, float rowHeight, HistoryListViewItem item, RowGUIArgs args, bool isBoldText, Action avatarLoadedAction) { for (int visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++) { Rect cellRect = args.GetCellRect(visibleColumnIdx); if (visibleColumnIdx == 0) { cellRect.x += UnityConstants.FIRST_COLUMN_WITHOUT_ICON_INDENT; cellRect.width -= UnityConstants.FIRST_COLUMN_WITHOUT_ICON_INDENT; } HistoryListColumn column = (HistoryListColumn)args.GetColumn(visibleColumnIdx); HistoryListViewItemCellGUI( cellRect, rowHeight, wkPath, repSpec, item, column, avatarLoadedAction, args.selected, args.focused, isBoldText); } } static void HistoryListViewItemCellGUI( Rect rect, float rowHeight, string wkPath, RepositorySpec repSpec, HistoryListViewItem item, HistoryListColumn column, Action avatarLoadedAction, bool isSelected, bool isFocused, bool isBoldText) { string columnText = HistoryInfoView.GetColumnText( wkPath, repSpec, item.Revision, HistoryListHeaderState.GetColumnName(column)); string userName = PlasticGui.Plastic.API.GetUserName(repSpec.Server, item.Revision.Owner); if (column == HistoryListColumn.Comment) { DrawTreeViewItem.ForItemCell( rect, rowHeight, -1, GetAvatar.ForEmail(userName, avatarLoadedAction), userName, null, columnText, isSelected, isFocused, isBoldText, false); return; } if (column == HistoryListColumn.Type) { DrawTreeViewItem.ForItemCell( rect, rowHeight, -1, null, null, null, GetRevisionText(item.Revision), isSelected, isFocused, isBoldText, false); return; } if (column == HistoryListColumn.CreationDate) { DrawTreeViewItem.ForLabel( rect, new GUIContent( Time.GetLongTimeAgoString(item.Revision.LocalTimeStamp), columnText), isSelected, isFocused, isBoldText); return; } if (column == HistoryListColumn.Branch) { DrawTreeViewItem.ForSecondaryLabel( rect, columnText, isSelected, isFocused, isBoldText); return; } DrawTreeViewItem.ForLabel( rect, columnText, isSelected, isFocused, isBoldText); } static string GetRevisionText(RepObjectInfo revision) { if (revision is MoveRealizationInfo) return PlasticLocalization.Name.MovedDiffCategory.GetString(); if (revision is RemovedRealizationInfo) return PlasticLocalization.Name.DeletedDiffCategory.GetString(); if (((HistoryRevision)revision).ParentRevisionId == -1) return PlasticLocalization.Name.AddedDiffCategory.GetString(); return PlasticLocalization.Name.ChangedDiffCategory.GetString(); } ListViewItemIds mListViewItemIds = new ListViewItemIds(); HistoryRevisionList mRevisionsList; long mLoadedRevisionId; RepositorySpec mRepSpec; readonly DelayedActionBySecondsRunner mDelayedFilterAction; readonly HistoryListViewMenu mMenu; readonly List mColumnNames; readonly Action mDoubleClickAction; readonly Action> mAfterItemsChangedAction; readonly string mWkPath; } }