using System.Text.Json.Serialization;
namespace Terminal.Gui;
///
/// The is a that by default is centered and contains
/// one or more s. It defaults to the Colors.ColorSchemes ["Dialog"] color scheme and has a
/// 1 cell padding around the edges.
///
///
/// To run the modally, create the , and pass it to
/// . This will execute the dialog until it terminates via the
/// [ESC] or [CTRL-Q] key, or when one of the views or buttons added to the dialog calls
/// .
///
public class Dialog : Window
{
// TODO: Reenable once border/borderframe design is settled
///
/// 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,
//};
private readonly List _buttons = new ();
///
/// Initializes a new instance of the class using
/// positioning with no s.
///
///
/// By default, and are set to Pos.Center () and
/// and are set to Width = Dim.Percent (85) , centering the
/// Dialog vertically and horizontally.
///
public Dialog ()
{
Arrangement = ViewArrangement.Movable;
X = Pos.Center ();
Y = Pos.Center ();
//ValidatePosDim = true;
Width = Dim.Percent (85);
Height = Dim.Percent (85);
ColorScheme = Colors.ColorSchemes ["Dialog"];
Modal = true;
ButtonAlignment = DefaultButtonAlignment;
ButtonAlignmentModes = DefaultButtonAlignmentModes;
AddCommand (
Command.QuitToplevel,
() =>
{
Canceled = true;
RequestStop ();
return true;
});
KeyBindings.Add (Key.Esc, Command.QuitToplevel);
}
private bool _canceled;
/// Gets a value indicating whether the was canceled.
/// The default value is .
public bool Canceled
{
get
{
#if DEBUG_IDISPOSABLE
if (WasDisposed)
{
throw new ObjectDisposedException (GetType ().FullName);
}
#endif
return _canceled;
}
set
{
#if DEBUG_IDISPOSABLE
if (WasDisposed)
{
throw new ObjectDisposedException (GetType ().FullName);
}
#endif
_canceled = value;
return;
}
}
// TODO: Update button.X = Pos.Justify when alignment changes
/// Determines how the s are aligned along the bottom of the dialog.
public Alignment ButtonAlignment { get; set; }
///
/// Gets or sets the alignment modes for the dialog's buttons.
///
public AlignmentModes ButtonAlignmentModes { get; set; }
/// Optional buttons to lay out at the bottom of the dialog.
public Button [] Buttons
{
get => _buttons.ToArray ();
init
{
if (value is null)
{
return;
}
foreach (Button b in value)
{
AddButton (b);
}
}
}
/// The default for .
/// This property can be set in a Theme.
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
[JsonConverter (typeof (JsonStringEnumConverter))]
public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End;
/// The default for .
/// This property can be set in a Theme.
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
[JsonConverter (typeof (JsonStringEnumConverter))]
public static AlignmentModes DefaultButtonAlignmentModes { get; set; } = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems;
///
/// Adds a to the , its layout will be controlled by the
///
///
/// Button to add.
public void AddButton (Button button)
{
if (button is null)
{
return;
}
// Use a distinct GroupId so users can use Pos.Align for other views in the Dialog
button.X = Pos.Align (ButtonAlignment, ButtonAlignmentModes, groupId: GetHashCode ());
button.Y = Pos.AnchorEnd ();
_buttons.Add (button);
Add (button);
SetNeedsDisplay ();
if (IsInitialized)
{
LayoutSubviews ();
}
}
///
//public override void LayoutSubviews ()
//{
// if (_inLayout)
// {
// return;
// }
// _inLayout = true;
// SetRelativeLayout(SuperView?.ContentSize ?? Driver.Screen.Size);
// LayoutButtons ();
// base.LayoutSubviews ();
// _inLayout = false;
//}
// Get the width of all buttons, not including any Margin.
internal int GetButtonsWidth ()
{
if (_buttons.Count == 0)
{
return 0;
}
//var widths = buttons.Select (b => b.TextFormatter.GetFormattedSize ().Width + b.BorderFrame.Thickness.Horizontal + b.Padding.Thickness.Horizontal);
IEnumerable widths = _buttons.Select (b => b.Frame.Width);
return widths.Sum ();
}
}