2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[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 _type;
43                 Type _componentType;
44                 
45                 public ReflectionPropertyDescriptor (Type componentType, PropertyDescriptor oldPropertyDescriptor, Attribute [] attributes)
46                 : base (oldPropertyDescriptor, attributes)
47                 {
48                         _type = oldPropertyDescriptor.PropertyType;
49                         _componentType = componentType;
50                 }
51                                                          
52                 public ReflectionPropertyDescriptor (Type componentType, string name, Type type, Attribute [] attributes)
53                 : base (name, attributes)
54                 {
55                         _type = type;
56                         _componentType = componentType;
57                 }
58                                                          
59                 public ReflectionPropertyDescriptor (PropertyInfo info)
60                 : base (info.Name, (Attribute[])info.GetCustomAttributes (true))
61                 {
62                         _member = info;
63                         _componentType = _member.DeclaringType;
64                 }
65                 
66                 PropertyInfo GetPropertyInfo ()
67                 {
68                         if (_member == null) {
69                                 _member = _componentType.GetProperty (Name);
70                                 if (_member == null)
71                                         throw new ArgumentException ("Accessor methods for the " + Name + " property are missing");
72                         }
73                         return _member;
74                 }               
75
76                 public override Type ComponentType 
77                 { 
78                         get { return _componentType; }
79                 }
80
81                 public override bool IsReadOnly 
82                 {
83                         get
84                         {
85                                 return !GetPropertyInfo ().CanWrite;
86                         }
87                 }
88
89                 public override Type PropertyType 
90                 {
91                         get
92                         {
93                                 return GetPropertyInfo ().PropertyType;
94                         }
95                 }
96                 
97                 public override object GetValue (object component)
98                 {
99                         return GetPropertyInfo ().GetValue (component, null);
100                 }
101                 
102                 DesignerTransaction CreateTransaction (object obj)
103                 {
104                         Component com = obj as Component;
105                         if (com == null || com.Site == null) return null;
106                         
107                         IDesignerHost dh = (IDesignerHost) com.Site.GetService (typeof(IDesignerHost));
108                         if (dh == null) return null;
109                         
110                         DesignerTransaction tran = dh.CreateTransaction ();
111                         IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
112                         if (ccs != null)
113                                 ccs.OnComponentChanging (com, this);
114                         return tran;
115                 }
116                 
117                 void EndTransaction (object obj, DesignerTransaction tran, object oldValue, object newValue, bool commit)
118                 {
119                         if (tran == null) return;
120                         
121                         if (commit) {
122                                 Component com = obj as Component;
123                                 IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
124                                 if (ccs != null)
125                                         ccs.OnComponentChanged (com, this, oldValue, newValue);
126                                 tran.Commit ();
127                         }
128                         else
129                                 tran.Cancel ();
130                 }
131                 
132                 public override void SetValue (object component, object value)
133                 {
134                         DesignerTransaction tran = CreateTransaction (component);
135                         object old = GetValue (component);
136                         
137                         try
138                         {
139                                 GetPropertyInfo ().SetValue (component, value, null);
140                                 EndTransaction (component, tran, old, value, true);
141                         }
142                         catch
143                         {
144                                 EndTransaction (component, tran, old, value, false);
145                                 throw;
146                         }
147                 }
148
149                 public override void ResetValue (object component)
150                 {
151                         DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
152                         if (attrib != null) {
153                                 SetValue (component, attrib.Value); 
154                         }
155                         
156                         DesignerTransaction tran = CreateTransaction (component);
157                         object old = GetValue (component);
158                         
159                         try
160                         {
161                                 MethodInfo mi = component.GetType().GetMethod ("Reset" + Name, Type.EmptyTypes);
162                                 if (mi != null) mi.Invoke (component, null);
163                                 EndTransaction (component, tran, old, GetValue (component), true);
164                         }
165                         catch
166                         {
167                                 EndTransaction (component, tran, old, GetValue (component), false);
168                                 throw;
169                         }
170                 }
171
172                 public override bool CanResetValue (object component)
173                 {
174                         DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
175                         if (attrib != null) {
176                                 object current = GetValue (component);
177                                 if ((attrib.Value == null || current == null) && attrib.Value != current) return true;
178                                 return !attrib.Value.Equals (current);
179                         }
180                         else {
181                                 MethodInfo mi = component.GetType().GetMethod ("ShouldPersist" + Name, Type.EmptyTypes);
182                                 if (mi != null) return (bool) mi.Invoke (component, null);
183                                 mi = component.GetType().GetMethod ("Reset" + Name, Type.EmptyTypes);
184                                 return (mi != null);
185                         }
186                 }
187
188                 public override bool ShouldSerializeValue (object component)
189                 {
190                         DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
191                         if (attrib != null) {
192                                 object current = GetValue (component);
193                                 if ((attrib.Value == null || current == null) && attrib.Value != current) return true;
194                                 return !attrib.Value.Equals (current);
195                         }
196                         else {
197                                 MethodInfo mi = component.GetType().GetMethod ("ShouldSerialize" + Name, Type.EmptyTypes);
198                                 if (mi != null) return (bool) mi.Invoke (component, null);
199                                 return true;
200                         }
201                 }
202         }
203 }
204