Move Mono.CompilerServices.SymbolWriter to build after 2.1 raw mscorlib
[mono.git] / mcs / class / System.Design / System.ComponentModel.Design / ComponentDesigner.cs
1 //
2 // System.ComponentModel.Design.ComponentDesigner
3 //
4 // Authors:
5 //        Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2006-2007 Ivan N. Zlatev
8
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30
31 using System;
32 using System.Collections;
33 using System.ComponentModel;
34
35 namespace System.ComponentModel.Design
36 {
37
38 #if NET_2_0
39         public class ComponentDesigner : ITreeDesigner, IDesigner, IDisposable, IDesignerFilter, IComponentInitializer
40 #else
41         public class ComponentDesigner : IDesigner, IDisposable, IDesignerFilter
42 #endif
43         {
44
45 #region ShadowPropertyCollection
46
47                 protected sealed class ShadowPropertyCollection
48                 {
49
50                         private Hashtable _properties = null;
51                         private IComponent _component;
52
53                         internal ShadowPropertyCollection (IComponent component)
54                         {
55                                 _component = component;
56                         }
57
58                         // Returns Control's property value (if available) if there is no shadowed one.
59                         //
60                         public object this[string propertyName]
61                         {
62                                 get {
63                                         if (propertyName == null)
64                                                 throw new System.ArgumentNullException("propertyName");
65
66                                         if (_properties != null && _properties.ContainsKey (propertyName))
67                                                 return _properties[propertyName];
68
69                                         PropertyDescriptor property = TypeDescriptor.GetProperties (_component.GetType ())[propertyName];
70                                         if (property != null)
71                                                 return property.GetValue (_component);
72                                         else
73                                                 throw new System.Exception ("Propery not found!");
74                                 }
75                                 set {
76                                         if (_properties == null)
77                                                 _properties = new Hashtable ();
78                                         _properties[propertyName] = value;
79                                 }
80                         }
81
82                         public bool Contains (string propertyName)
83                         {
84                                 if (_properties != null)
85                                         return _properties.ContainsKey (propertyName);
86                                 else
87                                         return false;
88                         }
89
90                 } // ShadowPropertyCollection
91 #endregion
92
93                 public ComponentDesigner ()
94                 {
95                 }
96
97
98                 private IComponent _component;
99                 private DesignerVerbCollection _verbs;
100                 private ShadowPropertyCollection _shadowPropertyCollection;
101 #if NET_2_0
102                 private DesignerActionListCollection _designerActionList;
103 #endif
104
105                 // This property indicates any components to copy or move along with the component managed
106                 // by the designer during a copy, drag, or move operation.
107                 // If this collection contains references to other components in the current design mode document,
108                 // those components will be copied along with the component managed by the designer during a copy operation.
109                 // When the component managed by the designer is selected, this collection is filled with any nested controls.
110                 // This collection can also include other components, such as the buttons of a toolbar.
111                 //
112                 // supposedly contains all the children of the component, thus used for ITreeDesigner.Children
113                 //
114                 public virtual ICollection AssociatedComponents {
115                         get { return new IComponent[0]; }
116                 }
117
118                 public IComponent Component {
119                         get { return _component; }
120                 }
121
122                 public virtual DesignerVerbCollection Verbs {
123                         get {
124                                 if (_verbs == null)
125                                         _verbs = new DesignerVerbCollection ();
126
127                                 return _verbs;
128                         }
129                 }
130
131                 protected virtual InheritanceAttribute InheritanceAttribute {
132                         get {
133                                 IInheritanceService service = (IInheritanceService) this.GetService (typeof (IInheritanceService));
134                                 if (service != null)
135                                         return service.GetInheritanceAttribute (_component);
136                                 else
137                                         return InheritanceAttribute.Default;
138                         }
139                 }
140
141                 protected bool Inherited {
142                         get { return !this.InheritanceAttribute.Equals (InheritanceAttribute.NotInherited); }
143                 }
144
145                 //Gets a collection of property values that override user settings.
146                 //
147                 protected ShadowPropertyCollection ShadowProperties {
148                         get {
149                                 if (_shadowPropertyCollection == null) {
150                                         _shadowPropertyCollection = new ShadowPropertyCollection(_component);
151                                 }
152                                 return _shadowPropertyCollection;
153                         }
154                 }
155
156 #if NET_2_0
157                 public virtual DesignerActionListCollection ActionLists {
158                         get {
159                                 if (_designerActionList == null)
160                                         _designerActionList = new DesignerActionListCollection ();
161
162                                 return _designerActionList;
163                         }
164                 }
165
166                 protected virtual IComponent ParentComponent {
167                         get {
168                                 IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
169                                 if (host != null) {
170                                         IComponent rootComponent = host.RootComponent;
171                                         if (rootComponent != _component)
172                                                 return rootComponent;
173                                 }
174                                 return null;
175                         }
176                 }
177
178                 public virtual void InitializeNewComponent (IDictionary defaultValues)
179                 {
180                         // Reset
181                         //
182                         OnSetComponentDefaults ();
183                 }
184
185                 // MSDN: The default implementation of this method does nothing.
186                 //
187                 public virtual void InitializeExistingComponent (IDictionary defaultValues)
188                 {
189                         InitializeNonDefault ();
190                 }
191 #endif
192
193
194                 public virtual void Initialize (IComponent component)
195                 {
196                         if (component == null)
197                                 throw new ArgumentNullException ("component");
198                                                                 
199                         _component = component;
200                 }
201
202 #if NET_2_0
203                 [Obsolete ("This method has been deprecated. Use InitializeExistingComponent instead.")]
204 #endif
205                 public virtual void InitializeNonDefault ()
206                 {
207                 }
208
209
210                 // This method is called when a user double-clicks (the representation of) a component.
211                 // Tries to bind the default event to a method or creates a new one.
212                 // 
213                 public virtual void DoDefaultAction()
214                 {
215                         IDesignerHost host = (IDesignerHost) this.GetService(typeof(IDesignerHost));
216                         DesignerTransaction transaction = null;
217                         if (host != null)
218                                 transaction = host.CreateTransaction ("ComponentDesigner_AddEvent");
219
220                         IEventBindingService eventBindingService = GetService (typeof(IEventBindingService)) as IEventBindingService;
221                         EventDescriptor defaultEventDescriptor = null;
222
223                         if (eventBindingService != null) {
224                                 ISelectionService selectionService = this.GetService (typeof (ISelectionService)) as ISelectionService;
225                                 try {
226                                         if (selectionService != null) {
227                                                 ICollection selectedComponents = selectionService.GetSelectedComponents ();
228
229                                                 foreach (IComponent component in selectedComponents) {
230                                                         EventDescriptor eventDescriptor = TypeDescriptor.GetDefaultEvent (component);
231                                                         if (eventDescriptor != null) {
232                                                                 PropertyDescriptor eventProperty = eventBindingService.GetEventProperty (eventDescriptor);
233                                                                 if (eventProperty != null && !eventProperty.IsReadOnly) {
234                                                                         string methodName = eventProperty.GetValue (component) as string;
235                                                                         bool newMethod = true;
236
237                                                                         if (methodName != null || methodName != String.Empty) {
238                                                                                 ICollection compatibleMethods = eventBindingService.GetCompatibleMethods (eventDescriptor);
239                                                                                 foreach (string signature in compatibleMethods) {
240                                                                                         if (signature == methodName) {
241                                                                                                 newMethod = false;
242                                                                                                 break;
243                                                                                         }
244                                                                                 }
245                                                                         }
246                                                                         if (newMethod) {
247                                                                                 if (methodName == null)
248                                                                                         methodName = eventBindingService.CreateUniqueMethodName (component, eventDescriptor);
249                                                                                                                         
250                                                                                 eventProperty.SetValue (component, methodName);
251                                                                         }
252
253                                                                         if (component == _component)
254                                                                                 defaultEventDescriptor = eventDescriptor;
255                                                                 }
256                                                         }
257                                                 }
258
259                                         }
260                                 }
261                                 catch {
262                                         if (transaction != null) {
263                                                 transaction.Cancel ();
264                                                 transaction = null;
265                                         }
266                                 }
267                                 finally {
268                                         if (transaction != null)
269                                                 transaction.Commit ();
270                                 }
271
272                                 if (defaultEventDescriptor != null)
273                                         eventBindingService.ShowCode (_component, defaultEventDescriptor);
274                         }
275                 }
276
277
278
279 #if NET_2_0
280                 [Obsolete ("This method has been deprecated. Use InitializeNewComponent instead.")]
281 #endif
282                 // The default implementation of this method sets the default property of the component to
283                 // the name of the component if the default property is a string and the property is not already set.
284                 // This method can be implemented in a derived class to customize the initialization of the component
285                 // that this designer is designing.
286                 //
287                 public virtual void OnSetComponentDefaults ()
288                 {
289                         if (_component != null && _component.Site != null) {
290                                 PropertyDescriptor property = TypeDescriptor.GetDefaultProperty (_component);
291                                 if (property != null && property.PropertyType.Equals (typeof (string))) {
292                                         string propertyValue = (string)property.GetValue (_component);
293                                         if (propertyValue != null && propertyValue.Length != 0)
294                                                 property.SetValue (_component, _component.Site.Name);
295                                 }
296                         }
297                 }
298
299
300
301
302                 protected InheritanceAttribute InvokeGetInheritanceAttribute (ComponentDesigner toInvoke)
303                 {
304                         return toInvoke.InheritanceAttribute;
305                 }
306
307 #region IDesignerFilter
308
309                 // TypeDescriptor queries the component's site for ITypeDescriptorFilterService 
310                 // then invokes ITypeDescriptorFilterService.XXXX before retrieveing props/event/attributes, 
311                 // which then invokes the IDesignerFilter implementation of the component
312                 // 
313                 protected virtual void PostFilterAttributes (IDictionary attributes)
314                 {
315                 }
316
317                 protected virtual void PostFilterEvents (IDictionary events)
318                 {
319                 }
320
321                 protected virtual void PostFilterProperties (IDictionary properties)
322                 {
323                 }
324
325                 protected virtual void PreFilterAttributes (IDictionary attributes)
326                 {
327                 }
328
329                 protected virtual void PreFilterEvents (IDictionary events)
330                 {
331                 }
332
333                 protected virtual void PreFilterProperties (IDictionary properties)
334                 {
335                 }
336 #endregion
337
338                 protected void RaiseComponentChanged (MemberDescriptor member, object oldValue, object newValue)
339                 {
340                         IComponentChangeService service = GetService (typeof (IComponentChangeService)) as IComponentChangeService;
341                         if (service != null)
342                                 service.OnComponentChanged (_component, member, oldValue, newValue);
343                 }
344
345                 protected void RaiseComponentChanging (MemberDescriptor member)
346                 {
347                         IComponentChangeService service = GetService (typeof (IComponentChangeService)) as IComponentChangeService;
348                         if (service != null)
349                                 service.OnComponentChanging (_component, member);
350                 }
351
352 #region Implementation of IDesignerFilter
353
354                 void IDesignerFilter.PostFilterAttributes (IDictionary attributes)
355                 {
356                         PostFilterAttributes (attributes);
357                 }
358
359                 void IDesignerFilter.PostFilterEvents (IDictionary events)
360                 {
361                         PostFilterEvents (events);
362                 }
363
364                 void IDesignerFilter.PostFilterProperties (IDictionary properties)
365                 {
366                         PostFilterProperties (properties);
367                 }
368
369                 void IDesignerFilter.PreFilterAttributes (IDictionary attributes)
370                 {
371                         PreFilterAttributes (attributes);
372                 }
373
374                 void IDesignerFilter.PreFilterEvents (IDictionary events)
375                 {
376                         PreFilterEvents (events);
377                 }
378
379                 void IDesignerFilter.PreFilterProperties (IDictionary properties)
380                 {
381                         PreFilterProperties (properties);
382                 }
383
384 #endregion
385
386 #if NET_2_0
387
388 #region ITreeDesigner
389                 // Returns a collection of the designers of the associated components
390                 //
391                 ICollection ITreeDesigner.Children {
392                         get {
393                                 ICollection components = this.AssociatedComponents;
394                                 IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
395                                 
396                                 if (host != null) {
397                                         ArrayList designers = new ArrayList ();
398                                         foreach (IComponent component in components) {
399                                                 IDesigner designer = host.GetDesigner (component);
400                                                 if (designer != null)
401                                                         designers.Add (designer);
402                                         }
403                                         IDesigner[] result = new IDesigner[designers.Count];
404                                         designers.CopyTo (result);
405                                         return result;
406                                 }
407                                 return new IDesigner[0];
408                         }
409                 }
410
411                 IDesigner ITreeDesigner.Parent {
412                         get {
413                                 IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
414                                 if (host != null && this.ParentComponent != null)
415                                         return host.GetDesigner (this.ParentComponent);
416         
417                                 return null;
418                         }
419                 }
420 #endregion
421
422 #endif
423                 // Helper method - not an ISerivceProvider
424                 //
425                 protected virtual object GetService (Type service)
426                 {
427                         if (_component != null && _component.Site != null)
428                                 return _component.Site.GetService (service);
429
430                         return null;
431                 }
432
433                 public void Dispose ()
434                 {
435                         this.Dispose (true);
436                         GC.SuppressFinalize (this);
437                 }
438
439
440                 protected virtual void Dispose (bool disposing)
441                 {
442                         if (disposing)
443                                 _component = null;
444                 }
445
446                 ~ComponentDesigner ()
447                 {
448                         this.Dispose (false);
449                 }
450         }
451 }