Merge pull request #1336 from esdrubal/datatablereadxmlschema
[mono.git] / mcs / class / System.Design / System.ComponentModel.Design / CollectionEditor.cs
1 //
2 // System.ComponentModel.Design.CollectionEditor
3 //
4 // Authors:
5 //      Martin Willemoes Hansen (mwh@sysrq.dk)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //      Ivan N. Zlatev (contact@i-nz.net)
8 // 
9 // (C) 2003 Martin Willemoes Hansen
10 // (C) 2007 Andreas Nahr
11 // (C) 2007 Ivan N. Zlatev
12 // (C) 2008 Novell, Inc
13 //
14
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36
37 using System;
38 using System.Reflection;
39 using System.Collections;
40 using System.ComponentModel;
41 using System.Drawing.Design;
42 using System.Windows.Forms;
43 using System.Windows.Forms.Design;
44
45 namespace System.ComponentModel.Design
46 {
47         public class CollectionEditor : UITypeEditor
48         {
49                 protected abstract class CollectionForm : Form
50                 {
51                         private CollectionEditor editor;
52                         private object editValue;
53
54                         public CollectionForm (CollectionEditor editor)
55                         {
56                                 this.editor = editor;
57                         }
58
59                         protected Type CollectionItemType
60                         {
61                                 get { return editor.CollectionItemType; }
62                         }
63
64                         protected Type CollectionType
65                         {
66                                 get { return editor.CollectionType; }
67                         }
68
69                         protected ITypeDescriptorContext Context
70                         {
71                                 get { return editor.Context; }
72                         }
73
74                         public object EditValue
75                         {
76                                 get { return editValue; }
77                                 set
78                                 {
79                                         editValue = value;
80                                         OnEditValueChanged ();
81                                 }
82                         }
83
84                         protected object[] Items
85                         {
86                                 get { return editor.GetItems (editValue); }
87                                 set {
88                                         if (editValue == null) {
89                                                 object newEmptyCollection = null;
90                                                 try {
91                                                         if (typeof (Array).IsAssignableFrom (CollectionType))
92                                                                 newEmptyCollection = Array.CreateInstance (CollectionItemType, 0);
93                                                         else
94                                                                 newEmptyCollection = Activator.CreateInstance (CollectionType);
95                                                 } catch {}
96
97                                                 object val = editor.SetItems (newEmptyCollection, value);
98                                                 if (val != newEmptyCollection)
99                                                         EditValue = val;
100                                         } else {
101                                                 object val = editor.SetItems (editValue, value);
102                                                 if (val != editValue)
103                                                         EditValue = val;
104                                         }
105                                 }
106                         }
107
108                         protected Type[] NewItemTypes
109                         {
110                                 get { return editor.NewItemTypes; }
111                         }
112
113                         protected bool CanRemoveInstance (object value)
114                         {
115                                 return editor.CanRemoveInstance (value);
116                         }
117
118                         protected virtual bool CanSelectMultipleInstances ()
119                         {
120                                 return editor.CanSelectMultipleInstances ();
121                         }
122
123                         protected object CreateInstance (Type itemType)
124                         {
125                                 return editor.CreateInstance (itemType);
126                         }
127
128                         protected void DestroyInstance (object instance)
129                         {
130                                 editor.DestroyInstance (instance);
131                         }
132
133                         protected virtual void DisplayError (Exception e)
134                         {
135                                 MessageBox.Show (e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
136                         }
137
138                         protected override object GetService (Type serviceType)
139                         {
140                                 return editor.GetService (serviceType);
141                         }
142
143                         protected abstract void OnEditValueChanged ();
144
145                         protected internal virtual DialogResult ShowEditorDialog (IWindowsFormsEditorService edSvc)
146                         {
147                                 return edSvc.ShowDialog (this);
148                         }
149                 }
150
151                 private class ConcreteCollectionForm : CollectionForm
152                 {
153                         internal class ObjectContainerConverter : TypeConverter
154                         {
155                                 private class ObjectContainerPropertyDescriptor : TypeConverter.SimplePropertyDescriptor
156                                 {
157                                         private AttributeCollection attributes;
158
159                                         public ObjectContainerPropertyDescriptor (Type componentType, Type propertyType)
160                                                 : base (componentType, "Value", propertyType)
161                                         {
162                                                 CategoryAttribute cat = new CategoryAttribute (propertyType.Name);
163                                                 attributes = new AttributeCollection (new Attribute[] { cat });
164                                         }
165
166                                         public override object GetValue (object component)
167                                         {
168                                                 ObjectContainer container = (ObjectContainer)component;
169                                                 return container.Object;
170                                         }
171
172                                         public override void SetValue (object component, object value)
173                                         {
174                                                 ObjectContainer container = (ObjectContainer)component;
175                                                 container.Object = value;
176                                         }
177
178                                         public override AttributeCollection Attributes
179                                         {
180                                                 get { return attributes; }
181                                         }
182                                 }
183
184                                 public override PropertyDescriptorCollection GetProperties (ITypeDescriptorContext context, object value, Attribute[] attributes)
185                                 {
186                                         ObjectContainer container = (ObjectContainer)value;
187                                         ObjectContainerPropertyDescriptor desc = new ObjectContainerPropertyDescriptor (value.GetType (), container.editor.CollectionItemType);
188                                         PropertyDescriptor[] properties = new PropertyDescriptor[] { desc };
189                                         PropertyDescriptorCollection pc = new PropertyDescriptorCollection (properties);
190                                         return pc;
191                                 }
192
193                                 public override bool GetPropertiesSupported (ITypeDescriptorContext context)
194                                 {
195                                         return true;
196                                 }
197                         }
198
199                         [TypeConverter (typeof (ObjectContainerConverter))]
200                         private class ObjectContainer
201                         {
202                                 internal object Object;
203                                 internal CollectionEditor editor;
204
205                                 public ObjectContainer (object obj, CollectionEditor editor)
206                                 {
207                                         this.Object = obj;
208                                         this.editor = editor;
209                                 }
210
211                                 internal string Name {
212                                         get { return editor.GetDisplayText (Object); }
213                                 }
214
215                                 public override string ToString ()
216                                 {
217                                         return Name;
218                                 }
219                         }
220
221                         private class UpdateableListbox : ListBox
222                         {
223                                 public void DoRefreshItem (int index)
224                                 {
225                                         base.RefreshItem (index);
226                                 }
227                         }
228
229                         private CollectionEditor editor;
230
231                         private System.Windows.Forms.Label labelMember;
232                         private System.Windows.Forms.Label labelProperty;
233                         private UpdateableListbox itemsList;
234                         private System.Windows.Forms.PropertyGrid itemDisplay;
235                         private System.Windows.Forms.Button doClose;
236                         private System.Windows.Forms.Button moveUp;
237                         private System.Windows.Forms.Button moveDown;
238                         private System.Windows.Forms.Button doAdd;
239                         private System.Windows.Forms.Button doRemove;
240                         private System.Windows.Forms.Button doCancel;
241                         private System.Windows.Forms.ComboBox addType;
242
243                         public ConcreteCollectionForm (CollectionEditor editor)
244                                 : base (editor)
245                         {
246                                 this.editor = editor;
247
248                                 this.labelMember = new System.Windows.Forms.Label ();
249                                 this.labelProperty = new System.Windows.Forms.Label ();
250                                 this.itemsList = new UpdateableListbox ();
251                                 this.itemDisplay = new System.Windows.Forms.PropertyGrid ();
252                                 this.doClose = new System.Windows.Forms.Button ();
253                                 this.moveUp = new System.Windows.Forms.Button ();
254                                 this.moveDown = new System.Windows.Forms.Button ();
255                                 this.doAdd = new System.Windows.Forms.Button ();
256                                 this.doRemove = new System.Windows.Forms.Button ();
257                                 this.doCancel = new System.Windows.Forms.Button ();
258                                 this.addType = new System.Windows.Forms.ComboBox ();
259                                 this.SuspendLayout ();
260                                 // 
261                                 // labelMember
262                                 // 
263                                 this.labelMember.Location = new System.Drawing.Point (12, 9);
264                                 this.labelMember.Size = new System.Drawing.Size (55, 13);
265                                 this.labelMember.Text = "Members:";
266                                 // 
267                                 // labelProperty
268                                 // 
269                                 this.labelProperty.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
270                                                         | System.Windows.Forms.AnchorStyles.Right)));
271                                 this.labelProperty.Location = new System.Drawing.Point (172, 9);
272                                 this.labelProperty.Size = new System.Drawing.Size (347, 13);
273                                 this.labelProperty.Text = "Properties:";
274                                 // 
275                                 // itemsList
276                                 // 
277                                 this.itemsList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
278                                                         | System.Windows.Forms.AnchorStyles.Left)));
279                                 this.itemsList.HorizontalScrollbar = true;
280                                 this.itemsList.Location = new System.Drawing.Point (12, 25);
281                                 this.itemsList.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
282                                 this.itemsList.Size = new System.Drawing.Size (120, 290);
283                                 this.itemsList.TabIndex = 0;
284                                 this.itemsList.SelectedIndexChanged += new System.EventHandler (this.itemsList_SelectedIndexChanged);
285                                 // 
286                                 // itemDisplay
287                                 // 
288                                 this.itemDisplay.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
289                                                         | System.Windows.Forms.AnchorStyles.Left)
290                                                         | System.Windows.Forms.AnchorStyles.Right)));
291                                 this.itemDisplay.HelpVisible = false;
292                                 this.itemDisplay.Location = new System.Drawing.Point (175, 25);
293                                 this.itemDisplay.Size = new System.Drawing.Size (344, 314);
294                                 this.itemDisplay.TabIndex = 6;
295                                 this.itemDisplay.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler (this.itemDisplay_PropertyValueChanged);
296                                 // 
297                                 // doClose
298                                 // 
299                                 this.doClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
300                                 this.doClose.Location = new System.Drawing.Point (341, 345);
301                                 this.doClose.Size = new System.Drawing.Size (86, 26);
302                                 this.doClose.TabIndex = 7;
303                                 this.doClose.Text = "OK";
304                                 this.doClose.Click += new System.EventHandler (this.doClose_Click);
305                                 // 
306                                 // moveUp
307                                 // 
308                                 this.moveUp.Location = new System.Drawing.Point (138, 25);
309                                 this.moveUp.Size = new System.Drawing.Size (31, 28);
310                                 this.moveUp.TabIndex = 4;
311                                 this.moveUp.Enabled = false;
312                                 this.moveUp.Text = "Up";
313                                 this.moveUp.Click += new System.EventHandler (this.moveUp_Click);
314                                 // 
315                                 // moveDown
316                                 // 
317                                 this.moveDown.Location = new System.Drawing.Point (138, 59);
318                                 this.moveDown.Size = new System.Drawing.Size (31, 28);
319                                 this.moveDown.TabIndex = 5;
320                                 this.moveDown.Enabled = false;
321                                 this.moveDown.Text = "Dn";
322                                 this.moveDown.Click += new System.EventHandler (this.moveDown_Click);
323                                 // 
324                                 // doAdd
325                                 // 
326                                 this.doAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
327                                 this.doAdd.Location = new System.Drawing.Point (12, 346);
328                                 this.doAdd.Size = new System.Drawing.Size (59, 25);
329                                 this.doAdd.TabIndex = 1;
330                                 this.doAdd.Text = "Add";
331                                 this.doAdd.Click += new System.EventHandler (this.doAdd_Click);
332                                 // 
333                                 // doRemove
334                                 // 
335                                 this.doRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
336                                 this.doRemove.Location = new System.Drawing.Point (77, 346);
337                                 this.doRemove.Size = new System.Drawing.Size (55, 25);
338                                 this.doRemove.TabIndex = 2;
339                                 this.doRemove.Text = "Remove";
340                                 this.doRemove.Click += new System.EventHandler (this.doRemove_Click);
341                                 // 
342                                 // doCancel
343                                 // 
344                                 this.doCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
345                                 this.doCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
346                                 this.doCancel.Location = new System.Drawing.Point (433, 345);
347                                 this.doCancel.Size = new System.Drawing.Size (86, 26);
348                                 this.doCancel.TabIndex = 8;
349                                 this.doCancel.Text = "Cancel";
350                                 this.doCancel.Click += new System.EventHandler (this.doCancel_Click);
351                                 // 
352                                 // addType
353                                 // 
354                                 this.addType.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
355                                 this.addType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
356                                 this.addType.Location = new System.Drawing.Point (12, 319);
357                                 this.addType.Size = new System.Drawing.Size (120, 21);
358                                 this.addType.TabIndex = 3;
359                                 // 
360                                 // DesignerForm
361                                 // 
362                                 this.AcceptButton = this.doClose;
363                                 this.CancelButton = this.doCancel;
364                                 this.ClientSize = new System.Drawing.Size (531, 381);
365                                 this.ControlBox = false;
366                                 this.Controls.Add (this.addType);
367                                 this.Controls.Add (this.doCancel);
368                                 this.Controls.Add (this.doRemove);
369                                 this.Controls.Add (this.doAdd);
370                                 this.Controls.Add (this.moveDown);
371                                 this.Controls.Add (this.moveUp);
372                                 this.Controls.Add (this.doClose);
373                                 this.Controls.Add (this.itemDisplay);
374                                 this.Controls.Add (this.itemsList);
375                                 this.Controls.Add (this.labelProperty);
376                                 this.Controls.Add (this.labelMember);
377                                 this.HelpButton = true;
378                                 this.MaximizeBox = false;
379                                 this.MinimizeBox = false;
380                                 this.MinimumSize = new System.Drawing.Size (400, 300);
381                                 this.ShowInTaskbar = false;
382                                 this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
383                                 this.ResumeLayout (false);
384
385 #if NET_2_0
386                                 if (editor.CollectionType.IsGenericType)
387                                         this.Text = editor.CollectionItemType.Name + " Collection Editor";
388                                 else
389                                         this.Text = editor.CollectionType.Name + " Collection Editor";
390 #else
391                                 this.Text = editor.CollectionType.Name + " Collection Editor";
392 #endif
393                                 foreach (Type type in editor.NewItemTypes)
394                                         addType.Items.Add (type.Name);
395                                 if (addType.Items.Count > 0)
396                                         addType.SelectedIndex = 0;
397                         }
398
399                         private void UpdateItems ()
400                         {
401                                 object[] items = editor.GetItems (EditValue);
402                                 if (items != null) {
403                                         itemsList.BeginUpdate ();
404                                         itemsList.Items.Clear ();
405                                         foreach (object o in items)
406                                                 this.itemsList.Items.Add (new ObjectContainer (o, editor));
407                                         if (itemsList.Items.Count > 0)
408                                                 itemsList.SelectedIndex = 0;
409                                         itemsList.EndUpdate ();
410                                 }
411                         }
412
413                         private void doClose_Click (object sender, EventArgs e)
414                         {
415                                 SetEditValue ();
416                                 this.Close ();
417                         }
418
419                         private void SetEditValue ()
420                         {
421                                 object[] items = new object[itemsList.Items.Count];
422                                 for (int i = 0; i < itemsList.Items.Count; i++)
423                                         items[i] = ((ObjectContainer)itemsList.Items[i]).Object;
424                                 this.Items = items;
425                         }
426
427                         private void doCancel_Click (object sender, EventArgs e)
428                         {
429                                 editor.CancelChanges ();
430                                 this.Close ();
431                         }
432
433                         private void itemsList_SelectedIndexChanged (object sender, EventArgs e)
434                         {
435                                 if (itemsList.SelectedIndex == -1) {
436                                         itemDisplay.SelectedObject = null;
437                                         return;
438                                 }
439
440                                 if (itemsList.SelectedIndex <= 0 || itemsList.SelectedItems.Count > 1)
441                                         moveUp.Enabled = false;
442                                 else
443                                         moveUp.Enabled = true;
444                                 if (itemsList.SelectedIndex > itemsList.Items.Count - 2 || itemsList.SelectedItems.Count > 1)
445                                         moveDown.Enabled = false;
446                                 else
447                                         moveDown.Enabled = true;
448
449                                 if (itemsList.SelectedItems.Count == 1)
450                                 {
451                                         ObjectContainer o = (ObjectContainer)itemsList.SelectedItem;
452                                         if (Type.GetTypeCode (o.Object.GetType ()) != TypeCode.Object)
453                                                 itemDisplay.SelectedObject = o;
454                                         else
455                                                 itemDisplay.SelectedObject = o.Object;
456                                 }
457                                 else
458                                 {
459                                         object[] items = new object[itemsList.SelectedItems.Count];
460                                         for (int i = 0; i < itemsList.SelectedItems.Count; i++)
461                                         {
462                                                 ObjectContainer o = (ObjectContainer)itemsList.SelectedItem;
463                                                 if (Type.GetTypeCode (o.Object.GetType ()) != TypeCode.Object)
464                                                         items[i] = ((ObjectContainer)itemsList.SelectedItems[i]);
465                                                 else
466                                                         items[i] = ((ObjectContainer)itemsList.SelectedItems[i]).Object;
467                                         }
468                                         itemDisplay.SelectedObjects = items;
469                                 }
470                                 labelProperty.Text = ((ObjectContainer)itemsList.SelectedItem).Name + " properties:";
471                         }
472
473                         private void itemDisplay_PropertyValueChanged (object sender, EventArgs e)
474                         {
475                                 int[] selected = new int[itemsList.SelectedItems.Count];
476                                 for (int i = 0; i < itemsList.SelectedItems.Count; i++)
477                                         selected[i] = itemsList.Items.IndexOf (itemsList.SelectedItems[i]);
478
479                                 // The list might be repopulated if a new instance of the collection edited
480                                 // is created during the update. This happen for example for Arrays.
481                                 SetEditValue ();
482
483                                 // Restore current selection in case the list gets repopulated.
484                                 // Refresh the item after that to reflect possible value change.
485                                 // 
486                                 itemsList.BeginUpdate ();
487                                 itemsList.ClearSelected ();
488                                 foreach (int index in selected) {
489                                         itemsList.DoRefreshItem (index);
490                                         itemsList.SetSelected (index, true);
491                                 }
492                                 itemsList.SelectedIndex = selected[0];
493                                 itemsList.EndUpdate ();
494                         }
495
496                         private void moveUp_Click (object sender, EventArgs e)
497                         {
498                                 if (itemsList.SelectedIndex <= 0)
499                                         return;
500
501                                 object selected = itemsList.SelectedItem;
502                                 int index = itemsList.SelectedIndex;
503                                 itemsList.Items.RemoveAt (index);
504                                 itemsList.Items.Insert (index - 1, selected);
505                                 itemsList.SelectedIndex = index - 1;
506                         }
507
508                         private void moveDown_Click (object sender, EventArgs e)
509                         {
510                                 if (itemsList.SelectedIndex > itemsList.Items.Count - 2)
511                                         return;
512
513                                 object selected = itemsList.SelectedItem;
514                                 int index = itemsList.SelectedIndex;
515                                 itemsList.Items.RemoveAt (index);
516                                 itemsList.Items.Insert (index + 1, selected);
517                                 itemsList.SelectedIndex = index + 1;
518                         }
519
520                         private void doAdd_Click (object sender, EventArgs e)
521                         {
522                                 object o;
523                                 try {
524                                         o = editor.CreateInstance (editor.NewItemTypes[addType.SelectedIndex]);
525                                 } catch (Exception ex) {
526                                         DisplayError (ex);
527                                         return;
528                                 }
529                                 itemsList.Items.Add (new ObjectContainer (o, editor));
530                                 itemsList.SelectedIndex = -1;
531                                 itemsList.SelectedIndex = itemsList.Items.Count - 1;
532                         }
533
534                         private void doRemove_Click (object sender, EventArgs e)
535                         {
536                                 if (itemsList.SelectedIndex != -1) {
537                                         int[] selected = new int[itemsList.SelectedItems.Count];
538                                         for (int i=0; i < itemsList.SelectedItems.Count; i++)
539                                                 selected[i] = itemsList.Items.IndexOf (itemsList.SelectedItems[i]);
540
541                                         for (int i = selected.Length - 1; i >= 0; i--)
542                                                 itemsList.Items.RemoveAt (selected[i]);
543
544                                         itemsList.SelectedIndex = Math.Min (selected[0], itemsList.Items.Count-1);
545                                 }
546                         }
547
548                         // OnEditValueChanged is called only if the  EditValue has changed,
549                         // which is only in the case when a new instance of the collection is 
550                         // required, e.g for arrays.
551                         // 
552                         protected override void OnEditValueChanged ()
553                         {
554                                 UpdateItems ();
555                         }
556                 }
557
558                 private Type type;
559                 private Type collectionItemType;
560                 private Type[] newItemTypes;
561                 private ITypeDescriptorContext context;
562                 private IServiceProvider provider;
563                 private IWindowsFormsEditorService editorService;
564
565                 public CollectionEditor (Type type)
566                 {
567                         this.type = type;
568                         this.collectionItemType = CreateCollectionItemType ();
569                         this.newItemTypes = CreateNewItemTypes ();
570                 }
571
572                 protected Type CollectionItemType
573                 {
574                         get { return collectionItemType; }
575                 }
576
577                 protected Type CollectionType
578                 {
579                         get { return type; }
580                 }
581
582                 protected ITypeDescriptorContext Context
583                 {
584                         get { return context; }
585                 }
586
587                 protected virtual string HelpTopic
588                 {
589                         get { return "CollectionEditor"; }
590                 }
591
592                 protected Type[] NewItemTypes
593                 {
594                         get { return newItemTypes; }
595                 }
596
597                 protected virtual void CancelChanges ()
598                 {
599                 }
600
601                 protected virtual bool CanRemoveInstance (object value)
602                 {
603                         return true;
604                 }
605
606                 protected virtual bool CanSelectMultipleInstances ()
607                 {
608                         return true;
609                 }
610
611                 protected virtual CollectionEditor.CollectionForm CreateCollectionForm ()
612                 {
613                         return new ConcreteCollectionForm (this);
614                 }
615
616                 protected virtual Type CreateCollectionItemType ()
617                 {
618                         PropertyInfo[] properties = type.GetProperties ();
619                         foreach (PropertyInfo property in properties)
620                                 if (property.Name == "Item")
621                                         return property.PropertyType;
622                         return typeof (object);
623                 }
624                 
625                 protected virtual object CreateInstance (Type itemType)
626                 {
627                         object instance = null;
628                         if (typeof (IComponent).IsAssignableFrom (itemType)) {
629                                 IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
630                                 if (host != null)
631                                         instance = host.CreateComponent (itemType);
632                         }
633
634                         if (instance == null) {
635 #if NET_2_0
636                                 instance = TypeDescriptor.CreateInstance (provider, itemType, null, null);
637 #else
638                                 instance =  Activator.CreateInstance (itemType);
639 #endif
640                         }
641                         return instance;
642                 }
643                 
644                 protected virtual Type[] CreateNewItemTypes ()
645                 {
646                         return new Type[] { collectionItemType };
647                 }
648
649                 protected virtual void DestroyInstance (object instance)
650                 {
651                         IComponent component = instance as IComponent;
652                         if (component != null) {
653                                 IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
654                                 if (host != null)
655                                         host.DestroyComponent (component);
656                         }
657                 }
658
659                 public override object EditValue (ITypeDescriptorContext context, IServiceProvider provider, object value)
660                 {
661                         this.context = context;
662                         this.provider = provider;
663
664                         if (context != null && provider != null)
665                         {
666                                 editorService = (IWindowsFormsEditorService)provider.GetService (typeof (IWindowsFormsEditorService));
667                                 if (editorService != null)
668                                 {
669                                         CollectionForm editorForm = CreateCollectionForm ();
670                                         editorForm.EditValue = value;
671                                         editorForm.ShowEditorDialog (editorService);
672                                         return editorForm.EditValue;
673                                 }
674                         }
675                         return base.EditValue (context, provider, value);
676                 }
677
678                 protected virtual string GetDisplayText (object value)
679                 {
680                         if (value == null)
681                                 return string.Empty;
682
683                         PropertyInfo nameProperty = value.GetType ().GetProperty ("Name");
684                         if (nameProperty != null)
685                         {
686                                 string data = (nameProperty.GetValue (value, null)) as string;
687                                 if (data != null)
688                                         if (data.Length != 0)
689                                                 return data;
690                         }
691
692                         if (Type.GetTypeCode (value.GetType ()) == TypeCode.Object)
693                                 return value.GetType ().Name;
694                         else
695                                 return value.ToString ();
696                 }
697
698                 public override UITypeEditorEditStyle GetEditStyle (ITypeDescriptorContext context)
699                 {
700                         return UITypeEditorEditStyle.Modal;
701                 }
702
703                 protected virtual object[] GetItems (object editValue)
704                 {
705                         if (editValue == null)
706                                 return new object[0];
707                         ICollection collection = editValue as ICollection;
708                         if (collection == null)
709                                 return new object[0];
710
711                         object[] result = new object[collection.Count];
712                         collection.CopyTo (result, 0);
713                         return result;
714                 }
715
716                 protected virtual IList GetObjectsFromInstance (object instance)
717                 {
718                         ArrayList list = new ArrayList ();
719                         list.Add (instance);
720                         return list;
721                 }
722
723                 protected object GetService (Type serviceType)
724                 {
725                         return context.GetService (serviceType);
726                 }
727
728                 protected virtual object SetItems (object editValue, object[] value)
729                 {
730                         IList list = (IList) editValue;
731                         if (list == null)
732                                 return null;
733
734                         list.Clear ();
735                         foreach (object o in value)
736                                 list.Add (o);
737
738                         return list;
739                 }
740
741                 protected virtual void ShowHelp ()
742                 {
743                         //TODO: Fixme Add parent and URL
744                         Help.ShowHelp (null, "", HelpTopic);
745                 }
746         }
747 }