Notepad.cs 5.2 KB

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