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.

CheckinDialog.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using UnityEditor;
  5. using UnityEngine;
  6. using Codice.Client.Common;
  7. using Codice.Client.Common.EventTracking;
  8. using Codice.CM.Common;
  9. using GluonGui;
  10. using PlasticGui;
  11. using PlasticGui.Gluon;
  12. using Unity.PlasticSCM.Editor.AssetsOverlays;
  13. using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
  14. using Unity.PlasticSCM.Editor.AssetUtils;
  15. using Unity.PlasticSCM.Editor.AssetUtils.Processor;
  16. using Unity.PlasticSCM.Editor.UI;
  17. using Unity.PlasticSCM.Editor.UI.Progress;
  18. using Unity.PlasticSCM.Editor.UI.Tree;
  19. namespace Unity.PlasticSCM.Editor.AssetMenu.Dialogs
  20. {
  21. internal class CheckinDialog : PlasticDialog
  22. {
  23. protected override Rect DefaultRect
  24. {
  25. get
  26. {
  27. var baseRect = base.DefaultRect;
  28. return new Rect(baseRect.x, baseRect.y, 700, 450);
  29. }
  30. }
  31. protected override string GetTitle()
  32. {
  33. return PlasticLocalization.GetString(
  34. PlasticLocalization.Name.CheckinChanges);
  35. }
  36. internal static bool CheckinPaths(
  37. WorkspaceInfo wkInfo,
  38. List<string> paths,
  39. IAssetStatusCache assetStatusCache,
  40. bool isGluonMode,
  41. EditorWindow parentWindow,
  42. IWorkspaceWindow workspaceWindow,
  43. ViewHost viewHost,
  44. WorkspaceOperationsMonitor workspaceOperationsMonitor,
  45. GuiMessage.IGuiMessage guiMessage,
  46. IMergeViewLauncher mergeViewLauncher,
  47. IGluonViewSwitcher gluonViewSwitcher)
  48. {
  49. MetaCache metaCache = new MetaCache();
  50. metaCache.Build(paths);
  51. CheckinDialog dialog = Create(
  52. wkInfo,
  53. paths,
  54. assetStatusCache,
  55. metaCache,
  56. isGluonMode,
  57. new ProgressControlsForDialogs(),
  58. workspaceWindow,
  59. viewHost,
  60. workspaceOperationsMonitor,
  61. guiMessage,
  62. mergeViewLauncher,
  63. gluonViewSwitcher);
  64. return dialog.RunModal(parentWindow) == ResponseType.Ok;
  65. }
  66. protected override void OnModalGUI()
  67. {
  68. Title(PlasticLocalization.GetString(
  69. PlasticLocalization.Name.CheckinComment));
  70. GUI.SetNextControlName(CHECKIN_TEXTAREA_NAME);
  71. mComment = GUILayout.TextArea(
  72. mComment,
  73. EditorStyles.textArea,
  74. GUILayout.MinHeight(120));
  75. if (!mTextAreaFocused)
  76. {
  77. EditorGUI.FocusTextInControl(CHECKIN_TEXTAREA_NAME);
  78. mTextAreaFocused = true;
  79. }
  80. Title(PlasticLocalization.GetString(PlasticLocalization.Name.Files));
  81. DoFileList(
  82. mWkInfo,
  83. mPaths,
  84. mAssetStatusCache,
  85. mMetaCache);
  86. DrawProgressForDialogs.For(
  87. mProgressControls.ProgressData);
  88. DoButtonsArea();
  89. mProgressControls.ForcedUpdateProgress(this);
  90. }
  91. void DoFileList(
  92. WorkspaceInfo wkInfo,
  93. List<string> paths,
  94. IAssetStatusCache assetStatusCache,
  95. MetaCache metaCache)
  96. {
  97. mFileListScrollPosition = GUILayout.BeginScrollView(
  98. mFileListScrollPosition,
  99. EditorStyles.helpBox,
  100. GUILayout.ExpandHeight(true));
  101. foreach (string path in paths)
  102. {
  103. if (MetaPath.IsMetaPath(path))
  104. continue;
  105. Texture fileIcon = Directory.Exists(path) ?
  106. Images.GetDirectoryIcon() :
  107. Images.GetFileIcon(path);
  108. string label = WorkspacePath.GetWorkspaceRelativePath(
  109. wkInfo.ClientPath, path);
  110. if (metaCache.HasMeta(path))
  111. label = string.Concat(label, UnityConstants.TREEVIEW_META_LABEL);
  112. AssetsOverlays.AssetStatus assetStatus =
  113. assetStatusCache.GetStatus(path);
  114. Rect selectionRect = EditorGUILayout.GetControlRect();
  115. DoListViewItem(selectionRect, fileIcon, label, assetStatus);
  116. }
  117. GUILayout.EndScrollView();
  118. }
  119. void DoListViewItem(
  120. Rect itemRect,
  121. Texture fileIcon,
  122. string label,
  123. AssetsOverlays.AssetStatus statusToDraw)
  124. {
  125. Texture overlayIcon = DrawAssetOverlay.DrawOverlayIcon.
  126. GetOverlayIcon(statusToDraw);
  127. itemRect = DrawTreeViewItem.DrawIconLeft(
  128. itemRect,
  129. UnityConstants.TREEVIEW_ROW_HEIGHT,
  130. fileIcon,
  131. overlayIcon);
  132. GUI.Label(itemRect, label);
  133. }
  134. void DoButtonsArea()
  135. {
  136. using (new EditorGUILayout.HorizontalScope())
  137. {
  138. GUILayout.FlexibleSpace();
  139. if (Application.platform == RuntimePlatform.WindowsEditor)
  140. {
  141. DoCheckinButton();
  142. DoCancelButton();
  143. return;
  144. }
  145. DoCancelButton();
  146. DoCheckinButton();
  147. }
  148. }
  149. void DoCheckinButton()
  150. {
  151. GUI.enabled = !string.IsNullOrEmpty(mComment) && !mIsRunningCheckin;
  152. try
  153. {
  154. if (!AcceptButton(PlasticLocalization.GetString(
  155. PlasticLocalization.Name.CheckinButton)))
  156. return;
  157. }
  158. finally
  159. {
  160. if (!mSentCheckinTrackEvent)
  161. {
  162. TrackFeatureUseEvent.For(
  163. PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
  164. TrackFeatureUseEvent.Features.ContextMenuCheckinDialogCheckin);
  165. mSentCheckinTrackEvent = true;
  166. }
  167. GUI.enabled = true;
  168. }
  169. OkButtonWithCheckinAction();
  170. }
  171. void DoCancelButton()
  172. {
  173. if (!NormalButton(PlasticLocalization.GetString(
  174. PlasticLocalization.Name.CancelButton)))
  175. return;
  176. if (!mSentCancelTrackEvent)
  177. {
  178. TrackFeatureUseEvent.For(
  179. PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
  180. TrackFeatureUseEvent.Features.ContextMenuCheckinDialogCancel);
  181. mSentCancelTrackEvent = true;
  182. }
  183. CancelButtonAction();
  184. }
  185. void OkButtonWithCheckinAction()
  186. {
  187. bool isCancelled;
  188. SaveAssets.ForPathsWithConfirmation(
  189. mPaths, mWorkspaceOperationsMonitor,
  190. out isCancelled);
  191. if (isCancelled)
  192. return;
  193. mIsRunningCheckin = true;
  194. mPaths.AddRange(mMetaCache.GetExistingMeta(mPaths));
  195. if (mIsGluonMode)
  196. {
  197. CheckinDialogOperations.CheckinPathsPartial(
  198. mWkInfo,
  199. mPaths,
  200. mComment,
  201. mViewHost,
  202. this,
  203. mGuiMessage,
  204. mProgressControls,
  205. mGluonViewSwitcher);
  206. return;
  207. }
  208. CheckinDialogOperations.CheckinPaths(
  209. mWkInfo,
  210. mPaths,
  211. mComment,
  212. mWorkspaceWindow,
  213. this,
  214. mGuiMessage,
  215. mProgressControls,
  216. mMergeViewLauncher);
  217. }
  218. static CheckinDialog Create(
  219. WorkspaceInfo wkInfo,
  220. List<string> paths,
  221. IAssetStatusCache assetStatusCache,
  222. MetaCache metaCache,
  223. bool isGluonMode,
  224. ProgressControlsForDialogs progressControls,
  225. IWorkspaceWindow workspaceWindow,
  226. ViewHost viewHost,
  227. WorkspaceOperationsMonitor workspaceOperationsMonitor,
  228. GuiMessage.IGuiMessage guiMessage,
  229. IMergeViewLauncher mergeViewLauncher,
  230. IGluonViewSwitcher gluonViewSwitcher)
  231. {
  232. var instance = CreateInstance<CheckinDialog>();
  233. instance.IsResizable = true;
  234. instance.minSize = new Vector2(520, 370);
  235. instance.mWkInfo = wkInfo;
  236. instance.mPaths = paths;
  237. instance.mAssetStatusCache = assetStatusCache;
  238. instance.mMetaCache = metaCache;
  239. instance.mIsGluonMode = isGluonMode;
  240. instance.mProgressControls = progressControls;
  241. instance.mWorkspaceWindow = workspaceWindow;
  242. instance.mViewHost = viewHost;
  243. instance.mWorkspaceOperationsMonitor = workspaceOperationsMonitor;
  244. instance.mGuiMessage = guiMessage;
  245. instance.mMergeViewLauncher = mergeViewLauncher;
  246. instance.mGluonViewSwitcher = gluonViewSwitcher;
  247. instance.mEscapeKeyAction = instance.CancelButtonAction;
  248. return instance;
  249. }
  250. WorkspaceInfo mWkInfo;
  251. List<string> mPaths;
  252. IAssetStatusCache mAssetStatusCache;
  253. MetaCache mMetaCache;
  254. bool mIsGluonMode;
  255. bool mTextAreaFocused;
  256. string mComment;
  257. bool mIsRunningCheckin;
  258. Vector2 mFileListScrollPosition;
  259. // IMGUI evaluates every frame, need to make sure feature tracks get sent only once
  260. bool mSentCheckinTrackEvent = false;
  261. bool mSentCancelTrackEvent = false;
  262. ProgressControlsForDialogs mProgressControls;
  263. IWorkspaceWindow mWorkspaceWindow;
  264. WorkspaceOperationsMonitor mWorkspaceOperationsMonitor;
  265. ViewHost mViewHost;
  266. IMergeViewLauncher mMergeViewLauncher;
  267. IGluonViewSwitcher mGluonViewSwitcher;
  268. GuiMessage.IGuiMessage mGuiMessage;
  269. const string CHECKIN_TEXTAREA_NAME = "checkin_textarea";
  270. class MetaCache
  271. {
  272. internal bool HasMeta(string path)
  273. {
  274. return mCache.Contains(MetaPath.GetMetaPath(path));
  275. }
  276. internal List<string> GetExistingMeta(List<string> paths)
  277. {
  278. List<string> result = new List<string>();
  279. foreach (string path in paths)
  280. {
  281. string metaPath = MetaPath.GetMetaPath(path);
  282. if (!mCache.Contains(metaPath))
  283. continue;
  284. result.Add(metaPath);
  285. }
  286. return result;
  287. }
  288. internal void Build(List<string> paths)
  289. {
  290. HashSet<string> indexedKeys = BuildIndexedKeys(paths);
  291. for (int i = paths.Count - 1; i >= 0; i--)
  292. {
  293. string currentPath = paths[i];
  294. if (!MetaPath.IsMetaPath(currentPath))
  295. continue;
  296. string realPath = MetaPath.GetPathFromMetaPath(currentPath);
  297. if (!indexedKeys.Contains(realPath))
  298. continue;
  299. // found foo.c and foo.c.meta
  300. // with the same chage types - move .meta to cache
  301. mCache.Add(currentPath);
  302. paths.RemoveAt(i);
  303. }
  304. }
  305. static HashSet<string> BuildIndexedKeys(List<string> paths)
  306. {
  307. HashSet<string> result = new HashSet<string>();
  308. foreach (string path in paths)
  309. {
  310. if (MetaPath.IsMetaPath(path))
  311. continue;
  312. result.Add(path);
  313. }
  314. return result;
  315. }
  316. HashSet<string> mCache =
  317. new HashSet<string>();
  318. }
  319. }
  320. }