A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3
4using UnityEditor;
5using UnityEngine;
6
7using Codice.Client.BaseCommands;
8using Codice.Client.BaseCommands.Merge;
9using Codice.Client.Commands;
10using Codice.Client.Common;
11using Codice.Client.Common.FsNodeReaders;
12using Codice.Client.Common.Threading;
13using Codice.CM.Common;
14using Codice.CM.Common.Merge;
15using Codice.CM.Common.Mount;
16using PlasticGui;
17using PlasticGui.WorkspaceWindow;
18using PlasticGui.WorkspaceWindow.BranchExplorer;
19using PlasticGui.WorkspaceWindow.Topbar;
20using PlasticGui.WorkspaceWindow.Diff;
21using PlasticGui.WorkspaceWindow.Merge;
22using Unity.PlasticSCM.Editor.AssetUtils;
23using Unity.PlasticSCM.Editor.Settings;
24using Unity.PlasticSCM.Editor.Tool;
25using Unity.PlasticSCM.Editor.UI;
26using Unity.PlasticSCM.Editor.UI.Progress;
27using Unity.PlasticSCM.Editor.UI.StatusBar;
28using Unity.PlasticSCM.Editor.UI.Tree;
29using Unity.PlasticSCM.Editor.Views.Merge.Developer.DirectoryConflicts;
30using UnityEditor.IMGUI.Controls;
31using ObjectInfo = Codice.CM.Common.ObjectInfo;
32
33namespace Unity.PlasticSCM.Editor.Views.Merge.Developer
34{
35 internal class MergeTab :
36 IIncomingChangesTab,
37 IRefreshableView,
38 IMergeView,
39 IMergeViewMenuOperations,
40 MergeViewFileConflictMenu.IMetaMenuOperations
41 {
42
43 internal MergeTreeView Table { get { return mMergeTreeView; } }
44 internal ConflictResolutionState ConflictResolutionState { get { return mConflictResolutionState; } }
45 internal int DirectoryConflictCount { get { return mDirectoryConflictCount; } }
46 internal bool IsProcessingMerge { get { return mMergeViewLogic.IsProcessingMerge; } }
47 internal GUIContent ValidationLabel { get { return mValidationLabel; } }
48
49 internal static MergeTab Build(
50 WorkspaceInfo wkInfo,
51 RepositorySpec repSpec,
52 IWorkspaceWindow workspaceWindow,
53 IViewSwitcher switcher,
54 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
55 IHistoryViewLauncher historyViewLauncher,
56 NewIncomingChangesUpdater newIncomingChangesUpdater,
57 StatusBar statusBar,
58 EditorWindow parentWindow,
59 ObjectInfo objectInfo,
60 ObjectInfo ancestorChangesetInfo,
61 EnumMergeType mergeType,
62 ShowIncomingChangesFrom from,
63 PlasticNotifier plasticNotifier,
64 MergeViewLogic.IMergeController mergeController,
65 MergeViewLogic.IGetWorkingBranch getWorkingBranch,
66 CheckShelvedChanges.IUpdateShelvedChangesNotification updateShelvedChangesNotification,
67 IShelvedChangesUpdater shelvedChangesUpdater,
68 IRefreshView refreshView,
69 bool isIncomingMerge,
70 bool isMergeFinished,
71 bool showDiscardChangesButton)
72 {
73 MergeTab mergeTab = new MergeTab(
74 wkInfo,
75 repSpec,
76 workspaceWindow,
77 switcher,
78 showDownloadPlasticExeWindow,
79 historyViewLauncher,
80 newIncomingChangesUpdater,
81 statusBar,
82 parentWindow,
83 objectInfo,
84 ancestorChangesetInfo,
85 mergeType,
86 from,
87 plasticNotifier,
88 mergeController,
89 getWorkingBranch,
90 updateShelvedChangesNotification,
91 shelvedChangesUpdater,
92 refreshView,
93 isIncomingMerge,
94 isMergeFinished,
95 showDiscardChangesButton);
96
97 if (!isMergeFinished)
98 ((IRefreshableView)mergeTab).Refresh();
99
100 return mergeTab;
101 }
102
103 internal static MergeTab BuildFromCalculatedMerge(
104 WorkspaceInfo wkInfo,
105 RepositorySpec repSpec,
106 IWorkspaceWindow workspaceWindow,
107 IViewSwitcher switcher,
108 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
109 IHistoryViewLauncher historyViewLauncher,
110 NewIncomingChangesUpdater newIncomingChangesUpdater,
111 StatusBar statusBar,
112 EditorWindow parentWindow,
113 ObjectInfo objectInfo,
114 ObjectInfo ancestorChangesetInfo,
115 EnumMergeType mergeType,
116 ShowIncomingChangesFrom from,
117 PlasticNotifier plasticNotifier,
118 MergeViewLogic.IMergeController mergeController,
119 MergeViewLogic.IGetWorkingBranch getWorkingBranch,
120 CheckShelvedChanges.IUpdateShelvedChangesNotification updateShelvedChangesNotification,
121 IShelvedChangesUpdater shelvedChangesUpdater,
122 IRefreshView refreshView,
123 bool isIncomingMerge,
124 bool isMergeFinished,
125 CalculatedMergeResult calculatedMergeResult,
126 bool showDiscardChangesButton)
127 {
128 MergeTab mergeTab = new MergeTab(
129 wkInfo,
130 repSpec,
131 workspaceWindow,
132 switcher,
133 showDownloadPlasticExeWindow,
134 historyViewLauncher,
135 newIncomingChangesUpdater,
136 statusBar,
137 parentWindow,
138 objectInfo,
139 ancestorChangesetInfo,
140 mergeType,
141 from,
142 plasticNotifier,
143 mergeController,
144 getWorkingBranch,
145 updateShelvedChangesNotification,
146 shelvedChangesUpdater,
147 refreshView,
148 isIncomingMerge,
149 isMergeFinished,
150 showDiscardChangesButton);
151
152 mergeTab.mMergeViewLogic.CalculateMergeFromMergeResult(calculatedMergeResult);
153
154 mergeTab.ProcessAllMerges();
155
156 return mergeTab;
157 }
158
159 MergeTab(
160 WorkspaceInfo wkInfo,
161 RepositorySpec repSpec,
162 IWorkspaceWindow workspaceWindow,
163 IViewSwitcher switcher,
164 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
165 IHistoryViewLauncher historyViewLauncher,
166 NewIncomingChangesUpdater newIncomingChangesUpdater,
167 StatusBar statusBar,
168 EditorWindow parentWindow,
169 ObjectInfo objectInfo,
170 ObjectInfo ancestorChangesetInfo,
171 EnumMergeType mergeType,
172 ShowIncomingChangesFrom from,
173 PlasticNotifier plasticNotifier,
174 MergeViewLogic.IMergeController mergeController,
175 MergeViewLogic.IGetWorkingBranch getWorkingBranch,
176 CheckShelvedChanges.IUpdateShelvedChangesNotification updateShelvedChangesNotification,
177 IShelvedChangesUpdater shelvedChangesUpdater,
178 IRefreshView refreshView,
179 bool isIncomingMerge,
180 bool isMergeFinished,
181 bool showDiscardChangesButton)
182 {
183 mWkInfo = wkInfo;
184 mWorkspaceWindow = workspaceWindow;
185 mSwitcher = switcher;
186 mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
187 mHistoryViewLauncher = historyViewLauncher;
188 mNewIncomingChangesUpdater = newIncomingChangesUpdater;
189 mParentWindow = parentWindow;
190 mStatusBar = statusBar;
191 mObjectInfo = objectInfo;
192 mAncestorObjectInfo = ancestorChangesetInfo;
193 mMergeType = mergeType;
194 mFrom = from;
195 mGuiMessage = new UnityPlasticGuiMessage();
196 mMergeController = mergeController;
197 mUpdateShelvedChangesNotification = updateShelvedChangesNotification;
198 mShelvedChangesUpdater = shelvedChangesUpdater;
199 mRefreshView = refreshView;
200 mIsIncomingMerge = isIncomingMerge;
201 mShowDiscardChangesButton = showDiscardChangesButton;
202 mIsMergeFinished = isMergeFinished;
203
204 mIsMergeTo = MergeTypeClassifier.IsMergeTo(mergeType);
205 mRepSpec = PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo);
206 mTitleText = MergeViewTitle.Get(objectInfo, ancestorChangesetInfo, mergeType);
207
208 BuildComponents(
209 mWkInfo,
210 mIsIncomingMerge,
211 mIsMergeTo,
212 mMergeController.IsShelvesetMerge());
213
214 mMergeDialogParameters = PlasticGui.WorkspaceWindow.Merge.MergeSourceBuilder.
215 BuildMergeDialogParameters(mergeType, mRepSpec);
216
217 mMergeController.SetMergeDialogParameters(mMergeDialogParameters);
218
219 mProgressControls = new ProgressControlsForViews();
220
221 mCooldownClearUpdateSuccessAction = new CooldownWindowDelayer(
222 DelayedClearUpdateSuccess,
223 UnityConstants.NOTIFICATION_CLEAR_INTERVAL);
224
225 mMergeViewLogic = new MergeViewLogic(
226 mWkInfo,
227 repSpec,
228 mergeType,
229 mIsIncomingMerge,
230 mMergeController,
231 getWorkingBranch,
232 plasticNotifier,
233 from,
234 null,
235 mNewIncomingChangesUpdater,
236 shelvedChangesUpdater,
237 null,
238 this,
239 NewChangesInWk.Build(mWkInfo, new BuildWorkspacekIsRelevantNewChange()),
240 mProgressControls,
241 null);
242 }
243
244 internal void OnEnable()
245 {
246 mSearchField.downOrUpArrowKeyPressed +=
247 SearchField_OnDownOrUpArrowKeyPressed;
248 }
249
250 internal void OnDisable()
251 {
252 mSearchField.downOrUpArrowKeyPressed -=
253 SearchField_OnDownOrUpArrowKeyPressed;
254
255 TreeHeaderSettings.Save(
256 mMergeTreeView.multiColumnHeader.state,
257 mIsIncomingMerge
258 ? UnityConstants.DEVELOPER_INCOMING_CHANGES_TABLE_SETTINGS_NAME
259 : UnityConstants.DEVELOPER_MERGE_TABLE_SETTINGS_NAME);
260 }
261
262 internal SerializableMergeTabState GetSerializableState()
263 {
264 return new SerializableMergeTabState(
265 mRepSpec,
266 mObjectInfo,
267 mAncestorObjectInfo,
268 mMergeType,
269 mFrom,
270 mIsIncomingMerge,
271 mIsMergeFinished);
272 }
273
274 internal void Update()
275 {
276 mProgressControls.UpdateProgress(mParentWindow);
277 }
278
279 internal void OnGUI()
280 {
281 if (Event.current.type == EventType.Layout)
282 {
283 mHasPendingDirectoryConflicts = mMergeChangesTree != null &&
284 MergeChangesTreeParser.GetUnsolvedDirectoryConflictsCount(mMergeChangesTree) > 0;
285 mIsOperationRunning = mProgressControls.IsOperationRunning();
286 }
287
288 DoTitle(mTitleText, mMergeDialogParameters, mMergeViewLogic);
289
290 DoConflictsTree(
291 mMergeTreeView,
292 mEmptyStateData,
293 mCooldownClearUpdateSuccessAction,
294 mIsOperationRunning,
295 mIsUpdateSuccessful,
296 mIsIncomingMerge,
297 mParentWindow.Repaint);
298
299 List<MergeChangeInfo> selectedMergeChanges =
300 mMergeTreeView.GetSelectedMergeChanges();
301
302 if (MergeSelection.GetSelectedGroupInfo(
303 mMergeTreeView, mIsIncomingMerge).IsDirectoryConflictsSelection &&
304 !Mouse.IsRightMouseButtonPressed(Event.current))
305 {
306 DoDirectoryConflictResolutionPanel(
307 selectedMergeChanges,
308 new Action<MergeChangeInfo>(ResolveDirectoryConflict),
309 mConflictResolutionStates,
310 mValidationLabel,
311 mMergeDialogParameters.CherryPicking,
312 mIsDirectoryResolutionPanelEnabled,
313 ref mConflictResolutionState);
314 }
315
316 DrawActionToolbar.Begin(mParentWindow);
317
318 if (!mIsOperationRunning)
319 {
320 DoActionToolbarMessage(
321 mIsMessageLabelVisible,
322 mMessageLabelText,
323 mIsMergeFinished,
324 mIsErrorMessageLabelVisible,
325 mErrorMessageLabelText,
326 mDirectoryConflictCount,
327 mFileConflictCount,
328 mChangesSummary,
329 mSwitcher);
330
331 if (mIsProcessMergesButtonVisible && !mIsMergeFinished)
332 {
333 DoProcessMergesButton(
334 mIsProcessMergesButtonEnabled && !mHasPendingDirectoryConflicts,
335 mProcessMergesButtonText,
336 mSwitcher,
337 mShowDownloadPlasticExeWindow,
338 mWorkspaceWindow,
339 mGuiMessage,
340 mMergeViewLogic,
341 mMergeDialogParameters.Options.Contributor,
342 mWkInfo,
343 AfterProcessMerges,
344 MergeSuccessfullyFinished);
345
346 if (mShowDiscardChangesButton)
347 {
348 DoDiscardChangesButton(
349 mWkInfo,
350 (ChangesetInfo)mObjectInfo,
351 mUpdateShelvedChangesNotification,
352 mShelvedChangesUpdater,
353 mRefreshView,
354 mSwitcher);
355 }
356 }
357
358 if (mIsCancelMergesButtonVisible)
359 {
360 mIsCancelMergesButtonEnabled = DoCancelMergesButton(
361 mIsCancelMergesButtonEnabled,
362 mMergeViewLogic);
363 }
364
365 if (mHasPendingDirectoryConflicts)
366 {
367 GUILayout.Space(5);
368 DoWarningMessage();
369 }
370 }
371 else
372 {
373 DrawProgressForViews.ForIndeterminateProgress(
374 mProgressControls.ProgressData);
375 }
376
377 DrawActionToolbar.End();
378
379 if (mProgressControls.HasNotification())
380 {
381 DrawProgressForViews.ForNotificationArea(
382 mProgressControls.ProgressData);
383 }
384 }
385
386 internal void DrawSearchFieldForTab()
387 {
388 DrawSearchField.For(
389 mSearchField,
390 mMergeTreeView,
391 UnityConstants.SEARCH_FIELD_WIDTH);
392 }
393
394 internal void AutoRefresh()
395 {
396 mMergeViewLogic.AutoRefresh();
397 }
398
399 internal void ProcessMergeForTesting()
400 {
401 ProcessMerges(
402 new List<string>(),
403 null,
404 mMergeDialogParameters.Options.Contributor);
405 }
406
407 internal void ResolveDirectoryConflict(MergeChangeInfo conflict)
408 {
409 ConflictResolutionState state;
410
411 if (!mConflictResolutionStates.TryGetValue(conflict.DirectoryConflict, out state))
412 return;
413
414 List<DirectoryConflictResolutionData> conflictResolutions =
415 new List<DirectoryConflictResolutionData>();
416
417 AddConflictResolution(
418 conflict,
419 state.ResolveAction,
420 state.RenameValue,
421 conflictResolutions);
422
423 MergeChangeInfo metaConflict =
424 mMergeTreeView.GetMetaChange(conflict);
425
426 if (metaConflict != null)
427 {
428 AddConflictResolution(
429 metaConflict,
430 state.ResolveAction,
431 MetaPath.GetMetaPath(state.RenameValue),
432 conflictResolutions);
433 }
434
435 if (state.IsApplyActionsForNextConflictsChecked)
436 {
437 foreach (MergeChangeInfo otherConflict in mMergeTreeView.GetSelectedMergeChanges())
438 {
439 AddConflictResolution(
440 otherConflict,
441 state.ResolveAction,
442 state.RenameValue,
443 conflictResolutions);
444 }
445 }
446
447 mMergeViewLogic.ResolveDirectoryConflicts(conflictResolutions);
448 }
449
450 bool IIncomingChangesTab.IsVisible{ get; set; }
451
452 void IIncomingChangesTab.OnEnable()
453 {
454 OnEnable();
455 }
456
457 void IIncomingChangesTab.OnDisable()
458 {
459 OnDisable();
460 }
461
462 void IIncomingChangesTab.Update()
463 {
464 Update();
465 }
466
467 void IIncomingChangesTab.DrawSearchFieldForTab()
468 {
469 DrawSearchFieldForTab();
470 }
471
472 void IIncomingChangesTab.AutoRefresh()
473 {
474 AutoRefresh();
475 }
476
477 void IRefreshableView.Refresh()
478 {
479 mMergeViewLogic.Refresh();
480 }
481
482 void IMergeView.UpdateTitle(string title)
483 {
484 mTitleText = title;
485 }
486
487 void IIncomingChangesTab.OnGUI()
488 {
489 OnGUI();
490 }
491
492 void IMergeView.UpdateData(
493 MergeChangesTree mergeChangesTree,
494 ExplainMergeData explainMergeData,
495 MergeSolvedFileConflicts solvedFileConflicts,
496 bool isIncomingMerge,
497 bool isMergeTo,
498 bool mergeHasFinished)
499 {
500 HideMessage();
501
502 ShowProcessMergesButton(
503 MergeViewTexts.GetProcessMergesButtonText(
504 MergeChangesTreeParser.HasFileConflicts(mergeChangesTree),
505 mIsIncomingMerge,
506 mIsMergeTo));
507
508 mMergeChangesTree = mergeChangesTree;
509
510 mConflictResolutionStates.Clear();
511
512 UpdateFileConflictsTree(
513 mergeChangesTree,
514 mMergeTreeView);
515
516 UpdateOverview(mergeChangesTree, solvedFileConflicts);
517 }
518
519 void IMergeView.UpdateSolvedDirectoryConflicts()
520 {
521 if (mMergeChangesTree == null)
522 return;
523
524 mDirectoryConflictCount = MergeChangesTreeParser.GetUnsolvedDirectoryConflictsCount(
525 mMergeChangesTree);
526 }
527
528 void IMergeView.UpdateSolvedFileConflicts(
529 MergeSolvedFileConflicts solvedFileConflicts)
530 {
531 mMergeTreeView.UpdateSolvedFileConflicts(
532 solvedFileConflicts);
533 }
534
535 void IMergeView.ShowMessage(
536 string title,
537 string message,
538 bool isErrorMessage)
539 {
540 if (isErrorMessage)
541 {
542 mErrorMessageLabelText = message;
543 mIsErrorMessageLabelVisible = true;
544 return;
545 }
546
547 mMessageLabelText = message;
548 mIsMessageLabelVisible = true;
549 mIsMergeFinished = MergeViewTexts.IsMergeAlreadyProcessedMessage(message);
550 }
551
552 string IMergeView.GetComments(out bool bCancel)
553 {
554 bCancel = false;
555 return string.Empty;
556 }
557
558 ObjectInfo IMergeView.GetObjectInfo()
559 {
560 return mObjectInfo;
561 }
562
563 void IMergeView.DisableProcessMergesButton()
564 {
565 mIsProcessMergesButtonEnabled = false;
566 }
567
568 void IMergeView.EnableResolveDirectoryConflictsControls()
569 {
570 mIsDirectoryResolutionPanelEnabled = true;
571 }
572
573 void IMergeView.DisableResolveDirectoryConflictsControls()
574 {
575 mIsDirectoryResolutionPanelEnabled = false;
576 }
577
578 void IMergeView.ShowCancelButton()
579 {
580 mIsCancelMergesButtonEnabled = true;
581 mIsCancelMergesButtonVisible = true;
582 }
583
584 void IMergeView.HideCancelButton()
585 {
586 mIsCancelMergesButtonEnabled = false;
587 mIsCancelMergesButtonVisible = false;
588 }
589
590 void IMergeViewMenuOperations.MergeContributors()
591 {
592 ProcessMerges(
593 MergeSelection.GetPathsFromSelectedFileConflictsIncludingMeta(mMergeTreeView),
594 PlasticExeLauncher.BuildForMergeSelectedFiles(mWkInfo, false, mShowDownloadPlasticExeWindow),
595 MergeContributorType.MergeContributors);
596 }
597
598 void IMergeViewMenuOperations.MergeKeepingSourceChanges()
599 {
600 ProcessMerges(
601 MergeSelection.GetPathsFromSelectedFileConflictsIncludingMeta(mMergeTreeView),
602 null,
603 MergeContributorType.KeepSource);
604 }
605
606 void IMergeViewMenuOperations.MergeKeepingWorkspaceChanges()
607 {
608 ProcessMerges(
609 MergeSelection.GetPathsFromSelectedFileConflictsIncludingMeta(mMergeTreeView),
610 null,
611 MergeContributorType.KeepDestination);
612 }
613
614 SelectedMergeChangesGroupInfo IMergeViewMenuOperations.GetSelectedMergeChangesGroupInfo()
615 {
616 return GetSelectedMergeChangesGroupInfo.For(
617 mMergeTreeView.GetSelectedMergeChanges(), mIsIncomingMerge);
618 }
619
620 void IMergeViewMenuOperations.DiffSourceWithDestination()
621 {
622 MergeChangeInfo mergeChange = MergeSelection.
623 GetSingleSelectedMergeChange(mMergeTreeView);
624
625 if (mergeChange == null)
626 return;
627
628 if (mergeChange.DirectoryConflict != null)
629 {
630 DiffSourceWithDestinationForDirectoryConflict(
631 mShowDownloadPlasticExeWindow,
632 mergeChange,
633 mWkInfo,
634 mIsIncomingMerge);
635 return;
636 }
637
638 DiffSourceWithDestinationForFileConflict(
639 mShowDownloadPlasticExeWindow,
640 mergeChange,
641 mWkInfo,
642 mIsIncomingMerge);
643 }
644
645 void IMergeViewMenuOperations.DiffDestinationWithAncestor()
646 {
647 MergeChangeInfo mergeChange = MergeSelection.
648 GetSingleSelectedMergeChange(mMergeTreeView);
649
650 if (mergeChange == null)
651 return;
652
653 if (mergeChange.DirectoryConflict != null)
654 {
655 DiffDestinationWithAncestorForDirectoryConflict(
656 mShowDownloadPlasticExeWindow,
657 mergeChange,
658 mWkInfo,
659 mIsIncomingMerge);
660 return;
661 }
662
663 DiffDestinationWithAncestorForFileConflict(
664 mShowDownloadPlasticExeWindow,
665 mergeChange,
666 mWkInfo);
667 }
668
669 void IMergeViewMenuOperations.DiffSourceWithAncestor()
670 {
671 MergeChangeInfo mergeChange = MergeSelection.
672 GetSingleSelectedMergeChange(mMergeTreeView);
673
674 if (mergeChange == null)
675 return;
676
677 if (mergeChange.DirectoryConflict != null)
678 {
679 DiffSourceWithAncestorForDirectoryConflict(
680 mShowDownloadPlasticExeWindow,
681 mergeChange,
682 mWkInfo,
683 mIsIncomingMerge);
684 return;
685 }
686
687 DiffSourceWithAncestorForFileConflict(
688 mShowDownloadPlasticExeWindow,
689 mergeChange,
690 mWkInfo);
691 }
692
693 void IMergeViewMenuOperations.OpenSrcRevision()
694 {
695 MergeChangeInfo mergeChange = MergeSelection.
696 GetSingleSelectedMergeChange(mMergeTreeView);
697
698 if (mergeChange == null)
699 return;
700
701 OpenRevision.ForDifference(mRepSpec, mergeChange.DirectoryConflict.SrcDiff);
702 }
703
704 void IMergeViewMenuOperations.OpenDstRevision()
705 {
706 MergeChangeInfo mergeChange = MergeSelection.
707 GetSingleSelectedMergeChange(mMergeTreeView);
708
709 if (mergeChange == null)
710 return;
711
712 OpenRevision.ForDifference(mRepSpec, mergeChange.DirectoryConflict.DstDiff);
713 }
714
715 void IMergeViewMenuOperations.CopyFilePath(bool relativePath)
716 {
717 EditorGUIUtility.systemCopyBuffer = GetFilePathList.FromMergeChangeInfos(
718 mMergeTreeView.GetSelectedMergeChanges(),
719 relativePath,
720 mWkInfo.ClientPath);
721 }
722
723 void MergeViewFileConflictMenu.IMetaMenuOperations.ShowHistory()
724 {
725 MergeChangeInfo mergeChangeInfo = MergeSelection.GetSingleSelectedMergeChange(mMergeTreeView);
726 MergeChangeInfo metaChangeInfo = mMergeTreeView.GetMetaChange(mergeChangeInfo);
727 RevisionInfo revInfo = mergeChangeInfo.GetRevision();
728
729 mHistoryViewLauncher.ShowHistoryView(
730 metaChangeInfo.GetMount().RepSpec,
731 revInfo.ItemId,
732 metaChangeInfo.GetPath(),
733 revInfo.Type == EnumRevisionType.enDirectory);
734 }
735
736 void MergeViewFileConflictMenu.IMetaMenuOperations.DiffDestinationWithAncestor()
737 {
738 MergeChangeInfo mergeChange = MergeSelection.
739 GetSingleSelectedMergeChange(mMergeTreeView);
740
741 if (mergeChange == null)
742 return;
743
744 DiffDestinationWithAncestorForFileConflict(
745 mShowDownloadPlasticExeWindow,
746 mMergeTreeView.GetMetaChange(mergeChange),
747 mWkInfo);
748 }
749
750 void IMergeViewMenuOperations.ShowHistory()
751 {
752 MergeChangeInfo mergeChangeInfo = MergeSelection.GetSingleSelectedMergeChange(mMergeTreeView);
753 RevisionInfo revInfo = mergeChangeInfo.GetRevision();
754
755 mHistoryViewLauncher.ShowHistoryView(
756 mergeChangeInfo.GetMount().RepSpec,
757 revInfo.ItemId,
758 mergeChangeInfo.GetPath(),
759 revInfo.Type == EnumRevisionType.enDirectory);
760 }
761
762 void MergeViewFileConflictMenu.IMetaMenuOperations.DiffSourceWithAncestor()
763 {
764 MergeChangeInfo mergeChange = MergeSelection.
765 GetSingleSelectedMergeChange(mMergeTreeView);
766
767 if (mergeChange == null)
768 return;
769
770 DiffSourceWithAncestorForFileConflict(
771 mShowDownloadPlasticExeWindow,
772 mMergeTreeView.GetMetaChange(mergeChange),
773 mWkInfo);
774 }
775
776 void MergeViewFileConflictMenu.IMetaMenuOperations.DiffSourceWithDestination()
777 {
778 MergeChangeInfo mergeChange = MergeSelection.
779 GetSingleSelectedMergeChange(mMergeTreeView);
780
781 if (mergeChange == null)
782 return;
783
784 DiffSourceWithDestinationForFileConflict(
785 mShowDownloadPlasticExeWindow,
786 mMergeTreeView.GetMetaChange(mergeChange),
787 mWkInfo,
788 mIsIncomingMerge);
789 }
790
791 bool MergeViewFileConflictMenu.IMetaMenuOperations.SelectionHasMeta()
792 {
793 return mMergeTreeView.SelectionHasMeta();
794 }
795
796 void SearchField_OnDownOrUpArrowKeyPressed()
797 {
798 mMergeTreeView.SetFocusAndEnsureSelectedItem();
799 }
800
801 void UpdateOverview(
802 MergeChangesTree mergeChangesTree,
803 MergeSolvedFileConflicts solvedFileConflicts)
804 {
805 mChangesSummary = MergeChangesTreeParser.
806 GetChangesToApplySummary(mergeChangesTree);
807
808 mFileConflictCount = MergeChangesTreeParser.GetUnsolvedFileConflictsCount(
809 mergeChangesTree, solvedFileConflicts);
810
811 mDirectoryConflictCount = MergeChangesTreeParser.GetUnsolvedDirectoryConflictsCount(
812 mergeChangesTree);
813 }
814
815 void HideMessage()
816 {
817 mMessageLabelText = string.Empty;
818 mIsMessageLabelVisible = false;
819 mIsMergeFinished = false;
820
821 mErrorMessageLabelText = string.Empty;
822 mIsErrorMessageLabelVisible = false;
823 }
824
825 void DelayedClearUpdateSuccess()
826 {
827 mIsUpdateSuccessful = false;
828 }
829
830 void IMergeViewMenuOperations.ShowAnnotate()
831 {
832 }
833
834 void AfterProcessMerges(UpdateProgress progress)
835 {
836 RefreshAsset.AfterLongAssetOperation(
837 ProjectPackages.ShouldBeResolvedFromUpdateProgress(mWkInfo, progress));
838 }
839
840 void ShowProcessMergesButton(string processMergesButtonText)
841 {
842 mProcessMergesButtonText = processMergesButtonText;
843 mIsProcessMergesButtonEnabled = true;
844 mIsProcessMergesButtonVisible = true;
845 }
846
847 void ProcessMerges(
848 List<string> selectedPaths,
849 IToolLauncher toolLauncher,
850 MergeContributorType contributorType)
851 {
852 ProcessMerges(
853 mMergeViewLogic,
854 contributorType,
855 mWorkspaceWindow,
856 mSwitcher,
857 toolLauncher,
858 mGuiMessage,
859 selectedPaths,
860 AfterProcessMerges,
861 MergeSuccessfullyFinished);
862 }
863
864 void MergeSuccessfullyFinished()
865 {
866 mIsUpdateSuccessful = true;
867 }
868
869 void ProcessAllMerges()
870 {
871 ProcessMerges(
872 new List<string>(),
873 PlasticExeLauncher.BuildForMergeSelectedFiles(mWkInfo, false, mShowDownloadPlasticExeWindow),
874 mMergeDialogParameters.Options.Contributor);
875 }
876
877 void DoConflictsTree(
878 MergeTreeView mergeTreeView,
879 EmptyStateData emptyStateData,
880 CooldownWindowDelayer cooldownClearUpdateSuccessAction,
881 bool isOperationRunning,
882 bool isUpdateSuccessful,
883 bool isIncomingMerge,
884 Action repaint)
885 {
886 using (new EditorGUI.DisabledScope(isOperationRunning))
887 {
888 Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
889
890 mergeTreeView.OnGUI(rect);
891
892 if (isOperationRunning)
893 return;
894
895 if (mergeTreeView.GetTotalItemCount() == 0)
896 {
897 DrawEmptyState(
898 rect,
899 emptyStateData,
900 cooldownClearUpdateSuccessAction,
901 isUpdateSuccessful,
902 isIncomingMerge,
903 repaint);
904 return;
905 }
906
907 if (isUpdateSuccessful)
908 NotifySuccessInStatusBar();
909 }
910 }
911
912 void NotifySuccessInStatusBar()
913 {
914 mStatusBar.Notify(
915 new GUIContentNotification(
916 PlasticLocalization.Name.WorkspaceUpdateCompleted.GetString()),
917 UnityEditor.MessageType.None,
918 Images.GetStepOkIcon());
919 mIsUpdateSuccessful = false;
920 }
921
922 static void DiffSourceWithDestinationForDirectoryConflict(
923 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
924 MergeChangeInfo mergeChange,
925 WorkspaceInfo wkInfo,
926 bool isIncomingMerge)
927 {
928 DirectoryConflict conflict = mergeChange.DirectoryConflict;
929 MountPointWithPath mountPoint = mergeChange.GetMount();
930
931 DiffOperation.DiffRevisions(
932 wkInfo,
933 mountPoint.RepSpec,
934 conflict.SrcDiff.RevInfo,
935 conflict.DstDiff.RevInfo,
936 mountPoint.GetFullCmPath(conflict.SrcDiff.Path),
937 mountPoint.GetFullCmPath(conflict.DstDiff.Path),
938 isIncomingMerge,
939 PlasticExeLauncher.BuildForDiffContributors(wkInfo, false, showDownloadPlasticExeWindow),
940 imageDiffLauncher: null);
941 }
942
943 static void DiffDestinationWithAncestorForDirectoryConflict(
944 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
945 MergeChangeInfo mergeChange,
946 WorkspaceInfo wkInfo,
947 bool isIncomingMerge)
948 {
949 DirectoryConflict conflict = mergeChange.DirectoryConflict;
950 MountPointWithPath mountPoint = mergeChange.GetMount();
951
952 DiffOperation.DiffRevisions(
953 wkInfo,
954 mountPoint.RepSpec,
955 conflict.DstDiff.Base,
956 conflict.DstDiff.RevInfo,
957 mountPoint.GetFullCmPath(conflict.DstDiff.Path),
958 mountPoint.GetFullCmPath(conflict.DstDiff.Path),
959 isIncomingMerge,
960 PlasticExeLauncher.BuildForDiffContributors(wkInfo, false, showDownloadPlasticExeWindow),
961 imageDiffLauncher: null);
962 }
963
964 static void DiffSourceWithAncestorForDirectoryConflict(
965 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
966 MergeChangeInfo mergeChange,
967 WorkspaceInfo wkInfo,
968 bool isIncomingMerge)
969 {
970 DirectoryConflict conflict = mergeChange.DirectoryConflict;
971 MountPointWithPath mountPoint = mergeChange.GetMount();
972
973 DiffOperation.DiffRevisions(
974 wkInfo,
975 mountPoint.RepSpec,
976 conflict.SrcDiff.Base,
977 conflict.SrcDiff.RevInfo,
978 mountPoint.GetFullCmPath(conflict.SrcDiff.Path),
979 mountPoint.GetFullCmPath(conflict.SrcDiff.Path),
980 isIncomingMerge,
981 PlasticExeLauncher.BuildForDiffContributors(wkInfo, false, showDownloadPlasticExeWindow),
982 imageDiffLauncher: null);
983 }
984
985 static void DiffDestinationWithAncestorForFileConflict(
986 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
987 MergeChangeInfo mergeChange,
988 WorkspaceInfo wkInfo)
989 {
990 FileConflict conflict = mergeChange.FileConflict;
991 MountPointWithPath mountPoint = mergeChange.GetMount();
992
993 string path = mountPoint.GetFullCmPath(mergeChange.GetPath());
994
995 DiffOperation.DiffRevisions(
996 wkInfo,
997 mountPoint.RepSpec,
998 conflict.Base,
999 conflict.DstDiff.RevInfo,
1000 path,
1001 path,
1002 false,
1003 PlasticExeLauncher.BuildForDiffContributors(wkInfo, false, showDownloadPlasticExeWindow),
1004 imageDiffLauncher: null);
1005 }
1006
1007 static void DiffSourceWithDestinationForFileConflict(
1008 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
1009 MergeChangeInfo mergeChange,
1010 WorkspaceInfo wkInfo,
1011 bool isIncomingMerge)
1012 {
1013 PlasticExeLauncher plasticExeLauncher =
1014 PlasticExeLauncher.BuildForDiffContributors(wkInfo, false, showDownloadPlasticExeWindow);
1015
1016 if (isIncomingMerge)
1017 {
1018 DiffOperation.DiffYoursWithIncoming(
1019 wkInfo,
1020 mergeChange.GetMount(),
1021 mergeChange.GetRevision(),
1022 mergeChange.GetPath(),
1023 plasticExeLauncher,
1024 imageDiffLauncher: null);
1025 return;
1026 }
1027
1028 FileConflict conflict = mergeChange.FileConflict;
1029 MountPointWithPath mountPoint = mergeChange.GetMount();
1030
1031 string path = mountPoint.GetFullCmPath(mergeChange.GetPath());
1032
1033 DiffOperation.DiffRevisions(
1034 wkInfo,
1035 mountPoint.RepSpec,
1036 conflict.SrcDiff.RevInfo,
1037 conflict.DstDiff.RevInfo,
1038 path,
1039 path,
1040 false,
1041 plasticExeLauncher,
1042 imageDiffLauncher: null);
1043 }
1044
1045 static void UpdateFileConflictsTree(
1046 MergeChangesTree mergeChangesTree,
1047 MergeTreeView mergeTreeView)
1048 {
1049 UnityMergeTree unityMergeTree = UnityMergeTree.BuildMergeCategories(mergeChangesTree);
1050
1051 mergeTreeView.BuildModel(unityMergeTree);
1052 mergeTreeView.Refilter();
1053 mergeTreeView.Sort();
1054 mergeTreeView.Reload();
1055
1056 mergeTreeView.SelectFirstUnsolvedDirectoryConflict();
1057 }
1058
1059 static void DiffSourceWithAncestorForFileConflict(
1060 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
1061 MergeChangeInfo mergeChange,
1062 WorkspaceInfo wkInfo)
1063 {
1064 FileConflict conflict = mergeChange.FileConflict;
1065 MountPointWithPath mountPoint = mergeChange.GetMount();
1066
1067 string path = mountPoint.GetFullCmPath(mergeChange.GetPath());
1068
1069 DiffOperation.DiffRevisions(
1070 wkInfo,
1071 mountPoint.RepSpec,
1072 conflict.Base,
1073 conflict.SrcDiff.RevInfo,
1074 path,
1075 path,
1076 false,
1077 PlasticExeLauncher.BuildForDiffContributors(wkInfo, false, showDownloadPlasticExeWindow),
1078 imageDiffLauncher: null);
1079 }
1080
1081 static void ProcessMerges(
1082 MergeViewLogic mergeViewLogic,
1083 MergeContributorType contributorType,
1084 IWorkspaceWindow workspaceWindow,
1085 IViewSwitcher switcher,
1086 IToolLauncher toolLauncher,
1087 GuiMessage.IGuiMessage guiMessage,
1088 List<string> selectedPaths,
1089 EndOperationDelegateForUpdateProgress afterProcessMergesAction,
1090 Action successOperationDelegate)
1091 {
1092 mergeViewLogic.ProcessMerges(
1093 workspaceWindow,
1094 switcher,
1095 guiMessage,
1096 selectedPaths,
1097 null,
1098 contributorType,
1099 toolLauncher,
1100 false,
1101 RefreshAsset.BeforeLongAssetOperation,
1102 afterProcessMergesAction,
1103 successOperationDelegate);
1104 }
1105
1106 static void AddConflictResolution(
1107 MergeChangeInfo conflict,
1108 DirectoryConflictResolveActions resolveAction,
1109 string renameValue,
1110 List<DirectoryConflictResolutionData> conflictResolutions)
1111 {
1112 conflictResolutions.Add(new DirectoryConflictResolutionData(
1113 conflict.DirectoryConflict,
1114 conflict.Xlink,
1115 conflict.GetMount().Mount,
1116 resolveAction,
1117 renameValue));
1118 }
1119
1120 static void DoTitle(
1121 string title,
1122 MergeDialogParameters mergeDialogParameters,
1123 MergeViewLogic mergeViewLogic)
1124 {
1125 EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
1126
1127 GUILayout.Label(title, UnityStyles.MergeTab.TitleLabel);
1128
1129 GUILayout.FlexibleSpace();
1130
1131 if (GUILayout.Button(
1132 PlasticLocalization.Name.MergeOptionsButton.GetString(),
1133 EditorStyles.miniButton))
1134 {
1135 ShowMergeOptions(mergeDialogParameters, mergeViewLogic);
1136 }
1137
1138 EditorGUILayout.EndHorizontal();
1139 }
1140
1141 static void DrawEmptyState(
1142 Rect rect,
1143 EmptyStateData emptyStateData,
1144 CooldownWindowDelayer cooldownClearUpdateSuccessAction,
1145 bool isUpdateSuccessful,
1146 bool isIncomingMerge,
1147 Action repaint)
1148 {
1149 emptyStateData.Update(
1150 GetEmptyStateMessage(isUpdateSuccessful, isIncomingMerge),
1151 rect, Event.current.type, repaint);
1152
1153 if (!isUpdateSuccessful)
1154 {
1155 DrawTreeViewEmptyState.For(emptyStateData);
1156 return;
1157 }
1158
1159 if (!cooldownClearUpdateSuccessAction.IsRunning)
1160 cooldownClearUpdateSuccessAction.Ping();
1161
1162 DrawTreeViewEmptyState.For(Images.GetStepOkIcon(), emptyStateData);
1163 }
1164
1165 static void DoDirectoryConflictResolutionPanel(
1166 List<MergeChangeInfo> selectedChangeInfos,
1167 Action<MergeChangeInfo> resolveDirectoryConflictAction,
1168 Dictionary<DirectoryConflict, ConflictResolutionState> conflictResolutionStates,
1169 GUIContent validationLabel,
1170 bool isCherrypickMerge,
1171 bool isDirectoryResolutionPanelEnabled,
1172 ref ConflictResolutionState conflictResolutionState)
1173 {
1174 MergeChangeInfo selectedDirectoryConflict = selectedChangeInfos[0];
1175
1176 if (selectedDirectoryConflict.DirectoryConflict.IsResolved())
1177 return;
1178
1179 DirectoryConflictUserInfo conflictUserInfo;
1180 DirectoryConflictAction[] conflictActions;
1181
1182 DirectoryConflictResolutionInfo.FromDirectoryConflict(
1183 selectedDirectoryConflict.GetMount(),
1184 selectedDirectoryConflict.DirectoryConflict,
1185 isCherrypickMerge,
1186 out conflictUserInfo,
1187 out conflictActions);
1188
1189 conflictResolutionState = GetConflictResolutionState(
1190 selectedDirectoryConflict.DirectoryConflict,
1191 conflictActions,
1192 conflictResolutionStates);
1193
1194 int pendingSelectedConflictsCount = GetPendingConflictsCount(
1195 selectedChangeInfos);
1196
1197 DrawDirectoryResolutionPanel.ForConflict(
1198 selectedDirectoryConflict,
1199 (pendingSelectedConflictsCount <= 1) ? 0 : pendingSelectedConflictsCount - 1,
1200 conflictUserInfo,
1201 conflictActions,
1202 resolveDirectoryConflictAction,
1203 validationLabel,
1204 isDirectoryResolutionPanelEnabled,
1205 ref conflictResolutionState);
1206 }
1207
1208 static void DoActionToolbarMessage(
1209 bool isMessageLabelVisible,
1210 string messageLabelText,
1211 bool isMergeFinished,
1212 bool isErrorMessageLabelVisible,
1213 string errorMessageLabelText,
1214 int directoryConflictCount,
1215 int fileConflictCount,
1216 MergeViewTexts.ChangesToApplySummary changesSummary,
1217 IViewSwitcher viewSwitcher)
1218 {
1219 if (isMergeFinished)
1220 {
1221 DoMergeAlreadyProcessedArea(viewSwitcher);
1222 return;
1223 }
1224
1225 if (isMessageLabelVisible)
1226 DoInfoMessage(messageLabelText);
1227
1228 if (isErrorMessageLabelVisible)
1229 {
1230 DoErrorMessage(errorMessageLabelText);
1231 }
1232
1233 if (!isMessageLabelVisible && !isErrorMessageLabelVisible)
1234 {
1235 DrawMergeOverview.For(
1236 directoryConflictCount,
1237 fileConflictCount,
1238 changesSummary);
1239 }
1240 }
1241
1242 static void ShowMergeOptions(
1243 MergeDialogParameters mergeDialogParameters,
1244 MergeViewLogic mergeViewLogic)
1245 {
1246 bool previousMergeTrackingValue =
1247 mergeDialogParameters.Options.IgnoreMergeTracking;
1248
1249 ChangesetSpec previousAncestor = mergeDialogParameters.AncestorSpec;
1250 bool bIsPrevManualStrategy = mergeDialogParameters.Strategy == MergeStrategy.Manual;
1251
1252 if (!MergeOptionsDialog.MergeOptions(mergeDialogParameters))
1253 return;
1254
1255 if (!MergeDialogParameters.AreParametersChanged(
1256 previousMergeTrackingValue,
1257 previousAncestor,
1258 bIsPrevManualStrategy,
1259 mergeDialogParameters))
1260 return;
1261
1262 mergeViewLogic.Refresh();
1263 }
1264
1265 static void DoProcessMergesButton(
1266 bool isEnabled,
1267 string processMergesButtonText,
1268 IViewSwitcher switcher,
1269 LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
1270 IWorkspaceWindow workspaceWindow,
1271 GuiMessage.IGuiMessage guiMessage,
1272 MergeViewLogic mergeViewLogic,
1273 MergeContributorType contributorType,
1274 WorkspaceInfo wkInfo,
1275 EndOperationDelegateForUpdateProgress afterProcessMergesAction,
1276 Action successOperationDelegate)
1277 {
1278 GUI.enabled = isEnabled;
1279
1280 if (DrawActionButton.For(processMergesButtonText))
1281 {
1282 ProcessMerges(
1283 mergeViewLogic,
1284 contributorType,
1285 workspaceWindow,
1286 switcher,
1287 PlasticExeLauncher.BuildForResolveConflicts(wkInfo, false, showDownloadPlasticExeWindow),
1288 guiMessage,
1289 new List<string>(),
1290 afterProcessMergesAction,
1291 successOperationDelegate);
1292 }
1293
1294 GUI.enabled = true;
1295 }
1296
1297 static void DoDiscardChangesButton(
1298 WorkspaceInfo wkInfo,
1299 ChangesetInfo automaticShelvesetToDiscard,
1300 CheckShelvedChanges.IUpdateShelvedChangesNotification updateShelvedChangesNotification,
1301 IShelvedChangesUpdater shelvedChangesUpdater,
1302 IRefreshView refreshView,
1303 IViewSwitcher viewSwitcher)
1304 {
1305 if (DrawActionButton.For(PlasticLocalization.Name.DiscardChangesButton.GetString()))
1306 {
1307 ShelvedChangesNotificationPanelOperations.DiscardShelvedChanges(
1308 wkInfo,
1309 automaticShelvesetToDiscard,
1310 updateShelvedChangesNotification,
1311 shelvedChangesUpdater,
1312 viewSwitcher,
1313 refreshView);
1314 }
1315 }
1316
1317 static bool DoCancelMergesButton(
1318 bool isEnabled,
1319 MergeViewLogic mergeViewLogic)
1320 {
1321 bool shouldCancelMergesButtonEnabled = true;
1322
1323 GUI.enabled = isEnabled;
1324
1325 if (DrawActionButton.For(PlasticLocalization.GetString(
1326 PlasticLocalization.Name.CancelButton)))
1327 {
1328 mergeViewLogic.Cancel();
1329
1330 shouldCancelMergesButtonEnabled = false;
1331 }
1332
1333 GUI.enabled = true;
1334
1335 return shouldCancelMergesButtonEnabled;
1336 }
1337
1338 static void DoWarningMessage()
1339 {
1340 string label = PlasticLocalization.GetString(PlasticLocalization.Name.SolveConflictsInLable);
1341
1342 GUILayout.Label(
1343 new GUIContent(label, Images.GetWarnIcon()),
1344 UnityStyles.HeaderWarningLabel);
1345 }
1346
1347 static void DoInfoMessage(string message)
1348 {
1349 EditorGUILayout.BeginHorizontal();
1350
1351 GUILayout.Label(message, UnityStyles.MergeTab.InfoLabel);
1352
1353 EditorGUILayout.EndHorizontal();
1354 }
1355
1356 static void DoMergeAlreadyProcessedArea(IViewSwitcher viewSwitcher)
1357 {
1358 EditorGUILayout.BeginHorizontal();
1359
1360 GUILayout.Label(
1361 PlasticLocalization.Name.MergeAlreadyProcessedOpenPendingChangesText.GetString(),
1362 UnityStyles.MergeTab.InfoLabel);
1363
1364 if (GUILayout.Button(
1365 PlasticLocalization.Name.MergeAlreadyProcessedOpenPendingChangesLinkText.GetString(),
1366 UnityStyles.MergeTab.LinkLabel))
1367 {
1368 viewSwitcher.ShowPendingChanges();
1369 viewSwitcher.DisableMergeView();
1370 }
1371
1372 EditorGUIUtility.AddCursorRect(
1373 GUILayoutUtility.GetLastRect(), MouseCursor.Link);
1374
1375 GUILayout.Label(
1376 PlasticLocalization.Name.MergeAlreadyProcessedOpenPreferencesText.GetString(),
1377 UnityStyles.MergeTab.InfoLabel);
1378
1379 if (GUILayout.Button(
1380 PlasticLocalization.Name.MergeAlreadyProcessedOpenPreferencesLinkText.GetString(),
1381 UnityStyles.MergeTab.LinkLabel))
1382 {
1383 OpenPlasticProjectSettings.InDiffAndMergeFoldout();
1384 }
1385
1386 EditorGUIUtility.AddCursorRect(
1387 GUILayoutUtility.GetLastRect(), MouseCursor.Link);
1388
1389 EditorGUILayout.EndHorizontal();
1390 }
1391
1392 static void DoErrorMessage(string message)
1393 {
1394 EditorGUILayout.BeginHorizontal();
1395
1396 GUILayout.Label(message, UnityStyles.MergeTab.RedPendingConflictsOfTotalLabel);
1397
1398 EditorGUILayout.EndHorizontal();
1399 }
1400
1401 static ConflictResolutionState GetConflictResolutionState(
1402 DirectoryConflict directoryConflict,
1403 DirectoryConflictAction[] conflictActions,
1404 Dictionary<DirectoryConflict, ConflictResolutionState> conflictResoltionStates)
1405 {
1406 ConflictResolutionState result;
1407
1408 if (conflictResoltionStates.TryGetValue(directoryConflict, out result))
1409 return result;
1410
1411 result = ConflictResolutionState.Build(directoryConflict, conflictActions);
1412
1413 conflictResoltionStates.Add(directoryConflict, result);
1414 return result;
1415 }
1416
1417 static string GetEmptyStateMessage(
1418 bool isUpdateSuccessful,
1419 bool isIncomingMerge)
1420 {
1421 if (isUpdateSuccessful)
1422 return PlasticLocalization.Name.WorkspaceUpdateCompleted.GetString();
1423
1424 return isIncomingMerge ?
1425 PlasticLocalization.Name.NoIncomingChanges.GetString() :
1426 PlasticLocalization.Name.NoMergeChanges.GetString();
1427 }
1428
1429 static int GetPendingConflictsCount(
1430 List<MergeChangeInfo> selectedChangeInfos)
1431 {
1432 int result = 0;
1433 foreach (MergeChangeInfo changeInfo in selectedChangeInfos)
1434 {
1435 if (changeInfo.DirectoryConflict.IsResolved())
1436 continue;
1437
1438 result++;
1439 }
1440
1441 return result;
1442 }
1443
1444 void BuildComponents(
1445 WorkspaceInfo wkInfo,
1446 bool isIncomingMerge,
1447 bool isMergeTo,
1448 bool isShelvesetMerge)
1449 {
1450 mSearchField = new SearchField();
1451 mSearchField.downOrUpArrowKeyPressed +=
1452 SearchField_OnDownOrUpArrowKeyPressed;
1453
1454 MergeTreeHeaderState mergeHeaderState =
1455 MergeTreeHeaderState.GetDefault();
1456
1457 TreeHeaderSettings.Load(mergeHeaderState,
1458 isIncomingMerge ?
1459 UnityConstants.DEVELOPER_INCOMING_CHANGES_TABLE_SETTINGS_NAME :
1460 UnityConstants.DEVELOPER_MERGE_TABLE_SETTINGS_NAME,
1461 (int)MergeTreeColumn.Path, true);
1462
1463 mMenu = new MergeViewMenu(this, this, isIncomingMerge, isMergeTo, isShelvesetMerge);
1464 mMergeTreeView = new MergeTreeView(
1465 wkInfo, mergeHeaderState,
1466 MergeTreeHeaderState.GetColumnNames(),
1467 mMenu);
1468
1469 mMergeTreeView.Reload();
1470 }
1471
1472 bool mIsProcessMergesButtonVisible;
1473 bool mIsCancelMergesButtonVisible;
1474 bool mIsMessageLabelVisible;
1475 bool mIsErrorMessageLabelVisible;
1476 bool mIsMergeFinished;
1477
1478 bool mIsProcessMergesButtonEnabled;
1479 bool mIsCancelMergesButtonEnabled;
1480 bool mIsDirectoryResolutionPanelEnabled = true;
1481 bool mHasPendingDirectoryConflicts;
1482 bool mIsOperationRunning;
1483 bool mIsUpdateSuccessful;
1484
1485 string mProcessMergesButtonText;
1486
1487 string mTitleText;
1488 string mMessageLabelText;
1489 string mErrorMessageLabelText;
1490
1491 SearchField mSearchField;
1492 MergeTreeView mMergeTreeView;
1493
1494 MergeChangesTree mMergeChangesTree;
1495 MergeViewMenu mMenu;
1496 MergeDialogParameters mMergeDialogParameters;
1497
1498 Dictionary<DirectoryConflict, ConflictResolutionState> mConflictResolutionStates =
1499 new Dictionary<DirectoryConflict, ConflictResolutionState>();
1500
1501 ConflictResolutionState mConflictResolutionState;
1502
1503 int mDirectoryConflictCount;
1504 int mFileConflictCount;
1505 MergeViewTexts.ChangesToApplySummary mChangesSummary;
1506 readonly GUIContent mValidationLabel = new GUIContent(string.Empty, Images.GetWarnIcon());
1507 readonly EmptyStateData mEmptyStateData = new EmptyStateData();
1508 readonly ProgressControlsForViews mProgressControls;
1509 readonly CooldownWindowDelayer mCooldownClearUpdateSuccessAction;
1510 readonly MergeViewLogic mMergeViewLogic;
1511 readonly RepositorySpec mRepSpec;
1512 readonly bool mIsMergeTo;
1513 readonly bool mShowDiscardChangesButton;
1514 readonly bool mIsIncomingMerge;
1515 readonly IRefreshView mRefreshView;
1516 readonly IShelvedChangesUpdater mShelvedChangesUpdater;
1517 readonly CheckShelvedChanges.IUpdateShelvedChangesNotification mUpdateShelvedChangesNotification;
1518 readonly MergeViewLogic.IMergeController mMergeController;
1519 readonly GuiMessage.IGuiMessage mGuiMessage;
1520 readonly ObjectInfo mObjectInfo;
1521 readonly ObjectInfo mAncestorObjectInfo;
1522 readonly EnumMergeType mMergeType;
1523 readonly ShowIncomingChangesFrom mFrom;
1524 readonly EditorWindow mParentWindow;
1525 readonly StatusBar mStatusBar;
1526 readonly NewIncomingChangesUpdater mNewIncomingChangesUpdater;
1527 readonly IHistoryViewLauncher mHistoryViewLauncher;
1528 readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
1529 readonly IViewSwitcher mSwitcher;
1530 readonly IWorkspaceWindow mWorkspaceWindow;
1531 readonly WorkspaceInfo mWkInfo;
1532 }
1533}