#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace UICatalog.Scenarios;
///
/// Provides an editor UI for the Margin, Border, and Padding of a View.
///
public class PosEditor : EditorBase
{
public PosEditor ()
{
Title = "Pos";
Initialized += PosEditor_Initialized;
}
private int _value;
private OptionSelector? _posOptionSelector;
private TextField? _valueEdit;
protected override void OnUpdateLayoutSettings ()
{
Enabled = ViewToEdit is not Adornment;
if (ViewToEdit is null)
{
return;
}
Pos? pos;
if (Dimension == Dimension.Width)
{
pos = ViewToEdit.X;
}
else
{
pos = ViewToEdit.Y;
}
try
{
_posOptionSelector!.Value = _posNames.IndexOf (_posNames.First (s => pos.ToString ().Contains (s)));
}
catch (InvalidOperationException e)
{
// This is a hack to work around the fact that the Pos enum doesn't have an "Align" value yet
Debug.WriteLine ($"{e}");
}
_valueEdit!.Enabled = false;
switch (pos)
{
case PosPercent percent:
_valueEdit.Enabled = true;
_value = percent.Percent;
_valueEdit!.Text = _value.ToString ();
break;
case PosAbsolute absolute:
_valueEdit.Enabled = true;
_value = absolute.Position;
_valueEdit!.Text = _value.ToString ();
break;
case PosFunc func:
_valueEdit.Enabled = true;
_value = func.Fn (null);
_valueEdit!.Text = _value.ToString ();
break;
default:
_valueEdit!.Text = pos.ToString ();
break;
}
}
public Dimension Dimension { get; set; }
private void PosEditor_Initialized (object? sender, EventArgs e)
{
var label = new Label
{
X = 0, Y = 0,
Text = $"{Title}:"
};
Add (label);
_posOptionSelector = new () { X = 0, Y = Pos.Bottom (label), Labels = _optionLabels };
_posOptionSelector.ValueChanged += OnOptionSelectorOnValueChanged;
_valueEdit = new ()
{
X = Pos.Right (label) + 1,
Y = 0,
Width = Dim.Func (_ => _optionLabels.Max (i => i.GetColumns ()) - label.Frame.Width + 1),
Text = $"{_value}"
};
_valueEdit.Accepting += (s, args) =>
{
try
{
_value = int.Parse (_valueEdit.Text);
PosChanged ();
}
catch
{
// ignored
}
args.Handled = true;
};
Add (_valueEdit);
Add (_posOptionSelector);
}
private void OnOptionSelectorOnValueChanged (object? s, EventArgs selected) { PosChanged (); }
// These need to have same order
private readonly List _posNames = ["Absolute", "Align", "AnchorEnd", "Center", "Func", "Percent"];
private readonly string [] _optionLabels = ["Absolute(n)", "Align", "AnchorEnd", "Center", "Func(()=>n)", "Percent(n)"];
private void PosChanged ()
{
if (ViewToEdit == null || UpdatingLayoutSettings)
{
return;
}
try
{
Pos? pos = _posOptionSelector!.Value switch
{
0 => Pos.Absolute (_value),
1 => Pos.Align (Alignment.Start),
2 => new PosAnchorEnd (),
3 => Pos.Center (),
4 => Pos.Func (_ => _value),
5 => Pos.Percent (_value),
_ => Dimension == Dimension.Width ? ViewToEdit.X : ViewToEdit.Y
};
if (Dimension == Dimension.Width)
{
ViewToEdit.X = pos;
}
else
{
ViewToEdit.Y = pos;
}
SetNeedsLayout ();
}
catch (Exception e)
{
MessageBox.ErrorQuery (App, "Exception", e.Message, "Ok");
}
}
}