diff --git a/Terminal.Gui/Resources/config.json b/Terminal.Gui/Resources/config.json
index bdb642d36..7ec77e4f4 100644
--- a/Terminal.Gui/Resources/config.json
+++ b/Terminal.Gui/Resources/config.json
@@ -27,8 +27,10 @@
"Default": {
"Dialog.DefaultButtonAlignment": "End",
"Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems",
- "FrameView.DefaultBorderStyle": "Single",
+ "FrameView.DefaultBorderStyle": "Rounded",
"Window.DefaultBorderStyle": "Single",
+ "Dialog.DefaultBorderStyle": "Double",
+ "MessageBox.DefaultBorderStyle": "Double",
"ColorSchemes": [
{
"TopLevel": {
diff --git a/Terminal.Gui/View/Adornment/Margin.cs b/Terminal.Gui/View/Adornment/Margin.cs
index 1734de200..6c5660150 100644
--- a/Terminal.Gui/View/Adornment/Margin.cs
+++ b/Terminal.Gui/View/Adornment/Margin.cs
@@ -1,5 +1,6 @@
#nullable enable
-using static Unix.Terminal.Curses;
+
+using System.Drawing;
namespace Terminal.Gui;
@@ -27,7 +28,7 @@ public class Margin : Adornment
private void Margin_LayoutStarted (object? sender, LayoutEventArgs e)
{
// Adjust the shadow such that it is drawn aligned with the Border
- if (_shadow && _rightShadow is { } && _bottomShadow is { })
+ if (ShadowStyle != Gui.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) : 1;
_bottomShadow.X = Parent.Border.Thickness.Left > 0 ? Parent.Border.Thickness.Left : 1;
@@ -37,7 +38,7 @@ public class Margin : Adornment
private bool _pressed;
private void Margin_Highlight (object? sender, HighlightEventArgs e)
{
- if (_shadow)
+ if (ShadowStyle != Gui.ShadowStyle.None)
{
if (_pressed && e.HighlightStyle == HighlightStyle.None)
{
@@ -75,6 +76,7 @@ public class Margin : Adornment
}
+ ///
public override void OnDrawContent (Rectangle viewport)
{
Rectangle screen = ViewportToScreen (viewport);
@@ -82,7 +84,7 @@ public class Margin : Adornment
Driver.SetAttribute (normalAttr);
// This just draws/clears the thickness, not the insides.
- if (Parent?.Shadow == true)
+ if (ShadowStyle != ShadowStyle.None)
{
screen = Rectangle.Inflate (screen, -1, -1);
}
@@ -132,45 +134,53 @@ public class Margin : Adornment
}
}
- private bool _shadow;
+ ///
+ public override ShadowStyle ShadowStyle
+ {
+ get => base.ShadowStyle;
+ set
+ {
+ base.ShadowStyle = SetShadow (value);
+ }
+ }
///
- /// Gets or sets whether the Margin includes a shadow effect. The shadow is drawn on the right and bottom sides of the
+ /// Sets whether the Margin includes a shadow effect. The shadow is drawn on the right and bottom sides of the
/// Margin.
///
- public bool EnableShadow (bool enable)
+ public ShadowStyle SetShadow (ShadowStyle style)
{
- if (_shadow == enable)
+ if (ShadowStyle == style)
{
- return _shadow;
+ // return style;
}
- if (_shadow)
+ if (ShadowStyle != ShadowStyle.None)
{
+ // Turn off shadow
Thickness = new (Thickness.Left, Thickness.Top, Thickness.Right - 1, Thickness.Bottom - 1);
}
- _shadow = enable;
-
- if (_shadow)
+ if (style != ShadowStyle.None)
{
+ // Turn on shadow
Thickness = new (Thickness.Left, Thickness.Top, Thickness.Right + 1, Thickness.Bottom + 1);
}
if (_rightShadow is { })
{
- _rightShadow.Visible = _shadow;
+ _rightShadow.ShadowStyle = style;
}
if (_bottomShadow is { })
{
- _bottomShadow.Visible = _shadow;
+ _bottomShadow.ShadowStyle = style;
}
- return _shadow;
+ return style;
}
- private View? _bottomShadow;
- private View? _rightShadow;
+ private ShadowView? _bottomShadow;
+ private ShadowView? _rightShadow;
///
public override void BeginInit ()
@@ -182,8 +192,7 @@ public class Margin : Adornment
return;
}
- Attribute attr = Parent.GetNormalColor ();
-
+ ShadowStyle = base.ShadowStyle;
Add (
_rightShadow = new ShadowView
{
@@ -191,7 +200,7 @@ public class Margin : Adornment
Y = 0,
Width = 1,
Height = Dim.Fill (),
- Visible = _shadow,
+ ShadowStyle = ShadowStyle,
Orientation = Orientation.Vertical
},
_bottomShadow = new ShadowView
@@ -200,88 +209,9 @@ public class Margin : Adornment
Y = Pos.AnchorEnd (1),
Width = Dim.Fill (),
Height = 1,
- Visible = _shadow,
+ ShadowStyle = ShadowStyle,
Orientation = Orientation.Horizontal
}
);
}
-}
-
-///
-/// Draws a shadow on the right or bottom of the view.
-///
-internal class ShadowView : View
-{
- // TODO: Add these to CM.Glyphs
- private readonly char VERTICAL_START_GLYPH = '\u258C'; // Half: '\u2596';
- private readonly char VERTICAL_GLYPH = '\u258C';
- private readonly char HORIZONTAL_START_GLYPH = '\u2580'; // Half: '\u259d';
- private readonly char HORIZONTAL_GLYPH = '\u2580';
- private readonly char HORIZONTAL_END_GLYPH = '\u2598';
-
- ///
- /// Gets or sets the orientation of the shadow.
- ///
- public Orientation Orientation { get; set; }
-
- ///
- public override Attribute GetNormalColor ()
- {
- if (SuperView is Adornment adornment)
- {
- if (adornment.Parent.SuperView is { })
- {
- Attribute attr = adornment.Parent.SuperView.GetNormalColor ();
- return new (new Attribute (attr.Foreground.GetDarkerColor (), attr.Background));
- }
- else
- {
- Attribute attr = Application.Top.GetNormalColor ();
- return new (new Attribute (attr.Foreground.GetDarkerColor (), attr.Background));
- }
- }
- return base.GetNormalColor ();
- }
-
- ///
- public override void OnDrawContent (Rectangle viewport)
- {
- //base.OnDrawContent (viewport);
-
- if (Orientation == Orientation.Vertical)
- {
- DrawVerticalShadow (viewport);
- }
- else
- {
- DrawHorizontalShadow (viewport);
- }
- }
-
- private void DrawHorizontalShadow (Rectangle rectangle)
- {
- // Draw the start glyph
- AddRune (0, 0, (Rune)HORIZONTAL_START_GLYPH);
-
- // Fill the rest of the rectangle with the glyph
- for (var i = 1; i < rectangle.Width - 1; i++)
- {
- AddRune (i, 0, (Rune)HORIZONTAL_GLYPH);
- }
-
- // Last is special
- AddRune (rectangle.Width - 1, 0, (Rune)HORIZONTAL_END_GLYPH);
- }
-
- private void DrawVerticalShadow (Rectangle viewport)
- {
- // Draw the start glyph
- AddRune (0, 0, (Rune)VERTICAL_START_GLYPH);
-
- // Fill the rest of the rectangle with the glyph
- for (var i = 1; i < viewport.Height; i++)
- {
- AddRune (0, i, (Rune)VERTICAL_GLYPH);
- }
- }
-}
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Adornment/ShadowStyle.cs b/Terminal.Gui/View/Adornment/ShadowStyle.cs
new file mode 100644
index 000000000..e95d76d5b
--- /dev/null
+++ b/Terminal.Gui/View/Adornment/ShadowStyle.cs
@@ -0,0 +1,23 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Defines the style of shadow to be drawn on the right and bottom sides of the .
+///
+public enum ShadowStyle
+{
+ ///
+ /// No shadow.
+ ///
+ None,
+
+ ///
+ /// A shadow that is drawn using block elements. Ideal for smaller views such as buttons.
+ ///
+ Opaque,
+
+ ///
+ /// A shadow that is drawn using the underlying text with a darker background. Ideal for larger views such as windows.
+ ///
+ Transparent
+}
diff --git a/Terminal.Gui/View/Adornment/ShadowView.cs b/Terminal.Gui/View/Adornment/ShadowView.cs
new file mode 100644
index 000000000..b0480c23f
--- /dev/null
+++ b/Terminal.Gui/View/Adornment/ShadowView.cs
@@ -0,0 +1,140 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Draws a shadow on the right or bottom of the view. Used internally by .
+///
+internal class ShadowView : View
+{
+ // TODO: Add these to CM.Glyphs
+ private readonly char VERTICAL_START_GLYPH = '\u258C'; // Half: '\u2596';
+ private readonly char VERTICAL_GLYPH = '\u258C';
+ private readonly char HORIZONTAL_START_GLYPH = '\u2580'; // Half: '\u259d';
+ private readonly char HORIZONTAL_GLYPH = '\u2580';
+ private readonly char HORIZONTAL_END_GLYPH = '\u2598';
+
+ ///
+ public override Attribute GetNormalColor ()
+ {
+ if (SuperView is Adornment adornment)
+ {
+ Attribute attr = Attribute.Default;
+ if (adornment.Parent.SuperView is { })
+ {
+ attr = adornment.Parent.SuperView.GetNormalColor ();
+ }
+ else
+ {
+ attr = Application.Top.GetNormalColor ();
+ }
+ return new (new Attribute (ShadowStyle == ShadowStyle.Opaque ? Color.Black : attr.Foreground.GetDarkerColor (),
+ ShadowStyle == ShadowStyle.Opaque ? attr.Background : attr.Background.GetDarkerColor()));
+ }
+
+ return base.GetNormalColor ();
+ }
+
+ ///
+ public override void OnDrawContent (Rectangle viewport)
+ {
+ //base.OnDrawContent (viewport);
+ switch (ShadowStyle)
+ {
+ case ShadowStyle.Opaque:
+ if (Orientation == Orientation.Vertical)
+ {
+ DrawVerticalShadowOpaque (viewport);
+ }
+ else
+ {
+ DrawHorizontalShadowOpaque (viewport);
+ }
+
+ break;
+
+ case ShadowStyle.Transparent:
+ //Attribute prevAttr = Driver.GetAttribute ();
+ //var attr = new Attribute (prevAttr.Foreground, prevAttr.Background);
+ //Driver.SetAttribute (attr);
+
+ if (Orientation == Orientation.Vertical)
+ {
+ DrawVerticalShadowTransparent (viewport);
+ }
+ else
+ {
+ DrawHorizontalShadowTransparent (viewport);
+ }
+
+ //Driver.SetAttribute (prevAttr);
+
+ break;
+ }
+ }
+
+ ///
+ /// Gets or sets the orientation of the shadow.
+ ///
+ public Orientation Orientation { get; set; }
+
+ private ShadowStyle _shadowStyle;
+ public override ShadowStyle ShadowStyle
+ {
+ get => _shadowStyle;
+ set
+ {
+ Visible = value != ShadowStyle.None;
+ _shadowStyle = value;
+ }
+ }
+
+ private void DrawHorizontalShadowOpaque (Rectangle rectangle)
+ {
+ // Draw the start glyph
+ AddRune (0, 0, (Rune)HORIZONTAL_START_GLYPH);
+
+ // Fill the rest of the rectangle with the glyph
+ for (var i = 1; i < rectangle.Width - 1; i++)
+ {
+ AddRune (i, 0, (Rune)HORIZONTAL_GLYPH);
+ }
+
+ // Last is special
+ AddRune (rectangle.Width - 1, 0, (Rune)HORIZONTAL_END_GLYPH);
+ }
+
+ private void DrawHorizontalShadowTransparent (Rectangle viewport)
+ {
+ Rectangle screen = ViewportToScreen (viewport);
+
+ for (int i = screen.X; i < screen.X + screen.Width - 1; i++)
+ {
+ Driver.Move (i, screen.Y);
+ Driver.AddRune (Driver.Contents [screen.Y, i].Rune);
+ }
+ }
+
+ private void DrawVerticalShadowOpaque (Rectangle viewport)
+ {
+ // Draw the start glyph
+ AddRune (0, 0, (Rune)VERTICAL_START_GLYPH);
+
+ // Fill the rest of the rectangle with the glyph
+ for (var i = 1; i < viewport.Height; i++)
+ {
+ AddRune (0, i, (Rune)VERTICAL_GLYPH);
+ }
+ }
+
+ private void DrawVerticalShadowTransparent (Rectangle viewport)
+ {
+ Rectangle screen = ViewportToScreen (viewport);
+
+ // Fill the rest of the rectangle with the glyph
+ for (int i = screen.Y; i < screen.Y + viewport.Height; i++)
+ {
+ Driver.Move (screen.X, i);
+ Driver.AddRune (Driver.Contents [i, screen.X].Rune);
+ }
+ }
+}
diff --git a/Terminal.Gui/View/ViewAdornments.cs b/Terminal.Gui/View/ViewAdornments.cs
index a34cc65a7..27223ef11 100644
--- a/Terminal.Gui/View/ViewAdornments.cs
+++ b/Terminal.Gui/View/ViewAdornments.cs
@@ -1,4 +1,5 @@
using System.ComponentModel;
+using System.Text.Json.Serialization;
namespace Terminal.Gui;
@@ -59,11 +60,7 @@ public partial class View
///
public Margin Margin { get; private set; }
- [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- public static bool DefaultShadow { get; set; } = false;
-
-
- private bool _shadow;
+ private ShadowStyle _shadowStyle;
///
/// Gets or sets whether the View is shown with a shadow effect. The shadow is drawn on the right and bottom sides of the
/// Margin.
@@ -72,19 +69,19 @@ public partial class View
/// Setting this property to will add a shadow to the right and bottom sides of the Margin.
/// The View 's will be expanded to include the shadow.
///
- public bool Shadow
+ public virtual ShadowStyle ShadowStyle
{
- get => _shadow;
+ get => _shadowStyle;
set
{
- if (_shadow == value)
+ if (_shadowStyle == value)
{
return;
}
- _shadow = value;
+ _shadowStyle = value;
if (Margin is { })
{
- _shadow = Margin.EnableShadow (value);
+ Margin.ShadowStyle = value;
}
}
}
diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs
index 5a93405e2..98e299c4c 100644
--- a/Terminal.Gui/Views/Button.cs
+++ b/Terminal.Gui/Views/Button.cs
@@ -5,6 +5,8 @@
// Miguel de Icaza (miguel@gnome.org)
//
+using System.Text.Json.Serialization;
+
namespace Terminal.Gui;
/// Button is a that provides an item that invokes raises the event.
@@ -37,7 +39,9 @@ public class Button : View
/// Gets or sets whether s are shown with a shadow effect by default.
///
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- public new static bool DefaultShadow { get; set; } = false;
+ [JsonConverter (typeof (JsonStringEnumConverter))]
+
+ public static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.Opaque;
/// Initializes a new instance of .
public Button ()
@@ -72,7 +76,7 @@ public class Button : View
TitleChanged += Button_TitleChanged;
MouseClick += Button_MouseClick;
- Shadow = DefaultShadow;
+ ShadowStyle = DefaultShadow;
}
private bool _wantContinuousButtonPressed;
diff --git a/Terminal.Gui/Views/Dialog.cs b/Terminal.Gui/Views/Dialog.cs
index b0ee0169a..f6f670fcc 100644
--- a/Terminal.Gui/Views/Dialog.cs
+++ b/Terminal.Gui/Views/Dialog.cs
@@ -42,16 +42,23 @@ public class Dialog : Window
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
public static int DefaultMinimumHeight { get; set; } = 25;
- // TODO: Reenable once border/borderframe design is settled
+
+ ///
+ /// Gets or sets whether all s are shown with a shadow effect by default.
+ ///
+ [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
+ public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.Transparent;
+
///
/// Defines the default border styling for . Can be configured via
/// .
///
- //[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- //public static Border DefaultBorder { get; set; } = new Border () {
- // LineStyle = LineStyle.Single,
- //};
+ [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
+ public new static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Rounded;
+
private readonly List