Adornments.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. using System;
  2. using System.Linq;
  3. using Terminal.Gui;
  4. namespace UICatalog.Scenarios;
  5. [ScenarioMetadata ("Adornments Demo", "Demonstrates Margin, Border, and Padding on Views.")]
  6. [ScenarioCategory ("Layout"), ScenarioCategory ("Borders")]
  7. public class Adornments : Scenario {
  8. public override void Init ()
  9. {
  10. Application.Init ();
  11. ConfigurationManager.Themes.Theme = Theme;
  12. ConfigurationManager.Apply ();
  13. Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
  14. var view = new Window { Title = "The Window" };
  15. var tf1 = new TextField ("TextField") { Width = 10 };
  16. var color = new ColorPicker () { Title = "BG", BoxHeight = 1, BoxWidth =1, X = Pos.AnchorEnd(11) };
  17. color.BorderStyle = LineStyle.RoundedDotted;
  18. color.ColorChanged += (s, e) => {
  19. color.SuperView.ColorScheme = new ColorScheme (color.SuperView.ColorScheme) {
  20. Normal = new Attribute(color.SuperView.ColorScheme.Normal.Foreground, e.Color)
  21. };
  22. };
  23. var button = new Button ("Press me!") {
  24. X = Pos.Center (),
  25. Y = Pos.Center ()
  26. };
  27. button.Clicked += (s, e) => MessageBox.Query (20, 7, "Hi", $"Am I a {view.GetType ().Name}?", "Yes", "No");
  28. var label = new TextView () {
  29. X = Pos.Center (),
  30. Y = Pos.Bottom (button),
  31. Title = "Title",
  32. Text = "I have a 3 row top border.\nMy border inherits from the SuperView.",
  33. Width = 40,
  34. Height = 6 // TODO: Use Dim.Auto
  35. };
  36. label.Border.Thickness = new Thickness (1, 3, 1, 1);
  37. var tf2 = new Button ("Button") {
  38. X = Pos.AnchorEnd (10),
  39. Y = Pos.AnchorEnd (1),
  40. Width = 10
  41. };
  42. var tv = new Label {
  43. Y = Pos.AnchorEnd (3),
  44. Width = 25,
  45. Height = Dim.Fill (),
  46. Text = "Label\nY=AnchorEnd(3),Height=Dim.Fill()"
  47. };
  48. view.Margin.Data = "Margin";
  49. view.Margin.Thickness = new Thickness (3);
  50. view.Border.Data = "Border";
  51. view.Border.Thickness = new Thickness (3);
  52. view.Padding.Data = "Padding";
  53. view.Padding.Thickness = new Thickness (3);
  54. view.Add (tf1, color, button, label, tf2, tv);
  55. var editor = new AdornmentsEditor {
  56. Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
  57. ColorScheme = Colors.ColorSchemes [TopLevelColorScheme],
  58. };
  59. view.X = 36;
  60. view.Y = 0;
  61. view.Width = Dim.Fill ();
  62. view.Height = Dim.Fill ();
  63. editor.Initialized += (s, e) => {
  64. editor.ViewToEdit = view;
  65. };
  66. //view.Margin.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Dialog"]);
  67. //view.Border.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Error"]);
  68. //view.Padding.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Menu"]);
  69. Application.Run (editor);
  70. Application.Shutdown ();
  71. }
  72. public override void Run () { }
  73. public class AdornmentEditor : View {
  74. readonly ColorPicker _backgroundColorPicker = new () {
  75. Title = "BG",
  76. BoxWidth = 1,
  77. BoxHeight = 1,
  78. BorderStyle = LineStyle.Single,
  79. SuperViewRendersLineCanvas = true
  80. };
  81. readonly ColorPicker _foregroundColorPicker = new () {
  82. Title = "FG",
  83. BoxWidth = 1,
  84. BoxHeight = 1,
  85. BorderStyle = LineStyle.Single,
  86. SuperViewRendersLineCanvas = true
  87. };
  88. TextField _bottomEdit;
  89. bool _isUpdating;
  90. TextField _leftEdit;
  91. TextField _rightEdit;
  92. Thickness _thickness;
  93. TextField _topEdit;
  94. public AdornmentEditor ()
  95. {
  96. Margin.Thickness = new Thickness (0);
  97. BorderStyle = LineStyle.Double;
  98. Initialized += AdornmentEditor_Initialized;
  99. }
  100. public Attribute Color {
  101. get => new (_foregroundColorPicker.SelectedColor, _backgroundColorPicker.SelectedColor);
  102. set {
  103. _foregroundColorPicker.SelectedColor = value.Foreground.ColorName;
  104. _backgroundColorPicker.SelectedColor = value.Background.ColorName;
  105. }
  106. }
  107. public Thickness Thickness {
  108. get => _thickness;
  109. set {
  110. if (_isUpdating) {
  111. return;
  112. }
  113. _thickness = value;
  114. ThicknessChanged?.Invoke (this, new ThicknessEventArgs { Thickness = Thickness });
  115. if (IsInitialized) {
  116. _isUpdating = true;
  117. if (_topEdit.Text != _thickness.Top.ToString ()) {
  118. _topEdit.Text = _thickness.Top.ToString ();
  119. }
  120. if (_leftEdit.Text != _thickness.Left.ToString ()) {
  121. _leftEdit.Text = _thickness.Left.ToString ();
  122. }
  123. if (_rightEdit.Text != _thickness.Right.ToString ()) {
  124. _rightEdit.Text = _thickness.Right.ToString ();
  125. }
  126. if (_bottomEdit.Text != _thickness.Bottom.ToString ()) {
  127. _bottomEdit.Text = _thickness.Bottom.ToString ();
  128. }
  129. _isUpdating = false;
  130. }
  131. }
  132. }
  133. public event EventHandler<ThicknessEventArgs> ThicknessChanged;
  134. public event EventHandler<Attribute> AttributeChanged;
  135. void AdornmentEditor_Initialized (object sender, EventArgs e)
  136. {
  137. var editWidth = 3;
  138. _topEdit = new TextField ("") {
  139. X = Pos.Center (),
  140. Y = 0,
  141. Width = editWidth
  142. };
  143. _topEdit.TextChanging += Edit_TextChanging;
  144. Add (_topEdit);
  145. _leftEdit = new TextField ("") {
  146. X = Pos.Left (_topEdit) - editWidth,
  147. Y = Pos.Bottom (_topEdit),
  148. Width = editWidth
  149. };
  150. _leftEdit.TextChanging += Edit_TextChanging;
  151. Add (_leftEdit);
  152. _rightEdit = new TextField ("") {
  153. X = Pos.Right (_topEdit),
  154. Y = Pos.Bottom (_topEdit),
  155. Width = editWidth
  156. };
  157. _rightEdit.TextChanging += Edit_TextChanging;
  158. Add (_rightEdit);
  159. _bottomEdit = new TextField ("") {
  160. X = Pos.Center (),
  161. Y = Pos.Bottom (_leftEdit),
  162. Width = editWidth
  163. };
  164. _bottomEdit.TextChanging += Edit_TextChanging;
  165. Add (_bottomEdit);
  166. var copyTop = new Button ("Cop_y Top") {
  167. X = Pos.Center () + 1,
  168. Y = Pos.Bottom (_bottomEdit)
  169. };
  170. copyTop.Clicked += (s, e) => {
  171. Thickness = new Thickness (Thickness.Top);
  172. if (string.IsNullOrEmpty (_topEdit.Text)) {
  173. _topEdit.Text = "0";
  174. }
  175. _bottomEdit.Text = _leftEdit.Text = _rightEdit.Text = _topEdit.Text;
  176. };
  177. Add (copyTop);
  178. // Foreground ColorPicker.
  179. _foregroundColorPicker.X = -1;
  180. _foregroundColorPicker.Y = Pos.Bottom (copyTop) + 1;
  181. _foregroundColorPicker.SelectedColor = Color.Foreground.ColorName;
  182. _foregroundColorPicker.ColorChanged += (o, a) =>
  183. AttributeChanged?.Invoke (this,
  184. new Attribute (_foregroundColorPicker.SelectedColor, _backgroundColorPicker.SelectedColor));
  185. Add (_foregroundColorPicker);
  186. // Background ColorPicker.
  187. _backgroundColorPicker.X = Pos.Right (_foregroundColorPicker) - 1;
  188. _backgroundColorPicker.Y = Pos.Top (_foregroundColorPicker);
  189. _backgroundColorPicker.SelectedColor = Color.Background.ColorName;
  190. _backgroundColorPicker.ColorChanged += (o, a) =>
  191. AttributeChanged?.Invoke (this,
  192. new Attribute (
  193. _foregroundColorPicker.SelectedColor,
  194. _backgroundColorPicker.SelectedColor));
  195. Add (_backgroundColorPicker);
  196. _topEdit.Text = $"{Thickness.Top}";
  197. _leftEdit.Text = $"{Thickness.Left}";
  198. _rightEdit.Text = $"{Thickness.Right}";
  199. _bottomEdit.Text = $"{Thickness.Bottom}";
  200. LayoutSubviews ();
  201. Height = GetAdornmentsThickness ().Vertical + 4 + 4;
  202. Width = GetAdornmentsThickness ().Horizontal + _foregroundColorPicker.Frame.Width * 2 - 3;
  203. }
  204. void Edit_TextChanging (object sender, TextChangingEventArgs e)
  205. {
  206. try {
  207. if (string.IsNullOrEmpty (e.NewText)) {
  208. e.Cancel = true;
  209. ((TextField)sender).Text = "0";
  210. return;
  211. }
  212. switch (sender.ToString ()) {
  213. case var s when s == _topEdit.ToString ():
  214. Thickness = new Thickness (Thickness.Left,
  215. int.Parse (e.NewText), Thickness.Right,
  216. Thickness.Bottom);
  217. break;
  218. case var s when s == _leftEdit.ToString ():
  219. Thickness = new Thickness (int.Parse (e.NewText),
  220. Thickness.Top, Thickness.Right,
  221. Thickness.Bottom);
  222. break;
  223. case var s when s == _rightEdit.ToString ():
  224. Thickness = new Thickness (Thickness.Left,
  225. Thickness.Top, int.Parse (e.NewText),
  226. Thickness.Bottom);
  227. break;
  228. case var s when s == _bottomEdit.ToString ():
  229. Thickness = new Thickness (Thickness.Left,
  230. Thickness.Top, Thickness.Right,
  231. int.Parse (e.NewText));
  232. break;
  233. }
  234. } catch {
  235. if (!string.IsNullOrEmpty (e.NewText)) {
  236. e.Cancel = true;
  237. }
  238. }
  239. }
  240. }
  241. public class AdornmentsEditor : Window {
  242. AdornmentEditor _borderEditor;
  243. CheckBox _diagCheckBox;
  244. AdornmentEditor _marginEditor;
  245. String _origTitle = string.Empty;
  246. AdornmentEditor _paddingEditor;
  247. View _viewToEdit;
  248. public View ViewToEdit {
  249. get => _viewToEdit;
  250. set {
  251. _origTitle = value.Title;
  252. _viewToEdit = value;
  253. _marginEditor = new AdornmentEditor {
  254. X = 0,
  255. Y = 0,
  256. Title = "Margin",
  257. Thickness = _viewToEdit.Margin.Thickness,
  258. Color = new Attribute (_viewToEdit.Margin.ColorScheme.Normal),
  259. SuperViewRendersLineCanvas = true
  260. };
  261. _marginEditor.ThicknessChanged += Editor_ThicknessChanged;
  262. _marginEditor.AttributeChanged += Editor_AttributeChanged;
  263. Add (_marginEditor);
  264. _borderEditor = new AdornmentEditor {
  265. X = Pos.Left (_marginEditor),
  266. Y = Pos.Bottom (_marginEditor),
  267. Title = "Border",
  268. Thickness = _viewToEdit.Border.Thickness,
  269. Color = new Attribute (_viewToEdit.Border.ColorScheme.Normal),
  270. SuperViewRendersLineCanvas = true
  271. };
  272. _borderEditor.ThicknessChanged += Editor_ThicknessChanged;
  273. _borderEditor.AttributeChanged += Editor_AttributeChanged;
  274. Add (_borderEditor);
  275. var borderStyleEnum = Enum.GetValues (typeof (LineStyle)).Cast<LineStyle> ().ToList ();
  276. var rbBorderStyle = new RadioGroup (borderStyleEnum.Select (
  277. e => e.ToString ()).ToArray ()) {
  278. X = Pos.Right (_borderEditor) - 1,
  279. Y = Pos.Top (_borderEditor),
  280. SelectedItem = (int)_viewToEdit.Border.LineStyle,
  281. BorderStyle = LineStyle.Double,
  282. Title = "Border Style",
  283. SuperViewRendersLineCanvas = true
  284. };
  285. Add (rbBorderStyle);
  286. rbBorderStyle.SelectedItemChanged += (s, e) => {
  287. var prevBorderStyle = _viewToEdit.BorderStyle;
  288. _viewToEdit.Border.LineStyle = (LineStyle)e.SelectedItem;
  289. if (_viewToEdit.Border.LineStyle == LineStyle.None) {
  290. _viewToEdit.Border.Thickness = new Thickness (0);
  291. } else if (prevBorderStyle == LineStyle.None && _viewToEdit.Border.LineStyle != LineStyle.None) {
  292. _viewToEdit.Border.Thickness = new Thickness (1);
  293. }
  294. _borderEditor.Thickness = new Thickness (_viewToEdit.Border.Thickness.Left, _viewToEdit.Border.Thickness.Top,
  295. _viewToEdit.Border.Thickness.Right, _viewToEdit.Border.Thickness.Bottom);
  296. _viewToEdit.SetNeedsDisplay ();
  297. LayoutSubviews ();
  298. };
  299. var ckbTitle = new CheckBox ("Show Title") {
  300. BorderStyle = LineStyle.Double,
  301. X = Pos.Left (_borderEditor),
  302. Y = Pos.Bottom (_borderEditor) - 1,
  303. Width = Dim.Width (_borderEditor),
  304. Checked = true,
  305. SuperViewRendersLineCanvas = true
  306. };
  307. ckbTitle.Toggled += (sender, args) => {
  308. if (ckbTitle.Checked == true) {
  309. _viewToEdit.Title = _origTitle;
  310. } else {
  311. _viewToEdit.Title = string.Empty;
  312. }
  313. };
  314. Add (ckbTitle);
  315. _paddingEditor = new AdornmentEditor {
  316. X = Pos.Left (_borderEditor),
  317. Y = Pos.Bottom (rbBorderStyle),
  318. Title = "Padding",
  319. Thickness = _viewToEdit.Padding.Thickness,
  320. Color = new Attribute (_viewToEdit.Padding.ColorScheme.Normal),
  321. SuperViewRendersLineCanvas = true
  322. };
  323. _paddingEditor.ThicknessChanged += Editor_ThicknessChanged;
  324. _paddingEditor.AttributeChanged += Editor_AttributeChanged;
  325. Add (_paddingEditor);
  326. _diagCheckBox = new CheckBox {
  327. Text = "_Diagnostics",
  328. Y = Pos.Bottom (_paddingEditor)
  329. };
  330. _diagCheckBox.Toggled += (s, e) => {
  331. if (e.NewValue == true) {
  332. ConsoleDriver.Diagnostics = ConsoleDriver.DiagnosticFlags.FramePadding | ConsoleDriver.DiagnosticFlags.FrameRuler;
  333. } else {
  334. ConsoleDriver.Diagnostics = ConsoleDriver.DiagnosticFlags.Off;
  335. }
  336. };
  337. Add (_diagCheckBox);
  338. Add (_viewToEdit);
  339. _viewToEdit.LayoutComplete += (s, e) => {
  340. if (ckbTitle.Checked == true) {
  341. _viewToEdit.Title = _origTitle;
  342. } else {
  343. _viewToEdit.Title = string.Empty;
  344. }
  345. };
  346. }
  347. }
  348. void Editor_AttributeChanged (object sender, Attribute attr)
  349. {
  350. switch (sender.ToString ()) {
  351. case var s when s == _marginEditor.ToString ():
  352. _viewToEdit.Margin.ColorScheme = new ColorScheme (_viewToEdit.Margin.ColorScheme) { Normal = attr };
  353. break;
  354. case var s when s == _borderEditor.ToString ():
  355. _viewToEdit.Border.ColorScheme = new ColorScheme (_viewToEdit.Border.ColorScheme) { Normal = attr };
  356. break;
  357. case var s when s == _paddingEditor.ToString ():
  358. _viewToEdit.Padding.ColorScheme = new ColorScheme (_viewToEdit.Padding.ColorScheme) { Normal = attr };
  359. break;
  360. }
  361. }
  362. void Editor_ThicknessChanged (object sender, ThicknessEventArgs e)
  363. {
  364. try {
  365. switch (sender.ToString ()) {
  366. case var s when s == _marginEditor.ToString ():
  367. _viewToEdit.Margin.Thickness = e.Thickness;
  368. break;
  369. case var s when s == _borderEditor.ToString ():
  370. _viewToEdit.Border.Thickness = e.Thickness;
  371. break;
  372. case var s when s == _paddingEditor.ToString ():
  373. _viewToEdit.Padding.Thickness = e.Thickness;
  374. break;
  375. }
  376. } catch {
  377. switch (sender.ToString ()) {
  378. case var s when s == _marginEditor.ToString ():
  379. _viewToEdit.Margin.Thickness = e.PreviousThickness;
  380. break;
  381. case var s when s == _borderEditor.ToString ():
  382. _viewToEdit.Border.Thickness = e.PreviousThickness;
  383. break;
  384. case var s when s == _paddingEditor.ToString ():
  385. _viewToEdit.Padding.Thickness = e.PreviousThickness;
  386. break;
  387. }
  388. }
  389. }
  390. }
  391. }