A game about forced loneliness, made by TACStudios
at master 526 lines 18 kB view raw
1using System; 2using System.Collections.Generic; 3using System.IO; 4 5using UnityEditor; 6using UnityEditor.IMGUI.Controls; 7using UnityEngine; 8 9using Codice.Client.Commands; 10using Codice.Client.Common; 11using Codice.Client.Common.EventTracking; 12using Codice.Client.Common.Threading; 13using Codice.CM.Common; 14using Codice.CM.Common.Mount; 15using PlasticGui; 16using PlasticGui.WorkspaceWindow; 17using PlasticGui.WorkspaceWindow.BrowseRepository; 18using PlasticGui.WorkspaceWindow.Diff; 19using Unity.PlasticSCM.Editor.AssetUtils; 20using Unity.PlasticSCM.Editor.Tool; 21using Unity.PlasticSCM.Editor.UI; 22using Unity.PlasticSCM.Editor.UI.Progress; 23using Unity.PlasticSCM.Editor.UI.Tree; 24using Unity.PlasticSCM.Editor.Views.Diff.Dialogs; 25using Unity.PlasticSCM.Editor.Views.History; 26 27namespace Unity.PlasticSCM.Editor.Views.Diff 28{ 29 internal class DiffPanel : 30 IDiffTreeViewMenuOperations, 31 DiffTreeViewMenu.IMetaMenuOperations, 32 UndeleteClientDiffsOperation.IGetRestorePathDialog 33 { 34 internal DiffPanel( 35 WorkspaceInfo wkInfo, 36 IWorkspaceWindow workspaceWindow, 37 IRefreshView refreshView, 38 IViewSwitcher viewSwitcher, 39 IHistoryViewLauncher historyViewLauncher, 40 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow, 41 EditorWindow parentWindow, 42 bool isGluonMode) 43 { 44 mWkInfo = wkInfo; 45 mWorkspaceWindow = workspaceWindow; 46 mRefreshView = refreshView; 47 mViewSwitcher = viewSwitcher; 48 mHistoryViewLauncher = historyViewLauncher; 49 mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow; 50 mParentWindow = parentWindow; 51 mGuiMessage = new UnityPlasticGuiMessage(); 52 mIsGluonMode = isGluonMode; 53 54 BuildComponents(); 55 56 mProgressControls = new ProgressControlsForViews(); 57 } 58 59 internal void ClearInfo() 60 { 61 ClearData(); 62 63 mParentWindow.Repaint(); 64 } 65 66 internal void UpdateInfo( 67 MountPointWithPath mountWithPath, 68 ChangesetInfo csetInfo) 69 { 70 FillData(mountWithPath, csetInfo); 71 72 mParentWindow.Repaint(); 73 } 74 75 internal void OnEnable() 76 { 77 mSearchField.downOrUpArrowKeyPressed += 78 SearchField_OnDownOrUpArrowKeyPressed; 79 } 80 81 internal void OnDisable() 82 { 83 mSearchField.downOrUpArrowKeyPressed -= 84 SearchField_OnDownOrUpArrowKeyPressed; 85 } 86 87 internal void Update() 88 { 89 mProgressControls.UpdateProgress(mParentWindow); 90 } 91 92 internal void OnGUI() 93 { 94 EditorGUILayout.BeginVertical(); 95 96 DoActionsToolbar( 97 mDiffs, 98 mDiffsBranchResolver, 99 mProgressControls, 100 mIsSkipMergeTrackingButtonVisible, 101 mIsSkipMergeTrackingButtonChecked, 102 mSearchField, 103 mDiffTreeView); 104 105 DoDiffTreeViewArea( 106 mDiffTreeView, 107 mEmptyStateData, 108 mProgressControls.IsOperationRunning(), 109 mParentWindow.Repaint); 110 111 if (mProgressControls.HasNotification()) 112 { 113 DrawProgressForViews.ForNotificationArea( 114 mProgressControls.ProgressData); 115 } 116 117 EditorGUILayout.EndVertical(); 118 } 119 120 void IDiffTreeViewMenuOperations.SaveRevisionAs() 121 { 122 TrackFeatureUseEvent.For( 123 PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo), 124 TrackFeatureUseEvent.Features.SaveRevisionFromDiff); 125 126 ClientDiffInfo clientDiffInfo = 127 DiffSelection.GetSelectedDiff(mDiffTreeView); 128 RepositorySpec repSpec = clientDiffInfo.DiffWithMount.Mount.RepSpec; 129 RevisionInfo revision = clientDiffInfo.DiffWithMount.Difference.RevInfo; 130 131 string defaultFileName = DefaultRevisionName.Get( 132 Path.GetFileName(clientDiffInfo.DiffWithMount.Difference.Path), revision.Changeset); 133 string destinationPath = SaveAction.GetDestinationPath( 134 mWkInfo.ClientPath, 135 clientDiffInfo.DiffWithMount.Difference.Path, 136 defaultFileName); 137 138 if (string.IsNullOrEmpty(destinationPath)) 139 return; 140 141 SaveRevisionOperation.SaveRevision( 142 repSpec, 143 destinationPath, 144 revision, 145 mProgressControls); 146 } 147 148 SelectedDiffsGroupInfo IDiffTreeViewMenuOperations.GetSelectedDiffsGroupInfo() 149 { 150 return SelectedDiffsGroupInfo.BuildFromSelectedNodes( 151 DiffSelection.GetSelectedDiffsWithoutMeta(mDiffTreeView), 152 mWkInfo != null); 153 } 154 155 void IDiffTreeViewMenuOperations.Diff() 156 { 157 ClientDiffInfo clientDiffInfo = 158 DiffSelection.GetSelectedDiff(mDiffTreeView); 159 160 DiffOperation.DiffClientDiff( 161 mWkInfo, 162 clientDiffInfo.DiffWithMount.Mount.Mount, 163 clientDiffInfo.DiffWithMount.Difference, 164 PlasticExeLauncher.BuildForDiffRevision(mWkInfo, mIsGluonMode, mShowDownloadPlasticExeWindow), 165 imageDiffLauncher: null); 166 } 167 168 void IDiffTreeViewMenuOperations.History() 169 { 170 ClientDiffInfo clientDiffInfo = 171 DiffSelection.GetSelectedDiff(mDiffTreeView); 172 173 mHistoryViewLauncher.ShowHistoryView( 174 clientDiffInfo.DiffWithMount.Mount.RepSpec, 175 clientDiffInfo.DiffWithMount.Difference.RevInfo.ItemId, 176 clientDiffInfo.DiffWithMount.Difference.Path, 177 clientDiffInfo.DiffWithMount.Difference.IsDirectory); 178 } 179 180 void IDiffTreeViewMenuOperations.RevertChanges() 181 { 182 RevertClientDiffsOperation.RevertChanges( 183 mWkInfo, 184 DiffSelection.GetSelectedDiffs(mDiffTreeView), 185 mWorkspaceWindow, 186 mProgressControls, 187 mGuiMessage, 188 AfterRevertOrUndeleteOperation); 189 } 190 191 void IDiffTreeViewMenuOperations.Undelete() 192 { 193 UndeleteClientDiffsOperation.Undelete( 194 mWkInfo, 195 DiffSelection.GetSelectedDiffs(mDiffTreeView), 196 mRefreshView, 197 mProgressControls, 198 this, 199 mGuiMessage, 200 AfterRevertOrUndeleteOperation); 201 } 202 203 void IDiffTreeViewMenuOperations.UndeleteToSpecifiedPaths() 204 { 205 UndeleteClientDiffsOperation.UndeleteToSpecifiedPaths( 206 mWkInfo, 207 DiffSelection.GetSelectedDiffs(mDiffTreeView), 208 mRefreshView, 209 mProgressControls, 210 this, 211 mGuiMessage, 212 AfterRevertOrUndeleteOperation); 213 } 214 215 void IDiffTreeViewMenuOperations.Annotate() 216 { 217 } 218 219 void IDiffTreeViewMenuOperations.CopyFilePath(bool relativePath) 220 { 221 EditorGUIUtility.systemCopyBuffer = GetFilePathList.FromClientDiffInfos( 222 DiffSelection.GetSelectedDiffsWithoutMeta(mDiffTreeView), 223 relativePath, 224 mWkInfo.ClientPath); 225 } 226 227 bool DiffTreeViewMenu.IMetaMenuOperations.SelectionHasMeta() 228 { 229 return mDiffTreeView.SelectionHasMeta(); 230 } 231 232 void DiffTreeViewMenu.IMetaMenuOperations.DiffMeta() 233 { 234 ClientDiffInfo clientDiffInfo = 235 DiffSelection.GetSelectedDiff(mDiffTreeView); 236 237 ClientDiffInfo clientDiffInfoMeta = 238 mDiffTreeView.GetMetaDiff(clientDiffInfo); 239 240 DiffOperation.DiffClientDiff( 241 mWkInfo, 242 clientDiffInfoMeta.DiffWithMount.Mount.Mount, 243 clientDiffInfoMeta.DiffWithMount.Difference, 244 PlasticExeLauncher.BuildForDiffRevision(mWkInfo, mIsGluonMode, mShowDownloadPlasticExeWindow), 245 imageDiffLauncher: null); 246 } 247 248 GetRestorePathData 249 UndeleteClientDiffsOperation.IGetRestorePathDialog.GetRestorePath( 250 string wkPath, string restorePath, string explanation, 251 bool isDirectory, bool showSkipButton) 252 { 253 return GetRestorePathDialog.GetRestorePath( 254 wkPath, restorePath, explanation, isDirectory, 255 showSkipButton, mParentWindow); 256 } 257 258 void DiffTreeViewMenu.IMetaMenuOperations.HistoryMeta() 259 { 260 ClientDiffInfo clientDiffInfo = 261 DiffSelection.GetSelectedDiff(mDiffTreeView); 262 263 ClientDiffInfo clientDiffInfoMeta = 264 mDiffTreeView.GetMetaDiff(clientDiffInfo); 265 266 mHistoryViewLauncher.ShowHistoryView( 267 clientDiffInfoMeta.DiffWithMount.Mount.RepSpec, 268 clientDiffInfoMeta.DiffWithMount.Difference.RevInfo.ItemId, 269 clientDiffInfoMeta.DiffWithMount.Difference.Path, 270 clientDiffInfoMeta.DiffWithMount.Difference.IsDirectory); 271 } 272 273 void SearchField_OnDownOrUpArrowKeyPressed() 274 { 275 mDiffTreeView.SetFocusAndEnsureSelectedItem(); 276 } 277 278 void AfterRevertOrUndeleteOperation() 279 { 280 RefreshAsset.UnityAssetDatabase(); 281 282 mViewSwitcher.ShowPendingChanges(); 283 } 284 285 void ClearData() 286 { 287 mSelectedMountWithPath = null; 288 mSelectedChangesetInfo = null; 289 290 mDiffs = null; 291 292 ClearDiffs(); 293 } 294 295 void FillData( 296 MountPointWithPath mountWithPath, 297 ChangesetInfo csetInfo) 298 { 299 mSelectedMountWithPath = mountWithPath; 300 mSelectedChangesetInfo = csetInfo; 301 302 ((IProgressControls)mProgressControls).ShowProgress( 303 PlasticLocalization.GetString(PlasticLocalization.Name.Loading)); 304 305 mIsSkipMergeTrackingButtonVisible = false; 306 307 IThreadWaiter waiter = ThreadWaiter.GetWaiter(100); 308 waiter.Execute( 309 /*threadOperationDelegate*/ delegate 310 { 311 mDiffs = PlasticGui.Plastic.API.GetChangesetDifferences( 312 mountWithPath, csetInfo); 313 314 mDiffsBranchResolver = BuildBranchResolver.ForDiffs(mDiffs); 315 }, 316 /*afterOperationDelegate*/ delegate 317 { 318 ((IProgressControls)mProgressControls).HideProgress(); 319 320 if (mSelectedMountWithPath != mountWithPath || 321 mSelectedChangesetInfo != csetInfo) 322 return; 323 324 if (waiter.Exception != null) 325 { 326 ExceptionsHandler.LogException("DiffPanel", waiter.Exception); 327 328 ((IProgressControls)mProgressControls).ShowError(waiter.Exception.Message); 329 330 ClearDiffs(); 331 return; 332 } 333 334 if (mDiffs == null || mDiffs.Count == 0) 335 { 336 ClearDiffs(); 337 return; 338 } 339 340 mIsSkipMergeTrackingButtonVisible = 341 ClientDiffList.HasMerges(mDiffs); 342 343 bool skipMergeTracking = 344 mIsSkipMergeTrackingButtonVisible && 345 mIsSkipMergeTrackingButtonChecked; 346 347 UpdateDiffTreeView( 348 mWkInfo, 349 mDiffs, 350 mDiffsBranchResolver, 351 skipMergeTracking, 352 mDiffTreeView); 353 }); 354 } 355 356 void ClearDiffs() 357 { 358 mIsSkipMergeTrackingButtonVisible = false; 359 360 ClearDiffTreeView(mDiffTreeView); 361 } 362 363 static void ClearDiffTreeView( 364 DiffTreeView diffTreeView) 365 { 366 diffTreeView.ClearModel(); 367 368 diffTreeView.Reload(); 369 } 370 371 static void UpdateDiffTreeView( 372 WorkspaceInfo wkInfo, 373 List<ClientDiff> diffs, 374 BranchResolver brResolver, 375 bool skipMergeTracking, 376 DiffTreeView diffTreeView) 377 { 378 diffTreeView.BuildModel( 379 wkInfo, diffs, brResolver, skipMergeTracking); 380 381 diffTreeView.Refilter(); 382 383 diffTreeView.Sort(); 384 385 diffTreeView.Reload(); 386 } 387 388 void DoActionsToolbar( 389 List<ClientDiff> diffs, 390 BranchResolver brResolver, 391 ProgressControlsForViews progressControls, 392 bool isSkipMergeTrackingButtonVisible, 393 bool isSkipMergeTrackingButtonChecked, 394 SearchField searchField, 395 DiffTreeView diffTreeView) 396 { 397 EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); 398 399 if (progressControls.IsOperationRunning()) 400 { 401 DrawProgressForViews.ForIndeterminateProgress( 402 progressControls.ProgressData); 403 } 404 405 GUILayout.FlexibleSpace(); 406 407 if (isSkipMergeTrackingButtonVisible) 408 { 409 DoSkipMergeTrackingButton( 410 diffs, brResolver, 411 isSkipMergeTrackingButtonChecked, 412 diffTreeView); 413 } 414 415 DrawSearchField.For( 416 searchField, 417 diffTreeView, 418 UnityConstants.SEARCH_FIELD_WIDTH); 419 420 EditorGUILayout.EndHorizontal(); 421 } 422 423 void DoSkipMergeTrackingButton( 424 List<ClientDiff> diffs, 425 BranchResolver brResolver, 426 bool isSkipMergeTrackingButtonChecked, 427 DiffTreeView diffTreeView) 428 { 429 bool wasChecked = isSkipMergeTrackingButtonChecked; 430 431 GUIContent buttonContent = new GUIContent( 432 PlasticLocalization.GetString( 433 PlasticLocalization.Name.SkipDiffMergeTracking)); 434 435 GUIStyle buttonStyle = new GUIStyle(EditorStyles.toolbarButton); 436 437 float buttonWidth = buttonStyle.CalcSize(buttonContent).x + 10; 438 439 Rect toggleRect = GUILayoutUtility.GetRect( 440 buttonContent, buttonStyle, GUILayout.Width(buttonWidth)); 441 442 bool isChecked = GUI.Toggle( 443 toggleRect, wasChecked, buttonContent, buttonStyle); 444 445 if (wasChecked == isChecked) 446 return; 447 448 // if user just checked the skip merge tracking button 449 if (isChecked) 450 { 451 TrackFeatureUseEvent.For( 452 PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo), 453 TrackFeatureUseEvent.Features.ChangesetViewSkipMergeTrackingButton); 454 } 455 456 UpdateDiffTreeView(mWkInfo, diffs, brResolver, isChecked, diffTreeView); 457 458 mIsSkipMergeTrackingButtonChecked = isChecked; 459 } 460 461 static void DoDiffTreeViewArea( 462 DiffTreeView diffTreeView, 463 EmptyStateData emptyStateData, 464 bool isOperationRunning, 465 Action repaint) 466 { 467 GUI.enabled = !isOperationRunning; 468 469 Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000); 470 471 diffTreeView.OnGUI(rect); 472 473 emptyStateData.Update( 474 GetEmptyStateMessage(diffTreeView), 475 rect, Event.current.type, repaint); 476 477 if (!emptyStateData.IsEmpty()) 478 DrawTreeViewEmptyState.For(emptyStateData); 479 480 GUI.enabled = true; 481 } 482 483 static string GetEmptyStateMessage(DiffTreeView diffTreeView) 484 { 485 if (diffTreeView.GetRows().Count > 0) 486 return string.Empty; 487 488 return string.IsNullOrEmpty(diffTreeView.searchString) ? 489 PlasticLocalization.Name.NoContentToCompareExplanation.GetString() : 490 PlasticLocalization.Name.DiffsEmptyState.GetString(); 491 } 492 493 void BuildComponents() 494 { 495 mSearchField = new SearchField(); 496 mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed; 497 498 mDiffTreeView = new DiffTreeView(new DiffTreeViewMenu(this, this)); 499 mDiffTreeView.Reload(); 500 } 501 502 bool mIsSkipMergeTrackingButtonVisible; 503 bool mIsSkipMergeTrackingButtonChecked; 504 505 ChangesetInfo mSelectedChangesetInfo; 506 MountPointWithPath mSelectedMountWithPath; 507 508 volatile List<ClientDiff> mDiffs; 509 volatile BranchResolver mDiffsBranchResolver; 510 511 SearchField mSearchField; 512 DiffTreeView mDiffTreeView; 513 514 readonly EmptyStateData mEmptyStateData = new EmptyStateData(); 515 readonly ProgressControlsForViews mProgressControls; 516 readonly GuiMessage.IGuiMessage mGuiMessage; 517 readonly EditorWindow mParentWindow; 518 readonly IRefreshView mRefreshView; 519 readonly IWorkspaceWindow mWorkspaceWindow; 520 readonly IHistoryViewLauncher mHistoryViewLauncher; 521 readonly IViewSwitcher mViewSwitcher; 522 readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow; 523 readonly WorkspaceInfo mWkInfo; 524 readonly bool mIsGluonMode; 525 } 526}