mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-27 08:17:53 +01:00
Added Border Settings.
Enabled BorderSettings.Gradient
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using Terminal.Gui.Drawing;
|
||||
|
||||
namespace Terminal.Gui;
|
||||
|
||||
/// <summary>The Border for a <see cref="View"/>.</summary>
|
||||
@@ -78,7 +80,7 @@ public class Border : Adornment
|
||||
if ((Parent?.Arrangement & ViewArrangement.Movable) != 0)
|
||||
{
|
||||
HighlightStyle |= HighlightStyle.Hover;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
base.BeginInit ();
|
||||
@@ -149,31 +151,32 @@ public class Border : Adornment
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle GetBorderRectangle (Rectangle screenRect)
|
||||
private Rectangle GetBorderRectangle (Rectangle screenRect)
|
||||
{
|
||||
return new (
|
||||
screenRect.X + Math.Max (0, Thickness.Left - 1),
|
||||
screenRect.Y + Math.Max (0, Thickness.Top - 1),
|
||||
Math.Max (
|
||||
0,
|
||||
screenRect.Width
|
||||
- Math.Max (
|
||||
0,
|
||||
Math.Max (0, Thickness.Left - 1)
|
||||
+ Math.Max (0, Thickness.Right - 1)
|
||||
)
|
||||
),
|
||||
Math.Max (
|
||||
0,
|
||||
screenRect.Height
|
||||
- Math.Max (
|
||||
0,
|
||||
Math.Max (0, Thickness.Top - 1)
|
||||
+ Math.Max (0, Thickness.Bottom - 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
screenRect.X + Math.Max (0, Thickness.Left - 1),
|
||||
screenRect.Y + Math.Max (0, Thickness.Top - 1),
|
||||
Math.Max (
|
||||
0,
|
||||
screenRect.Width
|
||||
- Math.Max (
|
||||
0,
|
||||
Math.Max (0, Thickness.Left - 1)
|
||||
+ Math.Max (0, Thickness.Right - 1)
|
||||
)
|
||||
),
|
||||
Math.Max (
|
||||
0,
|
||||
screenRect.Height
|
||||
- Math.Max (
|
||||
0,
|
||||
Math.Max (0, Thickness.Top - 1)
|
||||
+ Math.Max (0, Thickness.Bottom - 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the style of the border by changing the <see cref="Thickness"/>. This is a helper API for setting the
|
||||
/// <see cref="Thickness"/> to <c>(1,1,1,1)</c> and setting the line style of the views that comprise the border. If
|
||||
@@ -196,21 +199,22 @@ public class Border : Adornment
|
||||
set => _lineStyle = value;
|
||||
}
|
||||
|
||||
private bool _showTitle = true;
|
||||
private BorderSettings _settings = BorderSettings.Title;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the title should be shown. The default is <see langword="true"/>.
|
||||
/// Gets or sets the settings for the border.
|
||||
/// </summary>
|
||||
public bool ShowTitle
|
||||
public BorderSettings Settings
|
||||
{
|
||||
get => _showTitle;
|
||||
get => _settings;
|
||||
set
|
||||
{
|
||||
if (value == _showTitle)
|
||||
if (value == _settings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_showTitle = value;
|
||||
|
||||
_settings = value;
|
||||
|
||||
Parent?.SetNeedsDisplay ();
|
||||
}
|
||||
@@ -225,6 +229,7 @@ public class Border : Adornment
|
||||
if (!Parent.Arrangement.HasFlag (ViewArrangement.Movable))
|
||||
{
|
||||
e.Cancel = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -235,9 +240,9 @@ public class Border : Adornment
|
||||
_savedForeColor = ColorScheme.Normal.Foreground;
|
||||
}
|
||||
|
||||
ColorScheme cs = new ColorScheme (ColorScheme)
|
||||
var cs = new ColorScheme (ColorScheme)
|
||||
{
|
||||
Normal = new Attribute (ColorScheme.Normal.Foreground.GetHighlightColor (), ColorScheme.Normal.Background)
|
||||
Normal = new (ColorScheme.Normal.Foreground.GetHighlightColor (), ColorScheme.Normal.Background)
|
||||
};
|
||||
ColorScheme = cs;
|
||||
}
|
||||
@@ -254,12 +259,13 @@ public class Border : Adornment
|
||||
|
||||
if (e.NewValue == HighlightStyle.None && _savedForeColor.HasValue)
|
||||
{
|
||||
ColorScheme cs = new ColorScheme (ColorScheme)
|
||||
var cs = new ColorScheme (ColorScheme)
|
||||
{
|
||||
Normal = new Attribute (_savedForeColor.Value, ColorScheme.Normal.Background)
|
||||
Normal = new (_savedForeColor.Value, ColorScheme.Normal.Background)
|
||||
};
|
||||
ColorScheme = cs;
|
||||
}
|
||||
|
||||
Parent?.SetNeedsDisplay ();
|
||||
e.Cancel = true;
|
||||
}
|
||||
@@ -267,7 +273,7 @@ public class Border : Adornment
|
||||
private Point? _dragPosition;
|
||||
private Point _startGrabPoint;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc/>
|
||||
protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
|
||||
{
|
||||
if (base.OnMouseEvent (mouseEvent))
|
||||
@@ -322,16 +328,17 @@ public class Border : Adornment
|
||||
|
||||
_dragPosition = mouseEvent.Position;
|
||||
|
||||
Point parentLoc = Parent.SuperView?.ScreenToViewport (new (mouseEvent.ScreenPosition.X, mouseEvent.ScreenPosition.Y)) ?? mouseEvent.ScreenPosition;
|
||||
Point parentLoc = Parent.SuperView?.ScreenToViewport (new (mouseEvent.ScreenPosition.X, mouseEvent.ScreenPosition.Y))
|
||||
?? mouseEvent.ScreenPosition;
|
||||
|
||||
GetLocationEnsuringFullVisibility (
|
||||
Parent,
|
||||
parentLoc.X - _startGrabPoint.X,
|
||||
parentLoc.Y - _startGrabPoint.Y,
|
||||
out int nx,
|
||||
out int ny,
|
||||
out _
|
||||
);
|
||||
Parent,
|
||||
parentLoc.X - _startGrabPoint.X,
|
||||
parentLoc.Y - _startGrabPoint.Y,
|
||||
out int nx,
|
||||
out int ny,
|
||||
out _
|
||||
);
|
||||
|
||||
Parent.X = nx;
|
||||
Parent.Y = ny;
|
||||
@@ -352,7 +359,6 @@ public class Border : Adornment
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
@@ -403,7 +409,7 @@ public class Border : Adornment
|
||||
// ...thickness extends outward (border/title is always as far in as possible)
|
||||
// PERF: How about a call to Rectangle.Offset?
|
||||
|
||||
var borderBounds = GetBorderRectangle (screenBounds);
|
||||
Rectangle borderBounds = GetBorderRectangle (screenBounds);
|
||||
int topTitleLineY = borderBounds.Y;
|
||||
int titleY = borderBounds.Y;
|
||||
var titleBarsLength = 0; // the little vertical thingies
|
||||
@@ -421,7 +427,7 @@ public class Border : Adornment
|
||||
int sideLineLength = borderBounds.Height;
|
||||
bool canDrawBorder = borderBounds is { Width: > 0, Height: > 0 };
|
||||
|
||||
if (ShowTitle)
|
||||
if (Settings.FastHasFlags (BorderSettings.Title))
|
||||
{
|
||||
if (Thickness.Top == 2)
|
||||
{
|
||||
@@ -453,9 +459,10 @@ public class Border : Adornment
|
||||
}
|
||||
}
|
||||
|
||||
if (canDrawBorder && Thickness.Top > 0 && maxTitleWidth > 0 && ShowTitle && !string.IsNullOrEmpty (Parent?.Title))
|
||||
if (canDrawBorder && Thickness.Top > 0 && maxTitleWidth > 0 && Settings.FastHasFlags (BorderSettings.Title) && !string.IsNullOrEmpty (Parent?.Title))
|
||||
{
|
||||
var focus = Parent.GetNormalColor ();
|
||||
Attribute focus = Parent.GetNormalColor ();
|
||||
|
||||
if (Parent.SuperView is { } && Parent.SuperView?.Subviews!.Count (s => s.CanFocus) > 1)
|
||||
{
|
||||
// Only use focus color if there are multiple focusable views
|
||||
@@ -492,7 +499,7 @@ public class Border : Adornment
|
||||
{
|
||||
// ╔╡Title╞═════╗
|
||||
// ╔╡╞═════╗
|
||||
if (borderBounds.Width < 4 || !ShowTitle || string.IsNullOrEmpty (Parent?.Title))
|
||||
if (borderBounds.Width < 4 || !Settings.FastHasFlags (BorderSettings.Title) || string.IsNullOrEmpty (Parent?.Title))
|
||||
{
|
||||
// ╔╡╞╗ should be ╔══╗
|
||||
lc.AddLine (
|
||||
@@ -631,7 +638,7 @@ public class Border : Adornment
|
||||
Driver.SetAttribute (prevAttr);
|
||||
|
||||
// TODO: This should be moved to LineCanvas as a new BorderStyle.Ruler
|
||||
if (View.Diagnostics.HasFlag (ViewDiagnosticFlags.Ruler))
|
||||
if (Diagnostics.HasFlag (ViewDiagnosticFlags.Ruler))
|
||||
{
|
||||
// Top
|
||||
var hruler = new Ruler { Length = screenBounds.Width, Orientation = Orientation.Horizontal };
|
||||
@@ -642,7 +649,7 @@ public class Border : Adornment
|
||||
}
|
||||
|
||||
// Redraw title
|
||||
if (drawTop && maxTitleWidth > 0 && ShowTitle)
|
||||
if (drawTop && maxTitleWidth > 0 && Settings.FastHasFlags (BorderSettings.Title))
|
||||
{
|
||||
Parent.TitleTextFormatter.Draw (
|
||||
new (borderBounds.X + 2, titleY, maxTitleWidth, 1),
|
||||
@@ -670,6 +677,45 @@ public class Border : Adornment
|
||||
vruler.Draw (new (screenBounds.X + screenBounds.Width - 1, screenBounds.Y + 1), 1);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This should not be done on each draw?
|
||||
if (Settings.FastHasFlags (BorderSettings.Gradient))
|
||||
{
|
||||
SetupGradientLineCanvas (lc, screenBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
lc.Fill = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupGradientLineCanvas (LineCanvas lc, Rectangle rect)
|
||||
{
|
||||
GetAppealingGradientColors (out List<Color> stops, out List<int> steps);
|
||||
|
||||
var g = new Gradient (stops, steps);
|
||||
|
||||
var fore = new GradientFill (rect, g, GradientDirection.Diagonal);
|
||||
var back = new SolidFill (GetNormalColor ().Background);
|
||||
|
||||
lc.Fill = new (fore, back);
|
||||
}
|
||||
|
||||
private static void GetAppealingGradientColors (out List<Color> stops, out List<int> steps)
|
||||
{
|
||||
// Define the colors of the gradient stops with more appealing colors
|
||||
stops = new()
|
||||
{
|
||||
new (0, 128, 255), // Bright Blue
|
||||
new (0, 255, 128), // Bright Green
|
||||
new (255, 255), // Bright Yellow
|
||||
new (255, 128), // Bright Orange
|
||||
new (255, 0, 128) // Bright Pink
|
||||
};
|
||||
|
||||
// Define the number of steps between each color for smoother transitions
|
||||
// If we pass only a single value then it will assume equal steps between all pairs
|
||||
steps = new() { 15 };
|
||||
}
|
||||
}
|
||||
|
||||
26
Terminal.Gui/View/Adornment/BorderSettings.cs
Normal file
26
Terminal.Gui/View/Adornment/BorderSettings.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Terminal.Gui.Analyzers.Internal.Attributes;
|
||||
|
||||
namespace Terminal.Gui;
|
||||
|
||||
/// <summary>
|
||||
/// Determines the settings for <see cref="Border"/>.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
[GenerateEnumExtensionMethods (FastHasFlags = true)]
|
||||
public enum BorderSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// No settings.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Show the title.
|
||||
/// </summary>
|
||||
Title = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Use <see cref="GradientFill"/> to draw the border.
|
||||
/// </summary>
|
||||
Gradient = 2,
|
||||
}
|
||||
@@ -223,7 +223,7 @@ public class Margin : Adornment
|
||||
if (ShadowStyle != ShadowStyle.None && _rightShadow is { } && _bottomShadow is { })
|
||||
{
|
||||
_rightShadow.Y = Parent.Border.Thickness.Top > 0
|
||||
? Parent.Border.Thickness.Top - (Parent.Border.Thickness.Top > 2 && Parent.Border.ShowTitle ? 1 : 0)
|
||||
? Parent.Border.Thickness.Top - (Parent.Border.Thickness.Top > 2 && Parent.Border.Settings.FastHasFlags (BorderSettings.Title) ? 1 : 0)
|
||||
: 1;
|
||||
_bottomShadow.X = Parent.Border.Thickness.Left > 0 ? Parent.Border.Thickness.Left : 1;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public class Shortcut : View
|
||||
void OnInitialized (object sender, EventArgs e)
|
||||
{
|
||||
SuperViewRendersLineCanvas = true;
|
||||
Border.ShowTitle = false;
|
||||
Border.Settings &= ~BorderSettings.Title;
|
||||
|
||||
ShowHide ();
|
||||
|
||||
|
||||
@@ -9,29 +9,30 @@ public class BorderEditor : AdornmentEditor
|
||||
{
|
||||
private CheckBox _ckbTitle;
|
||||
private RadioGroup _rbBorderStyle;
|
||||
private CheckBox _ckbGradient;
|
||||
|
||||
public BorderEditor ()
|
||||
{
|
||||
Title = "_Border";
|
||||
Initialized += BorderEditor_Initialized;
|
||||
AdornmentChanged += BorderEditor_AdornmentChanged;
|
||||
|
||||
}
|
||||
|
||||
private void BorderEditor_AdornmentChanged (object sender, EventArgs e)
|
||||
{
|
||||
_ckbTitle.State = ((Border)AdornmentToEdit).ShowTitle ? CheckState.Checked : CheckState.UnChecked;
|
||||
_ckbTitle.State = ((Border)AdornmentToEdit).Settings.FastHasFlags (BorderSettings.Title) ? CheckState.Checked : CheckState.UnChecked;
|
||||
_rbBorderStyle.SelectedItem = (int)((Border)AdornmentToEdit).LineStyle;
|
||||
_ckbGradient.State = ((Border)AdornmentToEdit).Settings.FastHasFlags (BorderSettings.Gradient) ? CheckState.Checked : CheckState.UnChecked;
|
||||
}
|
||||
|
||||
private void BorderEditor_Initialized (object sender, EventArgs e)
|
||||
{
|
||||
|
||||
List<LineStyle> borderStyleEnum = Enum.GetValues (typeof (LineStyle)).Cast<LineStyle> ().ToList ();
|
||||
|
||||
_rbBorderStyle = new RadioGroup
|
||||
_rbBorderStyle = new()
|
||||
{
|
||||
X = 0,
|
||||
|
||||
// BUGBUG: Hack until dimauto is working properly
|
||||
Y = Pos.Bottom (Subviews [^1]),
|
||||
Width = Dim.Width (Subviews [^2]) + Dim.Width (Subviews [^1]) - 1,
|
||||
@@ -46,21 +47,34 @@ public class BorderEditor : AdornmentEditor
|
||||
|
||||
_rbBorderStyle.SelectedItemChanged += OnRbBorderStyleOnSelectedItemChanged;
|
||||
|
||||
_ckbTitle = new CheckBox
|
||||
_ckbTitle = new()
|
||||
{
|
||||
X = 0,
|
||||
Y = Pos.Bottom (_rbBorderStyle),
|
||||
|
||||
State = CheckState.Checked,
|
||||
SuperViewRendersLineCanvas = true,
|
||||
Text = "Show Title",
|
||||
Text = "Title",
|
||||
Enabled = AdornmentToEdit is { }
|
||||
};
|
||||
|
||||
|
||||
_ckbTitle.Toggle += OnCkbTitleOnToggle;
|
||||
Add (_ckbTitle);
|
||||
|
||||
_ckbGradient = new ()
|
||||
{
|
||||
X = 0,
|
||||
Y = Pos.Bottom (_ckbTitle),
|
||||
|
||||
State = CheckState.Checked,
|
||||
SuperViewRendersLineCanvas = true,
|
||||
Text = "Gradient",
|
||||
Enabled = AdornmentToEdit is { }
|
||||
};
|
||||
|
||||
_ckbGradient.Toggle += OnCkbGradientOnToggle;
|
||||
Add (_ckbGradient);
|
||||
|
||||
return;
|
||||
|
||||
void OnRbBorderStyleOnSelectedItemChanged (object s, SelectedItemChangedArgs e)
|
||||
@@ -81,6 +95,32 @@ public class BorderEditor : AdornmentEditor
|
||||
LayoutSubviews ();
|
||||
}
|
||||
|
||||
void OnCkbTitleOnToggle (object sender, CancelEventArgs<CheckState> args) { ((Border)AdornmentToEdit).ShowTitle = args.NewValue == CheckState.Checked; }
|
||||
void OnCkbTitleOnToggle (object sender, CancelEventArgs<CheckState> args)
|
||||
{
|
||||
if (args.NewValue == CheckState.Checked)
|
||||
|
||||
{
|
||||
((Border)AdornmentToEdit).Settings |= BorderSettings.Title;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
((Border)AdornmentToEdit).Settings &= ~BorderSettings.Title;
|
||||
}
|
||||
}
|
||||
|
||||
void OnCkbGradientOnToggle (object sender, CancelEventArgs<CheckState> args)
|
||||
{
|
||||
if (args.NewValue == CheckState.Checked)
|
||||
|
||||
{
|
||||
((Border)AdornmentToEdit).Settings |= BorderSettings.Gradient;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
((Border)AdornmentToEdit).Settings &= ~BorderSettings.Gradient;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user