forked from OSchip/llvm-project
138 lines
5.2 KiB
C#
138 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace LLVM.ClangTidy
|
|
{
|
|
public class DynamicPropertyDescriptor<T> : PropertyDescriptor
|
|
{
|
|
T Value_;
|
|
DynamicPropertyDescriptor<T> Parent_;
|
|
bool IsInheriting_;
|
|
object Component_;
|
|
|
|
public DynamicPropertyDescriptor(object Component, DynamicPropertyDescriptor<T> Parent, string Name, Attribute[] Attrs)
|
|
: base(Name, Attrs)
|
|
{
|
|
foreach (DefaultValueAttribute Attr in Attrs.OfType<DefaultValueAttribute>())
|
|
{
|
|
Value_ = (T)Attr.Value;
|
|
}
|
|
Parent_ = Parent;
|
|
IsInheriting_ = true;
|
|
Component_ = Component;
|
|
}
|
|
|
|
public bool IsInheriting { get { return IsInheriting_; } set { IsInheriting_ = value; } }
|
|
public DynamicPropertyDescriptor<T> Parent { get { return Parent_; } }
|
|
|
|
/// <summary>
|
|
/// Determines whether this property's value should be considered "default" (e.g.
|
|
/// displayed in bold in the property grid). Root properties are unmodifiable and
|
|
/// always default. Non-root properties are default iff they are inheriting.
|
|
/// That is to say, if a property is explicitly set to False, the property should
|
|
/// be serialized even if the parent is also False. It would only not be serialized
|
|
/// if the user had explicitly chosen to inherit it.
|
|
/// </summary>
|
|
/// <param name="component"></param>
|
|
/// <returns></returns>
|
|
public override bool ShouldSerializeValue(object component)
|
|
{
|
|
return (Parent_ != null) && !IsInheriting;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the value back to the default. For root properties, this essentially does
|
|
/// nothing as they are read-only anyway. For non-root properties, this only means
|
|
/// that the property is now inheriting.
|
|
/// </summary>
|
|
/// <param name="component"></param>
|
|
public override void ResetValue(object component)
|
|
{
|
|
IsInheriting_ = true;
|
|
}
|
|
|
|
public override void SetValue(object component, object value)
|
|
{
|
|
// This is a bit of a trick. If the user chose the inheritance option from the
|
|
// dropdown, we will try to set the value to that string. So look for that and
|
|
// then just reset the value.
|
|
if (value.Equals(MagicInheritance.Text))
|
|
ResetValue(component);
|
|
else
|
|
{
|
|
// By explicitly setting the value, this property is no longer inheriting,
|
|
// even if the value the property is being set to is the same as that of
|
|
// the parent.
|
|
IsInheriting_ = false;
|
|
Value_ = (T)value;
|
|
}
|
|
}
|
|
|
|
public override TypeConverter Converter
|
|
{
|
|
get
|
|
{
|
|
// We need to return a DynamicPropertyConverter<> that can deal with our requirement
|
|
// to inject the inherit property option into the dropdown. But we still need to use
|
|
// the "real" converter to do the actual work for the underlying type. Therefore,
|
|
// we need to look for a TypeConverter<> attribute on the property, and if it is present
|
|
// forward an instance of that converter to the DynamicPropertyConverter<>. Otherwise,
|
|
// forward an instance of the default converter for type T to the DynamicPropertyConverter<>.
|
|
TypeConverter UnderlyingConverter = null;
|
|
var ConverterAttr = this.Attributes.OfType<TypeConverterAttribute>().LastOrDefault();
|
|
if (ConverterAttr != null)
|
|
{
|
|
Type ConverterType = Type.GetType(ConverterAttr.ConverterTypeName);
|
|
UnderlyingConverter = (TypeConverter)Activator.CreateInstance(ConverterType);
|
|
}
|
|
else
|
|
UnderlyingConverter = TypeDescriptor.GetConverter(typeof(T));
|
|
|
|
return new DynamicPropertyConverter<T>(this, UnderlyingConverter);
|
|
}
|
|
}
|
|
|
|
public override bool IsReadOnly
|
|
{
|
|
get
|
|
{
|
|
return (Parent_ == null);
|
|
}
|
|
}
|
|
|
|
public override Type ComponentType
|
|
{
|
|
get
|
|
{
|
|
return Component_.GetType();
|
|
}
|
|
}
|
|
|
|
public override object GetValue(object component)
|
|
{
|
|
// Return either this property's value or the parents value, depending on
|
|
// whether or not this property is inheriting.
|
|
if (IsInheriting_ && Parent != null)
|
|
return Parent.GetValue(component);
|
|
return Value_;
|
|
}
|
|
|
|
public override bool CanResetValue(object component)
|
|
{
|
|
return !IsReadOnly;
|
|
}
|
|
|
|
public override Type PropertyType
|
|
{
|
|
get
|
|
{
|
|
return typeof(T);
|
|
}
|
|
}
|
|
}
|
|
}
|