No Description
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.

DiffPanel.cs 18KB

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