156 lines
5.0 KiB
C#
156 lines
5.0 KiB
C#
|
|
using System.ComponentModel;
|
|||
|
|
|
|||
|
|
namespace UnshackleGUI
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// This is the object assigned to PropertyGrid.SelectedObject
|
|||
|
|
/// It correctly implements ICustomTypeDescriptor.
|
|||
|
|
/// </summary>
|
|||
|
|
public class DynamicObject : ICustomTypeDescriptor
|
|||
|
|
{
|
|||
|
|
private readonly Dictionary<string, object> _values;
|
|||
|
|
private readonly List<UnshackleParameter> _defs;
|
|||
|
|
|
|||
|
|
public DynamicObject(Dictionary<string, object> values, List<UnshackleParameter> defs)
|
|||
|
|
{
|
|||
|
|
_values = values;
|
|||
|
|
_defs = defs;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public PropertyDescriptorCollection GetProperties()
|
|||
|
|
{
|
|||
|
|
return new DynamicCustomTypeDescriptor(_values, _defs).GetProperties();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
|
|||
|
|
{
|
|||
|
|
return GetProperties();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public object GetPropertyOwner(PropertyDescriptor pd) => this;
|
|||
|
|
|
|||
|
|
public AttributeCollection GetAttributes() => AttributeCollection.Empty;
|
|||
|
|
public string GetClassName() => nameof(DynamicObject);
|
|||
|
|
public string GetComponentName() => null;
|
|||
|
|
public TypeConverter GetConverter() => null;
|
|||
|
|
public EventDescriptor GetDefaultEvent() => null;
|
|||
|
|
public PropertyDescriptor GetDefaultProperty() => null;
|
|||
|
|
public object GetEditor(Type editorBaseType) => null;
|
|||
|
|
public EventDescriptorCollection GetEvents() => EventDescriptorCollection.Empty;
|
|||
|
|
public EventDescriptorCollection GetEvents(Attribute[] attributes) => EventDescriptorCollection.Empty;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
internal class DynamicCustomTypeDescriptor : CustomTypeDescriptor
|
|||
|
|
{
|
|||
|
|
private readonly Dictionary<string, object> _values;
|
|||
|
|
private readonly List<UnshackleParameter> _defs;
|
|||
|
|
private PropertyDescriptorCollection _cache;
|
|||
|
|
|
|||
|
|
public DynamicCustomTypeDescriptor(Dictionary<string, object> values, List<UnshackleParameter> defs)
|
|||
|
|
{
|
|||
|
|
_values = values;
|
|||
|
|
_defs = defs;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override PropertyDescriptorCollection GetProperties()
|
|||
|
|
{
|
|||
|
|
return GetProperties(null);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
|
|||
|
|
{
|
|||
|
|
if (_cache == null)
|
|||
|
|
{
|
|||
|
|
var props = new List<PropertyDescriptor>();
|
|||
|
|
|
|||
|
|
foreach (var def in _defs)
|
|||
|
|
{
|
|||
|
|
props.Add(new DynamicPropertyDescriptor(def, _values));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_cache = new PropertyDescriptorCollection(props.ToArray());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return _cache;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
internal class DynamicPropertyDescriptor : PropertyDescriptor
|
|||
|
|
{
|
|||
|
|
private readonly UnshackleParameter _parameter;
|
|||
|
|
private readonly Dictionary<string, object> _values;
|
|||
|
|
|
|||
|
|
public DynamicPropertyDescriptor(UnshackleParameter parameter, Dictionary<string, object> values)
|
|||
|
|
: base(parameter.Name, null)
|
|||
|
|
{
|
|||
|
|
_parameter = parameter;
|
|||
|
|
_values = values;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override string Category => _parameter.Category;
|
|||
|
|
|
|||
|
|
// IMPORTANT FIX
|
|||
|
|
public override Type ComponentType => typeof(object);
|
|||
|
|
|
|||
|
|
public override bool IsReadOnly => false;
|
|||
|
|
|
|||
|
|
public override Type PropertyType =>
|
|||
|
|
_parameter.Type switch
|
|||
|
|
{
|
|||
|
|
"Bool" => typeof(bool),
|
|||
|
|
"Number" => typeof(int),
|
|||
|
|
_ => typeof(string)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
public override TypeConverter Converter =>
|
|||
|
|
(_parameter.Type == "Selection" && _parameter.Options != null)
|
|||
|
|
? new StandardValuesConverter(_parameter.Options)
|
|||
|
|
: base.Converter;
|
|||
|
|
|
|||
|
|
public override object GetValue(object component)
|
|||
|
|
{
|
|||
|
|
return _values.ContainsKey(_parameter.Name)
|
|||
|
|
? _values[_parameter.Name]
|
|||
|
|
: _parameter.Default;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void SetValue(object component, object value)
|
|||
|
|
{
|
|||
|
|
_values[_parameter.Name] = value;
|
|||
|
|
|
|||
|
|
OnValueChanged(component, EventArgs.Empty);
|
|||
|
|
|
|||
|
|
// Force grid refresh
|
|||
|
|
TypeDescriptor.Refresh(component);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override bool CanResetValue(object component) => true;
|
|||
|
|
|
|||
|
|
public override void ResetValue(object component)
|
|||
|
|
{
|
|||
|
|
_values[_parameter.Name] = _parameter.Default;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override bool ShouldSerializeValue(object component) => true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
internal class StandardValuesConverter : TypeConverter
|
|||
|
|
{
|
|||
|
|
private readonly List<string> _values;
|
|||
|
|
|
|||
|
|
public StandardValuesConverter(List<string> values)
|
|||
|
|
{
|
|||
|
|
_values = values;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override bool GetStandardValuesSupported(ITypeDescriptorContext context) => true;
|
|||
|
|
|
|||
|
|
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) => true;
|
|||
|
|
|
|||
|
|
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
|
|||
|
|
{
|
|||
|
|
return new StandardValuesCollection(_values);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|