ASCIICustomButton.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  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. return;
  55. void ChangeWindowSize ()
  56. {
  57. _smallerWindow = (bool)(_miSmallerWindow.Checked = !_miSmallerWindow.Checked);
  58. top.Remove (_scrollViewTestWindow);
  59. _scrollViewTestWindow.Dispose ();
  60. _scrollViewTestWindow = new ScrollViewTestWindow ();
  61. top.Add (_scrollViewTestWindow);
  62. }
  63. }
  64. public class ASCIICustomButton : Button
  65. {
  66. private FrameView _border;
  67. private Label _fill;
  68. public string Description => $"Description of: {Id}";
  69. public void CustomInitialize ()
  70. {
  71. _border = new FrameView { Width = Width, Height = Height };
  72. AutoSize = false;
  73. var fillText = new StringBuilder ();
  74. for (var i = 0; i < Bounds.Height; i++)
  75. {
  76. if (i > 0)
  77. {
  78. fillText.AppendLine ("");
  79. }
  80. for (var j = 0; j < Bounds.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 = "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. AutoSize = false,
  164. Id = j.ToString (),
  165. Text = $"section {j}",
  166. Y = yPos,
  167. Width = BUTTON_WIDTH,
  168. Height = BUTTON_HEIGHT
  169. };
  170. button.Initialized += Button_Initialized;
  171. button.Accept += Button_Clicked;
  172. button.PointerEnter += Button_PointerEnter;
  173. button.MouseClick += Button_MouseClick;
  174. button.KeyDown += Button_KeyPress;
  175. _scrollView.Add (button);
  176. _buttons.Add (button);
  177. prevButton = button;
  178. }
  179. var closeButton = new ASCIICustomButton
  180. {
  181. AutoSize = false,
  182. Id = "close",
  183. Text = "Close",
  184. Y = Pos.Bottom (prevButton),
  185. Width = BUTTON_WIDTH,
  186. Height = BUTTON_HEIGHT
  187. };
  188. closeButton.Initialized += Button_Initialized;
  189. closeButton.Accept += Button_Clicked;
  190. closeButton.PointerEnter += Button_PointerEnter;
  191. closeButton.MouseClick += Button_MouseClick;
  192. closeButton.KeyDown += Button_KeyPress;
  193. _scrollView.Add (closeButton);
  194. _buttons.Add (closeButton);
  195. int pages = _buttons.Count / BUTTONS_ON_PAGE;
  196. if (_buttons.Count % BUTTONS_ON_PAGE > 0)
  197. {
  198. pages++;
  199. }
  200. _scrollView.ContentSize = new (25, pages * BUTTONS_ON_PAGE * BUTTON_HEIGHT);
  201. if (_smallerWindow)
  202. {
  203. Add (_scrollView);
  204. }
  205. else
  206. {
  207. Add (titleLabel, _scrollView);
  208. }
  209. }
  210. private void Button_Initialized (object sender, EventArgs e)
  211. {
  212. var button = sender as ASCIICustomButton;
  213. button?.CustomInitialize ();
  214. }
  215. private void Button_Clicked (object sender, EventArgs e)
  216. {
  217. MessageBox.Query ("Button clicked.", $"'{_selected.Text}' clicked!", "Ok");
  218. if (_selected.Text == "Close")
  219. {
  220. Application.RequestStop ();
  221. }
  222. }
  223. private void Button_KeyPress (object sender, Key obj)
  224. {
  225. switch (obj.KeyCode)
  226. {
  227. case KeyCode.End:
  228. _scrollView.ContentOffset = new Point (
  229. _scrollView.ContentOffset.X,
  230. -(_scrollView.ContentSize.Height
  231. - _scrollView.Frame.Height
  232. + (_scrollView.ShowHorizontalScrollIndicator ? 1 : 0))
  233. );
  234. obj.Handled = true;
  235. return;
  236. case KeyCode.Home:
  237. _scrollView.ContentOffset = new Point (_scrollView.ContentOffset.X, 0);
  238. obj.Handled = true;
  239. return;
  240. case KeyCode.PageDown:
  241. _scrollView.ContentOffset = new Point (
  242. _scrollView.ContentOffset.X,
  243. Math.Max (
  244. _scrollView.ContentOffset.Y
  245. - _scrollView.Frame.Height,
  246. -(_scrollView.ContentSize.Height
  247. - _scrollView.Frame.Height
  248. + (_scrollView.ShowHorizontalScrollIndicator
  249. ? 1
  250. : 0))
  251. )
  252. );
  253. obj.Handled = true;
  254. return;
  255. case KeyCode.PageUp:
  256. _scrollView.ContentOffset = new Point (
  257. _scrollView.ContentOffset.X,
  258. Math.Min (
  259. _scrollView.ContentOffset.Y
  260. + _scrollView.Frame.Height,
  261. 0
  262. )
  263. );
  264. obj.Handled = true;
  265. return;
  266. }
  267. }
  268. private void Button_MouseClick (object sender, MouseEventEventArgs obj)
  269. {
  270. if (obj.MouseEvent.Flags == MouseFlags.WheeledDown)
  271. {
  272. _scrollView.ContentOffset = new Point (
  273. _scrollView.ContentOffset.X,
  274. _scrollView.ContentOffset.Y - BUTTON_HEIGHT
  275. );
  276. obj.Handled = true;
  277. }
  278. else if (obj.MouseEvent.Flags == MouseFlags.WheeledUp)
  279. {
  280. _scrollView.ContentOffset = new Point (
  281. _scrollView.ContentOffset.X,
  282. Math.Min (_scrollView.ContentOffset.Y + BUTTON_HEIGHT, 0)
  283. );
  284. obj.Handled = true;
  285. }
  286. }
  287. private void Button_PointerEnter (ASCIICustomButton obj)
  288. {
  289. bool? moveDown;
  290. if (obj.Frame.Y > _selected?.Frame.Y)
  291. {
  292. moveDown = true;
  293. }
  294. else if (obj.Frame.Y < _selected?.Frame.Y)
  295. {
  296. moveDown = false;
  297. }
  298. else
  299. {
  300. moveDown = null;
  301. }
  302. int offSet = _selected != null
  303. ? obj.Frame.Y - _selected.Frame.Y + -_scrollView.ContentOffset.Y % BUTTON_HEIGHT
  304. : 0;
  305. _selected = obj;
  306. if (moveDown == true && _selected.Frame.Y + _scrollView.ContentOffset.Y + BUTTON_HEIGHT >= _scrollView.Frame.Height && offSet != BUTTON_HEIGHT)
  307. {
  308. _scrollView.ContentOffset = new Point (
  309. _scrollView.ContentOffset.X,
  310. Math.Min (
  311. _scrollView.ContentOffset.Y - BUTTON_HEIGHT,
  312. -(_selected.Frame.Y
  313. - _scrollView.Frame.Height
  314. + BUTTON_HEIGHT)
  315. )
  316. );
  317. }
  318. else if (moveDown == true && _selected.Frame.Y + _scrollView.ContentOffset.Y >= _scrollView.Frame.Height)
  319. {
  320. _scrollView.ContentOffset = new Point (
  321. _scrollView.ContentOffset.X,
  322. _scrollView.ContentOffset.Y - BUTTON_HEIGHT
  323. );
  324. }
  325. else if (moveDown == true && _selected.Frame.Y + _scrollView.ContentOffset.Y < 0)
  326. {
  327. _scrollView.ContentOffset = new Point (
  328. _scrollView.ContentOffset.X,
  329. -_selected.Frame.Y
  330. );
  331. }
  332. else if (moveDown == false && _selected.Frame.Y < -_scrollView.ContentOffset.Y)
  333. {
  334. _scrollView.ContentOffset = new Point (
  335. _scrollView.ContentOffset.X,
  336. Math.Max (
  337. _scrollView.ContentOffset.Y + BUTTON_HEIGHT,
  338. _selected.Frame.Y
  339. )
  340. );
  341. }
  342. else if (moveDown == false && _selected.Frame.Y + _scrollView.ContentOffset.Y > _scrollView.Frame.Height)
  343. {
  344. _scrollView.ContentOffset = new Point (
  345. _scrollView.ContentOffset.X,
  346. -(_selected.Frame.Y - _scrollView.Frame.Height + BUTTON_HEIGHT)
  347. );
  348. }
  349. }
  350. }
  351. }