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.

PendingChangesTab.cs 38KB

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