[reflection] Coop handles icalls in System.Reflection and System.RuntimeTypeHandle...
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / View / TypeKeyValue.cs
1 namespace System.Activities.Presentation.View
2 {
3     using System;
4     using System.Collections.ObjectModel;
5     using System.ComponentModel;
6     using System.Windows;
7     using System.Windows.Automation.Peers;
8     using System.Windows.Input;
9
10     //helper class, used to resolve generics. supports cascading generic type arguments (i.e. IList< IList < int > >)
11     internal class TypeKeyValue : INotifyPropertyChanged
12     {
13         string errorText;
14         //generic type
15         Type genericType;
16
17         bool isValid = true;
18         //generic's type generic parameters
19         ObservableCollection<TypeKeyValue> subTypes = new ObservableCollection<TypeKeyValue>();
20         //target type
21         Type targetType;
22         //type resolver reference
23         Action<TypeKeyValue> typeChangedCallBack;
24         //if this type is selected
25         bool isSelected;
26         Func<Type, bool> filter;
27         ObservableCollection<Type> mostRecentlyUsedTypes;
28         string hintText = null;
29         //if type presenter should skip the drop down list
30         bool browseTypeDirectly = true;
31
32         public TypeKeyValue(Type genericType, Action<TypeKeyValue> typeChangedCallBack)
33         {
34             this.GenericType = genericType;
35             this.typeChangedCallBack = typeChangedCallBack;
36         }
37
38         public event PropertyChangedEventHandler PropertyChanged;
39
40         public string ErrorText
41         {
42             get { return this.errorText; }
43             set
44             {
45                 this.errorText = value;
46                 OnPropertyChanged("ErrorText");
47             }
48         }
49
50         public Type GenericType
51         {
52             get { return this.genericType; }
53             set
54             {
55                 this.genericType = value;
56                 OnPropertyChanged("GenericType");
57             }
58         }
59
60         public bool IsSelected
61         {
62             get { return this.isSelected; }
63             set
64             {
65                 this.isSelected = value;
66                 OnPropertyChanged("IsSelected");
67             }
68         }
69
70         public Func<Type, bool> Filter
71         {
72             get { return this.filter; }
73             set
74             {
75                 this.filter = value;
76                 OnPropertyChanged("Filter");
77             }
78         }
79
80         public ObservableCollection<Type> MostRecentlyUsedTypes
81         {
82             get { return this.mostRecentlyUsedTypes; }
83             set
84             {
85                 this.mostRecentlyUsedTypes = value;
86                 OnPropertyChanged("MostRecentlyUsedTypes");
87             }
88         }
89
90         public string HintText
91         {
92             get { return this.hintText; }
93             set
94             {
95                 this.hintText = value;
96                 this.OnPropertyChanged("HintText");
97             }
98         }
99
100         public bool BrowseTypeDirectly
101         {
102             get { return this.browseTypeDirectly; }
103             set
104             {
105                 this.browseTypeDirectly = value;
106                 OnPropertyChanged("BrowseTypeDirectly");
107             }
108         }
109
110         public bool IsValid
111         {
112             get { return this.isValid; }
113             set
114             {
115                 this.isValid = value;
116                 OnPropertyChanged("IsValid");
117             }
118         }
119
120
121         public ObservableCollection<TypeKeyValue> SubTypes
122         {
123             get { return this.subTypes; }
124         }
125
126         public Type TargetType
127         {
128             get { return this.targetType; }
129             set
130             {
131                 this.targetType = value;
132                 //whenever target type changes, check if there are some generic parameters required
133                 LoadGenericTypes();
134                 OnPropertyChanged("TargetType");
135                 if (typeChangedCallBack != null)
136                 {
137                     typeChangedCallBack(this);
138                 }
139             }
140         }
141
142         public Type GetConcreteType()
143         {
144             Type result = null;
145             if (null != this.targetType)
146             {
147                 //do we have generic?
148                 if (this.targetType.IsGenericTypeDefinition)
149                 {
150                     //resolve all generic arguments
151                     Type[] arguments = new Type[this.subTypes.Count];
152                     bool isValid = true;
153                     for (int i = 0; i < this.subTypes.Count && isValid; ++i)
154                     {
155                         arguments[i] = this.subTypes[i].GetConcreteType();
156                         isValid = (null != arguments[i]);
157                     }
158                     if (isValid)
159                     {
160                         //and create target type
161                         result = this.targetType.MakeGenericType(arguments);
162                     }
163                 }
164                 else
165                 {
166                     result = targetType;
167                 }
168             }
169             return result;
170         }
171
172         void LoadGenericTypes()
173         {
174             this.subTypes.Clear();
175             if (null != this.targetType && this.targetType.IsGenericTypeDefinition)
176             {
177                 Type[] generics = this.targetType.GetGenericArguments();
178                 foreach (Type t in generics)
179                 {
180                     TypeKeyValue entry = new TypeKeyValue(t, typeChangedCallBack);
181                     this.subTypes.Add(entry);
182                     typeChangedCallBack(entry);
183                 }
184             }
185         }
186
187         void OnPropertyChanged(string propertyName)
188         {
189             if (null != PropertyChanged)
190             {
191                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
192             }
193         }
194
195     }
196 }