initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 97b1b110b0cf5ec428f9553e02bb7c03
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,17 @@
|
|||
using UnityEditor.IMGUI.Controls;
|
||||
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal class ChangeCategoryTreeViewItem : TreeViewItem
|
||||
{
|
||||
internal MergeChangesCategory Category { get; private set; }
|
||||
|
||||
internal ChangeCategoryTreeViewItem(int id, MergeChangesCategory category)
|
||||
: base(id, 0, category.CategoryType.ToString())
|
||||
{
|
||||
Category = category;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c408e05e88bc93c458a3195b15e9d625
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,19 @@
|
|||
using UnityEditor.IMGUI.Controls;
|
||||
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal class ChangeTreeViewItem : TreeViewItem
|
||||
{
|
||||
internal MergeChangeInfo ChangeInfo { get; private set; }
|
||||
|
||||
internal ChangeTreeViewItem(int id, MergeChangeInfo change)
|
||||
: base(id, 1)
|
||||
{
|
||||
ChangeInfo = change;
|
||||
|
||||
displayName = id.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 69ebbdad2c303214683305d65fe26726
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5b3802c1581ef894d83aa9fcb7ace84c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,39 @@
|
|||
using Codice.Client.BaseCommands.Merge;
|
||||
using Codice.CM.Common.Merge;
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer.DirectoryConflicts
|
||||
{
|
||||
internal class ConflictResolutionState
|
||||
{
|
||||
internal DirectoryConflictResolveActions ResolveAction { get; set; }
|
||||
internal string RenameValue { get; set; }
|
||||
internal bool IsApplyActionsForNextConflictsChecked { get; set; }
|
||||
|
||||
internal static ConflictResolutionState Build(
|
||||
DirectoryConflict directoryConflict,
|
||||
DirectoryConflictAction[] conflictActions)
|
||||
{
|
||||
bool hasRenameOption = DirectoryConflictResolutionInfo.HasRenameOption(
|
||||
conflictActions);
|
||||
|
||||
ConflictResolutionState result = new ConflictResolutionState()
|
||||
{
|
||||
IsApplyActionsForNextConflictsChecked = false,
|
||||
ResolveAction = (hasRenameOption) ?
|
||||
DirectoryConflictResolveActions.Rename :
|
||||
DirectoryConflictResolveActions.KeepSource,
|
||||
};
|
||||
|
||||
if (!hasRenameOption)
|
||||
return result;
|
||||
|
||||
|
||||
result.RenameValue = DirectoryConflictResolutionInfo.GetProposeNewItemName(
|
||||
directoryConflict, "dst");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f88a4e9dbb5a07744954a86cbb61d54f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,256 @@
|
|||
using System;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.BaseCommands.Merge;
|
||||
using Codice.CM.Common.Merge;
|
||||
using PlasticGui;
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
using Unity.PlasticSCM.Editor.UI;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer.DirectoryConflicts
|
||||
{
|
||||
internal static class DrawDirectoryResolutionPanel
|
||||
{
|
||||
internal static void ForConflict(
|
||||
MergeChangeInfo conflict,
|
||||
int pendingConflictsCount,
|
||||
DirectoryConflictUserInfo conflictUserInfo,
|
||||
DirectoryConflictAction[] actions,
|
||||
Action<MergeChangeInfo> resolveConflictAction,
|
||||
ref ConflictResolutionState state)
|
||||
{
|
||||
bool isResolveButtonEnabled;
|
||||
string validationMessage = null;
|
||||
|
||||
GetValidationData(
|
||||
conflict,
|
||||
state,
|
||||
out isResolveButtonEnabled,
|
||||
out validationMessage);
|
||||
|
||||
GUILayout.Space(2);
|
||||
DoHeader(
|
||||
conflictUserInfo.ConflictTitle,
|
||||
conflict,
|
||||
resolveConflictAction,
|
||||
isResolveButtonEnabled,
|
||||
ref state);
|
||||
DoConflictExplanation(conflictUserInfo.ConflictExplanation);
|
||||
DoSourceAndDestinationLabels(
|
||||
conflictUserInfo.SourceOperation,
|
||||
conflictUserInfo.DestinationOperation);
|
||||
DoResolutionOptions(
|
||||
actions,
|
||||
validationMessage,
|
||||
ref state);
|
||||
DoApplyActionsForNextConflictsCheck(pendingConflictsCount, ref state);
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
|
||||
static void DoHeader(
|
||||
string conflictName,
|
||||
MergeChangeInfo conflict,
|
||||
Action<MergeChangeInfo> resolveConflictAction,
|
||||
bool isResolveButtonEnabled,
|
||||
ref ConflictResolutionState state)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUILayout.Label(conflictName,
|
||||
UnityStyles.DirectoryConflicts.TitleLabel);
|
||||
|
||||
GUI.enabled = isResolveButtonEnabled;
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
if (GUILayout.Button(PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.ResolveDirectoryConflict)))
|
||||
{
|
||||
resolveConflictAction(conflict);
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
static void DoConflictExplanation(string explanation)
|
||||
{
|
||||
GUILayout.Space(5);
|
||||
GUILayout.Label(explanation, EditorStyles.wordWrappedLabel);
|
||||
}
|
||||
|
||||
static void DoSourceAndDestinationLabels(
|
||||
string sourceOperation,
|
||||
string destinationOperation)
|
||||
{
|
||||
GUILayout.Space(5);
|
||||
|
||||
GUIStyle boldLabelStyle = UnityStyles.DirectoryConflicts.BoldLabel;
|
||||
|
||||
GUIContent srcLabel = new GUIContent(
|
||||
PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.Source));
|
||||
|
||||
GUIContent dstLabel = new GUIContent(
|
||||
PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.Destination));
|
||||
|
||||
float maxWidth = GetMaxWidth(srcLabel, dstLabel, boldLabelStyle);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(25);
|
||||
GUILayout.Label(srcLabel, boldLabelStyle, GUILayout.Width(maxWidth));
|
||||
GUILayout.Label(sourceOperation, EditorStyles.label);
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(25);
|
||||
GUILayout.Label(dstLabel, boldLabelStyle, GUILayout.Width(maxWidth));
|
||||
GUILayout.Label(destinationOperation, EditorStyles.label);
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
static void DoResolutionOptions(
|
||||
DirectoryConflictAction[] actions,
|
||||
string validationMessage,
|
||||
ref ConflictResolutionState state)
|
||||
{
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Label(PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.ResolveDirectoryConflictChooseOption));
|
||||
|
||||
foreach (DirectoryConflictAction action in actions)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(25);
|
||||
if (GUILayout.Toggle(
|
||||
state.ResolveAction == action.ActionKind,
|
||||
action.ActionText,
|
||||
EditorStyles.radioButton))
|
||||
{
|
||||
state.ResolveAction = action.ActionKind;
|
||||
}
|
||||
|
||||
if (action.ActionKind == DirectoryConflictResolveActions.Rename)
|
||||
{
|
||||
GUI.enabled = state.ResolveAction == DirectoryConflictResolveActions.Rename;
|
||||
state.RenameValue = GUILayout.TextField(
|
||||
state.RenameValue,
|
||||
UnityStyles.DirectoryConflicts.FileNameTextField,
|
||||
GUILayout.Width(250));
|
||||
GUI.enabled = true;
|
||||
|
||||
if (!string.IsNullOrEmpty(validationMessage))
|
||||
{
|
||||
GUILayout.Label(new GUIContent(
|
||||
validationMessage,
|
||||
Images.GetWarnIcon()),
|
||||
UnityStyles.DirectoryConflictResolution.WarningLabel,
|
||||
GUILayout.Height(UnityConstants.DIR_CONFLICT_VALIDATION_WARNING_LABEL_HEIGHT));
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
static void DoApplyActionsForNextConflictsCheck(
|
||||
int pendingConflictsCount,
|
||||
ref ConflictResolutionState state)
|
||||
{
|
||||
if (pendingConflictsCount == 0)
|
||||
return;
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
bool isCheckEnabled = state.ResolveAction != DirectoryConflictResolveActions.Rename;
|
||||
bool isChecked = state.IsApplyActionsForNextConflictsChecked & isCheckEnabled;
|
||||
|
||||
GUI.enabled = isCheckEnabled;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
state.IsApplyActionsForNextConflictsChecked = !GUILayout.Toggle(
|
||||
isChecked,
|
||||
GetApplyActionCheckButtonText(pendingConflictsCount));
|
||||
|
||||
if (!isCheckEnabled)
|
||||
state.IsApplyActionsForNextConflictsChecked = false;
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
static bool IsValidName(
|
||||
string name,
|
||||
DirectoryConflict conflict,
|
||||
out string errorMessage)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
errorMessage = PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.InputItemNameMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name == DirectoryConflictResolutionInfo.GetOldItemName(conflict))
|
||||
{
|
||||
errorMessage = PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.ProvideDifferentItemNameForRenameResolution);
|
||||
return false;
|
||||
}
|
||||
|
||||
errorMessage = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void GetValidationData(
|
||||
MergeChangeInfo conflict,
|
||||
ConflictResolutionState state,
|
||||
out bool isResolveButtonEnabled,
|
||||
out string renameWarningMessage)
|
||||
{
|
||||
if (state.ResolveAction != DirectoryConflictResolveActions.Rename)
|
||||
{
|
||||
renameWarningMessage = string.Empty;
|
||||
isResolveButtonEnabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
isResolveButtonEnabled = IsValidName(
|
||||
state.RenameValue,
|
||||
conflict.DirectoryConflict,
|
||||
out renameWarningMessage);
|
||||
}
|
||||
|
||||
static float GetMaxWidth(
|
||||
GUIContent label1,
|
||||
GUIContent label2,
|
||||
GUIStyle style)
|
||||
{
|
||||
Vector2 srcLabelSize = style.CalcSize(label1);
|
||||
Vector2 dstLabelSize = style.CalcSize(label2);
|
||||
|
||||
return Math.Max(srcLabelSize.x, dstLabelSize.x);
|
||||
}
|
||||
|
||||
static string GetApplyActionCheckButtonText(int pendingConflictsCount)
|
||||
{
|
||||
if (pendingConflictsCount > 1)
|
||||
return PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.ApplyActionForNextConflictsCheckButtonSingular,
|
||||
pendingConflictsCount);
|
||||
|
||||
return PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.ApplyActionForNextConflictsCheckButtonPlural,
|
||||
pendingConflictsCount);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a9881fce7e445b84bbbd53752db30fe9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,44 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using PlasticGui.WorkspaceWindow.IncomingChanges;
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal static class IncomingChangesSelection
|
||||
{
|
||||
internal static List<string> GetPathsFromSelectedFileConflictsIncludingMeta(
|
||||
IncomingChangesTreeView treeView)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
|
||||
List<MergeChangeInfo> selection =
|
||||
treeView.GetSelectedFileConflicts();
|
||||
|
||||
treeView.FillWithMeta(selection);
|
||||
|
||||
foreach (MergeChangeInfo incomingChange in selection)
|
||||
{
|
||||
result.Add(incomingChange.GetPath());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static SelectedIncomingChangesGroupInfo GetSelectedGroupInfo(
|
||||
IncomingChangesTreeView treeView)
|
||||
{
|
||||
List<MergeChangeInfo> selectedIncomingChanges =
|
||||
treeView.GetSelectedIncomingChanges();
|
||||
|
||||
return GetSelectedIncomingChangesGroupInfo.For(
|
||||
selectedIncomingChanges);
|
||||
}
|
||||
|
||||
internal static MergeChangeInfo GetSingleSelectedIncomingChange(
|
||||
IncomingChangesTreeView treeView)
|
||||
{
|
||||
return treeView.GetSelectedIncomingChange();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b10c9294742ed4040ad32d0b73b16c75
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,920 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.BaseCommands;
|
||||
using Codice.Client.BaseCommands.EventTracking;
|
||||
using Codice.Client.BaseCommands.Merge;
|
||||
using Codice.Client.Commands;
|
||||
using Codice.Client.Common;
|
||||
using Codice.Client.Common.FsNodeReaders;
|
||||
using Codice.Client.Common.Threading;
|
||||
using Codice.CM.Common;
|
||||
using Codice.CM.Common.Merge;
|
||||
using PlasticGui;
|
||||
using PlasticGui.WorkspaceWindow;
|
||||
using PlasticGui.WorkspaceWindow.BranchExplorer;
|
||||
using PlasticGui.WorkspaceWindow.Diff;
|
||||
using PlasticGui.WorkspaceWindow.IncomingChanges;
|
||||
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.Tree;
|
||||
using Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer.DirectoryConflicts;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal class IncomingChangesTab :
|
||||
IIncomingChangesTab,
|
||||
IRefreshableView,
|
||||
MergeViewLogic.IMergeView,
|
||||
IIncomingChangesViewMenuOperations,
|
||||
IncomingChangesViewMenu.IMetaMenuOperations
|
||||
{
|
||||
internal IncomingChangesTab(
|
||||
WorkspaceInfo wkInfo,
|
||||
IWorkspaceWindow workspaceWindow,
|
||||
IViewSwitcher switcher,
|
||||
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
|
||||
NewIncomingChangesUpdater newIncomingChangesUpdater,
|
||||
EditorWindow parentWindow)
|
||||
{
|
||||
mWkInfo = wkInfo;
|
||||
mWorkspaceWindow = workspaceWindow;
|
||||
mSwitcher = switcher;
|
||||
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
|
||||
mNewIncomingChangesUpdater = newIncomingChangesUpdater;
|
||||
mParentWindow = parentWindow;
|
||||
mGuiMessage = new UnityPlasticGuiMessage();
|
||||
|
||||
BuildComponents(mWkInfo);
|
||||
|
||||
mProgressControls = new ProgressControlsForViews();
|
||||
|
||||
mCooldownClearUpdateSuccessAction = new CooldownWindowDelayer(
|
||||
DelayedClearUpdateSuccess,
|
||||
UnityConstants.NOTIFICATION_CLEAR_INTERVAL);
|
||||
|
||||
PlasticNotifier plasticNotifier = new PlasticNotifier();
|
||||
|
||||
mMergeController = new MergeController(
|
||||
mWkInfo,
|
||||
null,
|
||||
null,
|
||||
EnumMergeType.IncomingMerge,
|
||||
true,
|
||||
plasticNotifier,
|
||||
null);
|
||||
|
||||
mMergeViewLogic = new MergeViewLogic(
|
||||
mWkInfo,
|
||||
EnumMergeType.IncomingMerge,
|
||||
true,
|
||||
mMergeController,
|
||||
plasticNotifier,
|
||||
ShowIncomingChangesFrom.NotificationBar,
|
||||
null,
|
||||
mNewIncomingChangesUpdater,
|
||||
null,
|
||||
this,
|
||||
NewChangesInWk.Build(mWkInfo, new BuildWorkspacekIsRelevantNewChange()),
|
||||
mProgressControls,
|
||||
null);
|
||||
|
||||
((IRefreshableView)this).Refresh();
|
||||
}
|
||||
|
||||
bool IIncomingChangesTab.IsVisible{ get; set; }
|
||||
|
||||
void IIncomingChangesTab.OnDisable()
|
||||
{
|
||||
TreeHeaderSettings.Save(
|
||||
mIncomingChangesTreeView.multiColumnHeader.state,
|
||||
UnityConstants.DEVELOPER_INCOMING_CHANGES_TABLE_SETTINGS_NAME);
|
||||
|
||||
mResolveChangeset.Clear();
|
||||
}
|
||||
|
||||
void IIncomingChangesTab.Update()
|
||||
{
|
||||
mProgressControls.UpdateProgress(mParentWindow);
|
||||
}
|
||||
|
||||
void IIncomingChangesTab.OnGUI()
|
||||
{
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
mHasPendingDirectoryConflicts =
|
||||
MergeTreeResultParser.GetUnsolvedDirectoryConflictsCount(mResultConflicts) > 0;
|
||||
mIsOperationRunning = mProgressControls.IsOperationRunning();
|
||||
}
|
||||
|
||||
DoConflictsTree(
|
||||
mIncomingChangesTreeView,
|
||||
mIsOperationRunning,
|
||||
mHasNothingToDownload,
|
||||
mIsUpdateSuccessful);
|
||||
|
||||
List<MergeChangeInfo> selectedIncomingChanges =
|
||||
mIncomingChangesTreeView.GetSelectedIncomingChanges();
|
||||
|
||||
if (GetSelectedIncomingChangesGroupInfo.For(
|
||||
selectedIncomingChanges).IsDirectoryConflictsSelection &&
|
||||
!Mouse.IsRightMouseButtonPressed(Event.current))
|
||||
{
|
||||
DoDirectoryConflictResolutionPanel(
|
||||
selectedIncomingChanges,
|
||||
new Action<MergeChangeInfo>(ResolveDirectoryConflict),
|
||||
mConflictResolutionStates);
|
||||
}
|
||||
|
||||
DrawActionToolbar.Begin(mParentWindow);
|
||||
|
||||
if (!mIsOperationRunning)
|
||||
{
|
||||
DoActionToolbarMessage(
|
||||
mIsMessageLabelVisible,
|
||||
mMessageLabelText,
|
||||
mHasNothingToDownload,
|
||||
mIsErrorMessageLabelVisible,
|
||||
mErrorMessageLabelText,
|
||||
mDirectoryConflictCount,
|
||||
mFileConflictCount,
|
||||
mChangesSummary);
|
||||
|
||||
if (mIsProcessMergesButtonVisible)
|
||||
{
|
||||
DoProcessMergesButton(
|
||||
mIsProcessMergesButtonEnabled && !mHasPendingDirectoryConflicts,
|
||||
mProcessMergesButtonText,
|
||||
mSwitcher,
|
||||
mWorkspaceWindow,
|
||||
mGuiMessage,
|
||||
mMergeViewLogic,
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation));
|
||||
}
|
||||
|
||||
if (mIsCancelMergesButtonVisible)
|
||||
{
|
||||
mIsCancelMergesButtonEnabled = DoCancelMergesButton(
|
||||
mIsCancelMergesButtonEnabled,
|
||||
mMergeViewLogic);
|
||||
}
|
||||
|
||||
if (mHasPendingDirectoryConflicts)
|
||||
{
|
||||
GUILayout.Space(5);
|
||||
DoWarningMessage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawProgressForViews.ForIndeterminateProgress(
|
||||
mProgressControls.ProgressData);
|
||||
}
|
||||
|
||||
DrawActionToolbar.End();
|
||||
|
||||
if (mProgressControls.HasNotification())
|
||||
{
|
||||
DrawProgressForViews.ForNotificationArea(
|
||||
mProgressControls.ProgressData);
|
||||
}
|
||||
}
|
||||
|
||||
void IIncomingChangesTab.AutoRefresh()
|
||||
{
|
||||
BranchInfo workingBranch = null;
|
||||
|
||||
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
|
||||
waiter.Execute(
|
||||
/*threadOperationDelegate*/ delegate
|
||||
{
|
||||
workingBranch = OverlappedCalculator.GetWorkingBranch(
|
||||
mWkInfo.ClientPath);
|
||||
},
|
||||
/*afterOperationDelegate*/ delegate
|
||||
{
|
||||
if (waiter.Exception != null)
|
||||
{
|
||||
ExceptionsHandler.DisplayException(waiter.Exception);
|
||||
return;
|
||||
}
|
||||
|
||||
// No need for merge info if it's a label
|
||||
if (workingBranch == null)
|
||||
return;
|
||||
|
||||
mMergeController.UpdateMergeObjectInfoIfNeeded(workingBranch);
|
||||
mMergeViewLogic.AutoRefresh();
|
||||
});
|
||||
}
|
||||
|
||||
void IRefreshableView.Refresh()
|
||||
{
|
||||
BranchInfo workingBranch = null;
|
||||
|
||||
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
|
||||
waiter.Execute(
|
||||
/*threadOperationDelegate*/ delegate
|
||||
{
|
||||
workingBranch = OverlappedCalculator.GetWorkingBranch(
|
||||
mWkInfo.ClientPath);
|
||||
},
|
||||
/*afterOperationDelegate*/ delegate
|
||||
{
|
||||
if (waiter.Exception != null)
|
||||
{
|
||||
ExceptionsHandler.DisplayException(waiter.Exception);
|
||||
return;
|
||||
}
|
||||
|
||||
// No need for merge info if it's a label
|
||||
if (workingBranch == null)
|
||||
return;
|
||||
|
||||
mMergeController.UpdateMergeObjectInfoIfNeeded(workingBranch);
|
||||
mMergeViewLogic.Refresh();
|
||||
});
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.UpdateData(
|
||||
MergeTreeResult resultConflicts,
|
||||
MergeChangesTree mergeChangesTree,
|
||||
ExplainMergeData explainMergeData,
|
||||
MergeSolvedFileConflicts solvedFileConflicts,
|
||||
MountPointWithPath rootMountPoint,
|
||||
bool isIncomingMerge,
|
||||
bool isMergeTo,
|
||||
bool isUpdateMerge,
|
||||
bool mergeHasFinished)
|
||||
{
|
||||
HideMessage();
|
||||
|
||||
ShowProcessMergesButton(MergeViewTexts.GetProcessMergeButtonText(
|
||||
MergeTreeResultParser.GetFileConflictsCount(resultConflicts) > 0,
|
||||
true));
|
||||
|
||||
mResultConflicts = resultConflicts;
|
||||
mConflictResolutionStates.Clear();
|
||||
|
||||
UpdateFileConflictsTree(
|
||||
mergeChangesTree,
|
||||
mIncomingChangesTreeView,
|
||||
mResolveChangeset);
|
||||
|
||||
UpdateOverview(
|
||||
resultConflicts,
|
||||
solvedFileConflicts,
|
||||
rootMountPoint);
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.UpdateSolvedDirectoryConflicts()
|
||||
{
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.UpdateSolvedFileConflicts(
|
||||
MergeSolvedFileConflicts solvedFileConflicts)
|
||||
{
|
||||
mIncomingChangesTreeView.UpdateSolvedFileConflicts(
|
||||
solvedFileConflicts);
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.ShowMessage(
|
||||
string title,
|
||||
string message,
|
||||
bool isErrorMessage)
|
||||
{
|
||||
if (isErrorMessage)
|
||||
{
|
||||
mErrorMessageLabelText = message;
|
||||
mIsErrorMessageLabelVisible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mMessageLabelText = message;
|
||||
mIsMessageLabelVisible = true;
|
||||
mHasNothingToDownload = message == PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.MergeNothingToDownloadForIncomingView);
|
||||
}
|
||||
|
||||
string MergeViewLogic.IMergeView.GetComments(out bool bCancel)
|
||||
{
|
||||
bCancel = false;
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.DisableProcessMergesButton()
|
||||
{
|
||||
mIsProcessMergesButtonEnabled = false;
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.ShowCancelButton()
|
||||
{
|
||||
mIsCancelMergesButtonEnabled = true;
|
||||
mIsCancelMergesButtonVisible = true;
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.HideCancelButton()
|
||||
{
|
||||
mIsCancelMergesButtonEnabled = false;
|
||||
mIsCancelMergesButtonVisible = false;
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.EnableMergeOptionButton()
|
||||
{
|
||||
}
|
||||
|
||||
void MergeViewLogic.IMergeView.DisableMergeOptionsButton()
|
||||
{
|
||||
}
|
||||
|
||||
SelectedIncomingChangesGroupInfo IIncomingChangesViewMenuOperations.GetSelectedIncomingChangesGroupInfo()
|
||||
{
|
||||
return IncomingChangesSelection.GetSelectedGroupInfo(mIncomingChangesTreeView);
|
||||
}
|
||||
|
||||
void IIncomingChangesViewMenuOperations.MergeContributors()
|
||||
{
|
||||
if (mShowDownloadPlasticExeWindow.Show(
|
||||
mWkInfo,
|
||||
false,
|
||||
TrackFeatureUseEvent.Features.InstallPlasticCloudFromMergeSelectedFiles,
|
||||
TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromMergeSelectedFiles,
|
||||
TrackFeatureUseEvent.Features.CancelPlasticInstallationFromMergeSelectedFiles))
|
||||
return;
|
||||
|
||||
List<string> selectedPaths = IncomingChangesSelection.
|
||||
GetPathsFromSelectedFileConflictsIncludingMeta(
|
||||
mIncomingChangesTreeView);
|
||||
|
||||
mMergeViewLogic.ProcessMerges(
|
||||
mWorkspaceWindow,
|
||||
mSwitcher,
|
||||
mGuiMessage,
|
||||
selectedPaths,
|
||||
MergeContributorType.MergeContributors,
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation),
|
||||
null);
|
||||
}
|
||||
|
||||
void IIncomingChangesViewMenuOperations.MergeKeepingSourceChanges()
|
||||
{
|
||||
List<string> selectedPaths = IncomingChangesSelection.
|
||||
GetPathsFromSelectedFileConflictsIncludingMeta(
|
||||
mIncomingChangesTreeView);
|
||||
|
||||
mMergeViewLogic.ProcessMerges(
|
||||
mWorkspaceWindow,
|
||||
mSwitcher,
|
||||
mGuiMessage,
|
||||
selectedPaths,
|
||||
MergeContributorType.KeepSource,
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation),
|
||||
null);
|
||||
}
|
||||
|
||||
void IIncomingChangesViewMenuOperations.MergeKeepingWorkspaceChanges()
|
||||
{
|
||||
List<string> selectedPaths = IncomingChangesSelection.
|
||||
GetPathsFromSelectedFileConflictsIncludingMeta(
|
||||
mIncomingChangesTreeView);
|
||||
|
||||
mMergeViewLogic.ProcessMerges(
|
||||
mWorkspaceWindow,
|
||||
mSwitcher,
|
||||
mGuiMessage,
|
||||
selectedPaths,
|
||||
MergeContributorType.KeepDestination,
|
||||
RefreshAsset.BeforeLongAssetOperation,
|
||||
() => AfterProcessMerges(RefreshAsset.AfterLongAssetOperation),
|
||||
null);
|
||||
}
|
||||
|
||||
void IIncomingChangesViewMenuOperations.DiffYoursWithIncoming()
|
||||
{
|
||||
MergeChangeInfo incomingChange = IncomingChangesSelection.
|
||||
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
|
||||
|
||||
if (incomingChange == null)
|
||||
return;
|
||||
|
||||
DiffYoursWithIncoming(
|
||||
mShowDownloadPlasticExeWindow,
|
||||
incomingChange,
|
||||
mWkInfo);
|
||||
}
|
||||
|
||||
void IIncomingChangesViewMenuOperations.DiffIncomingChanges()
|
||||
{
|
||||
MergeChangeInfo incomingChange = IncomingChangesSelection.
|
||||
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
|
||||
|
||||
if (incomingChange == null)
|
||||
return;
|
||||
|
||||
DiffIncomingChanges(
|
||||
mShowDownloadPlasticExeWindow,
|
||||
incomingChange,
|
||||
mWkInfo);
|
||||
}
|
||||
|
||||
void IncomingChangesViewMenu.IMetaMenuOperations.DiffIncomingChanges()
|
||||
{
|
||||
MergeChangeInfo incomingChange = IncomingChangesSelection.
|
||||
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
|
||||
|
||||
if (incomingChange == null)
|
||||
return;
|
||||
|
||||
DiffIncomingChanges(
|
||||
mShowDownloadPlasticExeWindow,
|
||||
mIncomingChangesTreeView.GetMetaChange(incomingChange),
|
||||
mWkInfo);
|
||||
}
|
||||
|
||||
void IncomingChangesViewMenu.IMetaMenuOperations.DiffYoursWithIncoming()
|
||||
{
|
||||
MergeChangeInfo incomingChange = IncomingChangesSelection.
|
||||
GetSingleSelectedIncomingChange(mIncomingChangesTreeView);
|
||||
|
||||
if (incomingChange == null)
|
||||
return;
|
||||
|
||||
DiffYoursWithIncoming(
|
||||
mShowDownloadPlasticExeWindow,
|
||||
mIncomingChangesTreeView.GetMetaChange(incomingChange),
|
||||
mWkInfo);
|
||||
}
|
||||
|
||||
bool IncomingChangesViewMenu.IMetaMenuOperations.SelectionHasMeta()
|
||||
{
|
||||
return mIncomingChangesTreeView.SelectionHasMeta();
|
||||
}
|
||||
|
||||
static void DiffYoursWithIncoming(
|
||||
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
|
||||
MergeChangeInfo incomingChange,
|
||||
WorkspaceInfo wkInfo)
|
||||
{
|
||||
if (showDownloadPlasticExeWindow.Show(
|
||||
wkInfo,
|
||||
false,
|
||||
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 DiffIncomingChanges(
|
||||
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
|
||||
MergeChangeInfo incomingChange,
|
||||
WorkspaceInfo wkInfo)
|
||||
{
|
||||
if (showDownloadPlasticExeWindow.Show(
|
||||
wkInfo,
|
||||
false,
|
||||
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);
|
||||
}
|
||||
|
||||
void ShowProcessMergesButton(string processMergesButtonText)
|
||||
{
|
||||
mProcessMergesButtonText = processMergesButtonText;
|
||||
mIsProcessMergesButtonEnabled = true;
|
||||
mIsProcessMergesButtonVisible = true;
|
||||
}
|
||||
|
||||
void HideMessage()
|
||||
{
|
||||
mMessageLabelText = string.Empty;
|
||||
mIsMessageLabelVisible = false;
|
||||
mHasNothingToDownload = false;
|
||||
|
||||
mErrorMessageLabelText = string.Empty;
|
||||
mIsErrorMessageLabelVisible = false;
|
||||
}
|
||||
|
||||
void DelayedClearUpdateSuccess()
|
||||
{
|
||||
mIsUpdateSuccessful = false;
|
||||
}
|
||||
|
||||
static void DoDirectoryConflictResolutionPanel(
|
||||
List<MergeChangeInfo> selectedChangeInfos,
|
||||
Action<MergeChangeInfo> resolveDirectoryConflictAction,
|
||||
Dictionary<DirectoryConflict, ConflictResolutionState> conflictResolutionStates)
|
||||
{
|
||||
MergeChangeInfo selectedDirectoryConflict = selectedChangeInfos[0];
|
||||
|
||||
if (selectedDirectoryConflict.DirectoryConflict.IsResolved())
|
||||
return;
|
||||
|
||||
DirectoryConflictUserInfo conflictUserInfo;
|
||||
DirectoryConflictAction[] conflictActions;
|
||||
|
||||
DirectoryConflictResolutionInfo.FromDirectoryConflict(
|
||||
selectedDirectoryConflict.GetMount(),
|
||||
selectedDirectoryConflict.DirectoryConflict,
|
||||
out conflictUserInfo,
|
||||
out conflictActions);
|
||||
|
||||
ConflictResolutionState conflictResolutionState = GetConflictResolutionState(
|
||||
selectedDirectoryConflict.DirectoryConflict,
|
||||
conflictActions,
|
||||
conflictResolutionStates);
|
||||
|
||||
int pendingSelectedConflictsCount = GetPendingConflictsCount(
|
||||
selectedChangeInfos);
|
||||
|
||||
DrawDirectoryResolutionPanel.ForConflict(
|
||||
selectedDirectoryConflict,
|
||||
(pendingSelectedConflictsCount <= 1) ? 0 : pendingSelectedConflictsCount - 1,
|
||||
conflictUserInfo,
|
||||
conflictActions,
|
||||
resolveDirectoryConflictAction,
|
||||
ref conflictResolutionState);
|
||||
}
|
||||
|
||||
void ResolveDirectoryConflict(MergeChangeInfo conflict)
|
||||
{
|
||||
ConflictResolutionState state;
|
||||
|
||||
if (!mConflictResolutionStates.TryGetValue(conflict.DirectoryConflict, out state))
|
||||
return;
|
||||
|
||||
List<DirectoryConflictResolutionData> conflictResolutions =
|
||||
new List<DirectoryConflictResolutionData>();
|
||||
|
||||
AddConflictResolution(
|
||||
conflict,
|
||||
state.ResolveAction,
|
||||
state.RenameValue,
|
||||
conflictResolutions);
|
||||
|
||||
MergeChangeInfo metaConflict =
|
||||
mIncomingChangesTreeView.GetMetaChange(conflict);
|
||||
|
||||
if (metaConflict != null)
|
||||
{
|
||||
AddConflictResolution(
|
||||
metaConflict,
|
||||
state.ResolveAction,
|
||||
MetaPath.GetMetaPath(state.RenameValue),
|
||||
conflictResolutions);
|
||||
}
|
||||
|
||||
if (state.IsApplyActionsForNextConflictsChecked)
|
||||
{
|
||||
foreach (MergeChangeInfo otherConflict in mIncomingChangesTreeView.GetSelectedIncomingChanges())
|
||||
{
|
||||
AddConflictResolution(
|
||||
otherConflict,
|
||||
state.ResolveAction,
|
||||
state.RenameValue,
|
||||
conflictResolutions);
|
||||
}
|
||||
}
|
||||
|
||||
mMergeViewLogic.ResolveDirectoryConflicts(conflictResolutions);
|
||||
}
|
||||
|
||||
static void AddConflictResolution(
|
||||
MergeChangeInfo conflict,
|
||||
DirectoryConflictResolveActions resolveAction,
|
||||
string renameValue,
|
||||
List<DirectoryConflictResolutionData> conflictResolutions)
|
||||
{
|
||||
conflictResolutions.Add(new DirectoryConflictResolutionData(
|
||||
conflict.DirectoryConflict,
|
||||
conflict.Xlink,
|
||||
conflict.GetMount().Mount,
|
||||
resolveAction,
|
||||
renameValue));
|
||||
}
|
||||
|
||||
static void DoConflictsTree(
|
||||
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));
|
||||
}
|
||||
|
||||
static void DoActionToolbarMessage(
|
||||
bool isMessageLabelVisible,
|
||||
string messageLabelText,
|
||||
bool hasNothingToDownload,
|
||||
bool isErrorMessageLabelVisible,
|
||||
string errorMessageLabelText,
|
||||
int directoryConflictCount,
|
||||
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(
|
||||
directoryConflictCount,
|
||||
fileConflictCount,
|
||||
changesSummary);
|
||||
}
|
||||
}
|
||||
|
||||
void AfterProcessMerges(Action afterAssetLongOperation)
|
||||
{
|
||||
mIsUpdateSuccessful = true;
|
||||
mCooldownClearUpdateSuccessAction.Ping();
|
||||
|
||||
afterAssetLongOperation();
|
||||
}
|
||||
|
||||
static void DoProcessMergesButton(
|
||||
bool isEnabled,
|
||||
string processMergesButtonText,
|
||||
IViewSwitcher switcher,
|
||||
IWorkspaceWindow workspaceWindow,
|
||||
GuiMessage.IGuiMessage guiMessage,
|
||||
MergeViewLogic mergeViewLogic,
|
||||
Action beforeProcessMergesAction,
|
||||
Action afterProcessMergesAction)
|
||||
{
|
||||
GUI.enabled = isEnabled;
|
||||
|
||||
if (DrawActionButton.For(processMergesButtonText))
|
||||
{
|
||||
mergeViewLogic.ProcessMerges(
|
||||
workspaceWindow,
|
||||
switcher,
|
||||
guiMessage,
|
||||
new List<string>(),
|
||||
MergeContributorType.MergeContributors,
|
||||
beforeProcessMergesAction,
|
||||
afterProcessMergesAction,
|
||||
null);
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
static bool DoCancelMergesButton(
|
||||
bool isEnabled,
|
||||
MergeViewLogic mergeViewLogic)
|
||||
{
|
||||
bool shouldCancelMergesButtonEnabled = true;
|
||||
|
||||
GUI.enabled = isEnabled;
|
||||
|
||||
if (DrawActionButton.For(PlasticLocalization.GetString(
|
||||
PlasticLocalization.Name.CancelButton)))
|
||||
{
|
||||
mergeViewLogic.Cancel();
|
||||
|
||||
shouldCancelMergesButtonEnabled = false;
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
|
||||
return shouldCancelMergesButtonEnabled;
|
||||
}
|
||||
|
||||
static void DoWarningMessage()
|
||||
{
|
||||
string label = PlasticLocalization.GetString(PlasticLocalization.Name.SolveConflictsInLable);
|
||||
|
||||
GUILayout.Label(
|
||||
new GUIContent(label, Images.GetWarnIcon()),
|
||||
UnityStyles.IncomingChangesTab.HeaderWarningLabel);
|
||||
}
|
||||
|
||||
void UpdateFileConflictsTree(
|
||||
MergeChangesTree incomingChangesTree,
|
||||
IncomingChangesTreeView incomingChangesTreeView,
|
||||
IResolveChangeset resolveChangeset)
|
||||
{
|
||||
UnityIncomingChangesTree unityIncomingChangesTree = null;
|
||||
|
||||
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
|
||||
waiter.Execute(
|
||||
/*threadOperationDelegate*/ delegate
|
||||
{
|
||||
unityIncomingChangesTree = UnityIncomingChangesTree.BuildIncomingChangeCategories(
|
||||
incomingChangesTree);
|
||||
incomingChangesTree.ResolveUserNames(
|
||||
new MergeChangesTree.ResolveUserName());
|
||||
incomingChangesTree.ResolveComments(resolveChangeset);
|
||||
},
|
||||
/*afterOperationDelegate*/ delegate
|
||||
{
|
||||
incomingChangesTreeView.BuildModel(unityIncomingChangesTree);
|
||||
incomingChangesTreeView.Sort();
|
||||
incomingChangesTreeView.Reload();
|
||||
|
||||
incomingChangesTreeView.SelectFirstUnsolvedDirectoryConflict();
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateOverview(
|
||||
MergeTreeResult resultConflicts,
|
||||
MergeSolvedFileConflicts solvedFileConflicts,
|
||||
MountPointWithPath rootMountPoint)
|
||||
{
|
||||
if (resultConflicts == null || rootMountPoint == null)
|
||||
{
|
||||
mChangesSummary = new MergeViewTexts.ChangesToApplySummary();
|
||||
mFileConflictCount = 0;
|
||||
mDirectoryConflictCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
mChangesSummary = MergeTreeResultParser.
|
||||
GetChangesToApplySummary(resultConflicts);
|
||||
|
||||
mFileConflictCount = MergeTreeResultParser.GetUnsolvedFileConflictsCount(
|
||||
resultConflicts, rootMountPoint.Id, solvedFileConflicts);
|
||||
|
||||
mDirectoryConflictCount = MergeTreeResultParser.GetUnsolvedDirectoryConflictsCount(
|
||||
resultConflicts);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void BuildComponents(WorkspaceInfo wkInfo)
|
||||
{
|
||||
IncomingChangesTreeHeaderState incomingChangesHeaderState =
|
||||
IncomingChangesTreeHeaderState.GetDefault();
|
||||
|
||||
TreeHeaderSettings.Load(incomingChangesHeaderState,
|
||||
UnityConstants.DEVELOPER_INCOMING_CHANGES_TABLE_SETTINGS_NAME,
|
||||
(int)IncomingChangesTreeColumn.Path, true);
|
||||
|
||||
mIncomingChangesTreeView = new IncomingChangesTreeView(
|
||||
wkInfo, incomingChangesHeaderState,
|
||||
IncomingChangesTreeHeaderState.GetColumnNames(),
|
||||
new IncomingChangesViewMenu(this, this));
|
||||
|
||||
mIncomingChangesTreeView.Reload();
|
||||
}
|
||||
|
||||
static ConflictResolutionState GetConflictResolutionState(
|
||||
DirectoryConflict directoryConflict,
|
||||
DirectoryConflictAction[] conflictActions,
|
||||
Dictionary<DirectoryConflict, ConflictResolutionState> conflictResoltionStates)
|
||||
{
|
||||
ConflictResolutionState result;
|
||||
|
||||
if (conflictResoltionStates.TryGetValue(directoryConflict, out result))
|
||||
return result;
|
||||
|
||||
result = ConflictResolutionState.Build(directoryConflict, conflictActions);
|
||||
|
||||
conflictResoltionStates.Add(directoryConflict, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int GetPendingConflictsCount(
|
||||
List<MergeChangeInfo> selectedChangeInfos)
|
||||
{
|
||||
int result = 0;
|
||||
foreach (MergeChangeInfo changeInfo in selectedChangeInfos)
|
||||
{
|
||||
if (changeInfo.DirectoryConflict.IsResolved())
|
||||
continue;
|
||||
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
bool mIsProcessMergesButtonVisible;
|
||||
bool mIsCancelMergesButtonVisible;
|
||||
bool mIsMessageLabelVisible;
|
||||
bool mIsErrorMessageLabelVisible;
|
||||
bool mHasNothingToDownload;
|
||||
|
||||
bool mIsProcessMergesButtonEnabled;
|
||||
bool mIsCancelMergesButtonEnabled;
|
||||
bool mHasPendingDirectoryConflicts;
|
||||
bool mIsOperationRunning;
|
||||
bool mIsUpdateSuccessful;
|
||||
|
||||
string mProcessMergesButtonText;
|
||||
string mMessageLabelText;
|
||||
string mErrorMessageLabelText;
|
||||
|
||||
IncomingChangesTreeView mIncomingChangesTreeView;
|
||||
|
||||
MergeTreeResult mResultConflicts;
|
||||
|
||||
Dictionary<DirectoryConflict, ConflictResolutionState> mConflictResolutionStates =
|
||||
new Dictionary<DirectoryConflict, ConflictResolutionState>();
|
||||
|
||||
int mDirectoryConflictCount;
|
||||
int mFileConflictCount;
|
||||
MergeViewTexts.ChangesToApplySummary mChangesSummary;
|
||||
|
||||
readonly ProgressControlsForViews mProgressControls;
|
||||
readonly CooldownWindowDelayer mCooldownClearUpdateSuccessAction;
|
||||
readonly MergeViewLogic mMergeViewLogic;
|
||||
readonly MergeController mMergeController;
|
||||
readonly GuiMessage.IGuiMessage mGuiMessage;
|
||||
readonly EditorWindow mParentWindow;
|
||||
readonly NewIncomingChangesUpdater mNewIncomingChangesUpdater;
|
||||
readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
|
||||
readonly IViewSwitcher mSwitcher;
|
||||
readonly IWorkspaceWindow mWorkspaceWindow;
|
||||
readonly WorkspaceInfo mWkInfo;
|
||||
readonly IResolveChangeset mResolveChangeset = new ResolveChangeset();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4f04b21b06239da4f95a5a9753647440
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,176 @@
|
|||
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.Developer
|
||||
{
|
||||
internal enum IncomingChangesTreeColumn
|
||||
{
|
||||
Path,
|
||||
Size,
|
||||
Author,
|
||||
Details,
|
||||
Resolution,
|
||||
DateModified,
|
||||
Comment
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class IncomingChangesTreeHeaderState : MultiColumnHeaderState, ISerializationCallbackReceiver
|
||||
{
|
||||
internal static IncomingChangesTreeHeaderState GetDefault()
|
||||
{
|
||||
IncomingChangesTreeHeaderState headerState =
|
||||
new IncomingChangesTreeHeaderState(BuildColumns());
|
||||
|
||||
headerState.visibleColumns = GetDefaultVisibleColumns();
|
||||
|
||||
return headerState;
|
||||
}
|
||||
|
||||
internal static List<string> GetColumnNames()
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.PathColumn));
|
||||
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.SizeColumn));
|
||||
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.CreatedByColumn));
|
||||
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.DetailsColumn));
|
||||
result.Add(PlasticLocalization.GetString(PlasticLocalization.Name.ResolutionMethodColumn));
|
||||
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.Size:
|
||||
return PlasticLocalization.GetString(PlasticLocalization.Name.SizeColumn);
|
||||
case IncomingChangesTreeColumn.Author:
|
||||
return PlasticLocalization.GetString(PlasticLocalization.Name.AuthorColumn);
|
||||
case IncomingChangesTreeColumn.Details:
|
||||
return PlasticLocalization.GetString(PlasticLocalization.Name.DetailsColumn);
|
||||
case IncomingChangesTreeColumn.Resolution:
|
||||
return PlasticLocalization.GetString(PlasticLocalization.Name.ResolutionMethodColumn);
|
||||
case IncomingChangesTreeColumn.DateModified:
|
||||
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 int[] GetDefaultVisibleColumns()
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
result.Add((int)IncomingChangesTreeColumn.Path);
|
||||
result.Add((int)IncomingChangesTreeColumn.Size);
|
||||
result.Add((int)IncomingChangesTreeColumn.Author);
|
||||
result.Add((int)IncomingChangesTreeColumn.DateModified);
|
||||
result.Add((int)IncomingChangesTreeColumn.Comment);
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
static Column[] BuildColumns()
|
||||
{
|
||||
return new Column[]
|
||||
{
|
||||
new Column()
|
||||
{
|
||||
width = 450,
|
||||
headerContent = new GUIContent(
|
||||
GetColumnName(IncomingChangesTreeColumn.Path)),
|
||||
minWidth = 200,
|
||||
allowToggleVisibility = false,
|
||||
sortingArrowAlignment = TextAlignment.Right
|
||||
},
|
||||
new Column()
|
||||
{
|
||||
width = 150,
|
||||
headerContent = new GUIContent(
|
||||
GetColumnName(IncomingChangesTreeColumn.Size)),
|
||||
minWidth = 45,
|
||||
sortingArrowAlignment = TextAlignment.Right
|
||||
},
|
||||
new Column()
|
||||
{
|
||||
width = 150,
|
||||
headerContent = new GUIContent(
|
||||
GetColumnName(IncomingChangesTreeColumn.Author)),
|
||||
minWidth = 80,
|
||||
sortingArrowAlignment = TextAlignment.Right
|
||||
},
|
||||
new Column()
|
||||
{
|
||||
width = 200,
|
||||
headerContent = new GUIContent(
|
||||
GetColumnName(IncomingChangesTreeColumn.Details)),
|
||||
minWidth = 100,
|
||||
sortingArrowAlignment = TextAlignment.Right
|
||||
},
|
||||
new Column()
|
||||
{
|
||||
width = 250,
|
||||
headerContent = new GUIContent(
|
||||
GetColumnName(IncomingChangesTreeColumn.Resolution)),
|
||||
minWidth = 120,
|
||||
sortingArrowAlignment = TextAlignment.Right
|
||||
},
|
||||
new Column()
|
||||
{
|
||||
width = 330,
|
||||
headerContent = new GUIContent(
|
||||
GetColumnName(IncomingChangesTreeColumn.DateModified)),
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6c8b04d6403125b4ca51861863f386ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,576 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.BaseCommands.Merge;
|
||||
using Codice.Client.Common;
|
||||
using Codice.CM.Common;
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
using Unity.PlasticSCM.Editor.UI;
|
||||
using Unity.PlasticSCM.Editor.UI.Tree;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal class IncomingChangesTreeView : TreeView
|
||||
{
|
||||
internal IncomingChangesTreeView(
|
||||
WorkspaceInfo wkInfo,
|
||||
IncomingChangesTreeHeaderState headerState,
|
||||
List<string> columnNames,
|
||||
IncomingChangesViewMenu menu)
|
||||
: base(new TreeViewState())
|
||||
{
|
||||
mWkInfo = wkInfo;
|
||||
mColumnNames = columnNames;
|
||||
mMenu = menu;
|
||||
|
||||
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)
|
||||
{
|
||||
ChangeCategoryTreeViewItem categoryItem =
|
||||
(ChangeCategoryTreeViewItem)args.item;
|
||||
|
||||
CategoryTreeViewItemGUI(
|
||||
args.rowRect,
|
||||
categoryItem,
|
||||
GetSolvedChildrenCount(categoryItem.Category, mSolvedFileConflicts),
|
||||
args.selected,
|
||||
args.focused);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.item is ChangeTreeViewItem)
|
||||
{
|
||||
ChangeTreeViewItem changeTreeViewItem =
|
||||
(ChangeTreeViewItem)args.item;
|
||||
|
||||
MergeChangeInfo changeInfo =
|
||||
changeTreeViewItem.ChangeInfo;
|
||||
|
||||
bool isCurrentConflict = IsCurrent.Conflict(
|
||||
changeInfo,
|
||||
mIncomingChangesTree.GetMetaChange(changeInfo),
|
||||
mSolvedFileConflicts);
|
||||
|
||||
bool isSolvedConflict = IsSolved.Conflict(
|
||||
changeInfo,
|
||||
mIncomingChangesTree.GetMetaChange(changeInfo),
|
||||
mSolvedFileConflicts);
|
||||
|
||||
IncomingChangeTreeViewItemGUI(
|
||||
mWkInfo.ClientPath,
|
||||
mIncomingChangesTree,
|
||||
this,
|
||||
changeTreeViewItem,
|
||||
args,
|
||||
isCurrentConflict,
|
||||
isSolvedConflict);
|
||||
return;
|
||||
}
|
||||
|
||||
base.RowGUI(args);
|
||||
}
|
||||
|
||||
internal void SelectFirstUnsolvedDirectoryConflict()
|
||||
{
|
||||
foreach (MergeChangesCategory category in mIncomingChangesTree.GetNodes())
|
||||
{
|
||||
if (category.CategoryType != MergeChangesCategory.Type.DirectoryConflicts)
|
||||
continue;
|
||||
|
||||
foreach (MergeChangeInfo changeInfo in category.GetChanges())
|
||||
{
|
||||
if (changeInfo.DirectoryConflict.IsResolved())
|
||||
continue;
|
||||
|
||||
int itemId = -1;
|
||||
if (mTreeViewItemIds.TryGetInfoItemId(changeInfo, out itemId))
|
||||
{
|
||||
SetSelection(new List<int>() { itemId });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void BuildModel(UnityIncomingChangesTree tree)
|
||||
{
|
||||
mTreeViewItemIds.Clear();
|
||||
|
||||
mIncomingChangesTree = tree;
|
||||
mSolvedFileConflicts = null;
|
||||
|
||||
mExpandCategories = true;
|
||||
}
|
||||
|
||||
internal void Sort()
|
||||
{
|
||||
int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
|
||||
bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
|
||||
|
||||
mIncomingChangesTree.Sort(mColumnNames[sortedColumnIdx], sortAscending);
|
||||
}
|
||||
|
||||
internal void UpdateSolvedFileConflicts(
|
||||
MergeSolvedFileConflicts solvedFileConflicts)
|
||||
{
|
||||
mSolvedFileConflicts = solvedFileConflicts;
|
||||
}
|
||||
|
||||
internal MergeChangeInfo GetMetaChange(MergeChangeInfo change)
|
||||
{
|
||||
if (change == null)
|
||||
return null;
|
||||
|
||||
return mIncomingChangesTree.GetMetaChange(change);
|
||||
}
|
||||
|
||||
internal void FillWithMeta(List<MergeChangeInfo> changes)
|
||||
{
|
||||
mIncomingChangesTree.FillWithMeta(changes);
|
||||
}
|
||||
|
||||
internal bool SelectionHasMeta()
|
||||
{
|
||||
MergeChangeInfo selectedChangeInfo = GetSelectedIncomingChange();
|
||||
|
||||
if (selectedChangeInfo == null)
|
||||
return false;
|
||||
|
||||
return mIncomingChangesTree.HasMeta(selectedChangeInfo);
|
||||
}
|
||||
|
||||
internal MergeChangeInfo GetSelectedIncomingChange()
|
||||
{
|
||||
IList<int> selectedIds = GetSelection();
|
||||
|
||||
if (selectedIds.Count != 1)
|
||||
return null;
|
||||
|
||||
int selectedId = selectedIds[0];
|
||||
|
||||
foreach (KeyValuePair<MergeChangeInfo, int> item
|
||||
in mTreeViewItemIds.GetInfoItems())
|
||||
{
|
||||
if (selectedId == item.Value)
|
||||
return item.Key;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal List<MergeChangeInfo> GetSelectedIncomingChanges()
|
||||
{
|
||||
List<MergeChangeInfo> result = new List<MergeChangeInfo>();
|
||||
|
||||
IList<int> selectedIds = GetSelection();
|
||||
|
||||
if (selectedIds.Count == 0)
|
||||
return result;
|
||||
|
||||
foreach (KeyValuePair<MergeChangeInfo, int> item
|
||||
in mTreeViewItemIds.GetInfoItems())
|
||||
{
|
||||
if (!selectedIds.Contains(item.Value))
|
||||
continue;
|
||||
|
||||
result.Add(item.Key);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal List<MergeChangeInfo> GetSelectedFileConflicts()
|
||||
{
|
||||
List<MergeChangeInfo> result = new List<MergeChangeInfo>();
|
||||
|
||||
IList<int> selectedIds = GetSelection();
|
||||
|
||||
if (selectedIds.Count == 0)
|
||||
return result;
|
||||
|
||||
foreach (KeyValuePair<MergeChangeInfo, int> item
|
||||
in mTreeViewItemIds.GetInfoItems())
|
||||
{
|
||||
if (!selectedIds.Contains(item.Value))
|
||||
continue;
|
||||
|
||||
if (item.Key.CategoryType !=
|
||||
MergeChangesCategory.Type.FileConflicts)
|
||||
continue;
|
||||
|
||||
result.Add(item.Key);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SortingChanged(MultiColumnHeader multiColumnHeader)
|
||||
{
|
||||
Sort();
|
||||
|
||||
Reload();
|
||||
}
|
||||
|
||||
static void RegenerateRows(
|
||||
UnityIncomingChangesTree incomingChangesTree,
|
||||
TreeViewItemIds<MergeChangesCategory, MergeChangeInfo> treeViewItemIds,
|
||||
IncomingChangesTreeView treeView,
|
||||
TreeViewItem rootItem,
|
||||
List<TreeViewItem> rows,
|
||||
bool expandCategories)
|
||||
{
|
||||
if (incomingChangesTree == null)
|
||||
return;
|
||||
|
||||
ClearRows(rootItem, rows);
|
||||
|
||||
List<MergeChangesCategory> categories = incomingChangesTree.GetNodes();
|
||||
|
||||
if (categories == null)
|
||||
return;
|
||||
|
||||
List<int> categoriesToExpand = new List<int>();
|
||||
|
||||
foreach (MergeChangesCategory 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,
|
||||
expandCategories,
|
||||
categories.Count))
|
||||
continue;
|
||||
|
||||
categoriesToExpand.Add(categoryTreeViewItem.id);
|
||||
|
||||
foreach (MergeChangeInfo changeInfo in category.GetChanges())
|
||||
{
|
||||
int differenceId;
|
||||
if (!treeViewItemIds.TryGetInfoItemId(changeInfo, out differenceId))
|
||||
differenceId = treeViewItemIds.AddInfoItem(changeInfo);
|
||||
|
||||
TreeViewItem changeTreeViewItem =
|
||||
new ChangeTreeViewItem(differenceId, changeInfo);
|
||||
|
||||
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 CategoryTreeViewItemGUI(
|
||||
Rect rowRect,
|
||||
ChangeCategoryTreeViewItem item,
|
||||
int solvedChildrenCount,
|
||||
bool isSelected,
|
||||
bool isFocused)
|
||||
{
|
||||
string label = item.Category.GetCategoryName();
|
||||
string infoLabel = item.Category.GetChildrenCountText();
|
||||
|
||||
DefaultStyles.label = GetCategoryStyle(
|
||||
item.Category,
|
||||
solvedChildrenCount,
|
||||
isSelected);
|
||||
|
||||
DrawTreeViewItem.ForCategoryItem(
|
||||
rowRect,
|
||||
item.depth,
|
||||
label,
|
||||
infoLabel,
|
||||
isSelected,
|
||||
isFocused);
|
||||
|
||||
DefaultStyles.label = UnityStyles.Tree.Label;
|
||||
}
|
||||
|
||||
static void IncomingChangeTreeViewItemGUI(
|
||||
string wkPath,
|
||||
UnityIncomingChangesTree incomingChangesTree,
|
||||
IncomingChangesTreeView treeView,
|
||||
ChangeTreeViewItem item,
|
||||
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,
|
||||
column,
|
||||
args.selected,
|
||||
args.focused,
|
||||
isCurrentConflict,
|
||||
isSolvedConflict);
|
||||
}
|
||||
}
|
||||
|
||||
static void IncomingChangeTreeViewItemCellGUI(
|
||||
string wkPath,
|
||||
Rect rect,
|
||||
float rowHeight,
|
||||
UnityIncomingChangesTree incomingChangesTree,
|
||||
IncomingChangesTreeView treeView,
|
||||
ChangeTreeViewItem item,
|
||||
IncomingChangesTreeColumn column,
|
||||
bool isSelected,
|
||||
bool isFocused,
|
||||
bool isCurrentConflict,
|
||||
bool isSolvedConflict)
|
||||
{
|
||||
MergeChangeInfo 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.ForPlasticIncomingChange(
|
||||
incomingChange, isSolvedConflict);
|
||||
|
||||
DrawTreeViewItem.ForItemCell(
|
||||
rect,
|
||||
rowHeight,
|
||||
item.depth,
|
||||
icon,
|
||||
overlayIcon,
|
||||
label,
|
||||
isSelected,
|
||||
isFocused,
|
||||
isCurrentConflict,
|
||||
false);
|
||||
|
||||
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))
|
||||
{
|
||||
MergeChangeInfo 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,
|
||||
MergeChangeInfo incomingChange)
|
||||
{
|
||||
RevisionInfo revInfo = incomingChange.GetRevision();
|
||||
bool isDirectory = revInfo.
|
||||
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(
|
||||
MergeChangesCategory category,
|
||||
int solvedChildrenCount,
|
||||
bool isSelected)
|
||||
{
|
||||
if (isSelected)
|
||||
return UnityStyles.Tree.Label;
|
||||
|
||||
if (category.CategoryType == MergeChangesCategory.Type.FileConflicts ||
|
||||
category.CategoryType == MergeChangesCategory.Type.DirectoryConflicts)
|
||||
{
|
||||
return category.GetChildrenCount() > solvedChildrenCount ?
|
||||
UnityStyles.Tree.RedLabel : UnityStyles.Tree.GreenLabel;
|
||||
}
|
||||
|
||||
return UnityStyles.Tree.Label;
|
||||
}
|
||||
|
||||
static bool ShouldExpandCategory(
|
||||
IncomingChangesTreeView treeView,
|
||||
ChangeCategoryTreeViewItem categoryTreeViewItem,
|
||||
bool expandCategories,
|
||||
int categoriesCount)
|
||||
{
|
||||
if (expandCategories)
|
||||
{
|
||||
if (categoriesCount == 1)
|
||||
return true;
|
||||
|
||||
if (categoryTreeViewItem.Category.CategoryType ==
|
||||
MergeChangesCategory.Type.FileConflicts)
|
||||
return true;
|
||||
|
||||
if (categoryTreeViewItem.Category.GetChildrenCount() >
|
||||
NODES_TO_EXPAND_CATEGORY)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return treeView.IsExpanded(categoryTreeViewItem.id);
|
||||
}
|
||||
|
||||
static int GetSolvedChildrenCount(
|
||||
MergeChangesCategory category,
|
||||
MergeSolvedFileConflicts solvedFileConflicts)
|
||||
{
|
||||
int solvedDirConflicts = 0;
|
||||
if (category.CategoryType == MergeChangesCategory.Type.DirectoryConflicts)
|
||||
{
|
||||
foreach (MergeChangeInfo change in category.GetChanges())
|
||||
{
|
||||
if (change.DirectoryConflict.IsResolved())
|
||||
solvedDirConflicts++;
|
||||
}
|
||||
|
||||
return solvedDirConflicts;
|
||||
}
|
||||
|
||||
return (solvedFileConflicts == null) ? 0 :
|
||||
solvedFileConflicts.GetCount();
|
||||
}
|
||||
|
||||
bool mExpandCategories;
|
||||
|
||||
TreeViewItemIds<MergeChangesCategory, MergeChangeInfo> mTreeViewItemIds =
|
||||
new TreeViewItemIds<MergeChangesCategory, MergeChangeInfo>();
|
||||
List<TreeViewItem> mRows = new List<TreeViewItem>();
|
||||
|
||||
MergeSolvedFileConflicts mSolvedFileConflicts;
|
||||
UnityIncomingChangesTree mIncomingChangesTree;
|
||||
|
||||
readonly IncomingChangesViewMenu mMenu;
|
||||
readonly List<string> mColumnNames;
|
||||
readonly WorkspaceInfo mWkInfo;
|
||||
|
||||
const int NODES_TO_EXPAND_CATEGORY = 10;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1e0aed0a10caba04583f2474f8279b27
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,223 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.BaseCommands.EventTracking;
|
||||
using Codice.CM.Common;
|
||||
using PlasticGui;
|
||||
using PlasticGui.WorkspaceWindow.IncomingChanges;
|
||||
using Unity.PlasticSCM.Editor.Tool;
|
||||
using Unity.PlasticSCM.Editor.UI;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal class IncomingChangesViewMenu
|
||||
{
|
||||
internal interface IMetaMenuOperations
|
||||
{
|
||||
void DiffIncomingChanges();
|
||||
void DiffYoursWithIncoming();
|
||||
bool SelectionHasMeta();
|
||||
}
|
||||
|
||||
internal IncomingChangesViewMenu(
|
||||
IIncomingChangesViewMenuOperations incomingChangesViewMenuOperations,
|
||||
IMetaMenuOperations incomingChangesMetaMenuOperations)
|
||||
{
|
||||
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 IIncomingChangesViewMenuOperations mIncomingChangesViewMenuOperations;
|
||||
readonly IMetaMenuOperations mIncomingChangesMetaMenuOperations;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 182343c61d477e2449cfbc9cb20dfb35
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,37 @@
|
|||
using Codice.Client.BaseCommands.Merge;
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
// internal for testing purpuses
|
||||
internal static class IsCurrent
|
||||
{
|
||||
internal static bool Conflict(
|
||||
MergeChangeInfo changeInfo,
|
||||
MergeChangeInfo metaChangeInfo,
|
||||
MergeSolvedFileConflicts solvedFileConflicts)
|
||||
{
|
||||
if (solvedFileConflicts == null)
|
||||
return false;
|
||||
|
||||
MergeSolvedFileConflicts.CurrentConflict currentConflict;
|
||||
|
||||
if (!solvedFileConflicts.TryGetCurrentConflict(out currentConflict))
|
||||
return false;
|
||||
|
||||
return IsSameConflict(currentConflict, changeInfo) ||
|
||||
IsSameConflict(currentConflict, metaChangeInfo);
|
||||
}
|
||||
|
||||
static bool IsSameConflict(
|
||||
MergeSolvedFileConflicts.CurrentConflict currentConflict,
|
||||
MergeChangeInfo changeInfo)
|
||||
{
|
||||
if (changeInfo == null)
|
||||
return false;
|
||||
|
||||
return currentConflict.MountId.Equals(changeInfo.GetMount().Id)
|
||||
&& currentConflict.ItemId == changeInfo.GetRevision().ItemId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5013a6f8fee1f2a49b06f75fc5a6ece4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,54 @@
|
|||
using Codice.Client.BaseCommands.Merge;
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal static class IsSolved
|
||||
{
|
||||
internal static bool Conflict(
|
||||
MergeChangeInfo changeInfo,
|
||||
MergeChangeInfo metaChangeInfo,
|
||||
MergeSolvedFileConflicts solvedFileConflicts)
|
||||
{
|
||||
if (IsDirectoryConflict(changeInfo))
|
||||
{
|
||||
if (metaChangeInfo == null)
|
||||
return IsDirectoryConflictResolved(changeInfo);
|
||||
|
||||
return IsDirectoryConflictResolved(changeInfo) &&
|
||||
IsDirectoryConflictResolved(metaChangeInfo);
|
||||
}
|
||||
|
||||
if (metaChangeInfo == null)
|
||||
{
|
||||
return IsFileConflictResolved(
|
||||
changeInfo, solvedFileConflicts);
|
||||
}
|
||||
|
||||
return IsFileConflictResolved(changeInfo, solvedFileConflicts) &&
|
||||
IsFileConflictResolved(metaChangeInfo, solvedFileConflicts);
|
||||
}
|
||||
|
||||
static bool IsFileConflictResolved(
|
||||
MergeChangeInfo changeInfo,
|
||||
MergeSolvedFileConflicts solvedFileConflicts)
|
||||
{
|
||||
if (solvedFileConflicts == null)
|
||||
return false;
|
||||
|
||||
return solvedFileConflicts.IsResolved(
|
||||
changeInfo.GetMount().Id,
|
||||
changeInfo.GetRevision().ItemId);
|
||||
}
|
||||
|
||||
static bool IsDirectoryConflictResolved(MergeChangeInfo changeInfo)
|
||||
{
|
||||
return changeInfo.DirectoryConflict.IsResolved();
|
||||
}
|
||||
|
||||
static bool IsDirectoryConflict(MergeChangeInfo changeInfo)
|
||||
{
|
||||
return (changeInfo.DirectoryConflict != null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d6db53f93de967c489902da57a7290a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,182 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Developer
|
||||
{
|
||||
internal class UnityIncomingChangesTree
|
||||
{
|
||||
internal static UnityIncomingChangesTree BuildIncomingChangeCategories(
|
||||
MergeChangesTree tree)
|
||||
{
|
||||
return new UnityIncomingChangesTree(tree);
|
||||
}
|
||||
|
||||
UnityIncomingChangesTree(
|
||||
MergeChangesTree tree)
|
||||
{
|
||||
mInnerTree = tree;
|
||||
|
||||
mMetaCache.Build(mInnerTree.GetNodes());
|
||||
}
|
||||
|
||||
internal List<MergeChangesCategory> GetNodes()
|
||||
{
|
||||
return mInnerTree.GetNodes();
|
||||
}
|
||||
|
||||
internal bool HasMeta(MergeChangeInfo changeInfo)
|
||||
{
|
||||
return mMetaCache.ContainsMeta(changeInfo);
|
||||
}
|
||||
|
||||
internal MergeChangeInfo GetMetaChange(MergeChangeInfo change)
|
||||
{
|
||||
return mMetaCache.GetExistingMeta(change);
|
||||
}
|
||||
|
||||
internal void FillWithMeta(List<MergeChangeInfo> changes)
|
||||
{
|
||||
changes.AddRange(
|
||||
mMetaCache.GetExistingMeta(changes));
|
||||
}
|
||||
|
||||
internal void Sort(string key, bool isAscending)
|
||||
{
|
||||
mInnerTree.Sort(key, isAscending);
|
||||
}
|
||||
|
||||
internal void ResolveUserNames(
|
||||
MergeChangesTree.ResolveUserName resolveUserName)
|
||||
{
|
||||
mInnerTree.ResolveUserNames(resolveUserName);
|
||||
}
|
||||
|
||||
MetaCache mMetaCache = new MetaCache();
|
||||
MergeChangesTree mInnerTree;
|
||||
|
||||
class MetaCache
|
||||
{
|
||||
internal bool ContainsMeta(MergeChangeInfo changeInfo)
|
||||
{
|
||||
string key = BuildKey.ForMetaChange(changeInfo);
|
||||
|
||||
return mCache.ContainsKey(key);
|
||||
}
|
||||
|
||||
internal MergeChangeInfo GetExistingMeta(MergeChangeInfo change)
|
||||
{
|
||||
MergeChangeInfo result;
|
||||
|
||||
if (!mCache.TryGetValue(BuildKey.ForMetaChange(change), out result))
|
||||
return null;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal List<MergeChangeInfo> GetExistingMeta(
|
||||
List<MergeChangeInfo> changes)
|
||||
{
|
||||
List<MergeChangeInfo> result = new List<MergeChangeInfo>();
|
||||
|
||||
foreach (MergeChangeInfo change in changes)
|
||||
{
|
||||
string key = BuildKey.ForMetaChange(change);
|
||||
|
||||
MergeChangeInfo metaChange;
|
||||
if (!mCache.TryGetValue(key, out metaChange))
|
||||
continue;
|
||||
|
||||
result.Add(metaChange);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void Build(List<MergeChangesCategory> incomingChangesCategories)
|
||||
{
|
||||
mCache.Clear();
|
||||
|
||||
foreach (MergeChangesCategory category in incomingChangesCategories)
|
||||
{
|
||||
ExtractMetaToCache(category, mCache);
|
||||
}
|
||||
}
|
||||
|
||||
static void ExtractMetaToCache(
|
||||
MergeChangesCategory category,
|
||||
Dictionary<string, MergeChangeInfo> cache)
|
||||
{
|
||||
List<MergeChangeInfo> changes = category.GetChanges();
|
||||
|
||||
HashSet<string> indexedKeys = BuildIndexedKeys(
|
||||
changes);
|
||||
|
||||
for (int i = changes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
MergeChangeInfo 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<MergeChangeInfo> changes)
|
||||
{
|
||||
HashSet<string> result = new HashSet<string>();
|
||||
|
||||
foreach (MergeChangeInfo change in changes)
|
||||
{
|
||||
if (MetaPath.IsMetaPath(change.GetPath()))
|
||||
continue;
|
||||
|
||||
result.Add(BuildKey.ForChange(change));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Dictionary<string, MergeChangeInfo> mCache =
|
||||
new Dictionary<string, MergeChangeInfo>();
|
||||
|
||||
static class BuildKey
|
||||
{
|
||||
internal static string ForChange(
|
||||
MergeChangeInfo change)
|
||||
{
|
||||
return BuildCacheKey(
|
||||
change.CategoryType,
|
||||
change.GetPath());
|
||||
}
|
||||
|
||||
internal static string ForMetaChange(
|
||||
MergeChangeInfo change)
|
||||
{
|
||||
return BuildCacheKey(
|
||||
change.CategoryType,
|
||||
MetaPath.GetMetaPath(change.GetPath()));
|
||||
}
|
||||
|
||||
internal static string BuildCacheKey(
|
||||
MergeChangesCategory.Type type,
|
||||
string path)
|
||||
{
|
||||
return string.Concat(type, ":", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b57672168ae882a4b8483a000638c433
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,89 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
using Codice.Client.Common;
|
||||
using PlasticGui;
|
||||
using PlasticGui.WorkspaceWindow.Merge;
|
||||
using Unity.PlasticSCM.Editor.UI;
|
||||
|
||||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges
|
||||
{
|
||||
internal static class DrawIncomingChangesOverview
|
||||
{
|
||||
internal static void For(
|
||||
int directoryConflictCount,
|
||||
int fileConflictCount,
|
||||
MergeViewTexts.ChangesToApplySummary changesSummary)
|
||||
{
|
||||
DrawItem(
|
||||
Images.GetConflictedIcon(),
|
||||
PlasticLocalization.Name.DirectoryConflictsTitleSingular,
|
||||
PlasticLocalization.Name.DirectoryConflictsTitlePlural,
|
||||
directoryConflictCount,
|
||||
0,
|
||||
false);
|
||||
|
||||
DrawItem(
|
||||
Images.GetConflictedIcon(),
|
||||
PlasticLocalization.Name.FileConflictsTitleSingular,
|
||||
PlasticLocalization.Name.FileConflictsTitlePlural,
|
||||
fileConflictCount,
|
||||
0,
|
||||
false);
|
||||
|
||||
DrawItem(
|
||||
Images.GetOutOfSyncIcon(),
|
||||
PlasticLocalization.Name.MergeChangesMadeInSourceOfMergeOverviewSingular,
|
||||
PlasticLocalization.Name.MergeChangesMadeInSourceOfMergeOverviewPlural,
|
||||
changesSummary.FilesToModify,
|
||||
changesSummary.SizeToModify,
|
||||
true);
|
||||
|
||||
DrawItem(
|
||||
Images.GetAddedLocalIcon(),
|
||||
PlasticLocalization.Name.MergeNewItemsToDownloadOverviewSingular,
|
||||
PlasticLocalization.Name.MergeNewItemsToDownloadOverviewPlural,
|
||||
changesSummary.FilesToAdd,
|
||||
changesSummary.SizeToAdd,
|
||||
true);
|
||||
|
||||
DrawItem(
|
||||
Images.GetDeletedRemoteIcon(),
|
||||
PlasticLocalization.Name.MergeDeletesToApplyOverviewSingular,
|
||||
PlasticLocalization.Name.MergeDeletesToApplyOverviewPlural,
|
||||
changesSummary.FilesToDelete,
|
||||
changesSummary.SizeToDelete,
|
||||
true);
|
||||
}
|
||||
|
||||
static void DrawItem(
|
||||
Texture2D icon,
|
||||
PlasticLocalization.Name singularLabel,
|
||||
PlasticLocalization.Name pluralLabel,
|
||||
int count,
|
||||
long size,
|
||||
bool showSize)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUIContent iconContent = new GUIContent(icon);
|
||||
GUILayout.Label(iconContent, GUILayout.Width(20f), GUILayout.Height(20f));
|
||||
|
||||
string label = PlasticLocalization.GetString(count > 1 ? pluralLabel : singularLabel);
|
||||
if (showSize)
|
||||
label = string.Format(label, count, SizeConverter.ConvertToSizeString(size));
|
||||
else
|
||||
label = string.Format(label, count);
|
||||
|
||||
GUIContent content = new GUIContent(label);
|
||||
GUILayout.Label(content, UnityStyles.IncomingChangesTab.ChangesToApplySummaryLabel);
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f8686930677b1f44d9ad7deab4888955
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 184012b39edc5c7468c23f916818433e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: faf2afd8696f4604f82f46b06b357f06
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d491adc3134c2ac4d9e3c61ed42a7ccd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4edf5537f8245134c8b023ab85d8e640
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 71c34e5fa319ca644b6806e573c33d88
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8c069d7fb0d30cf499458f0d9c9fe035
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 331d1c37d891f334390adb8324042856
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d287890d8b11cb7498506935c825b43d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9b917d42ad338ab4494088f574472998
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c0821447a35700c4280782d1092cf4c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7f2f2eb277e02054cbc5ccee904b593b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 349d4bc84d3b4fa48a1970539c06144c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6fb9548ec1290b943b7beca241c81e7d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
namespace Unity.PlasticSCM.Editor.Views.IncomingChanges
|
||||
{
|
||||
internal interface IIncomingChangesTab
|
||||
{
|
||||
bool IsVisible
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
void OnDisable();
|
||||
void Update();
|
||||
void OnGUI();
|
||||
void AutoRefresh();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a04ed4805f84fd4a8ceee51915ba39a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue