namespace Terminal.Gui; /// Event arguments for the events. public class ColorEventArgs : EventArgs { /// Initializes a new instance of public ColorEventArgs () { } /// The new Thickness. public Color Color { get; set; } /// The previous Thickness. public Color PreviousColor { get; set; } } /// The Color picker. public class ColorPicker : View { /// Columns of color boxes private readonly int _cols = 8; /// Rows of color boxes private readonly int _rows = 2; private int _boxHeight = 2; private int _boxWidth = 4; private int _selectColorIndex = (int)Color.Black; /// Initializes a new instance of . public ColorPicker () { SetInitialProperties (); } /// Height of a color box public int BoxHeight { get => _boxHeight; set { if (_boxHeight != value) { _boxHeight = value; SetNeedsLayout (); } } } /// Width of a color box public int BoxWidth { get => _boxWidth; set { if (_boxWidth != value) { _boxWidth = value; SetNeedsLayout (); } } } /// Cursor for the selected color. public Point Cursor { get => new (_selectColorIndex % _cols, _selectColorIndex / _cols); set { int colorIndex = value.Y * _cols + value.X; SelectedColor = (ColorName)colorIndex; } } /// Selected color. public ColorName SelectedColor { get => (ColorName)_selectColorIndex; set { var prev = (ColorName)_selectColorIndex; _selectColorIndex = (int)value; ColorChanged?.Invoke ( this, new ColorEventArgs { PreviousColor = new Color (prev), Color = new Color (value) } ); SetNeedsDisplay (); } } /// Fired when a color is picked. public event EventHandler ColorChanged; /// protected internal override bool OnMouseEvent (MouseEvent me) { if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) || !CanFocus) { return false; } SetFocus (); if (me.X > Viewport.Width || me.Y > Viewport.Height) { return true; } Cursor = new Point (me.X / _boxWidth, me.Y / _boxHeight); return true; } /// Moves the selected item index to the next row. /// public virtual bool MoveDown () { if (Cursor.Y < _rows - 1) { SelectedColor += _cols; } return true; } /// Moves the selected item index to the previous column. /// public virtual bool MoveLeft () { if (Cursor.X > 0) { SelectedColor--; } return true; } /// Moves the selected item index to the next column. /// public virtual bool MoveRight () { if (Cursor.X < _cols - 1) { SelectedColor++; } return true; } /// Moves the selected item index to the previous row. /// public virtual bool MoveUp () { if (Cursor.Y > 0) { SelectedColor -= _cols; } return true; } /// public override void OnDrawContent (Rectangle viewport) { base.OnDrawContent (viewport); Driver.SetAttribute (HasFocus ? ColorScheme.Focus : GetNormalColor ()); var colorIndex = 0; for (var y = 0; y < Viewport.Height / BoxHeight; y++) { for (var x = 0; x < Viewport.Width / BoxWidth; x++) { int foregroundColorIndex = y == 0 ? colorIndex + _cols : colorIndex - _cols; Driver.SetAttribute (new Attribute ((ColorName)foregroundColorIndex, (ColorName)colorIndex)); bool selected = x == Cursor.X && y == Cursor.Y; DrawColorBox (x, y, selected); colorIndex++; } } } /// public override bool OnEnter (View view) { Application.Driver.SetCursorVisibility (CursorVisibility.Invisible); return base.OnEnter (view); } /// Add the commands. private void AddCommands () { AddCommand (Command.Left, () => MoveLeft ()); AddCommand (Command.Right, () => MoveRight ()); AddCommand (Command.LineUp, () => MoveUp ()); AddCommand (Command.LineDown, () => MoveDown ()); } /// Add the KeyBindinds. private void AddKeyBindings () { KeyBindings.Add (Key.CursorLeft, Command.Left); KeyBindings.Add (Key.CursorRight, Command.Right); KeyBindings.Add (Key.CursorUp, Command.LineUp); KeyBindings.Add (Key.CursorDown, Command.LineDown); } /// Draw a box for one color. /// X location. /// Y location /// private void DrawColorBox (int x, int y, bool selected) { var index = 0; for (var zoomedY = 0; zoomedY < BoxHeight; zoomedY++) { for (var zoomedX = 0; zoomedX < BoxWidth; zoomedX++) { Move (x * BoxWidth + zoomedX, y * BoxHeight + zoomedY); Driver.AddRune ((Rune)' '); index++; } } if (selected) { DrawFocusRect (new (x * BoxWidth, y * BoxHeight, BoxWidth, BoxHeight)); } } private void DrawFocusRect (Rectangle rect) { var lc = new LineCanvas (); if (rect.Width == 1) { lc.AddLine (rect.Location, rect.Height, Orientation.Vertical, LineStyle.Dotted); } else if (rect.Height == 1) { lc.AddLine (rect.Location, rect.Width, Orientation.Horizontal, LineStyle.Dotted); } else { lc.AddLine (rect.Location, rect.Width, Orientation.Horizontal, LineStyle.Dotted); lc.AddLine ( rect.Location with { Y = rect.Location.Y + rect.Height - 1 }, rect.Width, Orientation.Horizontal, LineStyle.Dotted ); lc.AddLine (rect.Location, rect.Height, Orientation.Vertical, LineStyle.Dotted); lc.AddLine ( rect.Location with { X = rect.Location.X + rect.Width - 1 }, rect.Height, Orientation.Vertical, LineStyle.Dotted ); } foreach (KeyValuePair p in lc.GetMap ()) { AddRune (p.Key.X, p.Key.Y, p.Value); } } private void SetInitialProperties () { CanFocus = true; AddCommands (); AddKeyBindings (); LayoutStarted += (o, a) => { Thickness thickness = GetAdornmentsThickness (); Width = _cols * BoxWidth + thickness.Vertical; Height = _rows * BoxHeight + thickness.Horizontal; }; } }