DiffWindow.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright (c) 2025 TerraByte Inc.
  2. //
  3. // A modal editor window for displaying text differences (diffs) and
  4. // confirming an action with the user.
  5. using System;
  6. using System.IO;
  7. using UnityEditor;
  8. using UnityEngine;
  9. namespace Terra.Arbitrator
  10. {
  11. public class DiffWindow : EditorWindow
  12. {
  13. private string _filePath;
  14. private string _diffContent;
  15. private Action<bool> _onCloseCallback;
  16. private Vector2 _scrollPosition;
  17. private bool _callbackInvoked = false;
  18. /// <summary>
  19. /// Shows a modal window to display the diff and get user confirmation.
  20. /// </summary>
  21. /// <param name="filePath">The path of the file being diffed.</param>
  22. /// <param name="diffContent">The diff text to display.</param>
  23. /// <param name="onCloseCallback">A callback that returns true if the user confirmed, otherwise false.</param>
  24. public static void ShowWindow(string filePath, string diffContent, Action<bool> onCloseCallback)
  25. {
  26. DiffWindow window = GetWindow<DiffWindow>(true, "Diff Viewer", true);
  27. window.titleContent = new GUIContent($"Diff: {Path.GetFileName(filePath)}");
  28. window.minSize = new Vector2(700, 500);
  29. window._filePath = filePath;
  30. window._diffContent = diffContent;
  31. window._onCloseCallback = onCloseCallback;
  32. window._callbackInvoked = false;
  33. window.ShowModalUtility(); // Show as a blocking modal window
  34. }
  35. private void OnGUI()
  36. {
  37. EditorGUILayout.LabelField(_filePath, EditorStyles.boldLabel);
  38. // Create a custom style for the diff text for better readability
  39. var diffStyle = new GUIStyle(EditorStyles.textArea)
  40. {
  41. richText = true,
  42. wordWrap = false
  43. };
  44. _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, EditorStyles.helpBox, GUILayout.ExpandHeight(true));
  45. EditorGUILayout.SelectableLabel(GetColoredDiff(_diffContent), diffStyle, GUILayout.ExpandHeight(true));
  46. EditorGUILayout.EndScrollView();
  47. EditorGUILayout.Space();
  48. EditorGUILayout.HelpBox("Review the changes above. Green lines are additions, red lines are deletions. Reverting will permanently discard these changes.", MessageType.Warning);
  49. EditorGUILayout.BeginHorizontal();
  50. GUILayout.FlexibleSpace();
  51. if (GUILayout.Button("Revert Changes", GUILayout.Height(30), GUILayout.Width(150)))
  52. {
  53. _callbackInvoked = true;
  54. _onCloseCallback?.Invoke(true);
  55. Close();
  56. }
  57. if (GUILayout.Button("Cancel", GUILayout.Height(30), GUILayout.Width(120)))
  58. {
  59. // Let OnDestroy handle the callback
  60. Close();
  61. }
  62. EditorGUILayout.EndHorizontal();
  63. }
  64. private static string GetColoredDiff(string rawDiff)
  65. {
  66. var coloredDiff = "";
  67. var lines = rawDiff.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
  68. foreach (var line in lines)
  69. {
  70. if (line.StartsWith("+"))
  71. {
  72. coloredDiff += $"<color=green>{line}</color>\n";
  73. }
  74. else if (line.StartsWith("-"))
  75. {
  76. coloredDiff += $"<color=red>{line}</color>\n";
  77. }
  78. else if (line.StartsWith("@@"))
  79. {
  80. coloredDiff += $"<color=cyan>{line}</color>\n";
  81. }
  82. else
  83. {
  84. coloredDiff += $"{line}\n";
  85. }
  86. }
  87. return coloredDiff;
  88. }
  89. private void OnDestroy()
  90. {
  91. // This is called when the window is closed by any means.
  92. // If the callback hasn't been invoked yet (i.e., user clicked 'X' or 'Cancel'),
  93. // we invoke it with 'false' to signify cancellation.
  94. if (!_callbackInvoked)
  95. {
  96. _onCloseCallback?.Invoke(false);
  97. }
  98. }
  99. }
  100. }