A game about forced loneliness, made by TACStudios
1using System.Collections.Generic;
2
3using UnityEditor;
4using UnityEditor.IMGUI.Controls;
5using UnityEngine;
6
7using Codice.Client.Common;
8using Codice.Client.Common.Threading;
9using Codice.CM.Common;
10using Codice.CM.Common.Mount;
11using PlasticGui;
12using PlasticGui.WorkspaceWindow;
13using PlasticGui.WorkspaceWindow.Update;
14using PlasticGui.WorkspaceWindow.QueryViews;
15using PlasticGui.WorkspaceWindow.QueryViews.Changesets;
16using GluonGui;
17using PlasticGui.WorkspaceWindow.CodeReview;
18using Unity.PlasticSCM.Editor.AssetUtils;
19using Unity.PlasticSCM.Editor.AssetUtils.Processor;
20using Unity.PlasticSCM.Editor.UI;
21using Unity.PlasticSCM.Editor.UI.Progress;
22using Unity.PlasticSCM.Editor.UI.Tree;
23using Unity.PlasticSCM.Editor.Tool;
24using Unity.PlasticSCM.Editor.Views.Diff;
25
26using GluonNewIncomingChangesUpdater = PlasticGui.Gluon.WorkspaceWindow.NewIncomingChangesUpdater;
27using IGluonUpdateReport = PlasticGui.Gluon.IUpdateReport;
28
29namespace Unity.PlasticSCM.Editor.Views.Changesets
30{
31 internal partial class ChangesetsTab :
32 IRefreshableView,
33 IChangesetMenuOperations,
34 ChangesetsViewMenu.IMenuOperations,
35 ILaunchCodeReviewWindow
36 {
37 internal ChangesetsListView Table { get { return mChangesetsListView; } }
38 internal IChangesetMenuOperations Operations { get { return this; } }
39
40 internal interface IRevertToChangesetListener
41 {
42 void OnSuccessOperation();
43 }
44
45 internal ChangesetsTab(
46 WorkspaceInfo wkInfo,
47 WorkspaceWindow workspaceWindow,
48 ChangesetInfo changesetToSelect,
49 IViewSwitcher viewSwitcher,
50 IMergeViewLauncher mergeViewLauncher,
51 IHistoryViewLauncher historyViewLauncher,
52 ViewHost viewHost,
53 IUpdateReport updateReport,
54 IGluonUpdateReport gluonUpdateReport,
55 NewIncomingChangesUpdater developerNewIncomingChangesUpdater,
56 GluonNewIncomingChangesUpdater gluonNewIncomingChangesUpdater,
57 IShelvedChangesUpdater shelvedChangesUpdater,
58 IRevertToChangesetListener revertToChangesetListener,
59 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
60 LaunchTool.IProcessExecutor processExecutor,
61 WorkspaceOperationsMonitor workspaceOperationsMonitor,
62 ISaveAssets saveAssets,
63 EditorWindow parentWindow,
64 bool isGluonMode)
65 {
66 mWkInfo = wkInfo;
67 mViewHost = viewHost;
68 mWorkspaceWindow = workspaceWindow;
69 mViewSwitcher = viewSwitcher;
70 mRevertToChangesetListener = revertToChangesetListener;
71 mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
72 mProcessExecutor = processExecutor;
73 mWorkspaceOperationsMonitor = workspaceOperationsMonitor;
74 mSaveAssets = saveAssets;
75 mParentWindow = parentWindow;
76 mIsGluonMode = isGluonMode;
77 mGluonUpdateReport = gluonUpdateReport;
78
79 mGluonNewIncomingChangesUpdater = gluonNewIncomingChangesUpdater;
80 mShelvePendingChangesQuestionerBuilder = new ShelvePendingChangesQuestionerBuilder(parentWindow);
81 mShelvedChangesUpdater = shelvedChangesUpdater;
82 mEnableSwitchAndShelveFeatureDialog = new EnableSwitchAndShelveFeature(
83 PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
84 mParentWindow);
85
86 BuildComponents(
87 wkInfo,
88 workspaceWindow,
89 workspaceWindow,
90 viewSwitcher,
91 historyViewLauncher,
92 parentWindow);
93
94 mProgressControls = new ProgressControlsForViews();
95
96 mSplitterState = PlasticSplitterGUILayout.InitSplitterState(
97 new float[] { 0.50f, 0.50f },
98 new int[] { 100, (int)UnityConstants.DIFF_PANEL_MIN_WIDTH },
99 new int[] { 100000, 100000 }
100 );
101
102 mChangesetOperations = new ChangesetOperations(
103 wkInfo,
104 workspaceWindow,
105 viewSwitcher,
106 mergeViewLauncher,
107 ViewType.ChangesetsView,
108 mProgressControls,
109 updateReport,
110 new ContinueWithPendingChangesQuestionerBuilder(viewSwitcher, parentWindow),
111 mShelvePendingChangesQuestionerBuilder,
112 new ApplyShelveWithConflictsQuestionerBuilder(),
113 developerNewIncomingChangesUpdater,
114 shelvedChangesUpdater,
115 null,
116 null,
117 mEnableSwitchAndShelveFeatureDialog);
118
119 RefreshAndSelect(changesetToSelect);
120 }
121
122 internal void OnEnable()
123 {
124 mDiffPanel.OnEnable();
125
126 mSearchField.downOrUpArrowKeyPressed +=
127 SearchField_OnDownOrUpArrowKeyPressed;
128 }
129
130 internal void OnDisable()
131 {
132 mDiffPanel.OnDisable();
133
134 mSearchField.downOrUpArrowKeyPressed -=
135 SearchField_OnDownOrUpArrowKeyPressed;
136
137 TreeHeaderSettings.Save(
138 mChangesetsListView.multiColumnHeader.state,
139 UnityConstants.CHANGESETS_TABLE_SETTINGS_NAME);
140 }
141
142 internal void Update()
143 {
144 mDiffPanel.Update();
145
146 mProgressControls.UpdateProgress(mParentWindow);
147 }
148
149 internal void OnGUI()
150 {
151 DoActionsToolbar(mProgressControls);
152
153 PlasticSplitterGUILayout.BeginHorizontalSplit(mSplitterState);
154
155 DoChangesetsArea(
156 mChangesetsListView,
157 mProgressControls.IsOperationRunning());
158
159 EditorGUILayout.BeginHorizontal();
160
161 Rect border = GUILayoutUtility.GetRect(1, 0, 1, 100000);
162 EditorGUI.DrawRect(border, UnityStyles.Colors.BarBorder);
163
164 DoChangesArea(mDiffPanel);
165
166 EditorGUILayout.EndHorizontal();
167
168 PlasticSplitterGUILayout.EndHorizontalSplit();
169
170 }
171
172 internal void DrawSearchFieldForTab()
173 {
174 DrawSearchField.For(
175 mSearchField,
176 mChangesetsListView,
177 UnityConstants.SEARCH_FIELD_WIDTH);
178 }
179
180 internal void DrawDateFilter()
181 {
182 GUI.enabled = !mProgressControls.IsOperationRunning();
183
184 EditorGUI.BeginChangeCheck();
185
186 mDateFilter.FilterType = (DateFilter.Type)
187 EditorGUILayout.EnumPopup(
188 mDateFilter.FilterType,
189 EditorStyles.toolbarDropDown,
190 GUILayout.Width(100));
191
192 if (EditorGUI.EndChangeCheck())
193 {
194 EnumPopupSetting<DateFilter.Type>.Save(
195 mDateFilter.FilterType,
196 UnityConstants.CHANGESETS_DATE_FILTER_SETTING_NAME);
197
198 ((IRefreshableView)this).Refresh();
199 }
200
201 GUI.enabled = true;
202 }
203
204 internal void SetWorkingObjectInfo(WorkingObjectInfo homeInfo)
205 {
206 if (mIsGluonMode)
207 return;
208
209 lock (mLock)
210 {
211 mLoadedChangesetId = homeInfo.GetChangesetId();
212 }
213
214 mChangesetsListView.SetLoadedChangesetId(mLoadedChangesetId);
215 mChangesetsViewMenu.SetLoadedBranchId(homeInfo.BranchInfo.BranchId);
216 }
217
218 internal void SetRevertToChangesetOperationInterfacesForTesting(
219 RevertToChangesetOperation.IGetStatusForWorkspace getStatusForWorkspace,
220 RevertToChangesetOperation.IUndoCheckoutOperation undoCheckoutOperation,
221 RevertToChangesetOperation.IRevertToChangesetMergeController revertToChangesetMergeController)
222 {
223 mGetStatusForWorkspace = getStatusForWorkspace;
224 mUndoCheckoutOperation = undoCheckoutOperation;
225 mRevertToChangesetMergeController = revertToChangesetMergeController;
226 }
227
228 internal void SetLaunchToolForTesting(
229 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
230 LaunchTool.IProcessExecutor processExecutor)
231 {
232 mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
233 mProcessExecutor = processExecutor;
234 }
235
236 internal void RefreshAndSelect(RepObjectInfo repObj)
237 {
238 List<RepObjectInfo> changesetsToSelect = repObj == null ?
239 ChangesetsSelection.GetSelectedRepObjectInfos(mChangesetsListView) :
240 new List<RepObjectInfo> { repObj };
241
242 string query = GetChangesetsQuery(mDateFilter);
243
244 FillChangesets(
245 mWkInfo,
246 query,
247 changesetsToSelect);
248 }
249
250 void IRefreshableView.Refresh()
251 {
252 RefreshAndSelect(null);
253 }
254
255 int IChangesetMenuOperations.GetSelectedChangesetsCount()
256 {
257 return ChangesetsSelection.GetSelectedChangesetsCount(mChangesetsListView);
258 }
259
260 void IChangesetMenuOperations.DiffChangeset()
261 {
262 LaunchDiffOperations.DiffChangeset(
263 mShowDownloadPlasticExeWindow,
264 mProcessExecutor,
265 ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
266 ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
267 mIsGluonMode);
268 }
269
270 void IChangesetMenuOperations.DiffSelectedChangesets()
271 {
272 List<RepObjectInfo> selectedChangesets = ChangesetsSelection.
273 GetSelectedRepObjectInfos(mChangesetsListView);
274
275 if (selectedChangesets.Count < 2)
276 return;
277
278 LaunchDiffOperations.DiffSelectedChangesets(
279 mShowDownloadPlasticExeWindow,
280 mProcessExecutor,
281 ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
282 (ChangesetExtendedInfo)selectedChangesets[0],
283 (ChangesetExtendedInfo)selectedChangesets[1],
284 mIsGluonMode);
285 }
286
287 void IChangesetMenuOperations.SwitchToChangeset()
288 {
289 SwitchToChangesetForMode();
290 }
291
292 void IChangesetMenuOperations.DiffWithAnotherChangeset() { }
293
294 void IChangesetMenuOperations.CreateBranch()
295 {
296 CreateBranchForMode();
297 }
298
299 void IChangesetMenuOperations.LabelChangeset() { }
300
301 void IChangesetMenuOperations.MergeChangeset()
302 {
303 mChangesetOperations.MergeChangeset(
304 ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
305 ChangesetsSelection.GetSelectedChangeset(mChangesetsListView));
306 }
307
308 void IChangesetMenuOperations.CherryPickChangeset() { }
309
310 void IChangesetMenuOperations.SubtractiveChangeset() { }
311
312 void IChangesetMenuOperations.SubtractiveChangesetInterval() { }
313
314 void IChangesetMenuOperations.CherryPickChangesetInterval() { }
315
316 void IChangesetMenuOperations.MergeToChangeset() { }
317
318 void IChangesetMenuOperations.MoveChangeset() { }
319
320 void IChangesetMenuOperations.DeleteChangeset() { }
321
322 void IChangesetMenuOperations.BrowseRepositoryOnChangeset() { }
323
324 void IChangesetMenuOperations.CreateCodeReview()
325 {
326 RepositorySpec repSpec = ChangesetsSelection.GetSelectedRepository(mChangesetsListView);
327 ChangesetInfo changesetInfo = ChangesetsSelection.GetSelectedChangeset(mChangesetsListView);
328
329 NewCodeReviewBehavior choice = SelectNewCodeReviewBehavior.For(repSpec.Server);
330
331 switch (choice)
332 {
333 case NewCodeReviewBehavior.CreateAndOpenInDesktop:
334 mChangesetOperations.CreateCodeReview(repSpec, changesetInfo, this);
335 break;
336 case NewCodeReviewBehavior.RequestFromUnityCloud:
337 OpenRequestReviewPage.ForChangeset(repSpec, changesetInfo.ChangesetId);
338 break;
339 case NewCodeReviewBehavior.Ask:
340 default:
341 break;
342 }
343 }
344
345 void ILaunchCodeReviewWindow.Show(
346 WorkspaceInfo wkInfo,
347 RepositorySpec repSpec,
348 ReviewInfo reviewInfo,
349 RepObjectInfo repObjectInfo,
350 bool bShowReviewChangesTab)
351 {
352 LaunchTool.OpenCodeReview(
353 mShowDownloadPlasticExeWindow,
354 mProcessExecutor,
355 repSpec,
356 reviewInfo.Id,
357 mIsGluonMode);
358 }
359
360 void IChangesetMenuOperations.RevertToChangeset()
361 {
362 if (((IChangesetMenuOperations)this).GetSelectedChangesetsCount() != 1)
363 return;
364
365 ChangesetExtendedInfo targetChangesetInfo = ((ChangesetsViewMenu.IMenuOperations)this).GetSelectedChangeset();
366
367 RevertToChangesetOperation.RevertTo(
368 mWkInfo,
369 mViewSwitcher,
370 mWorkspaceWindow,
371 mProgressControls,
372 mGetStatusForWorkspace,
373 mUndoCheckoutOperation,
374 mRevertToChangesetMergeController,
375 GuiMessage.Get(),
376 targetChangesetInfo,
377 RefreshAsset.BeforeLongAssetOperation,
378 RefreshAsset.AfterLongAssetOperation,
379 mRevertToChangesetListener.OnSuccessOperation);
380 }
381
382 void ChangesetsViewMenu.IMenuOperations.DiffBranch()
383 {
384 LaunchDiffOperations.DiffBranch(
385 mShowDownloadPlasticExeWindow,
386 mProcessExecutor,
387 ChangesetsSelection.GetSelectedRepository(mChangesetsListView),
388 ChangesetsSelection.GetSelectedChangeset(mChangesetsListView),
389 mIsGluonMode);
390 }
391
392 ChangesetExtendedInfo ChangesetsViewMenu.IMenuOperations.GetSelectedChangeset()
393 {
394 return ChangesetsSelection.GetSelectedChangeset(
395 mChangesetsListView);
396 }
397
398 void SearchField_OnDownOrUpArrowKeyPressed()
399 {
400 mChangesetsListView.SetFocusAndEnsureSelectedItem();
401 }
402
403 void OnChangesetsListViewSizeChanged()
404 {
405 if (!mShouldScrollToSelection)
406 return;
407
408 mShouldScrollToSelection = false;
409 TableViewOperations.ScrollToSelection(mChangesetsListView);
410 }
411
412 void OnSelectionChanged()
413 {
414 List<RepObjectInfo> selectedChangesets = ChangesetsSelection.
415 GetSelectedRepObjectInfos(mChangesetsListView);
416
417 if (selectedChangesets.Count != 1)
418 return;
419
420 mDiffPanel.UpdateInfo(
421 MountPointWithPath.BuildWorkspaceRootMountPoint(
422 ChangesetsSelection.GetSelectedRepository(mChangesetsListView)),
423 (ChangesetExtendedInfo)selectedChangesets[0]);
424 }
425
426 void FillChangesets(
427 WorkspaceInfo wkInfo,
428 string query,
429 List<RepObjectInfo> changesetsToSelect)
430 {
431 if (mIsRefreshing)
432 return;
433
434 mIsRefreshing = true;
435
436 int defaultRow = TableViewOperations.GetFirstSelectedRow(mChangesetsListView);
437
438 ((IProgressControls)mProgressControls).ShowProgress(
439 PlasticLocalization.GetString(
440 PlasticLocalization.Name.LoadingChangesets));
441
442 ViewQueryResult queryResult = null;
443
444 IThreadWaiter waiter = ThreadWaiter.GetWaiter();
445 waiter.Execute(
446 /*threadOperationDelegate*/ delegate
447 {
448 queryResult = new ViewQueryResult(
449 PlasticGui.Plastic.API.FindQuery(wkInfo, query));
450
451 long changesetId = PlasticGui.Plastic.API.GetLoadedChangeset(wkInfo);
452
453 lock (mLock)
454 {
455 mLoadedChangesetId = changesetId;
456 }
457
458 BranchInfo currentBranch = PlasticGui.Plastic.API.GetWorkingBranch(wkInfo);
459
460 if (currentBranch != null)
461 mChangesetsViewMenu.SetLoadedBranchId(currentBranch.BranchId);
462 },
463 /*afterOperationDelegate*/ delegate
464 {
465 try
466 {
467 if (waiter.Exception != null)
468 {
469 mDiffPanel.ClearInfo();
470
471 ExceptionsHandler.DisplayException(waiter.Exception);
472 return;
473 }
474
475 UpdateChangesetsList(
476 mChangesetsListView,
477 queryResult,
478 mLoadedChangesetId);
479
480 int changesetsCount = GetChangesetsCount(queryResult);
481
482 if (changesetsCount == 0)
483 {
484 mDiffPanel.ClearInfo();
485 return;
486 }
487
488 ChangesetsSelection.SelectChangesets(
489 mChangesetsListView, changesetsToSelect, defaultRow);
490 }
491 finally
492 {
493 ((IProgressControls)mProgressControls).HideProgress();
494 mIsRefreshing = false;
495 }
496 });
497 }
498
499 static void UpdateChangesetsList(
500 ChangesetsListView changesetsListView,
501 ViewQueryResult queryResult,
502 long loadedChangesetId)
503 {
504 changesetsListView.BuildModel(
505 queryResult,
506 loadedChangesetId);
507
508 changesetsListView.Refilter();
509
510 changesetsListView.Sort();
511
512 changesetsListView.Reload();
513 }
514
515 static int GetChangesetsCount(
516 ViewQueryResult queryResult)
517 {
518 if (queryResult == null)
519 return 0;
520
521 return queryResult.Count();
522 }
523
524 static string GetChangesetsQuery(DateFilter dateFilter)
525 {
526 if (dateFilter.FilterType == DateFilter.Type.AllTime)
527 return QueryConstants.ChangesetsBeginningQuery;
528
529 string whereClause = QueryConstants.GetDateWhereClause(
530 dateFilter.GetTimeAgo());
531
532 return string.Format("{0} {1}",
533 QueryConstants.ChangesetsBeginningQuery,
534 whereClause);
535 }
536
537 void DoActionsToolbar(ProgressControlsForViews progressControls)
538 {
539 EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
540
541 if (progressControls.IsOperationRunning())
542 {
543 DrawProgressForViews.ForIndeterminateProgress(
544 progressControls.ProgressData);
545 }
546
547 GUILayout.FlexibleSpace();
548
549 GUILayout.Space(2);
550
551 EditorGUILayout.EndHorizontal();
552 }
553
554 static void DoChangesetsArea(
555 ChangesetsListView changesetsListView,
556 bool isOperationRunning)
557 {
558 EditorGUILayout.BeginVertical();
559
560 GUI.enabled = !isOperationRunning;
561
562 Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
563
564 changesetsListView.OnGUI(rect);
565
566 GUI.enabled = true;
567
568 EditorGUILayout.EndVertical();
569 }
570
571 static void DoChangesArea(DiffPanel diffPanel)
572 {
573 EditorGUILayout.BeginVertical();
574
575 diffPanel.OnGUI();
576
577 EditorGUILayout.EndVertical();
578 }
579
580 void BuildComponents(
581 WorkspaceInfo wkInfo,
582 IWorkspaceWindow workspaceWindow,
583 IRefreshView refreshView,
584 IViewSwitcher viewSwitcher,
585 IHistoryViewLauncher historyViewLauncher,
586 EditorWindow parentWindow)
587 {
588 mSearchField = new SearchField();
589 mSearchField.downOrUpArrowKeyPressed += SearchField_OnDownOrUpArrowKeyPressed;
590
591 DateFilter.Type dateFilterType =
592 EnumPopupSetting<DateFilter.Type>.Load(
593 UnityConstants.CHANGESETS_DATE_FILTER_SETTING_NAME,
594 DateFilter.Type.LastMonth);
595 mDateFilter = new DateFilter(dateFilterType);
596
597 ChangesetsListHeaderState headerState =
598 ChangesetsListHeaderState.GetDefault();
599 TreeHeaderSettings.Load(headerState,
600 UnityConstants.CHANGESETS_TABLE_SETTINGS_NAME,
601 (int)ChangesetsListColumn.CreationDate, false);
602
603 mChangesetsViewMenu = new ChangesetsViewMenu(
604 this,
605 this,
606 mIsGluonMode);
607
608 mChangesetsListView = new ChangesetsListView(
609 headerState,
610 ChangesetsListHeaderState.GetColumnNames(),
611 mChangesetsViewMenu,
612 sizeChangedAction: OnChangesetsListViewSizeChanged,
613 selectionChangedAction: OnSelectionChanged,
614 doubleClickAction: ((IChangesetMenuOperations)this).DiffChangeset);
615 mChangesetsListView.Reload();
616
617 mDiffPanel = new DiffPanel(
618 wkInfo, workspaceWindow, refreshView, viewSwitcher,
619 historyViewLauncher, mShowDownloadPlasticExeWindow,
620 parentWindow, mIsGluonMode);
621 }
622
623 bool mIsRefreshing;
624 bool mShouldScrollToSelection;
625
626 long mLoadedChangesetId = -1;
627
628 object mSplitterState;
629 object mLock = new object();
630
631 DateFilter mDateFilter;
632 SearchField mSearchField;
633 ChangesetsListView mChangesetsListView;
634 ChangesetsViewMenu mChangesetsViewMenu;
635 DiffPanel mDiffPanel;
636
637 RevertToChangesetOperation.IGetStatusForWorkspace mGetStatusForWorkspace =
638 new RevertToChangesetOperation.GetStatusFromWorkspace();
639 RevertToChangesetOperation.IUndoCheckoutOperation mUndoCheckoutOperation =
640 new RevertToChangesetOperation.UndoCheckout();
641 RevertToChangesetOperation.IRevertToChangesetMergeController mRevertToChangesetMergeController =
642 new RevertToChangesetOperation.RevertToChangesetMergeController();
643
644 ChangesetOperations mChangesetOperations;
645 LaunchTool.IProcessExecutor mProcessExecutor;
646 LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
647
648 readonly WorkspaceOperationsMonitor mWorkspaceOperationsMonitor;
649 readonly ISaveAssets mSaveAssets;
650 readonly bool mIsGluonMode;
651 readonly ViewHost mViewHost;
652 readonly IGluonUpdateReport mGluonUpdateReport;
653 readonly WorkspaceWindow mWorkspaceWindow;
654 readonly IViewSwitcher mViewSwitcher;
655 readonly ProgressControlsForViews mProgressControls;
656 readonly IRevertToChangesetListener mRevertToChangesetListener;
657 readonly EditorWindow mParentWindow;
658 readonly WorkspaceInfo mWkInfo;
659 readonly GluonNewIncomingChangesUpdater mGluonNewIncomingChangesUpdater;
660 readonly IShelvePendingChangesQuestionerBuilder mShelvePendingChangesQuestionerBuilder;
661 readonly IShelvedChangesUpdater mShelvedChangesUpdater;
662 readonly SwitchAndShelve.IEnableSwitchAndShelveFeatureDialog mEnableSwitchAndShelveFeatureDialog;
663 }
664}