暫無描述
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.

PendingChangesTab.cs 41KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEditor.IMGUI.Controls;
  5. using UnityEngine;
  6. using Codice.Client.BaseCommands;
  7. using Codice.Client.Commands;
  8. using Codice.Client.Common;
  9. using Codice.Client.Common.EventTracking;
  10. using Codice.Client.Common.FsNodeReaders;
  11. using Codice.Client.Common.Threading;
  12. using Codice.CM.Client.Gui;
  13. using Codice.CM.Common;
  14. using Codice.CM.Common.Merge;
  15. using Codice.CM.Common.Mount;
  16. using Codice.LogWrapper;
  17. using GluonGui;
  18. using GluonGui.WorkspaceWindow.Views.Checkin.Operations;
  19. using PlasticGui;
  20. using PlasticGui.Help.Actions;
  21. using PlasticGui.Help.Conditions;
  22. using PlasticGui.WorkspaceWindow;
  23. using PlasticGui.WorkspaceWindow.Diff;
  24. using PlasticGui.WorkspaceWindow.Items;
  25. using PlasticGui.WorkspaceWindow.Open;
  26. using PlasticGui.WorkspaceWindow.PendingChanges;
  27. using PlasticGui.WorkspaceWindow.PendingChanges.Changelists;
  28. using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
  29. using Unity.PlasticSCM.Editor.AssetUtils;
  30. using Unity.PlasticSCM.Editor.AssetUtils.Processor;
  31. using Unity.PlasticSCM.Editor.Help;
  32. using Unity.PlasticSCM.Editor.Tool;
  33. using Unity.PlasticSCM.Editor.UI;
  34. using Unity.PlasticSCM.Editor.UI.Progress;
  35. using Unity.PlasticSCM.Editor.UI.StatusBar;
  36. using Unity.PlasticSCM.Editor.UI.Tree;
  37. using Unity.PlasticSCM.Editor.Views.PendingChanges.Dialogs;
  38. using Unity.PlasticSCM.Editor.Views.PendingChanges.PendingMergeLinks;
  39. using Unity.PlasticSCM.Editor.Views.Changesets;
  40. using GluonNewIncomingChangesUpdater = PlasticGui.Gluon.WorkspaceWindow.NewIncomingChangesUpdater;
  41. namespace Unity.PlasticSCM.Editor.Views.PendingChanges
  42. {
  43. internal partial class PendingChangesTab :
  44. IRefreshableView,
  45. PlasticProjectSettingsProvider.IAutoRefreshView,
  46. IPendingChangesView,
  47. CheckinUIOperation.ICheckinView,
  48. PendingChangesViewPendingChangeMenu.IMetaMenuOperations,
  49. IPendingChangesMenuOperations,
  50. IChangelistMenuOperations,
  51. IOpenMenuOperations,
  52. PendingChangesViewPendingChangeMenu.IAdvancedUndoMenuOperations,
  53. IFilesFilterPatternsMenuOperations,
  54. PendingChangesViewMenu.IGetSelectedNodes,
  55. ChangesetsTab.IRevertToChangesetListener
  56. {
  57. internal IProgressControls ProgressControlsForTesting { get { return mProgressControls; } }
  58. internal HelpPanel HelpPanelForTesting { get { return mHelpPanel; } }
  59. internal void SetMergeLinksForTesting(
  60. IDictionary<MountPoint, IList<PendingMergeLink>> mergeLinks)
  61. {
  62. mPendingMergeLinks = mergeLinks;
  63. UpdateMergeLinksList();
  64. }
  65. internal string CommentText { get; set; }
  66. internal bool ForceToShowComment { get; set; }
  67. internal PendingChangesTab(
  68. WorkspaceInfo wkInfo,
  69. ViewHost viewHost,
  70. bool isGluonMode,
  71. WorkspaceWindow workspaceWindow,
  72. IViewSwitcher switcher,
  73. IMergeViewLauncher mergeViewLauncher,
  74. IHistoryViewLauncher historyViewLauncher,
  75. LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
  76. WorkspaceOperationsMonitor workspaceOperationsMonitor,
  77. NewIncomingChangesUpdater developerNewIncomingChangesUpdater,
  78. GluonNewIncomingChangesUpdater gluonNewIncomingChangesUpdater,
  79. IAssetStatusCache assetStatusCache,
  80. StatusBar statusBar,
  81. EditorWindow parentWindow)
  82. {
  83. mWkInfo = wkInfo;
  84. mViewHost = viewHost;
  85. mIsGluonMode = isGluonMode;
  86. mWorkspaceWindow = workspaceWindow;
  87. mHistoryViewLauncher = historyViewLauncher;
  88. mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
  89. mWorkspaceOperationsMonitor = workspaceOperationsMonitor;
  90. mDeveloperNewIncomingChangesUpdater = developerNewIncomingChangesUpdater;
  91. mGluonNewIncomingChangesUpdater = gluonNewIncomingChangesUpdater;
  92. mAssetStatusCache = assetStatusCache;
  93. mStatusBar = statusBar;
  94. mParentWindow = parentWindow;
  95. mGuiMessage = new UnityPlasticGuiMessage();
  96. mCheckedStateManager = new PendingChangesViewCheckedStateManager();
  97. mNewChangesInWk = NewChangesInWk.Build(
  98. mWkInfo,
  99. new BuildWorkspacekIsRelevantNewChange());
  100. BuildComponents(isGluonMode, parentWindow);
  101. mBorderColor = EditorGUIUtility.isProSkin
  102. ? (Color)new Color32(35, 35, 35, 255)
  103. : (Color)new Color32(153, 153, 153, 255);
  104. mProgressControls = new ProgressControlsForViews();
  105. mCooldownClearCheckinSuccessAction = new CooldownWindowDelayer(
  106. DelayedClearCheckinSuccess,
  107. UnityConstants.NOTIFICATION_CLEAR_INTERVAL);
  108. workspaceWindow.RegisterPendingChangesProgressControls(mProgressControls);
  109. mPendingChangesOperations = new PendingChangesOperations(
  110. mWkInfo,
  111. workspaceWindow,
  112. switcher,
  113. mergeViewLauncher,
  114. this,
  115. mProgressControls,
  116. workspaceWindow,
  117. null,
  118. null,
  119. null);
  120. InitIgnoreRulesAndRefreshView(mWkInfo.ClientPath, this);
  121. }
  122. internal void AutoRefresh()
  123. {
  124. if (mIsAutoRefreshDisabled)
  125. return;
  126. if (!PlasticGuiConfig.Get().Configuration.CommitAutoRefresh)
  127. return;
  128. if (mNewChangesInWk != null && !mNewChangesInWk.Detected())
  129. return;
  130. ((IRefreshableView)this).Refresh();
  131. }
  132. internal void ClearIsCommentWarningNeeded()
  133. {
  134. mIsEmptyCheckinCommentWarningNeeded = false;
  135. }
  136. internal void UpdateIsCommentWarningNeeded(string comment)
  137. {
  138. mIsEmptyCheckinCommentWarningNeeded =
  139. string.IsNullOrEmpty(comment) &&
  140. GuiClientConfig.Get().Configuration.ShowEmptyCommentWarning;
  141. mNeedsToShowEmptyCommentDialog = mIsEmptyCheckinCommentWarningNeeded;
  142. }
  143. internal void OnDisable()
  144. {
  145. mSearchField.downOrUpArrowKeyPressed -=
  146. SearchField_OnDownOrUpArrowKeyPressed;
  147. TreeHeaderSettings.Save(
  148. mPendingChangesTreeView.multiColumnHeader.state,
  149. UnityConstants.PENDING_CHANGES_TABLE_SETTINGS_NAME);
  150. }
  151. internal void Update()
  152. {
  153. mProgressControls.UpdateProgress(mParentWindow);
  154. // Displaying the dialog here, because showing it during the window's OnGUI function
  155. // caused errors
  156. if(mNeedsToShowEmptyCommentDialog)
  157. {
  158. mNeedsToShowEmptyCommentDialog = false;
  159. mHasPendingCheckinFromPreviousUpdate =
  160. EmptyCheckinMessageDialog.ShouldContinueWithCheckin(mParentWindow, mWkInfo);
  161. mIsEmptyCheckinCommentWarningNeeded = !mHasPendingCheckinFromPreviousUpdate;
  162. }
  163. }
  164. internal void OnGUI()
  165. {
  166. if (!string.IsNullOrEmpty(mGluonWarningMessage))
  167. DoWarningMessage(mGluonWarningMessage);
  168. DoActionsToolbar(
  169. mWkInfo,
  170. mIsGluonMode,
  171. mProgressControls);
  172. DoChangesArea(
  173. mPendingChangesTreeView,
  174. mProgressControls.IsOperationRunning(),
  175. mIsCheckedInSuccessful,
  176. mOrganizationToInviteUsers);
  177. if (HasPendingMergeLinks() && !mHasPendingMergeLinksFromRevert)
  178. DoMergeLinksArea(mMergeLinksListView, mParentWindow.position.width);
  179. // Border
  180. Rect result = GUILayoutUtility.GetRect(mParentWindow.position.width, 1);
  181. EditorGUI.DrawRect(result, mBorderColor);
  182. DoCommentsSection();
  183. if (mProgressControls.HasNotification())
  184. {
  185. DrawProgressForViews.ForNotificationArea(mProgressControls.ProgressData);
  186. }
  187. DrawHelpPanel.For(mHelpPanel);
  188. }
  189. internal void DrawSearchFieldForPendingChangesTab()
  190. {
  191. DrawSearchField.For(
  192. mSearchField,
  193. mPendingChangesTreeView,
  194. UnityConstants.SEARCH_FIELD_WIDTH);
  195. }
  196. void IPendingChangesView.SetDefaultComment(string defaultComment)
  197. {
  198. }
  199. void IPendingChangesView.ClearComments()
  200. {
  201. ClearComments();
  202. }
  203. void IRefreshableView.Refresh()
  204. {
  205. if (mProgressControls.IsOperationRunning())
  206. return;
  207. if (!mAreIgnoreRulesInitialized)
  208. return;
  209. if (mDeveloperNewIncomingChangesUpdater != null)
  210. mDeveloperNewIncomingChangesUpdater.Update(DateTime.Now);
  211. if (mGluonNewIncomingChangesUpdater != null)
  212. mGluonNewIncomingChangesUpdater.Update(DateTime.Now);
  213. FillPendingChanges(mNewChangesInWk);
  214. }
  215. void PlasticProjectSettingsProvider.IAutoRefreshView.DisableAutoRefresh()
  216. {
  217. mIsAutoRefreshDisabled = true;
  218. }
  219. void PlasticProjectSettingsProvider.IAutoRefreshView.EnableAutoRefresh()
  220. {
  221. mIsAutoRefreshDisabled = false;
  222. }
  223. void PlasticProjectSettingsProvider.IAutoRefreshView.ForceRefresh()
  224. {
  225. ((IRefreshableView)this).Refresh();
  226. }
  227. void IPendingChangesView.ClearChangesToCheck(List<string> changes)
  228. {
  229. mCheckedStateManager.ClearChangesToCheck(changes);
  230. mParentWindow.Repaint();
  231. }
  232. void IPendingChangesView.CleanCheckedElements(List<ChangeInfo> checkedChanges)
  233. {
  234. mCheckedStateManager.Clean(checkedChanges);
  235. mParentWindow.Repaint();
  236. }
  237. void IPendingChangesView.CheckChanges(List<string> changesToCheck)
  238. {
  239. mCheckedStateManager.SetChangesToCheck(changesToCheck);
  240. mParentWindow.Repaint();
  241. }
  242. bool IPendingChangesView.IncludeDependencies(
  243. IList<ChangeDependencies<ChangeInfo>> changesDependencies,
  244. string operation)
  245. {
  246. return DependenciesDialog.IncludeDependencies(
  247. mWkInfo, changesDependencies, operation, mParentWindow);
  248. }
  249. SearchMatchesData IPendingChangesView.AskForMatches(string changePath)
  250. {
  251. throw new NotImplementedException();
  252. }
  253. void IPendingChangesView.CleanLinkedTasks()
  254. {
  255. }
  256. void CheckinUIOperation.ICheckinView.CollapseWarningMessagePanel()
  257. {
  258. mGluonWarningMessage = string.Empty;
  259. mParentWindow.Repaint();
  260. }
  261. void CheckinUIOperation.ICheckinView.ExpandWarningMessagePanel(string text)
  262. {
  263. mGluonWarningMessage = text;
  264. mParentWindow.Repaint();
  265. }
  266. void CheckinUIOperation.ICheckinView.ClearComments()
  267. {
  268. ClearComments();
  269. }
  270. bool PendingChangesViewPendingChangeMenu.IMetaMenuOperations.SelectionHasMeta()
  271. {
  272. return mPendingChangesTreeView.SelectionHasMeta();
  273. }
  274. void PendingChangesViewPendingChangeMenu.IMetaMenuOperations.DiffMeta()
  275. {
  276. if (mShowDownloadPlasticExeWindow.Show(
  277. mWkInfo,
  278. mIsGluonMode,
  279. TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffWorkspaceContent,
  280. TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffWorkspaceContent,
  281. TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffWorkspaceContent))
  282. return;
  283. ChangeInfo selectedChange = PendingChangesSelection
  284. .GetSelectedChange(mPendingChangesTreeView);
  285. ChangeInfo selectedChangeMeta = mPendingChangesTreeView.GetMetaChange(
  286. selectedChange);
  287. ChangeInfo changedForMoved = mPendingChangesTreeView.GetChangedForMoved(selectedChange);
  288. ChangeInfo changedForMovedMeta = (changedForMoved == null) ?
  289. null : mPendingChangesTreeView.GetMetaChange(changedForMoved);
  290. DiffOperation.DiffWorkspaceContent(
  291. mWkInfo,
  292. selectedChangeMeta,
  293. changedForMovedMeta,
  294. mProgressControls,
  295. null,
  296. null);
  297. }
  298. void PendingChangesViewPendingChangeMenu.IMetaMenuOperations.HistoryMeta()
  299. {
  300. ChangeInfo selectedChange = PendingChangesSelection
  301. .GetSelectedChange(mPendingChangesTreeView);
  302. ChangeInfo selectedChangeMeta = mPendingChangesTreeView.GetMetaChange(
  303. selectedChange);
  304. mHistoryViewLauncher.ShowHistoryView(
  305. selectedChangeMeta.RepositorySpec,
  306. selectedChangeMeta.RevInfo.ItemId,
  307. selectedChangeMeta.Path,
  308. selectedChangeMeta.IsDirectory);
  309. }
  310. void PendingChangesViewPendingChangeMenu.IMetaMenuOperations.OpenMeta()
  311. {
  312. List<string> selectedPaths = PendingChangesSelection
  313. .GetSelectedMetaPaths(mPendingChangesTreeView);
  314. FileSystemOperation.Open(selectedPaths);
  315. }
  316. void PendingChangesViewPendingChangeMenu.IMetaMenuOperations.OpenMetaWith()
  317. {
  318. List<string> selectedPaths = PendingChangesSelection
  319. .GetSelectedMetaPaths(mPendingChangesTreeView);
  320. OpenOperation.OpenWith(
  321. FileSystemOperation.GetExePath(),
  322. selectedPaths);
  323. }
  324. void PendingChangesViewPendingChangeMenu.IMetaMenuOperations.OpenMetaInExplorer()
  325. {
  326. List<string> selectedPaths = PendingChangesSelection
  327. .GetSelectedMetaPaths(mPendingChangesTreeView);
  328. if (selectedPaths.Count < 1)
  329. return;
  330. FileSystemOperation.OpenInExplorer(selectedPaths[0]);
  331. }
  332. SelectedChangesGroupInfo IPendingChangesMenuOperations.GetSelectedChangesGroupInfo()
  333. {
  334. return PendingChangesSelection.GetSelectedChangesGroupInfo(
  335. mWkInfo.ClientPath, mPendingChangesTreeView);
  336. }
  337. void IPendingChangesMenuOperations.Diff()
  338. {
  339. if (mShowDownloadPlasticExeWindow.Show(
  340. mWkInfo,
  341. mIsGluonMode,
  342. TrackFeatureUseEvent.Features.InstallPlasticCloudFromDiffWorkspaceContent,
  343. TrackFeatureUseEvent.Features.InstallPlasticEnterpriseFromDiffWorkspaceContent,
  344. TrackFeatureUseEvent.Features.CancelPlasticInstallationFromDiffWorkspaceContent))
  345. return;
  346. ChangeInfo selectedChange = PendingChangesSelection
  347. .GetSelectedChange(mPendingChangesTreeView);
  348. DiffOperation.DiffWorkspaceContent(
  349. mWkInfo,
  350. selectedChange,
  351. mPendingChangesTreeView.GetChangedForMoved(selectedChange),
  352. null,
  353. null,
  354. null);
  355. }
  356. void IPendingChangesMenuOperations.UndoChanges()
  357. {
  358. List<ChangeInfo> changesToUndo = PendingChangesSelection
  359. .GetSelectedChanges(mPendingChangesTreeView);
  360. List<ChangeInfo> dependenciesCandidates =
  361. mPendingChangesTreeView.GetDependenciesCandidates(changesToUndo, true);
  362. UndoChangesForMode(
  363. mWkInfo, mIsGluonMode,
  364. changesToUndo, dependenciesCandidates);
  365. }
  366. void IPendingChangesMenuOperations.SearchMatches()
  367. {
  368. ChangeInfo selectedChange = PendingChangesSelection
  369. .GetSelectedChange(mPendingChangesTreeView);
  370. if (selectedChange == null)
  371. return;
  372. SearchMatchesOperation operation = new SearchMatchesOperation(
  373. mWkInfo, mWorkspaceWindow, this,
  374. mProgressControls, mDeveloperNewIncomingChangesUpdater);
  375. operation.SearchMatches(
  376. selectedChange,
  377. PendingChangesSelection.GetAllChanges(mPendingChangesTreeView),
  378. null);
  379. }
  380. void IPendingChangesMenuOperations.ApplyLocalChanges()
  381. {
  382. List<ChangeInfo> selectedChanges = PendingChangesSelection
  383. .GetSelectedChanges(mPendingChangesTreeView);
  384. if (selectedChanges.Count == 0)
  385. return;
  386. ApplyLocalChangesOperation operation = new ApplyLocalChangesOperation(
  387. mWkInfo, mWorkspaceWindow, this,
  388. mProgressControls, mDeveloperNewIncomingChangesUpdater);
  389. operation.ApplyLocalChanges(
  390. selectedChanges,
  391. PendingChangesSelection.GetAllChanges(mPendingChangesTreeView),
  392. null);
  393. }
  394. void IPendingChangesMenuOperations.Delete()
  395. {
  396. List<string> privateDirectoriesToDelete;
  397. List<string> privateFilesToDelete;
  398. if (!mPendingChangesTreeView.GetSelectedPathsToDelete(
  399. out privateDirectoriesToDelete,
  400. out privateFilesToDelete))
  401. return;
  402. DeleteOperation.Delete(
  403. mProgressControls,
  404. privateDirectoriesToDelete,
  405. privateFilesToDelete,
  406. mDeveloperNewIncomingChangesUpdater,
  407. RefreshAsset.UnityAssetDatabase,
  408. () => ((IWorkspaceWindow)mWorkspaceWindow).RefreshView(ViewType.ItemsView),
  409. () => ((IWorkspaceWindow)mWorkspaceWindow).RefreshView(ViewType.PendingChangesView));
  410. }
  411. void IPendingChangesMenuOperations.Annotate()
  412. {
  413. throw new NotImplementedException();
  414. }
  415. void IPendingChangesMenuOperations.History()
  416. {
  417. ChangeInfo selectedChange = PendingChangesSelection.
  418. GetSelectedChange(mPendingChangesTreeView);
  419. mHistoryViewLauncher.ShowHistoryView(
  420. selectedChange.RepositorySpec,
  421. selectedChange.RevInfo.ItemId,
  422. selectedChange.Path,
  423. selectedChange.IsDirectory);
  424. }
  425. SelectedChangesGroupInfo IChangelistMenuOperations.GetSelectedChangesGroupInfo()
  426. {
  427. return PendingChangesSelection.GetSelectedChangesGroupInfo(
  428. mWkInfo.ClientPath, mPendingChangesTreeView);
  429. }
  430. List<ChangeListInfo> IChangelistMenuOperations.GetSelectedChangelistInfos()
  431. {
  432. return PendingChangesSelection.GetSelectedChangeListInfos(
  433. mPendingChangesTreeView);
  434. }
  435. void IChangelistMenuOperations.Checkin()
  436. {
  437. List<ChangeInfo> changesToCheckin;
  438. List<ChangeInfo> dependenciesCandidates;
  439. mPendingChangesTreeView.GetCheckedChanges(
  440. PendingChangesSelection.GetSelectedChangelistNodes(mPendingChangesTreeView),
  441. false, out changesToCheckin, out dependenciesCandidates);
  442. CheckinChangesForMode(
  443. changesToCheckin, dependenciesCandidates,
  444. mWkInfo, mIsGluonMode, mKeepItemsLocked);
  445. }
  446. void IChangelistMenuOperations.Shelve()
  447. {
  448. if (mIsGluonMode)
  449. return;
  450. List<ChangeInfo> changesToShelve;
  451. List<ChangeInfo> dependenciesCandidates;
  452. mPendingChangesTreeView.GetCheckedChanges(
  453. PendingChangesSelection.GetSelectedChangelistNodes(mPendingChangesTreeView),
  454. false, out changesToShelve, out dependenciesCandidates);
  455. ShelveChanges(changesToShelve, dependenciesCandidates, mWkInfo);
  456. }
  457. void IChangelistMenuOperations.Undo()
  458. {
  459. List<ChangeInfo> changesToUndo;
  460. List<ChangeInfo> dependenciesCandidates;
  461. mPendingChangesTreeView.GetCheckedChanges(
  462. PendingChangesSelection.GetSelectedChangelistNodes(mPendingChangesTreeView),
  463. true, out changesToUndo, out dependenciesCandidates);
  464. UndoChangesForMode(
  465. mWkInfo, mIsGluonMode,
  466. changesToUndo, dependenciesCandidates);
  467. }
  468. void IChangelistMenuOperations.CreateNew()
  469. {
  470. ChangelistCreationData changelistCreationData =
  471. CreateChangelistDialog.CreateChangelist(mWkInfo, mParentWindow);
  472. ChangelistOperations.CreateNew(mWkInfo, this, changelistCreationData);
  473. }
  474. void IChangelistMenuOperations.MoveToNewChangelist(List<ChangeInfo> changes)
  475. {
  476. ChangelistCreationData changelistCreationData =
  477. CreateChangelistDialog.CreateChangelist(mWkInfo, mParentWindow);
  478. if (!changelistCreationData.Result)
  479. return;
  480. ChangelistOperations.CreateNew(mWkInfo, this, changelistCreationData);
  481. ChangelistOperations.MoveToChangelist(
  482. mWkInfo, this, changes,
  483. changelistCreationData.ChangelistInfo.Name);
  484. }
  485. void IChangelistMenuOperations.Edit()
  486. {
  487. ChangeListInfo changelistToEdit = PendingChangesSelection.GetSelectedChangeListInfo(
  488. mPendingChangesTreeView);
  489. ChangelistCreationData changelistCreationData = CreateChangelistDialog.EditChangelist(
  490. mWkInfo,
  491. changelistToEdit,
  492. mParentWindow);
  493. ChangelistOperations.Edit(mWkInfo, this, changelistToEdit, changelistCreationData);
  494. }
  495. void IChangelistMenuOperations.Delete()
  496. {
  497. ChangelistOperations.Delete(
  498. mWkInfo,
  499. this,
  500. PendingChangesSelection.GetSelectedChangelistNodes(mPendingChangesTreeView));
  501. }
  502. void IChangelistMenuOperations.MoveToChangelist(
  503. List<ChangeInfo> changes,
  504. string targetChangelist)
  505. {
  506. ChangelistOperations.MoveToChangelist(
  507. mWkInfo,
  508. this,
  509. changes,
  510. targetChangelist);
  511. }
  512. void IOpenMenuOperations.Open()
  513. {
  514. List<string> selectedPaths = PendingChangesSelection.
  515. GetSelectedPathsWithoutMeta(mPendingChangesTreeView);
  516. FileSystemOperation.Open(selectedPaths);
  517. }
  518. void IOpenMenuOperations.OpenWith()
  519. {
  520. List<string> selectedPaths = PendingChangesSelection.
  521. GetSelectedPathsWithoutMeta(mPendingChangesTreeView);
  522. OpenOperation.OpenWith(
  523. FileSystemOperation.GetExePath(),
  524. selectedPaths);
  525. }
  526. void IOpenMenuOperations.OpenWithCustom(string exePath, string args)
  527. {
  528. List<string> selectedPaths = PendingChangesSelection.
  529. GetSelectedPathsWithoutMeta(mPendingChangesTreeView);
  530. OpenOperation.OpenWith(exePath, selectedPaths);
  531. }
  532. void IOpenMenuOperations.OpenInExplorer()
  533. {
  534. List<string> selectedPaths = PendingChangesSelection
  535. .GetSelectedPathsWithoutMeta(mPendingChangesTreeView);
  536. if (selectedPaths.Count < 1)
  537. return;
  538. FileSystemOperation.OpenInExplorer(selectedPaths[0]);
  539. }
  540. void IFilesFilterPatternsMenuOperations.AddFilesFilterPatterns(
  541. FilterTypes type, FilterActions action, FilterOperationType operation)
  542. {
  543. List<string> selectedPaths = PendingChangesSelection.GetSelectedPaths(
  544. mPendingChangesTreeView);
  545. string[] rules = FilterRulesGenerator.GenerateRules(
  546. selectedPaths, mWkInfo.ClientPath, action, operation);
  547. bool isApplicableToAllWorkspaces = !mIsGluonMode;
  548. bool isAddOperation = operation == FilterOperationType.Add;
  549. FilterRulesConfirmationData filterRulesConfirmationData =
  550. FilterRulesConfirmationDialog.AskForConfirmation(
  551. rules, isAddOperation, isApplicableToAllWorkspaces, mParentWindow);
  552. AddFilesFilterPatternsOperation.Run(
  553. mWkInfo, mWorkspaceWindow, type, operation, filterRulesConfirmationData);
  554. }
  555. void PendingChangesViewPendingChangeMenu.IAdvancedUndoMenuOperations.UndoUnchanged()
  556. {
  557. UndoUnchangedFor(PendingChangesSelection.GetSelectedChanges(mPendingChangesTreeView));
  558. }
  559. void PendingChangesViewPendingChangeMenu.IAdvancedUndoMenuOperations.UndoCheckoutsKeepingChanges()
  560. {
  561. UndoCheckoutsKeepingChangesFor(PendingChangesSelection.GetSelectedChanges(mPendingChangesTreeView));
  562. }
  563. List<IPlasticTreeNode> PendingChangesViewMenu.IGetSelectedNodes.GetSelectedNodes()
  564. {
  565. return mPendingChangesTreeView.GetSelectedNodes();
  566. }
  567. void ChangesetsTab.IRevertToChangesetListener.OnSuccessOperation()
  568. {
  569. mHasPendingMergeLinksFromRevert = true;
  570. }
  571. void SearchField_OnDownOrUpArrowKeyPressed()
  572. {
  573. mPendingChangesTreeView.SetFocusAndEnsureSelectedItem();
  574. }
  575. void InitIgnoreRulesAndRefreshView(
  576. string wkPath, IRefreshableView view)
  577. {
  578. IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
  579. waiter.Execute(
  580. /*threadOperationDelegate*/ delegate
  581. {
  582. if (IsIgnoreConfigDefined.For(wkPath))
  583. return;
  584. AddIgnoreRules.WriteRules(
  585. wkPath, UnityConditions.GetMissingIgnoredRules(wkPath));
  586. },
  587. /*afterOperationDelegate*/ delegate
  588. {
  589. mAreIgnoreRulesInitialized = true;
  590. view.Refresh();
  591. if (waiter.Exception == null)
  592. return;
  593. mLog.ErrorFormat(
  594. "Error adding ignore rules for Unity: {0}",
  595. waiter.Exception);
  596. mLog.DebugFormat(
  597. "Stack trace: {0}",
  598. waiter.Exception.StackTrace);
  599. });
  600. }
  601. void FillPendingChanges(INewChangesInWk newChangesInWk)
  602. {
  603. if (mIsRefreshing)
  604. return;
  605. mIsRefreshing = true;
  606. List<ChangeInfo> changesToSelect =
  607. PendingChangesSelection.GetChangesToFocus(mPendingChangesTreeView);
  608. ((IProgressControls)mProgressControls).ShowProgress(PlasticLocalization.
  609. GetString(PlasticLocalization.Name.LoadingPendingChanges));
  610. IDictionary<MountPoint, IList<PendingMergeLink>> mergeLinks = null;
  611. WorkspaceStatusResult status = null;
  612. IThreadWaiter waiter = ThreadWaiter.GetWaiter();
  613. waiter.Execute(
  614. /*threadOperationDelegate*/ delegate
  615. {
  616. FilterManager.Get().Reload(mWkInfo);
  617. WorkspaceStatusOptions options = WorkspaceStatusOptions.None;
  618. options |= WorkspaceStatusOptions.FindAdded;
  619. options |= WorkspaceStatusOptions.FindDeleted;
  620. options |= WorkspaceStatusOptions.FindMoved;
  621. options |= WorkspaceStatusOptions.SplitModifiedMoved;
  622. options |= PendingChangesOptions.GetWorkspaceStatusOptions();
  623. if (newChangesInWk != null)
  624. newChangesInWk.Detected();
  625. status = GetStatus.ForWorkspace(
  626. mWkInfo,
  627. options,
  628. PendingChangesOptions.GetMovedMatchingOptions());
  629. mergeLinks = PlasticGui.Plastic.API.GetPendingMergeLinks(mWkInfo);
  630. },
  631. /*afterOperationDelegate*/ delegate
  632. {
  633. mPendingMergeLinks = mergeLinks;
  634. try
  635. {
  636. if (waiter.Exception != null)
  637. {
  638. ExceptionsHandler.DisplayException(waiter.Exception);
  639. return;
  640. }
  641. UpdateChangesTree(status.Changes);
  642. UpdateMergeLinksList();
  643. PendingChangesSelection.SelectChanges(
  644. mPendingChangesTreeView, changesToSelect);
  645. ClearAssetStatusCache();
  646. }
  647. finally
  648. {
  649. ((IProgressControls)mProgressControls).HideProgress();
  650. //UpdateIsCommentWarningNeeded(CommentText);
  651. UpdateNotificationPanel();
  652. mIsRefreshing = false;
  653. }
  654. });
  655. }
  656. void DoCommentsSection()
  657. {
  658. EditorGUILayout.BeginVertical(UnityStyles.PendingChangesTab.Comment);
  659. EditorGUILayout.Space(10);
  660. EditorGUILayout.BeginHorizontal();
  661. EditorGUILayout.Space(2);
  662. EditorGUILayout.BeginVertical();
  663. GUILayout.FlexibleSpace();
  664. DrawUserIcon.ForPendingChangesTab(CommentText);
  665. GUILayout.FlexibleSpace();
  666. EditorGUILayout.EndVertical();
  667. float width = Mathf.Clamp(mParentWindow.position.width, 300f, 820f);
  668. DrawCommentTextArea.For(
  669. this,
  670. width,
  671. mProgressControls.IsOperationRunning());
  672. EditorGUILayout.Space(2);
  673. // To center the action buttons vertically
  674. EditorGUILayout.BeginVertical();
  675. GUILayout.FlexibleSpace();
  676. DoOperationsToolbar(
  677. mWkInfo,
  678. mIsGluonMode,
  679. mUndoDropdownMenu,
  680. mProgressControls.IsOperationRunning());
  681. GUILayout.FlexibleSpace();
  682. EditorGUILayout.EndVertical();
  683. GUILayout.FlexibleSpace();
  684. EditorGUILayout.EndHorizontal();
  685. EditorGUILayout.Space(10);
  686. EditorGUILayout.EndVertical();
  687. }
  688. void DoOperationsToolbar(
  689. WorkspaceInfo wkInfo,
  690. bool isGluonMode,
  691. GenericMenu undoDropdownMenu,
  692. bool isOperationRunning)
  693. {
  694. EditorGUILayout.BeginHorizontal();
  695. using (new GuiEnabled(!isOperationRunning))
  696. {
  697. if(mHasPendingCheckinFromPreviousUpdate)
  698. {
  699. mHasPendingCheckinFromPreviousUpdate = false;
  700. CheckinForMode(wkInfo, isGluonMode, mKeepItemsLocked);
  701. }
  702. if (DrawActionButton.ForCommentSection(
  703. PlasticLocalization.GetString(
  704. PlasticLocalization.Name.CheckinChanges)))
  705. {
  706. UpdateIsCommentWarningNeeded(CommentText);
  707. if (!mIsEmptyCheckinCommentWarningNeeded)
  708. {
  709. CheckinForMode(wkInfo, isGluonMode, mKeepItemsLocked);
  710. }
  711. }
  712. GUILayout.Space(2);
  713. DoUndoButton(wkInfo, isGluonMode, undoDropdownMenu);
  714. if (isGluonMode)
  715. {
  716. mKeepItemsLocked = EditorGUILayout.ToggleLeft(
  717. PlasticLocalization.GetString(PlasticLocalization.Name.KeepLocked),
  718. mKeepItemsLocked,
  719. GUILayout.Width(UnityConstants.EXTRA_LARGE_BUTTON_WIDTH));
  720. }
  721. }
  722. EditorGUILayout.EndHorizontal();
  723. }
  724. void DoUndoButton(WorkspaceInfo wkInfo, bool isGluonMode, GenericMenu undoDropdownMenu)
  725. {
  726. string undoText = PlasticLocalization.GetString(PlasticLocalization.Name.UndoChanges);
  727. if (isGluonMode)
  728. {
  729. if (DrawActionButton.ForCommentSection(undoText))
  730. {
  731. UndoChangesAction(wkInfo, true);
  732. }
  733. }
  734. else
  735. {
  736. DrawActionButtonWithMenu.For(
  737. undoText,
  738. () => UndoChangesAction(wkInfo, false),
  739. undoDropdownMenu);
  740. }
  741. }
  742. void UndoChangesAction(WorkspaceInfo wkInfo, bool isGluonMode)
  743. {
  744. TrackFeatureUseEvent.For(PlasticGui.Plastic.API.GetRepositorySpec(wkInfo),
  745. TrackFeatureUseEvent.Features.UndoTextButton);
  746. UndoForMode(wkInfo, isGluonMode);
  747. }
  748. void UpdateChangesTree(List<ChangeInfo> changes)
  749. {
  750. mPendingChangesTreeView.BuildModel(changes, mCheckedStateManager);
  751. mPendingChangesTreeView.Refilter();
  752. mPendingChangesTreeView.Sort();
  753. mPendingChangesTreeView.Reload();
  754. }
  755. static void DoWarningMessage(string message)
  756. {
  757. GUILayout.Label(message, UnityStyles.WarningMessage);
  758. }
  759. void UpdateMergeLinksList()
  760. {
  761. mMergeLinksListView.BuildModel(mPendingMergeLinks);
  762. mMergeLinksListView.Reload();
  763. if (!HasPendingMergeLinks())
  764. mHasPendingMergeLinksFromRevert = false;
  765. }
  766. void ClearAssetStatusCache()
  767. {
  768. if (mAssetStatusCache != null)
  769. mAssetStatusCache.Clear();
  770. ProjectWindow.Repaint();
  771. RepaintInspector.All();
  772. }
  773. void UpdateNotificationPanel()
  774. {
  775. if (PlasticGui.Plastic.API.IsFsReaderWatchLimitReached(mWkInfo))
  776. {
  777. ((IProgressControls)mProgressControls).ShowWarning(PlasticLocalization.
  778. GetString(PlasticLocalization.Name.NotifyLinuxWatchLimitWarning));
  779. return;
  780. }
  781. }
  782. void DoActionsToolbar(
  783. WorkspaceInfo workspaceInfo,
  784. bool isGluonMode,
  785. ProgressControlsForViews progressControls)
  786. {
  787. EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
  788. if (progressControls.IsOperationRunning())
  789. {
  790. DrawProgressForViews.ForIndeterminateProgress(
  791. progressControls.ProgressData);
  792. }
  793. GUILayout.FlexibleSpace();
  794. EditorGUILayout.EndHorizontal();
  795. }
  796. static void DoChangesArea(
  797. PendingChangesTreeView changesTreeView,
  798. bool isOperationRunning,
  799. bool isCheckedInSuccessful,
  800. string organizationToInviteUsers)
  801. {
  802. GUI.enabled = !isOperationRunning;
  803. Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
  804. changesTreeView.OnGUI(rect);
  805. if (changesTreeView.GetTotalItemCount() == 0)
  806. {
  807. DrawEmptyState(rect, isCheckedInSuccessful, organizationToInviteUsers);
  808. }
  809. GUI.enabled = true;
  810. }
  811. static void DrawEmptyState(
  812. Rect rect,
  813. bool isCheckedInSuccessful,
  814. string organizationToInviteUsers)
  815. {
  816. if (isCheckedInSuccessful)
  817. {
  818. DrawCheckinSuccessfulEmptyState(rect, organizationToInviteUsers);
  819. return;
  820. }
  821. DrawNoPendingChangesEmptyState(rect);
  822. }
  823. static void DrawNoPendingChangesEmptyState(Rect rect)
  824. {
  825. DrawTreeViewEmptyState.For(
  826. rect,
  827. PlasticLocalization.GetString(PlasticLocalization.Name.NoPendingChanges));
  828. }
  829. static void DrawCheckinSuccessfulEmptyState(
  830. Rect rect,
  831. string organizationToInviteUsers)
  832. {
  833. if (string.IsNullOrEmpty(organizationToInviteUsers))
  834. {
  835. DrawTreeViewEmptyState.For(
  836. rect,
  837. PlasticLocalization.GetString(PlasticLocalization.Name.CheckinCompleted),
  838. Images.GetStepOkIcon());
  839. return;
  840. }
  841. DrawInviteOtherTeamMembersEmptyState(rect, organizationToInviteUsers);
  842. }
  843. static void DrawInviteOtherTeamMembersEmptyState(Rect rect, string organizationToInviteUsers)
  844. {
  845. ExternalLink inviteUsersLink = new ExternalLink
  846. {
  847. Label = PlasticLocalization.GetString(PlasticLocalization.Name.InviteOtherTeamMembers),
  848. Url = UnityUrl.UnityDashboard.Plastic.GetForInviteUsers(
  849. organizationToInviteUsers, UnityUrl.UnityDashboard.UnityCloudRequestSource.Editor)
  850. };
  851. DrawTreeViewEmptyState.For(
  852. rect,
  853. PlasticLocalization.GetString(PlasticLocalization.Name.CheckinCompleted),
  854. Images.GetStepOkIcon(),
  855. inviteUsersLink);
  856. }
  857. bool HasPendingMergeLinks()
  858. {
  859. if (mPendingMergeLinks == null)
  860. return false;
  861. return mPendingMergeLinks.Count > 0;
  862. }
  863. static void DoMergeLinksArea(
  864. MergeLinksListView mergeLinksListView, float width)
  865. {
  866. GUILayout.Label(
  867. PlasticLocalization.GetString(
  868. PlasticLocalization.Name.MergeLinkDescriptionColumn),
  869. EditorStyles.boldLabel);
  870. float desiredTreeHeight = mergeLinksListView.DesiredHeight;
  871. Rect treeRect = GUILayoutUtility.GetRect(
  872. 0,
  873. width,
  874. desiredTreeHeight,
  875. desiredTreeHeight);
  876. mergeLinksListView.OnGUI(treeRect);
  877. }
  878. void BuildComponents(
  879. bool isGluonMode,
  880. EditorWindow plasticWindow)
  881. {
  882. mHelpPanel = new HelpPanel(plasticWindow);
  883. mUndoDropdownMenu = new GenericMenu();
  884. mUndoDropdownMenu.AddItem(
  885. new GUIContent(PlasticLocalization.GetString(PlasticLocalization.Name.UndoUnchangedButton)),
  886. false, UndoUnchanged);
  887. mUndoDropdownMenu.AddItem(
  888. new GUIContent(PlasticLocalization.GetString(PlasticLocalization.Name.UndoCheckoutsKeepingChanges)),
  889. false, UndoCheckoutsKeepingChanges);
  890. mSearchField = new SearchField();
  891. mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
  892. PendingChangesTreeHeaderState headerState =
  893. PendingChangesTreeHeaderState.GetDefault(isGluonMode);
  894. TreeHeaderSettings.Load(headerState,
  895. UnityConstants.PENDING_CHANGES_TABLE_SETTINGS_NAME,
  896. (int)PendingChangesTreeColumn.Item, true);
  897. mPendingChangesTreeView = new PendingChangesTreeView(
  898. mWkInfo, mIsGluonMode, headerState,
  899. PendingChangesTreeHeaderState.GetColumnNames(),
  900. new PendingChangesViewMenu(mWkInfo, this, this, this, this, this, this, this, mIsGluonMode),
  901. mAssetStatusCache);
  902. mPendingChangesTreeView.Reload();
  903. mMergeLinksListView = new MergeLinksListView();
  904. mMergeLinksListView.Reload();
  905. }
  906. INewChangesInWk mNewChangesInWk;
  907. GenericMenu mUndoDropdownMenu;
  908. void ClearComments()
  909. {
  910. CommentText = string.Empty;
  911. ForceToShowComment = true;
  912. mParentWindow.Repaint();
  913. }
  914. PendingChangesTreeView mPendingChangesTreeView;
  915. MergeLinksListView mMergeLinksListView;
  916. HelpPanel mHelpPanel;
  917. volatile bool mAreIgnoreRulesInitialized = false;
  918. bool mIsRefreshing;
  919. bool mIsAutoRefreshDisabled;
  920. bool mIsEmptyCheckinCommentWarningNeeded = false;
  921. bool mNeedsToShowEmptyCommentDialog = false;
  922. bool mHasPendingCheckinFromPreviousUpdate = false;
  923. bool mHasPendingMergeLinksFromRevert = false;
  924. bool mKeepItemsLocked;
  925. string mGluonWarningMessage;
  926. bool mIsCheckedInSuccessful;
  927. string mOrganizationToInviteUsers;
  928. IDictionary<MountPoint, IList<PendingMergeLink>> mPendingMergeLinks;
  929. SearchField mSearchField;
  930. Color mBorderColor;
  931. readonly ProgressControlsForViews mProgressControls;
  932. readonly EditorWindow mParentWindow;
  933. readonly StatusBar mStatusBar;
  934. readonly CooldownWindowDelayer mCooldownClearCheckinSuccessAction;
  935. readonly IAssetStatusCache mAssetStatusCache;
  936. readonly PendingChangesOperations mPendingChangesOperations;
  937. readonly PendingChangesViewCheckedStateManager mCheckedStateManager;
  938. readonly GuiMessage.IGuiMessage mGuiMessage;
  939. readonly NewIncomingChangesUpdater mDeveloperNewIncomingChangesUpdater;
  940. readonly GluonNewIncomingChangesUpdater mGluonNewIncomingChangesUpdater;
  941. readonly bool mIsGluonMode;
  942. readonly WorkspaceOperationsMonitor mWorkspaceOperationsMonitor;
  943. readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
  944. readonly IHistoryViewLauncher mHistoryViewLauncher;
  945. readonly WorkspaceWindow mWorkspaceWindow;
  946. readonly ViewHost mViewHost;
  947. readonly WorkspaceInfo mWkInfo;
  948. static readonly ILog mLog = PlasticApp.GetLogger("PendingChangesTab");
  949. }
  950. }