Notepad.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. using System.IO;
  2. using Terminal.Gui;
  3. namespace UICatalog.Scenarios {
  4. [ScenarioMetadata (Name: "Notepad", Description: "Multi-tab text editor uising the TabView control.")]
  5. [ScenarioCategory ("Controls"), ScenarioCategory ("TabView")]
  6. public class Notepad : Scenario {
  7. TabView tabView;
  8. private int numbeOfNewTabs = 1;
  9. // Don't create a Window, just return the top-level view
  10. public override void Init (Toplevel top, ColorScheme colorScheme)
  11. {
  12. Application.Init ();
  13. Top = top;
  14. if (Top == null) {
  15. Top = Application.Top;
  16. }
  17. Top.ColorScheme = Colors.Base;
  18. }
  19. public override void Setup ()
  20. {
  21. var menu = new MenuBar (new MenuBarItem [] {
  22. new MenuBarItem ("_File", new MenuItem [] {
  23. new MenuItem ("_New", "", () => New()),
  24. new MenuItem ("_Open", "", () => Open()),
  25. new MenuItem ("_Save", "", () => Save()),
  26. new MenuItem ("Save _As", "", () => SaveAs()),
  27. new MenuItem ("_Close", "", () => Close()),
  28. new MenuItem ("_Quit", "", () => Quit()),
  29. })
  30. });
  31. Top.Add (menu);
  32. tabView = new TabView () {
  33. X = 0,
  34. Y = 1,
  35. Width = Dim.Fill (),
  36. Height = Dim.Fill (1),
  37. };
  38. tabView.Style.ShowBorder = true;
  39. tabView.ApplyStyleChanges ();
  40. Top.Add (tabView);
  41. var lenStatusItem = new StatusItem (Key.CharMask, "Len: ", null);
  42. var statusBar = new StatusBar (new StatusItem [] {
  43. new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
  44. // These shortcut keys don't seem to work correctly in linux
  45. //new StatusItem(Key.CtrlMask | Key.N, "~^O~ Open", () => Open()),
  46. //new StatusItem(Key.CtrlMask | Key.N, "~^N~ New", () => New()),
  47. new StatusItem(Key.CtrlMask | Key.S, "~^S~ Save", () => Save()),
  48. new StatusItem(Key.CtrlMask | Key.W, "~^W~ Close", () => Close()),
  49. lenStatusItem,
  50. });
  51. tabView.SelectedTabChanged += (s, e) => lenStatusItem.Title = $"Len:{(e.NewTab?.View?.Text?.Length ?? 0)}";
  52. Top.Add (statusBar);
  53. New ();
  54. }
  55. private void New ()
  56. {
  57. Open ("", null, $"new {numbeOfNewTabs++}");
  58. }
  59. private void Close ()
  60. {
  61. var tab = tabView.SelectedTab as OpenedFile;
  62. if (tab == null) {
  63. return;
  64. }
  65. if (tab.UnsavedChanges) {
  66. int result = MessageBox.Query ("Save Changes", $"Save changes to {tab.Text.ToString ().TrimEnd ('*')}", "Yes", "No", "Cancel");
  67. if (result == -1 || result == 2) {
  68. // user cancelled
  69. return;
  70. }
  71. if (result == 0) {
  72. tab.Save ();
  73. }
  74. }
  75. // close and dispose the tab
  76. tabView.RemoveTab (tab);
  77. tab.View.Dispose ();
  78. }
  79. private void Open ()
  80. {
  81. var open = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = true };
  82. Application.Run (open);
  83. if (!open.Canceled) {
  84. foreach (var path in open.FilePaths) {
  85. if (string.IsNullOrEmpty (path) || !File.Exists (path)) {
  86. return;
  87. }
  88. Open (File.ReadAllText (path), new FileInfo (path), Path.GetFileName (path));
  89. }
  90. }
  91. }
  92. /// <summary>
  93. /// Creates a new tab with initial text
  94. /// </summary>
  95. /// <param name="initialText"></param>
  96. /// <param name="fileInfo">File that was read or null if a new blank document</param>
  97. private void Open (string initialText, FileInfo fileInfo, string tabName)
  98. {
  99. var textView = new TextView () {
  100. X = 0,
  101. Y = 0,
  102. Width = Dim.Fill (),
  103. Height = Dim.Fill (),
  104. Text = initialText
  105. };
  106. var tab = new OpenedFile (tabName, fileInfo, textView);
  107. tabView.AddTab (tab, true);
  108. // when user makes changes rename tab to indicate unsaved
  109. textView.KeyUp += (k) => {
  110. // if current text doesn't match saved text
  111. var areDiff = tab.UnsavedChanges;
  112. if (areDiff) {
  113. if (!tab.Text.ToString ().EndsWith ('*')) {
  114. tab.Text = tab.Text.ToString () + '*';
  115. tabView.SetNeedsDisplay ();
  116. }
  117. } else {
  118. if (tab.Text.ToString ().EndsWith ('*')) {
  119. tab.Text = tab.Text.ToString ().TrimEnd ('*');
  120. tabView.SetNeedsDisplay ();
  121. }
  122. }
  123. };
  124. }
  125. public void Save ()
  126. {
  127. var tab = tabView.SelectedTab as OpenedFile;
  128. if (tab == null) {
  129. return;
  130. }
  131. if (tab.File == null) {
  132. SaveAs ();
  133. }
  134. tab.Save ();
  135. tabView.SetNeedsDisplay ();
  136. }
  137. public bool SaveAs ()
  138. {
  139. var tab = tabView.SelectedTab as OpenedFile;
  140. if (tab == null) {
  141. return false;
  142. }
  143. var fd = new SaveDialog ();
  144. Application.Run (fd);
  145. if (string.IsNullOrWhiteSpace (fd.FilePath?.ToString ())) {
  146. return false;
  147. }
  148. tab.File = new FileInfo (fd.FilePath.ToString ());
  149. tab.Text = fd.FileName.ToString ();
  150. tab.Save ();
  151. return true;
  152. }
  153. private class OpenedFile : TabView.Tab {
  154. public FileInfo File { get; set; }
  155. /// <summary>
  156. /// The text of the tab the last time it was saved
  157. /// </summary>
  158. /// <value></value>
  159. public string SavedText { get; set; }
  160. public bool UnsavedChanges => !string.Equals (SavedText, View.Text.ToString ());
  161. public OpenedFile (string name, FileInfo file, TextView control) : base (name, control)
  162. {
  163. File = file;
  164. SavedText = control.Text.ToString ();
  165. }
  166. internal void Save ()
  167. {
  168. var newText = View.Text.ToString ();
  169. System.IO.File.WriteAllText (File.FullName, newText);
  170. SavedText = newText;
  171. Text = Text.ToString ().TrimEnd ('*');
  172. }
  173. }
  174. private void Quit ()
  175. {
  176. Application.RequestStop ();
  177. }
  178. }
  179. }