ASCIICustomButton.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Text;
  5. using Terminal.Gui;
  6. namespace UICatalog.Scenarios;
  7. [ScenarioMetadata ("ASCIICustomButtonTest", "ASCIICustomButton sample")]
  8. [ScenarioCategory ("Controls")]
  9. public class ASCIICustomButtonTest : Scenario
  10. {
  11. private static bool _smallerWindow;
  12. private MenuItem _miSmallerWindow;
  13. private ScrollViewTestWindow _scrollViewTestWindow;
  14. public override void Main ()
  15. {
  16. _smallerWindow = false;
  17. Application.Init ();
  18. Toplevel top = new ();
  19. var menu = new MenuBar
  20. {
  21. Menus =
  22. [
  23. new MenuBarItem (
  24. "_Window Size",
  25. new []
  26. {
  27. _miSmallerWindow =
  28. new MenuItem (
  29. "Smaller Window",
  30. "",
  31. ChangeWindowSize
  32. )
  33. {
  34. CheckType = MenuItemCheckStyle
  35. .Checked
  36. },
  37. null,
  38. new MenuItem (
  39. "Quit",
  40. "",
  41. () => Application.RequestStop (),
  42. null,
  43. null,
  44. (KeyCode)Application.QuitKey
  45. )
  46. }
  47. )
  48. ]
  49. };
  50. _scrollViewTestWindow = new ScrollViewTestWindow ();
  51. top.Add (menu, _scrollViewTestWindow);
  52. Application.Run (top);
  53. top.Dispose ();
  54. Application.Shutdown ();
  55. return;
  56. void ChangeWindowSize ()
  57. {
  58. _smallerWindow = (bool)(_miSmallerWindow.Checked = !_miSmallerWindow.Checked);
  59. top.Remove (_scrollViewTestWindow);
  60. _scrollViewTestWindow.Dispose ();
  61. _scrollViewTestWindow = new ScrollViewTestWindow ();
  62. top.Add (_scrollViewTestWindow);
  63. }
  64. }
  65. public class ASCIICustomButton : Button
  66. {
  67. private FrameView _border;
  68. private Label _fill;
  69. public string Description => $"Description of: {Id}";
  70. public void CustomInitialize ()
  71. {
  72. _border = new FrameView { Width = Width, Height = Height };
  73. var fillText = new StringBuilder ();
  74. for (var i = 0; i < Viewport.Height; i++)
  75. {
  76. if (i > 0)
  77. {
  78. fillText.AppendLine ("");
  79. }
  80. for (var j = 0; j < Viewport.Width; j++)
  81. {
  82. fillText.Append ("█");
  83. }
  84. }
  85. _fill = new Label { Visible = false, CanFocus = false, Text = fillText.ToString () };
  86. var title = new Label { X = Pos.Center (), Y = Pos.Center (), Text = Text };
  87. _border.MouseClick += This_MouseClick;
  88. _fill.MouseClick += This_MouseClick;
  89. title.MouseClick += This_MouseClick;
  90. Add (_border, _fill, title);
  91. }
  92. public override bool OnEnter (View view)
  93. {
  94. _border.Visible = false;
  95. _fill.Visible = true;
  96. PointerEnter.Invoke (this);
  97. view = this;
  98. return base.OnEnter (view);
  99. }
  100. public override bool OnLeave (View view)
  101. {
  102. _border.Visible = true;
  103. _fill.Visible = false;
  104. if (view == null)
  105. {
  106. view = this;
  107. }
  108. return base.OnLeave (view);
  109. }
  110. public event Action<ASCIICustomButton> PointerEnter;
  111. private void This_MouseClick (object sender, MouseEventEventArgs obj) { NewMouseEvent (obj.MouseEvent); }
  112. }
  113. public class ScrollViewTestWindow : Window
  114. {
  115. private const int BUTTON_HEIGHT = 3;
  116. private const int BUTTON_WIDTH = 25;
  117. private const int BUTTONS_ON_PAGE = 7;
  118. private readonly List<Button> _buttons;
  119. private readonly ScrollView _scrollView;
  120. private ASCIICustomButton _selected;
  121. public ScrollViewTestWindow ()
  122. {
  123. Title = $"{Application.QuitKey} to Quit - Scenario: ScrollViewTestWindow";
  124. Label titleLabel = null;
  125. if (_smallerWindow)
  126. {
  127. Width = 80;
  128. Height = 25;
  129. _scrollView = new ScrollView
  130. {
  131. X = 3,
  132. Y = 1,
  133. Width = 24,
  134. Height = BUTTONS_ON_PAGE * BUTTON_HEIGHT,
  135. ShowVerticalScrollIndicator = true,
  136. ShowHorizontalScrollIndicator = false
  137. };
  138. }
  139. else
  140. {
  141. Width = Dim.Fill ();
  142. Height = Dim.Fill ();
  143. titleLabel = new Label { X = 0, Y = 0, Text = "DOCUMENTS" };
  144. _scrollView = new ScrollView
  145. {
  146. X = 0,
  147. Y = 1,
  148. Width = 27,
  149. Height = BUTTONS_ON_PAGE * BUTTON_HEIGHT,
  150. ShowVerticalScrollIndicator = true,
  151. ShowHorizontalScrollIndicator = false
  152. };
  153. }
  154. _scrollView.KeyBindings.Clear ();
  155. _buttons = new List<Button> ();
  156. Button prevButton = null;
  157. var count = 20;
  158. for (var j = 0; j < count; j++)
  159. {
  160. Pos yPos = prevButton == null ? 0 : Pos.Bottom (prevButton);
  161. var button = new ASCIICustomButton
  162. {
  163. Id = j.ToString (),
  164. Text = $"section {j}",
  165. Y = yPos,
  166. Width = BUTTON_WIDTH,
  167. Height = BUTTON_HEIGHT
  168. };
  169. button.Initialized += Button_Initialized;
  170. button.Accept += Button_Clicked;
  171. button.PointerEnter += Button_PointerEnter;
  172. button.MouseClick += Button_MouseClick;
  173. button.KeyDown += Button_KeyPress;
  174. _scrollView.Add (button);
  175. _buttons.Add (button);
  176. prevButton = button;
  177. }
  178. var closeButton = new ASCIICustomButton
  179. {
  180. Id = "close",
  181. Text = "Close",
  182. Y = Pos.Bottom (prevButton),
  183. Width = BUTTON_WIDTH,
  184. Height = BUTTON_HEIGHT
  185. };
  186. closeButton.Initialized += Button_Initialized;
  187. closeButton.Accept += Button_Clicked;
  188. closeButton.PointerEnter += Button_PointerEnter;
  189. closeButton.MouseClick += Button_MouseClick;
  190. closeButton.KeyDown += Button_KeyPress;
  191. _scrollView.Add (closeButton);
  192. _buttons.Add (closeButton);
  193. int pages = _buttons.Count / BUTTONS_ON_PAGE;
  194. if (_buttons.Count % BUTTONS_ON_PAGE > 0)
  195. {
  196. pages++;
  197. }
  198. // BUGBUG: set_ContentSize is supposed to be `protected`.
  199. _scrollView.SetContentSize (new (25, pages * BUTTONS_ON_PAGE * BUTTON_HEIGHT));
  200. if (_smallerWindow)
  201. {
  202. Add (_scrollView);
  203. }
  204. else
  205. {
  206. Add (titleLabel, _scrollView);
  207. }
  208. }
  209. private void Button_Initialized (object sender, EventArgs e)
  210. {
  211. var button = sender as ASCIICustomButton;
  212. button?.CustomInitialize ();
  213. }
  214. private void Button_Clicked (object sender, EventArgs e)
  215. {
  216. MessageBox.Query ("Button clicked.", $"'{_selected.Text}' clicked!", "Ok");
  217. if (_selected.Text == "Close")
  218. {
  219. Application.RequestStop ();
  220. }
  221. }
  222. private void Button_KeyPress (object sender, Key obj)
  223. {
  224. switch (obj.KeyCode)
  225. {
  226. case KeyCode.End:
  227. _scrollView.ContentOffset = new Point (
  228. _scrollView.ContentOffset.X,
  229. -(_scrollView.GetContentSize ().Height
  230. - _scrollView.Frame.Height
  231. + (_scrollView.ShowHorizontalScrollIndicator ? 1 : 0))
  232. );
  233. obj.Handled = true;
  234. return;
  235. case KeyCode.Home:
  236. _scrollView.ContentOffset = new Point (_scrollView.ContentOffset.X, 0);
  237. obj.Handled = true;
  238. return;
  239. case KeyCode.PageDown:
  240. _scrollView.ContentOffset = new Point (
  241. _scrollView.ContentOffset.X,
  242. Math.Max (
  243. _scrollView.ContentOffset.Y
  244. - _scrollView.Frame.Height,
  245. -(_scrollView.GetContentSize ().Height
  246. - _scrollView.Frame.Height
  247. + (_scrollView.ShowHorizontalScrollIndicator
  248. ? 1
  249. : 0))
  250. )
  251. );
  252. obj.Handled = true;
  253. return;
  254. case KeyCode.PageUp:
  255. _scrollView.ContentOffset = new Point (
  256. _scrollView.ContentOffset.X,
  257. Math.Min (
  258. _scrollView.ContentOffset.Y
  259. + _scrollView.Frame.Height,
  260. 0
  261. )
  262. );
  263. obj.Handled = true;
  264. return;
  265. }
  266. }
  267. private void Button_MouseClick (object sender, MouseEventEventArgs obj)
  268. {
  269. if (obj.MouseEvent.Flags == MouseFlags.WheeledDown)
  270. {
  271. _scrollView.ContentOffset = new Point (
  272. _scrollView.ContentOffset.X,
  273. _scrollView.ContentOffset.Y - BUTTON_HEIGHT
  274. );
  275. obj.Handled = true;
  276. }
  277. else if (obj.MouseEvent.Flags == MouseFlags.WheeledUp)
  278. {
  279. _scrollView.ContentOffset = new Point (
  280. _scrollView.ContentOffset.X,
  281. Math.Min (_scrollView.ContentOffset.Y + BUTTON_HEIGHT, 0)
  282. );
  283. obj.Handled = true;
  284. }
  285. }
  286. private void Button_PointerEnter (ASCIICustomButton obj)
  287. {
  288. bool? moveDown;
  289. if (obj.Frame.Y > _selected?.Frame.Y)
  290. {
  291. moveDown = true;
  292. }
  293. else if (obj.Frame.Y < _selected?.Frame.Y)
  294. {
  295. moveDown = false;
  296. }
  297. else
  298. {
  299. moveDown = null;
  300. }
  301. int offSet = _selected != null
  302. ? obj.Frame.Y - _selected.Frame.Y + -_scrollView.ContentOffset.Y % BUTTON_HEIGHT
  303. : 0;
  304. _selected = obj;
  305. if (moveDown == true && _selected.Frame.Y + _scrollView.ContentOffset.Y + BUTTON_HEIGHT >= _scrollView.Frame.Height && offSet != BUTTON_HEIGHT)
  306. {
  307. _scrollView.ContentOffset = new Point (
  308. _scrollView.ContentOffset.X,
  309. Math.Min (
  310. _scrollView.ContentOffset.Y - BUTTON_HEIGHT,
  311. -(_selected.Frame.Y
  312. - _scrollView.Frame.Height
  313. + BUTTON_HEIGHT)
  314. )
  315. );
  316. }
  317. else if (moveDown == true && _selected.Frame.Y + _scrollView.ContentOffset.Y >= _scrollView.Frame.Height)
  318. {
  319. _scrollView.ContentOffset = new Point (
  320. _scrollView.ContentOffset.X,
  321. _scrollView.ContentOffset.Y - BUTTON_HEIGHT
  322. );
  323. }
  324. else if (moveDown == true && _selected.Frame.Y + _scrollView.ContentOffset.Y < 0)
  325. {
  326. _scrollView.ContentOffset = new Point (
  327. _scrollView.ContentOffset.X,
  328. -_selected.Frame.Y
  329. );
  330. }
  331. else if (moveDown == false && _selected.Frame.Y < -_scrollView.ContentOffset.Y)
  332. {
  333. _scrollView.ContentOffset = new Point (
  334. _scrollView.ContentOffset.X,
  335. Math.Max (
  336. _scrollView.ContentOffset.Y + BUTTON_HEIGHT,
  337. _selected.Frame.Y
  338. )
  339. );
  340. }
  341. else if (moveDown == false && _selected.Frame.Y + _scrollView.ContentOffset.Y > _scrollView.Frame.Height)
  342. {
  343. _scrollView.ContentOffset = new Point (
  344. _scrollView.ContentOffset.X,
  345. -(_selected.Frame.Y - _scrollView.Frame.Height + BUTTON_HEIGHT)
  346. );
  347. }
  348. }
  349. }
  350. }