You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1126 lines
38 KiB
1126 lines
38 KiB
using System; |
|
using System.Linq; |
|
|
|
using UnityEditor; |
|
using UnityEngine; |
|
|
|
using Codice.Client.BaseCommands; |
|
using Codice.Client.BaseCommands.EventTracking; |
|
using Codice.Client.Common; |
|
using Codice.Client.Common.FsNodeReaders.Watcher; |
|
using Codice.Client.Common.Threading; |
|
using Codice.CM.Common; |
|
using Codice.LogWrapper; |
|
using GluonGui; |
|
using PlasticGui; |
|
using PlasticGui.WorkspaceWindow.NotificationBar; |
|
using Unity.PlasticSCM.Editor.AssetMenu; |
|
using Unity.PlasticSCM.Editor.AssetUtils; |
|
using Unity.PlasticSCM.Editor.Configuration; |
|
using Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome; |
|
using Unity.PlasticSCM.Editor.Inspector; |
|
using Unity.PlasticSCM.Editor.Tool; |
|
using Unity.PlasticSCM.Editor.UI; |
|
using Unity.PlasticSCM.Editor.UI.Avatar; |
|
using Unity.PlasticSCM.Editor.UI.Progress; |
|
using Unity.PlasticSCM.Editor.UI.StatusBar; |
|
using Unity.PlasticSCM.Editor.Views.CreateWorkspace; |
|
using Unity.PlasticSCM.Editor.Views.Welcome; |
|
using Unity.PlasticSCM.Editor.WebApi; |
|
|
|
using GluonCheckIncomingChanges = PlasticGui.Gluon.WorkspaceWindow.CheckIncomingChanges; |
|
using GluonNewIncomingChangesUpdater = PlasticGui.Gluon.WorkspaceWindow.NewIncomingChangesUpdater; |
|
using PlasticAssetModificationProcessor = Unity.PlasticSCM.Editor.AssetUtils.Processor.AssetModificationProcessor; |
|
|
|
namespace Unity.PlasticSCM.Editor |
|
{ |
|
internal class PlasticWindow : EditorWindow, |
|
PlasticGui.WorkspaceWindow.CheckIncomingChanges.IAutoRefreshIncomingChangesView, |
|
GluonCheckIncomingChanges.IAutoRefreshIncomingChangesView, |
|
CreateWorkspaceView.ICreateWorkspaceListener |
|
{ |
|
internal WorkspaceWindow WorkspaceWindowForTesting { get { return mWorkspaceWindow; } } |
|
internal ViewSwitcher ViewSwitcherForTesting { get { return mViewSwitcher; } } |
|
internal CmConnection CmConnectionForTesting { get { return CmConnection.Get(); } } |
|
|
|
internal void SetupWindowTitle(PlasticNotification.Status status) |
|
{ |
|
Texture windowIcon = PlasticNotification.GetIcon(status); |
|
|
|
// The titleContent icon does not update unless we also update the title text |
|
// Temporarily doing it by adding space characters |
|
string title = UnityConstants.PLASTIC_WINDOW_TITLE; |
|
title += String.Concat(Enumerable.Repeat(" ", (int)status)); |
|
|
|
titleContent = new GUIContent(title, windowIcon); |
|
} |
|
|
|
internal void DisableCollabIfEnabledWhenLoaded() |
|
{ |
|
mDisableCollabIfEnabledWhenLoaded = true; |
|
} |
|
|
|
void PlasticGui.WorkspaceWindow.CheckIncomingChanges.IAutoRefreshIncomingChangesView.IfVisible() |
|
{ |
|
mViewSwitcher.AutoRefreshIncomingChangesView(); |
|
} |
|
|
|
void GluonCheckIncomingChanges.IAutoRefreshIncomingChangesView.IfVisible() |
|
{ |
|
mViewSwitcher.AutoRefreshIncomingChangesView(); |
|
} |
|
|
|
void CreateWorkspaceView.ICreateWorkspaceListener.OnWorkspaceCreated( |
|
WorkspaceInfo wkInfo, bool isGluonMode) |
|
{ |
|
mWkInfo = wkInfo; |
|
mIsGluonMode = isGluonMode; |
|
mWelcomeView = null; |
|
|
|
PlasticPlugin.Enable(); |
|
|
|
if (mIsGluonMode) |
|
ConfigurePartialWorkspace.AsFullyChecked(mWkInfo); |
|
|
|
InitializePlastic(); |
|
Repaint(); |
|
} |
|
|
|
internal void RefreshWorkspaceUI() |
|
{ |
|
InitializePlastic(); |
|
Repaint(); |
|
|
|
OnFocus(); |
|
} |
|
|
|
void OnEnable() |
|
{ |
|
PlasticPlugin.Enable(); |
|
|
|
wantsMouseMove = true; |
|
|
|
if (mException != null) |
|
return; |
|
|
|
minSize = new Vector2( |
|
UnityConstants.PLASTIC_WINDOW_MIN_SIZE_WIDTH, |
|
UnityConstants.PLASTIC_WINDOW_MIN_SIZE_HEIGHT); |
|
|
|
SetupWindowTitle(PlasticNotification.Status.None); |
|
|
|
RegisterApplicationFocusHandlers(this); |
|
|
|
InitializePlastic(); |
|
} |
|
|
|
void OnDisable() |
|
{ |
|
// We need to disable FSWatcher because otherwise it hangs |
|
// when you move the window between monitors with different scale |
|
MonoFileSystemWatcher.IsEnabled = false; |
|
|
|
if (mException != null) |
|
return; |
|
|
|
if (mWkInfo == null) |
|
{ |
|
ClosePlasticWindow(this); |
|
return; |
|
} |
|
|
|
mViewSwitcher.OnDisable(); |
|
|
|
ClosePlasticWindow(this); |
|
} |
|
|
|
void OnDestroy() |
|
{ |
|
if (mException != null) |
|
return; |
|
|
|
if (mWkInfo == null) |
|
return; |
|
|
|
if (!mWorkspaceWindow.IsOperationInProgress()) |
|
return; |
|
|
|
bool bCloseWindow = GuiMessage.ShowQuestion( |
|
PlasticLocalization.GetString(PlasticLocalization.Name.OperationRunning), |
|
PlasticLocalization.GetString(PlasticLocalization.Name.ConfirmClosingRunningOperation), |
|
PlasticLocalization.GetString(PlasticLocalization.Name.YesButton)); |
|
|
|
if (bCloseWindow) |
|
return; |
|
|
|
mForceToOpen = true; |
|
ShowPlasticWindow(this); |
|
} |
|
|
|
void OnFocus() |
|
{ |
|
if (mException != null) |
|
return; |
|
|
|
if (mWkInfo == null) |
|
return; |
|
|
|
// We don't want to auto-refresh the views when the window |
|
// is focused due to a right mouse button click because |
|
// if there is no internet connection a dialog appears and |
|
// it prevents being able to open the context menu in order |
|
// to close the Plastic SCM window |
|
if (Mouse.IsRightMouseButtonPressed(Event.current)) |
|
return; |
|
|
|
mViewSwitcher.AutoRefreshPendingChangesView(); |
|
mViewSwitcher.AutoRefreshIncomingChangesView(); |
|
} |
|
|
|
void OnGUI() |
|
{ |
|
if (mException != null) |
|
{ |
|
DoExceptionErrorArea(); |
|
return; |
|
} |
|
|
|
try |
|
{ |
|
// IMPORTANT: disable collab (if needed) |
|
// must be executed before the next if statement |
|
// where we check if collab is enabled |
|
if (mDisableCollabIfEnabledWhenLoaded) |
|
{ |
|
mDisableCollabIfEnabledWhenLoaded = false; |
|
DisableCollabIfEnabled(ProjectPath.FromApplicationDataPath( |
|
ApplicationDataPath.Get())); |
|
} |
|
|
|
if (CollabPlugin.IsEnabled()) |
|
{ |
|
// execute Close() once after all inspectors update |
|
// to avoid our window to be drawn in back color |
|
EditorApplication.delayCall = Close; |
|
return; |
|
} |
|
|
|
bool isPlasticExeAvailable = IsExeAvailable.ForMode(mIsGluonMode); |
|
bool clientNeedsConfiguration = UnityConfigurationChecker.NeedsConfiguration(); |
|
|
|
var welcomeView = GetWelcomeView(); |
|
|
|
if (clientNeedsConfiguration && welcomeView.autoLoginState == AutoLogin.State.Off) |
|
{ |
|
welcomeView.autoLoginState = AutoLogin.State.Started; |
|
} |
|
|
|
if (welcomeView.autoLoginState == AutoLogin.State.OrganizationChoosed) |
|
{ |
|
OnEnable(); |
|
welcomeView.autoLoginState = AutoLogin.State.InitializingPlastic; |
|
} |
|
|
|
if (NeedsToDisplayWelcomeView(clientNeedsConfiguration, mWkInfo)) |
|
{ |
|
welcomeView.OnGUI(clientNeedsConfiguration); |
|
return; |
|
} |
|
|
|
//TODO: Codice - beta: hide the switcher until the update dialog is implemented |
|
//DrawGuiModeSwitcher.ForMode( |
|
// isGluonMode, plasticClient, changesTreeView, editorWindow); |
|
|
|
DoTabToolbar( |
|
isPlasticExeAvailable, |
|
mWkInfo, |
|
mViewSwitcher, |
|
mShowDownloadPlasticExeWindow, |
|
mProcessExecutor, |
|
mIsGluonMode); |
|
|
|
mViewSwitcher.TabViewGUI(); |
|
|
|
if (mWorkspaceWindow.IsOperationInProgress()) |
|
DrawProgressForOperations.For( |
|
mWorkspaceWindow, mWorkspaceWindow.Progress, |
|
position.width); |
|
|
|
mStatusBar.OnGUI( |
|
mWkInfo, |
|
mWorkspaceWindow, |
|
mViewSwitcher, |
|
mViewSwitcher, |
|
mIncomingChangesNotifier, |
|
mIsGluonMode); |
|
} |
|
catch (Exception ex) |
|
{ |
|
if (IsExitGUIException(ex)) |
|
throw; |
|
|
|
GUI.enabled = true; |
|
|
|
if (IsIMGUIPaintException(ex)) |
|
{ |
|
ExceptionsHandler.LogException("PlasticWindow", ex); |
|
return; |
|
} |
|
|
|
mException = ex; |
|
|
|
DoExceptionErrorArea(); |
|
|
|
ExceptionsHandler.HandleException("OnGUI", ex); |
|
} |
|
} |
|
|
|
void Update() |
|
{ |
|
if (mException != null) |
|
return; |
|
|
|
if (mWkInfo == null) |
|
return; |
|
|
|
try |
|
{ |
|
double currentUpdateTime = EditorApplication.timeSinceStartup; |
|
double elapsedSeconds = currentUpdateTime - mLastUpdateTime; |
|
|
|
mViewSwitcher.Update(); |
|
mWorkspaceWindow.OnParentUpdated(elapsedSeconds); |
|
|
|
if (mWelcomeView != null) |
|
mWelcomeView.Update(); |
|
|
|
mLastUpdateTime = currentUpdateTime; |
|
} |
|
catch (Exception ex) |
|
{ |
|
mException = ex; |
|
|
|
ExceptionsHandler.HandleException("Update", ex); |
|
} |
|
} |
|
|
|
internal void InitializePlastic() |
|
{ |
|
if (mForceToOpen) |
|
{ |
|
mForceToOpen = false; |
|
return; |
|
} |
|
|
|
try |
|
{ |
|
if (UnityConfigurationChecker.NeedsConfiguration()) |
|
return; |
|
|
|
mWkInfo = FindWorkspace.InfoForApplicationPath( |
|
ApplicationDataPath.Get(), PlasticGui.Plastic.API); |
|
|
|
if (mWkInfo == null) |
|
return; |
|
|
|
PlasticPlugin.EnableForWorkspace(); |
|
|
|
SetupCloudProjectIdIfNeeded(mWkInfo, PlasticGui.Plastic.API); |
|
|
|
DisableVCSIfEnabled(mWkInfo.ClientPath); |
|
|
|
mIsGluonMode = PlasticGui.Plastic.API.IsGluonWorkspace(mWkInfo); |
|
|
|
ViewHost viewHost = new ViewHost(); |
|
|
|
mStatusBar = new StatusBar(); |
|
|
|
mViewSwitcher = new ViewSwitcher( |
|
mWkInfo, |
|
viewHost, |
|
mIsGluonMode, |
|
PlasticPlugin.AssetStatusCache, |
|
mShowDownloadPlasticExeWindow, |
|
mProcessExecutor, |
|
PlasticPlugin.WorkspaceOperationsMonitor, |
|
mStatusBar, |
|
this); |
|
|
|
InitializeNewIncomingChanges(mWkInfo, mIsGluonMode, mViewSwitcher); |
|
|
|
mCooldownAutoRefreshPendingChangesAction = new CooldownWindowDelayer( |
|
mViewSwitcher.AutoRefreshPendingChangesView, |
|
UnityConstants.AUTO_REFRESH_PENDING_CHANGES_DELAYED_INTERVAL); |
|
|
|
mWorkspaceWindow = new WorkspaceWindow( |
|
mWkInfo, |
|
viewHost, |
|
mViewSwitcher, |
|
mViewSwitcher, |
|
mDeveloperNewIncomingChangesUpdater, |
|
this); |
|
|
|
mViewSwitcher.SetWorkspaceWindow(mWorkspaceWindow); |
|
mViewSwitcher.ShowInitialView(); |
|
|
|
PlasticPlugin.WorkspaceOperationsMonitor.RegisterWindow( |
|
mWorkspaceWindow, |
|
viewHost, |
|
mDeveloperNewIncomingChangesUpdater); |
|
|
|
UnityStyles.Initialize(Repaint); |
|
|
|
AssetMenuItems.BuildOperations( |
|
mWkInfo, |
|
mWorkspaceWindow, |
|
mViewSwitcher, |
|
mViewSwitcher, |
|
viewHost, |
|
mDeveloperNewIncomingChangesUpdater, |
|
PlasticPlugin.AssetStatusCache, |
|
mViewSwitcher, |
|
mViewSwitcher, |
|
mShowDownloadPlasticExeWindow, |
|
this, |
|
mIsGluonMode); |
|
|
|
DrawInspectorOperations.BuildOperations( |
|
mWkInfo, |
|
mWorkspaceWindow, |
|
mViewSwitcher, |
|
mViewSwitcher, |
|
viewHost, |
|
mDeveloperNewIncomingChangesUpdater, |
|
PlasticPlugin.AssetStatusCache, |
|
mViewSwitcher, |
|
mViewSwitcher, |
|
mShowDownloadPlasticExeWindow, |
|
this, |
|
mIsGluonMode); |
|
|
|
mLastUpdateTime = EditorApplication.timeSinceStartup; |
|
|
|
mViewSwitcher.ShowBranchesViewIfNeeded(); |
|
|
|
if (!EditionToken.IsCloudEdition()) |
|
return; |
|
|
|
InitializeNotificationBarUpdater( |
|
mWkInfo, mStatusBar.NotificationBar); |
|
} |
|
catch (Exception ex) |
|
{ |
|
mException = ex; |
|
|
|
ExceptionsHandler.HandleException("InitializePlastic", ex); |
|
} |
|
} |
|
|
|
void InitializeNewIncomingChanges( |
|
WorkspaceInfo wkInfo, |
|
bool bIsGluonMode, |
|
ViewSwitcher viewSwitcher) |
|
{ |
|
if (bIsGluonMode) |
|
{ |
|
Gluon.IncomingChangesNotifier gluonNotifier = |
|
new Gluon.IncomingChangesNotifier(this); |
|
mGluonNewIncomingChangesUpdater = |
|
NewIncomingChanges.BuildUpdaterForGluon( |
|
wkInfo, viewSwitcher, gluonNotifier, this, gluonNotifier, |
|
new GluonCheckIncomingChanges.CalculateIncomingChanges()); |
|
mIncomingChangesNotifier = gluonNotifier; |
|
return; |
|
} |
|
|
|
Developer.IncomingChangesNotifier developerNotifier = |
|
new Developer.IncomingChangesNotifier(this); |
|
mDeveloperNewIncomingChangesUpdater = |
|
NewIncomingChanges.BuildUpdaterForDeveloper( |
|
wkInfo, viewSwitcher, developerNotifier, |
|
this, developerNotifier); |
|
mIncomingChangesNotifier = developerNotifier; |
|
} |
|
|
|
void InitializeNotificationBarUpdater( |
|
WorkspaceInfo wkInfo, |
|
INotificationBar notificationBar) |
|
{ |
|
mNotificationBarUpdater = new NotificationBarUpdater( |
|
notificationBar, |
|
PlasticGui.Plastic.WebRestAPI, |
|
new UnityPlasticTimerBuilder(), |
|
new NotificationBarUpdater.NotificationBarConfig(), |
|
ScreenResolution.Get()); |
|
mNotificationBarUpdater.Start(); |
|
mNotificationBarUpdater.SetWorkspace(wkInfo); |
|
} |
|
|
|
void OnApplicationActivated() |
|
{ |
|
if (mException != null) |
|
return; |
|
|
|
Reload.IfWorkspaceConfigChanged( |
|
PlasticGui.Plastic.API, mWkInfo, mIsGluonMode, |
|
ExecuteFullReload); |
|
|
|
if (mWkInfo == null) |
|
return; |
|
|
|
((IWorkspaceWindow)mWorkspaceWindow).UpdateTitle(); |
|
|
|
NewIncomingChanges.LaunchUpdater( |
|
mDeveloperNewIncomingChangesUpdater, |
|
mGluonNewIncomingChangesUpdater); |
|
|
|
// When Unity Editor window is activated it writes some files to its Temp folder. |
|
// This causes the fswatcher to process those events. |
|
// We need to wait until the fswatcher finishes processing the events, |
|
// otherwise the NewChangesInWk method will return TRUE, causing |
|
// the pending changes view to unwanted auto-refresh. |
|
// So, we need to delay the auto-refresh call in order |
|
// to give the fswatcher enough time to process the events. |
|
// Note that the OnFocus event is not affected by this issue. |
|
mCooldownAutoRefreshPendingChangesAction.Ping(); |
|
|
|
mViewSwitcher.AutoRefreshIncomingChangesView(); |
|
} |
|
|
|
void OnApplicationDeactivated() |
|
{ |
|
if (mException != null) |
|
return; |
|
|
|
if (mWkInfo == null) |
|
return; |
|
|
|
NewIncomingChanges.StopUpdater( |
|
mDeveloperNewIncomingChangesUpdater, |
|
mGluonNewIncomingChangesUpdater); |
|
} |
|
|
|
void ExecuteFullReload() |
|
{ |
|
mException = null; |
|
|
|
DisposeNewIncomingChanges(this); |
|
|
|
DisposeNotificationBarUpdater(this); |
|
|
|
InitializePlastic(); |
|
} |
|
|
|
void DoExceptionErrorArea() |
|
{ |
|
string labelText = PlasticLocalization.GetString( |
|
PlasticLocalization.Name.UnexpectedError); |
|
|
|
string buttonText = PlasticLocalization.GetString( |
|
PlasticLocalization.Name.ReloadButton); |
|
|
|
DrawActionHelpBox.For( |
|
Images.GetErrorDialogIcon(), labelText, buttonText, |
|
ExecuteFullReload); |
|
} |
|
|
|
internal WelcomeView GetWelcomeView() |
|
{ |
|
if (mWelcomeView != null) |
|
return mWelcomeView; |
|
|
|
mWelcomeView = new WelcomeView( |
|
this, |
|
this, |
|
PlasticGui.Plastic.API, |
|
PlasticGui.Plastic.WebRestAPI, |
|
CmConnection.Get()); |
|
|
|
return mWelcomeView; |
|
} |
|
|
|
static void DoSearchField(ViewSwitcher viewSwitcher) |
|
{ |
|
if (viewSwitcher.IsViewSelected(ViewSwitcher.SelectedTab.PendingChanges)) |
|
{ |
|
viewSwitcher.PendingChangesTab.DrawSearchFieldForPendingChangesTab(); |
|
return; |
|
} |
|
if (viewSwitcher.IsViewSelected(ViewSwitcher.SelectedTab.Changesets)) |
|
{ |
|
viewSwitcher.ChangesetsTab.DrawSearchFieldForChangesetsTab(); |
|
return; |
|
} |
|
if (viewSwitcher.IsViewSelected(ViewSwitcher.SelectedTab.History)) |
|
{ |
|
viewSwitcher.HistoryTab.DrawSearchFieldForHistoryTab(); |
|
return; |
|
} |
|
if (viewSwitcher.IsViewSelected(ViewSwitcher.SelectedTab.Branches)) |
|
{ |
|
viewSwitcher.BranchesTab.DrawSearchFieldForBranchesTab(); |
|
return; |
|
} |
|
} |
|
|
|
static void DoTabToolbar( |
|
bool isPlasticExeAvailable, |
|
WorkspaceInfo workspaceInfo, |
|
ViewSwitcher viewSwitcher, |
|
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow, |
|
LaunchTool.IProcessExecutor processExecutor, |
|
bool isGluonMode) |
|
{ |
|
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); |
|
|
|
viewSwitcher.TabButtonsGUI(); |
|
|
|
GUILayout.FlexibleSpace(); |
|
|
|
DoSearchField(viewSwitcher); |
|
|
|
DoLaunchButtons( |
|
isPlasticExeAvailable, |
|
workspaceInfo, |
|
viewSwitcher, |
|
showDownloadPlasticExeWindow, |
|
processExecutor, |
|
isGluonMode); |
|
|
|
EditorGUILayout.EndHorizontal(); |
|
} |
|
|
|
static void OpenBranchListViewAndSendEvent( |
|
WorkspaceInfo wkInfo, |
|
ViewSwitcher viewSwitcher) |
|
{ |
|
viewSwitcher.ShowBranchesView(); |
|
TrackFeatureUseEvent.For( |
|
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo), |
|
TrackFeatureUseEvent.Features.OpenBranchesView); |
|
} |
|
|
|
static void ShowBranchesContextMenu( |
|
WorkspaceInfo wkInfo, |
|
ViewSwitcher viewSwitcher, |
|
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow, |
|
LaunchTool.IProcessExecutor processExecutor, |
|
bool isGluonMode) |
|
{ |
|
GenericMenu menu = new GenericMenu(); |
|
|
|
string branchesListView = PlasticLocalization.GetString( |
|
PlasticLocalization.Name.Branches); |
|
|
|
menu.AddItem( |
|
new GUIContent(branchesListView), |
|
false, |
|
() => OpenBranchListViewAndSendEvent(wkInfo, viewSwitcher)); |
|
|
|
string branchExplorer = PlasticLocalization.GetString( |
|
PlasticLocalization.Name.BranchExplorerMenu); |
|
|
|
menu.AddItem( |
|
new GUIContent(branchExplorer), |
|
false, |
|
() => LaunchTool.OpenBranchExplorer( |
|
showDownloadPlasticExeWindow, |
|
processExecutor, |
|
wkInfo, |
|
isGluonMode)); |
|
|
|
menu.ShowAsContext(); |
|
} |
|
|
|
static void ShowSettingsContextMenu( |
|
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow, |
|
LaunchTool.IProcessExecutor processExecutor, |
|
WorkspaceInfo wkInfo, |
|
bool isGluonMode) |
|
{ |
|
GenericMenu menu = new GenericMenu(); |
|
|
|
string openToolText = isGluonMode ? |
|
PlasticLocalization.GetString(PlasticLocalization.Name.LaunchGluonButton) : |
|
PlasticLocalization.GetString(PlasticLocalization.Name.LaunchPlasticButton); |
|
|
|
menu.AddItem( |
|
new GUIContent(openToolText), |
|
false, |
|
() => LaunchTool.OpenGUIForMode( |
|
showDownloadPlasticExeWindow, |
|
processExecutor, |
|
wkInfo, |
|
isGluonMode)); |
|
|
|
if (EditionToken.IsCloudEdition()) |
|
{ |
|
menu.AddItem(new GUIContent( |
|
PlasticLocalization.GetString( |
|
PlasticLocalization.Name.InviteMembers)), |
|
false, |
|
InviteMemberButton_clicked, |
|
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo)); |
|
} |
|
|
|
menu.AddSeparator(""); |
|
|
|
menu.AddItem( |
|
new GUIContent( |
|
PlasticLocalization.GetString( |
|
PlasticLocalization.Name.Options)), |
|
false, |
|
() => SettingsService.OpenProjectSettings(UnityConstants.PROJECT_SETTINGS_TAB_PATH)); |
|
|
|
// If the user has the simplified UI key of type .txt in the Assets folder |
|
// TODO: Remove when Simplified UI is complete |
|
if (AssetDatabase.FindAssets("simplifieduikey t:textasset", new[] { "Assets" }).Any()) |
|
menu.AddItem(new GUIContent("Try Simplified UI"), |
|
false, |
|
TrySimplifiedUIButton_Clicked, |
|
null); |
|
|
|
//TODO: Localization |
|
menu.AddItem( |
|
new GUIContent(PlasticAssetModificationProcessor.ForceCheckout ? |
|
PlasticLocalization.GetString(PlasticLocalization.Name.DisableForcedCheckout) : |
|
PlasticLocalization.GetString(PlasticLocalization.Name.EnableForcedCheckout)), |
|
false, |
|
ForceCheckout_Clicked, |
|
null); |
|
|
|
menu.ShowAsContext(); |
|
} |
|
|
|
static void DoLaunchButtons( |
|
bool isPlasticExeAvailable, |
|
WorkspaceInfo wkInfo, |
|
ViewSwitcher viewSwitcher, |
|
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow, |
|
LaunchTool.IProcessExecutor processExecutor, |
|
bool isGluonMode) |
|
{ |
|
//TODO: Codice - beta: hide the diff button until the behavior is implemented |
|
/*GUILayout.Button(PlasticLocalization.GetString( |
|
PlasticLocalization.Name.DiffWindowMenuItemDiff), |
|
EditorStyles.toolbarButton, |
|
GUILayout.Width(UnityConstants.REGULAR_BUTTON_WIDTH));*/ |
|
|
|
if (viewSwitcher.IsViewSelected(ViewSwitcher.SelectedTab.Changesets)) |
|
{ |
|
viewSwitcher.ChangesetsTab.DrawDateFilter(); |
|
} |
|
if (viewSwitcher.IsViewSelected(ViewSwitcher.SelectedTab.Branches)) |
|
{ |
|
viewSwitcher.BranchesTab.DrawDateFilter(); |
|
} |
|
|
|
Texture refreshIcon = Images.GetRefreshIcon(); |
|
string refreshIconTooltip = PlasticLocalization.GetString( |
|
PlasticLocalization.Name.RefreshButton); |
|
|
|
if (DrawLaunchButton(refreshIcon, refreshIconTooltip)) |
|
{ |
|
viewSwitcher.RefreshSelectedView(); |
|
} |
|
|
|
if (viewSwitcher.IsViewSelected(ViewSwitcher.SelectedTab.PendingChanges)) |
|
{ |
|
Texture2D icon = Images.GetUndoIcon(); |
|
string tooltip = PlasticLocalization.GetString( |
|
PlasticLocalization.Name.UndoSelectedChanges); |
|
|
|
if (DrawLaunchButton(icon, tooltip)) |
|
{ |
|
TrackFeatureUseEvent.For( |
|
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo), |
|
TrackFeatureUseEvent.Features.UndoIconButton); |
|
|
|
viewSwitcher.PendingChangesTab.UndoForMode(wkInfo, isGluonMode); |
|
} |
|
} |
|
|
|
if (isGluonMode) |
|
{ |
|
string label = PlasticLocalization.GetString(PlasticLocalization.Name.ConfigureGluon); |
|
if (DrawActionButton.For(label)) |
|
LaunchTool.OpenWorkspaceConfiguration( |
|
showDownloadPlasticExeWindow, |
|
processExecutor, |
|
wkInfo, |
|
isGluonMode); |
|
} |
|
else |
|
{ |
|
Texture2D icon = Images.GetBranchIcon(); |
|
string tooltip = PlasticLocalization.GetString(PlasticLocalization.Name.Branches); |
|
if (DrawLaunchButton(icon, tooltip)) |
|
{ |
|
ShowBranchesContextMenu( |
|
wkInfo, |
|
viewSwitcher, |
|
showDownloadPlasticExeWindow, |
|
processExecutor, |
|
isGluonMode); |
|
} |
|
} |
|
|
|
//TODO: Add settings button tooltip localization |
|
if (DrawLaunchButton(Images.GetSettingsIcon(), string.Empty)) |
|
{ |
|
ShowSettingsContextMenu( |
|
showDownloadPlasticExeWindow, |
|
processExecutor, |
|
wkInfo, |
|
isGluonMode); |
|
} |
|
} |
|
|
|
static bool DrawLaunchButton(Texture icon, string tooltip) |
|
{ |
|
return GUILayout.Button( |
|
new GUIContent(icon, tooltip), |
|
EditorStyles.toolbarButton, |
|
GUILayout.Width(26)); |
|
} |
|
|
|
static void InviteMemberButton_clicked(object obj) |
|
{ |
|
RepositorySpec repSpec = (RepositorySpec)obj; |
|
|
|
string organizationName = ServerOrganizationParser. |
|
GetOrganizationFromServer(repSpec.Server); |
|
|
|
CurrentUserAdminCheckResponse response = null; |
|
|
|
IThreadWaiter waiter = ThreadWaiter.GetWaiter(50); |
|
waiter.Execute( |
|
/*threadOperationDelegate*/ |
|
delegate |
|
{ |
|
ServerProfile serverProfile = CmConnection.Get(). |
|
GetProfileManager().GetProfileForServer(repSpec.Server); |
|
|
|
string authToken = serverProfile != null ? |
|
CmConnection.Get(). |
|
BuildWebApiTokenForCloudEditionForUser( |
|
serverProfile.Server, |
|
serverProfile.GetSEIDWorkingMode(), |
|
serverProfile.SecurityConfig): |
|
CmConnection.Get(). |
|
BuildWebApiTokenForCloudEditionForUser( |
|
repSpec.Server, |
|
ClientConfig.Get().GetSEIDWorkingMode(), |
|
ClientConfig.Get().GetSecurityConfig()); |
|
|
|
if (string.IsNullOrEmpty(authToken)) |
|
authToken = CmConnection.Get(). |
|
BuildWebApiTokenForCloudEditionDefaultUser(); |
|
|
|
if (string.IsNullOrEmpty(authToken)) |
|
{ |
|
return; |
|
} |
|
|
|
response = WebRestApiClient.PlasticScm.IsUserAdmin( |
|
organizationName, |
|
authToken); |
|
}, |
|
/*afterOperationDelegate*/ |
|
delegate |
|
{ |
|
if (waiter.Exception != null) |
|
{ |
|
ExceptionsHandler.LogException( |
|
"IsUserAdmin", |
|
waiter.Exception); |
|
|
|
OpenCloudDashboardUsersGroupsUrl(organizationName); |
|
return; |
|
} |
|
|
|
if (response == null) |
|
{ |
|
mLog.DebugFormat( |
|
"Error checking if the user is the organization admin for {0}", |
|
organizationName); |
|
|
|
OpenCloudDashboardUsersGroupsUrl(organizationName); |
|
return; |
|
} |
|
|
|
if (response.Error != null) |
|
{ |
|
mLog.DebugFormat( |
|
"Error checking if the user is the organization admin: {0}", |
|
string.Format("Unable to get IsUserAdminResponse: {0} [code {1}]", |
|
response.Error.Message, |
|
response.Error.ErrorCode)); |
|
|
|
OpenCloudDashboardUsersGroupsUrl(organizationName); |
|
return; |
|
} |
|
|
|
if (response.IsCurrentUserAdmin) |
|
{ |
|
OpenCloudDashboardUsersGroupsUrl(response.OrganizationName); |
|
return; |
|
} |
|
|
|
GuiMessage.ShowInformation( |
|
PlasticLocalization.GetString(PlasticLocalization.Name.InviteMembersTitle), |
|
PlasticLocalization.GetString(PlasticLocalization.Name.InviteMembersMessage)); |
|
}); |
|
} |
|
|
|
static void OpenCloudDashboardUsersGroupsUrl(string organization) |
|
{ |
|
Application.OpenURL("https://www.plasticscm.com/dashboard/cloud/" + |
|
organization + |
|
"/users-and-groups"); |
|
} |
|
|
|
static void TrySimplifiedUIButton_Clicked(object obj) |
|
{ |
|
PlasticSCMWindow.ShowWindow(); |
|
} |
|
|
|
static void ForceCheckout_Clicked(object obj) |
|
{ |
|
PlasticAssetModificationProcessor.SetForceCheckoutOption( |
|
!PlasticAssetModificationProcessor.ForceCheckout); |
|
} |
|
|
|
static void SetupCloudProjectIdIfNeeded( |
|
WorkspaceInfo wkInfo, |
|
IPlasticAPI plasticApi) |
|
{ |
|
if (SetupCloudProjectId.HasCloudProjectId()) |
|
return; |
|
|
|
SetupCloudProjectId.ForWorkspace(wkInfo, plasticApi); |
|
|
|
mLog.DebugFormat("Setup CloudProjectId on Project: {0}", |
|
wkInfo.ClientPath); |
|
} |
|
|
|
static void DisableVCSIfEnabled(string projectPath) |
|
{ |
|
if (!VCSPlugin.IsEnabled()) |
|
return; |
|
|
|
VCSPlugin.Disable(); |
|
|
|
mLog.DebugFormat("Disabled VCS Plugin on Project: {0}", |
|
projectPath); |
|
} |
|
|
|
static void DisposeNewIncomingChanges(PlasticWindow window) |
|
{ |
|
NewIncomingChanges.DisposeUpdater( |
|
window.mDeveloperNewIncomingChangesUpdater, |
|
window.mGluonNewIncomingChangesUpdater); |
|
|
|
window.mDeveloperNewIncomingChangesUpdater = null; |
|
window.mGluonNewIncomingChangesUpdater = null; |
|
} |
|
|
|
static void DisposeNotificationBarUpdater(PlasticWindow window) |
|
{ |
|
if (window.mNotificationBarUpdater == null) |
|
return; |
|
|
|
window.mNotificationBarUpdater.Dispose(); |
|
window.mNotificationBarUpdater = null; |
|
} |
|
|
|
static void RegisterApplicationFocusHandlers(PlasticWindow window) |
|
{ |
|
EditorWindowFocus.OnApplicationActivated += window.OnApplicationActivated; |
|
EditorWindowFocus.OnApplicationDeactivated += window.OnApplicationDeactivated; |
|
} |
|
|
|
static void UnRegisterApplicationFocusHandlers(PlasticWindow window) |
|
{ |
|
EditorWindowFocus.OnApplicationActivated -= window.OnApplicationActivated; |
|
EditorWindowFocus.OnApplicationDeactivated -= window.OnApplicationDeactivated; |
|
} |
|
|
|
static bool IsExitGUIException(Exception ex) |
|
{ |
|
return ex is ExitGUIException; |
|
} |
|
|
|
static bool IsIMGUIPaintException(Exception ex) |
|
{ |
|
if (!(ex is ArgumentException)) |
|
return false; |
|
|
|
return ex.Message.StartsWith("Getting control") && |
|
ex.Message.Contains("controls when doing repaint"); |
|
} |
|
|
|
static void ClosePlasticWindow(PlasticWindow window) |
|
{ |
|
UnRegisterApplicationFocusHandlers(window); |
|
|
|
if (PlasticPlugin.WorkspaceOperationsMonitor != null) |
|
PlasticPlugin.WorkspaceOperationsMonitor.UnRegisterWindow(); |
|
|
|
DisposeNewIncomingChanges(window); |
|
|
|
DisposeNotificationBarUpdater(window); |
|
|
|
AvatarImages.Dispose(); |
|
} |
|
|
|
static void ShowPlasticWindow(PlasticWindow window) |
|
{ |
|
EditorWindow dockWindow = FindEditorWindow.ToDock<PlasticWindow>(); |
|
|
|
PlasticWindow newPlasticWindow = InstantiateFrom(window); |
|
|
|
if (DockEditorWindow.IsAvailable()) |
|
DockEditorWindow.To(dockWindow, newPlasticWindow); |
|
|
|
newPlasticWindow.Show(); |
|
|
|
newPlasticWindow.Focus(); |
|
} |
|
|
|
static bool NeedsToDisplayWelcomeView( |
|
bool clientNeedsConfiguration, |
|
WorkspaceInfo wkInfo) |
|
{ |
|
if (clientNeedsConfiguration) |
|
return true; |
|
|
|
if (wkInfo == null) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
static void DisableCollabIfEnabled(string projectPath) |
|
{ |
|
if (!CollabPlugin.IsEnabled()) |
|
return; |
|
|
|
CollabPlugin.Disable(); |
|
|
|
mLog.DebugFormat("Disabled Collab Plugin on Project: {0}", |
|
projectPath); |
|
} |
|
|
|
static PlasticWindow InstantiateFrom(PlasticWindow window) |
|
{ |
|
PlasticWindow result = Instantiate(window); |
|
result.mWkInfo = window.mWkInfo; |
|
result.mWorkspaceWindow = window.mWorkspaceWindow; |
|
result.mViewSwitcher = window.mViewSwitcher; |
|
result.mCooldownAutoRefreshPendingChangesAction = window.mCooldownAutoRefreshPendingChangesAction; |
|
result.mDeveloperNewIncomingChangesUpdater = window.mDeveloperNewIncomingChangesUpdater; |
|
result.mGluonNewIncomingChangesUpdater = window.mGluonNewIncomingChangesUpdater; |
|
result.mException = window.mException; |
|
result.mLastUpdateTime = window.mLastUpdateTime; |
|
result.mIsGluonMode = window.mIsGluonMode; |
|
result.mIncomingChangesNotifier = window.mIncomingChangesNotifier; |
|
result.mStatusBar = window.mStatusBar; |
|
result.mWelcomeView = window.mWelcomeView; |
|
result.mNotificationBarUpdater = window.mNotificationBarUpdater; |
|
return result; |
|
} |
|
|
|
internal PlasticProjectSettingsProvider.IAutoRefreshView GetPendingChangesView() |
|
{ |
|
return mViewSwitcher != null ? mViewSwitcher.PendingChangesTab : null; |
|
} |
|
|
|
static class Reload |
|
{ |
|
internal static void IfWorkspaceConfigChanged( |
|
IPlasticAPI plasticApi, |
|
WorkspaceInfo lastWkInfo, |
|
bool lastIsGluonMode, |
|
Action reloadAction) |
|
{ |
|
string applicationPath = ApplicationDataPath.Get(); |
|
|
|
bool isGluonMode = false; |
|
WorkspaceInfo wkInfo = null; |
|
|
|
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10); |
|
waiter.Execute( |
|
/*threadOperationDelegate*/ delegate |
|
{ |
|
wkInfo = FindWorkspace. |
|
InfoForApplicationPath(applicationPath, plasticApi); |
|
|
|
if (wkInfo != null) |
|
isGluonMode = plasticApi.IsGluonWorkspace(wkInfo); |
|
}, |
|
/*afterOperationDelegate*/ delegate |
|
{ |
|
if (waiter.Exception != null) |
|
return; |
|
|
|
if (!IsWorkspaceConfigChanged( |
|
lastWkInfo, wkInfo, |
|
lastIsGluonMode, isGluonMode)) |
|
return; |
|
|
|
reloadAction(); |
|
}); |
|
} |
|
|
|
static bool IsWorkspaceConfigChanged( |
|
WorkspaceInfo lastWkInfo, |
|
WorkspaceInfo currentWkInfo, |
|
bool lastIsGluonMode, |
|
bool currentIsGluonMode) |
|
{ |
|
if (lastIsGluonMode != currentIsGluonMode) |
|
return true; |
|
|
|
if (lastWkInfo == null || currentWkInfo == null) |
|
return true; |
|
|
|
return !lastWkInfo.Equals(currentWkInfo); |
|
} |
|
} |
|
|
|
[SerializeField] |
|
bool mForceToOpen; |
|
|
|
[NonSerialized] |
|
WorkspaceInfo mWkInfo; |
|
|
|
Exception mException; |
|
|
|
internal IIncomingChangesNotifier mIncomingChangesNotifier; |
|
|
|
double mLastUpdateTime = 0f; |
|
|
|
CooldownWindowDelayer mCooldownAutoRefreshPendingChangesAction; |
|
internal ViewSwitcher mViewSwitcher; |
|
WelcomeView mWelcomeView; |
|
|
|
StatusBar mStatusBar; |
|
NotificationBarUpdater mNotificationBarUpdater; |
|
|
|
PlasticGui.WorkspaceWindow.NewIncomingChangesUpdater mDeveloperNewIncomingChangesUpdater; |
|
GluonNewIncomingChangesUpdater mGluonNewIncomingChangesUpdater; |
|
|
|
WorkspaceWindow mWorkspaceWindow; |
|
|
|
bool mIsGluonMode; |
|
bool mDisableCollabIfEnabledWhenLoaded; |
|
|
|
LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow = |
|
new LaunchTool.ShowDownloadPlasticExeWindow(); |
|
LaunchTool.IProcessExecutor mProcessExecutor = |
|
new LaunchTool.ProcessExecutor(); |
|
|
|
static readonly ILog mLog = LogManager.GetLogger("PlasticWindow"); |
|
} |
|
} |