initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

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

View file

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

View file

@ -0,0 +1,19 @@
using UnityEditor.IMGUI.Controls;
using PlasticGui.Gluon.WorkspaceWindow.Views.IncomingChanges;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon
{
internal class ChangeTreeViewItem : TreeViewItem
{
internal IncomingChangeInfo ChangeInfo { get; private set; }
internal ChangeTreeViewItem(int id, IncomingChangeInfo change)
: base(id, 1)
{
ChangeInfo = change;
displayName = change.GetPathString();
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,19 @@
using UnityEditor.IMGUI.Controls;
using Codice.Client.BaseCommands;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon.Errors
{
internal class ErrorListViewItem : TreeViewItem
{
internal ErrorMessage ErrorMessage { get; private set; }
internal ErrorListViewItem(int id, ErrorMessage errorMessage)
: base(id, 0)
{
ErrorMessage = errorMessage;
displayName = errorMessage.Path;
}
}
}

View file

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

View file

@ -0,0 +1,93 @@
using System;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon.Errors
{
internal enum ErrorsListColumn
{
Path,
Reason
}
[Serializable]
internal class ErrorsListHeaderState : MultiColumnHeaderState, ISerializationCallbackReceiver
{
internal static ErrorsListHeaderState GetDefault()
{
return new ErrorsListHeaderState(BuildColumns());
}
static string GetColumnName(ErrorsListColumn column)
{
switch (column)
{
case ErrorsListColumn.Path:
return PlasticLocalization.GetString(PlasticLocalization.Name.PathColumn);
case ErrorsListColumn.Reason:
return PlasticLocalization.GetString(PlasticLocalization.Name.Reason);
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 = 300,
headerContent = new GUIContent(
GetColumnName(ErrorsListColumn.Path)),
minWidth = 200,
allowToggleVisibility = false,
canSort = false,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 600,
headerContent = new GUIContent(
GetColumnName(ErrorsListColumn.Reason)),
minWidth = 200,
canSort = false,
sortingArrowAlignment = TextAlignment.Right
}
};
}
ErrorsListHeaderState(Column[] columns)
: base(columns)
{
if (mHeaderTitles == null)
mHeaderTitles = TreeHeaderColumns.GetTitles(columns);
if (mColumsAllowedToggleVisibility == null)
mColumsAllowedToggleVisibility = TreeHeaderColumns.GetVisibilities(columns);
}
[SerializeField]
string[] mHeaderTitles;
[SerializeField]
bool[] mColumsAllowedToggleVisibility;
}
}

View file

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

View file

@ -0,0 +1,179 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.IMGUI.Controls;
using Codice.Client.BaseCommands;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon.Errors
{
internal class ErrorsListView : TreeView
{
internal ErrorsListView(ErrorsListHeaderState headerState)
: base(new TreeViewState())
{
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.canSort = false;
rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
showAlternatingRowBackgrounds = true;
}
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, mErrorMessages, rootItem, mRows);
return mRows;
}
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 ErrorListViewItem)
{
ErrorListViewItemGUI((ErrorListViewItem)args.item, args);
return;
}
base.RowGUI(args);
}
internal void BuildModel(List<ErrorMessage> errorMessages)
{
mErrorMessages = errorMessages;
}
internal ErrorMessage GetSelectedError()
{
List<ErrorMessage> selectedErrors = GetSelectedErrors(this);
if (selectedErrors.Count != 1)
return null;
return selectedErrors[0];
}
static List<ErrorMessage> GetSelectedErrors(
ErrorsListView listView)
{
List<ErrorMessage> result = new List<ErrorMessage>();
IList<int> selectedIds = listView.GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (ErrorListViewItem treeViewItem in
listView.FindRows(selectedIds))
{
result.Add(treeViewItem.ErrorMessage);
}
return result;
}
static void RegenerateRows(
ErrorsListView listView,
List<ErrorMessage> errorMessages,
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
ClearRows(rootItem, rows);
if (errorMessages.Count == 0)
return;
for (int i = 0; i < errorMessages.Count; i++)
{
ErrorListViewItem errorListViewItem =
new ErrorListViewItem(i + 1, errorMessages[i]);
rootItem.AddChild(errorListViewItem);
rows.Add(errorListViewItem);
}
listView.SetSelection(new List<int> { 1 });
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static void ErrorListViewItemGUI(
ErrorListViewItem item,
RowGUIArgs args)
{
for (int visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++)
{
Rect cellRect = args.GetCellRect(visibleColumnIdx);
ErrorsListColumn column =
(ErrorsListColumn)args.GetColumn(visibleColumnIdx);
ErrorListViewItemCellGUI(
cellRect, item, column, args.selected, args.focused);
}
}
static void ErrorListViewItemCellGUI(
Rect rect,
ErrorListViewItem item,
ErrorsListColumn column,
bool isSelected,
bool isFocused)
{
ErrorMessage errorMessage = item.ErrorMessage;
string label = column == ErrorsListColumn.Path ?
errorMessage.Path : errorMessage.Error;
if (column == ErrorsListColumn.Path)
{
DrawTreeViewItem.ForLabel(
rect, label, isSelected, isFocused, false);
return;
}
DrawTreeViewItem.ForSecondaryLabel(
rect, label, isSelected, isFocused, false);
}
List<TreeViewItem> mRows = new List<TreeViewItem>();
List<ErrorMessage> mErrorMessages = new List<ErrorMessage>();
}
}

View file

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

View file

@ -0,0 +1,33 @@
using System.Collections.Generic;
using PlasticGui.Gluon.WorkspaceWindow.Views.IncomingChanges;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon
{
internal static class IncomingChangesSelection
{
internal static SelectedIncomingChangesGroupInfo GetSelectedGroupInfo(
IncomingChangesTreeView treeView)
{
List<IncomingChangeInfo> selectedIncomingChanges =
treeView.GetSelectedIncomingChanges();
return GetSelectedIncomingChangesGroupInfo.For(
selectedIncomingChanges);
}
internal static List<IncomingChangeInfo> GetSelectedFileConflictsIncludingMeta(
IncomingChangesTreeView treeView)
{
List<IncomingChangeInfo> result = treeView.GetSelectedFileConflicts();
treeView.FillWithMeta(result);
return result;
}
internal static IncomingChangeInfo GetSingleSelectedIncomingChange(
IncomingChangesTreeView treeView)
{
return treeView.GetSelectedIncomingChange();
}
}
}

View file

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

View file

@ -0,0 +1,797 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Codice.Client.BaseCommands;
using Codice.Client.BaseCommands.EventTracking;
using Codice.Client.Commands;
using Codice.Client.Common.FsNodeReaders;
using Codice.CM.Common;
using GluonGui;
using PlasticGui;
using PlasticGui.Gluon.WorkspaceWindow;
using PlasticGui.Gluon.WorkspaceWindow.Views.IncomingChanges;
using PlasticGui.WorkspaceWindow.Diff;
using PlasticGui.WorkspaceWindow.Merge;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.Tool;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.UI.StatusBar;
using Unity.PlasticSCM.Editor.UI.Tree;
using Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon.Errors;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon
{
internal class IncomingChangesTab :
IIncomingChangesTab,
IRefreshableView,
IncomingChangesViewLogic.IIncomingChangesView,
IIncomingChangesViewMenuOperations,
IncomingChangesViewMenu.IMetaMenuOperations
{
internal IncomingChangesTab(
WorkspaceInfo wkInfo,
ViewHost viewHost,
WorkspaceWindow workspaceWindow,
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
NewIncomingChangesUpdater newIncomingChangesUpdater,
CheckIncomingChanges.IUpdateIncomingChanges updateIncomingChanges,
StatusBar statusBar,
EditorWindow parentWindow)
{
mWkInfo = wkInfo;
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mNewIncomingChangesUpdater = newIncomingChangesUpdater;
mParentWindow = parentWindow;
mStatusBar = statusBar;
BuildComponents();
mProgressControls = new ProgressControlsForViews();
mCooldownClearUpdateSuccessAction = new CooldownWindowDelayer(
DelayedClearUpdateSuccess,
UnityConstants.NOTIFICATION_CLEAR_INTERVAL);
mErrorsSplitterState = PlasticSplitterGUILayout.InitSplitterState(
new float[] { 0.75f, 0.25f },
new int[] { 100, 100 },
new int[] { 100000, 100000 }
);
mErrorDetailsSplitterState = PlasticSplitterGUILayout.InitSplitterState(
new float[] { 0.60f, 0.40f },
new int[] { 100, 100 },
new int[] { 100000, 100000 }
);
mIncomingChangesViewLogic = new IncomingChangesViewLogic(
wkInfo, viewHost, this, new UnityPlasticGuiMessage(),
mProgressControls, updateIncomingChanges,
workspaceWindow.GluonProgressOperationHandler, workspaceWindow,
new IncomingChangesViewLogic.ApplyWorkspaceLocalChanges(),
new IncomingChangesViewLogic.OutOfDateItemsOperations(null),
new IncomingChangesViewLogic.GetWorkingBranch(),
new IncomingChangesViewLogic.ResolveUserName(),
new ResolveChangeset(),
NewChangesInWk.Build(wkInfo, new BuildWorkspacekIsRelevantNewChange()),
null);
mIncomingChangesViewLogic.Refresh();
}
bool IIncomingChangesTab.IsVisible
{
get { return mIsVisible; }
set { mIsVisible = value; }
}
void IIncomingChangesTab.OnDisable()
{
TreeHeaderSettings.Save(
mIncomingChangesTreeView.multiColumnHeader.state,
UnityConstants.GLUON_INCOMING_CHANGES_TABLE_SETTINGS_NAME);
TreeHeaderSettings.Save(
mErrorsListView.multiColumnHeader.state,
UnityConstants.GLUON_INCOMING_ERRORS_TABLE_SETTINGS_NAME);
}
void IIncomingChangesTab.Update()
{
mProgressControls.UpdateProgress(mParentWindow);
}
void IIncomingChangesTab.OnGUI()
{
bool splitterNeeded = mIsErrorsListVisible;
if (splitterNeeded)
PlasticSplitterGUILayout.BeginVerticalSplit(mErrorsSplitterState);
DoIncomingChangesArea(
mIncomingChangesTreeView,
mProgressControls.IsOperationRunning(),
mHasNothingToDownload,
mIsUpdateSuccessful);
DoErrorsArea(
mErrorsListView,
mErrorDetailsSplitterState,
mIsErrorsListVisible);
if (splitterNeeded)
PlasticSplitterGUILayout.EndVerticalSplit();
DrawActionToolbar.Begin(mParentWindow);
if (!mProgressControls.IsOperationRunning())
{
DoActionToolbarMessage(
mIsMessageLabelVisible,
mMessageLabelText,
mHasNothingToDownload,
mIsErrorMessageLabelVisible,
mErrorMessageLabelText,
mFileConflictCount,
mChangesSummary);
if (mIsProcessMergesButtonVisible)
{
DoProcessMergesButton(
mIsProcessMergesButtonEnabled,
mProcessMergesButtonText,
mIncomingChangesViewLogic,
mIncomingChangesTreeView,
RefreshAsset.BeforeLongAssetOperation,
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation));
}
if (mIsCancelMergesButtonVisible)
{
mIsCancelMergesButtonEnabled = DoCancelMergesButton(
mIsCancelMergesButtonEnabled,
mIncomingChangesViewLogic);
}
}
else
{
DrawProgressForViews.ForIndeterminateProgress(
mProgressControls.ProgressData);
}
DrawActionToolbar.End();
if (mProgressControls.HasNotification())
{
DrawProgressForViews.ForNotificationArea(
mProgressControls.ProgressData);
}
}
void IIncomingChangesTab.AutoRefresh()
{
mIncomingChangesViewLogic.AutoRefresh(DateTime.Now);
}
void IRefreshableView.Refresh()
{
if (mNewIncomingChangesUpdater != null)
mNewIncomingChangesUpdater.Update(DateTime.Now);
mIncomingChangesViewLogic.Refresh();
}
void IncomingChangesViewLogic.IIncomingChangesView.UpdateData(
IncomingChangesTree tree,
List<ErrorMessage> errorMessages,
string processMergesButtonText,
PendingConflictsLabelData conflictsLabelData,
string changesToApplySummaryText)
{
ShowProcessMergesButton(processMergesButtonText);
((IncomingChangesViewLogic.IIncomingChangesView)this).
UpdatePendingConflictsLabel(conflictsLabelData);
UpdateIncomingChangesTree(mIncomingChangesTreeView, tree);
UpdateErrorsList(mErrorsListView, errorMessages);
mIsErrorsListVisible = errorMessages.Count > 0;
UpdateOverview(tree, conflictsLabelData);
}
void IncomingChangesViewLogic.IIncomingChangesView.UpdatePendingConflictsLabel(
PendingConflictsLabelData data)
{
}
void IncomingChangesViewLogic.IIncomingChangesView.UpdateSolvedFileConflicts(
List<IncomingChangeInfo> solvedConflicts,
IncomingChangeInfo currentConflict)
{
mIncomingChangesTreeView.UpdateSolvedFileConflicts(
solvedConflicts, currentConflict);
}
void IncomingChangesViewLogic.IIncomingChangesView.ShowMessage(
string message, bool isErrorMessage)
{
if (isErrorMessage)
{
mErrorMessageLabelText = message;
mIsErrorMessageLabelVisible = true;
return;
}
mMessageLabelText = message;
mIsMessageLabelVisible = true;
mHasNothingToDownload = message == PlasticLocalization.GetString(
PlasticLocalization.Name.MergeNothingToDownloadForIncomingView);
}
void IncomingChangesViewLogic.IIncomingChangesView.HideMessage()
{
mMessageLabelText = string.Empty;
mIsMessageLabelVisible = false;
mHasNothingToDownload = false;
mErrorMessageLabelText = string.Empty;
mIsErrorMessageLabelVisible = false;
}
void IncomingChangesViewLogic.IIncomingChangesView.DisableProcessMergesButton()
{
mIsProcessMergesButtonEnabled = false;
}
void IncomingChangesViewLogic.IIncomingChangesView.ShowCancelButton()
{
mIsCancelMergesButtonEnabled = true;
mIsCancelMergesButtonVisible = true;
}
void IncomingChangesViewLogic.IIncomingChangesView.HideCancelButton()
{
mIsCancelMergesButtonEnabled = false;
mIsCancelMergesButtonVisible = false;
}
SelectedIncomingChangesGroupInfo IIncomingChangesViewMenuOperations.GetSelectedIncomingChangesGroupInfo()
{
return IncomingChangesSelection.GetSelectedGroupInfo(mIncomingChangesTreeView);
}
void IIncomingChangesViewMenuOperations.MergeContributors()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
true,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromMergeSelectedFiles,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromMergeSelectedFiles,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromMergeSelectedFiles))
return;
List<IncomingChangeInfo> fileConflicts = IncomingChangesSelection.
GetSelectedFileConflictsIncludingMeta(mIncomingChangesTreeView);
mIncomingChangesViewLogic.ProcessMergesForConflicts(
MergeContributorType.MergeContributors,
fileConflicts,
RefreshAsset.BeforeLongAssetOperation,
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation));
}
void IIncomingChangesViewMenuOperations.MergeKeepingSourceChanges()
{
List<IncomingChangeInfo> fileConflicts = IncomingChangesSelection.
GetSelectedFileConflictsIncludingMeta(mIncomingChangesTreeView);
mIncomingChangesViewLogic.ProcessMergesForConflicts(
MergeContributorType.KeepSource,
fileConflicts,
RefreshAsset.BeforeLongAssetOperation,
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation));
}
void IIncomingChangesViewMenuOperations.MergeKeepingWorkspaceChanges()
{
List<IncomingChangeInfo> fileConflicts = IncomingChangesSelection.
GetSelectedFileConflictsIncludingMeta(mIncomingChangesTreeView);
mIncomingChangesViewLogic.ProcessMergesForConflicts(
MergeContributorType.KeepDestination,
fileConflicts,
RefreshAsset.BeforeLongAssetOperation,
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation));
}
void IIncomingChangesViewMenuOperations.DiffIncomingChanges()
{
IncomingChangeInfo incomingChange = IncomingChangesSelection.
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
if (incomingChange == null)
return;
DiffIncomingChanges(
mShowDownloadPlasticExeWindow,
incomingChange,
mWkInfo);
}
void IIncomingChangesViewMenuOperations.DiffYoursWithIncoming()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
true,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffYoursWithIncoming,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffYoursWithIncoming,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffYoursWithIncoming))
return;
IncomingChangeInfo incomingChange = IncomingChangesSelection.
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
if (incomingChange == null)
return;
DiffYoursWithIncoming(
mShowDownloadPlasticExeWindow,
incomingChange,
mWkInfo);
}
void IncomingChangesViewMenu.IMetaMenuOperations.DiffIncomingChanges()
{
IncomingChangeInfo incomingChange = IncomingChangesSelection.
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
if (incomingChange == null)
return;
DiffIncomingChanges(
mShowDownloadPlasticExeWindow,
mIncomingChangesTreeView.GetMetaChange(incomingChange),
mWkInfo);
}
void IncomingChangesViewMenu.IMetaMenuOperations.DiffYoursWithIncoming()
{
if (mShowDownloadPlasticExeWindow.Show(
mWkInfo,
true,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffYoursWithIncoming,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffYoursWithIncoming,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffYoursWithIncoming))
return;
IncomingChangeInfo incomingChange = IncomingChangesSelection.
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
if (incomingChange == null)
return;
DiffYoursWithIncoming(
mShowDownloadPlasticExeWindow,
mIncomingChangesTreeView.GetMetaChange(incomingChange),
mWkInfo);
}
bool IncomingChangesViewMenu.IMetaMenuOperations.SelectionHasMeta()
{
return mIncomingChangesTreeView.SelectionHasMeta();
}
static void DiffIncomingChanges(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
IncomingChangeInfo incomingChange,
WorkspaceInfo wkInfo)
{
if (showDownloadPlasticExeWindow.Show(
wkInfo,
true,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffIncomingChanges,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffIncomingChanges,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffIncomingChanges))
return;
DiffOperation.DiffRevisions(
wkInfo,
incomingChange.GetMount().RepSpec,
incomingChange.GetBaseRevision(),
incomingChange.GetRevision(),
incomingChange.GetPath(),
incomingChange.GetPath(),
true,
xDiffLauncher: null,
imageDiffLauncher: null);
}
static void DiffYoursWithIncoming(
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
IncomingChangeInfo incomingChange,
WorkspaceInfo wkInfo)
{
if (showDownloadPlasticExeWindow.Show(
wkInfo,
true,
TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffYoursWithIncoming,
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffYoursWithIncoming,
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffYoursWithIncoming))
return;
DiffOperation.DiffYoursWithIncoming(
wkInfo,
incomingChange.GetMount(),
incomingChange.GetRevision(),
incomingChange.GetPath(),
xDiffLauncher: null,
imageDiffLauncher: null);
}
static void UpdateErrorsList(
ErrorsListView errorsListView,
List<ErrorMessage> errorMessages)
{
errorsListView.BuildModel(errorMessages);
errorsListView.Reload();
}
void UpdateProcessMergesButtonText()
{
mProcessMergesButtonText =
mIncomingChangesViewLogic.GetProcessMergesButtonText();
}
void ShowProcessMergesButton(string processMergesButtonText)
{
mProcessMergesButtonText = processMergesButtonText;
mIsProcessMergesButtonEnabled = true;
mIsProcessMergesButtonVisible = true;
}
static void DoActionToolbarMessage(
bool isMessageLabelVisible,
string messageLabelText,
bool hasNothingToDownload,
bool isErrorMessageLabelVisible,
string errorMessageLabelText,
int fileConflictCount,
MergeViewTexts.ChangesToApplySummary changesSummary)
{
if (isMessageLabelVisible)
{
string message = messageLabelText;
if (hasNothingToDownload)
{
message = PlasticLocalization.GetString(
PlasticLocalization.Name.WorkspaceIsUpToDate);
}
DoInfoMessage(message);
}
if (isErrorMessageLabelVisible)
{
DoErrorMessage(errorMessageLabelText);
}
if (!isMessageLabelVisible && !isErrorMessageLabelVisible)
{
DrawIncomingChangesOverview.For(
0,
fileConflictCount,
changesSummary);
}
}
static void DoInfoMessage(string message)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Label(message, UnityStyles.IncomingChangesTab.ChangesToApplySummaryLabel);
EditorGUILayout.EndHorizontal();
}
static void DoErrorMessage(string message)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Label(message, UnityStyles.IncomingChangesTab.RedPendingConflictsOfTotalLabel);
EditorGUILayout.EndHorizontal();
}
static void DoIncomingChangesArea(
IncomingChangesTreeView incomingChangesTreeView,
bool isOperationRunning,
bool hasNothingToDownload,
bool isUpdateSuccessful)
{
EditorGUILayout.BeginVertical();
DoIncomingChangesTreeViewArea(
incomingChangesTreeView,
isOperationRunning,
hasNothingToDownload,
isUpdateSuccessful);
EditorGUILayout.EndVertical();
}
static void DoProcessMergesButton(
bool isEnabled,
string processMergesButtonText,
IncomingChangesViewLogic incomingChangesViewLogic,
IncomingChangesTreeView incomingChangesTreeView,
Action beforeProcessMergesAction,
Action afterProcessMergesAction)
{
GUI.enabled = isEnabled;
if (DrawActionButton.For(processMergesButtonText))
{
List<IncomingChangeInfo> incomingChanges =
incomingChangesViewLogic.GetCheckedChanges();
incomingChangesTreeView.FillWithMeta(incomingChanges);
if (incomingChanges.Count == 0)
return;
incomingChangesViewLogic.ProcessMergesForItems(
incomingChanges,
beforeProcessMergesAction,
afterProcessMergesAction);
}
GUI.enabled = true;
}
static bool DoCancelMergesButton(
bool isEnabled,
IncomingChangesViewLogic incomingChangesViewLogic)
{
bool shouldCancelMergesButtonEnabled = true;
GUI.enabled = isEnabled;
if (DrawActionButton.For(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
{
incomingChangesViewLogic.Cancel();
shouldCancelMergesButtonEnabled = false;
}
GUI.enabled = true;
return shouldCancelMergesButtonEnabled;
}
void DoErrorsArea(
ErrorsListView errorsListView,
object splitterState,
bool isErrorsListVisible)
{
EditorGUILayout.BeginVertical();
if (isErrorsListVisible)
{
DrawSplitter.ForHorizontalIndicator();
DoErrorsListArea(errorsListView, splitterState);
}
EditorGUILayout.EndVertical();
}
static void UpdateIncomingChangesTree(
IncomingChangesTreeView incomingChangesTreeView,
IncomingChangesTree tree)
{
incomingChangesTreeView.BuildModel(
UnityIncomingChangesTree.BuildIncomingChangeCategories(tree));
incomingChangesTreeView.Sort();
incomingChangesTreeView.Reload();
}
static void DoIncomingChangesTreeViewArea(
IncomingChangesTreeView incomingChangesTreeView,
bool isOperationRunning,
bool hasNothingToDownload,
bool isUpdateSuccessful)
{
GUI.enabled = !isOperationRunning;
Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
incomingChangesTreeView.OnGUI(rect);
if (hasNothingToDownload)
DrawEmptyState(rect, isUpdateSuccessful);
GUI.enabled = true;
}
static void DrawEmptyState(
Rect rect,
bool isUpdateSuccessful)
{
if (isUpdateSuccessful)
{
DrawTreeViewEmptyState.For(
rect,
PlasticLocalization.GetString(PlasticLocalization.Name.WorkspaceUpdateCompleted),
Images.GetStepOkIcon());
return;
}
DrawTreeViewEmptyState.For(
rect,
PlasticLocalization.GetString(PlasticLocalization.Name.NoIncomingChanges));
}
void DoErrorsListArea(
ErrorsListView errorsListView,
object splitterState)
{
EditorGUILayout.BeginVertical();
GUILayout.Label(
PlasticLocalization.GetString(
PlasticLocalization.Name.IncomingChangesCannotBeApplied),
EditorStyles.boldLabel);
DoErrorsListSplitViewArea(
errorsListView, splitterState);
EditorGUILayout.EndVertical();
}
void DoErrorsListSplitViewArea(
ErrorsListView errorsListView,
object splitterState)
{
EditorGUILayout.BeginHorizontal();
PlasticSplitterGUILayout.BeginHorizontalSplit(splitterState);
DoErrorsListViewArea(errorsListView);
DoErrorDetailsTextArea(errorsListView.GetSelectedError());
PlasticSplitterGUILayout.EndHorizontalSplit();
EditorGUILayout.EndHorizontal();
}
static void DoErrorsListViewArea(
ErrorsListView errorsListView)
{
Rect treeRect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
errorsListView.OnGUI(treeRect);
}
void DoErrorDetailsTextArea(ErrorMessage selectedErrorMessage)
{
string errorDetailsText = selectedErrorMessage == null ?
string.Empty : selectedErrorMessage.Error;
mErrorDetailsScrollPosition = GUILayout.BeginScrollView(
mErrorDetailsScrollPosition);
GUILayout.TextArea(
errorDetailsText, UnityStyles.TextFieldWithWrapping,
GUILayout.ExpandHeight(true));
GUILayout.EndScrollView();
}
void AfterProcessMerges(Action afterAssetLongOperation)
{
afterAssetLongOperation();
bool isTreeViewEmpty = mIncomingChangesTreeView.GetCheckedItemCount() ==
mIncomingChangesTreeView.GetTotalItemCount();
if (isTreeViewEmpty)
{
mIsUpdateSuccessful = true;
mCooldownClearUpdateSuccessAction.Ping();
return;
}
mStatusBar.Notify(
PlasticLocalization.GetString(PlasticLocalization.Name.WorkspaceUpdateCompleted),
MessageType.None,
Images.GetStepOkIcon());
}
void UpdateOverview(
IncomingChangesTree incomingChangesTree,
PendingConflictsLabelData conflictsLabelData)
{
mChangesSummary = BuildFilesSummaryData.
GetChangesToApplySummary(incomingChangesTree);
mFileConflictCount = conflictsLabelData.PendingConflictsCount;
}
void DelayedClearUpdateSuccess()
{
mIsUpdateSuccessful = false;
}
void BuildComponents()
{
IncomingChangesTreeHeaderState incomingChangesHeaderState =
IncomingChangesTreeHeaderState.GetDefault();
TreeHeaderSettings.Load(incomingChangesHeaderState,
UnityConstants.GLUON_INCOMING_CHANGES_TABLE_SETTINGS_NAME,
(int)IncomingChangesTreeColumn.Path, true);
mIncomingChangesTreeView = new IncomingChangesTreeView(
mWkInfo, incomingChangesHeaderState,
IncomingChangesTreeHeaderState.GetColumnNames(),
new IncomingChangesViewMenu(mWkInfo, this, this),
UpdateProcessMergesButtonText);
mIncomingChangesTreeView.Reload();
ErrorsListHeaderState errorsListHeaderState =
ErrorsListHeaderState.GetDefault();
TreeHeaderSettings.Load(errorsListHeaderState,
UnityConstants.GLUON_INCOMING_ERRORS_TABLE_SETTINGS_NAME,
UnityConstants.UNSORT_COLUMN_ID);
mErrorsListView = new ErrorsListView(errorsListHeaderState);
mErrorsListView.Reload();
}
bool mIsVisible;
bool mIsProcessMergesButtonVisible;
bool mIsCancelMergesButtonVisible;
bool mIsMessageLabelVisible;
bool mIsErrorMessageLabelVisible;
bool mIsErrorsListVisible;
bool mIsProcessMergesButtonEnabled;
bool mIsCancelMergesButtonEnabled;
string mProcessMergesButtonText;
string mMessageLabelText;
string mErrorMessageLabelText;
bool mHasNothingToDownload;
bool mIsUpdateSuccessful;
IncomingChangesTreeView mIncomingChangesTreeView;
ErrorsListView mErrorsListView;
int mFileConflictCount;
MergeViewTexts.ChangesToApplySummary mChangesSummary;
object mErrorsSplitterState;
object mErrorDetailsSplitterState;
readonly ProgressControlsForViews mProgressControls;
readonly CooldownWindowDelayer mCooldownClearUpdateSuccessAction;
Vector2 mErrorDetailsScrollPosition;
readonly IncomingChangesViewLogic mIncomingChangesViewLogic;
readonly EditorWindow mParentWindow;
readonly StatusBar mStatusBar;
readonly NewIncomingChangesUpdater mNewIncomingChangesUpdater;
readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
readonly WorkspaceInfo mWkInfo;
}
}

View file

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

View file

@ -0,0 +1,136 @@
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.IncomingChanges.Gluon
{
internal enum IncomingChangesTreeColumn
{
Path,
LastEditedBy,
Size,
DateModififed,
Comment
}
[Serializable]
internal class IncomingChangesTreeHeaderState : MultiColumnHeaderState, ISerializationCallbackReceiver
{
internal static IncomingChangesTreeHeaderState GetDefault()
{
return new IncomingChangesTreeHeaderState(BuildColumns());
}
internal static List<string> GetColumnNames()
{
List<string> result = new List<string>();
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.PathColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.LastEditedByColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.SizeColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.DateModifiedColumn));
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CommentColumn));
return result;
}
internal static string GetColumnName(IncomingChangesTreeColumn column)
{
switch (column)
{
case IncomingChangesTreeColumn.Path:
return PlasticLocalization.GetString(PlasticLocalization.Name.PathColumn);
case IncomingChangesTreeColumn.LastEditedBy:
return PlasticLocalization.GetString(PlasticLocalization.Name.LastEditedByColumn);
case IncomingChangesTreeColumn.Size:
return PlasticLocalization.GetString(PlasticLocalization.Name.SizeColumn);
case IncomingChangesTreeColumn.DateModififed:
return PlasticLocalization.GetString(PlasticLocalization.Name.DateModifiedColumn);
case IncomingChangesTreeColumn.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 = 440,
headerContent = new GUIContent(
GetColumnName(IncomingChangesTreeColumn.Path)),
minWidth = 200,
allowToggleVisibility = false,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 150,
headerContent = new GUIContent(
GetColumnName(IncomingChangesTreeColumn.LastEditedBy)),
minWidth = 80,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 80,
headerContent = new GUIContent(
GetColumnName(IncomingChangesTreeColumn.Size)),
minWidth = 45,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 260,
headerContent = new GUIContent(
GetColumnName(IncomingChangesTreeColumn.DateModififed)),
minWidth = 100,
sortingArrowAlignment = TextAlignment.Right
},
new Column()
{
width = 400,
headerContent = new GUIContent(
GetColumnName(IncomingChangesTreeColumn.Comment)),
minWidth = 100,
sortingArrowAlignment = TextAlignment.Right
}
};
}
IncomingChangesTreeHeaderState(Column[] columns)
: base(columns)
{
if (mHeaderTitles == null)
mHeaderTitles = TreeHeaderColumns.GetTitles(columns);
if (mColumsAllowedToggleVisibility == null)
mColumsAllowedToggleVisibility = TreeHeaderColumns.GetVisibilities(columns);
}
[SerializeField]
string[] mHeaderTitles;
[SerializeField]
bool[] mColumsAllowedToggleVisibility;
}
}

View file

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

View file

@ -0,0 +1,638 @@
using System;
using System.IO;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.CM.Common;
using Codice.Client.Common;
using PlasticGui;
using PlasticGui.Gluon.WorkspaceWindow.Views.IncomingChanges;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon
{
internal class IncomingChangesTreeView : TreeView
{
internal IncomingChangesTreeView(
WorkspaceInfo wkInfo,
IncomingChangesTreeHeaderState headerState,
List<string> columnNames,
IncomingChangesViewMenu menu,
Action onCheckedNodeChanged)
: base(new TreeViewState())
{
mWkInfo = wkInfo;
mColumnNames = columnNames;
mMenu = menu;
mOnCheckedNodeChanged = onCheckedNodeChanged;
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.canSort = true;
multiColumnHeader.sortingChanged += SortingChanged;
customFoldoutYOffset = UnityConstants.TREEVIEW_FOLDOUT_Y_OFFSET;
rowHeight = UnityConstants.TREEVIEW_ROW_HEIGHT;
showAlternatingRowBackgrounds = false;
}
public override IList<TreeViewItem> GetRows()
{
return mRows;
}
protected override bool CanChangeExpandedState(TreeViewItem item)
{
return item is ChangeCategoryTreeViewItem;
}
protected override TreeViewItem BuildRoot()
{
return new TreeViewItem(0, -1, string.Empty);
}
protected override IList<TreeViewItem> BuildRows(TreeViewItem rootItem)
{
try
{
RegenerateRows(
mIncomingChangesTree, 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 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 ChangeCategoryTreeViewItem)
{
CategoryTreeViewItemGUI(
args.rowRect, rowHeight,
(ChangeCategoryTreeViewItem)args.item,
mOnCheckedNodeChanged,
mSolvedConflicts.Count,
args.selected, args.focused);
return;
}
if (args.item is ChangeTreeViewItem)
{
ChangeTreeViewItem changeTreeViewItem =
(ChangeTreeViewItem)args.item;
IncomingChangeInfo changeInfo = changeTreeViewItem.ChangeInfo;
IncomingChangeInfo metaChangeInfo = mIncomingChangesTree.GetMetaChange(
changeInfo);
bool isCurrentConflict = IsCurrentConflict(
changeInfo,
metaChangeInfo,
mCurrentConflict);
bool isSolvedConflict = IsSolvedConflict(
changeInfo,
metaChangeInfo,
mSolvedConflicts);
IncomingChangeTreeViewItemGUI(
mWkInfo.ClientPath,
mIncomingChangesTree,
this,
changeTreeViewItem,
mOnCheckedNodeChanged, args,
isCurrentConflict,
isSolvedConflict);
return;
}
base.RowGUI(args);
}
internal void BuildModel(UnityIncomingChangesTree tree)
{
mTreeViewItemIds.Clear();
mIncomingChangesTree = tree;
mSolvedConflicts = new List<IncomingChangeInfo>();
mCurrentConflict = null;
mExpandCategories = true;
}
internal void UpdateSolvedFileConflicts(
List<IncomingChangeInfo> solvedConflicts,
IncomingChangeInfo currentConflict)
{
mSolvedConflicts = solvedConflicts;
mCurrentConflict = currentConflict;
}
internal void Sort()
{
int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
mIncomingChangesTree.Sort(
mColumnNames[sortedColumnIdx],
sortAscending);
}
internal IncomingChangeInfo GetMetaChange(IncomingChangeInfo change)
{
if (change == null)
return null;
return mIncomingChangesTree.GetMetaChange(change);
}
internal void FillWithMeta(List<IncomingChangeInfo> changes)
{
mIncomingChangesTree.FillWithMeta(changes);
}
internal bool SelectionHasMeta()
{
IncomingChangeInfo selectedChangeInfo = GetSelectedIncomingChange();
if (selectedChangeInfo == null)
return false;
return mIncomingChangesTree.HasMeta(selectedChangeInfo);
}
internal IncomingChangeInfo GetSelectedIncomingChange()
{
IList<int> selectedIds = GetSelection();
if (selectedIds.Count != 1)
return null;
int selectedId = selectedIds[0];
foreach (KeyValuePair<IncomingChangeInfo, int> item
in mTreeViewItemIds.GetInfoItems())
{
if (selectedId == item.Value)
return item.Key;
}
return null;
}
internal List<IncomingChangeInfo> GetSelectedIncomingChanges()
{
List<IncomingChangeInfo> result = new List<IncomingChangeInfo>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<IncomingChangeInfo, int> item
in mTreeViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
result.Add(item.Key);
}
return result;
}
internal List<IncomingChangeInfo> GetSelectedFileConflicts()
{
List<IncomingChangeInfo> result = new List<IncomingChangeInfo>();
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 0)
return result;
foreach (KeyValuePair<IncomingChangeInfo, int> item
in mTreeViewItemIds.GetInfoItems())
{
if (!selectedIds.Contains(item.Value))
continue;
if (item.Key.CategoryType != IncomingChangeCategory.Type.Conflicted)
continue;
result.Add(item.Key);
}
return result;
}
internal int GetCheckedItemCount()
{
List<IncomingChangeCategory> categories = mIncomingChangesTree.GetNodes();
if (categories == null)
return 0;
int checkedCount = 0;
foreach (IncomingChangeCategory category in categories)
{
checkedCount += ((ICheckablePlasticTreeCategory)category).GetCheckedChangesCount();
}
return checkedCount;
}
internal int GetTotalItemCount()
{
List<IncomingChangeCategory> categories = mIncomingChangesTree.GetNodes();
if (categories == null)
return 0;
int totalCount = 0;
foreach (IncomingChangeCategory category in categories)
{
totalCount += category.GetChildrenCount();
}
return totalCount;
}
void SortingChanged(MultiColumnHeader multiColumnHeader)
{
Sort();
Reload();
}
static bool IsCurrentConflict(
IncomingChangeInfo changeInfo,
IncomingChangeInfo metaChangeInfo,
IncomingChangeInfo currentConflict)
{
if (metaChangeInfo == null)
return currentConflict == changeInfo;
return currentConflict == changeInfo ||
currentConflict == metaChangeInfo;
}
static bool IsSolvedConflict(
IncomingChangeInfo changeInfo,
IncomingChangeInfo metaChangeInfo,
List<IncomingChangeInfo> solvedConflicts)
{
if (metaChangeInfo == null)
return solvedConflicts.Contains(changeInfo);
return solvedConflicts.Contains(changeInfo) &&
solvedConflicts.Contains(metaChangeInfo);
}
static void RegenerateRows(
UnityIncomingChangesTree incomingChangesTree,
TreeViewItemIds<IncomingChangeCategory, IncomingChangeInfo> treeViewItemIds,
IncomingChangesTreeView treeView,
TreeViewItem rootItem,
List<TreeViewItem> rows,
bool expandCategories)
{
if (incomingChangesTree == null)
return;
ClearRows(rootItem, rows);
List<IncomingChangeCategory> categories = incomingChangesTree.GetNodes();
if (categories == null)
return;
List<int> categoriesToExpand = new List<int>();
foreach (IncomingChangeCategory category in categories)
{
int categoryId;
if (!treeViewItemIds.TryGetCategoryItemId(category, out categoryId))
categoryId = treeViewItemIds.AddCategoryItem(category);
ChangeCategoryTreeViewItem categoryTreeViewItem =
new ChangeCategoryTreeViewItem(categoryId, category);
rootItem.AddChild(categoryTreeViewItem);
rows.Add(categoryTreeViewItem);
if (!ShouldExpandCategory(
treeView, categoryTreeViewItem,
categories.Count, expandCategories))
continue;
categoriesToExpand.Add(categoryTreeViewItem.id);
foreach (IncomingChangeInfo incomingChange in category.GetChanges())
{
int changeId;
if (!treeViewItemIds.TryGetInfoItemId(incomingChange, out changeId))
changeId = treeViewItemIds.AddInfoItem(incomingChange);
TreeViewItem changeTreeViewItem =
new ChangeTreeViewItem(changeId, incomingChange);
categoryTreeViewItem.AddChild(changeTreeViewItem);
rows.Add(changeTreeViewItem);
}
}
treeView.state.expandedIDs = categoriesToExpand;
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static void UpdateCheckStateForSelection(
IncomingChangesTreeView treeView,
ChangeTreeViewItem senderTreeViewItem)
{
IList<int> selectedIds = treeView.GetSelection();
if (selectedIds.Count <= 1)
return;
if (!selectedIds.Contains(senderTreeViewItem.id))
return;
bool isChecked = ((ICheckablePlasticTreeNode)senderTreeViewItem.ChangeInfo).IsChecked();
foreach (TreeViewItem treeViewItem in treeView.FindRows(selectedIds))
{
if (treeViewItem is ChangeCategoryTreeViewItem)
{
((ICheckablePlasticTreeCategory)((ChangeCategoryTreeViewItem)treeViewItem)
.Category).UpdateCheckedState(isChecked);
continue;
}
((ICheckablePlasticTreeNode)((ChangeTreeViewItem)treeViewItem)
.ChangeInfo).UpdateCheckedState(isChecked);
}
}
static void CategoryTreeViewItemGUI(
Rect rowRect,
float rowHeight,
ChangeCategoryTreeViewItem item,
Action onCheckedNodeChanged,
int solvedConflictsCount,
bool isSelected,
bool isFocused)
{
string label = item.Category.CategoryName;
string infoLabel = item.Category.GetCheckedChangesText();
bool wasChecked = item.Category.IsChecked();
bool hadCheckedChildren = ((ICheckablePlasticTreeCategory)item.Category).GetCheckedChangesCount() > 0;
DefaultStyles.label = GetCategoryStyle(
item.Category, solvedConflictsCount, isSelected);
bool isChecked = DrawTreeViewItem.ForCheckableCategoryItem(
rowRect,
rowHeight,
item.depth,
label,
infoLabel,
isSelected,
isFocused,
wasChecked,
hadCheckedChildren,
hadPartiallyCheckedChildren: false);
DefaultStyles.label = UnityStyles.Tree.Label;
if (!wasChecked && isChecked)
{
((ICheckablePlasticTreeCategory)item.Category).UpdateCheckedState(true);
onCheckedNodeChanged();
return;
}
if (wasChecked && !isChecked)
{
((ICheckablePlasticTreeNode)item.Category).UpdateCheckedState(false);
onCheckedNodeChanged();
return;
}
}
static void IncomingChangeTreeViewItemGUI(
string wkPath,
UnityIncomingChangesTree incomingChangesTree,
IncomingChangesTreeView treeView,
ChangeTreeViewItem item,
Action onCheckedNodeChanged,
RowGUIArgs args,
bool isCurrentConflict,
bool isSolvedConflict)
{
for (int visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++)
{
Rect cellRect = args.GetCellRect(visibleColumnIdx);
IncomingChangesTreeColumn column =
(IncomingChangesTreeColumn)args.GetColumn(visibleColumnIdx);
IncomingChangeTreeViewItemCellGUI(
wkPath,
cellRect,
treeView.rowHeight,
incomingChangesTree,
treeView,
item,
onCheckedNodeChanged,
column,
args.selected,
args.focused,
isCurrentConflict,
isSolvedConflict);
}
}
static void IncomingChangeTreeViewItemCellGUI(
string wkPath,
Rect rect,
float rowHeight,
UnityIncomingChangesTree incomingChangesTree,
IncomingChangesTreeView treeView,
ChangeTreeViewItem item,
Action onCheckedNodeChanged,
IncomingChangesTreeColumn column,
bool isSelected,
bool isFocused,
bool isCurrentConflict,
bool isSolvedConflict)
{
IncomingChangeInfo incomingChange = item.ChangeInfo;
string label = incomingChange.GetColumnText(
IncomingChangesTreeHeaderState.GetColumnName(column));
if (column == IncomingChangesTreeColumn.Path)
{
if (incomingChangesTree.HasMeta(item.ChangeInfo))
label = string.Concat(label, UnityConstants.TREEVIEW_META_LABEL);
Texture icon = GetIcon(wkPath, incomingChange);
Texture overlayIcon =
GetChangesOverlayIcon.ForGluonIncomingChange(
incomingChange, isSolvedConflict);
bool wasChecked = ((ICheckablePlasticTreeNode)incomingChange).IsChecked();
bool isChecked = DrawTreeViewItem.ForCheckableItemCell(
rect, rowHeight, item.depth,
icon, overlayIcon, label,
isSelected, isFocused, isCurrentConflict,
wasChecked);
((ICheckablePlasticTreeNode)incomingChange).UpdateCheckedState(isChecked);
if (wasChecked != isChecked)
{
UpdateCheckStateForSelection(treeView, item);
onCheckedNodeChanged();
}
return;
}
if (column == IncomingChangesTreeColumn.Size)
{
// If there is a meta file, add the meta file to the file size so that it is consistent
// with the Incoming Changes overview
if (incomingChangesTree.HasMeta(item.ChangeInfo))
{
IncomingChangeInfo metaFileInfo = incomingChangesTree.GetMetaChange(incomingChange);
long metaFileSize = metaFileInfo.GetSize();
long fileSize = incomingChange.GetSize();
label = SizeConverter.ConvertToSizeString(fileSize + metaFileSize);
}
DrawTreeViewItem.ForSecondaryLabelRightAligned(
rect, label, isSelected, isFocused, isCurrentConflict);
return;
}
DrawTreeViewItem.ForSecondaryLabel(
rect, label, isSelected, isFocused, isCurrentConflict);
}
static Texture GetIcon(
string wkPath,
IncomingChangeInfo incomingChange)
{
bool isDirectory = incomingChange.GetRevision().
Type == EnumRevisionType.enDirectory;
if (isDirectory || incomingChange.IsXLink())
return Images.GetDirectoryIcon();
string fullPath = WorkspacePath.GetWorkspacePathFromCmPath(
wkPath, incomingChange.GetPath(), Path.DirectorySeparatorChar);
return Images.GetFileIcon(fullPath);
}
static GUIStyle GetCategoryStyle(
IncomingChangeCategory category,
int solvedConflictsCount,
bool isSelected)
{
if (isSelected)
return UnityStyles.Tree.Label;
if (category.CategoryType != IncomingChangeCategory.Type.Conflicted)
return UnityStyles.Tree.Label;
return category.GetChildrenCount() > solvedConflictsCount ?
UnityStyles.Tree.RedLabel : UnityStyles.Tree.GreenLabel;
}
static bool ShouldExpandCategory(
IncomingChangesTreeView treeView,
ChangeCategoryTreeViewItem categoryTreeViewItem,
int categoriesCount,
bool expandCategories)
{
if (expandCategories)
{
if (categoriesCount == 1)
return true;
if (categoryTreeViewItem.Category.CategoryType
== IncomingChangeCategory.Type.Conflicted)
return true;
if (categoryTreeViewItem.Category.GetChildrenCount()
> NODES_TO_EXPAND_CATEGORY)
return false;
return true;
}
return treeView.IsExpanded(categoryTreeViewItem.id);
}
bool mExpandCategories;
TreeViewItemIds<IncomingChangeCategory, IncomingChangeInfo> mTreeViewItemIds =
new TreeViewItemIds<IncomingChangeCategory, IncomingChangeInfo>();
List<TreeViewItem> mRows = new List<TreeViewItem>();
IncomingChangeInfo mCurrentConflict;
List<IncomingChangeInfo> mSolvedConflicts;
UnityIncomingChangesTree mIncomingChangesTree;
readonly Action mOnCheckedNodeChanged;
readonly IncomingChangesViewMenu mMenu;
readonly List<string> mColumnNames;
readonly WorkspaceInfo mWkInfo;
const int NODES_TO_EXPAND_CATEGORY = 10;
}
}

View file

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

View file

@ -0,0 +1,223 @@
using UnityEngine;
using UnityEditor;
using Codice.Client.BaseCommands.EventTracking;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.Gluon.WorkspaceWindow.Views.IncomingChanges;
using Unity.PlasticSCM.Editor.Tool;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon
{
internal class IncomingChangesViewMenu
{
internal interface IMetaMenuOperations
{
void DiffIncomingChanges();
void DiffYoursWithIncoming();
bool SelectionHasMeta();
}
internal IncomingChangesViewMenu(
WorkspaceInfo wkInfo,
IIncomingChangesViewMenuOperations incomingChangesViewMenuOperations,
IMetaMenuOperations incomingChangesMetaMenuOperations)
{
mWkInfo = wkInfo;
mIncomingChangesViewMenuOperations = incomingChangesViewMenuOperations;
mIncomingChangesMetaMenuOperations = incomingChangesMetaMenuOperations;
BuildComponents();
}
internal void Popup()
{
GenericMenu menu = new GenericMenu();
UpdateMenuItems(menu);
menu.ShowAsContext();
}
void MergeSelectedFilesMenuItem_Click()
{
mIncomingChangesViewMenuOperations.MergeContributors();
}
void MergeKeepingSourceChangesMenuItem_Click()
{
mIncomingChangesViewMenuOperations.MergeKeepingSourceChanges();
}
void MergeKeepingWorkspaceChangesMenuItem_Click()
{
mIncomingChangesViewMenuOperations.MergeKeepingWorkspaceChanges();
}
void DiffYoursWithIncomingMenuItem_Click()
{
mIncomingChangesViewMenuOperations.DiffYoursWithIncoming();
}
void DiffIncomingChangesMenuItem_Click()
{
mIncomingChangesViewMenuOperations.DiffIncomingChanges();
}
void DiffMetaYoursWithIncomingMenuItem_Click()
{
mIncomingChangesMetaMenuOperations.DiffYoursWithIncoming();
}
void DiffMetaIncomingChangesMenuItem_Click()
{
mIncomingChangesMetaMenuOperations.DiffIncomingChanges();
}
void UpdateMenuItems(GenericMenu menu)
{
SelectedIncomingChangesGroupInfo info =
mIncomingChangesViewMenuOperations.GetSelectedIncomingChangesGroupInfo();
IncomingChangesMenuOperations operations =
UpdateIncomingChangesMenu.GetAvailableMenuOperations(info);
if (operations == IncomingChangesMenuOperations.None)
{
menu.AddDisabledItem(GetNoActionMenuItemContent());
return;
}
AddMergeActions(menu, operations);
menu.AddSeparator(string.Empty);
AddDiffActions(menu, operations);
if (!mIncomingChangesMetaMenuOperations.SelectionHasMeta())
return;
menu.AddSeparator(string.Empty);
AddMetaActions(menu, operations);
}
void AddMergeActions(
GenericMenu menu,
IncomingChangesMenuOperations operations)
{
if (operations.HasFlag(IncomingChangesMenuOperations.MergeContributors))
menu.AddItem(mMergeSelectedFilesMenuItemContent, false,
MergeSelectedFilesMenuItem_Click);
else
menu.AddDisabledItem(mMergeSelectedFilesMenuItemContent);
if (operations.HasFlag(IncomingChangesMenuOperations.MergeKeepingSourceChanges))
menu.AddItem(mMergeKeepingSourceChangesMenuItemContent, false,
MergeKeepingSourceChangesMenuItem_Click);
else
menu.AddDisabledItem(mMergeKeepingSourceChangesMenuItemContent);
if (operations.HasFlag(IncomingChangesMenuOperations.MergeKeepingWorkspaceChanges))
menu.AddItem(mMergeKeepingWorkspaceChangesMenuItemContent, false,
MergeKeepingWorkspaceChangesMenuItem_Click);
else
menu.AddDisabledItem(mMergeKeepingWorkspaceChangesMenuItemContent);
}
void AddDiffActions(GenericMenu menu, IncomingChangesMenuOperations operations)
{
if (operations.HasFlag(IncomingChangesMenuOperations.DiffYoursWithIncoming))
menu.AddItem(mDiffYoursWithIncomingMenuItemContent, false,
DiffYoursWithIncomingMenuItem_Click);
else
menu.AddDisabledItem(mDiffYoursWithIncomingMenuItemContent);
if (operations.HasFlag(IncomingChangesMenuOperations.DiffIncomingChanges))
menu.AddItem(mDiffIncomingChangesMenuItemContent, false,
DiffIncomingChangesMenuItem_Click);
else
menu.AddDisabledItem(mDiffIncomingChangesMenuItemContent);
}
void AddMetaActions(GenericMenu menu, IncomingChangesMenuOperations operations)
{
if (operations.HasFlag(IncomingChangesMenuOperations.DiffYoursWithIncoming))
menu.AddItem(mDiffMetaYoursWithIncomingMenuItemContent, false,
DiffMetaYoursWithIncomingMenuItem_Click);
else
menu.AddDisabledItem(mDiffMetaYoursWithIncomingMenuItemContent);
if (operations.HasFlag(IncomingChangesMenuOperations.DiffIncomingChanges))
menu.AddItem(mDiffMetaIncomingChangesMenuItemContent, false,
DiffMetaIncomingChangesMenuItem_Click);
else
menu.AddDisabledItem(mDiffMetaIncomingChangesMenuItemContent);
}
GUIContent GetNoActionMenuItemContent()
{
if (mNoActionMenuItemContent == null)
{
mNoActionMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.
Name.NoActionMenuItem));
}
return mNoActionMenuItemContent;
}
void BuildComponents()
{
mMergeSelectedFilesMenuItemContent = new GUIContent(
PlasticLocalization.GetString(PlasticLocalization.
Name.MergeSelectedFiles));
mMergeKeepingSourceChangesMenuItemContent = new GUIContent(
UnityMenuItem.EscapedText(
PlasticLocalization.GetString(PlasticLocalization.
Name.IncomingChangesMenuItemMergeKeepingSourceChanges)));
mMergeKeepingWorkspaceChangesMenuItemContent = new GUIContent(
UnityMenuItem.EscapedText(
PlasticLocalization.GetString(PlasticLocalization.
Name.IncomingChangesMenuItemMergeKeepingWorkspaceChanges)));
string diffYoursWithIncomingText = UnityMenuItem.EscapedText(
PlasticLocalization.GetString(PlasticLocalization.
Name.IncomingChangesMenuItemDiffYoursWithIncoming));
string diffIncomingChangesText = UnityMenuItem.EscapedText(
PlasticLocalization.GetString(PlasticLocalization.
Name.IncomingChangesMenuItemDiffIncomingChanges));
mDiffYoursWithIncomingMenuItemContent = new GUIContent(
diffYoursWithIncomingText);
mDiffIncomingChangesMenuItemContent = new GUIContent(
diffIncomingChangesText);
mDiffMetaYoursWithIncomingMenuItemContent = new GUIContent(
string.Format(
"{0}/{1}",
MetaPath.META_EXTENSION,
diffYoursWithIncomingText));
mDiffMetaIncomingChangesMenuItemContent = new GUIContent(
string.Format(
"{0}/{1}",
MetaPath.META_EXTENSION,
diffIncomingChangesText));
}
GUIContent mNoActionMenuItemContent;
GUIContent mMergeSelectedFilesMenuItemContent;
GUIContent mMergeKeepingSourceChangesMenuItemContent;
GUIContent mMergeKeepingWorkspaceChangesMenuItemContent;
GUIContent mDiffYoursWithIncomingMenuItemContent;
GUIContent mDiffIncomingChangesMenuItemContent;
GUIContent mDiffMetaYoursWithIncomingMenuItemContent;
GUIContent mDiffMetaIncomingChangesMenuItemContent;
readonly WorkspaceInfo mWkInfo;
readonly IIncomingChangesViewMenuOperations mIncomingChangesViewMenuOperations;
readonly IMetaMenuOperations mIncomingChangesMetaMenuOperations;
}
}

View file

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

View file

@ -0,0 +1,175 @@
using System.Collections.Generic;
using PlasticGui.Gluon.WorkspaceWindow.Views.IncomingChanges;
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon
{
internal class UnityIncomingChangesTree
{
internal static UnityIncomingChangesTree BuildIncomingChangeCategories(
IncomingChangesTree tree)
{
return new UnityIncomingChangesTree(tree);
}
UnityIncomingChangesTree(IncomingChangesTree tree)
{
mInnerTree = tree;
mMetaCache.Build(mInnerTree.GetNodes());
}
internal List<IncomingChangeCategory> GetNodes()
{
return mInnerTree.GetNodes();
}
internal bool HasMeta(IncomingChangeInfo changeInfo)
{
return mMetaCache.ContainsMeta(changeInfo);
}
internal IncomingChangeInfo GetMetaChange(IncomingChangeInfo change)
{
return mMetaCache.GetExistingMeta(change);
}
internal void FillWithMeta(List<IncomingChangeInfo> changes)
{
changes.AddRange(
mMetaCache.GetExistingMeta(changes));
}
internal void Sort(string key, bool isAscending)
{
mInnerTree.Sort(key, isAscending);
}
MetaCache mMetaCache = new MetaCache();
IncomingChangesTree mInnerTree;
class MetaCache
{
internal bool ContainsMeta(IncomingChangeInfo changeInfo)
{
string key = BuildKey.ForMetaChange(changeInfo);
return mCache.ContainsKey(key);
}
internal IncomingChangeInfo GetExistingMeta(IncomingChangeInfo change)
{
IncomingChangeInfo result;
if (!mCache.TryGetValue(BuildKey.ForMetaChange(change), out result))
return null;
return result;
}
internal List<IncomingChangeInfo> GetExistingMeta(
List<IncomingChangeInfo> changes)
{
List<IncomingChangeInfo> result = new List<IncomingChangeInfo>();
foreach (IncomingChangeInfo change in changes)
{
string key = BuildKey.ForMetaChange(change);
IncomingChangeInfo metaChange;
if (!mCache.TryGetValue(key, out metaChange))
continue;
result.Add(metaChange);
}
return result;
}
internal void Build(List<IncomingChangeCategory> incomingChangesCategories)
{
mCache.Clear();
foreach (IncomingChangeCategory category in incomingChangesCategories)
{
ExtractMetaToCache(category, mCache);
}
}
static void ExtractMetaToCache(
IncomingChangeCategory category,
Dictionary<string, IncomingChangeInfo> cache)
{
List<IncomingChangeInfo> changes = category.GetChanges();
HashSet<string> indexedKeys = BuildIndexedKeys(
changes);
for (int i = changes.Count - 1; i >= 0; i--)
{
IncomingChangeInfo currentChange = changes[i];
string path = currentChange.GetPath();
if (!MetaPath.IsMetaPath(path))
continue;
string realPath = MetaPath.GetPathFromMetaPath(path);
if (!indexedKeys.Contains(BuildKey.BuildCacheKey(
currentChange.CategoryType, realPath)))
continue;
// found foo.c and foo.c.meta - move .meta to cache
cache.Add(BuildKey.ForChange(currentChange), currentChange);
changes.RemoveAt(i);
}
}
static HashSet<string> BuildIndexedKeys(
List<IncomingChangeInfo> changes)
{
HashSet<string> result = new HashSet<string>();
foreach (IncomingChangeInfo change in changes)
{
if (MetaPath.IsMetaPath(change.GetPath()))
continue;
result.Add(BuildKey.ForChange(change));
}
return result;
}
Dictionary<string, IncomingChangeInfo> mCache =
new Dictionary<string, IncomingChangeInfo>();
static class BuildKey
{
internal static string ForChange(
IncomingChangeInfo change)
{
return BuildCacheKey(
change.CategoryType,
change.GetPath());
}
internal static string ForMetaChange(
IncomingChangeInfo change)
{
return BuildCacheKey(
change.CategoryType,
MetaPath.GetMetaPath(change.GetPath()));
}
internal static string BuildCacheKey(
IncomingChangeCategory.Type type,
string path)
{
return string.Concat(type, ":", path);
}
}
}
}
}

View file

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