using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Xml.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Toolkit.Diagnostics; using Microsoft.Xna.Framework; namespace Barotrauma.LuaCs.Data; public class SettingList : SettingEntry, ISettingList where T : IEquatable, IConvertible { public class LFactory : ISettingBase.IFactory> { public ISettingList CreateInstance(IConfigInfo configInfo, Func, bool> valueChangePredicate) { Guard.IsNotNull(configInfo, nameof(configInfo)); return new SettingList(configInfo, valueChangePredicate); } } public SettingList(IConfigInfo configInfo, Func, bool> valueChangePredicate) : base(configInfo, valueChangePredicate) { if (!( typeof(T).IsEnum || typeof(T).IsPrimitive || typeof(T) == typeof(string))) { ThrowHelper.ThrowArgumentException($"{nameof(ISettingBase)}: The type of {nameof(T)} is not an allowed type."); } ValueChangePredicate = valueChangePredicate; var valuesElements = ConfigInfo.Element.GetChildElement("Values")?.GetChildElements("Value")?.ToImmutableArray(); Guard.IsNotNull(valuesElements, this.InternalName); if (valuesElements.Value.IsEmpty) { ThrowHelper.ThrowArgumentNullException($"{this.InternalName}: Could not find any values in list!"); } foreach (var element in valuesElements.Value) { if (!TryConvert(element, out var v1)) { ThrowHelper.ThrowArgumentException($"{this.InternalName}: Error while parsing list values"); } _valuesList.Add(v1); } if (TryConvert(ConfigInfo.Element, out var v) && _valuesList.Contains(v)) { Value = v; DefaultValue = v; } else { Value = _valuesList[0]; DefaultValue = _valuesList[0]; } bool TryConvert(XElement element, out T value) { try { value = (T)Convert.ChangeType(element.GetAttributeString("Value", null), typeof(T)); return true; } catch (Exception e) when (e is InvalidCastException or ArgumentNullException) { value = default(T); return false; } } } private readonly List _valuesList = new(); public override bool TrySetValue(T value) { if (!_valuesList.Contains(value)) { return false; } return base.TrySetValue(value); } public bool TrySetValueByIndex(int index) { throw new NotImplementedException(); } public IReadOnlyList Options => _valuesList.AsReadOnly(); public IReadOnlyList StringOptions => _valuesList.Select(e => e.ToString()).ToImmutableArray(); #if CLIENT public override void AddDisplayComponent(GUILayoutGroup layoutGroup, Vector2 relativeSize, Action onSerializedValue) { GUIUtil.Dropdown(layoutGroup, (T val) => val.ToString(), null, Options, Value, (T val) => { onSerializedValue?.Invoke(val.ToString()); }, new Vector2(relativeSize.X, 1f)); } #endif }