ConfigurationEditor.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #nullable enable
  2. using System;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using Terminal.Gui;
  7. namespace UICatalog.Scenarios;
  8. [ScenarioMetadata ("Configuration Editor", "Editor of Terminal.Gui Config Files")]
  9. [ScenarioCategory ("TabView")]
  10. [ScenarioCategory ("Colors")]
  11. [ScenarioCategory ("Files and IO")]
  12. [ScenarioCategory ("TextView")]
  13. [ScenarioCategory ("Configuration")]
  14. public class ConfigurationEditor : Scenario
  15. {
  16. //private static Scheme _editorScheme = SchemeManager.GetScheme (Schemes.Base);
  17. //private static Action? _editorSchemeChanged;
  18. private TabView? _tabView;
  19. private Shortcut? _lenShortcut;
  20. //[ConfigurationProperty (Scope = typeof (AppSettingsScope))]
  21. //public static Scheme EditorScheme
  22. //{
  23. // get => _editorScheme;
  24. // set
  25. // {
  26. // _editorScheme = value;
  27. // _editorSchemeChanged?.Invoke ();
  28. // }
  29. //}
  30. public override void Main ()
  31. {
  32. Application.Init ();
  33. Window? win = new ();
  34. _lenShortcut = new Shortcut ()
  35. {
  36. Title = "",
  37. };
  38. var quitShortcut = new Shortcut ()
  39. {
  40. Key = Application.QuitKey,
  41. Title = $"Quit",
  42. Action = Quit
  43. };
  44. var reloadShortcut = new Shortcut ()
  45. {
  46. Key = Key.F5.WithShift,
  47. Title = "Reload",
  48. };
  49. reloadShortcut.Accepting += (s, e) => { Reload (); };
  50. var saveShortcut = new Shortcut ()
  51. {
  52. Key = Key.F4,
  53. Title = "Save",
  54. Action = Save
  55. };
  56. var statusBar = new StatusBar ([quitShortcut, reloadShortcut, saveShortcut, _lenShortcut]);
  57. _tabView = new ()
  58. {
  59. Width = Dim.Fill (),
  60. Height = Dim.Fill (Dim.Func (() => statusBar.Frame.Height))
  61. };
  62. win.Add (_tabView, statusBar);
  63. win.Loaded += (s, a) =>
  64. {
  65. Open ();
  66. //_editorSchemeChanged?.Invoke ();
  67. };
  68. //_editorSchemeChanged += OnEditorSchemeChanged;
  69. ConfigurationManager.Applied += ConfigurationManagerOnApplied;
  70. Application.Run (win);
  71. //_editorSchemeChanged -= OnEditorSchemeChanged;
  72. win.Dispose ();
  73. win = null;
  74. Application.Shutdown ();
  75. return;
  76. //void OnEditorSchemeChanged ()
  77. //{
  78. // if (Application.Top is { })
  79. // {
  80. // return;
  81. // }
  82. // foreach (ConfigTextView t in _tabView.SubViews.OfType<ConfigTextView> ())
  83. // {
  84. // t.SetScheme (EditorScheme);
  85. // }
  86. //}
  87. void ConfigurationManagerOnApplied (object? sender, ConfigurationManagerEventArgs e)
  88. {
  89. if (win is { })
  90. {
  91. win.SetNeedsDraw ();
  92. }
  93. }
  94. }
  95. public void Save ()
  96. {
  97. if (Application.Navigation?.GetFocused () is ConfigTextView editor)
  98. {
  99. editor.Save ();
  100. }
  101. }
  102. private void Open ()
  103. {
  104. foreach (var config in ConfigurationManager.SourcesManager!.Sources)
  105. {
  106. var homeDir = $"{Environment.GetFolderPath (Environment.SpecialFolder.UserProfile)}";
  107. var fileInfo = new FileInfo (config.Value.Replace ("~", homeDir));
  108. var editor = new ConfigTextView
  109. {
  110. Title = config.Value.StartsWith ("resource://") ? fileInfo.Name : config.Value,
  111. Width = Dim.Fill (),
  112. Height = Dim.Fill (),
  113. FileInfo = fileInfo,
  114. };
  115. if (config.Value == "HardCoded")
  116. {
  117. editor.Title = "HardCoded";
  118. }
  119. Tab tab = new Tab ()
  120. {
  121. View = editor,
  122. DisplayText = config.Key.ToString ()
  123. };
  124. _tabView!.AddTab (tab, false);
  125. editor.Read ();
  126. editor.ContentsChanged += (sender, args) =>
  127. {
  128. _lenShortcut!.Title = _lenShortcut!.Title.Replace ("*", "");
  129. if (editor.IsDirty)
  130. {
  131. _lenShortcut!.Title += "*";
  132. }
  133. };
  134. _lenShortcut!.Title = $"{editor.Title}";
  135. }
  136. _tabView!.SelectedTabChanged += (sender, args) =>
  137. {
  138. _lenShortcut!.Title = $"{args.NewTab.View!.Title}";
  139. };
  140. }
  141. private void Quit ()
  142. {
  143. foreach (ConfigTextView editor in _tabView!.Tabs.Select (v =>
  144. {
  145. if (v.View is ConfigTextView ctv)
  146. {
  147. return ctv;
  148. }
  149. return null;
  150. }).Cast<ConfigTextView> ())
  151. {
  152. if (editor.IsDirty)
  153. {
  154. int result = MessageBox.Query (
  155. "Save Changes",
  156. $"Save changes to {editor.FileInfo!.Name}",
  157. "_Yes",
  158. "_No",
  159. "_Cancel"
  160. );
  161. if (result == -1 || result == 2)
  162. {
  163. // user cancelled
  164. }
  165. if (result == 0)
  166. {
  167. editor.Save ();
  168. }
  169. }
  170. }
  171. Application.RequestStop ();
  172. }
  173. private void Reload ()
  174. {
  175. if (Application.Navigation?.GetFocused () is ConfigTextView editor)
  176. {
  177. editor.Read ();
  178. }
  179. }
  180. private class ConfigTextView : TextView
  181. {
  182. internal ConfigTextView ()
  183. {
  184. TabStop = TabBehavior.TabGroup;
  185. }
  186. internal FileInfo? FileInfo { get; set; }
  187. internal void Read ()
  188. {
  189. Assembly? assembly = null;
  190. if (FileInfo!.FullName.Contains ("[Terminal.Gui]"))
  191. {
  192. // Library resources
  193. assembly = typeof (ConfigurationManager).Assembly;
  194. }
  195. else if (FileInfo.FullName.Contains ("[UICatalog]"))
  196. {
  197. assembly = Assembly.GetEntryAssembly ();
  198. }
  199. if (assembly != null)
  200. {
  201. string? name = assembly
  202. .GetManifestResourceNames ()
  203. .FirstOrDefault (x => x.EndsWith ("config.json"));
  204. if (!string.IsNullOrEmpty (name))
  205. {
  206. using Stream? stream = assembly.GetManifestResourceStream (name);
  207. using var reader = new StreamReader (stream!);
  208. Text = reader.ReadToEnd ();
  209. ReadOnly = true;
  210. Enabled = true;
  211. }
  212. return;
  213. }
  214. if (FileInfo!.FullName.Contains ("HardCoded"))
  215. {
  216. Text = ConfigurationManager.GetHardCodedConfig ()!;
  217. ReadOnly = true;
  218. Enabled = true;
  219. }
  220. else if (FileInfo!.FullName.Contains ("RuntimeConfig"))
  221. {
  222. Text = ConfigurationManager.RuntimeConfig!;
  223. }
  224. else if (!FileInfo.Exists)
  225. {
  226. // Create empty config file
  227. Text = ConfigurationManager.GetEmptyConfig ();
  228. }
  229. else
  230. {
  231. Text = File.ReadAllText (FileInfo.FullName);
  232. }
  233. }
  234. internal void Save ()
  235. {
  236. if (FileInfo!.FullName.Contains ("RuntimeConfig"))
  237. {
  238. ConfigurationManager.RuntimeConfig = Text;
  239. IsDirty = false;
  240. return;
  241. }
  242. if (!Directory.Exists (FileInfo.DirectoryName))
  243. {
  244. // Create dir
  245. Directory.CreateDirectory (FileInfo.DirectoryName!);
  246. }
  247. using StreamWriter writer = File.CreateText (FileInfo.FullName);
  248. writer.Write (Text);
  249. writer.Close ();
  250. IsDirty = false;
  251. }
  252. }
  253. }