* TextControl.cs: Oops, we need to use the ClientRect not the
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / PropertyGrid.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Jonathan Chambers (jonathan.chambers@ansys.com)
24 //
25
26 // NOT COMPLETE
27
28 using System;
29 using System.Drawing;
30 using System.Drawing.Design;
31 using System.ComponentModel;
32 using System.Collections;
33 using System.ComponentModel.Design;
34 using System.Reflection;
35 using System.Runtime.InteropServices;
36 using System.Windows.Forms.Design;
37 using System.Windows.Forms.PropertyGridInternal;
38
39 namespace System.Windows.Forms {
40         [Designer("System.Windows.Forms.Design.PropertyGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
41 #if NET_2_0
42         [ClassInterface (ClassInterfaceType.AutoDispatch)]
43         [ComVisible (true)]
44 #endif
45         public class PropertyGrid : System.Windows.Forms.ContainerControl, ComponentModel.Com2Interop.IComPropertyBrowser {
46                 #region Private Members
47                 
48                 
49                 private const int GRID_ITEM_HEIGHT = 16;
50                 private const int GRID_LEFT_COLUMN_WIDTH = 16;
51                 private const int DIVIDER_PADDING = 2;
52
53                 private AttributeCollection browsable_attributes = null;
54                 private bool can_show_commands = false;
55                 private Color commands_back_color;
56                 private Color commands_fore_color;
57                 private bool commands_visible;
58                 private bool commands_visible_if_available;
59                 private Point context_menu_default_location;
60                 private bool large_buttons;
61                 private Color line_color;
62                 private PropertySort property_sort;
63                 private PropertyTabCollection property_tabs;
64                 private GridItem selected_grid_item;
65                 internal GridItem root_grid_item;
66                 private object[] selected_objects;
67                 private PropertyTab selected_tab;
68
69                 private ImageList toolbar_imagelist;
70                 private ToolBarButton categorized_toolbarbutton;
71                 private ToolBarButton alphabetic_toolbarbutton;
72                 private ToolBarButton separator_toolbarbutton;
73                 private ToolBarButton propertypages_toolbarbutton;
74
75                 internal ToolBar toolbar;
76                 internal PropertyGridView property_grid_view;
77                 internal Splitter splitter;
78                 internal Panel help_panel;
79                 internal Label help_title_label;
80                 internal Label help_description_label;
81                 private MenuItem reset_menuitem;
82                 private MenuItem description_menuitem;
83                 private object current_property_value;
84
85                 #endregion      // Private Members
86                 
87                 #region Contructors
88                 public PropertyGrid() {
89                         selected_objects = new object[0];
90                         property_tabs = new PropertyTabCollection();
91
92                         line_color = SystemColors.ScrollBar;
93                         line_color = SystemColors.ScrollBar;
94                         browsable_attributes = new AttributeCollection(new Attribute[] {});
95                         commands_visible_if_available = false;
96                         property_sort = PropertySort.Categorized;
97
98                         property_grid_view = new PropertyGridView(this);
99
100                         splitter = new Splitter();
101                         splitter.Dock = DockStyle.Bottom;
102
103                         help_panel = new Panel();
104                         help_panel.Dock = DockStyle.Bottom;
105                         //help_panel.DockPadding.All = 3;
106                         help_panel.Height = 50;
107                         help_panel.BackColor = SystemColors.Control;
108
109
110                         help_title_label = new Label();
111                         help_title_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
112                         help_title_label.Name = "help_title_label";
113                         help_title_label.Font = new Font(this.Font,FontStyle.Bold);
114                         help_title_label.Location = new Point(2,2);
115                         help_title_label.Height = 17;
116                         help_title_label.Width = help_panel.Width - 4;
117
118                         
119                         help_description_label = new Label();
120                         help_description_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
121                         help_description_label.Name = "help_description_label";
122                         help_description_label.Font = this.Font;
123                         help_description_label.Location = new Point(2,help_title_label.Top+help_title_label.Height);
124                         help_description_label.Width = help_panel.Width - 4;
125                         help_description_label.Height = help_panel.Height - help_description_label.Top - 2;
126
127                         help_panel.Controls.Add(help_description_label);
128                         help_panel.Controls.Add(help_title_label);
129                         help_panel.Paint+=new PaintEventHandler(help_panel_Paint);
130
131                         toolbar = new PropertyToolBar();
132                         toolbar.Dock = DockStyle.Top;
133                         categorized_toolbarbutton = new ToolBarButton();
134                         alphabetic_toolbarbutton = new ToolBarButton();
135                         separator_toolbarbutton = new ToolBarButton();
136                         propertypages_toolbarbutton = new ToolBarButton();
137                         ContextMenu context_menu = new ContextMenu();
138
139                         toolbar_imagelist = new ImageList();
140                         toolbar_imagelist.ColorDepth = ColorDepth.Depth32Bit;
141                         toolbar_imagelist.ImageSize = new System.Drawing.Size(16, 16);
142                         toolbar_imagelist.TransparentColor = System.Drawing.Color.Transparent;
143                         toolbar_imagelist.Images.Add( (Image)Locale.GetResource( "propertygrid_sort_category") );
144                         toolbar_imagelist.Images.Add( (Image)Locale.GetResource( "propertygrid_sort_alphabetical") );
145                         toolbar_imagelist.Images.Add( (Image)Locale.GetResource( "propertygrid_tab_properties") );
146
147                         toolbar.Appearance = ToolBarAppearance.Flat;
148                         toolbar.AutoSize = false;
149                         toolbar.Buttons.AddRange(new ToolBarButton[] {categorized_toolbarbutton,
150                                                                       alphabetic_toolbarbutton,
151                                                                       separator_toolbarbutton,
152                                                                       propertypages_toolbarbutton});
153                         
154                         toolbar.ButtonSize = new System.Drawing.Size(20, 20);
155                         toolbar.ImageList = toolbar_imagelist;
156                         toolbar.Location = new System.Drawing.Point(0, 0);
157                         toolbar.ShowToolTips = true;
158                         toolbar.Size = new System.Drawing.Size(256, 27);
159                         toolbar.TabIndex = 0;
160                         toolbar.ButtonClick += new ToolBarButtonClickEventHandler(toolbar_ButtonClick);
161
162                         categorized_toolbarbutton.ImageIndex = 0;
163                         categorized_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
164                         categorized_toolbarbutton.ToolTipText = Locale.GetText ("Categorized");
165
166                         alphabetic_toolbarbutton.ImageIndex = 1;
167                         alphabetic_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
168                         alphabetic_toolbarbutton.ToolTipText = Locale.GetText ("Alphabetic");
169
170                         separator_toolbarbutton.Style = ToolBarButtonStyle.Separator;
171
172                         propertypages_toolbarbutton.Enabled = false;
173                         propertypages_toolbarbutton.ImageIndex = 2;
174                         propertypages_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
175                         propertypages_toolbarbutton.ToolTipText = "Property Pages";
176
177                         
178                         reset_menuitem = context_menu.MenuItems.Add("Reset");
179                         reset_menuitem.Click +=new EventHandler(OnResetPropertyClick);
180                         context_menu.MenuItems.Add("-");
181                         description_menuitem = context_menu.MenuItems.Add("Description");
182                         description_menuitem.Click += new EventHandler(OnDescriptionClick);
183                         description_menuitem.Checked = this.HelpVisible;
184                         this.ContextMenu = context_menu;
185                         toolbar.ContextMenu = context_menu;
186                         
187                         BorderHelperControl helper = new BorderHelperControl ();
188                         helper.Dock = DockStyle.Fill;
189                         helper.Controls.Add (property_grid_view);
190                         
191                         this.Controls.Add(helper);
192                         this.Controls.Add(toolbar);
193                         this.Controls.Add(splitter);
194                         this.Controls.Add(help_panel);
195                         this.Name = "PropertyGrid";
196                         this.Size = new System.Drawing.Size(256, 400);
197
198                         UpdateToolBarButtons();
199                 }
200                 #endregion      // Constructors
201
202                 #region Public Instance Properties
203
204                 [BrowsableAttribute(false)]
205                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
206                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
207                 public AttributeCollection BrowsableAttributes {
208                         get {
209                                 return browsable_attributes;
210                         }
211
212                         set {
213                                 if (browsable_attributes == value) {
214                                         return;
215                                 }
216
217                                 browsable_attributes = value;
218                         }
219                 }
220                 
221                 [Browsable(false)]
222                 [EditorBrowsable(EditorBrowsableState.Never)]
223                 public override bool AutoScroll {
224                         get {
225                                 return base.AutoScroll;
226                         }
227                         set {
228                                 base.AutoScroll = value;
229                         }
230                 }
231
232                 public override Color BackColor {
233                         get {
234                                 return base.BackColor;
235                         }
236
237                         set {
238                                 base.BackColor = value;
239                                 toolbar.BackColor = value;
240                                 Refresh ();
241                         }
242                 }
243                 
244                 [Browsable(false)]
245                 [EditorBrowsable(EditorBrowsableState.Never)]
246                 public override Image BackgroundImage {
247                         get {
248                                 return base.BackgroundImage;
249                         }               
250                         set {
251                                 base.BackgroundImage = value;
252                         }
253                 }
254
255
256                 [BrowsableAttribute(false)]
257                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
258                 public virtual bool CanShowCommands {
259                         get {
260                                 return can_show_commands;
261                         }
262                 }
263
264                 public Color CommandsBackColor {
265                         get {
266                                 return commands_back_color;
267                         }
268
269                         set {
270                                 if (commands_back_color == value) {
271                                         return;
272                                 }
273                                 commands_back_color = value;
274                         }
275                 }
276
277                 public Color CommandsForeColor {
278                         get {
279                                 return commands_fore_color;
280                         }
281
282                         set {
283                                 if (commands_fore_color == value) {
284                                         return;
285                                 }
286                                 commands_fore_color = value;
287                         }
288                 }
289
290                 [BrowsableAttribute (false)]
291                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
292                 public virtual bool CommandsVisible {
293                         get {
294                                 return commands_visible;
295                         }
296                 }
297
298 #if NET_2_0
299                 [DefaultValue (true)]
300 #else
301                 [DefaultValue (false)]
302 #endif
303                 public virtual bool CommandsVisibleIfAvailable {
304                         get {
305                                 return commands_visible_if_available;
306                         }
307
308                         set {
309                                 if (commands_visible_if_available == value) {
310                                         return;
311                                 }
312                                 commands_visible_if_available = value;
313                         }
314                 }
315
316                 [BrowsableAttribute(false)]
317                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
318                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
319                 public Point ContextMenuDefaultLocation {
320                         get {
321                                 return context_menu_default_location;
322                         }
323                 }
324                 
325                 [Browsable(false)]
326                 [EditorBrowsable(EditorBrowsableState.Never)]
327                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
328                 public new Control.ControlCollection Controls {
329                         get {
330                                 return base.Controls;
331                         }
332                 }
333                 
334                 [Browsable(false)]
335                 [EditorBrowsable(EditorBrowsableState.Never)]
336                 public override Color ForeColor {
337                         get {
338                                 return base.ForeColor;
339                         }
340                         set {
341                                 base.ForeColor = value;
342                         }
343                 }
344
345 #if NET_2_0
346                 [DefaultValue ("Color [Control]")]
347 #endif
348                 public Color HelpBackColor {
349                         get {
350                                 return help_panel.BackColor;
351                         }
352                         set {
353                                 if (help_panel.BackColor == value) {
354                                         return;
355                                 }
356
357                                 help_panel.BackColor = value;
358                         }
359                 }
360
361 #if NET_2_0
362                 [DefaultValue ("Color [ControlText]")]
363 #endif
364                 public Color HelpForeColor {
365                         get {
366                                 return help_panel.ForeColor;
367                         }
368
369                         set {
370                                 if (help_panel.ForeColor == value) {
371                                         return;
372                                 }
373
374                                 help_panel.ForeColor = value;
375                         }
376                 }
377
378                 [DefaultValue(true)]
379                 [Localizable(true)]
380                 public virtual bool HelpVisible {
381                         get {
382                                 return help_panel.Visible;
383                         }
384
385                         set {
386                                 if (help_panel.Visible == value) {
387                                         return;
388                                 }
389
390                                 help_panel.Visible = value;
391                         }
392                 }
393
394 #if NET_2_0
395                 [DefaultValue (false)]
396 #endif
397                 public bool LargeButtons {
398                         get {
399                                 return large_buttons;
400                         }
401
402                         set {
403                                 if (large_buttons == value) {
404                                         return;
405                                 }
406
407                                 large_buttons = value;
408                         }
409                 }
410
411 #if NET_2_0
412                 [DefaultValue ("Color [InactiveBorder]")]
413 #endif
414                 public Color LineColor {
415                         get {
416                                 return line_color;
417                         }
418
419                         set {
420                                 if (line_color == value) {
421                                         return;
422                                 }
423
424                                 line_color = value;
425                         }
426                 }
427
428                 [DefaultValue(PropertySort.CategorizedAlphabetical)]
429                 public PropertySort PropertySort {
430                         get {
431                                 return property_sort;
432                         }
433
434                         set {
435                                 if (!Enum.IsDefined (typeof (PropertySort), value)) {
436                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for PropertySort", value));
437                                 }
438
439                                 if (property_sort == value) {
440                                         return;
441                                 }
442
443                                 property_sort = value;
444
445                                 UpdateToolBarButtons();
446                                 ReflectObjects();
447                                 property_grid_view.Refresh();
448
449                                 EventHandler eh = (EventHandler)(Events [PropertySortChangedEvent]);
450                                 if (eh != null)
451                                         eh (this, EventArgs.Empty);
452                         }
453                 }
454
455                 [BrowsableAttribute(false)]
456                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
457                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
458                 public PropertyTabCollection PropertyTabs {
459                         get {
460                                 return property_tabs;
461                         }
462                 }
463
464                 [BrowsableAttribute(false)]
465                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
466                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
467                 public GridItem SelectedGridItem {
468                         get {
469                                 return selected_grid_item;
470                         }
471
472                         set {
473                                 if (selected_grid_item == value) {
474                                         return;
475                                 }
476
477                                 GridItem oldItem = selected_grid_item;
478                                 selected_grid_item = value;
479                                 this.help_title_label.Text = selected_grid_item.Label;
480                                 if (selected_grid_item.PropertyDescriptor != null)
481                                         this.help_description_label.Text = selected_grid_item.PropertyDescriptor.Description;
482                                         
483                                 current_property_value = value.Value;
484                                 if (oldItem != null && oldItem.PropertyDescriptor != null) {
485                                         for (int i = 0; i < ((GridEntry)oldItem).SelectedObjects.Length; i ++) {
486                                                 object target = GetTarget (oldItem, i);
487                                                 oldItem.PropertyDescriptor.RemoveValueChanged(target, new EventHandler(HandlePropertyValueChanged));
488                                         }
489                                 }
490                                 if (selected_grid_item.PropertyDescriptor != null) {
491                                         for (int i = 0; i < ((GridEntry)selected_grid_item).SelectedObjects.Length; i ++) {
492                                                 object target = GetTarget (selected_grid_item, i);
493                                                 selected_grid_item.PropertyDescriptor.AddValueChanged(target, new EventHandler(HandlePropertyValueChanged));
494                                         }
495                                 }
496                                 OnSelectedGridItemChanged(new SelectedGridItemChangedEventArgs (oldItem, selected_grid_item));
497                         }
498                 }
499
500                 private void HandlePropertyValueChanged(object sender, EventArgs e) {
501                         OnPropertyValueChanged(new PropertyValueChangedEventArgs( selected_grid_item, current_property_value));
502                 }
503
504                 [DefaultValue(null)]
505                 [TypeConverter("System.Windows.Forms.PropertyGrid+SelectedObjectConverter, " + Consts.AssemblySystem_Windows_Forms)]
506                 public object SelectedObject {
507                         get {
508                                 if (selected_objects.Length > 0)
509                                         return selected_objects[0];
510                                 return null;
511                         }
512
513                         set {
514                                 if (value == null)
515                                         SelectedObjects = new object[0];
516                                 else
517                                         SelectedObjects = new object[] {value};
518
519                         }
520                 }
521
522                 [BrowsableAttribute(false)]
523                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
524                 public object[] SelectedObjects {
525                         get {
526                                 return selected_objects;
527                         }
528
529                         set {
530                                 if (value != null) {
531                                         for (int i = 0; i < value.Length; i++) {
532                                                 if (value [i] == null)
533                                                         throw new ArgumentException (String.Format ("Item {0} in the objs array is null.", i));
534                                         }
535                                         selected_objects = value;
536                                 } else {
537                                         selected_objects = new object [0];
538                                 }
539
540                                 if (selected_objects.Length > 0) {
541                                         PropertyTabAttribute[] propTabs = (PropertyTabAttribute[])this.SelectedObject.GetType().GetCustomAttributes(typeof(PropertyTabAttribute),true);
542                                         if (propTabs.Length > 0) {
543                                                 foreach (Type tabType in propTabs[0].TabClasses) {
544                                                         this.PropertyTabs.AddTabType(tabType);
545                                                 }
546                                         }
547                                 }
548
549                                 RefreshTabs(PropertyTabScope.Component);
550                                 ReflectObjects();
551                                 if (root_grid_item != null) {
552                                         /* find the first non category grid item and select it */
553                                         SelectedGridItem = FindFirstItem (root_grid_item);
554                                 }
555                                 property_grid_view.Refresh();
556                                 OnSelectedObjectsChanged (EventArgs.Empty);
557                         }
558                 }
559
560                 [BrowsableAttribute(false)]
561                 [EditorBrowsable(EditorBrowsableState.Advanced)]
562                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
563                 public PropertyTab SelectedTab {
564                         get {
565                                 return selected_tab;
566                         }
567                 }
568
569                 public override ISite Site {
570                         get {
571                                 return base.Site;
572                         }
573
574                         set {
575                                 base.Site = value;
576                         }
577                 }
578
579
580                 [DefaultValue(true)]
581                 public virtual bool ToolbarVisible {
582                         get {
583                                 return toolbar.Visible;
584                         }
585
586                         set {
587                                 if (toolbar.Visible == value) {
588                                         return;
589                                 }
590
591                                 toolbar.Visible = value;
592                         }
593                 }
594
595 #if NET_2_0
596                 [DefaultValue ("Color [Window]")]
597 #endif
598                 public Color ViewBackColor {
599                         get {
600                                 return property_grid_view.BackColor;
601                         }
602
603                         set {
604                                 if (property_grid_view.BackColor == value) {
605                                         return;
606                                 }
607
608                                 property_grid_view.BackColor = value;
609                         }
610                 }
611
612 #if NET_2_0
613                 [DefaultValue ("Color [WindowText]")]
614 #endif
615                 public Color ViewForeColor {
616                         get {
617                                 return property_grid_view.ForeColor;
618                         }
619
620                         set {
621                                 if (property_grid_view.ForeColor == value) {
622                                         return;
623                                 }
624
625                                 property_grid_view.ForeColor = value;
626                         }
627                 }
628
629                 #endregion      // Public Instance Properties
630
631                 #region Protected Instance Properties
632
633                 protected override Size DefaultSize {
634                         get {
635                                 return base.DefaultSize;
636                         }
637                 }
638
639
640                 [Browsable(false)]
641                 [EditorBrowsable(EditorBrowsableState.Advanced)]
642                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
643                 protected virtual Type DefaultTabType {
644                         get {
645                                 return typeof(PropertiesTab);
646                         }
647                 }
648                 
649                 protected bool DrawFlatToolbar {
650                         get {
651                                 return (toolbar.Appearance == ToolBarAppearance.Flat);
652                         }                       
653                         set {
654                                 if (value) 
655                                         toolbar.Appearance = ToolBarAppearance.Flat;
656                                 else
657                                         toolbar.Appearance = ToolBarAppearance.Normal;
658                         }
659                 }
660
661                 protected override bool ShowFocusCues {
662                         get {
663                                 return base.ShowFocusCues;
664                         }
665                 }
666
667                 #endregion      // Protected Instance Properties
668
669                 #region Public Instance Methods
670                 
671                 protected override void Dispose(bool val) {
672                         base.Dispose(val);
673                 }
674
675                 [MonoTODO ("should this be recursive?  or just the toplevel items?")]
676                 public void CollapseAllGridItems () {
677                         if (root_grid_item != null) {
678                                 foreach (GridItem item in root_grid_item.GridItems) {
679                                         item.Expanded = false;
680                                 }
681                         }
682                 }
683
684                 [MonoTODO ("should this be recursive?  or just the toplevel items?")]
685                 public void ExpandAllGridItems () {
686                         if (root_grid_item != null) {
687                                 foreach (GridItem item in root_grid_item.GridItems) {
688                                         item.Expanded = true;
689                                 }
690                         }
691                 }
692
693                 public override void Refresh () {
694                         base.Refresh ();
695                 }
696
697                 public void RefreshTabs (PropertyTabScope tabScope) {
698                         
699                         /*button = new ToolBarButton("C");
700                         button.ImageIndex = 0;
701                         this.toolbar.Buttons.Add(button);
702                         button = new ToolBarButton();
703                         button.ImageIndex = 0;
704                         button.Style = ToolBarButtonStyle.Separator;
705                         this.toolbar.Buttons.Add(button);
706                         foreach (PropertyTab tab in this.PropertyTabs)
707                         {
708
709                                 int index = toolbar.ImageList.Images.Count;
710                                 this.toolbar.ImageList.Images.Add(tab.Bitmap);
711                                 button = new ToolBarButton();
712                                 button.ImageIndex = index;
713                                 this.toolbar.Buttons.Add(button);
714                         }*/
715                         
716                 }
717
718                 public void ResetSelectedProperty() {
719                         if (selected_grid_item == null || selected_grid_item.PropertyDescriptor == null)
720                                 return;
721                         
722                         selected_grid_item.PropertyDescriptor.ResetValue(SelectedObject);
723                 }
724                 #endregion      // Public Instance Methods
725
726                 #region Protected Instance Methods
727
728                 protected virtual PropertyTab CreatePropertyTab(Type tabType) {
729                         return (PropertyTab)Activator.CreateInstance(tabType);
730                 }
731                 
732                 [MonoTODO]
733                 protected void OnComComponentNameChanged(ComponentRenameEventArgs e)
734                 {
735                         ComponentRenameEventHandler eh = (ComponentRenameEventHandler)(Events [ComComponentNameChangedEvent]);
736                         if (eh != null)
737                                 eh (this, e);
738                 }
739
740                 protected override void OnFontChanged(EventArgs e) {
741                         base.OnFontChanged (e);
742                 }
743
744                 protected override void OnGotFocus(EventArgs e) {
745                         base.OnGotFocus(e);
746                 }
747
748                 protected override void OnHandleCreated (EventArgs e) {
749                         base.OnHandleCreated (e);
750                 }
751
752                 protected override void OnHandleDestroyed (EventArgs e) {
753                         base.OnHandleDestroyed (e);
754                 }
755
756                 protected override void OnMouseDown (MouseEventArgs e) {
757                         base.OnMouseDown (e);
758                 }
759
760                 protected override void OnMouseMove (MouseEventArgs e) {
761                         base.OnMouseMove (e);
762                 }
763
764                 protected override void OnMouseUp (MouseEventArgs e) {
765                         base.OnMouseUp (e);
766                 }
767                 
768                 [MonoTODO]
769                 protected void OnNotifyPropertyValueUIItemsChanged(object sender, EventArgs e) {
770                 }
771
772                 protected override void OnPaint (PaintEventArgs pevent) {
773                         pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
774                         base.OnPaint (pevent);
775                 }
776
777                 [MonoTODO]
778                 protected virtual void OnPropertyTabChanged (PropertyTabChangedEventArgs e) {
779                         throw new NotImplementedException();
780                 }
781
782                 protected virtual void OnPropertyValueChanged (PropertyValueChangedEventArgs e) {
783                         PropertyValueChangedEventHandler eh = (PropertyValueChangedEventHandler)(Events [PropertyValueChangedEvent]);
784                         if (eh != null) {
785                                 eh (this, e);
786                                 current_property_value = selected_grid_item.Value;
787                         }
788                 }
789
790                 protected override void OnResize (EventArgs e) {
791                         base.OnResize (e);
792                 }
793
794                 protected virtual void OnSelectedGridItemChanged (SelectedGridItemChangedEventArgs e) {
795                         SelectedGridItemChangedEventHandler eh = (SelectedGridItemChangedEventHandler)(Events [SelectedGridItemChangedEvent]);
796                         if (eh != null)
797                                 eh (this, e);
798                 }
799
800                 protected virtual void OnSelectedObjectsChanged (EventArgs e) {
801                         EventHandler eh = (EventHandler)(Events [SelectedObjectsChangedEvent]);
802                         if (eh != null)
803                                 eh (this, e);
804                 }
805
806                 protected override void OnSystemColorsChanged (EventArgs e) {
807                         base.OnSystemColorsChanged (e);
808                 }
809
810                 protected override void OnVisibleChanged (EventArgs e) {
811                         base.OnVisibleChanged (e);
812                 }
813
814                 protected override bool ProcessDialogKey (Keys keyData) {
815                         return base.ProcessDialogKey (keyData);
816                 }
817
818 #if NET_2_0
819                 [EditorBrowsable (EditorBrowsableState.Never)]
820 #endif
821                 protected override void ScaleCore (float dx, float dy) {
822                         base.ScaleCore (dx, dy);
823                 }
824                 
825                 [MonoTODO]
826                 protected void ShowEventsButton(bool value) {
827                         throw new NotImplementedException();
828                 }
829
830                 protected override void WndProc (ref Message m) {
831                         base.WndProc (ref m);
832                 }
833                 #endregion
834
835                 #region Events
836                 static object PropertySortChangedEvent = new object ();
837                 static object PropertyTabChangedEvent = new object ();
838                 static object PropertyValueChangedEvent = new object ();
839                 static object SelectedGridItemChangedEvent = new object ();
840                 static object SelectedObjectsChangedEvent = new object ();
841
842                 public event EventHandler PropertySortChanged {
843                         add { Events.AddHandler (PropertySortChangedEvent, value); }
844                         remove { Events.RemoveHandler (PropertySortChangedEvent, value); }
845                 }
846
847                 public event PropertyTabChangedEventHandler PropertyTabChanged {
848                         add { Events.AddHandler (PropertyTabChangedEvent, value); }
849                         remove { Events.RemoveHandler (PropertyTabChangedEvent, value); }
850                 }
851
852                 public event PropertyValueChangedEventHandler PropertyValueChanged {
853                         add { Events.AddHandler (PropertyValueChangedEvent, value); }
854                         remove { Events.RemoveHandler (PropertyValueChangedEvent, value); }
855                 }
856
857                 public event SelectedGridItemChangedEventHandler SelectedGridItemChanged {
858                         add { Events.AddHandler (SelectedGridItemChangedEvent, value); }
859                         remove { Events.RemoveHandler (SelectedGridItemChangedEvent, value); }
860                 }
861
862                 public event EventHandler SelectedObjectsChanged {
863                         add { Events.AddHandler (SelectedObjectsChangedEvent, value); }
864                         remove { Events.RemoveHandler (SelectedObjectsChangedEvent, value); }
865                 }
866                 
867                 [Browsable(false)]
868                 [EditorBrowsable(EditorBrowsableState.Never)]
869                 public new event EventHandler BackgroundImageChanged {
870                         add { base.BackgroundImageChanged += value; }
871                         remove { base.BackgroundImageChanged -= value; }
872                 }
873
874                 [Browsable(false)]
875                 [EditorBrowsable(EditorBrowsableState.Never)]
876                 public new event EventHandler ForeColorChanged {
877                         add { base.ForeColorChanged += value; }
878                         remove { base.ForeColorChanged -= value; }
879                 }
880                 #endregion
881
882                 #region Com2Interop.IComPropertyBrowser Interface
883                 [MonoTODO]
884                 bool ComponentModel.Com2Interop.IComPropertyBrowser.InPropertySet {
885                         get  {
886                                 throw new NotImplementedException();
887                         }
888                 }
889
890                 [MonoTODO]
891                 void ComponentModel.Com2Interop.IComPropertyBrowser.DropDownDone() {
892                         throw new NotImplementedException();
893                 }
894
895                 [MonoTODO]
896                 bool ComponentModel.Com2Interop.IComPropertyBrowser.EnsurePendingChangesCommitted() {
897                         throw new NotImplementedException();
898                 }
899
900                 [MonoTODO]
901                 void ComponentModel.Com2Interop.IComPropertyBrowser.HandleF4() {
902                         throw new NotImplementedException();
903                 }
904
905                 [MonoTODO]
906                 void ComponentModel.Com2Interop.IComPropertyBrowser.LoadState(Microsoft.Win32.RegistryKey key) {
907                         throw new NotImplementedException();
908                 }
909
910                 [MonoTODO]
911                 void ComponentModel.Com2Interop.IComPropertyBrowser.SaveState(Microsoft.Win32.RegistryKey key) {
912                         throw new NotImplementedException();
913                 }
914
915                 static object ComComponentNameChangedEvent = new object ();
916                 event ComponentRenameEventHandler ComponentModel.Com2Interop.IComPropertyBrowser.ComComponentNameChanged {
917                         add { Events.AddHandler (ComComponentNameChangedEvent, value); }
918                         remove { Events.RemoveHandler (ComComponentNameChangedEvent, value); }
919                 }
920                 #endregion      // Com2Interop.IComPropertyBrowser Interface
921
922                 #region PropertyTabCollection Class
923                 public class PropertyTabCollection : ICollection, IEnumerable {
924                         System.Collections.ArrayList list;
925                         #region Private Constructors
926                         internal PropertyTabCollection() {
927                                 list = new ArrayList();
928                         }
929
930                         #endregion      // Private Constructors
931
932                         public PropertyTab this[int index] {
933                                 get {
934                                         return (PropertyTab)list[index];
935                                 }
936                         }
937                 
938                         #region ICollection Members
939                         bool ICollection.IsSynchronized {
940                                 get {
941                                         return list.IsSynchronized;
942                                 }
943                         }
944
945                         void ICollection.CopyTo(Array array, int index) {
946                                 list.CopyTo(array, index);
947                         }
948
949                         object ICollection.SyncRoot {
950                                 get {
951                                         return list.SyncRoot;
952                                 }
953                         }
954
955                         #endregion
956
957                         #region IEnumerable Members
958                         public IEnumerator GetEnumerator() {
959                                 return list.GetEnumerator();
960                         }
961
962                         #endregion
963                 
964                         #region ICollection Members
965                         public int Count {
966                                 get {
967                                         return list.Count;
968                                 }
969                         }
970
971                         #endregion
972                         
973                         #region Public Instance Methods
974                         public void AddTabType(System.Type propertyTabType) {
975                                 list.Add(Activator.CreateInstance(propertyTabType));
976                         }
977                         [MonoTODO]
978                         public void AddTabType(System.Type propertyTabType,
979                                 System.ComponentModel.PropertyTabScope tabScope) {
980                                 AddTabType(propertyTabType);
981                         }
982                         [MonoTODO]
983                         public void Clear(System.ComponentModel.PropertyTabScope tabScope) {
984                                 throw new NotImplementedException();
985                         }
986                         [MonoTODO]
987                         public void RemoveTabType(System.Type propertyTabType) {
988                                 throw new NotImplementedException();
989                         }
990                         #endregion
991                 }
992                 #endregion      // PropertyTabCollection Class
993
994                 #region Private Helper Methods
995
996                 private GridItem FindFirstItem (GridItem root)
997                 {
998                         if (root.GridItemType == GridItemType.Property)
999                                 return root;
1000
1001                         foreach (GridItem item in root.GridItems) {
1002                                 GridItem subitem = FindFirstItem (item);
1003                                 if (subitem != null)
1004                                         return subitem;
1005                         }
1006
1007                         return null;
1008                 }
1009
1010
1011                 private void toolbar_ButtonClick (object sender, ToolBarButtonClickEventArgs e) {
1012                         if (e.Button == alphabetic_toolbarbutton) {
1013                                 this.PropertySort = PropertySort.Alphabetical;
1014                         }
1015                         else if (e.Button == categorized_toolbarbutton) {
1016                                 this.PropertySort = PropertySort.Categorized;
1017                         }
1018                 }
1019
1020                 internal void UpdateToolBarButtons () {
1021                         if (PropertySort == PropertySort.Alphabetical) {
1022                                 categorized_toolbarbutton.Pushed = false;
1023                                 alphabetic_toolbarbutton.Pushed = true;
1024                         }
1025                         else if (PropertySort == PropertySort.Categorized) {
1026                                 categorized_toolbarbutton.Pushed = true;
1027                                 alphabetic_toolbarbutton.Pushed = false;
1028                         }
1029                         else {
1030                                 categorized_toolbarbutton.Pushed = false;
1031                                 alphabetic_toolbarbutton.Pushed = false;
1032                         }
1033                 }
1034
1035                 private void OnResetPropertyClick (object sender, EventArgs e) {
1036                         ResetSelectedProperty();
1037                 }
1038
1039                 private void OnDescriptionClick (object sender, EventArgs e) {
1040                         this.HelpVisible = !this.HelpVisible;
1041                         description_menuitem.Checked = this.HelpVisible;
1042
1043                 }
1044
1045                 private void ReflectObjects () {
1046                         if (selected_objects.Length > 0) {
1047                                 root_grid_item = new RootGridEntry (property_grid_view,
1048                                                                     selected_objects.Length > 1 ? selected_objects : selected_objects[0]);
1049                                                                            
1050                                 PopulateMergedGridItems (selected_objects, root_grid_item.GridItems, true, root_grid_item);
1051                         }
1052                 }
1053
1054                 private void PopulateMergedGridItems (object[] objs, GridItemCollection grid_item_coll, bool recurse, GridItem parent_grid_item)
1055                 {
1056                         ArrayList intersection = null;
1057
1058                         for (int i = 0; i < objs.Length; i ++) {
1059                                 if (objs [i] == null)
1060                                         continue;
1061
1062                                 ArrayList new_intersection = new ArrayList ();
1063                                 Type type = objs[i].GetType();
1064
1065                                 /* i tried using filter attributes, but there's no way to do it for EditorBrowsableAttributes,
1066                                    since that type lacks an override for IsDefaultAttribute, and for some reason the
1067                                    BrowsableAttribute.Yes filter wasn't working */
1068                                 PropertyDescriptorCollection properties = null;
1069
1070                                 if (typeof (ICustomTypeDescriptor).IsAssignableFrom (type)) {
1071                                         properties = ((ICustomTypeDescriptor)objs[i]).GetProperties ();
1072                                 }
1073                                 if (properties == null) {
1074                                         TypeConverter cvt = TypeDescriptor.GetConverter (objs[i]);
1075                                         properties = cvt.GetProperties (objs[i]);
1076                                 }
1077                                 if (properties == null) {
1078                                         properties = TypeDescriptor.GetProperties (objs[i]);
1079                                 }
1080
1081                                 foreach (PropertyDescriptor p in (i == 0 ? (ICollection)properties : (ICollection)intersection)) {
1082                                         PropertyDescriptor property = (i == 0 ? p : properties [p.Name]);
1083                                         if (property == null) {
1084                                                 /* since the property doesn't exist in at least one of the other types, 
1085                                                    exclude it */
1086                                         }
1087                                         else if (!property.IsBrowsable
1088                                             || (objs.Length > 1 && property.Attributes.Contains (MergablePropertyAttribute.No))
1089                                             || property.Attributes.Contains (new EditorBrowsableAttribute (EditorBrowsableState.Never))
1090                                             || property.Attributes.Contains (new EditorBrowsableAttribute (EditorBrowsableState.Advanced))) {
1091                                                 /* if the property isn't supposed to be displayed in the merged view,
1092                                                    excluded it */
1093                                         }
1094                                         else {
1095                                                 Type p_type = p.ComponentType;
1096                                                 Type property_type = property.ComponentType;
1097
1098                                                 if (p_type.IsAssignableFrom (type))
1099                                                         new_intersection.Add (p);
1100                                                 else if (property_type.IsAssignableFrom (p_type))
1101                                                         new_intersection.Add (property);
1102                                         }
1103                                 }
1104
1105                                 intersection = new_intersection;
1106                         }
1107
1108                         if (intersection != null && intersection.Count > 0)
1109                                 PopulateGridItemsFromProperties (objs, intersection, grid_item_coll, recurse, parent_grid_item);
1110                 }
1111
1112                 private void PopulateGridItemsFromProperties (object[] objs, ArrayList properties,
1113                                                               GridItemCollection grid_item_coll, bool recurse, GridItem parent_grid_item) {
1114                         foreach (PropertyDescriptor property in properties) {
1115
1116                                 GridEntry grid_entry = new GridEntry (property_grid_view, objs, property);
1117                                 grid_entry.SetParent (parent_grid_item);
1118                                 if (property_sort == PropertySort.Alphabetical || /* XXX */property_sort == PropertySort.NoSort || !recurse) {
1119                                         if (grid_item_coll[property.Name] == null) {
1120                                                 grid_item_coll.Add(property.Name,grid_entry);
1121                                                 grid_entry.SetParent ((GridEntry)parent_grid_item);
1122                                         }
1123                                 }
1124                                 else if (property_sort == PropertySort.Categorized || property_sort == PropertySort.CategorizedAlphabetical) {
1125
1126                                         string category = property.Category;
1127                                         CategoryGridEntry cat_item = grid_item_coll[category] as CategoryGridEntry;
1128                                         if (cat_item == null) {
1129                                                 cat_item = new CategoryGridEntry (property_grid_view, category);
1130                                                 cat_item.SetParent (parent_grid_item);
1131                                                 grid_item_coll.Add (category, cat_item);
1132                                         }
1133                                         if (cat_item.GridItems[property.Name] == null) {
1134                                                 cat_item.GridItems.Add(property.Name,grid_entry);
1135                                                 grid_entry.SetParent (cat_item);
1136                                         }
1137                                 }
1138
1139                                 if (recurse && property.Converter != null && property.Converter.GetPropertiesSupported()) {
1140                                         object[] subobjs = new object[objs.Length];
1141                                         for (int i = 0; i < objs.Length; i ++)
1142                                                 subobjs[i] = property.GetValue (objs[i]);
1143                                         PopulateMergedGridItems (subobjs, grid_entry.GridItems, false, grid_entry);
1144                                 }
1145                                 grid_entry.Expanded = false;
1146                         }
1147                 }
1148
1149                 private void help_panel_Paint(object sender, PaintEventArgs e) {
1150                         e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(help_panel.BackColor), help_panel.ClientRectangle );
1151                         e.Graphics.DrawRectangle(SystemPens.ControlDark, 0,0,help_panel.Width-1,help_panel.Height-1 );
1152                 }
1153
1154                 internal object GetTarget (GridItem item, int selected_index)
1155                 {
1156                         object target = ((GridEntry)item).SelectedObjects[selected_index];
1157
1158                         while (item.Parent != null && item.Parent.GridItemType != GridItemType.Property)
1159                                 item = item.Parent;
1160
1161                         if (item.Parent != null && item.Parent.PropertyDescriptor != null)
1162                                 target = item.Parent.PropertyDescriptor.GetValue (((GridEntry)item.Parent).SelectedObjects[selected_index]);
1163
1164                         return target;
1165                 }
1166                 #endregion      // Private Helper Methods
1167
1168
1169 #if NET_2_0
1170
1171                 [DefaultValue (false)]
1172                 public bool UseCompatibleTextRendering {
1173                         get {
1174                                 return use_compatible_text_rendering;
1175                         }
1176
1177                         set {
1178                                 use_compatible_text_rendering = value;
1179                         }
1180                 }
1181 #endif
1182                 
1183                 // as we can not change the color for BorderStyle.FixedSingle and we need the correct
1184                 // ClientRectangle so that the ScrollBar doesn't draw over the border we need this class
1185                 internal class BorderHelperControl : Control {
1186
1187                         public BorderHelperControl ()
1188                         {
1189                                 BackColor = ThemeEngine.Current.ColorWindow;
1190                         }
1191
1192                         protected override void OnPaint (PaintEventArgs e)
1193                         {
1194                                 e.Graphics.DrawRectangle (SystemPens.ControlDark, 0 , 0 , Width - 1, Height - 1);
1195                                 base.OnPaint (e);
1196                         }
1197                         
1198                         protected override void OnSizeChanged (EventArgs e)
1199                         {
1200                                 if (Controls.Count == 1) {
1201                                         Control control = Controls [0];
1202                                         
1203                                         if (control.Location.X != 1 || control.Location.Y != 1)
1204                                                 control.Location = new Point (1, 1);
1205                                         
1206                                         control.Width = ClientRectangle.Width - 2;
1207                                         control.Height = ClientRectangle.Height - 2;
1208                                 }
1209                                 base.OnSizeChanged (e);
1210                         }
1211                 }
1212                 
1213                 // needed! this little helper makes it possible to draw a different toolbar border
1214                 // and toolbar backcolor in ThemeWin32Classic
1215                 internal class PropertyToolBar : ToolBar {}
1216
1217
1218                 [MonoTODO ("not sure what this class does, but it's listed as a type converter for a property in this class, and this causes problems if it's not present")]
1219                 internal class SelectedObjectConverter : TypeConverter
1220                 {
1221                 }
1222         }
1223 }