暫無描述
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.

PlasticDialog.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine;
  5. using PlasticGui;
  6. namespace Unity.PlasticSCM.Editor.UI
  7. {
  8. internal abstract class PlasticDialog : EditorWindow, IPlasticDialogCloser
  9. {
  10. protected virtual Rect DefaultRect
  11. {
  12. get
  13. {
  14. int pixelWidth = Screen.currentResolution.width;
  15. float x = (pixelWidth - DEFAULT_WIDTH) / 2;
  16. return new Rect(x, 200, DEFAULT_WIDTH, DEFAULT_HEIGHT);
  17. }
  18. }
  19. protected virtual bool IsResizable { get; set; }
  20. internal void OkButtonAction()
  21. {
  22. CompleteModal(ResponseType.Ok);
  23. }
  24. internal void CancelButtonAction()
  25. {
  26. CompleteModal(ResponseType.Cancel);
  27. }
  28. internal void CloseButtonAction()
  29. {
  30. CompleteModal(ResponseType.None);
  31. }
  32. internal void ApplyButtonAction()
  33. {
  34. CompleteModal(ResponseType.Apply);
  35. }
  36. internal void RunUtility(EditorWindow parentWindow)
  37. {
  38. InitializeVars(parentWindow);
  39. if (!IsResizable)
  40. MakeNonResizable();
  41. ShowUtility();
  42. }
  43. internal ResponseType RunModal(EditorWindow parentWindow)
  44. {
  45. InitializeVars(parentWindow);
  46. if (!IsResizable)
  47. MakeNonResizable();
  48. if (UI.RunModal.IsAvailable())
  49. {
  50. UI.RunModal.Dialog(this);
  51. return mAnswer;
  52. }
  53. EditorUtility.DisplayDialog(
  54. PlasticLocalization.GetString(PlasticLocalization.Name.UnityVersionControl),
  55. PlasticLocalization.GetString(PlasticLocalization.Name.PluginModalInformation),
  56. PlasticLocalization.GetString(PlasticLocalization.Name.CloseButton));
  57. return ResponseType.None;
  58. }
  59. protected void OnGUI()
  60. {
  61. try
  62. {
  63. // If the Dialog has been saved into the Unity editor layout and persisted between restarts, the methods
  64. // to configure the dialogs will be skipped. Simple fix here is to close it when this state is detected.
  65. // Fixes a NPE loop when the state mentioned above is occurring.
  66. if (!mIsConfigured)
  67. {
  68. mIsClosed = true;
  69. Close();
  70. return;
  71. }
  72. if (Event.current.type == EventType.Layout)
  73. {
  74. EditorDispatcher.Update();
  75. }
  76. if (!mFocusedOnce)
  77. {
  78. // Somehow the prevents the dialog from jumping when dragged
  79. // NOTE(rafa): We cannot do every frame because the modal kidnaps focus for all processes (in mac at least)
  80. Focus();
  81. mFocusedOnce = true;
  82. }
  83. ProcessKeyActions();
  84. if (mIsClosed)
  85. return;
  86. GUI.Box(new Rect(0, 0, position.width, position.height), GUIContent.none, EditorStyles.label);
  87. float margin = 25;
  88. float marginTop = 25;
  89. using (new EditorGUILayout.HorizontalScope(GUILayout.Height(position.height)))
  90. {
  91. GUILayout.Space(margin);
  92. using (new EditorGUILayout.VerticalScope(GUILayout.Height(position.height)))
  93. {
  94. GUILayout.Space(marginTop);
  95. OnModalGUI();
  96. GUILayout.Space(margin);
  97. }
  98. GUILayout.Space(margin);
  99. }
  100. var lastRect = GUILayoutUtility.GetLastRect();
  101. float desiredHeight = lastRect.yMax;
  102. Rect newPos = position;
  103. newPos.height = desiredHeight;
  104. if (position.height < desiredHeight)
  105. position = newPos;
  106. if (Event.current.type == EventType.Repaint)
  107. {
  108. if (mIsCompleted)
  109. {
  110. mIsClosed = true;
  111. Close();
  112. }
  113. }
  114. }
  115. finally
  116. {
  117. if (mIsClosed)
  118. EditorGUIUtility.ExitGUI();
  119. }
  120. }
  121. void OnDestroy()
  122. {
  123. if (!mIsConfigured)
  124. return;
  125. SaveSettings();
  126. if (mParentWindow == null)
  127. return;
  128. mParentWindow.Focus();
  129. }
  130. protected virtual void SaveSettings() { }
  131. protected abstract void OnModalGUI();
  132. protected abstract string GetTitle();
  133. protected void Paragraph(string text)
  134. {
  135. GUILayout.Label(text, UnityStyles.Paragraph);
  136. GUILayout.Space(DEFAULT_PARAGRAPH_SPACING);
  137. }
  138. protected void TextBlockWithEndLink(
  139. string url, string formattedExplanation,
  140. GUIStyle textblockStyle)
  141. {
  142. DrawTextBlockWithEndLink.For(url, formattedExplanation, textblockStyle);
  143. }
  144. protected static void Title(string text)
  145. {
  146. GUILayout.Label(text, UnityStyles.Dialog.Toggle);
  147. }
  148. protected static bool TitleToggle(string text, bool isOn)
  149. {
  150. return EditorGUILayout.ToggleLeft(text, isOn, UnityStyles.Dialog.Toggle);
  151. }
  152. protected static bool TitleToggle(string text, bool isOn, GUIStyle style)
  153. {
  154. return EditorGUILayout.ToggleLeft(text, isOn, style);
  155. }
  156. protected static string TextEntry(
  157. string label,
  158. string value,
  159. float width,
  160. float x)
  161. {
  162. return TextEntry(
  163. label,
  164. value,
  165. null,
  166. width,
  167. x);
  168. }
  169. protected static string TextEntry(
  170. string label, string value, string controlName, float width, float x)
  171. {
  172. using (new EditorGUILayout.HorizontalScope())
  173. {
  174. EntryLabel(label);
  175. GUILayout.FlexibleSpace();
  176. var rt = GUILayoutUtility.GetRect(
  177. new GUIContent(value), UnityStyles.Dialog.EntryLabel);
  178. rt.width = width;
  179. rt.x = x;
  180. if (!string.IsNullOrEmpty(controlName))
  181. GUI.SetNextControlName(controlName);
  182. return GUI.TextField(rt, value);
  183. }
  184. }
  185. protected static string ComboBox(
  186. string label,
  187. string value,
  188. List<string> dropDownOptions,
  189. GenericMenu.MenuFunction2 optionSelected,
  190. float width,
  191. float x)
  192. {
  193. using (new EditorGUILayout.HorizontalScope())
  194. {
  195. EntryLabel(label);
  196. GUILayout.FlexibleSpace();
  197. var rt = GUILayoutUtility.GetRect(
  198. new GUIContent(value), UnityStyles.Dialog.EntryLabel);
  199. rt.width = width;
  200. rt.x = x;
  201. return DropDownTextField.DoDropDownTextField(
  202. value,
  203. label,
  204. dropDownOptions,
  205. optionSelected,
  206. rt);
  207. }
  208. }
  209. protected static string PasswordEntry(
  210. string label, string value, float width, float x)
  211. {
  212. using (new EditorGUILayout.HorizontalScope())
  213. {
  214. EntryLabel(label);
  215. GUILayout.FlexibleSpace();
  216. var rt = GUILayoutUtility.GetRect(
  217. new GUIContent(value), UnityStyles.Dialog.EntryLabel);
  218. rt.width = width;
  219. rt.x = x;
  220. return GUI.PasswordField(rt, value, '*');
  221. }
  222. }
  223. static void EntryLabel(string labelText)
  224. {
  225. GUIContent labelContent = new GUIContent(labelText);
  226. GUIStyle labelStyle = UnityStyles.Dialog.EntryLabel;
  227. Rect rt = GUILayoutUtility.GetRect(labelContent, labelStyle);
  228. GUI.Label(rt, labelText, EditorStyles.label);
  229. }
  230. protected static bool ToggleEntry(
  231. string label, bool value, float width, float x)
  232. {
  233. var rt = GUILayoutUtility.GetRect(
  234. new GUIContent(label), UnityStyles.Dialog.EntryLabel);
  235. rt.width = width;
  236. rt.x = x;
  237. return GUI.Toggle(rt, value, label);
  238. }
  239. protected static bool ToggleEntry(string label, bool value)
  240. {
  241. var rt = GUILayoutUtility.GetRect(
  242. new GUIContent(label), UnityStyles.Dialog.EntryLabel);
  243. return GUI.Toggle(rt, value, label);
  244. }
  245. protected static bool NormalButton(string text)
  246. {
  247. return GUILayout.Button(
  248. text, UnityStyles.Dialog.NormalButton,
  249. GUILayout.MinWidth(80),
  250. GUILayout.Height(25));
  251. }
  252. void IPlasticDialogCloser.CloseDialog()
  253. {
  254. OkButtonAction();
  255. }
  256. void ProcessKeyActions()
  257. {
  258. Event e = Event.current;
  259. if (mEnterKeyAction != null &&
  260. Keyboard.IsReturnOrEnterKeyPressed(e))
  261. {
  262. mEnterKeyAction.Invoke();
  263. e.Use();
  264. return;
  265. }
  266. if (mEscapeKeyAction != null &&
  267. Keyboard.IsKeyPressed(e, KeyCode.Escape))
  268. {
  269. mEscapeKeyAction.Invoke();
  270. e.Use();
  271. return;
  272. }
  273. }
  274. protected static bool AcceptButton(string text, int extraWidth = 10)
  275. {
  276. GUI.color = new Color(0.098f, 0.502f, 0.965f, .8f);
  277. int textWidth = (int)((GUIStyle)UnityStyles.Dialog.AcceptButtonText)
  278. .CalcSize(new GUIContent(text)).x;
  279. bool pressed = GUILayout.Button(
  280. string.Empty, GetEditorSkin().button,
  281. GUILayout.MinWidth(Math.Max(80, textWidth + extraWidth)),
  282. GUILayout.Height(25));
  283. GUI.color = Color.white;
  284. Rect buttonRect = GUILayoutUtility.GetLastRect();
  285. GUI.Label(buttonRect, text, UnityStyles.Dialog.AcceptButtonText);
  286. return pressed;
  287. }
  288. void CompleteModal(ResponseType answer)
  289. {
  290. mIsCompleted = true;
  291. mAnswer = answer;
  292. }
  293. void InitializeVars(EditorWindow parentWindow)
  294. {
  295. mIsConfigured = true;
  296. mIsCompleted = false;
  297. mIsClosed = false;
  298. mAnswer = ResponseType.Cancel;
  299. titleContent = new GUIContent(GetTitle());
  300. mFocusedOnce = false;
  301. position = DefaultRect;
  302. mParentWindow = parentWindow;
  303. }
  304. void MakeNonResizable()
  305. {
  306. maxSize = DefaultRect.size;
  307. minSize = maxSize;
  308. }
  309. static GUISkin GetEditorSkin()
  310. {
  311. return EditorGUIUtility.isProSkin ?
  312. EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene) :
  313. EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector);
  314. }
  315. bool mIsConfigured;
  316. bool mIsCompleted;
  317. bool mIsClosed;
  318. ResponseType mAnswer;
  319. protected Action mEnterKeyAction = null;
  320. protected Action mEscapeKeyAction = null;
  321. bool mFocusedOnce;
  322. EditorWindow mParentWindow;
  323. const float DEFAULT_WIDTH = 500f;
  324. const float DEFAULT_HEIGHT = 180f;
  325. const float DEFAULT_PARAGRAPH_SPACING = 10f;
  326. }
  327. }