123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Terminal.Gui;
- namespace UICatalog.Scenarios;
- [ScenarioMetadata ("Line Drawing", "Demonstrates LineCanvas.")]
- [ScenarioCategory ("Controls")]
- [ScenarioCategory ("Drawing")]
- public class LineDrawing : Scenario
- {
- public override void Main ()
- {
- Application.Init ();
- var win = new Window { Title = GetQuitKeyAndName () };
- var canvas = new DrawingArea { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
- var tools = new ToolsView { Title = "Tools", X = Pos.Right (canvas) - 20, Y = 2 };
- tools.ColorChanged += c => canvas.SetColor (c);
- tools.SetStyle += b => canvas.LineStyle = b;
- tools.AddLayer += () => canvas.AddLayer ();
- win.Add (canvas);
- win.Add (tools);
- win.KeyDown += (s, e) => { e.Handled = canvas.OnKeyDown (e); };
- Application.Run (win);
- win.Dispose ();
- Application.Shutdown ();
- }
- private class DrawingArea : View
- {
- private readonly List<LineCanvas> _layers = new ();
- private readonly Stack<StraightLine> _undoHistory = new ();
- private Color _currentColor = new (Color.White);
- private LineCanvas _currentLayer;
- private StraightLine _currentLine;
- public DrawingArea () { AddLayer (); }
- public LineStyle LineStyle { get; set; }
- public override void OnDrawContentComplete (Rectangle viewport)
- {
- base.OnDrawContentComplete (viewport);
- foreach (LineCanvas canvas in _layers)
- {
- foreach (KeyValuePair<Point, Cell?> c in canvas.GetCellMap ())
- {
- if (c.Value is { })
- {
- Driver.SetAttribute (c.Value.Value.Attribute ?? ColorScheme.Normal);
- // TODO: #2616 - Support combining sequences that don't normalize
- AddRune (c.Key.X, c.Key.Y, c.Value.Value.Rune);
- }
- }
- }
- }
- //// BUGBUG: Why is this not handled by a key binding???
- public override bool OnKeyDown (Key e)
- {
- // BUGBUG: These should be implemented with key bindings
- if (e.KeyCode == (KeyCode.Z | KeyCode.CtrlMask))
- {
- StraightLine pop = _currentLayer.RemoveLastLine ();
- if (pop != null)
- {
- _undoHistory.Push (pop);
- SetNeedsDisplay ();
- return true;
- }
- }
- if (e.KeyCode == (KeyCode.Y | KeyCode.CtrlMask))
- {
- if (_undoHistory.Any ())
- {
- StraightLine pop = _undoHistory.Pop ();
- _currentLayer.AddLine (pop);
- SetNeedsDisplay ();
- return true;
- }
- }
- return false;
- }
- protected override bool OnMouseEvent (MouseEvent mouseEvent)
- {
- if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
- {
- if (_currentLine == null)
- {
- // Mouse pressed down
- _currentLine = new StraightLine (
- mouseEvent.Position,
- 0,
- Orientation.Vertical,
- LineStyle,
- new Attribute (_currentColor, GetNormalColor ().Background)
- );
- _currentLayer.AddLine (_currentLine);
- }
- else
- {
- // Mouse dragged
- Point start = _currentLine.Start;
- var end = mouseEvent.Position;
- var orientation = Orientation.Vertical;
- int length = end.Y - start.Y;
- // if line is wider than it is tall switch to horizontal
- if (Math.Abs (start.X - end.X) > Math.Abs (start.Y - end.Y))
- {
- orientation = Orientation.Horizontal;
- length = end.X - start.X;
- }
- if (length > 0)
- {
- length++;
- }
- else
- {
- length--;
- }
- _currentLine.Length = length;
- _currentLine.Orientation = orientation;
- _currentLayer.ClearCache ();
- SetNeedsDisplay ();
- }
- }
- else
- {
- // Mouse released
- if (_currentLine != null)
- {
- if (_currentLine.Length == 0)
- {
- _currentLine.Length = 1;
- }
- if (_currentLine.Style == LineStyle.None)
- {
- // Treat none as eraser
- int idx = _layers.IndexOf (_currentLayer);
- _layers.Remove (_currentLayer);
- _currentLayer = new LineCanvas (
- _currentLayer.Lines.Exclude (
- _currentLine.Start,
- _currentLine.Length,
- _currentLine.Orientation
- )
- );
- _layers.Insert (idx, _currentLayer);
- }
- _currentLine = null;
- _undoHistory.Clear ();
- SetNeedsDisplay ();
- }
- }
- return base.OnMouseEvent (mouseEvent);
- }
- internal void AddLayer ()
- {
- _currentLayer = new LineCanvas ();
- _layers.Add (_currentLayer);
- }
- internal void SetColor (Color c) { _currentColor = c; }
- }
- private class ToolsView : Window
- {
- private Button _addLayerBtn;
- private ColorPicker _colorPicker;
- private RadioGroup _stylePicker;
- public ToolsView ()
- {
- BorderStyle = LineStyle.Dotted;
- Border.Thickness = new Thickness (1, 2, 1, 1);
- Initialized += ToolsView_Initialized;
- }
- public event Action AddLayer;
- public override void BeginInit ()
- {
- base.BeginInit ();
- _colorPicker = new ColorPicker { X = 0, Y = 0, BoxHeight = 1, BoxWidth = 2 };
- _colorPicker.ColorChanged += (s, a) => ColorChanged?.Invoke (a.Color);
- _stylePicker = new RadioGroup
- {
- X = 0, Y = Pos.Bottom (_colorPicker), RadioLabels = Enum.GetNames (typeof (LineStyle)).ToArray ()
- };
- _stylePicker.SelectedItemChanged += (s, a) => { SetStyle?.Invoke ((LineStyle)a.SelectedItem); };
- _stylePicker.SelectedItem = 1;
- _addLayerBtn = new Button { Text = "New Layer", X = Pos.Center (), Y = Pos.Bottom (_stylePicker) };
- _addLayerBtn.Accept += (s, a) => AddLayer?.Invoke ();
- Add (_colorPicker, _stylePicker, _addLayerBtn);
- }
- public event Action<Color> ColorChanged;
- public event Action<LineStyle> SetStyle;
- private void ToolsView_Initialized (object sender, EventArgs e)
- {
- LayoutSubviews ();
- Width = Math.Max (_colorPicker.Frame.Width, _stylePicker.Frame.Width) + GetAdornmentsThickness ().Horizontal;
- Height = _colorPicker.Frame.Height + _stylePicker.Frame.Height + _addLayerBtn.Frame.Height + GetAdornmentsThickness ().Vertical;
- SuperView.LayoutSubviews ();
- }
- }
- }
|