blob: e8843db40e21c99c7099cb9cb9cb1006d23263bd [file] [log] [blame]
Zachary Turner1122be82016-09-07 18:28:55 +00001using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7
8namespace LLVM.ClangTidy
9{
10 /// <summary>
11 /// The goal of this class is to enable displaying of a PropertyGrid in much the
12 /// same way that Visual Studio's C++ project system does. A project or file can
13 /// have properties which might inherit from their parent, or be overridden.
14 /// It turns out this is somewhat non-trivial. The .NET PropertyGrid is good makes
15 /// displaying simple properties with a static notion of what constitutes a
16 /// "default" value very easy. You simply apply an Attribute to the class that says
17 /// what the default value is and you're done. But when you try to introduce the idea
18 /// that a property's default value depends on some other factor, things get much more
19 /// complicated due to the static nature of Attributes.
20 ///
21 /// The solution to this is to inherit from ICustomTypeDescriptor. This is the mechanism
22 /// by which you can inject or modify attributes or properties at runtime. The .NET
23 /// PropertyGrid is designed in such a way that instead of using simple .NET Reflection to
24 /// look for the properties and attributes on a class, it will invoke the methods of
25 /// ICustomTypeDescriptor (if your type inherits from it), and ask those methods. Our
26 /// implementation of ICustomTypeDescriptor works by waiting until the PropertyGrid requests
27 /// PropertyDescriptors for each of the properties, and then "decorating" them with our
28 /// own custom PropertyDescriptor implementation which understands the proeprty inheritance
29 /// model we wish to implement.
30 /// </summary>
31 public partial class DynamicPropertyComponent : Component, ICustomTypeDescriptor
32 {
33 PropertyDescriptorCollection DynamicProperties_ = new PropertyDescriptorCollection(null);
34 private DynamicPropertyComponent Parent_;
35
36 public DynamicPropertyComponent(DynamicPropertyComponent Parent)
37 {
38 Parent_ = Parent;
39 }
40
41 public DynamicPropertyComponent(DynamicPropertyComponent Parent, IContainer container)
42 {
43 Parent_ = Parent;
44
45 container.Add(this);
46 InitializeComponent();
47 }
48
49 public AttributeCollection GetAttributes()
50 {
51 return TypeDescriptor.GetAttributes(GetType());
52 }
53
54 public string GetClassName()
55 {
56 return TypeDescriptor.GetClassName(GetType());
57 }
58
59 public string GetComponentName()
60 {
61 return TypeDescriptor.GetComponentName(GetType());
62 }
63
64 public TypeConverter GetConverter()
65 {
66 return TypeDescriptor.GetConverter(GetType());
67 }
68
69 public EventDescriptor GetDefaultEvent()
70 {
71 return TypeDescriptor.GetDefaultEvent(GetType());
72 }
73
74 public PropertyDescriptor GetDefaultProperty()
75 {
76 return TypeDescriptor.GetDefaultProperty(GetType());
77 }
78
79 public object GetEditor(Type editorBaseType)
80 {
81 return TypeDescriptor.GetEditor(GetType(), editorBaseType);
82 }
83
84 public EventDescriptorCollection GetEvents()
85 {
86 return TypeDescriptor.GetEvents(GetType());
87 }
88
89 public EventDescriptorCollection GetEvents(Attribute[] attributes)
90 {
91 return TypeDescriptor.GetEvents(GetType(), attributes);
92 }
93
94 public PropertyDescriptorCollection GetProperties()
95 {
96 return DynamicProperties_;
97 }
98
99 public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
100 {
101 var Props = DynamicProperties_.OfType<PropertyDescriptor>();
102 var Filtered = Props.Where(x => x.Attributes.Contains(attributes)).ToArray();
103 return new PropertyDescriptorCollection(Filtered);
104 }
105
106 public object GetPropertyOwner(PropertyDescriptor pd)
107 {
108 return this;
109 }
110
111 public void SetDynamicValue<T>(string Name, T Value)
112 {
113 Name = Name.Replace('-', '_');
114 DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);
115 Descriptor.SetValue(this, Value);
116 }
117
118 public T GetDynamicValue<T>(string Name)
119 {
120 Name = Name.Replace('-', '_');
121 DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);
122 return (T)Descriptor.GetValue(this);
123 }
124
125 protected void AddDynamicProperty<T>(string Name, Attribute[] Attributes)
126 {
127 Name = Name.Replace('-', '_');
128
129 // If we have a parent, find the corresponding PropertyDescriptor with the same
130 // name from the parent.
131 DynamicPropertyDescriptor<T> ParentDescriptor = null;
132 if (Parent_ != null)
133 ParentDescriptor = (DynamicPropertyDescriptor<T>)Parent_.GetProperties().Find(Name, false);
134
135 DynamicProperties_.Add(new DynamicPropertyDescriptor<T>(Name, ParentDescriptor, Name, Attributes));
136 }
137 }
138}