2006-11-28 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / class / System / System.ComponentModel / ReflectionPropertyDescriptor.cs
1 //
2 // System.ComponentModel.PropertyDescriptor.cs
3 //
4 // Author:
5 //  Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (C) Novell, Inc.  
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Collections;
33 using System.Reflection;
34 using System.Runtime.InteropServices;
35 using System.ComponentModel.Design;
36
37 namespace System.ComponentModel
38 {
39         internal class ReflectionPropertyDescriptor : PropertyDescriptor
40         {
41                 PropertyInfo _member;
42                 Type _componentType;
43                 
44                 public ReflectionPropertyDescriptor (Type componentType, PropertyDescriptor oldPropertyDescriptor, Attribute [] attributes)
45                 : base (oldPropertyDescriptor, attributes)
46                 {
47                         _componentType = componentType;
48                 }
49                                                          
50                 public ReflectionPropertyDescriptor (Type componentType, string name, Type type, Attribute [] attributes)
51                 : base (name, attributes)
52                 {
53                         _componentType = componentType;
54                 }
55                                                          
56                 public ReflectionPropertyDescriptor (PropertyInfo info)
57                 : base (info.Name, (Attribute[])info.GetCustomAttributes (true))
58                 {
59                         _member = info;
60                         _componentType = _member.DeclaringType;
61                 }
62                 
63                 PropertyInfo GetPropertyInfo ()
64                 {
65                         if (_member == null) {
66                                 _member = _componentType.GetProperty (Name);
67                                 if (_member == null)
68                                         throw new ArgumentException ("Accessor methods for the " + Name + " property are missing");
69                         }
70                         return _member;
71                 }               
72
73                 public override Type ComponentType 
74                 { 
75                         get { return _componentType; }
76                 }
77
78                 public override bool IsReadOnly 
79                 {
80                         get
81                         {
82                                 bool attr_ro = false;
83
84                                 ReadOnlyAttribute attrib = ((ReadOnlyAttribute) Attributes[typeof (ReadOnlyAttribute)]);
85                                 if (attrib != null)
86                                         attr_ro = attrib.IsReadOnly;
87
88                                 return !GetPropertyInfo ().CanWrite || attrib.IsReadOnly;
89                         }
90                 }
91
92                 public override Type PropertyType 
93                 {
94                         get
95                         {
96                                 return GetPropertyInfo ().PropertyType;
97                         }
98                 }
99                 
100                 public override object GetValue (object component)
101                 {
102                         return GetPropertyInfo ().GetValue (component, null);
103                 }
104                 
105                 DesignerTransaction CreateTransaction (object obj)
106                 {
107                         IComponent com = obj as IComponent;
108                         if (com == null || com.Site == null)
109                                 return null;
110                         
111                         IDesignerHost dh = (IDesignerHost) com.Site.GetService (typeof(IDesignerHost));
112                         if (dh == null)
113                                 return null;
114                         
115                         DesignerTransaction tran = dh.CreateTransaction ();
116                         IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
117                         if (ccs != null)
118                                 ccs.OnComponentChanging (com, this);
119                         return tran;
120                 }
121                 
122                 void EndTransaction (object obj, DesignerTransaction tran, object oldValue, object newValue, bool commit)
123                 {
124                         if (tran == null) {
125                                 // FIXME: EventArgs might be differen type.
126                                 OnValueChanged (obj, new PropertyChangedEventArgs (Name));
127                                 return;
128                         }
129                         
130                         if (commit) {
131                                 IComponent com = obj as IComponent;
132                                 IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
133                                 if (ccs != null)
134                                         ccs.OnComponentChanged (com, this, oldValue, newValue);
135                                 tran.Commit ();
136                                 // FIXME: EventArgs might be differen type.
137                                 OnValueChanged (obj, new PropertyChangedEventArgs (Name));
138                         } else
139                                 tran.Cancel ();
140                 }
141                 
142                 public override void SetValue (object component, object value)
143                 {
144                         DesignerTransaction tran = CreateTransaction (component);
145                         object old = GetValue (component);
146                         
147                         try {
148                                 GetPropertyInfo ().SetValue (component, value, null);
149                                 EndTransaction (component, tran, old, value, true);
150                         } catch {
151                                 EndTransaction (component, tran, old, value, false);
152                                 throw;
153                         }
154                 }
155
156                 public override void ResetValue (object component)
157                 {
158                         DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
159                         if (attrib != null) 
160                                 SetValue (component, attrib.Value); 
161                         
162                         DesignerTransaction tran = CreateTransaction (component);
163                         object old = GetValue (component);
164                         
165                         try {
166                                 MethodInfo mi = component.GetType().GetMethod ("Reset" + Name, Type.EmptyTypes);
167                                 if (mi != null)
168                                         mi.Invoke (component, null);
169                                 EndTransaction (component, tran, old, GetValue (component), true);
170                         } catch {
171                                 EndTransaction (component, tran, old, GetValue (component), false);
172                                 throw;
173                         }
174                 }
175
176                 public override bool CanResetValue (object component)
177                 {
178                         DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
179                         if (attrib != null) {
180                                 object current = GetValue (component);
181                                 if (attrib.Value == null || current == null){
182                                         if (attrib.Value != current)
183                                                 return true;
184                                         if (attrib.Value == null && current == null)
185                                                 return false;
186                                 }
187
188                                 return !attrib.Value.Equals (current);
189                         } else {
190                                 MethodInfo mi = component.GetType().GetMethod ("ShouldPersist" + Name, Type.EmptyTypes);
191                                 if (mi != null)
192                                         return (bool) mi.Invoke (component, null);
193                                 mi = component.GetType().GetMethod ("Reset" + Name, Type.EmptyTypes);
194                                 return mi != null;
195                         }
196                 }
197
198                 public override bool ShouldSerializeValue (object component)
199                 {
200                         DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
201                         if (attrib != null) {
202                                 object current = GetValue (component);
203                                 if ((attrib.Value == null || current == null) && attrib.Value != current)
204                                         return true;
205                                 return !attrib.Value.Equals (current);
206                         }
207                         else {
208                                 MethodInfo mi = component.GetType().GetMethod ("ShouldSerialize" + Name, Type.EmptyTypes);
209                                 if (mi != null)
210                                         return (bool) mi.Invoke (component, null);
211                                 return true;
212                         }
213                 }
214         }
215 }
216