using System.ComponentModel;
using System.Text.Json.Serialization;
namespace Terminal.Gui;
public partial class View // Adornments
{
///
/// Initializes the Adornments of the View. Called by the constructor.
///
private void SetupAdornments ()
{
//// TODO: Move this to Adornment as a static factory method
if (this is not Adornment)
{
Margin = new (this);
Border = new (this);
Padding = new (this);
}
}
private void BeginInitAdornments ()
{
Margin?.BeginInit ();
Border?.BeginInit ();
Padding?.BeginInit ();
}
private void EndInitAdornments ()
{
Margin?.EndInit ();
Border?.EndInit ();
Padding?.EndInit ();
}
private void DisposeAdornments ()
{
Margin?.Dispose ();
Margin = null;
Border?.Dispose ();
Border = null;
Padding?.Dispose ();
Padding = null;
}
///
/// The that enables separation of a View from other SubViews of the same
/// SuperView. The margin offsets the from the .
///
///
///
/// The adornments (, , and ) are not part of the
/// View's content and are not clipped by the View's Clip Area.
///
///
/// Changing the size of an adornment (, , or ) will
/// change the size of and trigger to update the layout of the
/// and its .
///
///
public Margin Margin { get; private set; }
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.
///
///
/// 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 virtual ShadowStyle ShadowStyle
{
get => _shadowStyle;
set
{
if (_shadowStyle == value)
{
return;
}
_shadowStyle = value;
if (Margin is { })
{
Margin.ShadowStyle = value;
}
}
}
///
/// The that offsets the from the .
/// The Border provides the space for a visual border (drawn using
/// line-drawing glyphs) and the Title. The Border expands inward; in other words if `Border.Thickness.Top == 2` the
/// border and title will take up the first row and the second row will be filled with spaces.
///
///
/// provides a simple helper for turning a simple border frame on or off.
///
/// The adornments (, , and ) are not part of the
/// View's content and are not clipped by the View's Clip Area.
///
///
/// Changing the size of a frame (, , or ) will
/// change the size of the and trigger to update the layout of the
/// and its .
///
///
public Border Border { get; private set; }
/// Gets or sets whether the view has a one row/col thick border.
///
///
/// This is a helper for manipulating the view's . Setting this property to any value other
/// than is equivalent to setting 's
/// to `1` and to the value.
///
///
/// Setting this property to is equivalent to setting 's
/// to `0` and to .
///
/// For more advanced customization of the view's border, manipulate see directly.
///
public LineStyle BorderStyle
{
get => Border?.LineStyle ?? LineStyle.Single;
set
{
var old = Border?.LineStyle ?? LineStyle.None;
CancelEventArgs e = new (ref old, ref value);
OnBorderStyleChanging (e);
}
}
///
/// Called when the is changing. Invokes , which allows the event to be cancelled.
///
///
/// Override to prevent the from changing.
///
///
protected void OnBorderStyleChanging (CancelEventArgs e)
{
if (Border is null)
{
return;
}
BorderStyleChanging?.Invoke (this, e);
if (e.Cancel)
{
return;
}
SetBorderStyle (e.NewValue);
LayoutAdornments ();
SetNeedsLayout ();
return;
}
///
/// Sets the of the view to the specified value.
///
///
///
/// is a helper for manipulating the view's . Setting this property to any value other
/// than is equivalent to setting 's
/// to `1` and to the value.
///
///
/// Setting this property to is equivalent to setting 's
/// to `0` and to .
///
/// For more advanced customization of the view's border, manipulate see directly.
///
///
public virtual void SetBorderStyle (LineStyle value)
{
if (value != LineStyle.None)
{
if (Border.Thickness == Thickness.Empty)
{
Border.Thickness = new (1);
}
}
else
{
Border.Thickness = new (0);
}
Border.LineStyle = value;
}
///
/// Fired when the is changing. Allows the event to be cancelled.
///
public event EventHandler> BorderStyleChanging;
///
/// The inside of the view that offsets the
/// from the .
///
///
///
/// The adornments (, , and ) are not part of the
/// View's content and are not clipped by the View's Clip Area.
///
///
/// Changing the size of a frame (, , or ) will
/// change the size of the and trigger to update the layout of the
/// and its .
///
///
public Padding Padding { get; private set; }
///
/// Gets the thickness describing the sum of the Adornments' thicknesses.
///
///
///
/// The is offset from the by the thickness returned by this method.
///
///
/// A thickness that describes the sum of the Adornments' thicknesses.
public Thickness GetAdornmentsThickness ()
{
if (Margin is null)
{
return Thickness.Empty;
}
return Margin.Thickness + Border.Thickness + Padding.Thickness;
}
/// Lays out the Adornments of the View.
///
/// Overriden by to do nothing, as does not have adornments.
///
internal virtual void LayoutAdornments ()
{
if (Margin is null)
{
return; // CreateAdornments () has not been called yet
}
if (Margin.Frame.Size != Frame.Size)
{
Margin.SetFrame (Rectangle.Empty with { Size = Frame.Size });
Margin.X = 0;
Margin.Y = 0;
Margin.Width = Frame.Size.Width;
Margin.Height = Frame.Size.Height;
}
Margin.SetNeedsLayout ();
Margin.SetNeedsDisplay ();
if (IsInitialized)
{
Margin.LayoutSubviews ();
}
Rectangle border = Margin.Thickness.GetInside (Margin.Frame);
if (border != Border.Frame)
{
Border.SetFrame (border);
Border.X = border.Location.X;
Border.Y = border.Location.Y;
Border.Width = border.Size.Width;
Border.Height = border.Size.Height;
}
Border.SetNeedsLayout ();
Border.SetNeedsDisplay ();
if (IsInitialized)
{
Border.LayoutSubviews ();
}
Rectangle padding = Border.Thickness.GetInside (Border.Frame);
if (padding != Padding.Frame)
{
Padding.SetFrame (padding);
Padding.X = padding.Location.X;
Padding.Y = padding.Location.Y;
Padding.Width = padding.Size.Width;
Padding.Height = padding.Size.Height;
}
Padding.SetNeedsLayout ();
Padding.SetNeedsDisplay ();
if (IsInitialized)
{
Padding.LayoutSubviews ();
}
}
}