Buttons.cs 17 KB

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