Buttons.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Text;
  5. using JetBrains.Annotations;
  6. using Terminal.Gui;
  7. namespace UICatalog.Scenarios;
  8. [ScenarioMetadata ("Buttons", "Demonstrates all sorts of Buttons.")]
  9. [ScenarioCategory ("Controls")]
  10. [ScenarioCategory ("Layout")]
  11. public class Buttons : Scenario
  12. {
  13. public override void Main ()
  14. {
  15. Application.Init ();
  16. Window main = new ()
  17. {
  18. Title = GetQuitKeyAndName ()
  19. };
  20. // Add a label & text field so we can demo IsDefault
  21. var editLabel = new Label { X = 0, Y = 0, Text = "TextField (to demo IsDefault):" };
  22. main.Add (editLabel);
  23. // Add a TextField using Absolute layout.
  24. var edit = new TextField { X = 31, Width = 15, HotKey = Key.Y.WithAlt };
  25. main.Add (edit);
  26. // This is the default button (IsDefault = true); if user presses ENTER in the TextField
  27. // the scenario will quit
  28. var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (), IsDefault = true, Text = "_Quit" };
  29. main.Accept += (s, e) => Application.RequestStop ();
  30. main.Add (defaultButton);
  31. var swapButton = new Button
  32. {
  33. X = 50,
  34. Width = 45,
  35. Height = 3,
  36. Text = "S_wap Default (Size = 45, 3)",
  37. ColorScheme = Colors.ColorSchemes ["Error"]
  38. };
  39. swapButton.Accept += (s, e) =>
  40. {
  41. e.Handled = !swapButton.IsDefault;
  42. defaultButton.IsDefault = !defaultButton.IsDefault;
  43. swapButton.IsDefault = !swapButton.IsDefault;
  44. };
  45. main.Add (swapButton);
  46. static void DoMessage (Button button, string txt)
  47. {
  48. button.Accept += (s, e) =>
  49. {
  50. string btnText = button.Text;
  51. MessageBox.Query ("Message", $"Did you click {txt}?", "Yes", "No");
  52. e.Handled = true;
  53. };
  54. }
  55. var colorButtonsLabel = new Label { X = 0, Y = Pos.Bottom (swapButton) + 1, Text = "Color Buttons: " };
  56. main.Add (colorButtonsLabel);
  57. View prev = colorButtonsLabel;
  58. foreach (KeyValuePair<string, ColorScheme> colorScheme in Colors.ColorSchemes)
  59. {
  60. var colorButton = new Button
  61. {
  62. X = Pos.Right (prev),
  63. Y = Pos.Y (colorButtonsLabel),
  64. Text = $"_{colorScheme.Key}",
  65. ColorScheme = colorScheme.Value,
  66. };
  67. DoMessage (colorButton, colorButton.Text);
  68. main.Add (colorButton);
  69. prev = colorButton;
  70. }
  71. Button button;
  72. main.Add (
  73. button = new ()
  74. {
  75. X = 2,
  76. Y = Pos.Bottom (colorButtonsLabel) + 1,
  77. Text =
  78. "A super l_öng Button that will probably expose a bug in clipping or wrapping of text. Will it?"
  79. }
  80. );
  81. DoMessage (button, button.Text);
  82. // Note the 'N' in 'Newline' will be the hotkey
  83. main.Add (
  84. button = new () { X = 2, Y = Pos.Bottom (button) + 1, Height = 2, Text = "a Newline\nin the button" }
  85. );
  86. button.Accept += (s, e) =>
  87. {
  88. MessageBox.Query ("Message", "Question?", "Yes", "No");
  89. e.Handled = true;
  90. };
  91. var textChanger = new Button { X = 2, Y = Pos.Bottom (button) + 1, Text = "Te_xt Changer" };
  92. main.Add (textChanger);
  93. textChanger.Accept += (s, e) =>
  94. {
  95. textChanger.Text += "!";
  96. e.Handled = true;
  97. };
  98. main.Add (
  99. button = new ()
  100. {
  101. X = Pos.Right (textChanger) + 2,
  102. Y = Pos.Y (textChanger),
  103. Text = "Lets see if this will move as \"Text Changer\" grows"
  104. }
  105. );
  106. var removeButton = new Button
  107. {
  108. X = 2, Y = Pos.Bottom (button) + 1,
  109. ColorScheme = Colors.ColorSchemes ["Error"], Text = "Remove this button"
  110. };
  111. main.Add (removeButton);
  112. // This in interesting test case because `moveBtn` and below are laid out relative to this one!
  113. removeButton.Accept += (s, e) =>
  114. {
  115. removeButton.Visible = false;
  116. };
  117. var computedFrame = new FrameView
  118. {
  119. X = 0,
  120. Y = Pos.Bottom (removeButton) + 1,
  121. Width = Dim.Percent (50),
  122. Height = 6,
  123. Title = "Computed Layout"
  124. };
  125. main.Add (computedFrame);
  126. // Demonstrates how changing the View.Frame property can move Views
  127. var moveBtn = new Button
  128. {
  129. X = 0,
  130. Y = Pos.Center () - 1,
  131. Width = 30,
  132. ColorScheme = Colors.ColorSchemes ["Error"],
  133. Text = "Move This \u263b Button v_ia Pos"
  134. };
  135. moveBtn.Accept += (s, e) =>
  136. {
  137. moveBtn.X = moveBtn.Frame.X + 5;
  138. };
  139. computedFrame.Add (moveBtn);
  140. // Demonstrates how changing the View.Frame property can SIZE Views (#583)
  141. var sizeBtn = new Button
  142. {
  143. Y = Pos.Center () + 1,
  144. X = 0,
  145. Width = 30,
  146. Text = "Grow This \u263a Button _via Pos",
  147. ColorScheme = Colors.ColorSchemes ["Error"],
  148. };
  149. sizeBtn.Accept += (s, e) =>
  150. {
  151. sizeBtn.Width = sizeBtn.Frame.Width + 5;
  152. };
  153. computedFrame.Add (sizeBtn);
  154. var absoluteFrame = new FrameView
  155. {
  156. X = Pos.Right (computedFrame),
  157. Y = Pos.Bottom (removeButton) + 1,
  158. Width = Dim.Fill (),
  159. Height = 6,
  160. Title = "Absolute Layout"
  161. };
  162. main.Add (absoluteFrame);
  163. // Demonstrates how changing the View.Frame property can move Views
  164. var moveBtnA = new Button { ColorScheme = Colors.ColorSchemes ["Error"], Text = "Move This Button via Frame" };
  165. moveBtnA.Accept += (s, e) =>
  166. {
  167. moveBtnA.Frame = new (
  168. moveBtnA.Frame.X + 5,
  169. moveBtnA.Frame.Y,
  170. moveBtnA.Frame.Width,
  171. moveBtnA.Frame.Height
  172. );
  173. };
  174. absoluteFrame.Add (moveBtnA);
  175. // Demonstrates how changing the View.Frame property can SIZE Views (#583)
  176. var sizeBtnA = new Button
  177. {
  178. Y = 2, ColorScheme = Colors.ColorSchemes ["Error"], Text = " ~  s  gui.cs   master ↑_10 = Сохранить"
  179. };
  180. sizeBtnA.Accept += (s, e) =>
  181. {
  182. sizeBtnA.Frame = new (
  183. sizeBtnA.Frame.X,
  184. sizeBtnA.Frame.Y,
  185. sizeBtnA.Frame.Width + 5,
  186. sizeBtnA.Frame.Height
  187. );
  188. };
  189. absoluteFrame.Add (sizeBtnA);
  190. var label = new Label
  191. {
  192. X = 2, Y = Pos.Bottom (computedFrame) + 1,
  193. Text = "Text Alignment (changes the four buttons above): "
  194. };
  195. main.Add (label);
  196. var radioGroup = new RadioGroup
  197. {
  198. X = 4,
  199. Y = Pos.Bottom (label) + 1,
  200. SelectedItem = 2,
  201. RadioLabels = new [] { "Start", "End", "Center", "Fill" }
  202. };
  203. main.Add (radioGroup);
  204. // Demo changing hotkey
  205. string MoveHotkey (string txt)
  206. {
  207. // Remove the '_'
  208. List<Rune> runes = txt.ToRuneList ();
  209. int i = runes.IndexOf ((Rune)'_');
  210. var start = "";
  211. if (i > -1)
  212. {
  213. start = StringExtensions.ToString (runes.GetRange (0, i));
  214. }
  215. txt = start + StringExtensions.ToString (runes.GetRange (i + 1, runes.Count - (i + 1)));
  216. runes = txt.ToRuneList ();
  217. // Move over one or go to start
  218. i++;
  219. if (i >= runes.Count)
  220. {
  221. i = 0;
  222. }
  223. // Slip in the '_'
  224. start = StringExtensions.ToString (runes.GetRange (0, i));
  225. return start + '_' + StringExtensions.ToString (runes.GetRange (i, runes.Count - i));
  226. }
  227. var mhkb = "Click to Change th_is Button's Hotkey";
  228. var moveHotKeyBtn = new Button
  229. {
  230. X = 2,
  231. Y = Pos.Bottom (radioGroup) + 1,
  232. Width = Dim.Width (computedFrame) - 2,
  233. ColorScheme = Colors.ColorSchemes ["TopLevel"],
  234. Text = mhkb
  235. };
  236. moveHotKeyBtn.Accept += (s, e) => { moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text); };
  237. main.Add (moveHotKeyBtn);
  238. var muhkb = " ~  s  gui.cs   master ↑10 = Сохранить";
  239. var moveUnicodeHotKeyBtn = new Button
  240. {
  241. X = Pos.Left (absoluteFrame) + 1,
  242. Y = Pos.Bottom (radioGroup) + 1,
  243. Width = Dim.Width (absoluteFrame) - 2,
  244. ColorScheme = Colors.ColorSchemes ["TopLevel"],
  245. Text = muhkb
  246. };
  247. moveUnicodeHotKeyBtn.Accept += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); };
  248. main.Add (moveUnicodeHotKeyBtn);
  249. radioGroup.SelectedItemChanged += (s, args) =>
  250. {
  251. switch (args.SelectedItem)
  252. {
  253. case 0:
  254. moveBtn.TextAlignment = Alignment.Start;
  255. sizeBtn.TextAlignment = Alignment.Start;
  256. moveBtnA.TextAlignment = Alignment.Start;
  257. sizeBtnA.TextAlignment = Alignment.Start;
  258. moveHotKeyBtn.TextAlignment = Alignment.Start;
  259. moveUnicodeHotKeyBtn.TextAlignment = Alignment.Start;
  260. break;
  261. case 1:
  262. moveBtn.TextAlignment = Alignment.End;
  263. sizeBtn.TextAlignment = Alignment.End;
  264. moveBtnA.TextAlignment = Alignment.End;
  265. sizeBtnA.TextAlignment = Alignment.End;
  266. moveHotKeyBtn.TextAlignment = Alignment.End;
  267. moveUnicodeHotKeyBtn.TextAlignment = Alignment.End;
  268. break;
  269. case 2:
  270. moveBtn.TextAlignment = Alignment.Center;
  271. sizeBtn.TextAlignment = Alignment.Center;
  272. moveBtnA.TextAlignment = Alignment.Center;
  273. sizeBtnA.TextAlignment = Alignment.Center;
  274. moveHotKeyBtn.TextAlignment = Alignment.Center;
  275. moveUnicodeHotKeyBtn.TextAlignment = Alignment.Center;
  276. break;
  277. case 3:
  278. moveBtn.TextAlignment = Alignment.Fill;
  279. sizeBtn.TextAlignment = Alignment.Fill;
  280. moveBtnA.TextAlignment = Alignment.Fill;
  281. sizeBtnA.TextAlignment = Alignment.Fill;
  282. moveHotKeyBtn.TextAlignment = Alignment.Fill;
  283. moveUnicodeHotKeyBtn.TextAlignment = Alignment.Fill;
  284. break;
  285. }
  286. };
  287. label = new ()
  288. {
  289. X = 0,
  290. Y = Pos.Bottom (moveUnicodeHotKeyBtn) + 1,
  291. Title = "_Numeric Up/Down (press-and-hold):",
  292. };
  293. var numericUpDown = new NumericUpDown<int>
  294. {
  295. Value = 69,
  296. X = Pos.Right (label) + 1,
  297. Y = Pos.Top (label),
  298. };
  299. numericUpDown.ValueChanged += NumericUpDown_ValueChanged;
  300. void NumericUpDown_ValueChanged (object sender, EventArgs<int> e) { }
  301. main.Add (label, numericUpDown);
  302. label = new ()
  303. {
  304. X = 0,
  305. Y = Pos.Bottom (numericUpDown) + 1,
  306. Title = "_No Repeat:"
  307. };
  308. var noRepeatAcceptCount = 0;
  309. var noRepeatButton = new Button
  310. {
  311. X = Pos.Right (label) + 1,
  312. Y = Pos.Top (label),
  313. Title = $"Accept Cou_nt: {noRepeatAcceptCount}",
  314. WantContinuousButtonPressed = false
  315. };
  316. noRepeatButton.Accept += (s, e) => { noRepeatButton.Title = $"Accept Cou_nt: {++noRepeatAcceptCount}"; };
  317. main.Add (label, noRepeatButton);
  318. label = new ()
  319. {
  320. X = 0,
  321. Y = Pos.Bottom (label) + 1,
  322. Title = "_Repeat (press-and-hold):"
  323. };
  324. var acceptCount = 0;
  325. var repeatButton = new Button
  326. {
  327. X = Pos.Right (label) + 1,
  328. Y = Pos.Top (label),
  329. Title = $"Accept Co_unt: {acceptCount}",
  330. WantContinuousButtonPressed = true
  331. };
  332. repeatButton.Accept += (s, e) => { repeatButton.Title = $"Accept Co_unt: {++acceptCount}"; };
  333. var enableCB = new CheckBox
  334. {
  335. X = Pos.Right (repeatButton) + 1,
  336. Y = Pos.Top (repeatButton),
  337. Title = "Enabled",
  338. CheckedState = CheckState.Checked
  339. };
  340. enableCB.CheckedStateChanging += (s, e) => { repeatButton.Enabled = !repeatButton.Enabled; };
  341. main.Add (label, repeatButton, enableCB);
  342. var decNumericUpDown = new NumericUpDown<int>
  343. {
  344. Value = 911,
  345. Increment = 1,
  346. Format = "{0:X}",
  347. X = 0,
  348. Y = Pos.Bottom (enableCB) + 1,
  349. };
  350. main.Add (decNumericUpDown);
  351. main.Ready += (s, e) =>
  352. {
  353. radioGroup.Refresh ();
  354. };
  355. Application.Run (main);
  356. main.Dispose ();
  357. Application.Shutdown ();
  358. }
  359. }