Geen omschrijving
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

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