using System; using System.Collections.Generic; using System.Linq; namespace InABox.Core { // When creating a new field with properties, make sure to override LoadProperties() and SaveProperties() public abstract class DFLayoutFieldProperties : DFLayoutObject { [EditorSequence(-999)] [CodeEditor(Editable = Editable.Enabled, ValidChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789")] public string Code { get; set; } [EditorSequence(-998)] [TextBoxEditor] public string Description { get; set; } [EditorSequence(-997)] [ComboLookupEditor(typeof(PropertyLookupGenerator))] public string Property { get; set; } [CheckBoxEditor] [EditorSequence(4)] public bool Required { get; set; } [CheckBoxEditor] [EditorSequence(5)] public bool Secure { get; set; } [CheckBoxEditor] [EditorSequence(6)] public bool Retain { get; set; } [CheckBoxEditor] [EditorSequence(7)] public bool Hidden { get; set; } [ExpressionEditor(null)] [EditorSequence(8)] public string Expression { get; set; } /// /// An expression that sets the field to have a background colour of its result. /// The result of the expression should be either a hex code like #rrggbb or #aarrggbb, or the string name of a , /// like 'Yellow'. /// [ExpressionEditor(null, ToolTip = "Evalutes to either a hex code (#RRGGBB or #AARRGGBB) or a colour name (like 'Red' or 'Yellow'), which sets the background colour for this variable.")] [EditorSequence(9)] public string ColourExpression { get; set; } public abstract string FormatValue(object? value); public abstract void Serialize(DFSaveStorageEntry entry, object? value); public abstract object? Deserialize(DFLoadStorageEntry entry); public abstract object? GetValue(object? value); public virtual IEnumerable GetAdditionalColumns() { return Enumerable.Empty(); } public virtual IEnumerable> GetAdditionalValues(object? value) { return Enumerable.Empty>(); } public abstract IEnumerable GetDisplayColumns(); public abstract IEnumerable> GetDisplayValues(object? value); protected override void LoadProperties() { Description = GetProperty(nameof(Description), ""); Property = GetProperty(nameof(Property), ""); Required = GetProperty(nameof(Required), false); Secure = GetProperty(nameof(Secure), false); Retain = GetProperty(nameof(Retain), false); Expression = GetProperty(nameof(Expression), ""); ColourExpression = GetProperty(nameof(ColourExpression), ""); } protected override void SaveProperties() { SetProperty(nameof(Description), Description); SetProperty(nameof(Property), Property); SetProperty(nameof(Required), Required); SetProperty(nameof(Secure), Secure); SetProperty(nameof(Retain), Retain); SetProperty(nameof(Expression), Expression); SetProperty(nameof(ColourExpression), ColourExpression); } private class PropertyLookupGenerator : LookupGenerator { public PropertyLookupGenerator(object[] items) : base(items) { } protected override void DoGenerateLookups() { var form = Items?.FirstOrDefault() as DigitalForm; if (form != null) { var type = CoreUtils.TypeList( AppDomain.CurrentDomain.GetAssemblies(), x => string.Equals(x.Name, form.AppliesTo) ).FirstOrDefault(); if (type != null) { var props = CoreUtils.PropertyList(type, x => true, true); foreach (var prop in props.Keys) { var info = CoreUtils.GetProperty(type, prop); var editor = info.GetEditor(); if (editor != null && editor.Editable.IsEditable()) { var bOK = true; if (prop.Contains(".")) { var comps = prop.Split('.').Reverse().Skip(1).Reverse().ToList(); while (comps.Count > 0) { var parent = string.Join(".", comps); comps.Remove(comps.Last()); try { var parentinfo = CoreUtils.GetProperty(type, parent); var parenteditor = parentinfo.GetEditor(); if (parenteditor is NullEditor) bOK = false; } catch (Exception e) { bOK = false; } } } if (bOK) AddValue(prop, prop); } } } } } } } public abstract class DFLayoutFieldProperties : DFLayoutFieldProperties { public DFLayoutFieldProperties() { Default = default; } [EditorSequence(-995)] public TValue Default { get; set; } protected override void LoadProperties() { base.LoadProperties(); Default = GetProperty("Default", default(TValue)); } protected override void SaveProperties() { base.SaveProperties(); SetProperty("Default", Default); } public sealed override void Serialize(DFSaveStorageEntry entry, object? value) { if(value is TSerialized ser) { SerializeValue(entry, ser); } } public sealed override object? Deserialize(DFLoadStorageEntry entry) { return DeserializeValue(entry); } public abstract void SerializeValue(DFSaveStorageEntry entry, TSerialized value); public abstract TSerialized DeserializeValue(DFLoadStorageEntry entry); public sealed override string FormatValue(object? value) { if (value is TSerialized ser) { return FormatValue(ser); } else { return ""; } } public abstract string FormatValue(TSerialized value); public sealed override object? GetValue(object? value) { if (value is TSerialized ser) { return GetValue(ser); } else { return null; } } public abstract TValue GetValue(TSerialized value); public sealed override IEnumerable> GetAdditionalValues(object? value) { if(value is TSerialized ser) { return GetAdditionalValues(ser); } return Enumerable.Empty>(); } public virtual IEnumerable> GetAdditionalValues(TSerialized value) { return Enumerable.Empty>(); } public override IEnumerable GetDisplayColumns() { yield return new CoreColumn { ColumnName = Code, DataType = typeof(TValue) }; foreach(var col in GetAdditionalColumns()) { yield return col; } } public sealed override IEnumerable> GetDisplayValues(object? value) { if (value is TSerialized ser) { return GetDisplayValues(ser); } return Enumerable.Empty>(); } public virtual IEnumerable> GetDisplayValues(TSerialized value) { yield return new KeyValuePair(Code, value); foreach (var pair in GetAdditionalValues(value)) { yield return pair; } } } }