ChangesetsTab.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEditor.IMGUI.Controls;
  5. using UnityEngine;
  6. using Codice.Client.Commands;
  7. using Codice.Client.Common.Threading;
  8. using Codice.CM.Common;
  9. using PlasticGui;
  10. using PlasticGui.WorkspaceWindow.QueryViews;
  11. using PlasticGui.WorkspaceWindow.QueryViews.Changesets;
  12. using Unity.PlasticSCM.Editor.UI;
  13. using Unity.PlasticSCM.Editor.UI.Progress;
  14. using Unity.PlasticSCM.Editor.UI.Tree;
  15. using Unity.PlasticSCM.Editor.Views.Diff;
  16. namespace Unity.PlasticSCM.Editor.Views.Changesets
  17. {
  18. internal class ChangesetsTab :
  19. IRefreshableView,
  20. IChangesetMenuOperations,
  21. ChangesetsViewMenu.IMenuOperations
  22. {
  23. internal ChangesetsTab(
  24. WorkspaceInfo wkInfo,
  25. IWorkspaceWindow workspaceWindow,
  26. IViewSwitcher viewSwitcher,
  27. IHistoryViewLauncher historyViewLauncher,
  28. EditorWindow parentWindow,
  29. bool isGluonMode)
  30. {
  31. mWkInfo = wkInfo;
  32. mParentWindow = parentWindow;
  33. mIsGluonMode = isGluonMode;
  34. BuildComponents(
  35. wkInfo, workspaceWindow, viewSwitcher,
  36. historyViewLauncher, parentWindow);
  37. mProgressControls = new ProgressControlsForViews();
  38. mSplitterState = PlasticSplitterGUILayout.InitSplitterState(
  39. new float[] { 0.50f, 0.50f },
  40. new int[] { 100, 100 },
  41. new int[] { 100000, 100000 }
  42. );
  43. ((IRefreshableView)this).Refresh();
  44. }
  45. internal void OnDisable()
  46. {
  47. mDiffPanel.OnDisable();
  48. mSearchField.downOrUpArrowKeyPressed -=
  49. SearchField_OnDownOrUpArrowKeyPressed;
  50. TreeHeaderSettings.Save(
  51. mChangesetsListView.multiColumnHeader.state,
  52. UnityConstants.CHANGESETS_TABLE_SETTINGS_NAME);
  53. BoolSetting.Save(
  54. mIsChangesPanelVisible,
  55. UnityConstants.CHANGESETS_SHOW_CHANGES_SETTING_NAME);
  56. }
  57. internal void Update()
  58. {
  59. mDiffPanel.Update();
  60. mProgressControls.UpdateProgress(mParentWindow);
  61. }
  62. internal void OnGUI()
  63. {
  64. InitializeShowChangesButtonWidth();
  65. bool wasChangesPanelVisible = mIsChangesPanelVisible;
  66. DoActionsToolbar(
  67. this,
  68. mProgressControls,
  69. mSearchField,
  70. mChangesetsListView,
  71. mDateFilter,
  72. mChangesetsLabelText,
  73. mShowChangesButtonWidth,
  74. wasChangesPanelVisible);
  75. if (mIsChangesPanelVisible)
  76. {
  77. PlasticSplitterGUILayout.BeginVerticalSplit(mSplitterState);
  78. }
  79. DoChangesetsArea(
  80. mChangesetsListView,
  81. mProgressControls.IsOperationRunning());
  82. if (mIsChangesPanelVisible)
  83. {
  84. if (!wasChangesPanelVisible)
  85. mShouldScrollToSelection = true;
  86. DoChangesArea(mDiffPanel);
  87. PlasticSplitterGUILayout.EndVerticalSplit();
  88. }
  89. }
  90. void IRefreshableView.Refresh()
  91. {
  92. string query = GetChangesetsQuery(mDateFilter);
  93. FillChangesets(mWkInfo, query);
  94. }
  95. int IChangesetMenuOperations.GetSelectedChangesetsCount()
  96. {
  97. return ChangesetsSelection.GetSelectedChangesetsCount(mChangesetsListView);
  98. }
  99. void IChangesetMenuOperations.DiffChangeset()
  100. {
  101. LaunchDiffOperations.DiffChangeset(
  102. ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
  103. ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
  104. mIsGluonMode);
  105. }
  106. void IChangesetMenuOperations.DiffSelectedChangesets()
  107. {
  108. List<RepObjectInfo> selectedChangesets = ChangesetsSelection.
  109. GetSelectedRepObjectInfos(mChangesetsListView);
  110. if (selectedChangesets.Count < 2)
  111. return;
  112. LaunchDiffOperations.DiffSelectedChangesets(
  113. ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
  114. (ChangesetExtendedInfo)selectedChangesets[0],
  115. (ChangesetExtendedInfo)selectedChangesets[1],
  116. mIsGluonMode);
  117. }
  118. void IChangesetMenuOperations.DiffWithAnotherChangeset() { }
  119. void IChangesetMenuOperations.CreateBranch() { }
  120. void IChangesetMenuOperations.LabelChangeset() { }
  121. void IChangesetMenuOperations.SwitchToChangeset() { }
  122. void IChangesetMenuOperations.MergeChangeset() {}
  123. void IChangesetMenuOperations.CherryPickChangeset() { }
  124. void IChangesetMenuOperations.SubtractiveChangeset() { }
  125. void IChangesetMenuOperations.SubtractiveChangesetInterval() { }
  126. void IChangesetMenuOperations.CherryPickChangesetInterval() { }
  127. void IChangesetMenuOperations.MergeToChangeset() { }
  128. void IChangesetMenuOperations.MoveChangeset() { }
  129. void IChangesetMenuOperations.DeleteChangeset() { }
  130. void IChangesetMenuOperations.BrowseRepositoryOnChangeset() { }
  131. void IChangesetMenuOperations.CreateCodeReview() { }
  132. void SearchField_OnDownOrUpArrowKeyPressed()
  133. {
  134. mChangesetsListView.SetFocusAndEnsureSelectedItem();
  135. }
  136. void FillChangesets(WorkspaceInfo wkInfo, string query)
  137. {
  138. if (mIsRefreshing)
  139. return;
  140. mIsRefreshing = true;
  141. List<RepObjectInfo> changesetsToSelect =
  142. ChangesetsSelection.GetSelectedRepObjectInfos(mChangesetsListView);
  143. int defaultRow = TableViewOperations.
  144. GetFirstSelectedRow(mChangesetsListView);
  145. ((IProgressControls)mProgressControls).ShowProgress(
  146. PlasticLocalization.GetString(
  147. PlasticLocalization.Name.LoadingChangesets));
  148. long loadedChangesetId = -1;
  149. ViewQueryResult queryResult = null;
  150. IThreadWaiter waiter = ThreadWaiter.GetWaiter();
  151. waiter.Execute(
  152. /*threadOperationDelegate*/ delegate
  153. {
  154. queryResult = new ViewQueryResult(
  155. PlasticGui.Plastic.API.FindQuery(wkInfo, query));
  156. loadedChangesetId = GetLoadedChangesetId(
  157. wkInfo, mIsGluonMode);
  158. },
  159. /*afterOperationDelegate*/ delegate
  160. {
  161. try
  162. {
  163. if (waiter.Exception != null)
  164. {
  165. ExceptionsHandler.DisplayException(waiter.Exception);
  166. return;
  167. }
  168. int changesetsCount = GetChangesetsCount(queryResult);
  169. mChangesetsLabelText = string.Format(
  170. PlasticLocalization.GetString(PlasticLocalization.Name.ChangesetsCount),
  171. changesetsCount);
  172. UpdateChangesetsList(
  173. mChangesetsListView,
  174. queryResult,
  175. loadedChangesetId);
  176. if (changesetsCount == 0)
  177. {
  178. mDiffPanel.ClearInfo();
  179. return;
  180. }
  181. ChangesetsSelection.SelectChangesets(
  182. mChangesetsListView, changesetsToSelect, defaultRow);
  183. }
  184. finally
  185. {
  186. ((IProgressControls)mProgressControls).HideProgress();
  187. mIsRefreshing = false;
  188. }
  189. });
  190. }
  191. void ChangesetsViewMenu.IMenuOperations.DiffBranch()
  192. {
  193. LaunchDiffOperations.DiffBranch(
  194. ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
  195. ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
  196. mIsGluonMode);
  197. }
  198. ChangesetExtendedInfo ChangesetsViewMenu.IMenuOperations.GetSelectedChangeset()
  199. {
  200. return ChangesetsSelection.GetSelectedChangeset(
  201. mChangesetsListView);
  202. }
  203. void OnChangesetsListViewSizeChanged()
  204. {
  205. if (!mShouldScrollToSelection)
  206. return;
  207. mShouldScrollToSelection = false;
  208. TableViewOperations.ScrollToSelection(mChangesetsListView);
  209. }
  210. void OnSelectionChanged()
  211. {
  212. List<RepObjectInfo> selectedChangesets = ChangesetsSelection.
  213. GetSelectedRepObjectInfos(mChangesetsListView);
  214. if (selectedChangesets.Count != 1)
  215. return;
  216. mDiffPanel.UpdateInfo(
  217. MountPointWithPath.BuildWorkspaceRootMountPoint(
  218. ChangesetsSelection.GetSelectedRepository(mChangesetsListView)),
  219. (ChangesetExtendedInfo)selectedChangesets[0]);
  220. }
  221. static void UpdateChangesetsList(
  222. ChangesetsListView changesetsListView,
  223. ViewQueryResult queryResult,
  224. long loadedChangesetId)
  225. {
  226. changesetsListView.BuildModel(
  227. queryResult,
  228. loadedChangesetId);
  229. changesetsListView.Refilter();
  230. changesetsListView.Sort();
  231. changesetsListView.Reload();
  232. }
  233. static long GetLoadedChangesetId(
  234. WorkspaceInfo wkInfo,
  235. bool isGluonMode)
  236. {
  237. if (isGluonMode)
  238. return -1;
  239. return PlasticGui.Plastic.API.GetLoadedChangeset(wkInfo);
  240. }
  241. static string GetChangesetsQuery(DateFilter dateFilter)
  242. {
  243. if (dateFilter.FilterType == DateFilter.Type.AllTime)
  244. return QueryConstants.ChangesetsBeginningQuery;
  245. string whereClause = QueryConstants.GetChangesetsDateWhereClause(
  246. dateFilter.GetFilterDate(DateTime.UtcNow));
  247. return string.Format("{0} {1}",
  248. QueryConstants.ChangesetsBeginningQuery,
  249. whereClause);
  250. }
  251. static int GetChangesetsCount(
  252. ViewQueryResult queryResult)
  253. {
  254. if (queryResult == null)
  255. return 0;
  256. return queryResult.Count();
  257. }
  258. void DoActionsToolbar(
  259. IRefreshableView refreshableView,
  260. ProgressControlsForViews progressControls,
  261. SearchField searchField,
  262. ChangesetsListView changesetsListView,
  263. DateFilter dateFilter,
  264. string changesetsLabelText,
  265. float showChangesButtonWidth,
  266. bool wasChangesPanelVisible)
  267. {
  268. EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
  269. if (!string.IsNullOrEmpty(changesetsLabelText))
  270. {
  271. GUILayout.Label(
  272. changesetsLabelText,
  273. UnityStyles.ChangesetsTab.HeaderLabel);
  274. }
  275. if (progressControls.IsOperationRunning())
  276. {
  277. DrawProgressForViews.ForIndeterminateProgress(
  278. progressControls.ProgressData);
  279. }
  280. GUILayout.FlexibleSpace();
  281. mIsChangesPanelVisible =
  282. DoShowChangesButton(
  283. showChangesButtonWidth,
  284. wasChangesPanelVisible);
  285. GUILayout.Space(2);
  286. DrawSearchField.For(
  287. searchField,
  288. changesetsListView,
  289. UnityConstants.SEARCH_FIELD_WIDTH);
  290. DoDateFilter(
  291. refreshableView,
  292. dateFilter,
  293. progressControls.IsOperationRunning());
  294. DoRefreshButton(
  295. refreshableView,
  296. progressControls.IsOperationRunning());
  297. EditorGUILayout.EndHorizontal();
  298. }
  299. static void DoChangesetsArea(
  300. ChangesetsListView changesetsListView,
  301. bool isOperationRunning)
  302. {
  303. EditorGUILayout.BeginVertical();
  304. GUI.enabled = !isOperationRunning;
  305. Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
  306. changesetsListView.OnGUI(rect);
  307. GUI.enabled = true;
  308. EditorGUILayout.EndVertical();
  309. }
  310. static void DoChangesArea(DiffPanel diffPanel)
  311. {
  312. EditorGUILayout.BeginVertical();
  313. diffPanel.OnGUI();
  314. EditorGUILayout.EndVertical();
  315. }
  316. static bool DoShowChangesButton(
  317. float showChangesButtonWidth,
  318. bool wasChecked)
  319. {
  320. string buttonText = wasChecked ?
  321. PlasticLocalization.GetString(PlasticLocalization.Name.HideChanges) :
  322. PlasticLocalization.GetString(PlasticLocalization.Name.ShowChanges);
  323. GUIContent buttonContent = new GUIContent(buttonText);
  324. GUIStyle buttonStyle = EditorStyles.toolbarButton;
  325. Rect toggleRect = GUILayoutUtility.GetRect(
  326. buttonContent, buttonStyle,
  327. GUILayout.Width(showChangesButtonWidth));
  328. bool isChecked = GUI.Toggle(
  329. toggleRect, wasChecked, buttonContent, buttonStyle);
  330. return isChecked;
  331. }
  332. static void DoDateFilter(
  333. IRefreshableView refreshableView,
  334. DateFilter dateFilter,
  335. bool isOperationRunning)
  336. {
  337. GUI.enabled = !isOperationRunning;
  338. EditorGUI.BeginChangeCheck();
  339. dateFilter.FilterType = (DateFilter.Type)
  340. EditorGUILayout.EnumPopup(
  341. dateFilter.FilterType,
  342. EditorStyles.toolbarDropDown,
  343. GUILayout.Width(100));
  344. if (EditorGUI.EndChangeCheck())
  345. {
  346. EnumPopupSetting<DateFilter.Type>.Save(
  347. dateFilter.FilterType,
  348. UnityConstants.CHANGESETS_DATE_FILTER_SETTING_NAME);
  349. refreshableView.Refresh();
  350. }
  351. GUI.enabled = true;
  352. }
  353. static void DoRefreshButton(
  354. IRefreshableView refreshableView,
  355. bool isOperationRunning)
  356. {
  357. EditorGUI.BeginDisabledGroup(isOperationRunning);
  358. if (GUILayout.Button(new GUIContent(
  359. Images.GetRefreshIcon()), EditorStyles.toolbarButton))
  360. refreshableView.Refresh();
  361. EditorGUI.EndDisabledGroup();
  362. }
  363. void InitializeShowChangesButtonWidth()
  364. {
  365. if (mShowChangesButtonWidth != -1)
  366. return;
  367. mShowChangesButtonWidth = MeasureMaxWidth.ForTexts(
  368. EditorStyles.toolbarButton,
  369. PlasticLocalization.GetString(PlasticLocalization.Name.HideChanges),
  370. PlasticLocalization.GetString(PlasticLocalization.Name.ShowChanges));
  371. }
  372. void BuildComponents(
  373. WorkspaceInfo wkInfo,
  374. IWorkspaceWindow workspaceWindow,
  375. IViewSwitcher viewSwitcher,
  376. IHistoryViewLauncher historyViewLauncher,
  377. EditorWindow parentWindow)
  378. {
  379. mSearchField = new SearchField();
  380. mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
  381. DateFilter.Type dateFilterType =
  382. EnumPopupSetting<DateFilter.Type>.Load(
  383. UnityConstants.CHANGESETS_DATE_FILTER_SETTING_NAME,
  384. DateFilter.Type.LastMonth);
  385. mDateFilter = new DateFilter(dateFilterType);
  386. ChangesetsListHeaderState headerState =
  387. ChangesetsListHeaderState.GetDefault();
  388. TreeHeaderSettings.Load(headerState,
  389. UnityConstants.CHANGESETS_TABLE_SETTINGS_NAME,
  390. (int)ChangesetsListColumn.CreationDate, false);
  391. mChangesetsListView = new ChangesetsListView(
  392. headerState,
  393. ChangesetsListHeaderState.GetColumnNames(),
  394. new ChangesetsViewMenu(this, this, mIsGluonMode),
  395. sizeChangedAction: OnChangesetsListViewSizeChanged,
  396. selectionChangedAction: OnSelectionChanged,
  397. doubleClickAction: ((IChangesetMenuOperations)this).DiffChangeset);
  398. mChangesetsListView.Reload();
  399. mIsChangesPanelVisible = BoolSetting.Load(
  400. UnityConstants.CHANGESETS_SHOW_CHANGES_SETTING_NAME,
  401. true);
  402. mDiffPanel = new DiffPanel(
  403. wkInfo, workspaceWindow, viewSwitcher,
  404. historyViewLauncher, parentWindow, mIsGluonMode);
  405. }
  406. bool mIsRefreshing;
  407. bool mShouldScrollToSelection;
  408. bool mIsChangesPanelVisible;
  409. float mShowChangesButtonWidth = -1;
  410. string mChangesetsLabelText;
  411. object mSplitterState;
  412. DateFilter mDateFilter;
  413. SearchField mSearchField;
  414. ChangesetsListView mChangesetsListView;
  415. DiffPanel mDiffPanel;
  416. readonly bool mIsGluonMode;
  417. readonly ProgressControlsForViews mProgressControls;
  418. readonly EditorWindow mParentWindow;
  419. readonly WorkspaceInfo mWkInfo;
  420. }
  421. }