using InABox.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace InABox.DynamicGrid { public interface IOptionControl { public string? GetValue(); public void SetValue(string value); public bool IsEmpty(); } public class ButtonsOptionControl : Grid, IOptionControl { private Action OnChanged; private class OptionButton : Border { public string Option { get; set; } private bool _selected { get; set; } public bool Selected { get => _selected; set { _selected = value; if (value == true) { Background = new SolidColorBrush(Colors.LightGray); } else if (value == false) { Background = new SolidColorBrush(Colors.DarkGray); } } } public OptionButton(string option, bool selected) { Option = option; Selected = selected; } } public ButtonsOptionControl(string[] options, Action onChanged) { OnChanged = onChanged; foreach (var option in options) { ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); var button = new OptionButton(option, false); var label = new Label() { Content = option.Replace("\r", "").Replace("\n", "") }; label.HorizontalContentAlignment = HorizontalAlignment.Center; label.VerticalContentAlignment = VerticalAlignment.Center; button.Child = label; button.Margin = new Thickness( Children.Count == 0 ? 0.0F : 2.5F, 0.0F, Children.Count == options.Length - 1 ? 0.0F : 2.5F, 0.0F ); button.Padding = new Thickness(5.0F, 0.0F, 5.0F, 0.0F); button.MouseUp += Button_MouseUp; button.SetValue(ColumnProperty, Children.Count); Children.Add(button); } } private void Button_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) { SelectButton((OptionButton)sender); OnChanged(); } private void SelectButton(OptionButton button) { foreach (var child in Children) { if (child is OptionButton childButton && childButton != button) { childButton.Selected = false; } } button.Selected = true; } public string? GetValue() { foreach (var child in Children) { if (child is OptionButton button) { if (button.Selected) { return button.Option; } } } return null; } public void SetValue(string value) { foreach (var child in Children) { if (child is OptionButton button) { if (button.Option == value) { SelectButton(button); } } } } public bool IsEmpty() => GetValue() == null; } public class RadioOptionControl : Grid, IOptionControl { private Action OnChanged; public RadioOptionControl(string[] options, Action onChanged) { Margin = new Thickness(4,2,4,2); OnChanged = onChanged; foreach (var option in options) { RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); var button = new RadioButton(); button.Margin = new Thickness(0, 2, 0, 2); button.Content = option.Replace("\r", "").Replace("\n", ""); button.VerticalContentAlignment = VerticalAlignment.Center; button.Padding = new Thickness(5.0F, 0.0F, 5.0F, 0.0F); button.SetValue(RowProperty, Children.Count); button.Tag = option; button.Checked += Button_Checked; button.Unchecked += Button_Checked; Children.Add(button); } } private void Button_Checked(object sender, RoutedEventArgs e) { OnChanged(); } public string? GetValue() { foreach (var child in Children) { if (child is RadioButton radio) { if (radio.IsChecked == true) { return radio.Tag as string; } } } return null; } public void SetValue(string value) { foreach (var child in Children) { if (child is RadioButton radio) { if ((string)radio.Tag == value) { radio.IsChecked = true; } } } } public bool IsEmpty() => GetValue() == null; } public class ComboBoxOptionControl : ComboBox, IOptionControl { private readonly Action OnChanged; public ComboBoxOptionControl(string[] options, Action onChanged) { SetResourceReference(StyleProperty, typeof(ComboBox)); OnChanged = onChanged; foreach (var option in options) Items.Add(option); VerticalContentAlignment = VerticalAlignment.Center; SelectionChanged += ComboBoxOptionControl_SelectionChanged; } private void ComboBoxOptionControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { OnChanged(); } public string? GetValue() { return SelectedValue as string; } public void SetValue(string value) { SelectedValue = value; } public bool IsEmpty() => GetValue() == null; } public class CheckBoxOptionControl : CheckBox, IOptionControl { private readonly Action OnChanged; private readonly string TrueValue; private readonly string FalseValue; public CheckBoxOptionControl(string trueValue, string falseValue, Action onChanged) { OnChanged = onChanged; TrueValue = trueValue; FalseValue = falseValue; IsThreeState = false; HorizontalContentAlignment = HorizontalAlignment.Center; VerticalContentAlignment = VerticalAlignment.Center; Checked += CheckBoxOptionControl_Checked; Unchecked += CheckBoxOptionControl_Checked; } private void CheckBoxOptionControl_Checked(object sender, RoutedEventArgs e) { OnChanged(); } public string? GetValue() { return IsChecked == true ? TrueValue : FalseValue; } public void SetValue(string value) { IsChecked = value == TrueValue; } public bool IsEmpty() => false; } public class DFOptionControl : DynamicFormFieldControl { private IOptionControl OptionControl = null!; // Late-initialised protected override FrameworkElement Create() { var options = string.IsNullOrWhiteSpace(Field.Properties.Options) ? new string[] { } : Field.Properties.Options.Replace(",","\n").Split('\n').Select(x=>x.Trim()).ToArray(); switch (Field.Properties.OptionType) { case DFLayoutOptionType.Buttons: return SetControl(new ButtonsOptionControl(options, ChangeField)); case DFLayoutOptionType.Radio: return SetControl(new RadioOptionControl(options, ChangeField)); } return SetControl(new ComboBoxOptionControl(options, ChangeField)); } private T SetControl(T value) where T : FrameworkElement, IOptionControl { OptionControl = value; return value; } public override void SetSerializedValue(string? value) { SetValue(value); } public override string? GetSerializedValue() { return OptionControl.GetValue(); } public override string GetValue() => OptionControl.GetValue() ?? ""; public override void SetValue(string? value) => OptionControl.SetValue(value ?? ""); protected override bool IsEmpty() => OptionControl.IsEmpty(); } }