暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

DiffPanel.cs 18KB

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