Buttons.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using System.Collections.Generic;
  2. using System.Text;
  3. using Terminal.Gui;
  4. namespace UICatalog.Scenarios;
  5. [ScenarioMetadata ("Buttons", "Demonstrates all sorts of Buttons.")]
  6. [ScenarioCategory ("Controls")]
  7. [ScenarioCategory ("Layout")]
  8. public class Buttons : Scenario
  9. {
  10. public override void Setup ()
  11. {
  12. // Add a label & text field so we can demo IsDefault
  13. var editLabel = new Label { X = 0, Y = 0, TabStop = true, Text = "TextField (to demo IsDefault):" };
  14. Win.Add (editLabel);
  15. // Add a TextField using Absolute layout.
  16. var edit = new TextField { X = 31, Width = 15, HotKey = Key.Y.WithAlt };
  17. Win.Add (edit);
  18. // This is the default button (IsDefault = true); if user presses ENTER in the TextField
  19. // the scenario will quit
  20. var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), IsDefault = true, Text = "_Quit" };
  21. defaultButton.Accept += (s, e) => Application.RequestStop ();
  22. Win.Add (defaultButton);
  23. var swapButton = new Button { X = 50, Text = "S_wap Default (Absolute Layout)" };
  24. swapButton.Accept += (s, e) =>
  25. {
  26. defaultButton.IsDefault = !defaultButton.IsDefault;
  27. swapButton.IsDefault = !swapButton.IsDefault;
  28. };
  29. Win.Add (swapButton);
  30. static void DoMessage (Button button, string txt)
  31. {
  32. button.Accept += (s, e) =>
  33. {
  34. string btnText = button.Text;
  35. MessageBox.Query ("Message", $"Did you click {txt}?", "Yes", "No");
  36. };
  37. }
  38. var colorButtonsLabel = new Label { X = 0, Y = Pos.Bottom (editLabel) + 1, Text = "Color Buttons:" };
  39. Win.Add (colorButtonsLabel);
  40. View prev = colorButtonsLabel;
  41. //With this method there is no need to call Application.TopReady += () => Application.TopRedraw (Top.Viewport);
  42. Pos x = Pos.Right (colorButtonsLabel) + 2;
  43. foreach (KeyValuePair<string, ColorScheme> colorScheme in Colors.ColorSchemes)
  44. {
  45. var colorButton = new Button
  46. {
  47. ColorScheme = colorScheme.Value,
  48. X = Pos.Right (prev) + 2,
  49. //X = x,
  50. Y = Pos.Y (colorButtonsLabel),
  51. Text = $"_{colorScheme.Key}"
  52. };
  53. DoMessage (colorButton, colorButton.Text);
  54. Win.Add (colorButton);
  55. prev = colorButton;
  56. // BUGBUG: AutoSize is true and the X doesn't change
  57. //x += colorButton.Frame.Width + 2;
  58. }
  59. Button button;
  60. Win.Add (
  61. button = new Button
  62. {
  63. X = 2,
  64. Y = Pos.Bottom (colorButtonsLabel) + 1,
  65. Text =
  66. "A super l_öng Button that will probably expose a bug in clipping or wrapping of text. Will it?"
  67. }
  68. );
  69. DoMessage (button, button.Text);
  70. // Note the 'N' in 'Newline' will be the hotkey
  71. Win.Add (
  72. button = new Button { X = 2, Y = Pos.Bottom (button) + 1, Text = "a Newline\nin the button" }
  73. );
  74. button.Accept += (s, e) => MessageBox.Query ("Message", "Question?", "Yes", "No");
  75. var textChanger = new Button { X = 2, Y = Pos.Bottom (button) + 1, Text = "Te_xt Changer" };
  76. Win.Add (textChanger);
  77. textChanger.Accept += (s, e) => textChanger.Text += "!";
  78. Win.Add (
  79. button = new Button
  80. {
  81. X = Pos.Right (textChanger) + 2,
  82. Y = Pos.Y (textChanger),
  83. Text = "Lets see if this will move as \"Text Changer\" grows"
  84. }
  85. );
  86. var removeButton = new Button
  87. {
  88. X = 2, Y = Pos.Bottom (button) + 1, ColorScheme = Colors.ColorSchemes ["Error"], Text = "Remove this button"
  89. };
  90. Win.Add (removeButton);
  91. // This in interesting test case because `moveBtn` and below are laid out relative to this one!
  92. removeButton.Accept += (s, e) =>
  93. {
  94. // Now this throw a InvalidOperationException on the TopologicalSort method as is expected.
  95. //Win.Remove (removeButton);
  96. removeButton.Visible = false;
  97. };
  98. var computedFrame = new FrameView
  99. {
  100. X = 0,
  101. Y = Pos.Bottom (removeButton) + 1,
  102. Width = Dim.Percent (50),
  103. Height = 5,
  104. Title = "Computed Layout"
  105. };
  106. Win.Add (computedFrame);
  107. // Demonstrates how changing the View.Frame property can move Views
  108. var moveBtn = new Button
  109. {
  110. X = 0,
  111. Y = Pos.Center () - 1,
  112. AutoSize = false,
  113. Width = 30,
  114. Height = 1,
  115. ColorScheme = Colors.ColorSchemes ["Error"],
  116. Text = "Move This \u263b Button v_ia Pos"
  117. };
  118. moveBtn.Accept += (s, e) =>
  119. {
  120. moveBtn.X = moveBtn.Frame.X + 5;
  121. // This is already fixed with the call to SetNeedDisplay() in the Pos Dim.
  122. //computedFrame.LayoutSubviews (); // BUGBUG: This call should not be needed. View.X is not causing relayout correctly
  123. };
  124. computedFrame.Add (moveBtn);
  125. // Demonstrates how changing the View.Frame property can SIZE Views (#583)
  126. var sizeBtn = new Button
  127. {
  128. X = 0,
  129. Y = Pos.Center () + 1,
  130. AutoSize = false,
  131. Width = 30,
  132. Height = 1,
  133. ColorScheme = Colors.ColorSchemes ["Error"],
  134. Text = "Size This \u263a Button _via Pos"
  135. };
  136. sizeBtn.Accept += (s, e) =>
  137. {
  138. sizeBtn.Width = sizeBtn.Frame.Width + 5;
  139. //computedFrame.LayoutSubviews (); // FIXED: This call should not be needed. View.X is not causing relayout correctly
  140. };
  141. computedFrame.Add (sizeBtn);
  142. var absoluteFrame = new FrameView
  143. {
  144. X = Pos.Right (computedFrame),
  145. Y = Pos.Bottom (removeButton) + 1,
  146. Width = Dim.Fill (),
  147. Height = 5,
  148. Title = "Absolute Layout"
  149. };
  150. Win.Add (absoluteFrame);
  151. // Demonstrates how changing the View.Frame property can move Views
  152. var moveBtnA = new Button { ColorScheme = Colors.ColorSchemes ["Error"], Text = "Move This Button via Frame" };
  153. moveBtnA.Accept += (s, e) =>
  154. {
  155. moveBtnA.Frame = new Rectangle (
  156. moveBtnA.Frame.X + 5,
  157. moveBtnA.Frame.Y,
  158. moveBtnA.Frame.Width,
  159. moveBtnA.Frame.Height
  160. );
  161. };
  162. absoluteFrame.Add (moveBtnA);
  163. // Demonstrates how changing the View.Frame property can SIZE Views (#583)
  164. var sizeBtnA = new Button
  165. {
  166. Y = 2, ColorScheme = Colors.ColorSchemes ["Error"], Text = " ~  s  gui.cs   master ↑_10 = Сохранить"
  167. };
  168. sizeBtnA.Accept += (s, e) =>
  169. {
  170. sizeBtnA.Frame = new Rectangle (
  171. sizeBtnA.Frame.X,
  172. sizeBtnA.Frame.Y,
  173. sizeBtnA.Frame.Width + 5,
  174. sizeBtnA.Frame.Height
  175. );
  176. };
  177. absoluteFrame.Add (sizeBtnA);
  178. var label = new Label
  179. {
  180. X = 2, Y = Pos.Bottom (computedFrame) + 1, Text = "Text Alignment (changes the four buttons above): "
  181. };
  182. Win.Add (label);
  183. var radioGroup = new RadioGroup
  184. {
  185. X = 4,
  186. Y = Pos.Bottom (label) + 1,
  187. SelectedItem = 2,
  188. RadioLabels = new [] { "Left", "Right", "Centered", "Justified" }
  189. };
  190. Win.Add (radioGroup);
  191. // Demo changing hotkey
  192. string MoveHotkey (string txt)
  193. {
  194. // Remove the '_'
  195. List<Rune> runes = txt.ToRuneList ();
  196. int i = runes.IndexOf ((Rune)'_');
  197. var start = "";
  198. if (i > -1)
  199. {
  200. start = StringExtensions.ToString (runes.GetRange (0, i));
  201. }
  202. txt = start + StringExtensions.ToString (runes.GetRange (i + 1, runes.Count - (i + 1)));
  203. runes = txt.ToRuneList ();
  204. // Move over one or go to start
  205. i++;
  206. if (i >= runes.Count)
  207. {
  208. i = 0;
  209. }
  210. // Slip in the '_'
  211. start = StringExtensions.ToString (runes.GetRange (0, i));
  212. return start + '_' + StringExtensions.ToString (runes.GetRange (i, runes.Count - i));
  213. }
  214. var mhkb = "Click to Change th_is Button's Hotkey";
  215. var moveHotKeyBtn = new Button
  216. {
  217. X = 2,
  218. Y = Pos.Bottom (radioGroup) + 1,
  219. AutoSize = false,
  220. Height = 1,
  221. Width = Dim.Width (computedFrame) - 2,
  222. ColorScheme = Colors.ColorSchemes ["TopLevel"],
  223. Text = mhkb
  224. };
  225. moveHotKeyBtn.Accept += (s, e) => { moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text); };
  226. Win.Add (moveHotKeyBtn);
  227. var muhkb = " ~  s  gui.cs   master ↑10 = Сохранить";
  228. var moveUnicodeHotKeyBtn = new Button
  229. {
  230. X = Pos.Left (absoluteFrame) + 1,
  231. Y = Pos.Bottom (radioGroup) + 1,
  232. AutoSize = false,
  233. Height = 1,
  234. Width = Dim.Width (absoluteFrame) - 2, // BUGBUG: Not always the width isn't calculated correctly.
  235. ColorScheme = Colors.ColorSchemes ["TopLevel"],
  236. Text = muhkb
  237. };
  238. moveUnicodeHotKeyBtn.Accept += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); };
  239. Win.Add (moveUnicodeHotKeyBtn);
  240. radioGroup.SelectedItemChanged += (s, args) =>
  241. {
  242. switch (args.SelectedItem)
  243. {
  244. case 0:
  245. moveBtn.TextAlignment = TextAlignment.Left;
  246. sizeBtn.TextAlignment = TextAlignment.Left;
  247. moveBtnA.TextAlignment = TextAlignment.Left;
  248. sizeBtnA.TextAlignment = TextAlignment.Left;
  249. moveHotKeyBtn.TextAlignment = TextAlignment.Left;
  250. moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Left;
  251. break;
  252. case 1:
  253. moveBtn.TextAlignment = TextAlignment.Right;
  254. sizeBtn.TextAlignment = TextAlignment.Right;
  255. moveBtnA.TextAlignment = TextAlignment.Right;
  256. sizeBtnA.TextAlignment = TextAlignment.Right;
  257. moveHotKeyBtn.TextAlignment = TextAlignment.Right;
  258. moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Right;
  259. break;
  260. case 2:
  261. moveBtn.TextAlignment = TextAlignment.Centered;
  262. sizeBtn.TextAlignment = TextAlignment.Centered;
  263. moveBtnA.TextAlignment = TextAlignment.Centered;
  264. sizeBtnA.TextAlignment = TextAlignment.Centered;
  265. moveHotKeyBtn.TextAlignment = TextAlignment.Centered;
  266. moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Centered;
  267. break;
  268. case 3:
  269. moveBtn.TextAlignment = TextAlignment.Justified;
  270. sizeBtn.TextAlignment = TextAlignment.Justified;
  271. moveBtnA.TextAlignment = TextAlignment.Justified;
  272. sizeBtnA.TextAlignment = TextAlignment.Justified;
  273. moveHotKeyBtn.TextAlignment = TextAlignment.Justified;
  274. moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Justified;
  275. break;
  276. }
  277. };
  278. Application.Top.Ready += (s, e) => radioGroup.Refresh ();
  279. }
  280. }