LineDrawing.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Terminal.Gui;
  5. using Attribute = Terminal.Gui.Attribute;
  6. namespace UICatalog.Scenarios {
  7. [ScenarioMetadata (Name: "Line Drawing", Description: "Demonstrates LineCanvas.")]
  8. [ScenarioCategory ("Controls")]
  9. [ScenarioCategory ("Layout")]
  10. public class LineDrawing : Scenario {
  11. public override void Setup ()
  12. {
  13. var canvas = new DrawingArea {
  14. X = 0,
  15. Y = 0,
  16. Width = Dim.Fill (),
  17. Height = Dim.Fill ()
  18. };
  19. var tools = new ToolsView () {
  20. Title = "Tools",
  21. X = Pos.Right (canvas) - 20,
  22. Y = 2
  23. };
  24. tools.ColorChanged += (c) => canvas.SetColor (c);
  25. tools.SetStyle += (b) => canvas.LineStyle = b;
  26. tools.AddLayer += () => canvas.AddLayer ();
  27. Win.Add (canvas);
  28. Win.Add (tools);
  29. Win.KeyPress += (s,e) => { e.Handled = canvas.ProcessKey (e.KeyEvent); };
  30. }
  31. class ToolsView : Window {
  32. public event Action<Color> ColorChanged;
  33. public event Action<LineStyle> SetStyle;
  34. public event Action AddLayer;
  35. private RadioGroup _stylePicker;
  36. private ColorPicker _colorPicker;
  37. private Button _addLayerBtn;
  38. public ToolsView ()
  39. {
  40. BorderStyle = LineStyle.Dotted;
  41. Border.Thickness = new Thickness (1, 2, 1, 1);
  42. Initialized += ToolsView_Initialized;
  43. }
  44. private void ToolsView_Initialized (object sender, EventArgs e)
  45. {
  46. LayoutSubviews ();
  47. Width = Math.Max (_colorPicker.Frame.Width, _stylePicker.Frame.Width) + GetFramesThickness ().Horizontal;
  48. Height = _colorPicker.Frame.Height + _stylePicker.Frame.Height + _addLayerBtn.Frame.Height + GetFramesThickness ().Vertical;
  49. SuperView.LayoutSubviews ();
  50. }
  51. public override void BeginInit ()
  52. {
  53. base.BeginInit ();
  54. _colorPicker = new ColorPicker () {
  55. X = 0,
  56. Y = 0,
  57. BoxHeight = 1,
  58. BoxWidth = 2
  59. };
  60. _colorPicker.ColorChanged += (s, a) => ColorChanged?.Invoke (a.Color);
  61. _stylePicker = new RadioGroup (Enum.GetNames (typeof (LineStyle)).ToArray ()) {
  62. X = 0,
  63. Y = Pos.Bottom (_colorPicker)
  64. };
  65. _stylePicker.SelectedItemChanged += (s, a) => {
  66. SetStyle?.Invoke ((LineStyle)a.SelectedItem);
  67. };
  68. _addLayerBtn = new Button () {
  69. Text = "New Layer",
  70. X = Pos.Center (),
  71. Y = Pos.Bottom (_stylePicker),
  72. };
  73. _addLayerBtn.Clicked += (s, a) => AddLayer?.Invoke ();
  74. Add (_colorPicker, _stylePicker, _addLayerBtn);
  75. }
  76. }
  77. class DrawingArea : View {
  78. List<LineCanvas> _layers = new List<LineCanvas> ();
  79. LineCanvas _currentLayer;
  80. Color _currentColor = Color.White;
  81. StraightLine _currentLine = null;
  82. public LineStyle LineStyle { get; set; }
  83. public DrawingArea ()
  84. {
  85. AddLayer ();
  86. }
  87. Stack<StraightLine> undoHistory = new ();
  88. public override bool ProcessKey (KeyEvent e)
  89. {
  90. if (e.Key == (Key.Z | Key.CtrlMask)) {
  91. var pop = _currentLayer.RemoveLastLine ();
  92. if(pop != null) {
  93. undoHistory.Push (pop);
  94. SetNeedsDisplay ();
  95. return true;
  96. }
  97. }
  98. if (e.Key == (Key.Y | Key.CtrlMask)) {
  99. if (undoHistory.Any()) {
  100. var pop = undoHistory.Pop ();
  101. _currentLayer.AddLine(pop);
  102. SetNeedsDisplay ();
  103. return true;
  104. }
  105. }
  106. return base.ProcessKey (e);
  107. }
  108. internal void AddLayer ()
  109. {
  110. _currentLayer = new LineCanvas ();
  111. _layers.Add (_currentLayer);
  112. }
  113. public override void OnDrawContentComplete (Rect contentArea)
  114. {
  115. base.OnDrawContentComplete (contentArea);
  116. foreach (var canvas in _layers) {
  117. foreach (var c in canvas.GetCellMap ()) {
  118. Driver.SetAttribute (c.Value.Attribute?.Value ?? ColorScheme.Normal);
  119. this.AddRune (c.Key.X, c.Key.Y, c.Value.Rune.Value);
  120. }
  121. }
  122. }
  123. public override bool OnMouseEvent (MouseEvent mouseEvent)
  124. {
  125. if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) {
  126. if (_currentLine == null) {
  127. _currentLine = new StraightLine (
  128. new Point (mouseEvent.X - GetBoundsOffset ().X, mouseEvent.Y - GetBoundsOffset ().X),
  129. 0, Orientation.Vertical, LineStyle, new Attribute (_currentColor, GetNormalColor ().Background));
  130. _currentLayer.AddLine (_currentLine);
  131. } else {
  132. var start = _currentLine.Start;
  133. var end = new Point (mouseEvent.X - GetBoundsOffset ().X, mouseEvent.Y - GetBoundsOffset ().Y);
  134. var orientation = Orientation.Vertical;
  135. var length = end.Y - start.Y;
  136. // if line is wider than it is tall switch to horizontal
  137. if (Math.Abs (start.X - end.X) > Math.Abs (start.Y - end.Y)) {
  138. orientation = Orientation.Horizontal;
  139. length = end.X - start.X;
  140. }
  141. if (length > 0) {
  142. length++;
  143. } else {
  144. length--;
  145. }
  146. _currentLine.Length = length;
  147. _currentLine.Orientation = orientation;
  148. _currentLayer.ClearCache ();
  149. SetNeedsDisplay ();
  150. }
  151. } else {
  152. if (_currentLine != null) {
  153. _currentLine = null;
  154. undoHistory.Clear ();
  155. SetNeedsDisplay ();
  156. }
  157. }
  158. return base.OnMouseEvent (mouseEvent);
  159. }
  160. internal void SetColor (Color c)
  161. {
  162. _currentColor = c;
  163. }
  164. }
  165. }
  166. }