This commit is contained in:
2024-09-20 20:30:10 +02:00
commit 4fabf1a6fd
29169 changed files with 1706941 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 15fe89692edc49a4891091bd0e1c6536
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using UnityEditor.IMGUI.Controls;
namespace Unity.PlasticSCM.Editor.Views.Branches
{
class BranchListViewItem : TreeViewItem
{
internal object ObjectInfo { get; private set; }
internal BranchListViewItem(int id, object objectInfo)
: base(id, 1)
{
ObjectInfo = objectInfo;
displayName = id.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ebbbce5f7ed39ab45b6f43340727ba5e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.Branches
{
internal enum BranchesListColumn
{
Name,
Repository,
CreatedBy,
CreationDate,
Comment,
Branch,
Guid
}
[Serializable]
internal class BranchesListHeaderState : MultiColumnHeaderState, ISerializationCallbackReceiver
{
internal static BranchesListHeaderState GetDefault()
{
return new BranchesListHeaderState(BuildColumns());
}
internal static List<string> GetColumnNames()
{
List<string> result = new List<string>();
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.NameColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.RepositoryColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CreatedByColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CreationDateColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CommentColumn));
return result;
}
internal static string GetColumnName(BranchesListColumn column)
{
switch (column)
{
case BranchesListColumn.Name:
return PlasticLocalization.GetString(PlasticLocalization.Name.NameColumn);
case BranchesListColumn.Repository:
return PlasticLocalization.GetString(PlasticLocalization.Name.RepositoryColumn);
case BranchesListColumn.CreatedBy:
return PlasticLocalization.GetString(PlasticLocalization.Name.CreatedByColumn);
case BranchesListColumn.CreationDate:
return PlasticLocalization.GetString(PlasticLocalization.Name.CreationDateColumn);
case BranchesListColumn.Comment:
return PlasticLocalization.GetString(PlasticLocalization.Name.CommentColumn);
default:
return null;
}
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (mHeaderTitles != null)
TreeHeaderColumns.SetTitles(columns, mHeaderTitles);
if (mColumsAllowedToggleVisibility != null)
TreeHeaderColumns.SetVisibilities(columns, mColumsAllowedToggleVisibility);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
static Column[] BuildColumns()
{
return new Column[]
{
new Column()
{
width = UnityConstants.BranchesColumns.BRANCHES_NAME_WIDTH,
minWidth = UnityConstants.BranchesColumns.BRANCHES_NAME_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(BranchesListColumn.Name)),
allowToggleVisibility = false,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.BranchesColumns.REPOSITORY_WIDTH,
minWidth = UnityConstants.BranchesColumns.REPOSITORY_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(BranchesListColumn.Repository)),
allowToggleVisibility = true,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.BranchesColumns.CREATEDBY_WIDTH,
minWidth = UnityConstants.BranchesColumns.CREATEDBY_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(BranchesListColumn.CreatedBy)),
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.BranchesColumns.CREATION_DATE_WIDTH,
minWidth = UnityConstants.BranchesColumns.CREATION_DATE_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(BranchesListColumn.CreationDate)),
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.BranchesColumns.COMMENT_WIDTH,
minWidth = UnityConstants.BranchesColumns.COMMENT_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(BranchesListColumn.Comment)),
sortingArrowAlignment = TextAlignment.Right
}
};
}
BranchesListHeaderState(Column[] columns)
: base(columns)
{
if (mHeaderTitles == null)
mHeaderTitles = TreeHeaderColumns.GetTitles(columns);
if (mColumsAllowedToggleVisibility == null)
mColumsAllowedToggleVisibility = TreeHeaderColumns.GetVisibilities(columns);
}
[SerializeField]
string[] mHeaderTitles;
[SerializeField]
bool[] mColumsAllowedToggleVisibility;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4a41e458bcb22946bcfa6b165c90288
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,418 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.QueryViews;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Avatar;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.Branches
{
internal class BranchesListView : TreeView
{
internal GenericMenu Menu { get { return mMenu.Menu; } }
internal BranchesListView(
BranchesListHeaderState headerState,
List<string> columnNames,
BranchesViewMenu menu,
Action sizeChangedAction)
: base(new TreeViewState())
{
mColumnNames = columnNames;
mMenu = menu;
mSizeChangedAction = sizeChangedAction;
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.canSort = true;
multiColumnHeader.sortingChanged += SortingChanged;
rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
showAlternatingRowBackgrounds = false;
mCooldownFilterAction = new CooldownWindowDelayer(
DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
}
public override IList<TreeViewItem> GetRows()
{
return mRows;
}
internal void SetLoadedBranchId(long loadedBranchId)
{
mLoadedBranchId = loadedBranchId;
}
protected override TreeViewItem BuildRoot()
{
return new TreeViewItem(0, -1, string.Empty);
}
protected override IList<TreeViewItem> BuildRows(
TreeViewItem rootItem)
{
if (mQueryResult == null)
{
ClearRows(rootItem, mRows);
return mRows;
}
RegenerateRows(
mListViewItemIds,
mQueryResult.GetObjects(),
rootItem, mRows);
return mRows;
}
protected override void SearchChanged(string newSearch)
{
mCooldownFilterAction.Ping();
}
protected override void ContextClickedItem(int id)
{
mMenu.Popup();
Repaint();
}
public override void OnGUI(Rect rect)
{
if (Event.current.type == EventType.Layout)
{
if (IsSizeChanged(treeViewRect, mLastRect))
mSizeChangedAction();
}
mLastRect = treeViewRect;
base.OnGUI(rect);
Event e = Event.current;
if (e.type != EventType.KeyDown)
return;
bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
if (isProcessed)
e.Use();
}
protected override void BeforeRowsGUI()
{
int firstRowVisible;
int lastRowVisible;
GetFirstAndLastVisibleRows(out firstRowVisible, out lastRowVisible);
GUI.DrawTexture(new Rect(0,
firstRowVisible * rowHeight,
GetRowRect(0).width,
(lastRowVisible * rowHeight) + 1000),
Images.GetTreeviewBackgroundTexture());
DrawTreeViewItem.InitializeStyles();
base.BeforeRowsGUI();
}
protected override void RowGUI(RowGUIArgs args)
{
if (args.item is BranchListViewItem)
{
BranchListViewItem branchListViewItem = (BranchListViewItem)args.item;
BranchInfo branchInfo = (BranchInfo)branchListViewItem.ObjectInfo;
BranchesListViewItemGUI(
mQueryResult,
rowHeight,
branchListViewItem,
args,
branchInfo.BranchId == mLoadedBranchId,
Repaint);
return;
}
base.RowGUI(args);
}
internal void BuildModel(
ViewQueryResult queryResult,
long loadedBranchId)
{
mListViewItemIds.Clear();
mQueryResult = queryResult;
mLoadedBranchId = loadedBranchId;
}
internal void Refilter()
{
if (mQueryResult == null)
return;
Filter filter = new Filter(searchString);
mQueryResult.ApplyFilter(filter, mColumnNames);
}
internal void Sort()
{
if (mQueryResult == null)
return;
int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
mQueryResult.Sort(
mColumnNames[sortedColumnIdx],
sortAscending);
}
internal List<RepositorySpec> GetSelectedRepositories()
{
List<RepositorySpec> result = new List<RepositorySpec>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<object, int> item
in mListViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
RepositorySpec repSpec =
mQueryResult.GetRepositorySpec(item.Key);
result.Add(repSpec);
}
return result;
}
internal List<RepObjectInfo> GetSelectedRepObjectInfos()
{
List<RepObjectInfo> result = new List<RepObjectInfo>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<object, int> item
in mListViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
RepObjectInfo repObjectInfo =
mQueryResult.GetRepObjectInfo(item.Key);
result.Add(repObjectInfo);
}
return result;
}
internal void SelectRepObjectInfos(
List<RepObjectInfo> repObjectsToSelect)
{
List<int> idsToSelect = new List<int>();
foreach (RepObjectInfo repObjectInfo in repObjectsToSelect)
{
int repObjectInfoId = GetTreeIdForItem(repObjectInfo);
if (repObjectInfoId == -1)
continue;
idsToSelect.Add(repObjectInfoId);
}
TableViewOperations.SetSelectionAndScroll(this, idsToSelect);
}
int GetTreeIdForItem(RepObjectInfo repObjectInfo)
{
foreach (KeyValuePair<object, int> item in mListViewItemIds.GetInfoItems())
{
RepObjectInfo currentRepObjectInfo =
mQueryResult.GetRepObjectInfo(item.Key);
if (!currentRepObjectInfo.Equals(repObjectInfo))
continue;
if (!currentRepObjectInfo.GUID.Equals(repObjectInfo.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<object> listViewItemIds,
List<object> objectInfos,
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
ClearRows(rootItem, rows);
if (objectInfos.Count == 0)
return;
foreach (object objectInfo in objectInfos)
{
int objectId;
if (!listViewItemIds.TryGetInfoItemId(objectInfo, out objectId))
objectId = listViewItemIds.AddInfoItem(objectInfo);
BranchListViewItem branchListViewItem =
new BranchListViewItem(objectId, objectInfo);
rootItem.AddChild(branchListViewItem);
rows.Add(branchListViewItem);
}
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static void BranchesListViewItemGUI(
ViewQueryResult queryResult,
float rowHeight,
BranchListViewItem 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;
}
BranchesListColumn column =
(BranchesListColumn)args.GetColumn(visibleColumnIdx);
BranchesListViewItemCellGUI(
cellRect,
rowHeight,
queryResult,
item,
column,
avatarLoadedAction,
args.selected,
args.focused,
isBoldText);
}
}
static void BranchesListViewItemCellGUI(
Rect rect,
float rowHeight,
ViewQueryResult queryResult,
BranchListViewItem item,
BranchesListColumn column,
Action avatarLoadedAction,
bool isSelected,
bool isFocused,
bool isBoldText)
{
string columnText = RepObjectInfoView.GetColumnText(
queryResult.GetRepositorySpec(item.ObjectInfo),
queryResult.GetRepObjectInfo(item.ObjectInfo),
BranchesListHeaderState.GetColumnName(column));
if (column == BranchesListColumn.CreatedBy)
{
DrawTreeViewItem.ForItemCell(
rect,
rowHeight,
-1,
GetAvatar.ForEmail(columnText, avatarLoadedAction),
null,
columnText,
isSelected,
isFocused,
isBoldText,
false);
return;
}
if (column == BranchesListColumn.Branch ||
column == BranchesListColumn.Repository ||
column == BranchesListColumn.Guid)
{
DrawTreeViewItem.ForSecondaryLabel(
rect, columnText, isSelected, isFocused, isBoldText);
return;
}
DrawTreeViewItem.ForLabel(
rect, columnText, isSelected, isFocused, isBoldText);
}
static bool IsSizeChanged(
Rect currentRect, Rect lastRect)
{
if (currentRect.width != lastRect.width)
return true;
if (currentRect.height != lastRect.height)
return true;
return false;
}
Rect mLastRect;
ListViewItemIds<object> mListViewItemIds = new ListViewItemIds<object>();
List<TreeViewItem> mRows = new List<TreeViewItem>();
ViewQueryResult mQueryResult;
long mLoadedBranchId;
readonly CooldownWindowDelayer mCooldownFilterAction;
readonly Action mSizeChangedAction;
readonly BranchesViewMenu mMenu;
readonly List<string> mColumnNames;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b909cb14b9a08c45b5d03f0b61feecb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,81 @@
using System.Collections.Generic;
using System.Linq;
using Codice.CM.Common;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.Branches
{
internal static class BranchesSelection
{
internal static void SelectBranches(
BranchesListView listView,
List<RepObjectInfo> branchesToSelect,
int defaultRow)
{
if (branchesToSelect == null || branchesToSelect.Count == 0)
{
TableViewOperations.SelectFirstRow(listView);
return;
}
listView.SelectRepObjectInfos(branchesToSelect);
if (listView.HasSelection())
return;
TableViewOperations.SelectDefaultRow(listView, defaultRow);
if (listView.HasSelection())
return;
TableViewOperations.SelectFirstRow(listView);
}
internal static List<RepObjectInfo> GetSelectedRepObjectInfos(
BranchesListView listView)
{
return listView.GetSelectedRepObjectInfos();
}
internal static int GetSelectedBranchesCount(
BranchesListView listView)
{
return listView.GetSelection().Count;
}
internal static BranchInfo GetSelectedBranch(
BranchesListView listView)
{
List<RepObjectInfo> selectedRepObjectsInfos = listView.GetSelectedRepObjectInfos();
if (selectedRepObjectsInfos.Count == 0)
return null;
return (BranchInfo)selectedRepObjectsInfos[0];
}
internal static List<BranchInfo> GetSelectedBranches(
BranchesListView listView)
{
return listView.GetSelectedRepObjectInfos().Cast<BranchInfo>().ToList();
}
internal static RepositorySpec GetSelectedRepository(
BranchesListView listView)
{
List<RepositorySpec> selectedRepositories = listView.GetSelectedRepositories();
if (selectedRepositories.Count == 0)
return null;
return selectedRepositories[0];
}
internal static List<RepositorySpec> GetSelectedRepositories(
BranchesListView listView)
{
return listView.GetSelectedRepositories();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 73306fe71bf092d4495ff28ee02b766b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,443 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.CM.Common;
using Codice.Client.Common.Threading;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.QueryViews;
using PlasticGui.WorkspaceWindow.QueryViews.Branches;
using PlasticGui.WorkspaceWindow.Update;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.UI.Tree;
using Unity.PlasticSCM.Editor.Views.Branches.Dialogs;
using Unity.PlasticSCM.Editor.Views.Changesets;
namespace Unity.PlasticSCM.Editor.Views.Branches
{
internal class BranchesTab :
IRefreshableView,
IBranchMenuOperations,
IQueryRefreshableView
{
internal BranchesListView Table { get { return mBranchesListView; } }
internal IBranchMenuOperations Operations { get { return this; } }
internal BranchesTab(
WorkspaceInfo wkInfo,
IWorkspaceWindow workspaceWindow,
IViewSwitcher viewSwitcher,
IMergeViewLauncher mergeViewLauncher,
IUpdateReport updateReport,
NewIncomingChangesUpdater developerNewIncomingChangesUpdater,
EditorWindow parentWindow)
{
mWkInfo = wkInfo;
mParentWindow = parentWindow;
mProgressControls = new ProgressControlsForViews();
mProgressControls = new ProgressControlsForViews();
BuildComponents(
wkInfo,
workspaceWindow,
viewSwitcher,
mergeViewLauncher,
updateReport,
developerNewIncomingChangesUpdater,
parentWindow);
((IRefreshableView)this).Refresh();
}
internal void Update()
{
mProgressControls.UpdateProgress(mParentWindow);
}
internal void OnGUI()
{
DoActionsToolbar(mProgressControls);
DoBranchesArea(
mBranchesListView,
mProgressControls.IsOperationRunning());
}
internal void SetWorkingObjectInfo(WorkingObjectInfo homeInfo)
{
lock(mLock)
{
mLoadedBranchId = homeInfo.BranchInfo.BranchId;
}
mBranchesListView.SetLoadedBranchId(mLoadedBranchId);
}
static void DoBranchesArea(
BranchesListView branchesListView,
bool isOperationRunning)
{
EditorGUILayout.BeginVertical();
GUI.enabled = !isOperationRunning;
Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
branchesListView.OnGUI(rect);
GUI.enabled = true;
EditorGUILayout.EndVertical();
}
internal void DrawSearchFieldForBranchesTab()
{
DrawSearchField.For(
mSearchField,
mBranchesListView,
UnityConstants.SEARCH_FIELD_WIDTH);
}
internal void OnDisable()
{
mSearchField.downOrUpArrowKeyPressed -=
SearchField_OnDownOrUpArrowKeyPressed;
TreeHeaderSettings.Save(
mBranchesListView.multiColumnHeader.state,
UnityConstants.BRANCHES_TABLE_SETTINGS_NAME);
}
void IRefreshableView.Refresh()
{
string query = GetBranchesQuery(mDateFilter);
FillBranches(mWkInfo,
query,
BranchesSelection.GetSelectedRepObjectInfos(mBranchesListView));
}
//IQueryRefreshableView
public void RefreshAndSelect(RepObjectInfo repObj)
{
string query = GetBranchesQuery(mDateFilter);
FillBranches(mWkInfo,
query,
new List<RepObjectInfo> { repObj });
}
void FillBranches(WorkspaceInfo wkInfo, string query, List<RepObjectInfo> branchesToSelect)
{
if (mIsRefreshing)
return;
mIsRefreshing = true;
int defaultRow = TableViewOperations.
GetFirstSelectedRow(mBranchesListView);
((IProgressControls)mProgressControls).ShowProgress(
PlasticLocalization.GetString(
PlasticLocalization.Name.LoadingBranches));
ViewQueryResult queryResult = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter();
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
long loadedBranchId = GetLoadedBranchId(wkInfo);
lock(mLock)
{
mLoadedBranchId = loadedBranchId;
}
queryResult = new ViewQueryResult(
PlasticGui.Plastic.API.FindQuery(wkInfo, query));
},
/*afterOperationDelegate*/ delegate
{
try
{
if (waiter.Exception != null)
{
ExceptionsHandler.DisplayException(waiter.Exception);
return;
}
UpdateBranchesList(
mBranchesListView,
queryResult,
mLoadedBranchId);
int branchesCount = GetBranchesCount(queryResult);
if (branchesCount == 0)
{
return;
}
BranchesSelection.SelectBranches(
mBranchesListView, branchesToSelect, defaultRow);
}
finally
{
((IProgressControls)mProgressControls).HideProgress();
mIsRefreshing = false;
}
});
}
static long GetLoadedBranchId(WorkspaceInfo wkInfo)
{
BranchInfo brInfo = PlasticGui.Plastic.API.GetWorkingBranch(wkInfo);
if (brInfo != null)
return brInfo.BranchId;
return -1;
}
static void UpdateBranchesList(
BranchesListView branchesListView,
ViewQueryResult queryResult,
long loadedBranchId)
{
branchesListView.BuildModel(
queryResult, loadedBranchId);
branchesListView.Refilter();
branchesListView.Sort();
branchesListView.Reload();
}
internal static int GetBranchesCount(
ViewQueryResult queryResult)
{
if (queryResult == null)
return 0;
return queryResult.Count();
}
internal static string GetBranchesQuery(DateFilter dateFilter)
{
if (dateFilter.FilterType == DateFilter.Type.AllTime)
return QueryConstants.BranchesBeginningQuery;
string whereClause = QueryConstants.GetDateWhereClause(
dateFilter.GetTimeAgo());
return string.Format("{0} {1}",
QueryConstants.BranchesBeginningQuery,
whereClause);
}
internal void DrawDateFilter()
{
GUI.enabled = !mProgressControls.IsOperationRunning();
EditorGUI.BeginChangeCheck();
mDateFilter.FilterType = (DateFilter.Type)
EditorGUILayout.EnumPopup(
mDateFilter.FilterType,
EditorStyles.toolbarDropDown,
GUILayout.Width(100));
if (EditorGUI.EndChangeCheck())
{
EnumPopupSetting<DateFilter.Type>.Save(
mDateFilter.FilterType,
UnityConstants.BRANCHES_DATE_FILTER_SETTING_NAME);
((IRefreshableView)this).Refresh();
}
GUI.enabled = true;
}
void SearchField_OnDownOrUpArrowKeyPressed()
{
mBranchesListView.SetFocusAndEnsureSelectedItem();
}
static void DoActionsToolbar(
ProgressControlsForViews progressControls)
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
if (progressControls.IsOperationRunning())
{
DrawProgressForViews.ForIndeterminateProgress(
progressControls.ProgressData);
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
}
void BuildComponents(
WorkspaceInfo wkInfo,
IWorkspaceWindow workspaceWindow,
IViewSwitcher viewSwitcher,
IMergeViewLauncher mergeViewLauncher,
IUpdateReport updateReport,
NewIncomingChangesUpdater developerNewIncomingChangesUpdater,
EditorWindow parentWindow)
{
mSearchField = new SearchField();
mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
DateFilter.Type dateFilterType =
EnumPopupSetting<DateFilter.Type>.Load(
UnityConstants.BRANCHES_DATE_FILTER_SETTING_NAME,
DateFilter.Type.LastMonth);
mDateFilter = new DateFilter(dateFilterType);
BranchesListHeaderState headerState =
BranchesListHeaderState.GetDefault();
TreeHeaderSettings.Load(headerState,
UnityConstants.BRANCHES_TABLE_SETTINGS_NAME,
(int)BranchesListColumn.CreationDate, false);
mBranchesListView = new BranchesListView(
headerState,
BranchesListHeaderState.GetColumnNames(),
new BranchesViewMenu(this),
sizeChangedAction: OnBranchesListViewSizeChanged);
mBranchesListView.Reload();
mBranchOperations = new BranchOperations(
wkInfo,
workspaceWindow,
viewSwitcher,
mergeViewLauncher,
this,
ViewType.BranchesView,
mProgressControls,
updateReport,
new ContinueWithPendingChangesQuestionerBuilder(viewSwitcher, parentWindow),
developerNewIncomingChangesUpdater);
}
void OnBranchesListViewSizeChanged()
{
if (!mShouldScrollToSelection)
return;
mShouldScrollToSelection = false;
TableViewOperations.ScrollToSelection(mBranchesListView);
}
int IBranchMenuOperations.GetSelectedBranchesCount()
{
return BranchesSelection.GetSelectedBranchesCount(mBranchesListView);
}
void IBranchMenuOperations.CreateBranch()
{
RepositorySpec repSpec = BranchesSelection.GetSelectedRepository(mBranchesListView);
BranchInfo branchInfo = BranchesSelection.GetSelectedBranch(mBranchesListView);
BranchCreationData branchCreationData = CreateBranchDialog.CreateBranchFromLastParentBranchChangeset(
mParentWindow,
repSpec,
branchInfo);
mBranchOperations.CreateBranch(
branchCreationData,
RefreshAsset.BeforeLongAssetOperation,
RefreshAsset.AfterLongAssetOperation);
}
void IBranchMenuOperations.CreateTopLevelBranch() { }
void IBranchMenuOperations.SwitchToBranch()
{
RepositorySpec repSpec = BranchesSelection.GetSelectedRepository(mBranchesListView);
BranchInfo branchInfo = BranchesSelection.GetSelectedBranch(mBranchesListView);
mBranchOperations.SwitchToBranch(
repSpec,
branchInfo,
RefreshAsset.BeforeLongAssetOperation,
RefreshAsset.AfterLongAssetOperation);
}
void IBranchMenuOperations.MergeBranch() { }
void IBranchMenuOperations.CherrypickBranch() { }
void IBranchMenuOperations.MergeToBranch() { }
void IBranchMenuOperations.PullBranch() { }
void IBranchMenuOperations.PullRemoteBranch() { }
void IBranchMenuOperations.SyncWithGit() { }
void IBranchMenuOperations.PushBranch() { }
void IBranchMenuOperations.DiffBranch() { }
void IBranchMenuOperations.DiffWithAnotherBranch() { }
void IBranchMenuOperations.ViewChangesets() { }
void IBranchMenuOperations.RenameBranch()
{
RepositorySpec repSpec = BranchesSelection.GetSelectedRepository(mBranchesListView);
BranchInfo branchInfo = BranchesSelection.GetSelectedBranch(mBranchesListView);
BranchRenameData branchRenameData = RenameBranchDialog.GetBranchRenameData(
repSpec,
branchInfo,
mParentWindow);
mBranchOperations.RenameBranch(branchRenameData);
}
void IBranchMenuOperations.DeleteBranch()
{
RepositorySpec repSpec = BranchesSelection.GetSelectedRepository(mBranchesListView);
List<RepositorySpec> repositories = BranchesSelection.GetSelectedRepositories(mBranchesListView);
List<BranchInfo> branchesToDelete = BranchesSelection.GetSelectedBranches(mBranchesListView);
mBranchOperations.DeleteBranch(repositories, branchesToDelete);
}
void IBranchMenuOperations.CreateCodeReview() { }
void IBranchMenuOperations.ViewPermissions() { }
SearchField mSearchField;
bool mIsRefreshing;
DateFilter mDateFilter;
bool mShouldScrollToSelection;
BranchesListView mBranchesListView;
BranchOperations mBranchOperations;
long mLoadedBranchId = -1;
object mLock = new object();
readonly WorkspaceInfo mWkInfo;
readonly ProgressControlsForViews mProgressControls;
readonly EditorWindow mParentWindow;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2350e7d7f6d79024da24dea8f15a6881
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,166 @@
using UnityEditor;
using UnityEngine;
using PlasticGui;
using PlasticGui.WorkspaceWindow.QueryViews.Branches;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.Views.Branches
{
internal class BranchesViewMenu
{
internal GenericMenu Menu { get { return mMenu; } }
internal BranchesViewMenu(
IBranchMenuOperations branchMenuOperations)
{
mBranchMenuOperations = branchMenuOperations;
BuildComponents();
}
internal void Popup()
{
mMenu = new GenericMenu();
UpdateMenuItems(mMenu);
mMenu.ShowAsContext();
}
internal bool ProcessKeyActionIfNeeded(Event e)
{
BranchMenuOperations operationToExecute = GetMenuOperations(e);
if (operationToExecute == BranchMenuOperations.None)
return false;
BranchMenuOperations operations =
BranchMenuUpdater.GetAvailableMenuOperations(
mBranchMenuOperations.GetSelectedBranchesCount(),
false);
if (!operations.HasFlag(operationToExecute))
return false;
ProcessMenuOperation(operationToExecute, mBranchMenuOperations);
return true;
}
void CreateBranchMenuItem_Click()
{
mBranchMenuOperations.CreateBranch();
}
void SwitchToBranchMenuItem_Click()
{
mBranchMenuOperations.SwitchToBranch();
}
void RenameBranchMenuItem_Click()
{
mBranchMenuOperations.RenameBranch();
}
void DeleteBranchMenuItem_Click()
{
mBranchMenuOperations.DeleteBranch();
}
internal void UpdateMenuItems(GenericMenu menu)
{
BranchMenuOperations operations = BranchMenuUpdater.GetAvailableMenuOperations(
mBranchMenuOperations.GetSelectedBranchesCount(), false);
AddBranchMenuItem(
mCreateBranchMenuItemContent,
menu,
operations,
BranchMenuOperations.CreateBranch,
CreateBranchMenuItem_Click);
AddBranchMenuItem(
mSwitchToBranchMenuItemContent,
menu,
operations,
BranchMenuOperations.SwitchToBranch,
SwitchToBranchMenuItem_Click);
menu.AddSeparator("");
AddBranchMenuItem(
mRenameBranchMenuItemContent,
menu,
operations,
BranchMenuOperations.Rename,
RenameBranchMenuItem_Click);
AddBranchMenuItem(
mDeleteBranchMenuItemContent,
menu,
operations,
BranchMenuOperations.Delete,
DeleteBranchMenuItem_Click);
}
static void AddBranchMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
BranchMenuOperations operations,
BranchMenuOperations operationsToCheck,
GenericMenu.MenuFunction menuFunction)
{
if (operations.HasFlag(operationsToCheck))
{
menu.AddItem(
menuItemContent,
false,
menuFunction);
return;
}
menu.AddDisabledItem(menuItemContent);
}
static void ProcessMenuOperation(
BranchMenuOperations operationToExecute,
IBranchMenuOperations branchMenuOperations)
{
if (operationToExecute == BranchMenuOperations.Delete)
{
branchMenuOperations.DeleteBranch();
return;
}
}
static BranchMenuOperations GetMenuOperations(Event e)
{
if (Keyboard.IsKeyPressed(e, KeyCode.Delete))
return BranchMenuOperations.Delete;
return BranchMenuOperations.None;
}
void BuildComponents()
{
mCreateBranchMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.BranchMenuItemCreateBranch));
mSwitchToBranchMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.BranchMenuItemSwitchToBranch));
mRenameBranchMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.BranchMenuItemRenameBranch));
mDeleteBranchMenuItemContent = new GUIContent(string.Format("{0} {1}",
PlasticLocalization.GetString(PlasticLocalization.Name.BranchMenuItemDeleteBranch),
GetPlasticShortcut.ForDelete()));
}
GenericMenu mMenu;
GUIContent mCreateBranchMenuItemContent;
GUIContent mSwitchToBranchMenuItemContent;
GUIContent mRenameBranchMenuItemContent;
GUIContent mDeleteBranchMenuItemContent;
readonly IBranchMenuOperations mBranchMenuOperations;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a1f5156c89fd104459e8ec0cc3098899
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,193 @@
using UnityEditor;
using UnityEngine;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.QueryViews.Branches;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
namespace Unity.PlasticSCM.Editor.Views.Branches
{
class CreateBranchDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 710, 290);
}
}
protected override string GetTitle()
{
return PlasticLocalization.GetString(PlasticLocalization.Name.CreateChildBranchTitle);
}
protected override void OnModalGUI()
{
DoTitleArea();
DoFieldsArea();
DoButtonsArea();
}
internal static BranchCreationData CreateBranchFromLastParentBranchChangeset(
EditorWindow parentWindow,
RepositorySpec repSpec,
BranchInfo parentBranchInfo )
{
string changesetStr = PlasticLocalization.GetString(
PlasticLocalization.Name.LastChangeset);
string explanation = BranchCreationUserInfo.GetFromObjectString(
repSpec, parentBranchInfo, changesetStr);
CreateBranchDialog dialog = Create(repSpec, parentBranchInfo, explanation);
ResponseType dialogueResult = dialog.RunModal(parentWindow);
BranchCreationData result = dialog.BuildCreationData();
result.Result = dialogueResult == ResponseType.Ok;
return result;
}
void DoTitleArea()
{
GUILayout.BeginVertical();
Title(PlasticLocalization.GetString(PlasticLocalization.Name.CreateChildBranchTitle));
GUILayout.Space(5);
Paragraph(string.Format("{0} {1}", PlasticLocalization.GetString(
PlasticLocalization.Name.CreateChildBranchExplanation), mExplanation));
GUILayout.EndVertical();
}
void DoFieldsArea()
{
GUILayout.BeginVertical();
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label(
PlasticLocalization.GetString(PlasticLocalization.Name.BranchNameEntry),
GUILayout.Width(100));
GUI.SetNextControlName(NAME_FIELD_CONTROL_NAME);
mNewBranchName = GUILayout.TextField(mNewBranchName);
if (!mWasNameFieldFocused)
{
EditorGUI.FocusTextInControl(NAME_FIELD_CONTROL_NAME);
mWasNameFieldFocused = true;
}
GUILayout.Space(5);
}
GUILayout.Space(5);
using (new EditorGUILayout.HorizontalScope())
{
using (new EditorGUILayout.VerticalScope(GUILayout.Width(100)))
{
GUILayout.Space(49);
GUILayout.Label(
PlasticLocalization.GetString(PlasticLocalization.Name.CommentsEntry),
GUILayout.Width(100));
}
mComment = GUILayout.TextArea(mComment, GUILayout.Height(100));
GUILayout.Space(5);
}
GUILayout.Space(5);
mSwitchToBranch = GUILayout.Toggle(mSwitchToBranch, PlasticLocalization.GetString(PlasticLocalization.Name.SwitchToBranchCheckButton));
GUILayout.Space(5);
GUILayout.EndVertical();
}
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
using (new EditorGUILayout.HorizontalScope(GUILayout.MinWidth(500)))
{
GUILayout.Space(2);
DrawProgressForDialogs.For(
mProgressControls.ProgressData);
GUILayout.Space(2);
}
GUILayout.FlexibleSpace();
DoCreateButton();
DoCancelButton();
}
}
void DoCancelButton()
{
if (NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
{
CancelButtonAction();
}
}
void DoCreateButton()
{
if (!NormalButton(PlasticLocalization.GetString(PlasticLocalization.Name.CreateButton)))
return;
BranchCreationValidation.AsyncValidation(
BuildCreationData(), this, mProgressControls);
}
static CreateBranchDialog Create(RepositorySpec repSpec, BranchInfo parentBranchInfo, string explanation)
{
var instance = CreateInstance<CreateBranchDialog>();
instance.IsResizable = false;
instance.mEscapeKeyAction = instance.CloseButtonAction;
instance.mRepositorySpec = repSpec;
instance.mParentBranchInfo = parentBranchInfo;
instance.mNewBranchName = "";
instance.mComment = "";
instance.mSwitchToBranch = true;
instance.mProgressControls = new ProgressControlsForDialogs();
instance.mExplanation = explanation;
return instance;
}
BranchCreationData BuildCreationData()
{
return new BranchCreationData(
mRepositorySpec,
mParentBranchInfo,
mParentBranchInfo.Changeset,
mNewBranchName,
mComment,
null,
mSwitchToBranch);
}
ProgressControlsForDialogs mProgressControls;
RepositorySpec mRepositorySpec;
BranchInfo mParentBranchInfo;
string mNewBranchName;
string mComment;
bool mSwitchToBranch;
string mExplanation;
bool mWasNameFieldFocused;
const string NAME_FIELD_CONTROL_NAME = "CreateBranchNameField";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0fc5252a48d8b34f945b4ae3ad45030
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 16e16045695760047a9bd172458c5d6b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,164 @@
using UnityEditor;
using UnityEngine;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.QueryViews.Branches;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
namespace Unity.PlasticSCM.Editor.Views.Branches.Dialogs
{
internal class RenameBranchDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 500, 200);
}
}
internal static BranchRenameData GetBranchRenameData(
RepositorySpec repSpec,
BranchInfo branchInfo,
EditorWindow parentWindow)
{
RenameBranchDialog dialog = Create(
repSpec,
branchInfo,
new ProgressControlsForDialogs());
ResponseType dialogResult = dialog.RunModal(parentWindow);
BranchRenameData result = dialog.BuildRenameData();
result.Result = dialogResult == ResponseType.Ok;
return result;
}
static RenameBranchDialog Create(
RepositorySpec repSpec,
BranchInfo branchInfo,
ProgressControlsForDialogs progressControls)
{
var instance = CreateInstance<RenameBranchDialog>();
instance.mRepSpec = repSpec;
instance.mBranchInfo = branchInfo;
instance.mBranchName = BranchRenameUserInfo.GetShortBranchName(branchInfo.BranchName);
instance.mTitle = PlasticLocalization.GetString(
PlasticLocalization.Name.RenameBranchTitle);
instance.mProgressControls = progressControls;
return instance;
}
protected override string GetTitle()
{
return mTitle;
}
protected override void OnModalGUI()
{
Title(mTitle);
GUILayout.Space(10f);
DoInputArea();
GUILayout.Space(10f);
DrawProgressForDialogs.For(mProgressControls.ProgressData);
GUILayout.Space(10f);
DoButtonsArea();
}
void DoInputArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label(
PlasticLocalization.GetString(PlasticLocalization.Name.NewName),
GUILayout.ExpandWidth(false));
GUILayout.Space(10f);
GUI.SetNextControlName(RENAME_BRANCH_TEXTAREA_NAME);
mBranchName = GUILayout.TextField(
mBranchName,
GUILayout.ExpandWidth(true));
if (!mTextAreaFocused)
{
EditorGUI.FocusTextInControl(RENAME_BRANCH_TEXTAREA_NAME);
mTextAreaFocused = true;
}
}
}
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
DoOkButton();
DoCancelButton();
return;
}
DoCancelButton();
DoOkButton();
}
}
void DoOkButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.RenameButton)))
return;
OkButtonWithValidationAction();
}
void DoCancelButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
return;
CancelButtonAction();
}
void OkButtonWithValidationAction()
{
BranchRenameValidation.AsyncValidation(
BuildRenameData(),
this,
mProgressControls);
}
BranchRenameData BuildRenameData()
{
return new BranchRenameData(mRepSpec, mBranchInfo, mBranchName);
}
string mTitle;
string mBranchName;
bool mTextAreaFocused;
RepositorySpec mRepSpec;
BranchInfo mBranchInfo;
ProgressControlsForDialogs mProgressControls;
const string RENAME_BRANCH_TEXTAREA_NAME = "rename_branch_textarea";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1de62e30afcba544e8e8da4b93a4fa39
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a83160f252281df4ebb018688dad5f08
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using UnityEditor.IMGUI.Controls;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
class ChangesetListViewItem : TreeViewItem
{
internal object ObjectInfo { get; private set; }
internal ChangesetListViewItem(int id, object objectInfo)
: base(id, 1)
{
ObjectInfo = objectInfo;
displayName = id.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6000865ce7fbfc643abdd3d085b4422e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
internal enum ChangesetsListColumn
{
Name,
CreationDate,
CreatedBy,
Comment,
Branch,
Repository,
Guid
}
[Serializable]
internal class ChangesetsListHeaderState : MultiColumnHeaderState, ISerializationCallbackReceiver
{
internal static ChangesetsListHeaderState GetDefault()
{
return new ChangesetsListHeaderState(BuildColumns());
}
internal static List<string> GetColumnNames()
{
List<string> result = new List<string>();
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.NameColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CreationDateColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CreatedByColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CommentColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.BranchColumn));
return result;
}
internal static string GetColumnName(ChangesetsListColumn column)
{
switch (column)
{
case ChangesetsListColumn.Name:
return PlasticLocalization.GetString(PlasticLocalization.Name.NameColumn);
case ChangesetsListColumn.CreationDate:
return PlasticLocalization.GetString(PlasticLocalization.Name.CreationDateColumn);
case ChangesetsListColumn.CreatedBy:
return PlasticLocalization.GetString(PlasticLocalization.Name.CreatedByColumn);
case ChangesetsListColumn.Comment:
return PlasticLocalization.GetString(PlasticLocalization.Name.CommentColumn);
case ChangesetsListColumn.Branch:
return PlasticLocalization.GetString(PlasticLocalization.Name.BranchColumn);
default:
return null;
}
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (mHeaderTitles != null)
TreeHeaderColumns.SetTitles(columns, mHeaderTitles);
if (mColumsAllowedToggleVisibility != null)
TreeHeaderColumns.SetVisibilities(columns, mColumsAllowedToggleVisibility);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
static Column[] BuildColumns()
{
return new Column[]
{
new Column()
{
width = UnityConstants.ChangesetsColumns.CHANGESET_NUMBER_WIDTH,
minWidth = UnityConstants.ChangesetsColumns.CHANGESET_NUMBER_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(ChangesetsListColumn.Name)),
allowToggleVisibility = false,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.ChangesetsColumns.CREATION_DATE_WIDTH,
minWidth = UnityConstants.ChangesetsColumns.CREATION_DATE_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(ChangesetsListColumn.CreationDate)),
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.ChangesetsColumns.CREATED_BY_WIDTH,
minWidth = UnityConstants.ChangesetsColumns.CREATED_BY_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(ChangesetsListColumn.CreatedBy)),
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.ChangesetsColumns.COMMENT_WIDTH,
minWidth = UnityConstants.ChangesetsColumns.COMMENT_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(ChangesetsListColumn.Comment)),
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = UnityConstants.ChangesetsColumns.BRANCH_WIDTH,
minWidth = UnityConstants.ChangesetsColumns.BRANCH_MIN_WIDTH,
headerContent = new GUIContent(
GetColumnName(ChangesetsListColumn.Branch)),
sortingArrowAlignment = TextAlignment.Right
}
};
}
ChangesetsListHeaderState(Column[] columns)
: base(columns)
{
if (mHeaderTitles == null)
mHeaderTitles = TreeHeaderColumns.GetTitles(columns);
if (mColumsAllowedToggleVisibility == null)
mColumsAllowedToggleVisibility = TreeHeaderColumns.GetVisibilities(columns);
}
[SerializeField]
string[] mHeaderTitles;
[SerializeField]
bool[] mColumsAllowedToggleVisibility;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ff9581aa143f4d41b4e351881b8f459
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,450 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.QueryViews;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Avatar;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
internal class ChangesetsListView : TreeView
{
internal GenericMenu Menu { get { return mMenu.Menu; } }
internal ChangesetsListView(
ChangesetsListHeaderState headerState,
List<string> columnNames,
ChangesetsViewMenu menu,
Action sizeChangedAction,
Action selectionChangedAction,
Action doubleClickAction)
: base(new TreeViewState())
{
mColumnNames = columnNames;
mMenu = menu;
mSizeChangedAction = sizeChangedAction;
mSelectionChangedAction = selectionChangedAction;
mDoubleClickAction = doubleClickAction;
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.canSort = true;
multiColumnHeader.sortingChanged += SortingChanged;
rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
showAlternatingRowBackgrounds = false;
mCooldownFilterAction = new CooldownWindowDelayer(
DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
mCooldownSelectionAction = new CooldownWindowDelayer(
DelayedSelectionChanged, UnityConstants.SELECTION_DELAYED_INPUT_ACTION_INTERVAL);
}
protected override void SelectionChanged(IList<int> selectedIds)
{
mCooldownSelectionAction.Ping();
}
public override IList<TreeViewItem> GetRows()
{
return mRows;
}
internal void SetLoadedChangesetId(long loadedChangesetId)
{
mLoadedChangesetId = loadedChangesetId;
}
protected override TreeViewItem BuildRoot()
{
return new TreeViewItem(0, -1, string.Empty);
}
protected override IList<TreeViewItem> BuildRows(
TreeViewItem rootItem)
{
if (mQueryResult == null)
{
ClearRows(rootItem, mRows);
return mRows;
}
RegenerateRows(
mListViewItemIds,
mQueryResult.GetObjects(),
rootItem, mRows);
return mRows;
}
protected override void SearchChanged(string newSearch)
{
mCooldownFilterAction.Ping();
}
protected override void ContextClickedItem(int id)
{
mMenu.Popup();
Repaint();
}
public override void OnGUI(Rect rect)
{
if (Event.current.type == EventType.Layout)
{
if (IsSizeChanged(treeViewRect, mLastRect))
mSizeChangedAction();
}
mLastRect = treeViewRect;
base.OnGUI(rect);
Event e = Event.current;
if (e.type != EventType.KeyDown)
return;
bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
if (isProcessed)
e.Use();
}
protected override void BeforeRowsGUI()
{
int firstRowVisible;
int lastRowVisible;
GetFirstAndLastVisibleRows(out firstRowVisible, out lastRowVisible);
GUI.DrawTexture(new Rect(0,
firstRowVisible * rowHeight,
GetRowRect(0).width,
(lastRowVisible * rowHeight) + 1000),
Images.GetTreeviewBackgroundTexture());
DrawTreeViewItem.InitializeStyles();
base.BeforeRowsGUI();
}
protected override void RowGUI(RowGUIArgs args)
{
if (args.item is ChangesetListViewItem)
{
ChangesetListViewItem changesetListViewItem = (ChangesetListViewItem)args.item;
ChangesetInfo changesetInfo = (ChangesetInfo)changesetListViewItem.ObjectInfo;
ChangesetsListViewItemGUI(
mQueryResult,
rowHeight,
changesetListViewItem,
args,
changesetInfo.ChangesetId == mLoadedChangesetId,
Repaint);
return;
}
base.RowGUI(args);
}
protected override void DoubleClickedItem(int id)
{
if (!HasSelection())
return;
mDoubleClickAction();
}
internal void BuildModel(
ViewQueryResult queryResult,
long loadedChangesetId)
{
mListViewItemIds.Clear();
mQueryResult = queryResult;
mLoadedChangesetId = loadedChangesetId;
}
internal void Refilter()
{
if (mQueryResult == null)
return;
Filter filter = new Filter(searchString);
mQueryResult.ApplyFilter(filter, mColumnNames);
}
internal void Sort()
{
if (mQueryResult == null)
return;
int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
mQueryResult.Sort(
mColumnNames[sortedColumnIdx],
sortAscending);
}
internal List<RepositorySpec> GetSelectedRepositories()
{
List<RepositorySpec> result = new List<RepositorySpec>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<object, int> item
in mListViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
RepositorySpec repSpec =
mQueryResult.GetRepositorySpec(item.Key);
result.Add(repSpec);
}
return result;
}
internal List<RepObjectInfo> GetSelectedRepObjectInfos()
{
List<RepObjectInfo> result = new List<RepObjectInfo>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<object, int> item
in mListViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
RepObjectInfo repObjectInfo =
mQueryResult.GetRepObjectInfo(item.Key);
result.Add(repObjectInfo);
}
return result;
}
internal void SelectRepObjectInfos(
List<RepObjectInfo> repObjectsToSelect)
{
List<int> idsToSelect = new List<int>();
foreach (RepObjectInfo repObjectInfo in repObjectsToSelect)
{
int repObjectInfoId = GetTreeIdForItem(repObjectInfo);
if (repObjectInfoId == -1)
continue;
idsToSelect.Add(repObjectInfoId);
}
TableViewOperations.SetSelectionAndScroll(this, idsToSelect);
}
int GetTreeIdForItem(RepObjectInfo repObjectInfo)
{
foreach (KeyValuePair<object, int> item in mListViewItemIds.GetInfoItems())
{
RepObjectInfo currentRepObjectInfo =
mQueryResult.GetRepObjectInfo(item.Key);
if (!currentRepObjectInfo.Equals(repObjectInfo))
continue;
if (!currentRepObjectInfo.GUID.Equals(repObjectInfo.GUID))
continue;
return item.Value;
}
return -1;
}
void DelayedSearchChanged()
{
Refilter();
Sort();
Reload();
TableViewOperations.ScrollToSelection(this);
}
void DelayedSelectionChanged()
{
if (!HasSelection())
return;
mSelectionChangedAction();
}
void SortingChanged(MultiColumnHeader multiColumnHeader)
{
Sort();
Reload();
}
static void RegenerateRows(
ListViewItemIds<object> listViewItemIds,
List<object> objectInfos,
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
ClearRows(rootItem, rows);
if (objectInfos.Count == 0)
return;
foreach (object objectInfo in objectInfos)
{
int objectId;
if (!listViewItemIds.TryGetInfoItemId(objectInfo, out objectId))
objectId = listViewItemIds.AddInfoItem(objectInfo);
ChangesetListViewItem changesetListViewItem =
new ChangesetListViewItem(objectId, objectInfo);
rootItem.AddChild(changesetListViewItem);
rows.Add(changesetListViewItem);
}
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static void ChangesetsListViewItemGUI(
ViewQueryResult queryResult,
float rowHeight,
ChangesetListViewItem 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;
}
ChangesetsListColumn column =
(ChangesetsListColumn)args.GetColumn(visibleColumnIdx);
ChangesetsListViewItemCellGUI(
cellRect,
rowHeight,
queryResult,
item,
column,
avatarLoadedAction,
args.selected,
args.focused,
isBoldText);
}
}
static void ChangesetsListViewItemCellGUI(
Rect rect,
float rowHeight,
ViewQueryResult queryResult,
ChangesetListViewItem item,
ChangesetsListColumn column,
Action avatarLoadedAction,
bool isSelected,
bool isFocused,
bool isBoldText)
{
string columnText = RepObjectInfoView.GetColumnText(
queryResult.GetRepositorySpec(item.ObjectInfo),
queryResult.GetRepObjectInfo(item.ObjectInfo),
ChangesetsListHeaderState.GetColumnName(column));
if (column == ChangesetsListColumn.CreatedBy)
{
DrawTreeViewItem.ForItemCell(
rect,
rowHeight,
-1,
GetAvatar.ForEmail(columnText, avatarLoadedAction),
null,
columnText,
isSelected,
isFocused,
isBoldText,
false);
return;
}
if (column == ChangesetsListColumn.Branch ||
column == ChangesetsListColumn.Repository ||
column == ChangesetsListColumn.Guid)
{
DrawTreeViewItem.ForSecondaryLabel(
rect, columnText, isSelected, isFocused, isBoldText);
return;
}
DrawTreeViewItem.ForLabel(
rect, columnText, isSelected, isFocused, isBoldText);
}
static bool IsSizeChanged(
Rect currentRect, Rect lastRect)
{
if (currentRect.width != lastRect.width)
return true;
if (currentRect.height != lastRect.height)
return true;
return false;
}
Rect mLastRect;
ListViewItemIds<object> mListViewItemIds = new ListViewItemIds<object>();
List<TreeViewItem> mRows = new List<TreeViewItem>();
ViewQueryResult mQueryResult;
long mLoadedChangesetId;
readonly CooldownWindowDelayer mCooldownFilterAction;
readonly CooldownWindowDelayer mCooldownSelectionAction;
readonly Action mDoubleClickAction;
readonly Action mSelectionChangedAction;
readonly Action mSizeChangedAction;
readonly ChangesetsViewMenu mMenu;
readonly List<string> mColumnNames;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59e682a8b37338a46910fa9a939425e3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
using System.Collections.Generic;
using Codice.CM.Common;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
internal static class ChangesetsSelection
{
internal static void SelectChangesets(
ChangesetsListView listView,
List<RepObjectInfo> csetsToSelect,
int defaultRow)
{
if (csetsToSelect == null || csetsToSelect.Count == 0)
{
TableViewOperations.SelectFirstRow(listView);
return;
}
listView.SelectRepObjectInfos(csetsToSelect);
if (listView.HasSelection())
return;
TableViewOperations.SelectDefaultRow(listView, defaultRow);
if (listView.HasSelection())
return;
TableViewOperations.SelectFirstRow(listView);
}
internal static List<RepObjectInfo> GetSelectedRepObjectInfos(
ChangesetsListView listView)
{
return listView.GetSelectedRepObjectInfos();
}
internal static int GetSelectedChangesetsCount(
ChangesetsListView listView)
{
return listView.GetSelection().Count;
}
internal static ChangesetExtendedInfo GetSelectedChangeset(
ChangesetsListView listView)
{
List<RepObjectInfo> selectedRepObjectsInfos = listView.GetSelectedRepObjectInfos();
if (selectedRepObjectsInfos.Count == 0)
return null;
return (ChangesetExtendedInfo)selectedRepObjectsInfos[0];
}
internal static RepositorySpec GetSelectedRepository(
ChangesetsListView listView)
{
List<RepositorySpec> selectedRepositories = listView.GetSelectedRepositories();
if (selectedRepositories.Count == 0)
return null;
return selectedRepositories[0];
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 20341761c2011b441b2a3af227beeb71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,651 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.Client.Commands;
using Codice.Client.Common;
using Codice.Client.Common.EventTracking;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.Update;
using PlasticGui.WorkspaceWindow.QueryViews;
using PlasticGui.WorkspaceWindow.QueryViews.Changesets;
using GluonGui;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.UI.Tree;
using Unity.PlasticSCM.Editor.Tool;
using Unity.PlasticSCM.Editor.Views.Diff;
using IGluonUpdateReport = PlasticGui.Gluon.IUpdateReport;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
internal partial class ChangesetsTab :
IRefreshableView,
IQueryRefreshableView,
IChangesetMenuOperations,
ChangesetsViewMenu.IMenuOperations
{
internal ChangesetsListView Table { get { return mChangesetsListView; } }
internal IChangesetMenuOperations Operations { get { return this; } }
internal interface IRevertToChangesetListener
{
void OnSuccessOperation();
}
internal ChangesetsTab(
WorkspaceInfo wkInfo,
WorkspaceWindow workspaceWindow,
IViewSwitcher viewSwitcher,
IMergeViewLauncher mergeViewLauncher,
IHistoryViewLauncher historyViewLauncher,
ViewHost viewHost,
IUpdateReport updateReport,
IGluonUpdateReport gluonUpdateReport,
NewIncomingChangesUpdater newIncomingChangesUpdater,
IRevertToChangesetListener revertToChangesetListener,
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor,
EditorWindow parentWindow,
bool isGluonMode)
{
mWkInfo = wkInfo;
mViewHost = viewHost;
mWorkspaceWindow = workspaceWindow;
mViewSwitcher = viewSwitcher;
mRevertToChangesetListener = revertToChangesetListener;
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mProcessExecutor = processExecutor;
mParentWindow = parentWindow;
mIsGluonMode = isGluonMode;
mGluonUpdateReport = gluonUpdateReport;
BuildComponents(
wkInfo,
workspaceWindow,
workspaceWindow,
viewSwitcher,
historyViewLauncher,
parentWindow);
mProgressControls = new ProgressControlsForViews();
mSplitterState = PlasticSplitterGUILayout.InitSplitterState(
new float[] { 0.50f, 0.50f },
new int[] { 100, (int)UnityConstants.DIFF_PANEL_MIN_WIDTH },
new int[] { 100000, 100000 }
);
mBorderColor = EditorGUIUtility.isProSkin
? (Color)new Color32(35, 35, 35, 255)
: (Color)new Color32(153, 153, 153, 255);
mChangesetOperations = new ChangesetOperations(
wkInfo,
workspaceWindow,
viewSwitcher,
mergeViewLauncher,
this,
ViewType.ChangesetsView,
mProgressControls,
updateReport,
new ContinueWithPendingChangesQuestionerBuilder(viewSwitcher, parentWindow),
newIncomingChangesUpdater,
null,
null);
((IRefreshableView)this).Refresh();
}
internal void OnDisable()
{
mDiffPanel.OnDisable();
mSearchField.downOrUpArrowKeyPressed -=
SearchField_OnDownOrUpArrowKeyPressed;
TreeHeaderSettings.Save(
mChangesetsListView.multiColumnHeader.state,
UnityConstants.CHANGESETS_TABLE_SETTINGS_NAME);
}
internal void Update()
{
mDiffPanel.Update();
mProgressControls.UpdateProgress(mParentWindow);
}
internal void OnGUI()
{
InitializeShowChangesButtonWidth();
DoActionsToolbar(
this,
mProgressControls,
mSearchField,
mChangesetsListView,
mDateFilter);
PlasticSplitterGUILayout.BeginHorizontalSplit(mSplitterState);
DoChangesetsArea(
mChangesetsListView,
mProgressControls.IsOperationRunning());
EditorGUILayout.BeginHorizontal();
Rect border = GUILayoutUtility.GetRect(1, 0, 1, 100000);
EditorGUI.DrawRect(border, mBorderColor);
DoChangesArea(mDiffPanel);
EditorGUILayout.EndHorizontal();
PlasticSplitterGUILayout.EndHorizontalSplit();
}
internal void DrawSearchFieldForChangesetsTab()
{
DrawSearchField.For(
mSearchField,
mChangesetsListView,
UnityConstants.SEARCH_FIELD_WIDTH);
VerifyIfSearchFieldIsRecentlyFocused(mSearchField);
}
internal void SetWorkingObjectInfo(WorkingObjectInfo homeInfo)
{
if (mIsGluonMode)
return;
lock (mLock)
{
mLoadedChangesetId = homeInfo.GetChangesetId();
}
mChangesetsListView.SetLoadedChangesetId(mLoadedChangesetId);
mChangesetsViewMenu.SetLoadedBranchId(homeInfo.BranchInfo.BranchId);
}
internal void SetRevertToChangesetOperationInterfacesForTesting(
RevertToChangesetOperation.IGetStatusForWorkspace getStatusForWorkspace,
RevertToChangesetOperation.IUndoCheckoutOperation undoCheckoutOperation,
RevertToChangesetOperation.IRevertToChangesetMergeController revertToChangesetMergeController)
{
mGetStatusForWorkspace = getStatusForWorkspace;
mUndoCheckoutOperation = undoCheckoutOperation;
mRevertToChangesetMergeController = revertToChangesetMergeController;
}
internal void SetLaunchToolForTesting(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor)
{
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mProcessExecutor = processExecutor;
}
void IRefreshableView.Refresh()
{
string query = GetChangesetsQuery(mDateFilter);
FillChangesets(
mWkInfo,
query,
ChangesetsSelection.GetSelectedRepObjectInfos(mChangesetsListView));
}
void IQueryRefreshableView.RefreshAndSelect(RepObjectInfo repObj)
{
string query = GetChangesetsQuery(mDateFilter);
FillChangesets(
mWkInfo,
query,
new List<RepObjectInfo> { repObj });
}
int IChangesetMenuOperations.GetSelectedChangesetsCount()
{
return ChangesetsSelection.GetSelectedChangesetsCount(mChangesetsListView);
}
void IChangesetMenuOperations.DiffChangeset()
{
LaunchDiffOperations.DiffChangeset(
mShowDownloadPlasticExeWindow,
mProcessExecutor,
ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
mIsGluonMode);
}
void IChangesetMenuOperations.DiffSelectedChangesets()
{
List<RepObjectInfo> selectedChangesets = ChangesetsSelection.
GetSelectedRepObjectInfos(mChangesetsListView);
if (selectedChangesets.Count < 2)
return;
LaunchDiffOperations.DiffSelectedChangesets(
mShowDownloadPlasticExeWindow,
mProcessExecutor,
ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
(ChangesetExtendedInfo)selectedChangesets[0],
(ChangesetExtendedInfo)selectedChangesets[1],
mIsGluonMode);
}
void IChangesetMenuOperations.SwitchToChangeset()
{
SwitchToChangesetForMode(mIsGluonMode);
}
void IChangesetMenuOperations.DiffWithAnotherChangeset() { }
void IChangesetMenuOperations.CreateBranch() { }
void IChangesetMenuOperations.LabelChangeset() { }
void IChangesetMenuOperations.MergeChangeset() {}
void IChangesetMenuOperations.CherryPickChangeset() { }
void IChangesetMenuOperations.SubtractiveChangeset() { }
void IChangesetMenuOperations.SubtractiveChangesetInterval() { }
void IChangesetMenuOperations.CherryPickChangesetInterval() { }
void IChangesetMenuOperations.MergeToChangeset() { }
void IChangesetMenuOperations.MoveChangeset() { }
void IChangesetMenuOperations.DeleteChangeset() { }
void IChangesetMenuOperations.BrowseRepositoryOnChangeset() { }
void IChangesetMenuOperations.CreateCodeReview() { }
void IChangesetMenuOperations.RevertToChangeset()
{
if (((IChangesetMenuOperations)this).GetSelectedChangesetsCount() != 1)
return;
ChangesetExtendedInfo targetChangesetInfo = ((ChangesetsViewMenu.IMenuOperations)this).GetSelectedChangeset();
RevertToChangesetOperation.RevertTo(
mWkInfo,
mViewSwitcher,
mWorkspaceWindow,
mProgressControls,
mGetStatusForWorkspace,
mUndoCheckoutOperation,
mRevertToChangesetMergeController,
GuiMessage.Get(),
targetChangesetInfo,
RefreshAsset.BeforeLongAssetOperation,
RefreshAsset.AfterLongAssetOperation,
mRevertToChangesetListener.OnSuccessOperation);
}
void SearchField_OnDownOrUpArrowKeyPressed()
{
mChangesetsListView.SetFocusAndEnsureSelectedItem();
}
void FillChangesets(WorkspaceInfo wkInfo, string query, List<RepObjectInfo> changesetsToSelect)
{
if (mIsRefreshing)
return;
mIsRefreshing = true;
int defaultRow = TableViewOperations.
GetFirstSelectedRow(mChangesetsListView);
((IProgressControls)mProgressControls).ShowProgress(
PlasticLocalization.GetString(
PlasticLocalization.Name.LoadingChangesets));
ViewQueryResult queryResult = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter();
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
long loadedChangesetId = GetLoadedChangesetId(
wkInfo, mIsGluonMode);
long loadedBranchId = GetLoadedBranchId(
wkInfo, loadedChangesetId, mIsGluonMode);
lock (mLock)
{
mLoadedChangesetId = loadedChangesetId;
}
mChangesetsViewMenu.SetLoadedBranchId(loadedBranchId);
queryResult = new ViewQueryResult(
PlasticGui.Plastic.API.FindQuery(wkInfo, query));
},
/*afterOperationDelegate*/ delegate
{
try
{
if (waiter.Exception != null)
{
ExceptionsHandler.DisplayException(waiter.Exception);
return;
}
UpdateChangesetsList(
mChangesetsListView,
queryResult,
mLoadedChangesetId);
int changesetsCount = GetChangesetsCount(queryResult);
if (changesetsCount == 0)
{
mDiffPanel.ClearInfo();
return;
}
ChangesetsSelection.SelectChangesets(
mChangesetsListView, changesetsToSelect, defaultRow);
}
finally
{
((IProgressControls)mProgressControls).HideProgress();
mIsRefreshing = false;
}
});
}
void ChangesetsViewMenu.IMenuOperations.DiffBranch()
{
LaunchDiffOperations.DiffBranch(
mShowDownloadPlasticExeWindow,
mProcessExecutor,
ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
mIsGluonMode);
}
ChangesetExtendedInfo ChangesetsViewMenu.IMenuOperations.GetSelectedChangeset()
{
return ChangesetsSelection.GetSelectedChangeset(
mChangesetsListView);
}
void OnChangesetsListViewSizeChanged()
{
if (!mShouldScrollToSelection)
return;
mShouldScrollToSelection = false;
TableViewOperations.ScrollToSelection(mChangesetsListView);
}
void OnSelectionChanged()
{
List<RepObjectInfo> selectedChangesets = ChangesetsSelection.
GetSelectedRepObjectInfos(mChangesetsListView);
if (selectedChangesets.Count != 1)
return;
mDiffPanel.UpdateInfo(
MountPointWithPath.BuildWorkspaceRootMountPoint(
ChangesetsSelection.GetSelectedRepository(mChangesetsListView)),
(ChangesetExtendedInfo)selectedChangesets[0]);
}
static void UpdateChangesetsList(
ChangesetsListView changesetsListView,
ViewQueryResult queryResult,
long loadedChangesetId)
{
changesetsListView.BuildModel(
queryResult,
loadedChangesetId);
changesetsListView.Refilter();
changesetsListView.Sort();
changesetsListView.Reload();
}
static long GetLoadedChangesetId(
WorkspaceInfo wkInfo,
bool isGluonMode)
{
if (isGluonMode)
return -1;
return PlasticGui.Plastic.API.GetLoadedChangeset(wkInfo);
}
static long GetLoadedBranchId(
WorkspaceInfo wkInfo,
long loadedChangesetId,
bool isGluonMode)
{
if (isGluonMode)
return -1;
return PlasticGui.Plastic.API.GetChangesetInfoFromId(
wkInfo, loadedChangesetId).BranchId;
}
static string GetChangesetsQuery(DateFilter dateFilter)
{
if (dateFilter.FilterType == DateFilter.Type.AllTime)
return QueryConstants.ChangesetsBeginningQuery;
string whereClause = QueryConstants.GetDateWhereClause(
dateFilter.GetTimeAgo());
return string.Format("{0} {1}",
QueryConstants.ChangesetsBeginningQuery,
whereClause);
}
static int GetChangesetsCount(
ViewQueryResult queryResult)
{
if (queryResult == null)
return 0;
return queryResult.Count();
}
void VerifyIfSearchFieldIsRecentlyFocused(SearchField searchField)
{
if (searchField.HasFocus() != mIsSearchFieldFocused)
{
mIsSearchFieldFocused = !mIsSearchFieldFocused;
if (mIsSearchFieldFocused)
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.ChangesetsViewChangesetsSearchBox);
}
}
}
void DoActionsToolbar(
IRefreshableView refreshableView,
ProgressControlsForViews progressControls,
SearchField searchField,
ChangesetsListView changesetsListView,
DateFilter dateFilter)
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
if (progressControls.IsOperationRunning())
{
DrawProgressForViews.ForIndeterminateProgress(
progressControls.ProgressData);
}
GUILayout.FlexibleSpace();
GUILayout.Space(2);
EditorGUILayout.EndHorizontal();
}
static void DoChangesetsArea(
ChangesetsListView changesetsListView,
bool isOperationRunning)
{
EditorGUILayout.BeginVertical();
GUI.enabled = !isOperationRunning;
Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
changesetsListView.OnGUI(rect);
GUI.enabled = true;
EditorGUILayout.EndVertical();
}
static void DoChangesArea(DiffPanel diffPanel)
{
EditorGUILayout.BeginVertical();
diffPanel.OnGUI();
EditorGUILayout.EndVertical();
}
internal void DrawDateFilter()
{
GUI.enabled = !mProgressControls.IsOperationRunning();
EditorGUI.BeginChangeCheck();
mDateFilter.FilterType = (DateFilter.Type)
EditorGUILayout.EnumPopup(
mDateFilter.FilterType,
EditorStyles.toolbarDropDown,
GUILayout.Width(100));
if (EditorGUI.EndChangeCheck())
{
EnumPopupSetting<DateFilter.Type>.Save(
mDateFilter.FilterType,
UnityConstants.CHANGESETS_DATE_FILTER_SETTING_NAME);
((IRefreshableView)this).Refresh();
}
GUI.enabled = true;
}
void InitializeShowChangesButtonWidth()
{
if (mShowChangesButtonWidth != -1)
return;
mShowChangesButtonWidth = MeasureMaxWidth.ForTexts(
EditorStyles.toolbarButton,
PlasticLocalization.GetString(PlasticLocalization.Name.HideChanges),
PlasticLocalization.GetString(PlasticLocalization.Name.ShowChanges));
}
void BuildComponents(
WorkspaceInfo wkInfo,
IWorkspaceWindow workspaceWindow,
IRefreshView refreshView,
IViewSwitcher viewSwitcher,
IHistoryViewLauncher historyViewLauncher,
EditorWindow parentWindow)
{
mSearchField = new SearchField();
mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
DateFilter.Type dateFilterType =
EnumPopupSetting<DateFilter.Type>.Load(
UnityConstants.CHANGESETS_DATE_FILTER_SETTING_NAME,
DateFilter.Type.LastMonth);
mDateFilter = new DateFilter(dateFilterType);
ChangesetsListHeaderState headerState =
ChangesetsListHeaderState.GetDefault();
TreeHeaderSettings.Load(headerState,
UnityConstants.CHANGESETS_TABLE_SETTINGS_NAME,
(int)ChangesetsListColumn.CreationDate, false);
mChangesetsViewMenu = new ChangesetsViewMenu(
wkInfo,
this,
this,
mShowDownloadPlasticExeWindow,
mIsGluonMode);
mChangesetsListView = new ChangesetsListView(
headerState,
ChangesetsListHeaderState.GetColumnNames(),
mChangesetsViewMenu,
sizeChangedAction: OnChangesetsListViewSizeChanged,
selectionChangedAction: OnSelectionChanged,
doubleClickAction: ((IChangesetMenuOperations)this).DiffChangeset);
mChangesetsListView.Reload();
mDiffPanel = new DiffPanel(
wkInfo, workspaceWindow, refreshView, viewSwitcher,
historyViewLauncher, mShowDownloadPlasticExeWindow,
parentWindow, mIsGluonMode);
}
bool mIsRefreshing;
bool mShouldScrollToSelection;
float mShowChangesButtonWidth = -1;
object mSplitterState;
Color mBorderColor;
DateFilter mDateFilter;
SearchField mSearchField;
bool mIsSearchFieldFocused = false;
ChangesetsListView mChangesetsListView;
ChangesetOperations mChangesetOperations;
DiffPanel mDiffPanel;
ChangesetsViewMenu mChangesetsViewMenu;
RevertToChangesetOperation.IGetStatusForWorkspace mGetStatusForWorkspace =
new RevertToChangesetOperation.GetStatusFromWorkspace();
RevertToChangesetOperation.IUndoCheckoutOperation mUndoCheckoutOperation =
new RevertToChangesetOperation.UndoCheckout();
RevertToChangesetOperation.IRevertToChangesetMergeController mRevertToChangesetMergeController =
new RevertToChangesetOperation.RevertToChangesetMergeController();
long mLoadedChangesetId = -1;
object mLock = new object();
LaunchTool.IProcessExecutor mProcessExecutor;
LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
readonly bool mIsGluonMode;
readonly ViewHost mViewHost;
readonly IGluonUpdateReport mGluonUpdateReport;
readonly WorkspaceWindow mWorkspaceWindow;
readonly IViewSwitcher mViewSwitcher;
readonly ProgressControlsForViews mProgressControls;
readonly IRevertToChangesetListener mRevertToChangesetListener;
readonly EditorWindow mParentWindow;
readonly WorkspaceInfo mWkInfo;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 471badd5c87fb154885f11cdf1b49a00
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using UnityEditor;
using Codice.CM.Common;
using GluonGui.WorkspaceWindow.Views.WorkspaceExplorer.Explorer;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
internal partial class ChangesetsTab
{
void SwitchToChangesetForMode(bool isGluonMode)
{
if (isGluonMode)
{
SwitchToChangesetForGluon();
return;
}
SwitchToChangesetForDeveloper();
}
void SwitchToChangesetForDeveloper()
{
mChangesetOperations.SwitchToChangeset(
ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
RefreshAsset.BeforeLongAssetOperation,
RefreshAsset.AfterLongAssetOperation);
}
void SwitchToChangesetForGluon()
{
ChangesetExtendedInfo csetInfo = ChangesetsSelection.GetSelectedChangeset(mChangesetsListView);
SwitchToUIOperation.SwitchToChangeset(
mWkInfo,
csetInfo.BranchName,
csetInfo.ChangesetId,
mViewHost,
null,
new UnityPlasticGuiMessage(),
mProgressControls,
mWorkspaceWindow.GluonProgressOperationHandler,
mGluonUpdateReport,
mWorkspaceWindow,
RefreshAsset.BeforeLongAssetOperation,
RefreshAsset.AfterLongAssetOperation);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06e8f2c592322e640ae99a833427b552
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,369 @@
using UnityEditor;
using UnityEngine;
using Codice.Client.Common.EventTracking;
using Codice.CM.Common;
using PlasticGui.WorkspaceWindow.QueryViews.Changesets;
using PlasticGui;
using Unity.PlasticSCM.Editor.Tool;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
internal class ChangesetsViewMenu
{
internal GenericMenu Menu { get { return mMenu; } }
public interface IMenuOperations
{
void DiffBranch();
ChangesetExtendedInfo GetSelectedChangeset();
}
internal ChangesetsViewMenu(
WorkspaceInfo wkInfo,
IChangesetMenuOperations changesetMenuOperations,
IMenuOperations menuOperations,
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
bool isGluonMode)
{
mWkInfo = wkInfo;
mChangesetMenuOperations = changesetMenuOperations;
mMenuOperations = menuOperations;
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mIsGluonMode = isGluonMode;
BuildComponents();
}
internal void Popup()
{
mMenu = new GenericMenu();
UpdateMenuItems(mMenu);
mMenu.ShowAsContext();
}
internal bool ProcessKeyActionIfNeeded(Event e)
{
int selectedChangesetsCount = mChangesetMenuOperations.GetSelectedChangesetsCount();
ChangesetMenuOperations operationToExecute = GetMenuOperations(
e, selectedChangesetsCount > 1);
if (operationToExecute == ChangesetMenuOperations.None)
return false;
ChangesetMenuOperations operations = ChangesetMenuUpdater.GetAvailableMenuOperations(
selectedChangesetsCount,
mIsGluonMode,
mMenuOperations.GetSelectedChangeset().BranchId,
mLoadedBranchId,
false);
if (!operations.HasFlag(operationToExecute))
return false;
ProcessMenuOperation(operationToExecute, mChangesetMenuOperations);
return true;
}
internal void SetLoadedBranchId(long loadedBranchId)
{
mLoadedBranchId = loadedBranchId;
}
void DiffChangesetMenuItem_Click()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffChangeset,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffChangeset,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffChangeset))
return;
mChangesetMenuOperations.DiffChangeset();
}
void DiffSelectedChangesetsMenuItem_Click()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffSelectedChangesets,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffSelectedChangesets,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffSelectedChangesets))
return;
mChangesetMenuOperations.DiffSelectedChangesets();
}
void RevertToChangesetMenuItem_Click()
{
mChangesetMenuOperations.RevertToChangeset();
}
void DiffBranchMenuItem_Click()
{
mMenuOperations.DiffBranch();
}
void SwitchToChangesetMenuItem_Click()
{
mChangesetMenuOperations.SwitchToChangeset();
}
internal void UpdateMenuItems(GenericMenu menu)
{
ChangesetExtendedInfo singleSelectedChangeset = mMenuOperations.GetSelectedChangeset();
ChangesetMenuOperations operations = ChangesetMenuUpdater.GetAvailableMenuOperations(
mChangesetMenuOperations.GetSelectedChangesetsCount(),
mIsGluonMode,
singleSelectedChangeset.BranchId,
mLoadedBranchId,
false);
AddDiffChangesetMenuItem(
mDiffChangesetMenuItemContent,
menu,
singleSelectedChangeset,
operations,
DiffChangesetMenuItem_Click);
AddDiffSelectedChangesetsMenuItem(
mDiffSelectedChangesetsMenuItemContent,
menu,
operations,
DiffSelectedChangesetsMenuItem_Click);
if (!IsOnMainBranch(singleSelectedChangeset))
{
menu.AddSeparator(string.Empty);
AddDiffBranchMenuItem(
mDiffBranchMenuItemContent,
menu,
singleSelectedChangeset,
operations,
DiffBranchMenuItem_Click);
}
menu.AddSeparator(string.Empty);
AddSwitchToChangesetMenuItem(
mSwitchToChangesetMenuItemContent,
menu,
operations,
SwitchToChangesetMenuItem_Click);
if (mIsGluonMode)
return;
AddBackToMenuItem(
mRevertToChangesetMenuItemContent,
menu,
operations,
RevertToChangesetMenuItem_Click);
}
void ProcessMenuOperation(
ChangesetMenuOperations operationToExecute,
IChangesetMenuOperations changesetMenuOperations)
{
if (operationToExecute == ChangesetMenuOperations.DiffChangeset)
{
DiffChangesetMenuItem_Click();
return;
}
if (operationToExecute == ChangesetMenuOperations.DiffSelectedChangesets)
{
DiffSelectedChangesetsMenuItem_Click();
return;
}
}
static void AddDiffChangesetMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
ChangesetExtendedInfo changeset,
ChangesetMenuOperations operations,
GenericMenu.MenuFunction menuFunction)
{
string changesetName =
changeset != null ?
changeset.ChangesetId.ToString() :
string.Empty;
menuItemContent.text = string.Format("{0} {1}",
PlasticLocalization.GetString(
PlasticLocalization.Name.AnnotateDiffChangesetMenuItem,
changesetName),
GetPlasticShortcut.ForDiff());
if (operations.HasFlag(ChangesetMenuOperations.DiffChangeset))
{
menu.AddItem(
menuItemContent,
false,
menuFunction);
return;
}
menu.AddDisabledItem(
menuItemContent);
}
static void AddDiffSelectedChangesetsMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
ChangesetMenuOperations operations,
GenericMenu.MenuFunction menuFunction)
{
if (operations.HasFlag(ChangesetMenuOperations.DiffSelectedChangesets))
{
menu.AddItem(
menuItemContent,
false,
menuFunction);
return;
}
menu.AddDisabledItem(menuItemContent);
}
static void AddBackToMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
ChangesetMenuOperations operations,
GenericMenu.MenuFunction menuFunction)
{
if (operations.HasFlag(ChangesetMenuOperations.RevertToChangeset))
{
menu.AddItem(
menuItemContent,
false,
menuFunction);
return;
}
menu.AddDisabledItem(menuItemContent);
}
static void AddDiffBranchMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
ChangesetExtendedInfo changeset,
ChangesetMenuOperations operations,
GenericMenu.MenuFunction menuFunction)
{
string branchName = GetBranchName(changeset);
menuItemContent.text =
PlasticLocalization.GetString(PlasticLocalization.Name.AnnotateDiffBranchMenuItem,
branchName);
if (operations.HasFlag(ChangesetMenuOperations.DiffChangeset))
{
menu.AddItem(
menuItemContent,
false,
menuFunction);
return;
}
menu.AddDisabledItem(
menuItemContent);
}
static void AddSwitchToChangesetMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
ChangesetMenuOperations operations,
GenericMenu.MenuFunction menuFunction)
{
if (operations.HasFlag(ChangesetMenuOperations.SwitchToChangeset))
{
menu.AddItem(
menuItemContent,
false,
menuFunction);
return;
}
menu.AddDisabledItem(menuItemContent);
}
static string GetBranchName(ChangesetExtendedInfo changesetInfo)
{
if (changesetInfo == null)
return string.Empty;
string branchName = changesetInfo.BranchName;
int lastIndex = changesetInfo.BranchName.LastIndexOf("/");
if (lastIndex == -1)
return branchName;
return branchName.Substring(lastIndex + 1);
}
static bool IsOnMainBranch(ChangesetExtendedInfo singleSeletedChangeset)
{
if (singleSeletedChangeset == null)
return false;
return singleSeletedChangeset.BranchName == MAIN_BRANCH_NAME;
}
static ChangesetMenuOperations GetMenuOperations(
Event e, bool isMultipleSelection)
{
if (Keyboard.IsControlOrCommandKeyPressed(e) &&
Keyboard.IsKeyPressed(e, KeyCode.D))
return isMultipleSelection ?
ChangesetMenuOperations.DiffSelectedChangesets :
ChangesetMenuOperations.DiffChangeset;
return ChangesetMenuOperations.None;
}
void BuildComponents()
{
mDiffChangesetMenuItemContent = new GUIContent(string.Empty);
mDiffSelectedChangesetsMenuItemContent = new GUIContent(string.Format("{0} {1}",
PlasticLocalization.GetString(PlasticLocalization.Name.ChangesetMenuItemDiffSelected),
GetPlasticShortcut.ForDiff()));
mDiffBranchMenuItemContent = new GUIContent();
mSwitchToChangesetMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.ChangesetMenuItemSwitchToChangeset));
mRevertToChangesetMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.ChangesetMenuItemRevertToChangeset));
}
GenericMenu mMenu;
GUIContent mDiffChangesetMenuItemContent;
GUIContent mDiffSelectedChangesetsMenuItemContent;
GUIContent mDiffBranchMenuItemContent;
GUIContent mSwitchToChangesetMenuItemContent;
GUIContent mRevertToChangesetMenuItemContent;
readonly WorkspaceInfo mWkInfo;
readonly IChangesetMenuOperations mChangesetMenuOperations;
readonly IMenuOperations mMenuOperations;
readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
readonly bool mIsGluonMode;
long mLoadedBranchId = -1;
const string MAIN_BRANCH_NAME = "/main";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 397f62458d0ad3441aaaa1a738bd4f94
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using System;
using PlasticGui.WorkspaceWindow.QueryViews;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
internal class DateFilter
{
internal enum Type
{
LastWeek,
Last15Days,
LastMonth,
Last3Months,
LastYear,
AllTime
}
internal Type FilterType;
internal DateFilter(Type filterType)
{
FilterType = filterType;
}
internal string GetTimeAgo()
{
switch (FilterType)
{
case DateFilter.Type.LastWeek:
return QueryConstants.OneWeekAgo;
case DateFilter.Type.Last15Days:
return QueryConstants.HalfMonthAgo;
case DateFilter.Type.LastMonth:
return QueryConstants.OneMonthAgo;
case DateFilter.Type.Last3Months:
return QueryConstants.ThreeMonthsAgo;
case DateFilter.Type.LastYear:
return QueryConstants.OneYearAgo;
}
return string.Empty;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a4d62c64067bca4cbbd6f7fcad2e190
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using Codice.CM.Common;
using Unity.PlasticSCM.Editor.Tool;
namespace Unity.PlasticSCM.Editor.Views.Changesets
{
static class LaunchDiffOperations
{
internal static void DiffChangeset(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor,
RepositorySpec repSpec,
long changesetId,
bool isGluonMode)
{
if (changesetId == -1)
return;
string changesetFullSpec = GetChangesetFullSpec(
repSpec, changesetId);
LaunchTool.OpenChangesetDiffs(
showDownloadPlasticExeWindow,
processExecutor,
repSpec,
changesetFullSpec,
isGluonMode);
}
internal static void DiffChangeset(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor,
RepositorySpec repSpec,
ChangesetInfo changesetInfo,
bool isGluonMode)
{
if (changesetInfo == null)
return;
string changesetFullSpec = GetChangesetFullSpec(
repSpec, changesetInfo.ChangesetId);
LaunchTool.OpenChangesetDiffs(
showDownloadPlasticExeWindow,
processExecutor,
repSpec,
changesetFullSpec,
isGluonMode);
}
internal static void DiffSelectedChangesets(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor,
RepositorySpec repSpec,
ChangesetInfo cset1,
ChangesetInfo cset2,
bool isGluonMode)
{
ChangesetInfo srcChangesetInfo;
ChangesetInfo dstChangesetInfo;
GetSrcAndDstCangesets(
cset1,
cset2,
out srcChangesetInfo,
out dstChangesetInfo);
string srcChangesetFullSpec = GetChangesetFullSpec(
repSpec, srcChangesetInfo.ChangesetId);
string dstChangesetFullSpec = GetChangesetFullSpec(
repSpec, dstChangesetInfo.ChangesetId);
LaunchTool.OpenSelectedChangesetsDiffs(
showDownloadPlasticExeWindow,
processExecutor,
repSpec,
srcChangesetFullSpec,
dstChangesetFullSpec,
isGluonMode);
}
internal static void DiffBranch(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor,
RepositorySpec repSpec,
ChangesetExtendedInfo changesetExtendedInfo,
bool isGluonMode)
{
if (changesetExtendedInfo == null)
return;
string branchFullSpec = GetBranchFullSpec(
repSpec, changesetExtendedInfo);
LaunchTool.OpenBranchDiffs(
showDownloadPlasticExeWindow,
processExecutor,
repSpec,
branchFullSpec,
isGluonMode);
}
static void GetSrcAndDstCangesets(
ChangesetInfo cset1,
ChangesetInfo cset2,
out ChangesetInfo srcChangesetInfo,
out ChangesetInfo dstChangesetInfo)
{
if (cset1.LocalTimeStamp < cset2.LocalTimeStamp)
{
srcChangesetInfo = cset1;
dstChangesetInfo = cset2;
return;
}
srcChangesetInfo = cset2;
dstChangesetInfo = cset1;
}
static string GetChangesetFullSpec(
RepositorySpec repSpec,
long changesetId)
{
return string.Format("cs:{0}@{1}",
changesetId, repSpec.ToString());
}
static string GetBranchFullSpec(
RepositorySpec repSpec,
ChangesetExtendedInfo changesetExtendedInfo)
{
return string.Format("br:{0}@{1}",
changesetExtendedInfo.BranchName,
repSpec.ToString());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6483fd05e8bf42a47aee5e11dbf6db8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,208 @@
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
using Codice.Client.Commands;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Update;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.Views
{
internal class ContinueWithPendingChangesQuestionerBuilder :
SwitchController.IContinueWithPendingChangesQuestionerBuilder
{
internal ContinueWithPendingChangesQuestionerBuilder(
IViewSwitcher viewSwitcher,
EditorWindow parentWindow)
{
mViewSwitcher = viewSwitcher;
mParentWindow = parentWindow;
}
public IContinueWithPendingChangesQuestioner Get(string title, string explanation)
{
return new ContinueWithPendingChangesQuestioner(
title,
explanation,
mViewSwitcher,
mParentWindow);
}
IViewSwitcher mViewSwitcher;
EditorWindow mParentWindow;
}
internal class ContinueWithPendingChangesQuestioner : IContinueWithPendingChangesQuestioner
{
internal ContinueWithPendingChangesQuestioner(
string title,
string explanation,
IViewSwitcher viewSwitcher,
EditorWindow parentWindow)
{
mTitle = title;
mExplanation = explanation;
mViewSwitcher = viewSwitcher;
mParentWindow = parentWindow;
}
public bool ContinueWithPendingChanges()
{
bool result = false;
GUIActionRunner.RunGUIAction(() =>
{
result = ConfirmContinueWithPendingChangesDialog.ConfirmContinue(
mTitle,
mExplanation,
mViewSwitcher,
mParentWindow);
});
return result;
}
string mTitle;
string mExplanation;
IViewSwitcher mViewSwitcher;
EditorWindow mParentWindow;
}
internal class ConfirmContinueWithPendingChangesDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 500, 287);
}
}
internal static bool ConfirmContinue(
string title,
string explanation,
IViewSwitcher viewSwitcher,
EditorWindow parentWindow)
{
ConfirmContinueWithPendingChangesDialog dialog = Create(
title,
explanation,
viewSwitcher);
if (dialog.RunModal(parentWindow) != ResponseType.Ok)
return false;
if (dialog.mIsSwitchToConfirmationChecked)
SavePreference();
return true;
}
static ConfirmContinueWithPendingChangesDialog Create(
string title,
string explanation,
IViewSwitcher viewSwitcher)
{
var instance = CreateInstance<ConfirmContinueWithPendingChangesDialog>();
instance.mTitle = title;
instance.mExplanation = explanation;
instance.mViewSwitcher = viewSwitcher;
return instance;
}
static void SavePreference()
{
ClientConfigData data = ClientConfig.Get().GetClientConfigData();
data.SetPendingChangesOnSwitchAction(UserAction.None);
ClientConfig.Get().Save(data);
}
protected override string GetTitle()
{
return mTitle;
}
protected override void OnModalGUI()
{
Title(mTitle);
Paragraph(mExplanation);
DoSwitchToConfirmationCheckButton();
GUILayout.Space(10);
DoButtonsArea();
}
void DoSwitchToConfirmationCheckButton()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
mIsSwitchToConfirmationChecked = TitleToggle(
PlasticLocalization.GetString(
PlasticLocalization.Name.SwitchToConfirmationCheckButton),
mIsSwitchToConfirmationChecked);
}
}
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
DoContinueButton();
DoCancelAndViewPendingChangesButton();
DoCancelButton();
return;
}
DoCancelButton();
DoCancelAndViewPendingChangesButton();
DoContinueButton();
}
}
void DoContinueButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.SwitchToConfirmationContinueButton)))
return;
OkButtonAction();
}
void DoCancelButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
return;
CancelButtonAction();
}
void DoCancelAndViewPendingChangesButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.SwitchToConfirmationCancelViewChangesButton)))
return;
mViewSwitcher.ShowPendingChanges();
CancelButtonAction();
}
string mTitle;
string mExplanation;
IViewSwitcher mViewSwitcher;
bool mIsSwitchToConfirmationChecked;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3389e142c33d23546a31fc469443a2c3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 173564ff53b74604b8e070b51861b3f9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,311 @@
using System;
using System.Collections;
using UnityEngine;
using Codice.Client.Common;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.Configuration.CloudEdition;
using PlasticGui.WorkspaceWindow.Home.Repositories;
using PlasticGui.WorkspaceWindow.Home.Workspaces;
using PlasticGui.WebApi;
using Unity.PlasticSCM.Editor.UI.Progress;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
{
internal class CreateWorkspaceView :
IPlasticDialogCloser,
IWorkspacesRefreshableView
{
internal interface ICreateWorkspaceListener
{
void OnWorkspaceCreated(WorkspaceInfo wkInfo, bool isGluonMode);
}
internal CreateWorkspaceView(
PlasticWindow parentWindow,
ICreateWorkspaceListener listener,
IPlasticAPI plasticApi,
IPlasticWebRestApi plasticWebRestApi,
string workspacePath)
{
mParentWindow = parentWindow;
mCreateWorkspaceListener = listener;
mWorkspacePath = workspacePath;
mPlasticWebRestApi = plasticWebRestApi;
mProgressControls = new ProgressControlsForViews();
mWorkspaceOperations = new WorkspaceOperations(this, mProgressControls, null);
mCreateWorkspaceState = CreateWorkspaceViewState.BuildForProjectDefaults();
Initialize(plasticApi, plasticWebRestApi);
}
internal void Update()
{
mProgressControls.UpdateProgress(mParentWindow);
}
internal void OnGUI()
{
if (Event.current.type == EventType.Layout)
{
mProgressControls.ProgressData.CopyInto(
mCreateWorkspaceState.ProgressData);
}
string repositoryName = mCreateWorkspaceState.RepositoryName;
DrawCreateWorkspace.ForState(
CreateRepository,
ValidateAndCreateWorkspace,
mParentWindow,
mPlasticWebRestApi,
mDefaultServer,
ref mCreateWorkspaceState);
if (repositoryName == mCreateWorkspaceState.RepositoryName)
return;
OnRepositoryChanged(
mDialogUserAssistant,
mCreateWorkspaceState,
mWorkspacePath);
}
void Initialize(IPlasticAPI plasticApi, IPlasticWebRestApi plasticWebRestApi)
{
((IProgressControls)mProgressControls).ShowProgress(string.Empty);
WorkspaceInfo[] allWorkspaces = null;
IList allRepositories = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
mDefaultServer = GetDefaultServer.ToCreateWorkspace(plasticWebRestApi);
allWorkspaces = plasticApi.GetAllWorkspacesArray();
allRepositories = plasticApi.GetAllRepositories(
mDefaultServer,
true);
},
/*afterOperationDelegate*/ delegate
{
((IProgressControls)mProgressControls).HideProgress();
if (waiter.Exception != null)
{
DisplayException(mProgressControls, waiter.Exception);
return;
}
string serverSpecPart = string.Format("@{0}", mDefaultServer);
mCreateWorkspaceState.RepositoryName = ValidRepositoryName.Get(
string.Format("{0}{1}",
mCreateWorkspaceState.RepositoryName,
serverSpecPart),
allRepositories);
mCreateWorkspaceState.WorkspaceName =
mCreateWorkspaceState.RepositoryName.Replace(
serverSpecPart,
string.Empty);
mDialogUserAssistant = new CreateWorkspaceDialogUserAssistant(
mWorkspacePath,
allWorkspaces);
OnRepositoryChanged(
mDialogUserAssistant,
mCreateWorkspaceState,
mWorkspacePath);
});
}
static void OnRepositoryChanged(
CreateWorkspaceDialogUserAssistant dialogUserAssistant,
CreateWorkspaceViewState createWorkspaceState,
string workspacePath)
{
if (dialogUserAssistant == null)
return;
dialogUserAssistant.RepositoryChanged(
createWorkspaceState.RepositoryName,
createWorkspaceState.WorkspaceName,
workspacePath);
createWorkspaceState.WorkspaceName =
dialogUserAssistant.GetProposedWorkspaceName();
}
void CreateRepository(RepositoryCreationData data)
{
if (!data.Result)
return;
((IProgressControls)mProgressControls).ShowProgress(
PlasticLocalization.GetString(
PlasticLocalization.Name.CreatingRepository,
data.RepName));
RepositoryInfo createdRepository = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter();
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
createdRepository = PlasticGui.Plastic.API.CreateRepository(
data.ServerName, data.RepName);
},
/*afterOperationDelegate*/ delegate
{
((IProgressControls)mProgressControls).HideProgress();
if (waiter.Exception != null)
{
DisplayException(mProgressControls, waiter.Exception);
return;
}
if (createdRepository == null)
return;
mCreateWorkspaceState.RepositoryName =
createdRepository.GetRepSpec().ToString();
});
}
void ValidateAndCreateWorkspace(
CreateWorkspaceViewState state)
{
mWkCreationData = BuildCreationDataFromState(
state, mWorkspacePath);
WorkspaceCreationValidation.AsyncValidation(
mWkCreationData, this, mProgressControls);
// validation calls IPlasticDialogCloser.CloseDialog()
// when the validation is ok
}
void IPlasticDialogCloser.CloseDialog()
{
((IProgressControls)mProgressControls).ShowProgress(string.Empty);
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
RepositorySpec repSpec = new SpecGenerator().GenRepositorySpec(
false, mWkCreationData.Repository);
bool repositoryExist = PlasticGui.Plastic.API.CheckRepositoryExists(
repSpec.Server, repSpec.Name);
if (!repositoryExist)
PlasticGui.Plastic.API.CreateRepository(repSpec.Server, repSpec.Name);
},
/*afterOperationDelegate*/ delegate
{
((IProgressControls)mProgressControls).HideProgress();
if (waiter.Exception != null)
{
DisplayException(mProgressControls, waiter.Exception);
return;
}
mWkCreationData.Result = true;
mWorkspaceOperations.CreateWorkspace(mWkCreationData);
// the operation calls IWorkspacesRefreshableView.RefreshAndSelect
// when the workspace is created
});
}
void IWorkspacesRefreshableView.RefreshAndSelect(WorkspaceInfo wkInfo)
{
PerformInitialCheckin.IfRepositoryIsEmpty(
wkInfo,
mWkCreationData.Repository,
mWkCreationData.IsGluonWorkspace,
PlasticGui.Plastic.API,
mProgressControls,
mCreateWorkspaceListener,
mParentWindow);
}
static WorkspaceCreationData BuildCreationDataFromState(
CreateWorkspaceViewState state,
string workspacePath)
{
return new WorkspaceCreationData(
state.WorkspaceName,
workspacePath,
state.RepositoryName,
state.WorkspaceMode == CreateWorkspaceViewState.WorkspaceModes.Gluon,
false);
}
static void DisplayException(
IProgressControls progressControls,
Exception ex)
{
ExceptionsHandler.LogException(
"CreateWorkspaceView", ex);
progressControls.ShowError(
ExceptionsHandler.GetCorrectExceptionMessage(ex));
}
class GetDefaultServer
{
internal static string ToCreateWorkspace(IPlasticWebRestApi plasticWebRestApi)
{
string clientConfServer = PlasticGui.Plastic.ConfigAPI.GetClientConfServer();
if (!EditionToken.IsCloudEdition())
return clientConfServer;
string cloudServer = PlasticGuiConfig.Get().
Configuration.DefaultCloudServer;
if (!string.IsNullOrEmpty(cloudServer))
return cloudServer;
CloudEditionCreds.Data config =
CloudEditionCreds.GetFromClientConf();
cloudServer = GetFirstCloudServer.
GetCloudServer(plasticWebRestApi, config.Email, config.Password);
if (string.IsNullOrEmpty(cloudServer))
return clientConfServer;
SaveCloudServer.ToPlasticGuiConfig(cloudServer);
return cloudServer;
}
}
WorkspaceCreationData mWkCreationData;
CreateWorkspaceViewState mCreateWorkspaceState;
CreateWorkspaceDialogUserAssistant mDialogUserAssistant;
string mDefaultServer;
readonly WorkspaceOperations mWorkspaceOperations;
readonly ProgressControlsForViews mProgressControls;
readonly string mWorkspacePath;
readonly ICreateWorkspaceListener mCreateWorkspaceListener;
readonly PlasticWindow mParentWindow;
readonly IPlasticWebRestApi mPlasticWebRestApi;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5294f667272fcb2438a79369c92cc7e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using System.IO;
using UnityEngine;
using Unity.PlasticSCM.Editor.UI.Progress;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
{
internal class CreateWorkspaceViewState
{
internal enum WorkspaceModes
{
Developer,
Gluon
}
internal string RepositoryName { get; set; }
internal string WorkspaceName { get; set; }
internal WorkspaceModes WorkspaceMode { get; set; }
internal ProgressControlsForViews.Data ProgressData { get; set; }
internal static CreateWorkspaceViewState BuildForProjectDefaults()
{
string projectName = Application.productName;
return new CreateWorkspaceViewState()
{
RepositoryName = projectName,
WorkspaceName = projectName,
WorkspaceMode = WorkspaceModes.Developer,
ProgressData = new ProgressControlsForViews.Data()
};
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 41633509da720014cbd77f755b378ce7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cecb087091caedf48adcc1cd3b0ebd6d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,231 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Home.Repositories;
using PlasticGui.WebApi;
using PlasticGui.WorkspaceWindow.Servers;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace.Dialogs
{
internal class CreateRepositoryDialog :
PlasticDialog,
KnownServersListOperations.IKnownServersList
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 600, 275);
}
}
internal static RepositoryCreationData CreateRepository(
EditorWindow parentWindow,
IPlasticWebRestApi plasticWebRestApi,
string proposedRepositoryName,
string proposedServer,
string lastUsedRepServer,
string clientConfServer)
{
string server = CreateRepositoryDialogUserAssistant.GetProposedServer(
proposedServer, lastUsedRepServer, clientConfServer);
CreateRepositoryDialog dialog = Create(
plasticWebRestApi,
new ProgressControlsForDialogs(),
proposedRepositoryName,
server);
ResponseType dialogResult = dialog.RunModal(parentWindow);
RepositoryCreationData result = dialog.BuildCreationData();
result.Result = dialogResult == ResponseType.Ok;
return result;
}
protected override void OnModalGUI()
{
Title(PlasticLocalization.GetString(
PlasticLocalization.Name.NewRepositoryTitle));
Paragraph(PlasticLocalization.GetString(
PlasticLocalization.Name.NewRepositoryExplanation));
Paragraph(PlasticLocalization.GetString(
PlasticLocalization.Name.CreateRepositoryDialogDetailedExplanation));
if (Event.current.type == EventType.Layout)
{
mProgressControls.ProgressData.CopyInto(mProgressData);
}
GUILayout.Space(5);
DoEntriesArea();
GUILayout.Space(10);
DrawProgressForDialogs.For(
mProgressControls.ProgressData);
DoButtonsArea();
mProgressControls.ForcedUpdateProgress(this);
}
protected override string GetTitle()
{
return PlasticLocalization.GetString(
PlasticLocalization.Name.NewRepositoryTitle);
}
void KnownServersListOperations.IKnownServersList.FillValues(List<string> values)
{
mKnownServers = values;
}
void DoEntriesArea()
{
mName = TextEntry(
PlasticLocalization.GetString(PlasticLocalization.Name.RepositoryNameShortLabel),
mName,
REPONAME_CONTROL_NAME,
ENTRY_WIDTH,
ENTRY_X);
if (!mFocusIsAreadySet)
{
mFocusIsAreadySet = true;
GUI.FocusControl(REPONAME_CONTROL_NAME);
}
GUILayout.Space(5);
mServer = ComboBox(
PlasticLocalization.GetString(PlasticLocalization.Name.RepositoryExplorerServerLabel),
mServer,
DROPDOWN_CONTROL_NAME,
mKnownServers,
new GenericMenu.MenuFunction2(SelectServer),
ENTRY_WIDTH,
ENTRY_X);
}
void SelectServer(object userData)
{
mServer = userData.ToString();
Repaint();
}
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
DoOkButton();
DoCancelButton();
return;
}
DoCancelButton();
DoOkButton();
}
}
void DoOkButton()
{
if (!AcceptButton(PlasticLocalization.GetString(
PlasticLocalization.Name.OkButton)))
return;
OkButtonWithValidationAction();
}
void DoCancelButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
return;
CancelButtonAction();
}
void OkButtonWithValidationAction()
{
RepositoryCreationValidation.AsyncValidation(
BuildCreationData(),
this,
mProgressControls);
}
RepositoryCreationData BuildCreationData()
{
return new RepositoryCreationData(mName, mServer);
}
static CreateRepositoryDialog Create(
IPlasticWebRestApi plasticWebRestApi,
ProgressControlsForDialogs progressControls,
string proposedRepositoryName,
string proposedServer)
{
var instance = CreateInstance<CreateRepositoryDialog>();
instance.mEnterKeyAction = instance.OkButtonWithValidationAction;
instance.mEscapeKeyAction = instance.CancelButtonAction;
instance.mPlasticWebRestApi = plasticWebRestApi;
instance.mProgressControls = progressControls;
instance.BuildComponents(proposedRepositoryName, proposedServer);
return instance;
}
void BuildComponents(string proposedRepositoryName, string proposedServer)
{
mName = proposedRepositoryName;
mServer = proposedServer;
KnownServersListOperations.GetCombinedServers(
true,
GetExtraServers(proposedServer),
mProgressControls,
this,
mPlasticWebRestApi,
CmConnection.Get().GetProfileManager());
}
static List<string> GetExtraServers(string proposedServer)
{
List<string> result = new List<string>();
if (!string.IsNullOrEmpty(proposedServer))
result.Add(proposedServer);
return result;
}
IPlasticWebRestApi mPlasticWebRestApi;
bool mFocusIsAreadySet;
string mName;
string mServer;
List<string> mKnownServers = new List<string>();
ProgressControlsForDialogs.Data mProgressData = new ProgressControlsForDialogs.Data();
ProgressControlsForDialogs mProgressControls;
const float ENTRY_WIDTH = 400;
const float ENTRY_X = 175f;
const string REPONAME_CONTROL_NAME = "CreateRepositoryDialog.RepositoryName";
const string DROPDOWN_CONTROL_NAME = "CreateRepositoryDialog.ServerDropdown";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61f74d0a8a3f1f542b8afe99e65686df
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace.Dialogs
{
internal enum RepositoriesListColumn
{
Name,
Server
}
[Serializable]
internal class RepositoriesListHeaderState : MultiColumnHeaderState, ISerializationCallbackReceiver
{
internal static RepositoriesListHeaderState GetDefault()
{
return new RepositoriesListHeaderState(BuildColumns());
}
internal static List<string> GetColumnNames()
{
List<string> result = new List<string>();
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.NameColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.ServerColumn));
return result;
}
static string GetColumnName(RepositoriesListColumn column)
{
switch (column)
{
case RepositoriesListColumn.Name:
return PlasticLocalization.GetString(PlasticLocalization.Name.NameColumn);
case RepositoriesListColumn.Server:
return PlasticLocalization.GetString(PlasticLocalization.Name.ServerColumn);
default:
return null;
}
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (mHeaderTitles != null)
TreeHeaderColumns.SetTitles(columns, mHeaderTitles);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
static Column[] BuildColumns()
{
return new Column[]
{
new Column()
{
width = 320,
headerContent = new GUIContent(
GetColumnName(RepositoriesListColumn.Name)),
minWidth = 200,
allowToggleVisibility = false,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 200,
headerContent = new GUIContent(
GetColumnName(RepositoriesListColumn.Server)),
minWidth = 200,
allowToggleVisibility = false,
sortingArrowAlignment = TextAlignment.Right
}
};
}
RepositoriesListHeaderState(Column[] columns)
: base(columns)
{
if (mHeaderTitles == null)
mHeaderTitles = TreeHeaderColumns.GetTitles(columns);
}
[SerializeField]
string[] mHeaderTitles;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da6a50477d2d7ff4f81d1c21c58a5b0e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,252 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Home.Repositories;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace.Dialogs
{
internal class RepositoriesListView :
TreeView,
IPlasticTable<RepositoryInfo>
{
internal RepositoriesListView(
RepositoriesListHeaderState headerState,
List<string> columnNames,
Action doubleClickAction)
: base(new TreeViewState())
{
mColumnNames = columnNames;
mDoubleClickAction = doubleClickAction;
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.canSort = true;
multiColumnHeader.sortingChanged += SortingChanged;
mColumnComparers = RepositoriesTableDefinition.BuildColumnComparers();
rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
showAlternatingRowBackgrounds = false;
}
public override IList<TreeViewItem> GetRows()
{
return mRows;
}
protected override TreeViewItem BuildRoot()
{
return new TreeViewItem(0, -1, string.Empty);
}
protected override IList<TreeViewItem> BuildRows(
TreeViewItem rootItem)
{
RegenerateRows(
this, mRepositories, rootItem, mRows);
return mRows;
}
protected override void SearchChanged(string newSearch)
{
Refilter();
Sort();
Reload();
TableViewOperations.ScrollToSelection(this);
}
protected override void DoubleClickedItem(int id)
{
mDoubleClickAction();
}
protected override void BeforeRowsGUI()
{
int firstRowVisible;
int lastRowVisible;
GetFirstAndLastVisibleRows(out firstRowVisible, out lastRowVisible);
GUI.DrawTexture(new Rect(0,
firstRowVisible * rowHeight,
GetRowRect(0).width,
(lastRowVisible * rowHeight) + 1000),
Images.GetTreeviewBackgroundTexture());
DrawTreeViewItem.InitializeStyles();
base.BeforeRowsGUI();
}
protected override void RowGUI(RowGUIArgs args)
{
if (args.item is RepositoryListViewItem)
{
RepositoryListViewItemGUI(
(RepositoryListViewItem)args.item,
args,
rowHeight);
return;
}
base.RowGUI(args);
}
internal string GetSelectedRepository()
{
IList<TreeViewItem> selectedItems = FindRows(GetSelection());
if (selectedItems.Count == 0)
return null;
return ((RepositoryListViewItem)selectedItems[0])
.Repository.GetRepSpec().ToString();
}
void IPlasticTable<RepositoryInfo>.FillEntriesAndSelectRows(
IList<RepositoryInfo> entries,
List<RepositoryInfo> entriesToSelect,
string currentFilter)
{
mUnfilteredRepositories = entries;
Refilter();
Sort();
Reload();
}
void Refilter()
{
mRepositories = RepositoriesTableDefinition.TableFilter.Filter(
searchString,
mUnfilteredRepositories);
}
void Sort()
{
int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
IComparer<RepositoryInfo> comparer = mColumnComparers[
mColumnNames[sortedColumnIdx]];
((List<RepositoryInfo>)mRepositories).Sort(new SortOrderComparer<RepositoryInfo>(
comparer, sortAscending));
}
void SortingChanged(MultiColumnHeader multiColumnHeader)
{
Sort();
Reload();
}
static void RegenerateRows(
RepositoriesListView listView,
IList<RepositoryInfo> repositories,
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
ClearRows(rootItem, rows);
if (repositories.Count == 0)
return;
for (int i = 0; i < repositories.Count; i++)
{
RepositoryListViewItem repositoryListViewItem =
new RepositoryListViewItem(i + 1, (RepositoryInfo)repositories[i]);
rootItem.AddChild(repositoryListViewItem);
rows.Add(repositoryListViewItem);
}
listView.SetSelection(new List<int> { 1 });
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static void RepositoryListViewItemGUI(
RepositoryListViewItem item,
RowGUIArgs args,
float rowHeight)
{
for (int visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++)
{
Rect cellRect = args.GetCellRect(visibleColumnIdx);
RepositoriesListColumn column =
(RepositoriesListColumn)args.GetColumn(visibleColumnIdx);
RepositoryListViewItemCellGUI(
cellRect,
item,
column,
rowHeight,
args.selected,
args.focused);
}
}
static void RepositoryListViewItemCellGUI(
Rect rect,
RepositoryListViewItem item,
RepositoriesListColumn column,
float rowHeight,
bool isSelected,
bool isFocused)
{
if (column == RepositoriesListColumn.Name)
{
DrawTreeViewItem.ForItemCell(
rect,
rowHeight,
0,
Images.GetRepositoryIcon(),
null,
item.Repository.Name,
isSelected,
isFocused,
false,
false);
return;
}
DrawTreeViewItem.ForSecondaryLabel(
rect,
item.Repository.Server,
isSelected,
isFocused,
false);
}
List<TreeViewItem> mRows = new List<TreeViewItem>();
IList<RepositoryInfo> mUnfilteredRepositories = new List<RepositoryInfo>();
IList<RepositoryInfo> mRepositories = new List<RepositoryInfo>();
readonly Dictionary<string, IComparer<RepositoryInfo>> mColumnComparers;
readonly List<string> mColumnNames;
readonly Action mDoubleClickAction;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c18598e9d808edb4583a6aa724ffc268
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,337 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.Client.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Home.Repositories;
using PlasticGui.WebApi;
using PlasticGui.WorkspaceWindow.Servers;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace.Dialogs
{
internal class RepositoryExplorerDialog :
PlasticDialog,
KnownServersListOperations.IKnownServersList,
FillRepositoriesTable.IGetFilterText
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 750, 450);
}
}
internal static string BrowseRepository(
EditorWindow parentWindow,
IPlasticWebRestApi plasticWebRestApi,
string defaultServer)
{
RepositoryExplorerDialog dialog = Create(
plasticWebRestApi,
new ProgressControlsForDialogs(),
defaultServer,
new UnityPlasticGuiMessage());
ResponseType dialogResult = dialog.RunModal(parentWindow);
if (dialogResult != ResponseType.Ok)
return null;
return dialog.mRepositoriesListView.GetSelectedRepository();
}
void OnDisable()
{
mSearchField.downOrUpArrowKeyPressed -=
SearchField_OnDownOrUpArrowKeyPressed;
}
protected override void SaveSettings()
{
TreeHeaderSettings.Save(
mRepositoriesListView.multiColumnHeader.state,
UnityConstants.REPOSITORIES_TABLE_SETTINGS_NAME);
}
protected override void OnModalGUI()
{
Title(PlasticLocalization.GetString(PlasticLocalization.Name.ChooseRepositoryTitle));
Paragraph(PlasticLocalization.GetString(
PlasticLocalization.Name.SelectRepositoryBelow));
if (Event.current.type == EventType.Layout)
{
mProgressControls.ProgressData.CopyInto(
mState.ProgressData);
}
bool isEnabled = !mProgressControls.ProgressData.IsWaitingAsyncResult;
DoToolbarArea(
mSearchField,
mRepositoriesListView,
isEnabled,
Refresh,
OnServerSelected,
ref mState);
GUILayout.Space(10);
DoListArea(
mRepositoriesListView,
isEnabled);
DrawProgressForDialogs.For(
mProgressControls.ProgressData);
DoButtonsArea();
mProgressControls.ForcedUpdateProgress(this);
}
protected override string GetTitle()
{
return PlasticLocalization.GetString(PlasticLocalization.Name.ExploreRepositories);
}
void SearchField_OnDownOrUpArrowKeyPressed()
{
mRepositoriesListView.SetFocusAndEnsureSelectedItem();
}
void Refresh()
{
mFillRepositoriesTable.FillTable(
mRepositoriesListView,
null,
mProgressControls,
null,
new FillRepositoriesTable.SaveLastUsedServer(true),
mGuiMessage,
null,
null,
this,
mState.Server,
false,
false,
true);
}
void KnownServersListOperations.IKnownServersList.FillValues(
List<string> values)
{
mState.AvailableServers = values;
Refresh();
}
string FillRepositoriesTable.IGetFilterText.Get()
{
return mRepositoriesListView.searchString;
}
void OnServerSelected(object server)
{
mState.Server = server.ToString();
Repaint();
Refresh();
}
static void DoToolbarArea(
SearchField searchField,
RepositoriesListView listView,
bool isEnabled,
Action refreshAction,
GenericMenu.MenuFunction2 selectServerAction,
ref State state)
{
GUILayout.BeginHorizontal();
GUILayout.Label(
PlasticLocalization.GetString(PlasticLocalization.Name.RepositoryExplorerServerLabel));
GUI.enabled = isEnabled;
state.Server = DoDropDownTextField(
state.Server,
state.AvailableServers,
selectServerAction,
refreshAction);
var refreshText = PlasticLocalization.GetString(PlasticLocalization.Name.RefreshButton);
if (GUILayout.Button(refreshText, EditorStyles.miniButton))
refreshAction();
GUILayout.FlexibleSpace();
DrawSearchField.For(
searchField, listView, SEARCH_FIELD_WIDTH);
GUI.enabled = true;
GUILayout.EndHorizontal();
}
static void DoListArea(
RepositoriesListView listView,
bool isEnabled)
{
GUI.enabled = isEnabled;
Rect treeRect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
listView.OnGUI(treeRect);
GUI.enabled = true;
}
static string DoDropDownTextField(
string text,
List<string> options,
GenericMenu.MenuFunction2 selectServerAction,
Action enterKeyAction)
{
bool isEnterKeyPressed = false;
Event e = Event.current;
if (Keyboard.IsReturnOrEnterKeyPressed(e))
{
isEnterKeyPressed = true;
}
string result = DropDownTextField.DoDropDownTextField(
text,
DROPDOWN_CONTROL_NAME,
options,
selectServerAction,
GUILayout.Width(DROPDOWN_WIDTH));
if (isEnterKeyPressed &&
GUI.GetNameOfFocusedControl() == DROPDOWN_CONTROL_NAME)
{
e.Use();
enterKeyAction();
}
return result;
}
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
DoOkButton();
DoCancelButton();
return;
}
DoCancelButton();
DoOkButton();
}
}
void DoOkButton()
{
if (!AcceptButton(PlasticLocalization.GetString(
PlasticLocalization.Name.OkButton)))
return;
OkButtonAction();
}
void DoCancelButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
return;
CancelButtonAction();
}
static RepositoryExplorerDialog Create(
IPlasticWebRestApi plasticWebRestApi,
ProgressControlsForDialogs progressControls,
string defaultServer,
GuiMessage.IGuiMessage guiMessage)
{
var instance = CreateInstance<RepositoryExplorerDialog>();
instance.mGuiMessage = guiMessage;
instance.mEscapeKeyAction = instance.CancelButtonAction;
instance.mProgressControls = progressControls;
instance.BuildComponents(defaultServer, plasticWebRestApi);
return instance;
}
void BuildComponents(
string defaultServer,
IPlasticWebRestApi plasticWebRestApi)
{
mSearchField = new SearchField();
mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
RepositoriesListHeaderState headerState =
RepositoriesListHeaderState.GetDefault();
TreeHeaderSettings.Load(headerState,
UnityConstants.REPOSITORIES_TABLE_SETTINGS_NAME,
(int)RepositoriesListColumn.Name);
mRepositoriesListView = new RepositoriesListView(
headerState,
RepositoriesListHeaderState.GetColumnNames(),
OkButtonAction);
mRepositoriesListView.Reload();
mFillRepositoriesTable = new FillRepositoriesTable(
new LocalRepositoriesProvider());
mState = new State()
{
Server = defaultServer,
ProgressData = new ProgressControlsForDialogs.Data()
};
KnownServersListOperations.GetCombinedServers(
true,
new List<string>(),
mProgressControls,
this,
plasticWebRestApi,
CmConnection.Get().GetProfileManager());
}
SearchField mSearchField;
RepositoriesListView mRepositoriesListView;
ProgressControlsForDialogs mProgressControls;
FillRepositoriesTable mFillRepositoriesTable;
State mState;
GuiMessage.IGuiMessage mGuiMessage;
const string DROPDOWN_CONTROL_NAME = "RepositoryExplorerDialog.ServerDropdown";
const float DROPDOWN_WIDTH = 250;
const float SEARCH_FIELD_WIDTH = 450;
class State
{
internal List<string> AvailableServers { get; set; }
internal string Server { get; set; }
internal ProgressControlsForDialogs.Data ProgressData { get; set; }
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b29af44841cd6644e876233cd057bc18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
using UnityEditor.IMGUI.Controls;
using Codice.CM.Common;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace.Dialogs
{
internal class RepositoryListViewItem : TreeViewItem
{
internal RepositoryInfo Repository { get; private set; }
internal RepositoryListViewItem(int id, RepositoryInfo repository)
: base(id, 0)
{
Repository = repository;
displayName = repository.Name;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 83882c7718d0fc34f8a05141328ceac1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,536 @@
using System;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WebApi;
using PlasticGui.WorkspaceWindow.Home.Repositories;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.Views.CreateWorkspace.Dialogs;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
{
internal static class DrawCreateWorkspace
{
internal static void ForState(
Action<RepositoryCreationData> createRepositoryAction,
Action<CreateWorkspaceViewState> createWorkspaceAction,
EditorWindow parentWindow,
IPlasticWebRestApi plasticWebRestApi,
string defaultServer,
ref CreateWorkspaceViewState state)
{
DoTitle();
GUILayout.Space(15);
DoFieldsArea(
createRepositoryAction,
parentWindow,
plasticWebRestApi,
defaultServer,
ref state);
GUILayout.Space(10);
DoRadioButtonsArea(ref state);
GUILayout.Space(3);
DoHelpLabel();
GUILayout.Space(10);
DoCreateWorkspaceButton(
createWorkspaceAction,
ref state);
GUILayout.Space(5);
DoNotificationArea(state.ProgressData);
}
static void DoTitle()
{
GUILayout.Label(
PlasticLocalization.GetString(
PlasticLocalization.Name.NewWorkspace),
UnityStyles.Dialog.MessageTitle);
GUILayout.Label(
PlasticLocalization.GetString(PlasticLocalization.Name.WorkspacesExplanationLabel),
EditorStyles.wordWrappedLabel);
}
static void DoFieldsArea(
Action<RepositoryCreationData> createRepositoryAction,
EditorWindow parentWindow,
IPlasticWebRestApi plasticWebRestApi,
string defaultServer,
ref CreateWorkspaceViewState state)
{
DoRepositoryField(
createRepositoryAction,
parentWindow,
plasticWebRestApi,
defaultServer,
ref state);
DoWorkspaceField(ref state);
}
static void DoRepositoryField(
Action<RepositoryCreationData> createRepositoryAction,
EditorWindow parentWindow,
IPlasticWebRestApi plasticWebRestApi,
string defaultServer,
ref CreateWorkspaceViewState state)
{
EditorGUILayout.BeginHorizontal();
DoLabel(
PlasticLocalization.GetString(PlasticLocalization.Name.RepositoryName));
state.RepositoryName = DoTextField(
state.RepositoryName,
!state.ProgressData.IsOperationRunning,
LABEL_WIDTH,
TEXTBOX_WIDTH - BROWSE_BUTTON_WIDTH);
float browseButtonX =
LABEL_WIDTH + TEXTBOX_WIDTH + BUTTON_MARGIN -
BROWSE_BUTTON_WIDTH;
float browseButtonWidth =
BROWSE_BUTTON_WIDTH - BUTTON_MARGIN;
if (DoButton(
"...",
!state.ProgressData.IsOperationRunning,
browseButtonX,
browseButtonWidth))
{
DoBrowseRepositoryButton(
parentWindow,
plasticWebRestApi,
defaultServer,
ref state);
EditorGUIUtility.ExitGUI();
}
float newButtonX =
LABEL_WIDTH + TEXTBOX_WIDTH + BUTTON_MARGIN;
float newButtonWidth =
NEW_BUTTON_WIDTH - BUTTON_MARGIN;
if (DoButton(
PlasticLocalization.GetString(PlasticLocalization.Name.NewButton),
!state.ProgressData.IsOperationRunning,
newButtonX, newButtonWidth))
{
DoNewRepositoryButton(
createRepositoryAction,
parentWindow,
plasticWebRestApi,
state.RepositoryName,
defaultServer);
EditorGUIUtility.ExitGUI();
}
ValidationResult validationResult = ValidateRepositoryName(
state.RepositoryName);
if (!validationResult.IsValid)
DoWarningLabel(validationResult.ErrorMessage,
LABEL_WIDTH + TEXTBOX_WIDTH + NEW_BUTTON_WIDTH + LABEL_MARGIN);
EditorGUILayout.EndHorizontal();
}
static void DoWorkspaceField(
ref CreateWorkspaceViewState state)
{
EditorGUILayout.BeginHorizontal();
DoLabel(
PlasticLocalization.GetString(PlasticLocalization.Name.WorkspaceName));
state.WorkspaceName = DoTextField(
state.WorkspaceName,
!state.ProgressData.IsOperationRunning,
LABEL_WIDTH,
TEXTBOX_WIDTH - BROWSE_BUTTON_WIDTH);
ValidationResult validationResult = ValidateWorkspaceName(
state.WorkspaceName);
if (!validationResult.IsValid)
DoWarningLabel(validationResult.ErrorMessage,
LABEL_WIDTH + TEXTBOX_WIDTH - BROWSE_BUTTON_WIDTH + LABEL_MARGIN);
EditorGUILayout.EndHorizontal();
}
static void DoRadioButtonsArea(
ref CreateWorkspaceViewState state)
{
EditorGUILayout.BeginVertical();
DoLabel(
PlasticLocalization.GetString(PlasticLocalization.Name.WorkPreferenceQuestion));
if (DoRadioButton(
PlasticLocalization.GetString(PlasticLocalization.Name.WorkPreferenceAnswerUnityVCS),
state.WorkspaceMode == CreateWorkspaceViewState.WorkspaceModes.Developer,
!state.ProgressData.IsOperationRunning,
RADIO_BUTTON_MARGIN))
state.WorkspaceMode = CreateWorkspaceViewState.WorkspaceModes.Developer;
if (DoRadioButton(
PlasticLocalization.GetString(PlasticLocalization.Name.WorkPreferenceAnswerGluon),
state.WorkspaceMode == CreateWorkspaceViewState.WorkspaceModes.Gluon,
!state.ProgressData.IsOperationRunning,
RADIO_BUTTON_MARGIN))
state.WorkspaceMode = CreateWorkspaceViewState.WorkspaceModes.Gluon;
EditorGUILayout.EndVertical();
}
static void DoCreateWorkspaceButton(
Action<CreateWorkspaceViewState> createWorkspaceAction,
ref CreateWorkspaceViewState state)
{
EditorGUILayout.BeginHorizontal();
bool isButtonEnabled =
IsValidState(state) &&
!state.ProgressData.IsOperationRunning;
string buttonText = PlasticLocalization.GetString(
PlasticLocalization.Name.CreateWorkspace);
bool isButtonClicked = DoButton(buttonText, isButtonEnabled,
CREATE_WORKSPACE_BUTTON_MARGIN, CREATE_WORKSPACE_BUTTON_WIDTH);
GUI.enabled = true;
if (state.ProgressData.IsOperationRunning)
{
DoProgress(state.ProgressData,
CREATE_WORKSPACE_BUTTON_MARGIN +
PROGRESS_MARGIN +
CREATE_WORKSPACE_BUTTON_WIDTH);
}
EditorGUILayout.EndHorizontal();
if (isButtonClicked)
createWorkspaceAction(state);
}
static void DoBrowseRepositoryButton(
EditorWindow parentWindow,
IPlasticWebRestApi plasticWebRestApi,
string defaultServer,
ref CreateWorkspaceViewState state)
{
string result = RepositoryExplorerDialog.BrowseRepository(
parentWindow,
plasticWebRestApi,
defaultServer);
if (string.IsNullOrEmpty(result))
return;
state.RepositoryName = result;
}
static void DoNewRepositoryButton(
Action<RepositoryCreationData> createRepositoryAction,
EditorWindow parentWindow,
IPlasticWebRestApi plasticWebRestApi,
string repositoryName,
string defaultServer)
{
string proposedRepositoryName = string.Empty;
string proposedServer = string.Empty;
RepositorySpec repSpec = GetRepSpecFromName(repositoryName);
if (repSpec != null)
{
proposedRepositoryName = repSpec.Name;
proposedServer = repSpec.Server;
}
RepositoryCreationData creationData = CreateRepositoryDialog.CreateRepository(
parentWindow,
plasticWebRestApi,
proposedRepositoryName,
proposedServer,
defaultServer,
ClientConfig.Get().GetWorkspaceServer());
createRepositoryAction(creationData);
}
static void DoHelpLabel()
{
string linkText = PlasticLocalization.GetString(PlasticLocalization.Name.HereLink);
string labelText = string.Format(
PlasticLocalization.GetString(PlasticLocalization.Name.LearnMoreDifferencesUnityVCS),
UnityStyles.HexColors.LINK_COLOR,
linkText);
EditorGUILayout.BeginHorizontal();
if (DoLinkLabel(labelText, linkText, RADIO_BUTTON_MARGIN))
Application.OpenURL(
PlasticLocalization.GetString(PlasticLocalization.Name.PlasticSCMFullVsPartialWorkspaceLink));
EditorGUILayout.EndHorizontal();
}
static void DoNotificationArea(ProgressControlsForViews.Data progressData)
{
if (string.IsNullOrEmpty(progressData.NotificationMessage))
return;
DrawProgressForViews.ForNotificationArea(progressData);
}
static void DoLabel(string labelText)
{
GUIStyle labelStyle = new GUIStyle(EditorStyles.label);
Rect rect = GUILayoutUtility.GetRect(
new GUIContent(labelText),
labelStyle);
GUI.Label(rect, labelText, labelStyle);
}
static string DoTextField(
string entryValue,
bool enabled,
float textBoxLeft,
float textBoxWidth)
{
GUI.enabled = enabled;
var rect = GUILayoutUtility.GetRect(
new GUIContent(entryValue),
UnityStyles.Dialog.EntryLabel);
rect.width = textBoxWidth;
rect.x = textBoxLeft;
string result = GUI.TextField(rect, entryValue);
GUI.enabled = true;
return result;
}
static bool DoButton(
string text,
bool isEnabled,
float buttonLeft,
float buttonWidth)
{
GUI.enabled = isEnabled;
var rect = GUILayoutUtility.GetRect(
new GUIContent(text),
UnityStyles.Dialog.EntryLabel);
rect.width = buttonWidth;
rect.x = buttonLeft;
bool result = GUI.Button(rect, text);
GUI.enabled = true;
return result;
}
static bool DoRadioButton(
string text,
bool isChecked,
bool isEnabled,
float buttonLeft)
{
GUI.enabled = isEnabled;
GUIStyle radioButtonStyle = new GUIStyle(EditorStyles.radioButton);
var rect = GUILayoutUtility.GetRect(
new GUIContent(text),
radioButtonStyle);
rect.x = buttonLeft;
bool result = GUI.Toggle(
rect,
isChecked,
text,
radioButtonStyle);
GUI.enabled = true;
return result;
}
static void DoWarningLabel(
string labelText,
float labelLeft)
{
Rect rect = GUILayoutUtility.GetRect(
new GUIContent(labelText),
EditorStyles.label);
rect.x = labelLeft;
GUI.Label(rect,
new GUIContent(labelText, Images.GetWarnIcon()),
UnityStyles.IncomingChangesTab.HeaderWarningLabel);
}
static bool DoLinkLabel(
string labelText,
string linkText,
float labelLeft)
{
GUIContent labelContent = new GUIContent(labelText);
GUIStyle labelStyle = new GUIStyle(EditorStyles.miniLabel);
labelStyle.richText = true;
Rect rect = GUILayoutUtility.GetRect(
labelContent,
labelStyle);
rect.x = labelLeft;
Rect linkRect = GetLinkRect(
labelText,
linkText,
labelContent,
labelStyle,
rect);
EditorGUIUtility.AddCursorRect(linkRect, MouseCursor.Link);
GUI.Label(rect, labelText, labelStyle);
return Mouse.IsLeftMouseButtonPressed(Event.current)
&& linkRect.Contains(Event.current.mousePosition);
}
static void DoProgress(
ProgressControlsForViews.Data data,
float progressLeft)
{
if (string.IsNullOrEmpty(data.ProgressMessage))
return;
var rect = GUILayoutUtility.GetRect(
new GUIContent(data.ProgressMessage),
UnityStyles.Dialog.EntryLabel);
rect.x = progressLeft;
GUI.Label(rect, data.ProgressMessage);
}
static Rect GetLinkRect(
string labelText,
string linkText,
GUIContent labelContent,
GUIStyle labelStyle,
Rect rect)
{
int beginLinkChar = labelText.IndexOf(linkText);
int endLinkChar = beginLinkChar + linkText.Length;
Vector2 beginPos = labelStyle.GetCursorPixelPosition(
rect, labelContent, beginLinkChar);
Vector2 endPos = labelStyle.GetCursorPixelPosition(
rect, labelContent, endLinkChar);
Rect linkRect = new Rect(
beginPos.x,
beginPos.y,
endPos.x - beginPos.x,
labelStyle.lineHeight * 1.2f);
return linkRect;
}
static bool IsValidState(
CreateWorkspaceViewState state)
{
if (!ValidateRepositoryName(state.RepositoryName).IsValid)
return false;
if (!ValidateWorkspaceName(state.WorkspaceName).IsValid)
return false;
return true;
}
static ValidationResult ValidateRepositoryName(string repositoryName)
{
ValidationResult result = new ValidationResult();
if (string.IsNullOrEmpty(repositoryName))
{
result.ErrorMessage = PlasticLocalization.GetString(PlasticLocalization.Name.RepositoryNameEmpty);
result.IsValid = false;
return result;
}
result.IsValid = true;
return result;
}
static ValidationResult ValidateWorkspaceName(string workspaceName)
{
ValidationResult result = new ValidationResult();
if (string.IsNullOrEmpty(workspaceName))
{
result.ErrorMessage = PlasticLocalization.GetString(PlasticLocalization.Name.WorkspaceNameEmpty);
result.IsValid = false;
return result;
}
result.IsValid = true;
return result;
}
static RepositorySpec GetRepSpecFromName(string repositoryName)
{
if (string.IsNullOrEmpty(repositoryName))
return null;
return new SpecGenerator().
GenRepositorySpec(false, repositoryName);
}
class ValidationResult
{
internal string ErrorMessage;
internal bool IsValid;
}
const float LABEL_WIDTH = 150;
const float TEXTBOX_WIDTH = 400;
const float BROWSE_BUTTON_WIDTH = 25;
const float NEW_BUTTON_WIDTH = 60;
const float BUTTON_MARGIN = 2;
const float LABEL_MARGIN = 2;
const float RADIO_BUTTON_MARGIN = 38;
const float PROGRESS_MARGIN = 5;
const float CREATE_WORKSPACE_BUTTON_MARGIN = 32;
const float CREATE_WORKSPACE_BUTTON_WIDTH = 160;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 788db2c7ca3c2804d912f447ffc19856
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,178 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Codice.Client.BaseCommands;
using Codice.Client.Commands;
using Codice.Client.Commands.CheckIn;
using Codice.Client.Common;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using Codice.Client.GameUI.Checkin;
using PlasticGui;
using PlasticGui.Help.Conditions;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
{
internal static class PerformInitialCheckin
{
internal static void IfRepositoryIsEmpty(
WorkspaceInfo wkInfo,
string repository,
bool isGluonWorkspace,
IPlasticAPI plasticApi,
IProgressControls progressControls,
CreateWorkspaceView.ICreateWorkspaceListener createWorkspaceListener,
PlasticWindow plasticWindow)
{
RepositoryInfo repInfo = null;
bool isEmptyRepository = false;
progressControls.ShowProgress(string.Empty);
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
RepositorySpec repSpec = new SpecGenerator().
GenRepositorySpec(false, repository);
repInfo = plasticApi.GetRepositoryInfo(repSpec);
isEmptyRepository = IsEmptyRepositoryCondition.
Evaluate(wkInfo, repSpec, plasticApi);
},
/*afterOperationDelegate*/ delegate
{
progressControls.HideProgress();
if (waiter.Exception != null)
{
DisplayException(progressControls, waiter.Exception);
return;
}
if (!isEmptyRepository)
{
plasticWindow.RefreshWorkspaceUI();
return;
}
CheckinPackagesAndProjectSettingsFolders(
wkInfo, isGluonWorkspace, plasticApi,
progressControls, createWorkspaceListener);
});
}
static void CheckinPackagesAndProjectSettingsFolders(
WorkspaceInfo wkInfo,
bool isGluonWorkspace,
IPlasticAPI plasticApi,
IProgressControls progressControls,
CreateWorkspaceView.ICreateWorkspaceListener createWorkspaceListener)
{
progressControls.ShowProgress(PlasticLocalization.GetString(
PlasticLocalization.Name.UnityInitialCheckinProgress));
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
PerformCheckinPackagesAndProjectSettingsFolders(
wkInfo, isGluonWorkspace, plasticApi);
},
/*afterOperationDelegate*/ delegate
{
progressControls.HideProgress();
if (waiter.Exception != null &&
!IsMergeNeededException(waiter.Exception))
{
DisplayException(progressControls, waiter.Exception);
return;
}
createWorkspaceListener.OnWorkspaceCreated(wkInfo, isGluonWorkspace);
});
}
internal static void PerformCheckinPackagesAndProjectSettingsFolders(
WorkspaceInfo wkInfo,
bool isGluonWorkspace,
IPlasticAPI plasticApi)
{
List<string> paths = new List<string> {
Path.Combine(wkInfo.ClientPath, "Packages"),
Path.Combine(wkInfo.ClientPath, "ProjectSettings")
};
string comment = PlasticLocalization.GetString(
PlasticLocalization.Name.UnityInitialCheckinComment);
PerformAdd(paths, plasticApi);
PerformCheckinForMode(wkInfo, paths, comment, isGluonWorkspace);
}
static void PerformAdd(
List<string> paths,
IPlasticAPI plasticApi)
{
AddOptions options = new AddOptions();
options.AddPrivateParents = true;
options.CheckoutParent = true;
options.Recurse = true;
options.SearchForPrivatePaths = true;
options.SkipIgnored = true;
IList checkouts;
plasticApi.Add(paths.ToArray(), options, out checkouts);
}
static void PerformCheckinForMode(
WorkspaceInfo wkInfo,
List<string> paths,
string comment,
bool isGluonWorkspace)
{
if (isGluonWorkspace)
{
new BaseCommandsImpl().PartialCheckin(wkInfo, paths, comment);
return;
}
CheckinParams ciParams = new CheckinParams();
ciParams.paths = paths.ToArray();
ciParams.comment = comment;
ciParams.time = DateTime.MinValue;
ciParams.flags = CheckinFlags.Recurse | CheckinFlags.ProcessSymlinks;
new BaseCommandsImpl().CheckIn(ciParams);
}
static bool IsMergeNeededException(Exception exception)
{
if (exception == null)
return false;
// Check the check-in exception for gluon
if (exception is CheckinConflictsException)
return true;
// Check the check-in exceptions for plastic
return exception is CmClientMergeNeededException;
}
static void DisplayException(
IProgressControls progressControls,
Exception ex)
{
ExceptionsHandler.LogException(
"PerformInitialCheckin", ex);
progressControls.ShowError(
ExceptionsHandler.GetCorrectExceptionMessage(ex));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29e0becc4ce852c439ff3e642f0375bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using System.Collections;
using Codice.CM.Common;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
{
internal static class ValidRepositoryName
{
internal static string Get(string repositoryName, IList repositories)
{
string validRepositoryName = GetValidRepositoryName(repositoryName);
string result = validRepositoryName;
int i = 2;
while (RepositoryExists(result, repositories))
{
result = validRepositoryName + "_" + i.ToString();
i++;
}
return result;
}
static bool RepositoryExists(string repositoryName, IList repositories)
{
if (repositories == null)
return false;
foreach (RepositoryInfo repInfo in repositories)
{
if (repInfo.Name.Equals(repositoryName))
return true;
}
return false;
}
static string GetValidRepositoryName(string newRepository)
{
string result = newRepository.Replace(SUBMODULE_SEPARATOR, '-');
result = result.Replace(PIPE_CHARACTER, '-');
return result;
}
const char SUBMODULE_SEPARATOR = '/';
const char PIPE_CHARACTER = '|';
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60f5fb7fb3626214f9d97215fe186cbf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 37b5532626676e045a3b172c915e5d79
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using UnityEditor.IMGUI.Controls;
using PlasticGui.WorkspaceWindow.Diff;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal class ChangeCategoryTreeViewItem : TreeViewItem
{
internal ChangeCategory Category { get; private set; }
internal ChangeCategoryTreeViewItem(
int id, int depth, ChangeCategory category)
: base(id, depth, category.GetHeaderText())
{
Category = category;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 156e16594aa6bd54cb77aa3f8eae5c82
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using UnityEditor.IMGUI.Controls;
using PlasticGui.WorkspaceWindow.Diff;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal class ClientDiffTreeViewItem : TreeViewItem
{
internal ClientDiffInfo Difference { get; private set; }
internal ClientDiffTreeViewItem(
int id, int depth, ClientDiffInfo diff)
: base(id, depth)
{
Difference = diff;
displayName = diff.PathString;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3fdd86a000d1ef04094416eefed53087
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3ac250bc549a212428286f328779be0e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,249 @@
using System.IO;
using UnityEditor;
using UnityEngine;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.Diff;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
namespace Unity.PlasticSCM.Editor.Views.Diff.Dialogs
{
internal class GetRestorePathDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 600, 205);
}
}
internal static GetRestorePathData GetRestorePath(
string wkPath,
string restorePath,
string explanation,
bool isDirectory,
bool showSkipButton,
EditorWindow parentWindow)
{
GetRestorePathDialog dialog = Create(
new ProgressControlsForDialogs(),
wkPath,
GetProposedRestorePath.For(restorePath),
explanation,
isDirectory,
showSkipButton);
ResponseType dialogResult = dialog.RunModal(parentWindow);
GetRestorePathData result = dialog.BuildGetRestorePathResult();
result.Result = GetRestorePathResultType(dialogResult);
return result;
}
protected override void OnModalGUI()
{
Title(PlasticLocalization.GetString(
PlasticLocalization.Name.EnterRestorePathFormTitle));
Paragraph(mExplanation);
DoEntryArea();
GUILayout.Space(10);
DrawProgressForDialogs.For(
mProgressControls.ProgressData);
DoButtonsArea();
mProgressControls.ForcedUpdateProgress(this);
}
void DoEntryArea()
{
GUILayout.Label(PlasticLocalization.GetString(
PlasticLocalization.Name.EnterRestorePathFormTextBoxExplanation),
EditorStyles.label);
GUILayout.BeginHorizontal();
mRestorePath = GUILayout.TextField(
mRestorePath, GUILayout.Width(TEXTBOX_WIDTH));
if (GUILayout.Button("...", EditorStyles.miniButton))
{
mRestorePath = (mIsDirectory) ?
DoOpenFolderPanel(mRestorePath) :
DoOpenFilePanel(mRestorePath);
}
GUILayout.EndHorizontal();
}
protected override string GetTitle()
{
return PlasticLocalization.GetString(
PlasticLocalization.Name.EnterRestorePathFormTitle);
}
static string DoOpenFolderPanel(string actualPath)
{
string parentDirectory = null;
string directoryName = null;
if (!string.IsNullOrEmpty(actualPath))
{
parentDirectory = Path.GetDirectoryName(actualPath);
directoryName = Path.GetFileName(actualPath);
}
string result = EditorUtility.SaveFolderPanel(
PlasticLocalization.GetString(PlasticLocalization.Name.SelectPathToRestore),
parentDirectory,
directoryName);
if (string.IsNullOrEmpty(result))
return actualPath;
return Path.GetFullPath(result);
}
static string DoOpenFilePanel(string actualPath)
{
string parentDirectory = null;
string fileName = null;
string extension = null;
if (!string.IsNullOrEmpty(actualPath))
{
parentDirectory = Path.GetDirectoryName(actualPath);
fileName = Path.GetFileName(actualPath);
extension = Path.GetExtension(actualPath);
}
string result = EditorUtility.SaveFilePanel(
PlasticLocalization.GetString(PlasticLocalization.Name.SelectPathToRestore),
parentDirectory,
fileName,
extension);
if (string.IsNullOrEmpty(result))
return actualPath;
return Path.GetFullPath(result);
}
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
DoOkButton();
DoSkipButton(mShowSkipButton);
DoCancelButton();
return;
}
DoCancelButton();
DoSkipButton(mShowSkipButton);
DoOkButton();
}
}
void DoOkButton()
{
if (!AcceptButton(PlasticLocalization.GetString(
PlasticLocalization.Name.OkButton)))
return;
OkButtonWithValidationAction();
}
void DoSkipButton(bool showSkipButton)
{
if (!showSkipButton)
return;
if (!NormalButton(PlasticLocalization.GetString(PlasticLocalization.Name.SkipRestoreButton)))
return;
CloseButtonAction();
}
void DoCancelButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
return;
CancelButtonAction();
}
void OkButtonWithValidationAction()
{
GetRestorePathValidation.Validation(
mWkPath, BuildGetRestorePathResult(),
this, mProgressControls);
}
GetRestorePathData BuildGetRestorePathResult()
{
return new GetRestorePathData(mRestorePath);
}
static GetRestorePathData.ResultType GetRestorePathResultType(
ResponseType dialogResult)
{
switch (dialogResult)
{
case ResponseType.None:
return GetRestorePathData.ResultType.Skip;
case ResponseType.Ok:
return GetRestorePathData.ResultType.OK;
case ResponseType.Cancel:
return GetRestorePathData.ResultType.Cancel;
}
return GetRestorePathData.ResultType.Cancel;
}
static GetRestorePathDialog Create(
ProgressControlsForDialogs progressControls,
string wkPath,
string restorePath,
string explanation,
bool isDirectory,
bool showSkipButton)
{
var instance = CreateInstance<GetRestorePathDialog>();
instance.mWkPath = wkPath;
instance.mRestorePath = restorePath;
instance.mExplanation = explanation;
instance.mIsDirectory = isDirectory;
instance.mShowSkipButton = showSkipButton;
instance.mEnterKeyAction = instance.OkButtonWithValidationAction;
instance.mEscapeKeyAction = instance.CancelButtonAction;
instance.mProgressControls = progressControls;
return instance;
}
bool mIsDirectory;
bool mShowSkipButton;
string mExplanation = string.Empty;
string mRestorePath = string.Empty;
string mWkPath = string.Empty;
ProgressControlsForDialogs mProgressControls;
const float TEXTBOX_WIDTH = 520;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 281456381b1a4c742b0efbe305328c7a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,531 @@
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.Client.Commands;
using Codice.Client.Common;
using Codice.Client.Common.EventTracking;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.BrowseRepository;
using PlasticGui.WorkspaceWindow.Diff;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.Tool;
using Unity.PlasticSCM.Editor.Views.Diff.Dialogs;
using Unity.PlasticSCM.Editor.Views.History;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal class DiffPanel :
IDiffTreeViewMenuOperations,
DiffTreeViewMenu.IMetaMenuOperations,
UndeleteClientDiffsOperation.IGetRestorePathDialog
{
internal DiffPanel(
WorkspaceInfo wkInfo,
IWorkspaceWindow workspaceWindow,
IRefreshView refreshView,
IViewSwitcher viewSwitcher,
IHistoryViewLauncher historyViewLauncher,
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
EditorWindow parentWindow,
bool isGluonMode)
{
mWkInfo = wkInfo;
mWorkspaceWindow = workspaceWindow;
mRefreshView = refreshView;
mViewSwitcher = viewSwitcher;
mHistoryViewLauncher = historyViewLauncher;
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mParentWindow = parentWindow;
mGuiMessage = new UnityPlasticGuiMessage();
mIsGluonMode = isGluonMode;
BuildComponents();
mProgressControls = new ProgressControlsForViews();
}
internal void ClearInfo()
{
ClearData();
mParentWindow.Repaint();
}
internal void UpdateInfo(
MountPointWithPath mountWithPath,
ChangesetInfo csetInfo)
{
FillData(mountWithPath, csetInfo);
mParentWindow.Repaint();
}
internal void OnDisable()
{
mSearchField.downOrUpArrowKeyPressed -=
SearchField_OnDownOrUpArrowKeyPressed;
}
internal void Update()
{
mProgressControls.UpdateProgress(mParentWindow);
}
internal void OnGUI()
{
EditorGUILayout.BeginVertical();
DoActionsToolbar(
mDiffs,
mDiffsBranchResolver,
mProgressControls,
mIsSkipMergeTrackingButtonVisible,
mIsSkipMergeTrackingButtonChecked,
mSearchField,
mDiffTreeView);
DoDiffTreeViewArea(
mDiffTreeView,
mProgressControls.IsOperationRunning());
if (mProgressControls.HasNotification())
{
DrawProgressForViews.ForNotificationArea(
mProgressControls.ProgressData);
}
EditorGUILayout.EndVertical();
}
void IDiffTreeViewMenuOperations.SaveRevisionAs()
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.SaveRevisionFromDiff);
ClientDiffInfo clientDiffInfo =
DiffSelection.GetSelectedDiff(mDiffTreeView);
RepositorySpec repSpec = clientDiffInfo.DiffWithMount.Mount.RepSpec;
RevisionInfo revision = clientDiffInfo.DiffWithMount.Difference.RevInfo;
string defaultFileName = DefaultRevisionName.Get(
Path.GetFileName(clientDiffInfo.DiffWithMount.Difference.Path), revision.Changeset);
string destinationPath = SaveAction.GetDestinationPath(
mWkInfo.ClientPath,
clientDiffInfo.DiffWithMount.Difference.Path,
defaultFileName);
if (string.IsNullOrEmpty(destinationPath))
return;
SaveRevisionOperation.SaveRevision(
repSpec,
destinationPath,
revision,
mProgressControls);
}
SelectedDiffsGroupInfo IDiffTreeViewMenuOperations.GetSelectedDiffsGroupInfo()
{
return SelectedDiffsGroupInfo.BuildFromSelectedNodes(
DiffSelection.GetSelectedDiffsWithoutMeta(mDiffTreeView));
}
void IDiffTreeViewMenuOperations.Diff()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffRevision,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffRevision,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffRevision))
return;
ClientDiffInfo clientDiffInfo =
DiffSelection.GetSelectedDiff(mDiffTreeView);
DiffOperation.DiffClientDiff(
mWkInfo,
clientDiffInfo.DiffWithMount.Mount.Mount,
clientDiffInfo.DiffWithMount.Difference,
xDiffLauncher: null,
imageDiffLauncher: null);
}
void IDiffTreeViewMenuOperations.History()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromShowHistory,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromShowHistory,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromShowHistory))
return;
ClientDiffInfo clientDiffInfo =
DiffSelection.GetSelectedDiff(mDiffTreeView);
mHistoryViewLauncher.ShowHistoryView(
clientDiffInfo.DiffWithMount.Mount.RepSpec,
clientDiffInfo.DiffWithMount.Difference.RevInfo.ItemId,
clientDiffInfo.DiffWithMount.Difference.Path,
clientDiffInfo.DiffWithMount.Difference.IsDirectory);
}
void IDiffTreeViewMenuOperations.RevertChanges()
{
RevertClientDiffsOperation.RevertChanges(
mWkInfo,
DiffSelection.GetSelectedDiffs(mDiffTreeView),
mWorkspaceWindow,
mProgressControls,
mGuiMessage,
AfterRevertOrUndeleteOperation);
}
void IDiffTreeViewMenuOperations.Undelete()
{
UndeleteClientDiffsOperation.Undelete(
mWkInfo,
DiffSelection.GetSelectedDiffs(mDiffTreeView),
mRefreshView,
mProgressControls,
this,
mGuiMessage,
AfterRevertOrUndeleteOperation);
}
void IDiffTreeViewMenuOperations.UndeleteToSpecifiedPaths()
{
UndeleteClientDiffsOperation.UndeleteToSpecifiedPaths(
mWkInfo,
DiffSelection.GetSelectedDiffs(mDiffTreeView),
mRefreshView,
mProgressControls,
this,
mGuiMessage,
AfterRevertOrUndeleteOperation);
}
bool DiffTreeViewMenu.IMetaMenuOperations.SelectionHasMeta()
{
return mDiffTreeView.SelectionHasMeta();
}
void DiffTreeViewMenu.IMetaMenuOperations.DiffMeta()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffRevision,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffRevision,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffRevision))
return;
ClientDiffInfo clientDiffInfo =
DiffSelection.GetSelectedDiff(mDiffTreeView);
ClientDiffInfo clientDiffInfoMeta =
mDiffTreeView.GetMetaDiff(clientDiffInfo);
DiffOperation.DiffClientDiff(
mWkInfo,
clientDiffInfoMeta.DiffWithMount.Mount.Mount,
clientDiffInfoMeta.DiffWithMount.Difference,
xDiffLauncher: null,
imageDiffLauncher: null);
}
GetRestorePathData
UndeleteClientDiffsOperation.IGetRestorePathDialog.GetRestorePath(
string wkPath, string restorePath, string explanation,
bool isDirectory, bool showSkipButton)
{
return GetRestorePathDialog.GetRestorePath(
wkPath, restorePath, explanation, isDirectory,
showSkipButton, mParentWindow);
}
void DiffTreeViewMenu.IMetaMenuOperations.HistoryMeta()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromShowHistory,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromShowHistory,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromShowHistory))
return;
ClientDiffInfo clientDiffInfo =
DiffSelection.GetSelectedDiff(mDiffTreeView);
ClientDiffInfo clientDiffInfoMeta =
mDiffTreeView.GetMetaDiff(clientDiffInfo);
mHistoryViewLauncher.ShowHistoryView(
clientDiffInfoMeta.DiffWithMount.Mount.RepSpec,
clientDiffInfoMeta.DiffWithMount.Difference.RevInfo.ItemId,
clientDiffInfoMeta.DiffWithMount.Difference.Path,
clientDiffInfoMeta.DiffWithMount.Difference.IsDirectory);
}
void SearchField_OnDownOrUpArrowKeyPressed()
{
mDiffTreeView.SetFocusAndEnsureSelectedItem();
}
void AfterRevertOrUndeleteOperation()
{
RefreshAsset.UnityAssetDatabase();
mViewSwitcher.ShowPendingChanges();
}
void ClearData()
{
mSelectedMountWithPath = null;
mSelectedChangesetInfo = null;
mDiffs = null;
ClearDiffs();
}
void FillData(
MountPointWithPath mountWithPath,
ChangesetInfo csetInfo)
{
mSelectedMountWithPath = mountWithPath;
mSelectedChangesetInfo = csetInfo;
((IProgressControls)mProgressControls).ShowProgress(
PlasticLocalization.GetString(PlasticLocalization.Name.Loading));
mIsSkipMergeTrackingButtonVisible = false;
IThreadWaiter waiter = ThreadWaiter.GetWaiter(100);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
mDiffs = PlasticGui.Plastic.API.GetChangesetDifferences(
mountWithPath, csetInfo);
mDiffsBranchResolver = BuildBranchResolver.ForDiffs(mDiffs);
},
/*afterOperationDelegate*/ delegate
{
((IProgressControls)mProgressControls).HideProgress();
if (waiter.Exception != null)
{
ExceptionsHandler.DisplayException(waiter.Exception);
return;
}
if (mSelectedMountWithPath != mountWithPath ||
mSelectedChangesetInfo != csetInfo)
return;
if (mDiffs == null || mDiffs.Count == 0)
{
ClearDiffs();
return;
}
mIsSkipMergeTrackingButtonVisible =
ClientDiffList.HasMerges(mDiffs);
bool skipMergeTracking =
mIsSkipMergeTrackingButtonVisible &&
mIsSkipMergeTrackingButtonChecked;
UpdateDiffTreeView(
mWkInfo,
mDiffs,
mDiffsBranchResolver,
skipMergeTracking,
mDiffTreeView);
});
}
void ClearDiffs()
{
mIsSkipMergeTrackingButtonVisible = false;
ClearDiffTreeView(mDiffTreeView);
((IProgressControls)mProgressControls).ShowNotification(
PlasticLocalization.GetString(PlasticLocalization.Name.NoContentToCompare));
}
static void ClearDiffTreeView(
DiffTreeView diffTreeView)
{
diffTreeView.ClearModel();
diffTreeView.Reload();
}
static void UpdateDiffTreeView(
WorkspaceInfo wkInfo,
List<ClientDiff> diffs,
BranchResolver brResolver,
bool skipMergeTracking,
DiffTreeView diffTreeView)
{
diffTreeView.BuildModel(
wkInfo, diffs, brResolver, skipMergeTracking);
diffTreeView.Refilter();
diffTreeView.Sort();
diffTreeView.Reload();
}
void DoActionsToolbar(
List<ClientDiff> diffs,
BranchResolver brResolver,
ProgressControlsForViews progressControls,
bool isSkipMergeTrackingButtonVisible,
bool isSkipMergeTrackingButtonChecked,
SearchField searchField,
DiffTreeView diffTreeView)
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
if (progressControls.IsOperationRunning())
{
DrawProgressForViews.ForIndeterminateProgress(
progressControls.ProgressData);
}
GUILayout.FlexibleSpace();
if (isSkipMergeTrackingButtonVisible)
{
DoSkipMergeTrackingButton(
diffs, brResolver,
isSkipMergeTrackingButtonChecked,
diffTreeView);
}
DrawSearchField.For(
searchField,
diffTreeView,
UnityConstants.SEARCH_FIELD_WIDTH);
VerifyIfSearchFieldIsRecentlyFocused(searchField);
EditorGUILayout.EndHorizontal();
}
void VerifyIfSearchFieldIsRecentlyFocused(SearchField searchField)
{
if (searchField.HasFocus() != mIsSearchFieldFocused)
{
mIsSearchFieldFocused = !mIsSearchFieldFocused;
if (mIsSearchFieldFocused)
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.ChangesetViewDiffSearchBox);
}
}
}
void DoSkipMergeTrackingButton(
List<ClientDiff> diffs,
BranchResolver brResolver,
bool isSkipMergeTrackingButtonChecked,
DiffTreeView diffTreeView)
{
bool wasChecked = isSkipMergeTrackingButtonChecked;
GUIContent buttonContent = new GUIContent(
PlasticLocalization.GetString(
PlasticLocalization.Name.SkipDiffMergeTracking));
GUIStyle buttonStyle = new GUIStyle(EditorStyles.toolbarButton);
float buttonWidth = buttonStyle.CalcSize(buttonContent).x + 10;
Rect toggleRect = GUILayoutUtility.GetRect(
buttonContent, buttonStyle, GUILayout.Width(buttonWidth));
bool isChecked = GUI.Toggle(
toggleRect, wasChecked, buttonContent, buttonStyle);
if (wasChecked == isChecked)
return;
// if user just checked the skip merge tracking button
if (isChecked)
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.ChangesetViewSkipMergeTrackingButton);
}
UpdateDiffTreeView(mWkInfo, diffs, brResolver, isChecked, diffTreeView);
mIsSkipMergeTrackingButtonChecked = isChecked;
}
static void DoDiffTreeViewArea(
DiffTreeView diffTreeView,
bool isOperationRunning)
{
GUI.enabled = !isOperationRunning;
Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
diffTreeView.OnGUI(rect);
GUI.enabled = true;
}
void BuildComponents()
{
mSearchField = new SearchField();
mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
mDiffTreeView = new DiffTreeView(new DiffTreeViewMenu(this, this));
mDiffTreeView.Reload();
}
volatile List<ClientDiff> mDiffs;
volatile BranchResolver mDiffsBranchResolver;
bool mIsSkipMergeTrackingButtonVisible;
bool mIsSkipMergeTrackingButtonChecked;
SearchField mSearchField;
bool mIsSearchFieldFocused = false;
DiffTreeView mDiffTreeView;
ChangesetInfo mSelectedChangesetInfo;
MountPointWithPath mSelectedMountWithPath;
readonly ProgressControlsForViews mProgressControls;
readonly GuiMessage.IGuiMessage mGuiMessage;
readonly EditorWindow mParentWindow;
readonly IRefreshView mRefreshView;
readonly IWorkspaceWindow mWorkspaceWindow;
readonly IHistoryViewLauncher mHistoryViewLauncher;
readonly IViewSwitcher mViewSwitcher;
readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
readonly WorkspaceInfo mWkInfo;
readonly bool mIsGluonMode;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ee79162e06c6984a97600b7c0680611
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using PlasticGui.WorkspaceWindow.Diff;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal static class DiffSelection
{
internal static List<ClientDiffInfo> GetSelectedDiffs(
DiffTreeView treeView)
{
return treeView.GetSelectedDiffs(true);
}
internal static List<ClientDiffInfo> GetSelectedDiffsWithoutMeta(
DiffTreeView treeView)
{
return treeView.GetSelectedDiffs(false);
}
internal static ClientDiffInfo GetSelectedDiff(
DiffTreeView treeView)
{
if (!treeView.HasSelection())
return null;
return treeView.GetSelectedDiffs(false)[0];
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ef5fb54cd29b40468eaf5a14e9845ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,565 @@
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.Client.Commands;
using Codice.Client.Common;
using Codice.CM.Common;
using Codice.Utils;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Diff;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal class DiffTreeView : TreeView
{
internal DiffTreeView(DiffTreeViewMenu menu)
: base(new TreeViewState())
{
mMenu = menu;
customFoldoutYOffset = UnityConstants.TREEVIEW_FOLDOUT_Y_OFFSET;
rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
showAlternatingRowBackgrounds = false;
mCooldownFilterAction = new CooldownWindowDelayer(
DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
EnableHorizontalScrollbar();
}
public override IList<TreeViewItem> GetRows()
{
return mRows;
}
public override void OnGUI(Rect rect)
{
base.OnGUI(rect);
Event e = Event.current;
if (e.type != EventType.KeyDown)
return;
bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
if (isProcessed)
e.Use();
}
protected override bool CanChangeExpandedState(TreeViewItem item)
{
return item is ChangeCategoryTreeViewItem
|| item is MergeCategoryTreeViewItem;
}
protected override TreeViewItem BuildRoot()
{
return new TreeViewItem(0, -1, string.Empty);
}
protected override IList<TreeViewItem> BuildRows(TreeViewItem rootItem)
{
try
{
RegenerateRows(
mDiffTree,
mTreeViewItemIds,
this,
rootItem,
mRows,
mExpandCategories);
}
finally
{
mExpandCategories = false;
}
return mRows;
}
protected override void CommandEventHandling()
{
// NOTE - empty override to prevent crash when pressing ctrl-a in the treeview
}
protected override void SearchChanged(string newSearch)
{
mCooldownFilterAction.Ping();
}
protected override void ContextClickedItem(int id)
{
mMenu.Popup();
Repaint();
}
protected override void BeforeRowsGUI()
{
int firstRowVisible;
int lastRowVisible;
GetFirstAndLastVisibleRows(out firstRowVisible, out lastRowVisible);
GUI.DrawTexture(new Rect(0,
firstRowVisible * rowHeight,
GetRowRect(0).width + 500,
(lastRowVisible * rowHeight) + 1500),
Images.GetTreeviewBackgroundTexture());
DrawTreeViewItem.InitializeStyles();
mLargestRowWidth = 0;
base.BeforeRowsGUI();
}
protected override void RowGUI(RowGUIArgs args)
{
float itemWidth;
TreeViewItemGUI(
args.item, args.rowRect, rowHeight, mDiffTree, args.selected, args.focused, out itemWidth);
float rowWidth = baseIndent + args.item.depth * depthIndentWidth +
itemWidth + UnityConstants.TREEVIEW_ROW_WIDTH_OFFSET;
if (rowWidth > mLargestRowWidth)
mLargestRowWidth = rowWidth;
}
protected override void AfterRowsGUI()
{
if (mHorizontalColumn != null)
mHorizontalColumn.width = mLargestRowWidth;
base.AfterRowsGUI();
}
internal void ClearModel()
{
mTreeViewItemIds.Clear();
mDiffTree = new UnityDiffTree();
}
internal void BuildModel(
WorkspaceInfo wkInfo,
List<ClientDiff> diffs,
BranchResolver brResolver,
bool skipMergeTracking)
{
mTreeViewItemIds.Clear();
mDiffTree.BuildCategories(wkInfo, diffs, brResolver, skipMergeTracking);
}
internal void Refilter()
{
Filter filter = new Filter(searchString);
mDiffTree.Filter(filter, ColumnsNames);
mExpandCategories = true;
}
internal void Sort()
{
mDiffTree.Sort(
PlasticLocalization.GetString(PlasticLocalization.Name.PathColumn),
sortAscending: true);
}
internal ClientDiffInfo GetMetaDiff(ClientDiffInfo diff)
{
return mDiffTree.GetMetaDiff(diff);
}
internal bool SelectionHasMeta()
{
if (!HasSelection())
return false;
ClientDiffInfo selectedDiff = GetSelectedDiffs(false)[0];
if (selectedDiff == null)
return false;
return mDiffTree.HasMeta(selectedDiff);
}
internal List<ClientDiffInfo> GetSelectedDiffs(bool includeMetaFiles)
{
List<ClientDiffInfo> result = new List<ClientDiffInfo>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<ITreeViewNode, int> item
in mTreeViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
if (!(item.Key is ClientDiffInfo))
continue;
result.Add((ClientDiffInfo)item.Key);
}
if (includeMetaFiles)
mDiffTree.FillWithMeta(result);
return result;
}
void DelayedSearchChanged()
{
Refilter();
Sort();
Reload();
TableViewOperations.ScrollToSelection(this);
}
void EnableHorizontalScrollbar()
{
mHorizontalColumn = new MultiColumnHeaderState.Column();
mHorizontalColumn.autoResize = false;
MultiColumnHeaderState.Column[] cols = { mHorizontalColumn };
MultiColumnHeaderState headerState = new MultiColumnHeaderState(cols);
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.height = 0f;
}
static void RegenerateRows(
UnityDiffTree diffTree,
TreeViewItemIds<IDiffCategory, ITreeViewNode> treeViewItemIds,
TreeView treeView,
TreeViewItem rootItem,
List<TreeViewItem> rows,
bool expandCategories)
{
ClearRows(rootItem, rows);
List<IDiffCategory> categories = diffTree.GetNodes();
if (categories == null)
return;
foreach (IDiffCategory category in categories)
{
if (category is CategoryGroup &&
((CategoryGroup)category).CategoryType == CategoryGroup.Type.MergeCategory)
{
AddMergeCategory(
rootItem,
category,
rows,
treeViewItemIds,
treeView,
expandCategories);
}
if (category is ChangeCategory)
{
AddChangeCategory(
rootItem,
category,
rows,
treeViewItemIds,
treeView,
expandCategories);
}
}
if (!expandCategories)
return;
treeView.state.expandedIDs = treeViewItemIds.GetCategoryIds();
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static void AddMergeCategory(
TreeViewItem rootItem,
IDiffCategory category,
List<TreeViewItem> rows,
TreeViewItemIds<IDiffCategory, ITreeViewNode> treeViewItemIds,
TreeView treeView,
bool expandCategories)
{
int categoryId;
if (!treeViewItemIds.TryGetCategoryItemId(category, out categoryId))
categoryId = treeViewItemIds.AddCategoryItem(category);
MergeCategoryTreeViewItem mergeCategoryTreeViewItem =
new MergeCategoryTreeViewItem(
categoryId,
rootItem.depth + 1,
(CategoryGroup)category);
rootItem.AddChild(mergeCategoryTreeViewItem);
rows.Add(mergeCategoryTreeViewItem);
if (!expandCategories &&
!treeView.IsExpanded(mergeCategoryTreeViewItem.id))
return;
for (int i = 0; i < category.GetChildrenCount(); i++)
{
IDiffCategory child = (IDiffCategory)((ITreeViewNode)category)
.GetChild(i);
AddChangeCategory(
mergeCategoryTreeViewItem,
child,
rows,
treeViewItemIds,
treeView,
expandCategories);
}
}
static void AddChangeCategory(
TreeViewItem parentItem,
IDiffCategory category,
List<TreeViewItem> rows,
TreeViewItemIds<IDiffCategory, ITreeViewNode> treeViewItemIds,
TreeView treeView,
bool expandCategories)
{
int categoryId;
if (!treeViewItemIds.TryGetCategoryItemId(category, out categoryId))
categoryId = treeViewItemIds.AddCategoryItem(category);
ChangeCategoryTreeViewItem changeCategoryTreeViewItem =
new ChangeCategoryTreeViewItem(
categoryId,
parentItem.depth + 1,
(ChangeCategory)category);
parentItem.AddChild(changeCategoryTreeViewItem);
rows.Add(changeCategoryTreeViewItem);
if (!expandCategories &&
!treeView.IsExpanded(changeCategoryTreeViewItem.id))
return;
AddClientDiffs(
changeCategoryTreeViewItem,
(ITreeViewNode)category,
rows,
treeViewItemIds);
}
static void AddClientDiffs(
TreeViewItem parentItem,
ITreeViewNode parentNode,
List<TreeViewItem> rows,
TreeViewItemIds<IDiffCategory, ITreeViewNode> treeViewItemIds)
{
for (int i = 0; i < parentNode.GetChildrenCount(); i++)
{
ITreeViewNode child = parentNode.GetChild(i);
int nodeId;
if (!treeViewItemIds.TryGetInfoItemId(child, out nodeId))
nodeId = treeViewItemIds.AddInfoItem(child);
TreeViewItem changeTreeViewItem =
new ClientDiffTreeViewItem(
nodeId,
parentItem.depth + 1,
(ClientDiffInfo)child);
parentItem.AddChild(changeTreeViewItem);
rows.Add(changeTreeViewItem);
}
}
static void TreeViewItemGUI(
TreeViewItem item,
Rect rowRect,
float rowHeight,
UnityDiffTree diffTree,
bool isSelected,
bool isFocused,
out float itemWidth)
{
if (item is MergeCategoryTreeViewItem)
{
MergeCategoryTreeViewItemGUI(
rowRect,
(MergeCategoryTreeViewItem)item,
isSelected,
isFocused,
out itemWidth);
return;
}
if (item is ChangeCategoryTreeViewItem)
{
ChangeCategoryTreeViewItemGUI(
rowRect,
(ChangeCategoryTreeViewItem)item,
isSelected,
isFocused,
out itemWidth);
return;
}
if (item is ClientDiffTreeViewItem)
{
ClientDiffTreeViewItemGUI(
rowRect,
rowHeight,
diffTree,
(ClientDiffTreeViewItem)item,
isSelected,
isFocused,
out itemWidth);
return;
}
itemWidth = 0;
}
static void MergeCategoryTreeViewItemGUI(
Rect rowRect,
MergeCategoryTreeViewItem item,
bool isSelected,
bool isFocused,
out float itemWidth)
{
string label = item.Category.CategoryName;
string infoLabel = PlasticLocalization.Name.ItemsCount.GetString(
item.Category.GetChildrenCount());
itemWidth = CalculateLabelWidth(label);
DrawTreeViewItem.ForCategoryItem(
rowRect,
item.depth,
label,
infoLabel,
isSelected,
isFocused);
}
static void ChangeCategoryTreeViewItemGUI(
Rect rowRect,
ChangeCategoryTreeViewItem item,
bool isSelected,
bool isFocused,
out float itemWidth)
{
string label = item.Category.CategoryName;
string infoLabel = PlasticLocalization.Name.ItemsCount.GetString(
item.Category.GetChildrenCount());
itemWidth = CalculateLabelWidth(label);
DrawTreeViewItem.ForCategoryItem(
rowRect,
item.depth,
label,
infoLabel,
isSelected,
isFocused);
}
static void ClientDiffTreeViewItemGUI(
Rect rowRect,
float rowHeight,
UnityDiffTree diffTree,
ClientDiffTreeViewItem item,
bool isSelected,
bool isFocused,
out float itemWidth)
{
string label = ClientDiffView.GetColumnText(
item.Difference.DiffWithMount.Mount.RepSpec,
item.Difference.DiffWithMount.Difference,
PlasticLocalization.GetString(PlasticLocalization.Name.PathColumn));
if (diffTree.HasMeta(item.Difference))
label = string.Concat(label, UnityConstants.TREEVIEW_META_LABEL);
Texture icon = GetClientDiffIcon(
item.Difference.DiffWithMount.Difference.IsDirectory,
label);
itemWidth = CalculateItemWidth(label, icon, rowHeight);
DrawTreeViewItem.ForItemCell(
rowRect,
rowHeight,
item.depth,
icon,
null,
label,
isSelected,
isFocused,
false,
false);
}
static float CalculateItemWidth(
string label,
Texture icon,
float rowHeight)
{
float labelWidth = CalculateLabelWidth(label);
float iconWidth = rowHeight * ((float)icon.width / icon.height);
return labelWidth + iconWidth;
}
static float CalculateLabelWidth(string label)
{
GUIContent content = new GUIContent(label);
Vector2 contentSize = DefaultStyles.label.CalcSize(content);
return contentSize.x;
}
static Texture GetClientDiffIcon(bool isDirectory, string path)
{
if (isDirectory)
return Images.GetDirectoryIcon();
return Images.GetFileIconFromCmPath(path);
}
bool mExpandCategories;
TreeViewItemIds<IDiffCategory, ITreeViewNode> mTreeViewItemIds =
new TreeViewItemIds<IDiffCategory, ITreeViewNode>();
List<TreeViewItem> mRows = new List<TreeViewItem>();
UnityDiffTree mDiffTree = new UnityDiffTree();
MultiColumnHeaderState.Column mHorizontalColumn;
float mLargestRowWidth;
readonly CooldownWindowDelayer mCooldownFilterAction;
static readonly List<string> ColumnsNames = new List<string> {
PlasticLocalization.GetString(PlasticLocalization.Name.PathColumn)};
readonly DiffTreeViewMenu mMenu;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ba4e6e12f66973142a87299287cb34dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,298 @@
using UnityEditor;
using UnityEngine;
using Codice.Client.Common.EventTracking;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Diff;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.Tool;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal class DiffTreeViewMenu
{
internal interface IMetaMenuOperations
{
bool SelectionHasMeta();
void DiffMeta();
void HistoryMeta();
}
internal DiffTreeViewMenu(
IDiffTreeViewMenuOperations operations,
IMetaMenuOperations metaMenuOperations)
{
mOperations = operations;
mMetaMenuOperations = metaMenuOperations;
BuildComponents();
}
internal void Popup()
{
GenericMenu menu = new GenericMenu();
UpdateMenuItems(menu);
menu.ShowAsContext();
}
internal bool ProcessKeyActionIfNeeded(Event e)
{
DiffTreeViewMenuOperations operationToExecute = GetMenuOperation(e);
if (operationToExecute == DiffTreeViewMenuOperations.None)
return false;
SelectedDiffsGroupInfo info =
mOperations.GetSelectedDiffsGroupInfo();
DiffTreeViewMenuOperations operations =
DiffTreeViewMenuUpdater.GetAvailableMenuOperations(info);
if (!operations.HasFlag(operationToExecute))
return false;
ProcessMenuOperation(operationToExecute);
return true;
}
void SaveRevisionAsMenuItem_Click()
{
mOperations.SaveRevisionAs();
}
void DiffMenuItem_Click()
{
mOperations.Diff();
}
void DiffMetaMenuItem_Click()
{
mMetaMenuOperations.DiffMeta();
}
void HistoryMenuItem_Click()
{
mOperations.History();
}
void HistoryMetaMenuItem_Click()
{
mMetaMenuOperations.HistoryMeta();
}
void RevertMenuItem_Click()
{
mOperations.RevertChanges();
}
void UndeleteMenuItem_Click()
{
mOperations.Undelete();
}
void UndeleteToSpecifiedPathMenuItem_Click()
{
mOperations.UndeleteToSpecifiedPaths();
}
void UpdateMenuItems(GenericMenu menu)
{
SelectedDiffsGroupInfo groupInfo =
mOperations.GetSelectedDiffsGroupInfo();
DiffTreeViewMenuOperations operations =
DiffTreeViewMenuUpdater.GetAvailableMenuOperations(groupInfo);
if (operations == DiffTreeViewMenuOperations.None)
{
menu.AddDisabledItem(GetNoActionMenuItemContent());
return;
}
bool isMultipleSelection = groupInfo.SelectedItemsCount > 1;
bool selectionHasMeta = mMetaMenuOperations.SelectionHasMeta();
if (operations.HasFlag(DiffTreeViewMenuOperations.SaveAs))
menu.AddItem(mSaveRevisionAsMenuItemContent, false, SaveRevisionAsMenuItem_Click);
if (operations.HasFlag(DiffTreeViewMenuOperations.Diff))
menu.AddItem(mDiffMenuItemContent, false, DiffMenuItem_Click);
else
menu.AddDisabledItem(mDiffMenuItemContent, false);
if (mMetaMenuOperations.SelectionHasMeta())
{
if (operations.HasFlag(DiffTreeViewMenuOperations.Diff))
menu.AddItem(mDiffMetaMenuItemContent, false, DiffMetaMenuItem_Click);
else
menu.AddDisabledItem(mDiffMetaMenuItemContent);
}
menu.AddSeparator(string.Empty);
if (operations.HasFlag(DiffTreeViewMenuOperations.History))
menu.AddItem(mViewHistoryMenuItemContent, false, HistoryMenuItem_Click);
else
menu.AddDisabledItem(mViewHistoryMenuItemContent, false);
if (mMetaMenuOperations.SelectionHasMeta())
{
if (operations.HasFlag(DiffTreeViewMenuOperations.History))
menu.AddItem(mViewHistoryMetaMenuItemContent, false, HistoryMetaMenuItem_Click);
else
menu.AddDisabledItem(mViewHistoryMetaMenuItemContent, false);
}
if (operations.HasFlag(DiffTreeViewMenuOperations.RevertChanges))
{
menu.AddSeparator(string.Empty);
mRevertMenuItemContent.text = GetRevertMenuItemText(
isMultipleSelection,
selectionHasMeta);
menu.AddItem(mRevertMenuItemContent, false, RevertMenuItem_Click);
}
if (operations.HasFlag(DiffTreeViewMenuOperations.Undelete) ||
operations.HasFlag(DiffTreeViewMenuOperations.UndeleteToSpecifiedPaths))
{
menu.AddSeparator(string.Empty);
}
if (operations.HasFlag(DiffTreeViewMenuOperations.Undelete))
{
mUndeleteMenuItemContent.text = GetUndeleteMenuItemText(
isMultipleSelection,
selectionHasMeta);
menu.AddItem(mUndeleteMenuItemContent, false, UndeleteMenuItem_Click);
}
if (operations.HasFlag(DiffTreeViewMenuOperations.UndeleteToSpecifiedPaths))
{
mUndeleteToSpecifiedPathMenuItemContent.text = GetUndeleteToSpecifiedPathMenuItemText(
isMultipleSelection,
selectionHasMeta);
menu.AddItem(mUndeleteToSpecifiedPathMenuItemContent, false, UndeleteToSpecifiedPathMenuItem_Click);
}
}
GUIContent GetNoActionMenuItemContent()
{
if (mNoActionMenuItemContent == null)
{
mNoActionMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.
Name.NoActionMenuItem));
}
return mNoActionMenuItemContent;
}
static string GetRevertMenuItemText(
bool isMultipleSelection,
bool selectionHasMeta)
{
if (selectionHasMeta && !isMultipleSelection)
return PlasticLocalization.GetString(PlasticLocalization.Name.UndoThisChangePlusMeta);
return isMultipleSelection ?
PlasticLocalization.GetString(PlasticLocalization.Name.UndoSelectedChanges) :
PlasticLocalization.GetString(PlasticLocalization.Name.UndoThisChange);
}
static string GetUndeleteMenuItemText(
bool isMultipleSelection,
bool selectionHasMeta)
{
if (selectionHasMeta && !isMultipleSelection)
return PlasticLocalization.GetString(PlasticLocalization.Name.UndeleteRevisionPlusMeta);
return isMultipleSelection ?
PlasticLocalization.GetString(PlasticLocalization.Name.UndeleteSelectedRevisions) :
PlasticLocalization.GetString(PlasticLocalization.Name.UndeleteRevisions);
}
static string GetUndeleteToSpecifiedPathMenuItemText(
bool isMultipleSelection,
bool selectionHasMeta)
{
if (selectionHasMeta && !isMultipleSelection)
return PlasticLocalization.GetString(PlasticLocalization.Name.UndeleteRevisionPlusMetaPath);
return isMultipleSelection ?
PlasticLocalization.GetString(PlasticLocalization.Name.UndeleteSelectedRevisionsPaths) :
PlasticLocalization.GetString(PlasticLocalization.Name.UndeleteRevisionPath);
}
void ProcessMenuOperation(DiffTreeViewMenuOperations operationToExecute)
{
if (operationToExecute == DiffTreeViewMenuOperations.SaveAs)
{
SaveRevisionAsMenuItem_Click();
return;
}
if (operationToExecute == DiffTreeViewMenuOperations.Diff)
{
DiffMenuItem_Click();
return;
}
if (operationToExecute == DiffTreeViewMenuOperations.History)
{
HistoryMenuItem_Click();
}
}
static DiffTreeViewMenuOperations GetMenuOperation(Event e)
{
if (Keyboard.IsControlOrCommandKeyPressed(e) && Keyboard.IsKeyPressed(e, KeyCode.D))
return DiffTreeViewMenuOperations.Diff;
if (Keyboard.IsControlOrCommandKeyPressed(e) && Keyboard.IsKeyPressed(e, KeyCode.H))
return DiffTreeViewMenuOperations.History;
return DiffTreeViewMenuOperations.None;
}
void BuildComponents()
{
mSaveRevisionAsMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.DiffMenuItemSaveRevisionAs));
mDiffMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlasticLocalization.GetString(PlasticLocalization.Name.DiffMenuItem),
GetPlasticShortcut.ForDiff()));
mDiffMetaMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.DiffMetaMenuItem));
mViewHistoryMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlasticLocalization.GetString(PlasticLocalization.Name.ViewHistoryMenuItem),
GetPlasticShortcut.ForHistory()));
mViewHistoryMetaMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.ViewHistoryMetaMenuItem));
mRevertMenuItemContent = new GUIContent();
mUndeleteMenuItemContent = new GUIContent();
mUndeleteToSpecifiedPathMenuItemContent = new GUIContent();
}
GUIContent mNoActionMenuItemContent;
GUIContent mSaveRevisionAsMenuItemContent;
GUIContent mDiffMenuItemContent;
GUIContent mDiffMetaMenuItemContent;
GUIContent mViewHistoryMenuItemContent;
GUIContent mViewHistoryMetaMenuItemContent;
GUIContent mRevertMenuItemContent;
GUIContent mUndeleteMenuItemContent;
GUIContent mUndeleteToSpecifiedPathMenuItemContent;
readonly IDiffTreeViewMenuOperations mOperations;
readonly IMetaMenuOperations mMetaMenuOperations;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c9c0041347ae4e4cb794a3da850fa79
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using Codice.Utils;
using PlasticGui.WorkspaceWindow.Diff;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal static class GetClientDiffInfos
{
internal static List<ClientDiffInfo> FromCategories(List<IDiffCategory> categories)
{
List<ClientDiffInfo> result = new List<ClientDiffInfo>();
foreach (ITreeViewNode node in categories)
AddClientDiffInfos(node, result);
return result;
}
static void AddClientDiffInfos(ITreeViewNode node, List<ClientDiffInfo> result)
{
if (node is ClientDiffInfo)
{
result.Add((ClientDiffInfo)node);
return;
}
for (int i = 0; i < node.GetChildrenCount(); i++)
AddClientDiffInfos(node.GetChild(i), result);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ab43506dddfc244ab5b44585140c5a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using UnityEditor.IMGUI.Controls;
using PlasticGui.WorkspaceWindow.Diff;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal class MergeCategoryTreeViewItem : TreeViewItem
{
internal CategoryGroup Category { get; private set; }
internal MergeCategoryTreeViewItem(
int id, int depth, CategoryGroup categoryGroup)
: base(id, depth, categoryGroup.GetHeaderText())
{
Category = categoryGroup;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 923dacaaac477a941a4a5c7c1657a250
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,233 @@
using System.Collections.Generic;
using Codice.Client.Commands;
using Codice.Client.Common;
using Codice.CM.Common;
using Codice.Utils;
using PlasticGui;
using PlasticGui.Diff;
using PlasticGui.WorkspaceWindow.Diff;
namespace Unity.PlasticSCM.Editor.Views.Diff
{
internal class UnityDiffTree
{
internal UnityDiffTree()
{
mInnerTree = new DiffTree();
mMetaCache = new MetaCache();
}
internal void BuildCategories(
WorkspaceInfo wkInfo,
List<ClientDiff> diffs,
BranchResolver brResolver,
bool skipMergeTracking)
{
mInnerTree.BuildCategories(
RevisionInfoCodeReviewAdapter.CalculateCodeReviewEntries(
wkInfo,
diffs,
brResolver,
skipMergeTracking),
brResolver);
mMetaCache.Build(mInnerTree.GetNodes());
}
internal List<IDiffCategory> GetNodes()
{
return mInnerTree.GetNodes();
}
internal bool HasMeta(ClientDiffInfo difference)
{
return mMetaCache.ContainsMeta(difference);
}
internal ClientDiffInfo GetMetaDiff(ClientDiffInfo diff)
{
return mMetaCache.GetExistingMeta(diff);
}
internal void FillWithMeta(List<ClientDiffInfo> diffs)
{
diffs.AddRange(
mMetaCache.GetExistingMeta(diffs));
}
internal void Sort(string key, bool sortAscending)
{
mInnerTree.Sort(key, sortAscending);
}
internal void Filter(Filter filter, List<string> columnNames)
{
mInnerTree.Filter(filter, columnNames);
}
MetaCache mMetaCache = new MetaCache();
DiffTree mInnerTree;
class MetaCache
{
internal void Build(List<IDiffCategory> categories)
{
mCache.Clear();
HashSet<string> indexedKeys = BuildIndexedKeys(
GetClientDiffInfos.FromCategories(categories));
for (int i = 0; i < categories.Count; i++)
{
ExtractToMetaCache(
(ITreeViewNode)categories[i],
i,
mCache,
indexedKeys);
}
}
internal bool ContainsMeta(ClientDiffInfo diff)
{
return mCache.ContainsKey(
BuildKey.ForMetaDiff(diff));
}
internal ClientDiffInfo GetExistingMeta(ClientDiffInfo diff)
{
ClientDiffInfo result;
if (!mCache.TryGetValue(BuildKey.ForMetaDiff(diff), out result))
return null;
return result;
}
internal List<ClientDiffInfo> GetExistingMeta(List<ClientDiffInfo> diffs)
{
List<ClientDiffInfo> result = new List<ClientDiffInfo>();
foreach (ClientDiffInfo diff in diffs)
{
string key = BuildKey.ForMetaDiff(diff);
ClientDiffInfo metaDiff;
if (!mCache.TryGetValue(key, out metaDiff))
continue;
result.Add(metaDiff);
}
return result;
}
static void ExtractToMetaCache(
ITreeViewNode node,
int nodeIndex,
Dictionary<string, ClientDiffInfo> cache,
HashSet<string> indexedKeys)
{
if (node is ClientDiffInfo)
{
ClientDiffInfo diff = (ClientDiffInfo)node;
string path = diff.DiffWithMount.Difference.Path;
if (!MetaPath.IsMetaPath(path))
return;
string realPath = MetaPath.GetPathFromMetaPath(path);
if (!indexedKeys.Contains(BuildKey.BuildCacheKey(
BuildKey.GetCategoryGroup(diff),
BuildKey.GetChangeCategory(diff),
realPath)))
return;
// found foo.c and foo.c.meta
// with the same chage types - move .meta to cache
cache.Add(BuildKey.ForDiff(diff), diff);
((ChangeCategory)node.GetParent()).RemoveDiffAt(nodeIndex);
}
for (int i = node.GetChildrenCount() - 1; i >= 0; i--)
{
ExtractToMetaCache(
node.GetChild(i),
i,
cache,
indexedKeys);
}
}
HashSet<string> BuildIndexedKeys(List<ClientDiffInfo> diffs)
{
HashSet<string> result = new HashSet<string>();
foreach (ClientDiffInfo diff in diffs)
{
if (MetaPath.IsMetaPath(diff.DiffWithMount.Difference.Path))
continue;
result.Add(BuildKey.ForDiff(diff));
}
return result;
}
Dictionary<string, ClientDiffInfo> mCache =
new Dictionary<string, ClientDiffInfo>();
static class BuildKey
{
internal static string ForDiff(
ClientDiffInfo diff)
{
return BuildCacheKey(
GetCategoryGroup(diff),
GetChangeCategory(diff),
diff.DiffWithMount.Difference.Path);
}
internal static string ForMetaDiff(
ClientDiffInfo diff)
{
return BuildCacheKey(
GetCategoryGroup(diff),
GetChangeCategory(diff),
MetaPath.GetMetaPath(diff.DiffWithMount.Difference.Path));
}
internal static string BuildCacheKey(
CategoryGroup categoryGroup,
ChangeCategory changeCategory,
string path)
{
string result = string.Concat(changeCategory.Type, ":", path);
if (categoryGroup == null)
return result;
return string.Concat(categoryGroup.GetHeaderText(), ":", result);
}
internal static ChangeCategory GetChangeCategory(ClientDiffInfo diff)
{
return (ChangeCategory)diff.GetParent();
}
internal static CategoryGroup GetCategoryGroup(ClientDiffInfo diff)
{
ChangeCategory changeCategory = GetChangeCategory(diff);
ITreeViewNode categoryGroup = changeCategory.GetParent();
if (categoryGroup == null)
return null;
return (CategoryGroup)categoryGroup;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e89b1e9e9f1060b4f817977507831248
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,198 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using Codice.Client.Common;
using Codice.Client.Common.EventTracking;
using Codice.CM.Common;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI.UIElements;
using Unity.PlasticSCM.Editor.Views.Welcome;
using Unity.PlasticSCM.Editor.Tool;
namespace Unity.PlasticSCM.Editor.Views
{
internal class DownloadPlasticExeWindow :
EditorWindow,
DownloadAndInstallOperation.INotify
{
internal bool IsPlasticInstalling { get { return mIsPlasticInstalling; } }
internal static void ShowWindow(
RepositorySpec repSpec,
bool isGluonMode,
string installCloudFrom,
string installEnterpriseFrom,
string cancelInstallFrom)
{
DownloadPlasticExeWindow window = GetWindow<DownloadPlasticExeWindow>();
window.mRepSpec = repSpec;
window.mIsGluonMode = isGluonMode;
window.mInstallCloudFrom = installCloudFrom;
window.mInstallEnterpriseFrom = installEnterpriseFrom;
window.mCancelInstallFrom = cancelInstallFrom;
window.titleContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.Name.UnityVersionControl));
if (EditionToken.IsCloudEdition())
window.minSize = window.maxSize = new Vector2(700, 160);
else
window.minSize = window.maxSize = new Vector2(700, 230);
window.Show();
}
void DownloadAndInstallOperation.INotify.InstallationStarted()
{
mIsPlasticInstalling = true;
}
void DownloadAndInstallOperation.INotify.InstallationFinished()
{
mIsPlasticInstalling = false;
}
void OnEnable()
{
BuildComponents();
mInstallerFile = GetInstallerTmpFileName.ForPlatform();
}
void OnDestroy()
{
Dispose();
}
void Dispose()
{
mDownloadCloudEditionButton.clicked -= DownloadCloudEditionButton_Clicked;
if (!EditionToken.IsCloudEdition())
mDownloadEnterpriseButton.clicked -= DownloadEnterpriseEditionButton_Clicked;
mCancelButton.clicked -= CancelButton_Clicked;
EditorApplication.update -= CheckForPlasticExe;
}
void DownloadCloudEditionButton_Clicked()
{
TrackFeatureUseEvent.For(mRepSpec, mInstallCloudFrom);
DownloadAndInstallOperation.Run(
Edition.Cloud,
mInstallerFile,
mProgressControls,
this);
EditorApplication.update += CheckForPlasticExe;
}
void DownloadEnterpriseEditionButton_Clicked()
{
TrackFeatureUseEvent.For(mRepSpec, mInstallEnterpriseFrom);
DownloadAndInstallOperation.Run(
Edition.Enterprise,
mInstallerFile,
mProgressControls,
this);
}
void CancelButton_Clicked()
{
if (!IsExeAvailable.ForMode(mIsGluonMode))
TrackFeatureUseEvent.For(mRepSpec, mCancelInstallFrom);
Close();
}
void CheckForPlasticExe()
{
// executable becomes available halfway through the install
// we do not want to say install is done too early
// when progress control finishes, cancel button will be enabled
// then we can check for exe existing
if (mCancelButton.enabledSelf && IsExeAvailable.ForMode(mIsGluonMode))
{
mMessageLabel.text = "Unity Version Control installed. You can now use the feature.";
mCancelButton.text =
PlasticLocalization.GetString(PlasticLocalization.Name.CloseButton);
mRequireMessageLabel.Collapse();
mDownloadCloudEditionButton.Collapse();
mDownloadEnterpriseButton.Collapse();
}
}
void BuildComponents()
{
VisualElement root = rootVisualElement;
root.Clear();
InitializeLayoutAndStyles();
mRequireMessageLabel = root.Q<Label>("requireMessage");
mMessageLabel = root.Q<Label>("message");
mDownloadCloudEditionButton = root.Q<Button>("downloadCloudEdition");
mDownloadEnterpriseButton = root.Q<Button>("downloadEnterpriseEdition");
mCancelButton = root.Q<Button>("cancel");
mProgressControlsContainer = root.Q<VisualElement>("progressControlsContainer");
root.Q<Label>("title").text =
PlasticLocalization.GetString(PlasticLocalization.Name.InstallUnityVersionControl);
mDownloadCloudEditionButton.text =
PlasticLocalization.GetString(PlasticLocalization.Name.DownloadCloudEdition);
mDownloadCloudEditionButton.clicked += DownloadCloudEditionButton_Clicked;
if (EditionToken.IsCloudEdition())
{
mDownloadEnterpriseButton.Collapse();
DownloadPlasticExeWindow window = GetWindow<DownloadPlasticExeWindow>();
}
else
{
mMessageLabel.text =
PlasticLocalization.GetString(
PlasticLocalization.Name.WhichVersionInstall);
mDownloadEnterpriseButton.text =
PlasticLocalization.GetString(
PlasticLocalization.Name.DownloadEnterpriseEdition);
mDownloadEnterpriseButton.clicked += DownloadEnterpriseEditionButton_Clicked;
}
mCancelButton.text =
PlasticLocalization.GetString(PlasticLocalization.Name.CancelButton);
mCancelButton.clicked += CancelButton_Clicked;
mProgressControls = new ProgressControlsForDialogs(
new VisualElement[] {
mDownloadCloudEditionButton,
mDownloadEnterpriseButton,
mCancelButton
});
mProgressControlsContainer.Add(mProgressControls);
}
void InitializeLayoutAndStyles()
{
rootVisualElement.LoadLayout(typeof(DownloadPlasticExeWindow).Name);
rootVisualElement.LoadStyle(typeof(DownloadPlasticExeWindow).Name);
}
bool mIsGluonMode;
string mInstallCloudFrom;
string mInstallEnterpriseFrom;
string mCancelInstallFrom;
RepositorySpec mRepSpec;
string mInstallerFile;
bool mIsPlasticInstalling = false;
Label mRequireMessageLabel;
Label mMessageLabel;
Button mDownloadCloudEditionButton;
Button mDownloadEnterpriseButton;
Button mCancelButton;
VisualElement mProgressControlsContainer;
ProgressControlsForDialogs mProgressControls;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08dbb8d51633f2f4bab9912fbce3e247
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using Codice.Client.Common.Threading;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Items;
namespace Unity.PlasticSCM.Editor.Views
{
internal static class FileSystemOperation
{
internal static string GetExePath()
{
string title = PlasticLocalization.GetString(
PlasticLocalization.Name.BrowseForExecutableFile);
string directory = Environment.GetFolderPath(
Environment.SpecialFolder.ProgramFiles);
string path = EditorUtility.OpenFilePanel(title, directory, null);
if (path.Length != 0)
return path;
return null;
}
internal static void Open(List<string> files)
{
try
{
foreach (string file in files)
OpenFile(file);
}
catch (Exception ex)
{
ExceptionsHandler.DisplayException(ex);
}
}
internal static void OpenInExplorer(string path)
{
EditorUtility.RevealInFinder(path);
}
static void OpenFile(string path)
{
if (path == null)
return;
string relativePath = GetRelativePath.ToApplication(path);
bool result = AssetDatabase.OpenAsset(
AssetDatabase.LoadMainAssetAtPath(relativePath));
if (result)
return;
OpenOperation.OpenFile(path);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5eff45d4f0cc5e478e6724c378098eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3ac7d3b2f88744a4c89cb263306add7d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.History
{
internal enum HistoryListColumn
{
Changeset,
CreationDate,
CreatedBy,
Comment,
Branch,
}
[Serializable]
internal class HistoryListHeaderState : MultiColumnHeaderState, ISerializationCallbackReceiver
{
internal static HistoryListHeaderState GetDefault()
{
return new HistoryListHeaderState(BuildColumns());
}
internal static List<string> GetColumnNames()
{
List<string> result = new List<string>();
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.ChangesetColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CreationDateColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CreatedByColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CommentColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.BranchColumn));
return result;
}
internal static string GetColumnName(HistoryListColumn column)
{
switch (column)
{
case HistoryListColumn.Changeset:
return PlasticLocalization.GetString(PlasticLocalization.Name.ChangesetColumn);
case HistoryListColumn.CreationDate:
return PlasticLocalization.GetString(PlasticLocalization.Name.CreationDateColumn);
case HistoryListColumn.CreatedBy:
return PlasticLocalization.GetString(PlasticLocalization.Name.CreatedByColumn);
case HistoryListColumn.Comment:
return PlasticLocalization.GetString(PlasticLocalization.Name.CommentColumn);
case HistoryListColumn.Branch:
return PlasticLocalization.GetString(PlasticLocalization.Name.BranchColumn);
default:
return null;
}
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (mHeaderTitles != null)
TreeHeaderColumns.SetTitles(columns, mHeaderTitles);
if (mColumsAllowedToggleVisibility != null)
TreeHeaderColumns.SetVisibilities(columns, mColumsAllowedToggleVisibility);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
static Column[] BuildColumns()
{
return new Column[]
{
new Column()
{
width = 100,
headerContent = new GUIContent(
GetColumnName(HistoryListColumn.Changeset)),
minWidth = 50,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 250,
headerContent = new GUIContent(
GetColumnName(HistoryListColumn.CreationDate)),
minWidth = 100,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 250,
headerContent = new GUIContent(
GetColumnName(HistoryListColumn.CreatedBy)),
minWidth = 100,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 400,
headerContent = new GUIContent(
GetColumnName(HistoryListColumn.Comment)),
minWidth = 100,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 200,
headerContent = new GUIContent(
GetColumnName(HistoryListColumn.Branch)),
minWidth = 100,
sortingArrowAlignment = TextAlignment.Right
},
};
}
HistoryListHeaderState(Column[] columns)
: base(columns)
{
if (mHeaderTitles == null)
mHeaderTitles = TreeHeaderColumns.GetTitles(columns);
if (mColumsAllowedToggleVisibility == null)
mColumsAllowedToggleVisibility = TreeHeaderColumns.GetVisibilities(columns);
}
[SerializeField]
string[] mHeaderTitles;
[SerializeField]
bool[] mColumsAllowedToggleVisibility;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5b6e8a80709e2264eb383ef6b40e181f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,411 @@
using System;
using System.Collections.Generic;
using System.Linq;
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;
namespace Unity.PlasticSCM.Editor.Views.History
{
internal class HistoryListView : TreeView
{
internal HistoryListView(
string wkPath,
RepositorySpec repSpec,
HistoryListHeaderState headerState,
HistoryListViewMenu menu,
List<string> columnNames) :
base(new TreeViewState())
{
mWkPath = wkPath;
mRepSpec = repSpec;
mMenu = menu;
mColumnNames = columnNames;
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.canSort = true;
multiColumnHeader.sortingChanged += SortingChanged;
rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
showAlternatingRowBackgrounds = false;
mCooldownFilterAction = new CooldownWindowDelayer(
DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
}
public override IList<TreeViewItem> GetRows()
{
return mRows;
}
public override void OnGUI(Rect rect)
{
base.OnGUI(rect);
Event e = Event.current;
if (e.type != EventType.KeyDown)
return;
bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
if (isProcessed)
e.Use();
}
protected override TreeViewItem BuildRoot()
{
return new TreeViewItem(0, -1, string.Empty);
}
protected override IList<TreeViewItem> BuildRows(
TreeViewItem rootItem)
{
if (mRevisionsList == null)
{
ClearRows(rootItem, mRows);
return mRows;
}
RegenerateRows(
mListViewItemIds,
mRevisionsList,
rootItem,
mRows);
return mRows;
}
protected override void SearchChanged(string newSearch)
{
mCooldownFilterAction.Ping();
}
protected override void ContextClickedItem(int id)
{
mMenu.Popup();
Repaint();
}
protected override void BeforeRowsGUI()
{
int firstRowVisible;
int lastRowVisible;
GetFirstAndLastVisibleRows(out firstRowVisible, out lastRowVisible);
GUI.DrawTexture(new Rect(0,
firstRowVisible * rowHeight,
GetRowRect(0).width,
(lastRowVisible * rowHeight) + 1000),
Images.GetTreeviewBackgroundTexture());
DrawTreeViewItem.InitializeStyles();
base.BeforeRowsGUI();
}
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);
}
internal void BuildModel(
HistoryRevisionList historyRevisionList,
long loadedRevisionId)
{
mListViewItemIds.Clear();
mRevisionsList = historyRevisionList;
mLoadedRevisionId = loadedRevisionId;
}
internal void Refilter()
{
if (mRevisionsList == null)
return;
Filter filter = new Filter(searchString);
mRevisionsList.Filter(filter, mColumnNames, null);
}
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<RepObjectInfo> GetSelectedRepObjectInfos()
{
List<RepObjectInfo> result = new List<RepObjectInfo>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<RepObjectInfo, int> item
in mListViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
result.Add(item.Key);
}
return result;
}
internal List<RepObjectInfo> GetAllRepObjectInfos()
{
List<RepObjectInfo> result = new List<RepObjectInfo>();
foreach (KeyValuePair<RepObjectInfo, int> item
in mListViewItemIds.GetInfoItems())
{
result.Add(item.Key);
}
return result;
}
internal List<HistoryRevision> GetSelectedHistoryRevisions()
{
return GetSelectedRepObjectInfos().OfType<HistoryRevision>().ToList();
}
internal void SelectRepObjectInfos(
List<RepObjectInfo> repObjectsToSelect)
{
List<int> idsToSelect = new List<int>();
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<RepObjectInfo, int> 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<RepObjectInfo> listViewItemIds,
HistoryRevisionList revisions,
TreeViewItem rootItem,
List<TreeViewItem> 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<TreeViewItem> 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);
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));
if (column == HistoryListColumn.Changeset)
{
DrawTreeViewItem.ForItemCell(
rect,
rowHeight,
0,
GetRevisionIcon(item.Revision),
null,
columnText,
isSelected,
isFocused,
isBoldText,
false);
return;
}
if (column == HistoryListColumn.CreatedBy)
{
DrawTreeViewItem.ForItemCell(
rect,
rowHeight,
-1,
GetAvatar.ForEmail(columnText, avatarLoadedAction),
null,
columnText,
isSelected,
isFocused,
isBoldText,
false);
return;
}
if (column == HistoryListColumn.Branch)
{
DrawTreeViewItem.ForSecondaryLabel(
rect, columnText, isSelected, isFocused, isBoldText);
return;
}
DrawTreeViewItem.ForLabel(
rect, columnText, isSelected, isFocused, isBoldText);
}
static Texture GetRevisionIcon(RepObjectInfo revision)
{
if (revision is MoveRealizationInfo)
return Images.GetMovedIcon();
if (revision is RemovedRealizationInfo)
return Images.GetDeletedIcon();
return Images.GetFileIcon();
}
ListViewItemIds<RepObjectInfo> mListViewItemIds = new ListViewItemIds<RepObjectInfo>();
List<TreeViewItem> mRows = new List<TreeViewItem>();
HistoryRevisionList mRevisionsList;
long mLoadedRevisionId;
readonly CooldownWindowDelayer mCooldownFilterAction;
readonly HistoryListViewMenu mMenu;
readonly List<string> mColumnNames;
readonly RepositorySpec mRepSpec;
readonly string mWkPath;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ee2845d0d4db9a4a9e8f4f6d0fa4e5e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@

using UnityEditor.IMGUI.Controls;
using Codice.CM.Common;
namespace Unity.PlasticSCM.Editor.Views.History
{
internal class HistoryListViewItem : TreeViewItem
{
internal RepObjectInfo Revision { get; private set; }
internal HistoryListViewItem(int id, RepObjectInfo revision)
: base(id, 1)
{
Revision = revision;
displayName = id.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1b8657301e8ead4a9389eda02c15883
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,220 @@
using UnityEditor;
using UnityEngine;
using PlasticGui;
using PlasticGui.WorkspaceWindow.History;
using PlasticGui.WorkspaceWindow.Open;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.Views.History
{
internal class HistoryListViewMenu
{
public interface IMenuOperations
{
long GetSelectedChangesetId();
}
internal HistoryListViewMenu(
IOpenMenuOperations openMenuOperations,
IHistoryViewMenuOperations operations,
IMenuOperations menuOperations)
{
mOpenMenuOperations = openMenuOperations;
mOperations = operations;
mMenuOperations = menuOperations;
BuildComponents();
}
internal void Popup()
{
GenericMenu menu = new GenericMenu();
UpdateMenuItems(menu);
menu.ShowAsContext();
}
internal bool ProcessKeyActionIfNeeded(Event e)
{
HistoryMenuOperations operationToExecute = GetMenuOperation(e);
if (operationToExecute == HistoryMenuOperations.None)
return false;
SelectedHistoryGroupInfo info =
mOperations.GetSelectedHistoryGroupInfo();
HistoryMenuOperations operations =
HistoryMenuUpdater.GetAvailableMenuOperations(info);
if (!operations.HasFlag(operationToExecute))
return false;
ProcessMenuOperation(operationToExecute);
return true;
}
void OpenRevisionMenu_Click()
{
mOpenMenuOperations.Open();
}
void OpenRevisionWithMenu_Click()
{
mOpenMenuOperations.OpenWith();
}
void SaveRevisionasMenu_Click()
{
mOperations.SaveRevisionAs();
}
void DiffWithPreviousMenuItem_Click()
{
mOperations.DiffWithPrevious();
}
void DiffSelectedRevisionsMenu_Click()
{
mOperations.DiffSelectedRevisions();
}
void DiffChangesetMenu_Click()
{
mOperations.DiffChangeset();
}
void RevertToThisRevisionMenu_Click()
{
mOperations.RevertToThisRevision();
}
internal void UpdateMenuItems(GenericMenu menu)
{
SelectedHistoryGroupInfo info =
mOperations.GetSelectedHistoryGroupInfo();
HistoryMenuOperations operations =
HistoryMenuUpdater.GetAvailableMenuOperations(info);
OpenMenuOperations openOperations =
GetOpenMenuOperations.ForHistoryView(info);
if (operations == HistoryMenuOperations.None &&
openOperations == OpenMenuOperations.None)
{
menu.AddDisabledItem(GetNoActionMenuItemContent(), false);
return;
}
if (openOperations.HasFlag(OpenMenuOperations.Open))
menu.AddItem(mOpenRevisionMenuItemContent, false, OpenRevisionMenu_Click);
else
menu.AddDisabledItem(mOpenRevisionMenuItemContent, false);
if (openOperations.HasFlag(OpenMenuOperations.OpenWith))
menu.AddItem(mOpenRevisionWithMenuItemContent, false, OpenRevisionWithMenu_Click);
else
menu.AddDisabledItem(mOpenRevisionWithMenuItemContent, false);
if (operations.HasFlag(HistoryMenuOperations.SaveAs))
menu.AddItem(mSaveRevisionAsMenuItemContent, false, SaveRevisionasMenu_Click);
else
menu.AddDisabledItem(mSaveRevisionAsMenuItemContent, false);
menu.AddSeparator(string.Empty);
if (operations.HasFlag(HistoryMenuOperations.DiffWithPrevious))
menu.AddItem(mDiffWithPreviousMenuItemContent, false, DiffWithPreviousMenuItem_Click);
if (operations.HasFlag(HistoryMenuOperations.DiffSelected))
menu.AddItem(mDiffSelectedRevisionsMenuItemContent, false, DiffSelectedRevisionsMenu_Click);
mDiffChangesetMenuItemContent.text =
PlasticLocalization.GetString(PlasticLocalization.Name.HistoryMenuItemDiffChangeset) +
string.Format(" {0}", GetSelectedChangesetName(mMenuOperations));
if (operations.HasFlag(HistoryMenuOperations.DiffChangeset))
menu.AddItem(mDiffChangesetMenuItemContent, false, DiffChangesetMenu_Click);
else
menu.AddDisabledItem(mDiffChangesetMenuItemContent, false);
menu.AddSeparator(string.Empty);
if (operations.HasFlag(HistoryMenuOperations.RevertTo))
menu.AddItem(mRevertToThisRevisionMenuItemContent, false, RevertToThisRevisionMenu_Click);
else
menu.AddDisabledItem(mRevertToThisRevisionMenuItemContent, false);
}
static HistoryMenuOperations GetMenuOperation(Event e)
{
if (Keyboard.IsControlOrCommandKeyPressed(e) && Keyboard.IsKeyPressed(e, KeyCode.D))
return HistoryMenuOperations.DiffWithPrevious;
return HistoryMenuOperations.None;
}
void ProcessMenuOperation(HistoryMenuOperations operationToExecute)
{
if (operationToExecute == HistoryMenuOperations.DiffWithPrevious)
{
DiffWithPreviousMenuItem_Click();
}
}
GUIContent GetNoActionMenuItemContent()
{
if (mNoActionMenuItemContent == null)
{
mNoActionMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.
Name.NoActionMenuItem));
}
return mNoActionMenuItemContent;
}
static string GetSelectedChangesetName(IMenuOperations menuOperations)
{
long selectedChangesetId = menuOperations.GetSelectedChangesetId();
if (selectedChangesetId == -1)
return string.Empty;
return selectedChangesetId.ToString();
}
void BuildComponents()
{
mOpenRevisionMenuItemContent = new GUIContent(PlasticLocalization.
GetString(PlasticLocalization.Name.HistoryMenuItemOpen));
mOpenRevisionWithMenuItemContent = new GUIContent(PlasticLocalization.
GetString(PlasticLocalization.Name.HistoryMenuItemOpenWith));
mSaveRevisionAsMenuItemContent = new GUIContent(PlasticLocalization.
GetString(PlasticLocalization.Name.SaveThisRevisionAs));
mDiffWithPreviousMenuItemContent = new GUIContent(string.Format("{0} {1}",
PlasticLocalization.GetString(PlasticLocalization.Name.HistoryMenuItemDiffWithPrevious),
GetPlasticShortcut.ForDiff()));
mDiffSelectedRevisionsMenuItemContent = new GUIContent(PlasticLocalization.
GetString(PlasticLocalization.Name.HistoryMenuItemDiffSelectedRevisions));
mDiffChangesetMenuItemContent = new GUIContent();
mRevertToThisRevisionMenuItemContent = new GUIContent(PlasticLocalization.
GetString(PlasticLocalization.Name.HistoryMenuItemRevertToThisRevision));
}
GUIContent mNoActionMenuItemContent;
GUIContent mOpenRevisionMenuItemContent;
GUIContent mOpenRevisionWithMenuItemContent;
GUIContent mSaveRevisionAsMenuItemContent;
GUIContent mDiffWithPreviousMenuItemContent;
GUIContent mDiffSelectedRevisionsMenuItemContent;
GUIContent mDiffChangesetMenuItemContent;
GUIContent mRevertToThisRevisionMenuItemContent;
readonly IOpenMenuOperations mOpenMenuOperations;
readonly IHistoryViewMenuOperations mOperations;
readonly IMenuOperations mMenuOperations;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3cec769cd6ff2849aa09c811b62e611
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
using System.Collections.Generic;
using Codice.CM.Common;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.History
{
internal static class HistorySelection
{
internal static void SelectRevisions(
HistoryListView listView,
List<RepObjectInfo> revisionsToSelect)
{
if (revisionsToSelect == null || revisionsToSelect.Count == 0)
{
TableViewOperations.SelectFirstRow(listView);
return;
}
listView.SelectRepObjectInfos(revisionsToSelect);
if (listView.HasSelection())
return;
TableViewOperations.SelectFirstRow(listView);
}
internal static List<RepObjectInfo> GetSelectedRepObjectInfos(
HistoryListView listView)
{
return listView.GetSelectedRepObjectInfos();
}
internal static List<HistoryRevision> GetSelectedHistoryRevisions(
HistoryListView listView)
{
return listView.GetSelectedHistoryRevisions();
}
internal static HistoryRevision GetSelectedHistoryRevision(
HistoryListView listView)
{
List<HistoryRevision> revisions =
listView.GetSelectedHistoryRevisions();
if (revisions.Count == 0)
return null;
return revisions[0];
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9553f392d0be2a24daf3cad457d2c612
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,446 @@
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.CM.Common;
using Codice.Client.Common;
using Codice.Client.Common.EventTracking;
using Codice.Utils;
using GluonGui;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.Diff;
using PlasticGui.WorkspaceWindow.History;
using PlasticGui.WorkspaceWindow.Open;
using GluonRevertOperation = GluonGui.WorkspaceWindow.Views.Details.History.RevertOperation;
using HistoryDescriptor = GluonGui.WorkspaceWindow.Views.Details.History.HistoryDescriptor;
using OpenRevisionOperation = PlasticGui.WorkspaceWindow.History.OpenRevisionOperation;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.Tool;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.UI.Tree;
using Unity.PlasticSCM.Editor.Views.Changesets;
namespace Unity.PlasticSCM.Editor.Views.History
{
internal class HistoryTab :
IRefreshableView,
HistoryViewLogic.IHistoryView,
HistoryListViewMenu.IMenuOperations,
IOpenMenuOperations,
IHistoryViewMenuOperations
{
internal HistoryListView Table { get { return mHistoryListView; } }
internal HistoryTab(
WorkspaceInfo wkInfo,
IWorkspaceWindow workspaceWindow,
RepositorySpec repSpec,
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor,
NewIncomingChangesUpdater newIncomingChangesUpdater,
ViewHost viewHost,
EditorWindow parentWindow,
bool isGluonMode)
{
mWkInfo = wkInfo;
mWorkspaceWindow = workspaceWindow;
mRepSpec = repSpec;
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mProcessExecutor = processExecutor;
mNewIncomingChangesUpdater = newIncomingChangesUpdater;
mViewHost = viewHost;
mParentWindow = parentWindow;
mIsGluonMode = isGluonMode;
BuildComponents(wkInfo, repSpec);
mProgressControls = new ProgressControlsForViews();
mHistoryViewLogic = new HistoryViewLogic(
wkInfo, this, mProgressControls);
}
internal void RefreshForItem(
long itemId,
string path,
bool isDirectory)
{
mItemId = itemId;
mPath = path;
mIsDirectory = isDirectory;
((IRefreshableView)this).Refresh();
}
internal void Update()
{
mProgressControls.UpdateProgress(mParentWindow);
}
internal void OnGUI()
{
DoActionsToolbar(
this,
mProgressControls,
mSearchField,
mHistoryListView,
GetViewTitle(mPath));
DoHistoryArea(
mHistoryListView,
mProgressControls.IsOperationRunning());
}
internal void DrawSearchFieldForHistoryTab()
{
DrawSearchField.For(
mSearchField,
mHistoryListView,
UnityConstants.SEARCH_FIELD_WIDTH);
}
internal void OnDisable()
{
mSearchField.downOrUpArrowKeyPressed -=
SearchField_OnDownOrUpArrowKeyPressed;
TreeHeaderSettings.Save(
mHistoryListView.multiColumnHeader.state,
UnityConstants.HISTORY_TABLE_SETTINGS_NAME);
}
internal void SetLaunchToolForTesting(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
LaunchTool.IProcessExecutor processExecutor)
{
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mProcessExecutor = processExecutor;
}
void IRefreshableView.Refresh()
{
mHistoryViewLogic.RefreshForItem(mRepSpec, mItemId, new CancelToken());
}
List<RepObjectInfo> HistoryViewLogic.IHistoryView.GetSelectedRevisions()
{
return HistorySelection.GetSelectedRepObjectInfos(mHistoryListView);
}
void HistoryViewLogic.IHistoryView.SelectRevisions(
List<RepObjectInfo> revisionsToSelect)
{
HistorySelection.SelectRevisions(
mHistoryListView, revisionsToSelect);
}
void HistoryViewLogic.IHistoryView.UpdateData(
Dictionary<BranchInfo, ChangesetInfo> branchesAndChangesets,
BranchInfo workingBranch,
HistoryRevisionList list,
long loadedRevisionId)
{
mHistoryListView.BuildModel(list, loadedRevisionId);
mHistoryListView.Refilter();
mHistoryListView.Sort();
mHistoryListView.Reload();
}
long HistoryListViewMenu.IMenuOperations.GetSelectedChangesetId()
{
HistoryRevision revision = HistorySelection.
GetSelectedHistoryRevision(mHistoryListView);
if (revision == null)
return -1;
return revision.ChangeSet;
}
SelectedHistoryGroupInfo IHistoryViewMenuOperations.GetSelectedHistoryGroupInfo()
{
return SelectedHistoryGroupInfo.BuildFromSelection(
HistorySelection.GetSelectedRepObjectInfos(mHistoryListView),
HistorySelection.GetSelectedHistoryRevisions(mHistoryListView),
mHistoryListView.GetLoadedRevisionId(),
mIsDirectory);
}
void IOpenMenuOperations.Open()
{
OpenRevisionOperation.Open(
mRepSpec,
Path.GetFileName(mPath),
HistorySelection.GetSelectedHistoryRevisions(
mHistoryListView));
}
void IOpenMenuOperations.OpenWith()
{
List<HistoryRevision> revisions = HistorySelection.
GetSelectedHistoryRevisions(mHistoryListView);
OpenRevisionOperation.OpenWith(
mRepSpec,
FileSystemOperation.GetExePath(),
Path.GetFileName(mPath),
revisions);
}
void IOpenMenuOperations.OpenWithCustom(string exePath, string args)
{
}
void IOpenMenuOperations.OpenInExplorer()
{
}
void IHistoryViewMenuOperations.SaveRevisionAs()
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.SaveRevisionFromFileHistory);
HistoryRevision revision = HistorySelection.
GetSelectedHistoryRevision(mHistoryListView);
string defaultFileName = DefaultRevisionName.Get(
Path.GetFileName(mPath), revision.ChangeSet);
string destinationPath = SaveAction.GetDestinationPath(
mWkInfo.ClientPath, mPath, defaultFileName);
if (string.IsNullOrEmpty(destinationPath))
return;
SaveRevisionOperation.SaveRevision(
mRepSpec,
destinationPath,
revision,
mProgressControls);
}
void IHistoryViewMenuOperations.DiffWithPrevious()
{
if (mShowDownloadPlasticExeWindow.Show(
mRepSpec,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffRevision,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffRevision,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffRevision))
return;
HistoryRevision revision = HistorySelection.
GetSelectedHistoryRevision(mHistoryListView);
DiffOperation.DiffWithPrevious(
mWkInfo,
mRepSpec,
Path.GetFileName(mPath),
string.Empty,
revision.Id,
mItemId,
revision.ChangeSet,
mProgressControls,
null,
null);
}
void IHistoryViewMenuOperations.DiffSelectedRevisions()
{
if(mShowDownloadPlasticExeWindow.Show(
mRepSpec,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffSelectedRevisions,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffSelectedRevisions,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffSelectedRevisions))
return;
List<HistoryRevision> revisions = HistorySelection.
GetSelectedHistoryRevisions(mHistoryListView);
bool areReversed = revisions[0].Id > revisions[1].Id;
DiffOperation.DiffRevisions(
mWkInfo,
mRepSpec,
Path.GetFileName(mPath),
string.Empty,
mItemId,
revisions[(areReversed) ? 1 : 0],
revisions[(areReversed) ? 0 : 1],
mProgressControls,
null,
null);
}
void IHistoryViewMenuOperations.DiffChangeset()
{
if (mShowDownloadPlasticExeWindow.Show(
mRepSpec,
mIsGluonMode,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffChangeset,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffChangeset,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffChangeset))
return;
HistoryRevision revision = HistorySelection.
GetSelectedHistoryRevision(mHistoryListView);
LaunchDiffOperations.DiffChangeset(
mShowDownloadPlasticExeWindow,
mProcessExecutor,
mRepSpec,
revision.ChangeSet,
mIsGluonMode);
}
void IHistoryViewMenuOperations.RevertToThisRevision()
{
HistoryRevision revision = HistorySelection.
GetSelectedHistoryRevision(mHistoryListView);
string fullPath = GetFullPath(mWkInfo.ClientPath, mPath);
if (mIsGluonMode)
{
HistoryDescriptor historyDescriptor = new HistoryDescriptor(
mRepSpec, fullPath, mItemId, revision.Id, mIsDirectory);
GluonRevertOperation.RevertToThisRevision(
mWkInfo,
mViewHost,
mProgressControls,
historyDescriptor,
revision,
RefreshAsset.UnityAssetDatabase);
return;
}
RevertOperation.RevertToThisRevision(
mWkInfo,
mProgressControls,
mWorkspaceWindow,
mRepSpec,
revision,
fullPath,
mNewIncomingChangesUpdater,
RefreshAsset.UnityAssetDatabase);
}
void SearchField_OnDownOrUpArrowKeyPressed()
{
mHistoryListView.SetFocusAndEnsureSelectedItem();
}
static string GetFullPath(string wkPath, string path)
{
if (PathHelper.IsContainedOn(path, wkPath))
return path;
return WorkspacePath.GetWorkspacePathFromCmPath(
wkPath, path, Path.DirectorySeparatorChar);
}
static void DoActionsToolbar(
IRefreshableView refreshableView,
ProgressControlsForViews progressControls,
SearchField searchField,
HistoryListView listView,
string viewTitle)
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
GUILayout.Label(
viewTitle,
UnityStyles.HistoryTab.HeaderLabel);
if (progressControls.IsOperationRunning())
{
DrawProgressForViews.ForIndeterminateProgress(
progressControls.ProgressData);
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
}
static void DoHistoryArea(
HistoryListView historyListView,
bool isOperationRunning)
{
GUI.enabled = !isOperationRunning;
Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
historyListView.OnGUI(rect);
GUI.enabled = true;
}
static string GetViewTitle(string path)
{
path = PathHelper.RemoveLastSlash(
path, Path.DirectorySeparatorChar);
return PlasticLocalization.GetString(
PlasticLocalization.Name.HistoryViewTitle,
Path.GetFileName(path));
}
void BuildComponents(
WorkspaceInfo wkInfo,
RepositorySpec repSpec)
{
mSearchField = new SearchField();
mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
HistoryListHeaderState headerState =
HistoryListHeaderState.GetDefault();
TreeHeaderSettings.Load(headerState,
UnityConstants.HISTORY_TABLE_SETTINGS_NAME,
(int)HistoryListColumn.CreationDate,
false);
mHistoryListView = new HistoryListView(
wkInfo.ClientPath,
repSpec,
headerState,
new HistoryListViewMenu(this, this, this),
HistoryListHeaderState.GetColumnNames());
mHistoryListView.Reload();
}
SearchField mSearchField;
HistoryListView mHistoryListView;
long mItemId;
string mPath;
bool mIsDirectory;
LaunchTool.IProcessExecutor mProcessExecutor;
LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
readonly WorkspaceInfo mWkInfo;
readonly HistoryViewLogic mHistoryViewLogic;
readonly ProgressControlsForViews mProgressControls;
readonly IWorkspaceWindow mWorkspaceWindow;
readonly RepositorySpec mRepSpec;
readonly bool mIsGluonMode;
readonly EditorWindow mParentWindow;
readonly ViewHost mViewHost;
readonly NewIncomingChangesUpdater mNewIncomingChangesUpdater;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a49359b59c12b74386ca6816923ec2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More