Text.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using Terminal.Gui;
  7. using Terminal.Gui.TextValidateProviders;
  8. namespace UICatalog.Scenarios;
  9. [ScenarioMetadata ("Text Input Controls", "Tests all text input controls")]
  10. [ScenarioCategory ("Controls")]
  11. [ScenarioCategory ("Mouse and Keyboard")]
  12. [ScenarioCategory ("Text and Formatting")]
  13. public class Text : Scenario
  14. {
  15. private Label _labelMirroringTimeField;
  16. private TimeField _timeField;
  17. public override void Main ()
  18. {
  19. Application.Init ();
  20. var win = new Window { Title = GetQuitKeyAndName () };
  21. // TextField is a simple, single-line text input control
  22. var label = new Label { Text = "_TextField:" };
  23. win.Add (label);
  24. var textField = new TextField
  25. {
  26. X = Pos.Right (label) + 1,
  27. Y = 0,
  28. Width = Dim.Percent (50) - 1,
  29. Text = "TextField with test text. Unicode shouldn't 𝔹Aℝ𝔽!"
  30. };
  31. var singleWordGenerator = new SingleWordSuggestionGenerator ();
  32. textField.Autocomplete.SuggestionGenerator = singleWordGenerator;
  33. textField.TextChanging += TextField_TextChanging;
  34. void TextField_TextChanging (object sender, CancelEventArgs<string> e)
  35. {
  36. singleWordGenerator.AllSuggestions = Regex.Matches (e.NewValue, "\\w+")
  37. .Select (s => s.Value)
  38. .Distinct ()
  39. .ToList ();
  40. }
  41. win.Add (textField);
  42. var labelMirroringTextField = new Label
  43. {
  44. X = Pos.Right (textField) + 1,
  45. Y = Pos.Top (textField),
  46. Width = Dim.Fill (1) - 1,
  47. Height = 1,
  48. Text = textField.Text
  49. };
  50. win.Add (labelMirroringTextField);
  51. textField.TextChanged += (s, prev) => { labelMirroringTextField.Text = textField.Text; };
  52. // TextView is a rich (as in functionality, not formatting) text editing control
  53. label = new() { Text = "T_extView:", Y = Pos.Bottom (label) + 1 };
  54. win.Add (label);
  55. var textView = new TextView
  56. {
  57. X = Pos.Right (label) + 1,
  58. Y = Pos.Top (label),
  59. Width = Dim.Percent (50) - 1,
  60. Height = Dim.Percent (20)
  61. };
  62. textView.Text = "TextView with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!";
  63. textView.DrawContent += TextView_DrawContent;
  64. // This shows how to enable autocomplete in TextView.
  65. void TextView_DrawContent (object sender, DrawEventArgs e)
  66. {
  67. singleWordGenerator.AllSuggestions = Regex.Matches (textView.Text, "\\w+")
  68. .Select (s => s.Value)
  69. .Distinct ()
  70. .ToList ();
  71. }
  72. win.Add (textView);
  73. var labelMirroringTextView = new Label
  74. {
  75. X = Pos.Right (textView) + 1,
  76. Y = Pos.Top (textView),
  77. Width = Dim.Fill (1) - 1,
  78. Height = Dim.Height (textView) - 1
  79. };
  80. win.Add (labelMirroringTextView);
  81. // Use ContentChanged to detect if the user has typed something in a TextView.
  82. // The TextChanged property is only fired if the TextView.Text property is
  83. // explicitly set
  84. textView.ContentsChanged += (s, a) =>
  85. {
  86. labelMirroringTextView.Enabled = !labelMirroringTextView.Enabled;
  87. labelMirroringTextView.Text = textView.Text;
  88. };
  89. // By default TextView is a multi-line control. It can be forced to
  90. // single-line mode.
  91. var chxMultiline = new CheckBox
  92. {
  93. X = Pos.Left (textView), Y = Pos.Bottom (textView), State = textView.Multiline ? CheckState.Checked : CheckState.UnChecked, Text = "_Multiline"
  94. };
  95. win.Add (chxMultiline);
  96. var chxWordWrap = new CheckBox
  97. {
  98. X = Pos.Right (chxMultiline) + 2,
  99. Y = Pos.Top (chxMultiline),
  100. State = textView.WordWrap ? CheckState.Checked : CheckState.UnChecked,
  101. Text = "_Word Wrap"
  102. };
  103. chxWordWrap.Toggle += (s, e) => textView.WordWrap = e.NewValue == CheckState.Checked;
  104. win.Add (chxWordWrap);
  105. // TextView captures Tabs (so users can enter /t into text) by default;
  106. // This means using Tab to navigate doesn't work by default. This shows
  107. // how to turn tab capture off.
  108. var chxCaptureTabs = new CheckBox
  109. {
  110. X = Pos.Right (chxWordWrap) + 2,
  111. Y = Pos.Top (chxWordWrap),
  112. State = textView.AllowsTab ? CheckState.Checked : CheckState.UnChecked,
  113. Text = "_Capture Tabs"
  114. };
  115. chxMultiline.Toggle += (s, e) =>
  116. {
  117. textView.Multiline = e.NewValue == CheckState.Checked;
  118. if (!textView.Multiline && chxWordWrap.State == CheckState.Checked)
  119. {
  120. chxWordWrap.State = CheckState.UnChecked;
  121. }
  122. if (!textView.Multiline && chxCaptureTabs.State == CheckState.Checked)
  123. {
  124. chxCaptureTabs.State = CheckState.UnChecked;
  125. }
  126. };
  127. Key keyTab = textView.KeyBindings.GetKeyFromCommands (Command.Tab);
  128. Key keyBackTab = textView.KeyBindings.GetKeyFromCommands (Command.BackTab);
  129. chxCaptureTabs.Toggle += (s, e) =>
  130. {
  131. if (e.NewValue == CheckState.Checked)
  132. {
  133. textView.KeyBindings.Add (keyTab, Command.Tab);
  134. textView.KeyBindings.Add (keyBackTab, Command.BackTab);
  135. }
  136. else
  137. {
  138. textView.KeyBindings.Remove (keyTab);
  139. textView.KeyBindings.Remove (keyBackTab);
  140. }
  141. textView.AllowsTab = e.NewValue == CheckState.Checked;
  142. };
  143. win.Add (chxCaptureTabs);
  144. // Hex editor
  145. label = new() { Text = "_HexView:", Y = Pos.Bottom (chxMultiline) + 1 };
  146. win.Add (label);
  147. var hexEditor =
  148. new HexView (
  149. new MemoryStream (Encoding.UTF8.GetBytes ("HexEditor Unicode that shouldn't 𝔹Aℝ𝔽!"))
  150. )
  151. {
  152. X = Pos.Right (label) + 1, Y = Pos.Bottom (chxMultiline) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30)
  153. };
  154. win.Add (hexEditor);
  155. var labelMirroringHexEditor = new Label
  156. {
  157. X = Pos.Right (hexEditor) + 1,
  158. Y = Pos.Top (hexEditor),
  159. Width = Dim.Fill (1) - 1,
  160. Height = Dim.Height (hexEditor) - 1
  161. };
  162. byte [] array = ((MemoryStream)hexEditor.Source).ToArray ();
  163. labelMirroringHexEditor.Text = Encoding.UTF8.GetString (array, 0, array.Length);
  164. hexEditor.Edited += (s, kv) =>
  165. {
  166. hexEditor.ApplyEdits ();
  167. byte [] array = ((MemoryStream)hexEditor.Source).ToArray ();
  168. labelMirroringHexEditor.Text = Encoding.UTF8.GetString (array, 0, array.Length);
  169. };
  170. win.Add (labelMirroringHexEditor);
  171. // DateField
  172. label = new() { Text = "_DateField:", Y = Pos.Bottom (hexEditor) + 1 };
  173. win.Add (label);
  174. var dateField = new DateField (DateTime.Now) { X = Pos.Right (label) + 1, Y = Pos.Bottom (hexEditor) + 1, Width = 20 };
  175. win.Add (dateField);
  176. var labelMirroringDateField = new Label
  177. {
  178. X = Pos.Right (dateField) + 1,
  179. Y = Pos.Top (dateField),
  180. Width = Dim.Width (dateField),
  181. Height = Dim.Height (dateField),
  182. Text = dateField.Text
  183. };
  184. win.Add (labelMirroringDateField);
  185. dateField.TextChanged += (s, prev) => { labelMirroringDateField.Text = dateField.Text; };
  186. // TimeField
  187. label = new() { Text = "T_imeField:", Y = Pos.Top (dateField), X = Pos.Right (labelMirroringDateField) + 5 };
  188. win.Add (label);
  189. _timeField = new()
  190. {
  191. X = Pos.Right (label) + 1,
  192. Y = Pos.Top (dateField),
  193. Width = 20,
  194. IsShortFormat = false,
  195. Time = DateTime.Now.TimeOfDay
  196. };
  197. win.Add (_timeField);
  198. _labelMirroringTimeField = new()
  199. {
  200. X = Pos.Right (_timeField) + 1,
  201. Y = Pos.Top (_timeField),
  202. Width = Dim.Width (_timeField),
  203. Height = Dim.Height (_timeField),
  204. Text = _timeField.Text
  205. };
  206. win.Add (_labelMirroringTimeField);
  207. _timeField.TimeChanged += TimeChanged;
  208. // MaskedTextProvider - uses .NET MaskedTextProvider
  209. var netProviderLabel = new Label
  210. {
  211. X = Pos.Left (dateField),
  212. Y = Pos.Bottom (dateField) + 1,
  213. Text = "_NetMaskedTextProvider [ 999 000 LLL >LLL |AAA aaa ]:"
  214. };
  215. win.Add (netProviderLabel);
  216. var netProvider = new NetMaskedTextProvider ("999 000 LLL >LLL |AAA aaa");
  217. var netProviderField = new TextValidateField
  218. {
  219. X = Pos.Right (netProviderLabel) + 1, Y = Pos.Y (netProviderLabel), Provider = netProvider
  220. };
  221. win.Add (netProviderField);
  222. var labelMirroringNetProviderField = new Label
  223. {
  224. X = Pos.Right (netProviderField) + 1,
  225. Y = Pos.Top (netProviderField),
  226. Width = Dim.Width (netProviderField),
  227. Height = Dim.Height (netProviderField),
  228. Text = netProviderField.Text
  229. };
  230. win.Add (labelMirroringNetProviderField);
  231. netProviderField.Provider.TextChanged += (s, prev) => { labelMirroringNetProviderField.Text = netProviderField.Text; };
  232. // TextRegexProvider - Regex provider implemented by Terminal.Gui
  233. var regexProvider = new Label
  234. {
  235. X = Pos.Left (netProviderLabel),
  236. Y = Pos.Bottom (netProviderLabel) + 1,
  237. Text = "Text_RegexProvider [ ^([0-9]?[0-9]?[0-9]|1000)$ ]:"
  238. };
  239. win.Add (regexProvider);
  240. var provider2 = new TextRegexProvider ("^([0-9]?[0-9]?[0-9]|1000)$") { ValidateOnInput = false };
  241. var regexProviderField = new TextValidateField
  242. {
  243. X = Pos.Right (regexProvider) + 1,
  244. Y = Pos.Y (regexProvider),
  245. Width = 30,
  246. TextAlignment = Alignment.Center,
  247. Provider = provider2
  248. };
  249. win.Add (regexProviderField);
  250. var labelMirroringRegexProviderField = new Label
  251. {
  252. X = Pos.Right (regexProviderField) + 1,
  253. Y = Pos.Top (regexProviderField),
  254. Width = Dim.Width (regexProviderField),
  255. Height = Dim.Height (regexProviderField),
  256. Text = regexProviderField.Text
  257. };
  258. win.Add (labelMirroringRegexProviderField);
  259. regexProviderField.Provider.TextChanged += (s, prev) => { labelMirroringRegexProviderField.Text = regexProviderField.Text; };
  260. var labelAppendAutocomplete = new Label
  261. {
  262. Y = Pos.Y (regexProviderField) + 2, X = 1, Text = "_Append Autocomplete:"
  263. };
  264. var appendAutocompleteTextField = new TextField
  265. {
  266. X = Pos.Right (labelAppendAutocomplete) + 1, Y = Pos.Top (labelAppendAutocomplete), Width = Dim.Fill ()
  267. };
  268. appendAutocompleteTextField.Autocomplete = new AppendAutocomplete (appendAutocompleteTextField);
  269. appendAutocompleteTextField.Autocomplete.SuggestionGenerator = new SingleWordSuggestionGenerator
  270. {
  271. AllSuggestions = new()
  272. {
  273. "fish",
  274. "flipper",
  275. "fin",
  276. "fun",
  277. "the",
  278. "at",
  279. "there",
  280. "some",
  281. "my",
  282. "of",
  283. "be",
  284. "use",
  285. "her",
  286. "than",
  287. "and",
  288. "this",
  289. "an",
  290. "would",
  291. "first",
  292. "have",
  293. "each",
  294. "make",
  295. "water",
  296. "to",
  297. "from",
  298. "which",
  299. "like",
  300. "been",
  301. "in",
  302. "or",
  303. "she",
  304. "him",
  305. "call",
  306. "is",
  307. "one",
  308. "do",
  309. "into",
  310. "who",
  311. "you",
  312. "had",
  313. "how",
  314. "time",
  315. "oil",
  316. "that",
  317. "by",
  318. "their",
  319. "has",
  320. "its",
  321. "it",
  322. "word",
  323. "if",
  324. "look",
  325. "now",
  326. "he",
  327. "but",
  328. "will",
  329. "two",
  330. "find",
  331. "was",
  332. "not",
  333. "up",
  334. "more",
  335. "long",
  336. "for",
  337. "what",
  338. "other",
  339. "write",
  340. "down",
  341. "on",
  342. "all",
  343. "about",
  344. "go",
  345. "day",
  346. "are",
  347. "were",
  348. "out",
  349. "see",
  350. "did",
  351. "as",
  352. "we",
  353. "many",
  354. "number",
  355. "get",
  356. "with",
  357. "when",
  358. "then",
  359. "no",
  360. "come",
  361. "his",
  362. "your",
  363. "them",
  364. "way",
  365. "made",
  366. "they",
  367. "can",
  368. "these",
  369. "could",
  370. "may",
  371. "said",
  372. "so",
  373. "people",
  374. "part"
  375. }
  376. };
  377. win.Add (labelAppendAutocomplete);
  378. win.Add (appendAutocompleteTextField);
  379. Application.Run (win);
  380. win.Dispose ();
  381. Application.Shutdown ();
  382. }
  383. private void TimeChanged (object sender, DateTimeEventArgs<TimeSpan> e) { _labelMirroringTimeField.Text = _timeField.Text; }
  384. }