Text.cs 15 KB

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