LineDrawing.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Terminal.Gui;
  5. namespace UICatalog.Scenarios {
  6. [ScenarioMetadata (Name: "Line Drawing", Description: "Demonstrates LineCanvas.")]
  7. [ScenarioCategory ("Controls")]
  8. [ScenarioCategory ("Layout")]
  9. public class LineDrawing : Scenario {
  10. public override void Setup ()
  11. {
  12. var canvas = new DrawingArea {
  13. X = 0,
  14. Y = 0,
  15. Width = Dim.Fill (),
  16. Height = Dim.Fill ()
  17. };
  18. var tools = new ToolsView () {
  19. Title = "Tools",
  20. X = Pos.Right (canvas) - 20,
  21. Y = 2
  22. };
  23. tools.ColorChanged += (c) => canvas.SetColor (c);
  24. tools.SetStyle += (b) => canvas.LineStyle = b;
  25. tools.AddLayer += () => canvas.AddLayer ();
  26. Win.Add (canvas);
  27. Win.Add (tools);
  28. Win.KeyPress += (s,e) => { e.Handled = canvas.ProcessKey (e.KeyEvent); };
  29. }
  30. class ToolsView : Window {
  31. public event Action<Color> ColorChanged;
  32. public event Action<LineStyle> SetStyle;
  33. public event Action AddLayer;
  34. private RadioGroup _stylePicker;
  35. private ColorPicker _colorPicker;
  36. private Button _addLayerBtn;
  37. public ToolsView ()
  38. {
  39. BorderStyle = LineStyle.Dotted;
  40. Border.Thickness = new Thickness (1, 2, 1, 1);
  41. Initialized += ToolsView_Initialized;
  42. }
  43. private void ToolsView_Initialized (object sender, EventArgs e)
  44. {
  45. LayoutSubviews ();
  46. Width = Math.Max (_colorPicker.Frame.Width, _stylePicker.Frame.Width) + GetFramesThickness ().Horizontal;
  47. Height = _colorPicker.Frame.Height + _stylePicker.Frame.Height + _addLayerBtn.Frame.Height + GetFramesThickness ().Vertical;
  48. SuperView.LayoutSubviews ();
  49. }
  50. public override void BeginInit ()
  51. {
  52. base.BeginInit ();
  53. _colorPicker = new ColorPicker () {
  54. X = 0,
  55. Y = 0,
  56. BoxHeight = 1,
  57. BoxWidth = 2
  58. };
  59. _colorPicker.ColorChanged += (s, a) => ColorChanged?.Invoke (a.Color);
  60. _stylePicker = new RadioGroup (Enum.GetNames (typeof (LineStyle)).ToArray ()) {
  61. X = 0,
  62. Y = Pos.Bottom (_colorPicker)
  63. };
  64. _stylePicker.SelectedItemChanged += (s, a) => {
  65. SetStyle?.Invoke ((LineStyle)a.SelectedItem);
  66. };
  67. _addLayerBtn = new Button () {
  68. Text = "New Layer",
  69. X = Pos.Center (),
  70. Y = Pos.Bottom (_stylePicker),
  71. };
  72. _addLayerBtn.Clicked += (s, a) => AddLayer?.Invoke ();
  73. Add (_colorPicker, _stylePicker, _addLayerBtn);
  74. }
  75. }
  76. class DrawingArea : View {
  77. List<LineCanvas> _layers = new List<LineCanvas> ();
  78. LineCanvas _currentLayer;
  79. Color _currentColor = (Color)Color.White;
  80. StraightLine _currentLine = null;
  81. public LineStyle LineStyle { get; set; }
  82. public DrawingArea ()
  83. {
  84. AddLayer ();
  85. }
  86. Stack<StraightLine> undoHistory = new ();
  87. public override bool ProcessKey (KeyEvent e)
  88. {
  89. if (e.Key == (Key.Z | Key.CtrlMask)) {
  90. var pop = _currentLayer.RemoveLastLine ();
  91. if(pop != null) {
  92. undoHistory.Push (pop);
  93. SetNeedsDisplay ();
  94. return true;
  95. }
  96. }
  97. if (e.Key == (Key.Y | Key.CtrlMask)) {
  98. if (undoHistory.Any()) {
  99. var pop = undoHistory.Pop ();
  100. _currentLayer.AddLine(pop);
  101. SetNeedsDisplay ();
  102. return true;
  103. }
  104. }
  105. return base.ProcessKey (e);
  106. }
  107. internal void AddLayer ()
  108. {
  109. _currentLayer = new LineCanvas ();
  110. _layers.Add (_currentLayer);
  111. }
  112. public override void OnDrawContentComplete (Rect contentArea)
  113. {
  114. base.OnDrawContentComplete (contentArea);
  115. foreach (var canvas in _layers) {
  116. foreach (var c in canvas.GetCellMap ()) {
  117. Driver.SetAttribute (c.Value.Attribute ?? ColorScheme.Normal);
  118. // TODO: #2616 - Support combining sequences that don't normalize
  119. this.AddRune (c.Key.X, c.Key.Y, c.Value.Runes [0]);
  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. }