Created unity project
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15fe89692edc49a4891091bd0e1c6536
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebbbce5f7ed39ab45b6f43340727ba5e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4a41e458bcb22946bcfa6b165c90288
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b909cb14b9a08c45b5d03f0b61feecb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73306fe71bf092d4495ff28ee02b766b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,485 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.Common.Threading;
|
||||
using Codice.CM.Common;
|
||||
using GluonGui;
|
||||
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;
|
||||
|
||||
using GluonNewIncomingChangesUpdater = PlasticGui.Gluon.WorkspaceWindow.NewIncomingChangesUpdater;
|
||||
using IGluonUpdateReport = PlasticGui.Gluon.IUpdateReport;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.Branches
|
||||
{
|
||||
internal partial class BranchesTab :
|
||||
IRefreshableView,
|
||||
IQueryRefreshableView,
|
||||
IBranchMenuOperations
|
||||
{
|
||||
internal BranchesListView Table { get { return mBranchesListView; } }
|
||||
internal IBranchMenuOperations Operations { get { return this; } }
|
||||
|
||||
internal BranchesTab(
|
||||
WorkspaceInfo wkInfo,
|
||||
WorkspaceWindow workspaceWindow,
|
||||
IViewSwitcher viewSwitcher,
|
||||
IMergeViewLauncher mergeViewLauncher,
|
||||
ViewHost viewHost,
|
||||
IUpdateReport updateReport,
|
||||
IGluonUpdateReport gluonUpdateReport,
|
||||
NewIncomingChangesUpdater developerNewIncomingChangesUpdater,
|
||||
GluonNewIncomingChangesUpdater gluonNewIncomingChangesUpdater,
|
||||
EditorWindow parentWindow,
|
||||
bool isGluonMode)
|
||||
{
|
||||
mWkInfo = wkInfo;
|
||||
mParentWindow = parentWindow;
|
||||
mGluonUpdateReport = gluonUpdateReport;
|
||||
mViewHost = viewHost;
|
||||
mWorkspaceWindow = workspaceWindow;
|
||||
mIsGluonMode = isGluonMode;
|
||||
mProgressControls = new ProgressControlsForViews();
|
||||
|
||||
mDeveloperNewIncomingChangesUpdater = developerNewIncomingChangesUpdater;
|
||||
mGluonNewIncomingChangesUpdater = gluonNewIncomingChangesUpdater;
|
||||
|
||||
BuildComponents(
|
||||
wkInfo,
|
||||
workspaceWindow,
|
||||
viewSwitcher,
|
||||
mergeViewLauncher,
|
||||
updateReport,
|
||||
developerNewIncomingChangesUpdater,
|
||||
parentWindow);
|
||||
|
||||
((IRefreshableView)this).Refresh();
|
||||
}
|
||||
|
||||
internal void OnEnable()
|
||||
{
|
||||
mSearchField.downOrUpArrowKeyPressed +=
|
||||
SearchField_OnDownOrUpArrowKeyPressed;
|
||||
}
|
||||
|
||||
internal void OnDisable()
|
||||
{
|
||||
mSearchField.downOrUpArrowKeyPressed -=
|
||||
SearchField_OnDownOrUpArrowKeyPressed;
|
||||
|
||||
TreeHeaderSettings.Save(
|
||||
mBranchesListView.multiColumnHeader.state,
|
||||
UnityConstants.BRANCHES_TABLE_SETTINGS_NAME);
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
mProgressControls.UpdateProgress(mParentWindow);
|
||||
}
|
||||
|
||||
internal void OnGUI()
|
||||
{
|
||||
DoActionsToolbar(mProgressControls);
|
||||
|
||||
DoBranchesArea(
|
||||
mBranchesListView,
|
||||
mProgressControls.IsOperationRunning());
|
||||
}
|
||||
|
||||
internal void DrawSearchFieldForTab()
|
||||
{
|
||||
DrawSearchField.For(
|
||||
mSearchField,
|
||||
mBranchesListView,
|
||||
UnityConstants.SEARCH_FIELD_WIDTH);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
internal void SetWorkingObjectInfo(WorkingObjectInfo homeInfo)
|
||||
{
|
||||
lock (mLock)
|
||||
{
|
||||
mLoadedBranchId = homeInfo.BranchInfo.BranchId;
|
||||
}
|
||||
|
||||
mBranchesListView.SetLoadedBranchId(mLoadedBranchId);
|
||||
}
|
||||
|
||||
void IRefreshableView.Refresh()
|
||||
{
|
||||
// VCS-1005209 - There are scenarios where the list of branches need to check for incoming changes.
|
||||
// For example, deleting the active branch will automatically switch your workspace to the parent changeset,
|
||||
// which might have incoming changes.
|
||||
if (mDeveloperNewIncomingChangesUpdater != null)
|
||||
mDeveloperNewIncomingChangesUpdater.Update(DateTime.Now);
|
||||
|
||||
if (mGluonNewIncomingChangesUpdater != null)
|
||||
mGluonNewIncomingChangesUpdater.Update(DateTime.Now);
|
||||
|
||||
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 });
|
||||
}
|
||||
|
||||
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,
|
||||
items => RefreshAsset.AfterLongAssetOperation(
|
||||
ProjectPackages.ShouldBeResolved(items, mWkInfo, false)));
|
||||
}
|
||||
|
||||
void IBranchMenuOperations.CreateTopLevelBranch() { }
|
||||
|
||||
void IBranchMenuOperations.SwitchToBranch()
|
||||
{
|
||||
SwitchToBranchForMode();
|
||||
}
|
||||
|
||||
void IBranchMenuOperations.MergeBranch()
|
||||
{
|
||||
mBranchOperations.MergeBranch(
|
||||
BranchesSelection.GetSelectedRepository(mBranchesListView),
|
||||
BranchesSelection.GetSelectedBranch(mBranchesListView));
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
var branchesToDelete = BranchesSelection.GetSelectedBranches(mBranchesListView);
|
||||
|
||||
if (!DeleteBranchDialog.ConfirmDelete(branchesToDelete))
|
||||
return;
|
||||
|
||||
mBranchOperations.DeleteBranch(
|
||||
BranchesSelection.GetSelectedRepositories(mBranchesListView),
|
||||
branchesToDelete,
|
||||
DeleteBranchOptions.IncludeChangesets);
|
||||
}
|
||||
|
||||
void IBranchMenuOperations.CreateCodeReview() { }
|
||||
|
||||
void IBranchMenuOperations.ViewPermissions() { }
|
||||
|
||||
void SearchField_OnDownOrUpArrowKeyPressed()
|
||||
{
|
||||
mBranchesListView.SetFocusAndEnsureSelectedItem();
|
||||
}
|
||||
|
||||
void OnBranchesListViewSizeChanged()
|
||||
{
|
||||
if (!mShouldScrollToSelection)
|
||||
return;
|
||||
|
||||
mShouldScrollToSelection = false;
|
||||
TableViewOperations.ScrollToSelection(mBranchesListView);
|
||||
}
|
||||
|
||||
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 void UpdateBranchesList(
|
||||
BranchesListView branchesListView,
|
||||
ViewQueryResult queryResult,
|
||||
long loadedBranchId)
|
||||
{
|
||||
branchesListView.BuildModel(
|
||||
queryResult, loadedBranchId);
|
||||
|
||||
branchesListView.Refilter();
|
||||
|
||||
branchesListView.Sort();
|
||||
|
||||
branchesListView.Reload();
|
||||
}
|
||||
|
||||
static long GetLoadedBranchId(WorkspaceInfo wkInfo)
|
||||
{
|
||||
BranchInfo brInfo = PlasticGui.Plastic.API.GetWorkingBranch(wkInfo);
|
||||
|
||||
if (brInfo != null)
|
||||
return brInfo.BranchId;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int GetBranchesCount(
|
||||
ViewQueryResult queryResult)
|
||||
{
|
||||
if (queryResult == null)
|
||||
return 0;
|
||||
|
||||
return queryResult.Count();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void DoActionsToolbar(ProgressControlsForViews progressControls)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
|
||||
if (progressControls.IsOperationRunning())
|
||||
{
|
||||
DrawProgressForViews.ForIndeterminateProgress(
|
||||
progressControls.ProgressData);
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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, mGluonNewIncomingChangesUpdater != null),
|
||||
sizeChangedAction: OnBranchesListViewSizeChanged);
|
||||
|
||||
mBranchesListView.Reload();
|
||||
|
||||
mBranchOperations = new BranchOperations(
|
||||
wkInfo,
|
||||
workspaceWindow,
|
||||
null,
|
||||
viewSwitcher,
|
||||
mergeViewLauncher,
|
||||
this,
|
||||
ViewType.BranchesView,
|
||||
mProgressControls,
|
||||
updateReport,
|
||||
new ContinueWithPendingChangesQuestionerBuilder(viewSwitcher, parentWindow),
|
||||
null,
|
||||
null,
|
||||
developerNewIncomingChangesUpdater,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
SearchField mSearchField;
|
||||
bool mIsRefreshing;
|
||||
|
||||
DateFilter mDateFilter;
|
||||
bool mShouldScrollToSelection;
|
||||
BranchesListView mBranchesListView;
|
||||
BranchOperations mBranchOperations;
|
||||
|
||||
long mLoadedBranchId = -1;
|
||||
object mLock = new object();
|
||||
|
||||
readonly bool mIsGluonMode;
|
||||
readonly ViewHost mViewHost;
|
||||
readonly IGluonUpdateReport mGluonUpdateReport;
|
||||
readonly WorkspaceWindow mWorkspaceWindow;
|
||||
|
||||
readonly WorkspaceInfo mWkInfo;
|
||||
readonly ProgressControlsForViews mProgressControls;
|
||||
readonly EditorWindow mParentWindow;
|
||||
readonly NewIncomingChangesUpdater mDeveloperNewIncomingChangesUpdater;
|
||||
readonly GluonNewIncomingChangesUpdater mGluonNewIncomingChangesUpdater;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2350e7d7f6d79024da24dea8f15a6881
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
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.Branches
|
||||
{
|
||||
internal partial class BranchesTab
|
||||
{
|
||||
private void SwitchToBranchForMode()
|
||||
{
|
||||
if (mIsGluonMode)
|
||||
{
|
||||
SwitchToBranchForGluon();
|
||||
return;
|
||||
}
|
||||
|
||||
SwitchToBranchForDeveloper();
|
||||
}
|
||||
|
||||
private void SwitchToBranchForDeveloper()
|
||||
{
|
||||
RepositorySpec repSpec = BranchesSelection.GetSelectedRepository(mBranchesListView);
|
||||
BranchInfo branchInfo = BranchesSelection.GetSelectedBranch(mBranchesListView);
|
||||
|
||||
mBranchOperations.SwitchToBranch(
|
||||
repSpec,
|
||||
branchInfo,
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
items => RefreshAsset.AfterLongAssetOperation(
|
||||
ProjectPackages.ShouldBeResolved(items, mWkInfo, false)));
|
||||
}
|
||||
|
||||
private void SwitchToBranchForGluon()
|
||||
{
|
||||
BranchInfo branchInfo = BranchesSelection.GetSelectedBranch(mBranchesListView);
|
||||
|
||||
new SwitchToUIOperation().SwitchToBranch(
|
||||
mWkInfo,
|
||||
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
|
||||
branchInfo,
|
||||
mViewHost,
|
||||
null,
|
||||
new UnityPlasticGuiMessage(),
|
||||
mProgressControls,
|
||||
mWorkspaceWindow.GluonProgressOperationHandler,
|
||||
mGluonUpdateReport,
|
||||
mWorkspaceWindow,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
items => RefreshAsset.AfterLongAssetOperation(
|
||||
ProjectPackages.ShouldBeResolved(items, mWkInfo, true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 732707d2b1ec963458b4ab9ffe539cbe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,201 @@
|
||||
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,
|
||||
bool isGluonMode)
|
||||
{
|
||||
mBranchMenuOperations = branchMenuOperations;
|
||||
mIsGluonMode = isGluonMode;
|
||||
|
||||
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(),
|
||||
mIsGluonMode,
|
||||
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();
|
||||
}
|
||||
|
||||
void MergeBranchMenuItem_Click()
|
||||
{
|
||||
mBranchMenuOperations.MergeBranch();
|
||||
}
|
||||
|
||||
void UpdateMenuItems(GenericMenu menu)
|
||||
{
|
||||
BranchMenuOperations operations = BranchMenuUpdater.GetAvailableMenuOperations(
|
||||
mBranchMenuOperations.GetSelectedBranchesCount(), mIsGluonMode, false);
|
||||
|
||||
AddBranchMenuItem(
|
||||
mCreateBranchMenuItemContent,
|
||||
menu,
|
||||
operations,
|
||||
BranchMenuOperations.CreateBranch,
|
||||
CreateBranchMenuItem_Click);
|
||||
|
||||
AddBranchMenuItem(
|
||||
mSwitchToBranchMenuItemContent,
|
||||
menu,
|
||||
operations,
|
||||
BranchMenuOperations.SwitchToBranch,
|
||||
SwitchToBranchMenuItem_Click);
|
||||
|
||||
if (!mIsGluonMode)
|
||||
{
|
||||
menu.AddSeparator(string.Empty);
|
||||
|
||||
AddBranchMenuItem(
|
||||
mMergeBranchMenuItemContent,
|
||||
menu,
|
||||
operations,
|
||||
BranchMenuOperations.MergeBranch,
|
||||
MergeBranchMenuItem_Click);
|
||||
}
|
||||
|
||||
menu.AddSeparator(string.Empty);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (operationToExecute == BranchMenuOperations.MergeBranch)
|
||||
{
|
||||
branchMenuOperations.MergeBranch();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static BranchMenuOperations GetMenuOperations(Event e)
|
||||
{
|
||||
if (Keyboard.IsKeyPressed(e, KeyCode.Delete))
|
||||
return BranchMenuOperations.Delete;
|
||||
|
||||
if (Keyboard.IsControlOrCommandKeyPressed(e) &&
|
||||
Keyboard.IsKeyPressed(e, KeyCode.M))
|
||||
return BranchMenuOperations.MergeBranch;
|
||||
|
||||
return BranchMenuOperations.None;
|
||||
}
|
||||
|
||||
void BuildComponents()
|
||||
{
|
||||
mCreateBranchMenuItemContent = new GUIContent(
|
||||
PlasticLocalization.GetString(PlasticLocalization.Name.BranchMenuItemCreateBranch));
|
||||
mSwitchToBranchMenuItemContent = new GUIContent(
|
||||
PlasticLocalization.GetString(PlasticLocalization.Name.BranchMenuItemSwitchToBranch));
|
||||
mMergeBranchMenuItemContent = new GUIContent(string.Format("{0} {1}",
|
||||
PlasticLocalization.GetString(PlasticLocalization.Name.BranchMenuItemMergeFromBranch),
|
||||
GetPlasticShortcut.ForMerge()));
|
||||
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 mMergeBranchMenuItemContent;
|
||||
GUIContent mRenameBranchMenuItemContent;
|
||||
GUIContent mDeleteBranchMenuItemContent;
|
||||
|
||||
readonly IBranchMenuOperations mBranchMenuOperations;
|
||||
readonly bool mIsGluonMode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1f5156c89fd104459e8ec0cc3098899
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16e16045695760047a9bd172458c5d6b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,194 @@
|
||||
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
|
||||
{
|
||||
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.Name.CreateChildBranchTitle.GetString();
|
||||
}
|
||||
|
||||
protected override void OnModalGUI()
|
||||
{
|
||||
DoTitleArea();
|
||||
|
||||
DoFieldsArea();
|
||||
|
||||
DoButtonsArea();
|
||||
}
|
||||
|
||||
internal static BranchCreationData CreateBranchFromLastParentBranchChangeset(
|
||||
EditorWindow parentWindow,
|
||||
RepositorySpec repSpec,
|
||||
BranchInfo parentBranchInfo)
|
||||
{
|
||||
string changesetStr = PlasticLocalization.Name.LastChangeset.GetString();
|
||||
|
||||
string explanation = BranchCreationUserInfo.GetFromObjectString(
|
||||
repSpec, parentBranchInfo, changesetStr);
|
||||
|
||||
CreateBranchDialog dialog = Create(repSpec, parentBranchInfo, -1 , explanation);
|
||||
ResponseType dialogueResult = dialog.RunModal(parentWindow);
|
||||
|
||||
BranchCreationData result = dialog.BuildCreationData();
|
||||
result.Result = dialogueResult == ResponseType.Ok;
|
||||
return result;
|
||||
}
|
||||
|
||||
void DoTitleArea()
|
||||
{
|
||||
GUILayout.BeginVertical();
|
||||
|
||||
Title(PlasticLocalization.Name.CreateChildBranchTitle.GetString());
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
Paragraph(string.Format("{0} {1}",
|
||||
PlasticLocalization.Name.CreateChildBranchExplanation.GetString(), mExplanation));
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
void DoFieldsArea()
|
||||
{
|
||||
GUILayout.BeginVertical();
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label(
|
||||
PlasticLocalization.Name.BranchNameEntry.GetString(),
|
||||
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.Name.CommentsEntry.GetString(),
|
||||
GUILayout.Width(100));
|
||||
}
|
||||
mComment = GUILayout.TextArea(mComment, GUILayout.Height(100));
|
||||
GUILayout.Space(5);
|
||||
}
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
mSwitchToBranch = GUILayout.Toggle(mSwitchToBranch, PlasticLocalization.Name.SwitchToBranchCheckButton.GetString());
|
||||
|
||||
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.Name.CancelButton.GetString()))
|
||||
return;
|
||||
|
||||
CancelButtonAction();
|
||||
}
|
||||
|
||||
void DoCreateButton()
|
||||
{
|
||||
if (!NormalButton(PlasticLocalization.Name.CreateButton.GetString()))
|
||||
return;
|
||||
|
||||
BranchCreationValidation.AsyncValidation(
|
||||
BuildCreationData(), this, mProgressControls);
|
||||
}
|
||||
|
||||
static CreateBranchDialog Create(
|
||||
RepositorySpec repSpec, BranchInfo parentBranchInfo, long changesetId, 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;
|
||||
instance.mChangesetId = changesetId;
|
||||
return instance;
|
||||
}
|
||||
|
||||
BranchCreationData BuildCreationData()
|
||||
{
|
||||
return new BranchCreationData(
|
||||
mRepositorySpec,
|
||||
mParentBranchInfo,
|
||||
mChangesetId,
|
||||
mNewBranchName,
|
||||
mComment,
|
||||
null,
|
||||
mSwitchToBranch);
|
||||
}
|
||||
|
||||
ProgressControlsForDialogs mProgressControls;
|
||||
|
||||
RepositorySpec mRepositorySpec;
|
||||
BranchInfo mParentBranchInfo;
|
||||
long mChangesetId;
|
||||
|
||||
string mNewBranchName;
|
||||
string mComment;
|
||||
bool mSwitchToBranch;
|
||||
string mExplanation;
|
||||
|
||||
bool mWasNameFieldFocused;
|
||||
const string NAME_FIELD_CONTROL_NAME = "CreateBranchNameField";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0fc5252a48d8b34f945b4ae3ad45030
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Codice.CM.Common;
|
||||
using PlasticGui;
|
||||
using Unity.PlasticSCM.Editor.UI;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.Branches.Dialogs
|
||||
{
|
||||
internal class DeleteBranchDialog : PlasticDialog
|
||||
{
|
||||
protected override Rect DefaultRect
|
||||
{
|
||||
get
|
||||
{
|
||||
var baseRect = base.DefaultRect;
|
||||
var increaseFactor = mNumberOfBranches <= MAX_ITEMS_TO_SHOW ?
|
||||
TEXT_LINE_HEIGHT * mNumberOfBranches :
|
||||
TEXT_LINE_HEIGHT * (MAX_ITEMS_TO_SHOW + 1);
|
||||
return new Rect(baseRect.x, baseRect.y, baseRect.width, baseRect.height + increaseFactor);
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool ConfirmDelete(IList<BranchInfo> branches)
|
||||
{
|
||||
DeleteBranchDialog dialog = Create(branches);
|
||||
|
||||
return dialog.RunModal(null) == ResponseType.Ok;
|
||||
}
|
||||
|
||||
protected override string GetTitle()
|
||||
{
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
protected override void OnModalGUI()
|
||||
{
|
||||
Paragraph(mMessage);
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
DoButtonsArea();
|
||||
}
|
||||
|
||||
void DoButtonsArea()
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
mConfirmDelete = ToggleEntry(
|
||||
PlasticLocalization.Name.ConfirmationCheckBox.GetString(),
|
||||
mConfirmDelete);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||
{
|
||||
DoDeleteButton();
|
||||
DoCancelButton();
|
||||
return;
|
||||
}
|
||||
|
||||
DoCancelButton();
|
||||
DoDeleteButton();
|
||||
}
|
||||
}
|
||||
|
||||
void DoCancelButton()
|
||||
{
|
||||
if (!NormalButton(PlasticLocalization.Name.NoButton.GetString()))
|
||||
return;
|
||||
|
||||
CancelButtonAction();
|
||||
}
|
||||
|
||||
void DoDeleteButton()
|
||||
{
|
||||
GUI.enabled = mConfirmDelete;
|
||||
|
||||
if (NormalButton(PlasticLocalization.Name.DeleteButton.GetString()))
|
||||
{
|
||||
OkButtonAction();
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
static DeleteBranchDialog Create(IList<BranchInfo> branches)
|
||||
{
|
||||
var instance = CreateInstance<DeleteBranchDialog>();
|
||||
instance.mMessage = BuildDeleteBranchesConfirmationMessage(branches);
|
||||
instance.mNumberOfBranches = branches.Count;
|
||||
instance.mTitle = PlasticLocalization.Name.ConfirmDeleteTitle.GetString();
|
||||
return instance;
|
||||
}
|
||||
|
||||
static string BuildDeleteBranchesConfirmationMessage(IList<BranchInfo> branchToDelete)
|
||||
{
|
||||
string[] itemNames = branchToDelete.Select(x => x.Name).ToArray();
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.AppendLine(PlasticLocalization.Name.DeleteBranchesExplanation.GetString());
|
||||
stringBuilder.AppendLine();
|
||||
int num = Math.Min(itemNames.Length, MAX_ITEMS_TO_SHOW);
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
stringBuilder.AppendLine(" " + (i + 1) + ". " + itemNames[i]);
|
||||
}
|
||||
|
||||
if (itemNames.Length > MAX_ITEMS_TO_SHOW)
|
||||
{
|
||||
stringBuilder.AppendLine(PlasticLocalization.Name.DeleteOthersMessage.GetString(itemNames.Length - MAX_ITEMS_TO_SHOW));
|
||||
}
|
||||
|
||||
stringBuilder.AppendLine();
|
||||
stringBuilder.AppendLine(PlasticLocalization.Name.DeleteBranchesConfirmation.GetString());
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
const int TEXT_LINE_HEIGHT = 15;
|
||||
const int MAX_ITEMS_TO_SHOW = 10;
|
||||
|
||||
string mMessage;
|
||||
string mTitle;
|
||||
int mNumberOfBranches;
|
||||
bool mConfirmDelete;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6780ea954e283bd4f82686f6e5ebafee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1de62e30afcba544e8e8da4b93a4fa39
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a83160f252281df4ebb018688dad5f08
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6000865ce7fbfc643abdd3d085b4422e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ff9581aa143f4d41b4e351881b8f459
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59e682a8b37338a46910fa9a939425e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20341761c2011b441b2a3af227beeb71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,676 @@
|
||||
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 Codice.CM.Common.Mount;
|
||||
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,
|
||||
null,
|
||||
viewSwitcher,
|
||||
mergeViewLauncher,
|
||||
this,
|
||||
ViewType.ChangesetsView,
|
||||
mProgressControls,
|
||||
updateReport,
|
||||
new ContinueWithPendingChangesQuestionerBuilder(viewSwitcher, parentWindow),
|
||||
null,
|
||||
null,
|
||||
newIncomingChangesUpdater,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
((IRefreshableView)this).Refresh();
|
||||
}
|
||||
|
||||
internal void OnEnable()
|
||||
{
|
||||
mDiffPanel.OnEnable();
|
||||
|
||||
mSearchField.downOrUpArrowKeyPressed +=
|
||||
SearchField_OnDownOrUpArrowKeyPressed;
|
||||
}
|
||||
|
||||
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(mProgressControls);
|
||||
|
||||
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 DrawSearchFieldForTab()
|
||||
{
|
||||
DrawSearchField.For(
|
||||
mSearchField,
|
||||
mChangesetsListView,
|
||||
UnityConstants.SEARCH_FIELD_WIDTH);
|
||||
|
||||
VerifyIfSearchFieldIsRecentlyFocused(mSearchField);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void IChangesetMenuOperations.DiffWithAnotherChangeset() { }
|
||||
|
||||
void IChangesetMenuOperations.CreateBranch() { }
|
||||
|
||||
void IChangesetMenuOperations.LabelChangeset() { }
|
||||
|
||||
void IChangesetMenuOperations.MergeChangeset()
|
||||
{
|
||||
mChangesetOperations.MergeChangeset(
|
||||
ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
|
||||
ChangesetsSelection.GetSelectedChangeset(mChangesetsListView));
|
||||
}
|
||||
|
||||
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 ChangesetsViewMenu.IMenuOperations.DiffBranch()
|
||||
{
|
||||
LaunchDiffOperations.DiffBranch(
|
||||
mShowDownloadPlasticExeWindow,
|
||||
mProcessExecutor,
|
||||
ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
|
||||
ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
|
||||
mIsGluonMode);
|
||||
}
|
||||
|
||||
ChangesetExtendedInfo ChangesetsViewMenu.IMenuOperations.GetSelectedChangeset()
|
||||
{
|
||||
return ChangesetsSelection.GetSelectedChangeset(
|
||||
mChangesetsListView);
|
||||
}
|
||||
|
||||
void SearchField_OnDownOrUpArrowKeyPressed()
|
||||
{
|
||||
mChangesetsListView.SetFocusAndEnsureSelectedItem();
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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 InitializeShowChangesButtonWidth()
|
||||
{
|
||||
if (mShowChangesButtonWidth != -1)
|
||||
return;
|
||||
|
||||
mShowChangesButtonWidth = MeasureMaxWidth.ForTexts(
|
||||
EditorStyles.toolbarButton,
|
||||
PlasticLocalization.GetString(PlasticLocalization.Name.HideChanges),
|
||||
PlasticLocalization.GetString(PlasticLocalization.Name.ShowChanges));
|
||||
}
|
||||
|
||||
void VerifyIfSearchFieldIsRecentlyFocused(SearchField searchField)
|
||||
{
|
||||
if (searchField.HasFocus() != mIsSearchFieldFocused)
|
||||
{
|
||||
mIsSearchFieldFocused = !mIsSearchFieldFocused;
|
||||
|
||||
if (mIsSearchFieldFocused)
|
||||
{
|
||||
TrackFeatureUseEvent.For(
|
||||
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
|
||||
TrackFeatureUseEvent.Features.ChangesetsViewChangesetsSearchBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 int GetChangesetsCount(
|
||||
ViewQueryResult queryResult)
|
||||
{
|
||||
if (queryResult == null)
|
||||
return 0;
|
||||
|
||||
return queryResult.Count();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void DoActionsToolbar(ProgressControlsForViews progressControls)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 471badd5c87fb154885f11cdf1b49a00
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
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()
|
||||
{
|
||||
if (mIsGluonMode)
|
||||
{
|
||||
SwitchToChangesetForGluon();
|
||||
return;
|
||||
}
|
||||
|
||||
SwitchToChangesetForDeveloper();
|
||||
}
|
||||
|
||||
void SwitchToChangesetForDeveloper()
|
||||
{
|
||||
mChangesetOperations.SwitchToChangeset(
|
||||
ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
|
||||
ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
items => RefreshAsset.AfterLongAssetOperation(
|
||||
ProjectPackages.ShouldBeResolved(items, mWkInfo, false)));
|
||||
}
|
||||
|
||||
void SwitchToChangesetForGluon()
|
||||
{
|
||||
ChangesetExtendedInfo csetInfo = ChangesetsSelection.GetSelectedChangeset(mChangesetsListView);
|
||||
|
||||
new SwitchToUIOperation().SwitchToChangeset(
|
||||
mWkInfo,
|
||||
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
|
||||
csetInfo.BranchName,
|
||||
csetInfo.ChangesetId,
|
||||
mViewHost,
|
||||
null,
|
||||
new UnityPlasticGuiMessage(),
|
||||
mProgressControls,
|
||||
mWorkspaceWindow.GluonProgressOperationHandler,
|
||||
mGluonUpdateReport,
|
||||
mWorkspaceWindow,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
items => RefreshAsset.AfterLongAssetOperation(
|
||||
ProjectPackages.ShouldBeResolved(items, mWkInfo, true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06e8f2c592322e640ae99a833427b552
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,398 @@
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void SetLoadedBranchId(long loadedBranchId)
|
||||
{
|
||||
mLoadedBranchId = loadedBranchId;
|
||||
}
|
||||
|
||||
void DiffChangesetMenuItem_Click()
|
||||
{
|
||||
mChangesetMenuOperations.DiffChangeset();
|
||||
}
|
||||
|
||||
void DiffSelectedChangesetsMenuItem_Click()
|
||||
{
|
||||
mChangesetMenuOperations.DiffSelectedChangesets();
|
||||
}
|
||||
|
||||
void RevertToChangesetMenuItem_Click()
|
||||
{
|
||||
mChangesetMenuOperations.RevertToChangeset();
|
||||
}
|
||||
|
||||
void DiffBranchMenuItem_Click()
|
||||
{
|
||||
mMenuOperations.DiffBranch();
|
||||
}
|
||||
|
||||
void SwitchToChangesetMenuItem_Click()
|
||||
{
|
||||
mChangesetMenuOperations.SwitchToChangeset();
|
||||
}
|
||||
|
||||
void MergeChangesetMenuItem_Click()
|
||||
{
|
||||
mChangesetMenuOperations.MergeChangeset();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
menu.AddSeparator(string.Empty);
|
||||
|
||||
AddMergeChangesetMenuItem(
|
||||
mMergeChangesetMenuItemContent,
|
||||
menu,
|
||||
operations,
|
||||
MergeChangesetMenuItem_Click);
|
||||
}
|
||||
|
||||
void ProcessMenuOperation(
|
||||
ChangesetMenuOperations operationToExecute)
|
||||
{
|
||||
if (operationToExecute == ChangesetMenuOperations.DiffChangeset)
|
||||
{
|
||||
DiffChangesetMenuItem_Click();
|
||||
return;
|
||||
}
|
||||
|
||||
if (operationToExecute == ChangesetMenuOperations.DiffSelectedChangesets)
|
||||
{
|
||||
DiffSelectedChangesetsMenuItem_Click();
|
||||
return;
|
||||
}
|
||||
|
||||
if (operationToExecute == ChangesetMenuOperations.MergeChangeset)
|
||||
{
|
||||
MergeChangesetMenuItem_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 void AddMergeChangesetMenuItem(
|
||||
GUIContent menuItemContent,
|
||||
GenericMenu menu,
|
||||
ChangesetMenuOperations operations,
|
||||
GenericMenu.MenuFunction menuFunction)
|
||||
{
|
||||
if (operations.HasFlag(ChangesetMenuOperations.MergeChangeset))
|
||||
{
|
||||
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;
|
||||
|
||||
if (Keyboard.IsControlOrCommandKeyPressed(e) &&
|
||||
Keyboard.IsKeyPressed(e, KeyCode.M))
|
||||
return ChangesetMenuOperations.MergeChangeset;
|
||||
|
||||
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));
|
||||
mMergeChangesetMenuItemContent = new GUIContent(string.Format("{0} {1}",
|
||||
PlasticLocalization.GetString(PlasticLocalization.Name.ChangesetMenuItemMergeFromChangeset),
|
||||
GetPlasticShortcut.ForMerge()));
|
||||
}
|
||||
|
||||
GenericMenu mMenu;
|
||||
|
||||
GUIContent mDiffChangesetMenuItemContent;
|
||||
GUIContent mDiffSelectedChangesetsMenuItemContent;
|
||||
GUIContent mDiffBranchMenuItemContent;
|
||||
GUIContent mSwitchToChangesetMenuItemContent;
|
||||
GUIContent mRevertToChangesetMenuItemContent;
|
||||
GUIContent mMergeChangesetMenuItemContent;
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 397f62458d0ad3441aaaa1a738bd4f94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a4d62c64067bca4cbbd6f7fcad2e190
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6483fd05e8bf42a47aee5e11dbf6db8a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3389e142c33d23546a31fc469443a2c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 173564ff53b74604b8e070b51861b3f9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,336 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
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.AssetUtils.Processor;
|
||||
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 repository = mCreateWorkspaceState.Repository;
|
||||
|
||||
DrawCreateWorkspace.ForState(
|
||||
SelectRepository,
|
||||
CreateRepository,
|
||||
ValidateAndCreateWorkspace,
|
||||
mParentWindow,
|
||||
mPlasticWebRestApi,
|
||||
mDefaultServer,
|
||||
ref mCreateWorkspaceState);
|
||||
|
||||
if (repository == mCreateWorkspaceState.Repository)
|
||||
return;
|
||||
|
||||
SynchronizeRepositoryAndWorkspace();
|
||||
}
|
||||
|
||||
void Initialize(IPlasticAPI plasticApi, IPlasticWebRestApi plasticWebRestApi)
|
||||
{
|
||||
((IProgressControls)mProgressControls).ShowProgress(string.Empty);
|
||||
|
||||
WorkspaceInfo[] allWorkspaces = null;
|
||||
IList allRepositories = null;
|
||||
string repositoryProject = null;
|
||||
|
||||
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
|
||||
waiter.Execute(
|
||||
/*threadOperationDelegate*/ delegate
|
||||
{
|
||||
mDefaultServer = GetDefaultServer.ToCreateWorkspace(plasticWebRestApi);
|
||||
|
||||
allWorkspaces = plasticApi.GetAllWorkspacesArray();
|
||||
allRepositories = plasticApi.GetAllRepositories(mDefaultServer, true);
|
||||
|
||||
if (OrganizationsInformation.IsUnityOrganization(mDefaultServer))
|
||||
{
|
||||
List<string> serverProjects = OrganizationsInformation.GetOrganizationProjects(mDefaultServer);
|
||||
|
||||
if (serverProjects.Count > 0)
|
||||
{
|
||||
repositoryProject = serverProjects.First();
|
||||
}
|
||||
}
|
||||
},
|
||||
/*afterOperationDelegate*/ delegate
|
||||
{
|
||||
((IProgressControls) mProgressControls).HideProgress();
|
||||
|
||||
if (waiter.Exception != null)
|
||||
{
|
||||
DisplayException(mProgressControls, waiter.Exception);
|
||||
return;
|
||||
}
|
||||
|
||||
string serverSpecPart = string.Format("@{0}", ResolveServer.ToDisplayString(mDefaultServer));
|
||||
|
||||
mCreateWorkspaceState.Repository = ValidRepositoryName.Get(
|
||||
string.Format("{0}{1}", mCreateWorkspaceState.Repository, serverSpecPart),
|
||||
allRepositories);
|
||||
|
||||
if (repositoryProject != null)
|
||||
{
|
||||
mCreateWorkspaceState.Repository = string.Format("{0}/{1}", repositoryProject, mCreateWorkspaceState.Repository);
|
||||
}
|
||||
|
||||
string proposedWorkspaceName = mCreateWorkspaceState.Repository.Replace(serverSpecPart, string.Empty);
|
||||
|
||||
mCreateWorkspaceState.WorkspaceName = CreateWorkspaceDialogUserAssistant.GetNonExistingWkNameForName(
|
||||
proposedWorkspaceName, allWorkspaces);
|
||||
|
||||
mDialogUserAssistant = CreateWorkspaceDialogUserAssistant.ForWkPathAndName(
|
||||
mWorkspacePath,
|
||||
allWorkspaces);
|
||||
|
||||
SynchronizeRepositoryAndWorkspace();
|
||||
});
|
||||
}
|
||||
|
||||
void SynchronizeRepositoryAndWorkspace()
|
||||
{
|
||||
if (mDialogUserAssistant == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDialogUserAssistant.RepositoryChanged(
|
||||
mCreateWorkspaceState.Repository,
|
||||
mCreateWorkspaceState.WorkspaceName,
|
||||
mWorkspacePath);
|
||||
|
||||
mCreateWorkspaceState.WorkspaceName = mDialogUserAssistant.GetProposedWorkspaceName();
|
||||
}
|
||||
|
||||
void SelectRepository(string repository)
|
||||
{
|
||||
mCreateWorkspaceState.Repository = repository;
|
||||
SynchronizeRepositoryAndWorkspace();
|
||||
}
|
||||
|
||||
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.Repository = createdRepository.GetRepSpec().ToDisplayString();
|
||||
|
||||
SynchronizeRepositoryAndWorkspace();
|
||||
});
|
||||
}
|
||||
|
||||
void ValidateAndCreateWorkspace(CreateWorkspaceViewState state)
|
||||
{
|
||||
// We need a conversion here because the actual repSpec is used during the AsyncValidation
|
||||
// to call UpdateLastUsedRepositoryPreference. Also, it is the one to be used during wk creation
|
||||
RepositorySpec repSpec = OrganizationsInformation.TryResolveRepositorySpecFromInput(state.Repository);
|
||||
|
||||
if (repSpec == null)
|
||||
{
|
||||
((IProgressControls) mProgressControls).ShowError(
|
||||
PlasticLocalization.Name.UnresolvedRepository.GetString(state.Repository));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mWkCreationData = BuildCreationDataFromState(state, mWorkspacePath, repSpec);
|
||||
|
||||
// AsyncValidation calls IPlasticDialogCloser.CloseDialog() when the validation is ok
|
||||
WorkspaceCreationValidation.AsyncValidation(mWkCreationData, this, mProgressControls);
|
||||
}
|
||||
|
||||
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, CmConnection.Get().UnityOrgResolver);
|
||||
|
||||
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)
|
||||
{
|
||||
UnityCloudProjectLinkMonitor.CheckCloudProjectAlignmentAsync(wkInfo);
|
||||
|
||||
PerformInitialCheckin.IfRepositoryIsEmpty(
|
||||
wkInfo,
|
||||
mWkCreationData.Repository,
|
||||
mWkCreationData.IsGluonWorkspace,
|
||||
PlasticGui.Plastic.API,
|
||||
mProgressControls,
|
||||
mCreateWorkspaceListener,
|
||||
mParentWindow);
|
||||
}
|
||||
|
||||
static WorkspaceCreationData BuildCreationDataFromState(
|
||||
CreateWorkspaceViewState state,
|
||||
string workspacePath,
|
||||
RepositorySpec repSpec)
|
||||
{
|
||||
return new WorkspaceCreationData(
|
||||
state.WorkspaceName,
|
||||
workspacePath,
|
||||
repSpec.ToString(),
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5294f667272fcb2438a79369c92cc7e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
using UnityEngine;
|
||||
|
||||
using Unity.PlasticSCM.Editor.UI.Progress;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
|
||||
{
|
||||
internal class CreateWorkspaceViewState
|
||||
{
|
||||
internal enum WorkspaceModes
|
||||
{
|
||||
Developer,
|
||||
Gluon
|
||||
}
|
||||
|
||||
internal string Repository { 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()
|
||||
{
|
||||
Repository = projectName,
|
||||
WorkspaceName = projectName,
|
||||
WorkspaceMode = WorkspaceModes.Developer,
|
||||
ProgressData = new ProgressControlsForViews.Data()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41633509da720014cbd77f755b378ce7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cecb087091caedf48adcc1cd3b0ebd6d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,430 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.Common;
|
||||
using Codice.Client.Common.Threading;
|
||||
using Codice.CM.Common;
|
||||
using PlasticGui;
|
||||
using PlasticGui.WorkspaceWindow.Home.Repositories;
|
||||
using PlasticGui.WebApi;
|
||||
using PlasticGui.WorkspaceWindow.Servers;
|
||||
using Unity.PlasticSCM.Editor.Tool;
|
||||
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, 340);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
bool dialogResultOk = dialogResult == ResponseType.Ok;
|
||||
|
||||
RepositoryCreationData result = dialogResultOk ? dialog.BuildCreationData() : new RepositoryCreationData();
|
||||
result.Result = dialogResultOk;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override void OnModalGUI()
|
||||
{
|
||||
Title(PlasticLocalization.Name.NewRepositoryTitle.GetString());
|
||||
|
||||
Paragraph(PlasticLocalization.Name.NewRepositoryExplanation.GetString());
|
||||
|
||||
Paragraph(PlasticLocalization.Name.CreateRepositoryDialogDetailedExplanation.GetString());
|
||||
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
mProgressControls.ProgressData.CopyInto(mProgressData);
|
||||
}
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
DoEntriesArea();
|
||||
|
||||
DrawProgressForDialogs.For(mProgressControls.ProgressData);
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
DoButtonsArea();
|
||||
|
||||
mProgressControls.ForcedUpdateProgress(this);
|
||||
}
|
||||
|
||||
protected override string GetTitle()
|
||||
{
|
||||
return PlasticLocalization.Name.NewRepositoryTitle.GetString();
|
||||
}
|
||||
|
||||
void KnownServersListOperations.IKnownServersList.FillValues(List<string> knownServers)
|
||||
{
|
||||
// Filter out local server if there is no local installation
|
||||
// TODO Remove if a unified solution is applied to the unityplastic library
|
||||
if (knownServers.Contains(LocalOnlyServer.Alias) && !IsExeAvailable.ForLocalServer())
|
||||
{
|
||||
knownServers.Remove(LocalOnlyServer.Alias);
|
||||
}
|
||||
|
||||
mKnownServers = knownServers.Select(ResolveServer.ToDisplayString).ToList();
|
||||
mKnownServers.Sort();
|
||||
|
||||
OnServerSelected(mSelectedServer);
|
||||
}
|
||||
|
||||
void DoEntriesArea()
|
||||
{
|
||||
mRepositoryName = TextEntry(
|
||||
PlasticLocalization.Name.RepositoryNameShortLabel.GetString(),
|
||||
mRepositoryName,
|
||||
REPONAME_CONTROL_NAME,
|
||||
ENTRY_WIDTH,
|
||||
ENTRY_X);
|
||||
|
||||
if (!mFocusIsAreadySet)
|
||||
{
|
||||
mFocusIsAreadySet = true;
|
||||
GUI.FocusControl(REPONAME_CONTROL_NAME);
|
||||
}
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
mSelectedServer = ComboBox(
|
||||
PlasticLocalization.Name.RepositoryServerOrOrganizationLabel.GetString(),
|
||||
mSelectedServer,
|
||||
mKnownServers,
|
||||
OnServerSelected,
|
||||
ENTRY_WIDTH,
|
||||
ENTRY_X);
|
||||
|
||||
if (OrganizationsInformation.IsUnityOrganization(mSelectedServer) && mKnownServers.Contains(mSelectedServer))
|
||||
{
|
||||
GUILayout.Space(5);
|
||||
|
||||
DoOrganizationProjectsDropdown();
|
||||
DoCreateOrganizationProjectLink();
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedProject = null;
|
||||
mCurrentServerProjects = null;
|
||||
}
|
||||
}
|
||||
|
||||
void DoOrganizationProjectsDropdown()
|
||||
{
|
||||
if (mIsLoadingProjects || mSelectedProject == null)
|
||||
{
|
||||
GUI.enabled = false;
|
||||
}
|
||||
|
||||
ComboBox(
|
||||
PlasticLocalization.Name.OrganizationProjectLabel.GetString(),
|
||||
mSelectedProject,
|
||||
mCurrentServerProjects,
|
||||
OnProjectSelected,
|
||||
ENTRY_WIDTH,
|
||||
ENTRY_X);
|
||||
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
void DoCreateOrganizationProjectLink()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
if (GUILayout.Button(
|
||||
PlasticLocalization.Name.CreateOrganizationProjectLabel.GetString(),
|
||||
UnityStyles.LinkLabel,
|
||||
GUILayout.Height(20)))
|
||||
{
|
||||
string resolvedServer = OrganizationsInformation.TryResolveServerFromInput(mSelectedServer);
|
||||
|
||||
if (!string.IsNullOrEmpty(resolvedServer))
|
||||
{
|
||||
string organizationName = ServerOrganizationParser.GetOrganizationFromServer(resolvedServer);
|
||||
Application.OpenURL(UnityUrl.UnityDashboard.UnityOrganizations.GetProjectsUrl(organizationName));
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
void OnServerSelected(object server)
|
||||
{
|
||||
((IProgressControls) mProgressControls).HideProgress();
|
||||
mProgressControls.ProgressData.StatusMessage = string.Empty;
|
||||
mProgressControls.ProgressData.StatusType = MessageType.None;
|
||||
|
||||
mIsLoadingProjects = false;
|
||||
|
||||
if (server == null || string.IsNullOrEmpty(server.ToString()))
|
||||
{
|
||||
mSelectedServer = null;
|
||||
mSelectedProject = null;
|
||||
mCurrentServerProjects = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mSelectedServer = server.ToString();
|
||||
|
||||
// We need to ensure it is a known server because the dropdown is editable
|
||||
if (OrganizationsInformation.IsUnityOrganization(mSelectedServer) && mKnownServers.Contains(mSelectedServer))
|
||||
{
|
||||
LoadServerProjects(mSelectedServer);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedProject = null;
|
||||
}
|
||||
|
||||
Repaint();
|
||||
}
|
||||
|
||||
void OnFocus()
|
||||
{
|
||||
OnServerSelected(mSelectedServer);
|
||||
}
|
||||
|
||||
void OnProjectSelected(object project)
|
||||
{
|
||||
mSelectedProject = project.ToString();
|
||||
|
||||
Repaint();
|
||||
}
|
||||
|
||||
void LoadServerProjects(string server)
|
||||
{
|
||||
mIsLoadingProjects = true;
|
||||
mCurrentServerProjects = null;
|
||||
|
||||
((IProgressControls) mProgressControls).ShowProgress(
|
||||
PlasticLocalization.Name.RetrievingServerProjects.GetString());
|
||||
|
||||
List<string> serverProjects = null;
|
||||
|
||||
IThreadWaiter waiter = ThreadWaiter.GetWaiter();
|
||||
waiter.Execute(
|
||||
/*threadOperationDelegate*/ delegate
|
||||
{
|
||||
string serverName = ResolveServer.FromUserInput(server, CmConnection.Get().UnityOrgResolver);
|
||||
|
||||
serverProjects = OrganizationsInformation.GetOrganizationProjects(serverName);
|
||||
},
|
||||
/*afterOperationDelegate*/ delegate
|
||||
{
|
||||
mIsLoadingProjects = false;
|
||||
|
||||
if (waiter.Exception != null)
|
||||
{
|
||||
((IProgressControls) mProgressControls).ShowError(
|
||||
PlasticLocalization.Name.ErrorRetrievingServerProjects.GetString());
|
||||
}
|
||||
|
||||
mCurrentServerProjects = serverProjects;
|
||||
|
||||
if (mCurrentServerProjects == null || mCurrentServerProjects.Count == 0)
|
||||
{
|
||||
mSelectedProject = null;
|
||||
|
||||
((IProgressControls) mProgressControls).ShowError(
|
||||
PlasticLocalization.Name.NoServerProjectsFound.GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(mSelectedProject) || !mCurrentServerProjects.Contains(mSelectedProject))
|
||||
{
|
||||
mSelectedProject = mCurrentServerProjects.First();
|
||||
}
|
||||
|
||||
((IProgressControls) mProgressControls).HideProgress();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void DoButtonsArea()
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||
{
|
||||
DoOkButton();
|
||||
DoCancelButton();
|
||||
return;
|
||||
}
|
||||
|
||||
DoCancelButton();
|
||||
DoOkButton();
|
||||
}
|
||||
}
|
||||
|
||||
void DoOkButton()
|
||||
{
|
||||
if (mIsLoadingProjects ||
|
||||
(OrganizationsInformation.IsUnityOrganization(mSelectedServer) && string.IsNullOrEmpty(mSelectedProject)))
|
||||
{
|
||||
GUI.enabled = false;
|
||||
}
|
||||
|
||||
if (AcceptButton(PlasticLocalization.Name.OkButton.GetString()))
|
||||
{
|
||||
OkButtonWithValidationAction();
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
void DoCancelButton()
|
||||
{
|
||||
if (!NormalButton(PlasticLocalization.Name.CancelButton.GetString()))
|
||||
return;
|
||||
|
||||
CancelButtonAction();
|
||||
}
|
||||
|
||||
void OkButtonWithValidationAction()
|
||||
{
|
||||
// If the validation goes OK, this method closes the dialog
|
||||
RepositoryCreationValidation.AsyncValidation(
|
||||
BuildCreationData(),
|
||||
this,
|
||||
mProgressControls);
|
||||
}
|
||||
|
||||
void OnEnterKeyAction()
|
||||
{
|
||||
if (!OrganizationsInformation.IsUnityOrganization(mSelectedServer))
|
||||
{
|
||||
OkButtonWithValidationAction();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mKnownServers.Contains(mSelectedServer))
|
||||
{
|
||||
if (string.IsNullOrEmpty(mSelectedProject))
|
||||
{
|
||||
OnServerSelected(mSelectedServer);
|
||||
}
|
||||
else
|
||||
{
|
||||
OkButtonWithValidationAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RepositoryCreationData BuildCreationData()
|
||||
{
|
||||
string resolvedServer = OrganizationsInformation.TryResolveServerFromInput(mSelectedServer);
|
||||
|
||||
string repositoryName = mSelectedProject != null
|
||||
? string.Format("{0}/{1}", mSelectedProject, mRepositoryName)
|
||||
: mRepositoryName;
|
||||
|
||||
return new RepositoryCreationData(
|
||||
repositoryName,
|
||||
resolvedServer != null ? resolvedServer : mSelectedServer);
|
||||
}
|
||||
|
||||
static CreateRepositoryDialog Create(
|
||||
IPlasticWebRestApi plasticWebRestApi,
|
||||
ProgressControlsForDialogs progressControls,
|
||||
string proposedRepositoryName,
|
||||
string proposedServer)
|
||||
{
|
||||
var instance = CreateInstance<CreateRepositoryDialog>();
|
||||
instance.mEnterKeyAction = instance.OnEnterKeyAction;
|
||||
instance.mEscapeKeyAction = instance.CancelButtonAction;
|
||||
instance.mPlasticWebRestApi = plasticWebRestApi;
|
||||
instance.mProgressControls = progressControls;
|
||||
instance.BuildComponents(proposedRepositoryName, proposedServer);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void BuildComponents(string proposedRepositoryName, string proposedServer)
|
||||
{
|
||||
mSelectedServer = ResolveServer.ToDisplayString(proposedServer);
|
||||
mRepositoryName = proposedRepositoryName;
|
||||
|
||||
if (OrganizationsInformation.IsUnityOrganization(proposedServer))
|
||||
{
|
||||
string[] repositoryNameParts = proposedRepositoryName.Split('/');
|
||||
|
||||
if (repositoryNameParts.Length > 1)
|
||||
{
|
||||
mRepositoryName = repositoryNameParts[repositoryNameParts.Length - 1].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
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 mRepositoryName;
|
||||
string mSelectedServer;
|
||||
string mSelectedProject;
|
||||
bool mIsLoadingProjects;
|
||||
List<string> mCurrentServerProjects;
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61f74d0a8a3f1f542b8afe99e65686df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da6a50477d2d7ff4f81d1c21c58a5b0e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,252 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Codice.Client.Common;
|
||||
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().ToDisplayString();
|
||||
}
|
||||
|
||||
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.ServerDisplayName,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c18598e9d808edb4583a6aa724ffc268
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,347 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.Common;
|
||||
using Codice.CM.Common;
|
||||
using PlasticGui;
|
||||
using PlasticGui.WorkspaceWindow.Home.Repositories;
|
||||
using PlasticGui.WebApi;
|
||||
using PlasticGui.WorkspaceWindow.Servers;
|
||||
using Unity.PlasticSCM.Editor.Tool;
|
||||
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()
|
||||
{
|
||||
string resolvedServer = OrganizationsInformation.TryResolveServerFromInput(mState.SelectedServer);
|
||||
|
||||
// Even if the server input cannot be resolved, we still want to fill the table so it gets reset
|
||||
mFillRepositoriesTable.FillTable(
|
||||
mRepositoriesListView,
|
||||
null,
|
||||
mProgressControls,
|
||||
null,
|
||||
new FillRepositoriesTable.SaveLastUsedServer(true),
|
||||
mGuiMessage,
|
||||
null,
|
||||
null,
|
||||
this,
|
||||
resolvedServer != null ? resolvedServer : mState.SelectedServer,
|
||||
false,
|
||||
false,
|
||||
true);
|
||||
}
|
||||
|
||||
void KnownServersListOperations.IKnownServersList.FillValues(List<string> knownServers)
|
||||
{
|
||||
// Filter out local server if there is no local installation
|
||||
// TODO Remove if a unified solution is applied to the unityplastic library
|
||||
if (knownServers.Contains(LocalOnlyServer.Alias) && !IsExeAvailable.ForLocalServer())
|
||||
{
|
||||
knownServers.Remove(LocalOnlyServer.Alias);
|
||||
}
|
||||
|
||||
mState.AvailableServers = knownServers.Select(ResolveServer.ToDisplayString).ToList();
|
||||
mState.AvailableServers.Sort();
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
string FillRepositoriesTable.IGetFilterText.Get()
|
||||
{
|
||||
return mRepositoriesListView.searchString;
|
||||
}
|
||||
|
||||
void OnServerSelected(object server)
|
||||
{
|
||||
mState.SelectedServer = 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.SelectedServer = DoDropDownTextField(
|
||||
state.SelectedServer,
|
||||
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()
|
||||
{
|
||||
SelectedServer = ResolveServer.ToDisplayString(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 SelectedServer { get; set; }
|
||||
internal ProgressControlsForDialogs.Data ProgressData { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b29af44841cd6644e876233cd057bc18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using Codice.Client.Common;
|
||||
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 string ServerDisplayName { get; private set; }
|
||||
|
||||
internal RepositoryListViewItem(int id, RepositoryInfo repository)
|
||||
: base(id, 0)
|
||||
{
|
||||
Repository = repository;
|
||||
ServerDisplayName = ResolveServer.ToDisplayString(repository.Server);
|
||||
|
||||
displayName = repository.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83882c7718d0fc34f8a05141328ceac1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,507 @@
|
||||
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<string> selectRepositoryAction,
|
||||
Action<RepositoryCreationData> createRepositoryAction,
|
||||
Action<CreateWorkspaceViewState> createWorkspaceAction,
|
||||
EditorWindow parentWindow,
|
||||
IPlasticWebRestApi plasticWebRestApi,
|
||||
string defaultServer,
|
||||
ref CreateWorkspaceViewState state)
|
||||
{
|
||||
DoTitle();
|
||||
|
||||
GUILayout.Space(15);
|
||||
|
||||
DoFieldsArea(
|
||||
selectRepositoryAction,
|
||||
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<string> selectRepositoryAction,
|
||||
Action<RepositoryCreationData> createRepositoryAction,
|
||||
EditorWindow parentWindow,
|
||||
IPlasticWebRestApi plasticWebRestApi,
|
||||
string defaultServer,
|
||||
ref CreateWorkspaceViewState state)
|
||||
{
|
||||
DoRepositoryField(
|
||||
selectRepositoryAction,
|
||||
createRepositoryAction,
|
||||
parentWindow,
|
||||
plasticWebRestApi,
|
||||
defaultServer,
|
||||
ref state);
|
||||
|
||||
DoWorkspaceField(ref state);
|
||||
}
|
||||
|
||||
static void DoRepositoryField(
|
||||
Action<string> selectRepositoryAction,
|
||||
Action<RepositoryCreationData> createRepositoryAction,
|
||||
EditorWindow parentWindow,
|
||||
IPlasticWebRestApi plasticWebRestApi,
|
||||
string defaultServer,
|
||||
ref CreateWorkspaceViewState state)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
DoLabel(PlasticLocalization.GetString(PlasticLocalization.Name.Repository));
|
||||
|
||||
state.Repository = DoTextField(
|
||||
state.Repository,
|
||||
!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(
|
||||
selectRepositoryAction,
|
||||
parentWindow,
|
||||
plasticWebRestApi,
|
||||
defaultServer);
|
||||
|
||||
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.Repository,
|
||||
defaultServer);
|
||||
|
||||
EditorGUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
ValidationResult validationResult = ValidateRepository(state.Repository);
|
||||
|
||||
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(
|
||||
Action<string> selectRepositoryAction,
|
||||
EditorWindow parentWindow,
|
||||
IPlasticWebRestApi plasticWebRestApi,
|
||||
string defaultServer)
|
||||
{
|
||||
string selectedRepository = RepositoryExplorerDialog.BrowseRepository(
|
||||
parentWindow,
|
||||
plasticWebRestApi,
|
||||
defaultServer);
|
||||
|
||||
if (string.IsNullOrEmpty(selectedRepository))
|
||||
return;
|
||||
|
||||
selectRepositoryAction(selectedRepository);
|
||||
}
|
||||
|
||||
static void DoNewRepositoryButton(
|
||||
Action<RepositoryCreationData> createRepositoryAction,
|
||||
EditorWindow parentWindow,
|
||||
IPlasticWebRestApi plasticWebRestApi,
|
||||
string repositorySpecInput,
|
||||
string defaultServer)
|
||||
{
|
||||
string proposedRepositoryName;
|
||||
string proposedServer;
|
||||
|
||||
RepositorySpec repSpec = OrganizationsInformation.TryResolveRepositorySpecFromInput(repositorySpecInput);
|
||||
|
||||
if (repSpec != null)
|
||||
{
|
||||
proposedRepositoryName = repSpec.Name;
|
||||
proposedServer = repSpec.Server;
|
||||
}
|
||||
else
|
||||
{
|
||||
proposedRepositoryName = ExtractRepositoryName(repositorySpecInput);
|
||||
proposedServer = defaultServer;
|
||||
}
|
||||
|
||||
RepositoryCreationData creationData = CreateRepositoryDialog.CreateRepository(
|
||||
parentWindow,
|
||||
plasticWebRestApi,
|
||||
proposedRepositoryName,
|
||||
proposedServer,
|
||||
defaultServer,
|
||||
ClientConfig.Get().GetWorkspaceServer());
|
||||
|
||||
createRepositoryAction(creationData);
|
||||
}
|
||||
|
||||
static string ExtractRepositoryName(string repositorySpec)
|
||||
{
|
||||
string[] repositoryParts = repositorySpec.Split('@');
|
||||
|
||||
return repositoryParts.Length > 0 ? repositoryParts[0] : string.Empty;
|
||||
}
|
||||
|
||||
static void DoHelpLabel()
|
||||
{
|
||||
string linkText =PlasticLocalization.Name.HereLink.GetString();
|
||||
string labelText = PlasticLocalization.Name.LearnMoreDifferencesUnityVCS.GetString();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUIStyle labelStyle = new GUIStyle(EditorStyles.miniLabel);
|
||||
labelStyle.richText = true;
|
||||
labelStyle.stretchWidth = false;
|
||||
labelStyle.margin = new RectOffset();
|
||||
labelStyle.padding.left = LEARN_MORE_LABEL_LEFT_PADDING;
|
||||
|
||||
GUILayout.Label(labelText, labelStyle);
|
||||
|
||||
GUIStyle linkStyle = new GUIStyle(UnityStyles.LinkLabel);
|
||||
linkStyle.fontSize = EditorStyles.miniLabel.fontSize;
|
||||
linkStyle.stretchWidth = false;
|
||||
linkStyle.margin = new RectOffset();
|
||||
|
||||
if (GUILayout.Button(linkText, linkStyle))
|
||||
{
|
||||
Application.OpenURL(PlasticLocalization.Name.PlasticSCMFullVsPartialWorkspaceLink.GetString());
|
||||
}
|
||||
|
||||
EditorGUIUtility.AddCursorRect(
|
||||
GUILayoutUtility.GetLastRect(), MouseCursor.Link);
|
||||
|
||||
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);
|
||||
radioButtonStyle.padding.left = RADIO_BUTTON_LEFT_PADDING;
|
||||
|
||||
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.HeaderWarningLabel);
|
||||
}
|
||||
|
||||
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 bool IsValidState(
|
||||
CreateWorkspaceViewState state)
|
||||
{
|
||||
if (!ValidateRepository(state.Repository).IsValid)
|
||||
return false;
|
||||
|
||||
if (!ValidateWorkspaceName(state.WorkspaceName).IsValid)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static ValidationResult ValidateRepository(string repository)
|
||||
{
|
||||
ValidationResult result = new ValidationResult();
|
||||
|
||||
if (string.IsNullOrEmpty(repository))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 int RADIO_BUTTON_LEFT_PADDING = 20;
|
||||
const float PROGRESS_MARGIN = 5;
|
||||
const float CREATE_WORKSPACE_BUTTON_MARGIN = 32;
|
||||
const float CREATE_WORKSPACE_BUTTON_WIDTH = 160;
|
||||
const int LEARN_MORE_LABEL_LEFT_PADDING = 10;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 788db2c7ca3c2804d912f447ffc19856
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,179 @@
|
||||
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.CM.Common.Checkin.Partial;
|
||||
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, CmConnection.Get().UnityOrgResolver);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29e0becc4ce852c439ff3e642f0375bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 = '|';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60f5fb7fb3626214f9d97215fe186cbf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37b5532626676e045a3b172c915e5d79
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 156e16594aa6bd54cb77aa3f8eae5c82
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3fdd86a000d1ef04094416eefed53087
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ac250bc549a212428286f328779be0e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 281456381b1a4c742b0efbe305328c7a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,519 @@
|
||||
using System;
|
||||
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 Codice.CM.Common.Mount;
|
||||
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 OnEnable()
|
||||
{
|
||||
mSearchField.downOrUpArrowKeyPressed +=
|
||||
SearchField_OnDownOrUpArrowKeyPressed;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
ClientDiffInfo clientDiffInfo =
|
||||
DiffSelection.GetSelectedDiff(mDiffTreeView);
|
||||
|
||||
DiffOperation.DiffClientDiff(
|
||||
mWkInfo,
|
||||
clientDiffInfo.DiffWithMount.Mount.Mount,
|
||||
clientDiffInfo.DiffWithMount.Difference,
|
||||
PlasticExeLauncher.BuildForDiffRevision(mWkInfo, mIsGluonMode, mShowDownloadPlasticExeWindow),
|
||||
imageDiffLauncher: null);
|
||||
}
|
||||
|
||||
void IDiffTreeViewMenuOperations.History()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
void IDiffTreeViewMenuOperations.Annotate()
|
||||
{
|
||||
}
|
||||
|
||||
void IDiffTreeViewMenuOperations.CopyFilePath(bool relativePath)
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = GetFilePathList.FromClientDiffInfos(
|
||||
DiffSelection.GetSelectedDiffsWithoutMeta(mDiffTreeView),
|
||||
relativePath,
|
||||
mWkInfo.ClientPath);
|
||||
}
|
||||
|
||||
bool DiffTreeViewMenu.IMetaMenuOperations.SelectionHasMeta()
|
||||
{
|
||||
return mDiffTreeView.SelectionHasMeta();
|
||||
}
|
||||
|
||||
void DiffTreeViewMenu.IMetaMenuOperations.DiffMeta()
|
||||
{
|
||||
ClientDiffInfo clientDiffInfo =
|
||||
DiffSelection.GetSelectedDiff(mDiffTreeView);
|
||||
|
||||
ClientDiffInfo clientDiffInfoMeta =
|
||||
mDiffTreeView.GetMetaDiff(clientDiffInfo);
|
||||
|
||||
DiffOperation.DiffClientDiff(
|
||||
mWkInfo,
|
||||
clientDiffInfoMeta.DiffWithMount.Mount.Mount,
|
||||
clientDiffInfoMeta.DiffWithMount.Difference,
|
||||
PlasticExeLauncher.BuildForDiffRevision(mWkInfo, mIsGluonMode, mShowDownloadPlasticExeWindow),
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ee79162e06c6984a97600b7c0680611
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ef5fb54cd29b40468eaf5a14e9845ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba4e6e12f66973142a87299287cb34dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,323 @@
|
||||
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 CopyFilePathMenuItem_Click()
|
||||
{
|
||||
mOperations.CopyFilePath(relativePath: false);
|
||||
}
|
||||
|
||||
void CopyRelativeFilePathMenuItem_Click()
|
||||
{
|
||||
mOperations.CopyFilePath(relativePath: true);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (operations.HasFlag(DiffTreeViewMenuOperations.CopyFilePath))
|
||||
{
|
||||
menu.AddSeparator(string.Empty);
|
||||
|
||||
menu.AddItem(
|
||||
mCopyFilePathMenuItemContent, false, CopyFilePathMenuItem_Click);
|
||||
menu.AddItem(
|
||||
mCopyRelativeFilePathMenuItemContent, false, CopyRelativeFilePathMenuItem_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();
|
||||
mCopyFilePathMenuItemContent = new GUIContent(PlasticLocalization.Name.CopyFilePathMenuItem.GetString());
|
||||
mCopyRelativeFilePathMenuItemContent =
|
||||
new GUIContent(PlasticLocalization.Name.CopyRelativeFilePathMenuItem.GetString());
|
||||
}
|
||||
|
||||
GUIContent mNoActionMenuItemContent;
|
||||
|
||||
GUIContent mSaveRevisionAsMenuItemContent;
|
||||
GUIContent mDiffMenuItemContent;
|
||||
GUIContent mDiffMetaMenuItemContent;
|
||||
GUIContent mViewHistoryMenuItemContent;
|
||||
GUIContent mViewHistoryMetaMenuItemContent;
|
||||
GUIContent mRevertMenuItemContent;
|
||||
GUIContent mUndeleteMenuItemContent;
|
||||
GUIContent mUndeleteToSpecifiedPathMenuItemContent;
|
||||
GUIContent mCopyFilePathMenuItemContent;
|
||||
GUIContent mCopyRelativeFilePathMenuItemContent;
|
||||
|
||||
readonly IDiffTreeViewMenuOperations mOperations;
|
||||
readonly IMetaMenuOperations mMetaMenuOperations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c9c0041347ae4e4cb794a3da850fa79
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ab43506dddfc244ab5b44585140c5a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 923dacaaac477a941a4a5c7c1657a250
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e89b1e9e9f1060b4f817977507831248
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,258 @@
|
||||
using System.Linq;
|
||||
|
||||
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.Tool;
|
||||
using Unity.PlasticSCM.Editor.UI;
|
||||
using Unity.PlasticSCM.Editor.UI.UIElements;
|
||||
using Unity.PlasticSCM.Editor.Views.Welcome;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views
|
||||
{
|
||||
internal class DownloadPlasticExeDialog : PlasticDialog, DownloadAndInstallOperation.INotify
|
||||
{
|
||||
internal bool IsPlasticInstalling { get { return mIsPlasticInstalling; } }
|
||||
|
||||
protected override Rect DefaultRect
|
||||
{
|
||||
get
|
||||
{
|
||||
var baseRect = base.DefaultRect;
|
||||
return new Rect(baseRect.x, baseRect.y, DIALOG_WIDTH, DIALOG_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
internal static ProgressControlsForDialogs.Data Show(
|
||||
RepositorySpec repSpec,
|
||||
bool isGluonMode,
|
||||
string installCloudFrom,
|
||||
string installEnterpriseFrom,
|
||||
string cancelInstallFrom,
|
||||
ProgressControlsForDialogs.Data progressData)
|
||||
{
|
||||
DownloadPlasticExeDialog dialog;
|
||||
|
||||
if (HasOpenInstances<DownloadPlasticExeDialog>())
|
||||
{
|
||||
dialog = GetWindow<DownloadPlasticExeDialog>(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
dialog = Create(repSpec, isGluonMode, installCloudFrom, installEnterpriseFrom, cancelInstallFrom, progressData);
|
||||
|
||||
dialog.RunUtility(focusedWindow);
|
||||
}
|
||||
|
||||
return progressData != null ? progressData : dialog.mProgressControls.ProgressData;
|
||||
}
|
||||
|
||||
static DownloadPlasticExeDialog Create(
|
||||
RepositorySpec repSpec,
|
||||
bool isGluonMode,
|
||||
string installCloudFrom,
|
||||
string installEnterpriseFrom,
|
||||
string cancelInstallFrom,
|
||||
ProgressControlsForDialogs.Data progressData)
|
||||
{
|
||||
var instance = CreateInstance<DownloadPlasticExeDialog>();
|
||||
instance.mRepSpec = repSpec;
|
||||
instance.mInstallCloudFrom = installCloudFrom;
|
||||
instance.mInstallEnterpriseFrom = installEnterpriseFrom;
|
||||
instance.mCancelInstallFrom = cancelInstallFrom;
|
||||
instance.mIsGluonMode = isGluonMode;
|
||||
instance.mProgressData = progressData;
|
||||
instance.mInstallerFile = GetInstallerTmpFileName.ForPlatform();
|
||||
instance.mIsCloudEdition = EditionToken.IsCloudEdition();
|
||||
instance.mTitle = PlasticLocalization.Name.UnityVersionControl.GetString();
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected override string GetTitle()
|
||||
{
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
BuildComponents();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
protected override void OnModalGUI()
|
||||
{
|
||||
if (InstallationFinished())
|
||||
{
|
||||
mMessageLabel.text = PlasticLocalization.Name.UnityVersionControlInstalled.GetString();
|
||||
mCancelButton.text = PlasticLocalization.Name.CloseButton.GetString();
|
||||
mConfirmMessageLabel.Collapse();
|
||||
mDownloadButton.Collapse();
|
||||
maxSize = new Vector2(DIALOG_WIDTH, REDUCED_DIALOG_HEIGHT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mProgressData != null)
|
||||
{
|
||||
if (mProgressControlsContainer.Children().OfType<ProgressControlsForDialogs>().Any())
|
||||
{
|
||||
mProgressControlsContainer.RemoveAt(0);
|
||||
mProgressLabel = new Label(GetMessageFromProgressData(mProgressData));
|
||||
mProgressControlsContainer.Add(mProgressLabel);
|
||||
}
|
||||
|
||||
mProgressLabel.text = GetMessageFromProgressData(mProgressData);
|
||||
UpdateButtonsStatuses();
|
||||
}
|
||||
}
|
||||
|
||||
void CancelButton_Clicked()
|
||||
{
|
||||
if (!IsExeAvailable.ForMode(mIsGluonMode))
|
||||
TrackFeatureUseEvent.For(mRepSpec, mCancelInstallFrom);
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
void DownloadButton_Clicked()
|
||||
{
|
||||
if (mIsCloudEdition)
|
||||
{
|
||||
TrackFeatureUseEvent.For(mRepSpec, mInstallCloudFrom);
|
||||
|
||||
DownloadAndInstallOperation.Run(
|
||||
Edition.Cloud, mInstallerFile, mProgressControls, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackFeatureUseEvent.For(mRepSpec, mInstallEnterpriseFrom);
|
||||
|
||||
DownloadAndInstallOperation.Run(
|
||||
Edition.Enterprise, mInstallerFile, mProgressControls, this);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadAndInstallOperation.INotify.InstallationStarted()
|
||||
{
|
||||
mIsPlasticInstalling = true;
|
||||
}
|
||||
|
||||
void DownloadAndInstallOperation.INotify.InstallationFinished()
|
||||
{
|
||||
mIsPlasticInstalling = false;
|
||||
}
|
||||
|
||||
bool InstallationFinished()
|
||||
{
|
||||
return mCancelButton.enabledSelf && IsExeAvailable.ForMode(mIsGluonMode);
|
||||
}
|
||||
|
||||
void UpdateButtonsStatuses()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(mProgressData.StatusMessage))
|
||||
{
|
||||
mCancelButton.SetEnabled(true);
|
||||
mCancelButton.text = PlasticLocalization.Name.CloseButton.GetString();
|
||||
mDownloadButton.Collapse();
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsExeAvailable.ForMode(mIsGluonMode))
|
||||
{
|
||||
mCancelButton.SetEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
mDownloadButton.SetEnabled(false);
|
||||
mCancelButton.SetEnabled(false);
|
||||
}
|
||||
|
||||
static string GetMessageFromProgressData(ProgressControlsForDialogs.Data data)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(data.StatusMessage))
|
||||
{
|
||||
return data.StatusMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data.ProgressPercent >= 0)
|
||||
return string.Format("{0} ({1}%)", data.ProgressMessage, (int)(data.ProgressPercent * 100));
|
||||
else
|
||||
return data.ProgressMessage;
|
||||
}
|
||||
}
|
||||
|
||||
void Dispose()
|
||||
{
|
||||
mDownloadButton.clicked -= DownloadButton_Clicked;
|
||||
mCancelButton.clicked -= CancelButton_Clicked;
|
||||
}
|
||||
|
||||
void BuildComponents()
|
||||
{
|
||||
VisualElement root = rootVisualElement;
|
||||
root.Clear();
|
||||
|
||||
InitializeLayoutAndStyles();
|
||||
|
||||
mMessageLabel = root.Q<Label>("title");
|
||||
mConfirmMessageLabel = root.Q<Label>("message");
|
||||
mDownloadButton = root.Q<Button>("download");
|
||||
mCancelButton = root.Q<Button>("cancel");
|
||||
mProgressControlsContainer = root.Q<VisualElement>("progressControlsContainer");
|
||||
|
||||
mMessageLabel.text = PlasticLocalization.Name.InstallUnityVersionControl.GetString();
|
||||
mConfirmMessageLabel.text = PlasticLocalization.Name.InstallConfirmationMessage.GetString();
|
||||
mDownloadButton.text = PlasticLocalization.Name.YesButton.GetString();
|
||||
mDownloadButton.clicked += DownloadButton_Clicked;
|
||||
mCancelButton.text = PlasticLocalization.Name.NoButton.GetString();
|
||||
mCancelButton.clicked += CancelButton_Clicked;
|
||||
|
||||
mProgressControls = new ProgressControlsForDialogs(
|
||||
new VisualElement[] {
|
||||
mDownloadButton,
|
||||
mCancelButton
|
||||
});
|
||||
|
||||
mProgressControlsContainer.Add(mProgressControls);
|
||||
}
|
||||
|
||||
void InitializeLayoutAndStyles()
|
||||
{
|
||||
rootVisualElement.LoadLayout(typeof(DownloadPlasticExeDialog).Name);
|
||||
rootVisualElement.LoadStyle(typeof(DownloadPlasticExeDialog).Name);
|
||||
}
|
||||
|
||||
string mTitle;
|
||||
|
||||
Label mMessageLabel;
|
||||
Label mConfirmMessageLabel;
|
||||
Label mProgressLabel;
|
||||
Button mDownloadButton;
|
||||
Button mCancelButton;
|
||||
ProgressControlsForDialogs mProgressControls;
|
||||
VisualElement mProgressControlsContainer;
|
||||
|
||||
RepositorySpec mRepSpec;
|
||||
string mInstallCloudFrom;
|
||||
string mInstallEnterpriseFrom;
|
||||
string mCancelInstallFrom;
|
||||
string mInstallerFile;
|
||||
bool mIsCloudEdition;
|
||||
bool mIsGluonMode;
|
||||
bool mIsPlasticInstalling;
|
||||
ProgressControlsForDialogs.Data mProgressData;
|
||||
|
||||
const float DIALOG_WIDTH = 500;
|
||||
const float DIALOG_HEIGHT = 250;
|
||||
const float REDUCED_DIALOG_HEIGHT = 125;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08dbb8d51633f2f4bab9912fbce3e247
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5eff45d4f0cc5e478e6724c378098eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ac7d3b2f88744a4c89cb263306add7d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b6e8a80709e2264eb383ef6b40e181f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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, 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ee2845d0d4db9a4a9e8f4f6d0fa4e5e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1b8657301e8ead4a9389eda02c15883
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,224 @@
|
||||
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
|
||||
{
|
||||
internal GenericMenu Menu { get { return mMenu; } }
|
||||
|
||||
public interface IMenuOperations
|
||||
{
|
||||
long GetSelectedChangesetId();
|
||||
}
|
||||
|
||||
internal HistoryListViewMenu(
|
||||
IOpenMenuOperations openMenuOperations,
|
||||
IHistoryViewMenuOperations operations,
|
||||
IMenuOperations menuOperations)
|
||||
{
|
||||
mOpenMenuOperations = openMenuOperations;
|
||||
mOperations = operations;
|
||||
mMenuOperations = menuOperations;
|
||||
|
||||
BuildComponents();
|
||||
}
|
||||
|
||||
internal void Popup()
|
||||
{
|
||||
mMenu = new GenericMenu();
|
||||
|
||||
UpdateMenuItems(mMenu);
|
||||
|
||||
mMenu.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();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
GenericMenu mMenu;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3cec769cd6ff2849aa09c811b62e611
|
||||
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
Reference in New Issue
Block a user