#nullable enable using System.Reflection; namespace UICatalog.Scenarios; [ScenarioMetadata ("Configuration Editor", "Edits of Terminal.Gui Config Files")] [ScenarioCategory ("TabView")] [ScenarioCategory ("Colors")] [ScenarioCategory ("Files and IO")] [ScenarioCategory ("TextView")] [ScenarioCategory ("Configuration")] public class ConfigurationEditor : Scenario { private TabView? _tabView; private Shortcut? _lenShortcut; public override void Main () { Application.Init (); Window? win = new (); _lenShortcut = new () { Title = "", }; Shortcut quitShortcut = new () { Key = Application.QuitKey, Title = $"Quit", Action = Quit }; Shortcut reloadShortcut = new () { Key = Key.F5.WithShift, Title = "Reload", }; reloadShortcut.Accepting += (s, e) => { Reload (); e.Handled = true; }; Shortcut saveShortcut = new () { Key = Key.F4, Title = "Save", Action = Save }; StatusBar statusBar = new ([quitShortcut, reloadShortcut, saveShortcut, _lenShortcut]); _tabView = new () { Width = Dim.Fill (), Height = Dim.Fill (Dim.Func (_ => statusBar.Frame.Height)) }; win.Add (_tabView, statusBar); win.Loaded += (s, a) => { Open (); }; ConfigurationManager.Applied += ConfigurationManagerOnApplied; Application.Run (win); win.Dispose (); Application.Shutdown (); return; void ConfigurationManagerOnApplied (object? sender, ConfigurationManagerEventArgs e) { Application.Current?.SetNeedsDraw (); } } public void Save () { if (Application.Navigation?.GetFocused () is ConfigTextView editor) { editor.Save (); } } private void Open () { foreach (KeyValuePair config in ConfigurationManager.SourcesManager!.Sources) { var homeDir = $"{Environment.GetFolderPath (Environment.SpecialFolder.UserProfile)}"; var fileInfo = new FileInfo (config.Value.Replace ("~", homeDir)); var editor = new ConfigTextView { Title = config.Value.StartsWith ("resource://") ? fileInfo.Name : config.Value, Width = Dim.Fill (), Height = Dim.Fill (), FileInfo = fileInfo, }; if (config.Value == "HardCoded") { editor.Title = "HardCoded"; } Tab tab = new () { View = editor, DisplayText = config.Key.ToString () }; _tabView!.AddTab (tab, false); editor.Read (); editor.ContentsChanged += (sender, args) => { _lenShortcut!.Title = _lenShortcut!.Title.Replace ("*", ""); if (editor.IsDirty) { _lenShortcut!.Title += "*"; } }; _lenShortcut!.Title = $"{editor.Title}"; } _tabView!.SelectedTabChanged += (sender, args) => { _lenShortcut!.Title = $"{args.NewTab.View!.Title}"; }; } private void Quit () { foreach (ConfigTextView editor in _tabView!.Tabs.Select (v => { if (v.View is ConfigTextView ctv) { return ctv; } return null; }).Cast ()) { if (!editor.IsDirty) { continue; } int result = MessageBox.Query ( "Save Changes", $"Save changes to {editor.FileInfo!.Name}", "_Yes", "_No", "_Cancel" ); switch (result) { case 0: editor.Save (); break; case 1: // user decided not save changes break; case -1 or 2: // user cancelled return; } } Application.RequestStop (); } private static void Reload () { if (Application.Navigation?.GetFocused () is ConfigTextView editor) { editor.Read (); } } private class ConfigTextView : TextView { internal ConfigTextView () { TabStop = TabBehavior.TabGroup; } internal FileInfo? FileInfo { get; init; } internal void Read () { Assembly? assembly = null; if (FileInfo!.FullName.Contains ("[Terminal.Gui]")) { // Library resources assembly = typeof (ConfigurationManager).Assembly; } else if (FileInfo.FullName.Contains ("[UICatalog]")) { assembly = Assembly.GetEntryAssembly (); } if (assembly != null) { string? name = assembly .GetManifestResourceNames () .FirstOrDefault (x => x.EndsWith ("config.json")); if (string.IsNullOrEmpty (name)) { return; } using Stream? stream = assembly.GetManifestResourceStream (name); using var reader = new StreamReader (stream!); Text = reader.ReadToEnd (); ReadOnly = true; Enabled = true; return; } if (FileInfo!.FullName.Contains ("HardCoded")) { Text = ConfigurationManager.GetHardCodedConfig ()!; ReadOnly = true; Enabled = true; } else if (FileInfo!.FullName.Contains ("RuntimeConfig")) { Text = ConfigurationManager.RuntimeConfig!; } else if (!FileInfo.Exists) { // Create empty config file Text = ConfigurationManager.GetEmptyConfig (); } else { Text = File.ReadAllText (FileInfo.FullName); } } internal void Save () { if (FileInfo!.FullName.Contains ("RuntimeConfig")) { ConfigurationManager.RuntimeConfig = Text; IsDirty = false; return; } if (!Directory.Exists (FileInfo.DirectoryName)) { // Create dir Directory.CreateDirectory (FileInfo.DirectoryName!); } using StreamWriter writer = File.CreateText (FileInfo.FullName); writer.Write (Text); writer.Close (); IsDirty = false; } } }