2007-01-03 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / PropertyGrid.cs
index 0bc88346ab81b23d6514f2945e40b831552c9d51..5646d06d53211f45fddbab352f632bce1a76938c 100644 (file)
@@ -32,14 +32,17 @@ using System.ComponentModel;
 using System.Collections;
 using System.ComponentModel.Design;
 using System.Reflection;
+using System.Runtime.InteropServices;
 using System.Windows.Forms.Design;
 using System.Windows.Forms.PropertyGridInternal;
 
-namespace System.Windows.Forms
-{
+namespace System.Windows.Forms {
        [Designer("System.Windows.Forms.Design.PropertyGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
-       public class PropertyGrid : System.Windows.Forms.ContainerControl, ComponentModel.Com2Interop.IComPropertyBrowser
-       {
+#if NET_2_0
+       [ClassInterface (ClassInterfaceType.AutoDispatch)]
+       [ComVisible (true)]
+#endif
+       public class PropertyGrid : System.Windows.Forms.ContainerControl, ComponentModel.Com2Interop.IComPropertyBrowser {
                #region Private Members
                
                
@@ -59,7 +62,7 @@ namespace System.Windows.Forms
                private PropertySort property_sort;
                private PropertyTabCollection property_tabs;
                private GridItem selected_grid_item;
-               internal GridItemCollection grid_items;
+               internal GridItem root_grid_item;
                private object[] selected_objects;
                private PropertyTab selected_tab;
 
@@ -75,17 +78,15 @@ namespace System.Windows.Forms
                internal Panel help_panel;
                internal Label help_title_label;
                internal Label help_description_label;
-               private ContextMenu context_menu;
                private MenuItem reset_menuitem;
                private MenuItem description_menuitem;
                private object current_property_value;
 
                #endregion      // Private Members
-
+               
                #region Contructors
                public PropertyGrid() {
-                       selected_objects = new object[1];
-                       grid_items = new GridItemCollection();
+                       selected_objects = new object[0];
                        property_tabs = new PropertyTabCollection();
 
                        line_color = SystemColors.ScrollBar;
@@ -95,7 +96,6 @@ namespace System.Windows.Forms
                        property_sort = PropertySort.Categorized;
 
                        property_grid_view = new PropertyGridView(this);
-                       property_grid_view.Dock = DockStyle.Fill;
 
                        splitter = new Splitter();
                        splitter.Dock = DockStyle.Bottom;
@@ -111,7 +111,6 @@ namespace System.Windows.Forms
                        help_title_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                        help_title_label.Name = "help_title_label";
                        help_title_label.Font = new Font(this.Font,FontStyle.Bold);
-                       help_title_label.Text = "Title";
                        help_title_label.Location = new Point(2,2);
                        help_title_label.Height = 17;
                        help_title_label.Width = help_panel.Width - 4;
@@ -121,22 +120,21 @@ namespace System.Windows.Forms
                        help_description_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                        help_description_label.Name = "help_description_label";
                        help_description_label.Font = this.Font;
-                       help_description_label.Text = "The long important Description";
                        help_description_label.Location = new Point(2,help_title_label.Top+help_title_label.Height);
                        help_description_label.Width = help_panel.Width - 4;
-                       help_description_label.Height = 17;
+                       help_description_label.Height = help_panel.Height - help_description_label.Top - 2;
 
                        help_panel.Controls.Add(help_description_label);
                        help_panel.Controls.Add(help_title_label);
                        help_panel.Paint+=new PaintEventHandler(help_panel_Paint);
 
-                       toolbar = new ToolBar();
+                       toolbar = new PropertyToolBar();
                        toolbar.Dock = DockStyle.Top;
                        categorized_toolbarbutton = new ToolBarButton();
                        alphabetic_toolbarbutton = new ToolBarButton();
                        separator_toolbarbutton = new ToolBarButton();
                        propertypages_toolbarbutton = new ToolBarButton();
-                       context_menu = new ContextMenu();
+                       ContextMenu context_menu = new ContextMenu();
 
                        toolbar_imagelist = new ImageList();
                        toolbar_imagelist.ColorDepth = ColorDepth.Depth32Bit;
@@ -148,16 +146,14 @@ namespace System.Windows.Forms
 
                        toolbar.Appearance = ToolBarAppearance.Flat;
                        toolbar.AutoSize = false;
-                       toolbar.Buttons.AddRange(new ToolBarButton[] {
-                                                                            categorized_toolbarbutton,
-                                                                            alphabetic_toolbarbutton,
-                                                                            separator_toolbarbutton,
-                                                                            propertypages_toolbarbutton});
-
+                       toolbar.Buttons.AddRange(new ToolBarButton[] {categorized_toolbarbutton,
+                                                                     alphabetic_toolbarbutton,
+                                                                     separator_toolbarbutton,
+                                                                     propertypages_toolbarbutton});
+                       
                        toolbar.ButtonSize = new System.Drawing.Size(20, 20);
                        toolbar.ImageList = toolbar_imagelist;
                        toolbar.Location = new System.Drawing.Point(0, 0);
-                       toolbar.Name = "toolbar";
                        toolbar.ShowToolTips = true;
                        toolbar.Size = new System.Drawing.Size(256, 27);
                        toolbar.TabIndex = 0;
@@ -165,11 +161,11 @@ namespace System.Windows.Forms
 
                        categorized_toolbarbutton.ImageIndex = 0;
                        categorized_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
-                       categorized_toolbarbutton.ToolTipText = (string)Locale.GetResource( "Categorized");
+                       categorized_toolbarbutton.ToolTipText = Locale.GetText ("Categorized");
 
                        alphabetic_toolbarbutton.ImageIndex = 1;
                        alphabetic_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
-                       alphabetic_toolbarbutton.ToolTipText = (string)Locale.GetResource( "Alphabetic");
+                       alphabetic_toolbarbutton.ToolTipText = Locale.GetText ("Alphabetic");
 
                        separator_toolbarbutton.Style = ToolBarButtonStyle.Separator;
 
@@ -187,22 +183,18 @@ namespace System.Windows.Forms
                        description_menuitem.Checked = this.HelpVisible;
                        this.ContextMenu = context_menu;
                        toolbar.ContextMenu = context_menu;
-
-                       this.Controls.Add(property_grid_view);
+                       
+                       BorderHelperControl helper = new BorderHelperControl ();
+                       helper.Dock = DockStyle.Fill;
+                       helper.Controls.Add (property_grid_view);
+                       
+                       this.Controls.Add(helper);
                        this.Controls.Add(toolbar);
                        this.Controls.Add(splitter);
                        this.Controls.Add(help_panel);
                        this.Name = "PropertyGrid";
                        this.Size = new System.Drawing.Size(256, 400);
 
-                       has_focus = false;
-
-                       //TextChanged+=new System.EventHandler(RedrawEvent);
-                       //ForeColorChanged+=new EventHandler(RedrawEvent);
-                       //BackColorChanged+=new System.EventHandler(RedrawEvent);
-                       //FontChanged+=new EventHandler(RedrawEvent);
-                       //SizeChanged+=new EventHandler(RedrawEvent);
-
                        UpdateToolBarButtons();
                }
                #endregion      // Constructors
@@ -243,10 +235,9 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               if (base.BackColor == value) {
-                                       return;
-                               }
                                base.BackColor = value;
+                               toolbar.BackColor = value;
+                               Refresh ();
                        }
                }
                
@@ -296,7 +287,7 @@ namespace System.Windows.Forms
                        }
                }
 
-               [BrowsableAttribute(false)]
+               [BrowsableAttribute (false)]
                [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
                public virtual bool CommandsVisible {
                        get {
@@ -304,7 +295,11 @@ namespace System.Windows.Forms
                        }
                }
 
-               [DefaultValue(false)]
+#if NET_2_0
+               [DefaultValue (true)]
+#else
+               [DefaultValue (false)]
+#endif
                public virtual bool CommandsVisibleIfAvailable {
                        get {
                                return commands_visible_if_available;
@@ -338,8 +333,7 @@ namespace System.Windows.Forms
                
                [Browsable(false)]
                [EditorBrowsable(EditorBrowsableState.Never)]
-               public override Color ForeColor 
-               {
+               public override Color ForeColor {
                        get {
                                return base.ForeColor;
                        }
@@ -348,13 +342,14 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [DefaultValue ("Color [Control]")]
+#endif
                public Color HelpBackColor {
-                       get
-                       {
+                       get {
                                return help_panel.BackColor;
                        }
-                       set
-                       {
+                       set {
                                if (help_panel.BackColor == value) {
                                        return;
                                }
@@ -363,6 +358,9 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [DefaultValue ("Color [ControlText]")]
+#endif
                public Color HelpForeColor {
                        get {
                                return help_panel.ForeColor;
@@ -393,6 +391,9 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [DefaultValue (false)]
+#endif
                public bool LargeButtons {
                        get {
                                return large_buttons;
@@ -407,6 +408,9 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [DefaultValue ("Color [InactiveBorder]")]
+#endif
                public Color LineColor {
                        get {
                                return line_color;
@@ -437,14 +441,14 @@ namespace System.Windows.Forms
                                }
 
                                property_sort = value;
-                               
+
+                               UpdateToolBarButtons();
                                ReflectObjects();
-                               Console.WriteLine("PropertySort");
                                property_grid_view.Refresh();
-                               
-                               if (PropertySortChanged != null) {
-                                       PropertySortChanged(this, EventArgs.Empty);
-                               }
+
+                               EventHandler eh = (EventHandler)(Events [PropertySortChangedEvent]);
+                               if (eh != null)
+                                       eh (this, EventArgs.Empty);
                        }
                }
 
@@ -476,19 +480,24 @@ namespace System.Windows.Forms
                                if (selected_grid_item.PropertyDescriptor != null)
                                        this.help_description_label.Text = selected_grid_item.PropertyDescriptor.Description;
                                        
-                               Console.WriteLine("SelectedGridItem");
                                current_property_value = value.Value;
-                               if (oldItem != null && oldItem.PropertyDescriptor != null)
-                                       oldItem.PropertyDescriptor.RemoveValueChanged(SelectedObject, new EventHandler(HandlePropertyValueChanged));
-                               if (selected_grid_item.PropertyDescriptor != null)
-                                       selected_grid_item.PropertyDescriptor.AddValueChanged(SelectedObject, new EventHandler(HandlePropertyValueChanged));
-                               OnSelectedGridItemChanged(new SelectedGridItemChangedEventArgs( oldItem, selected_grid_item));
-                               
+                               if (oldItem != null && oldItem.PropertyDescriptor != null) {
+                                       for (int i = 0; i < ((GridEntry)oldItem).SelectedObjects.Length; i ++) {
+                                               object target = GetTarget (oldItem, i);
+                                               oldItem.PropertyDescriptor.RemoveValueChanged(target, new EventHandler(HandlePropertyValueChanged));
+                                       }
+                               }
+                               if (selected_grid_item.PropertyDescriptor != null) {
+                                       for (int i = 0; i < ((GridEntry)selected_grid_item).SelectedObjects.Length; i ++) {
+                                               object target = GetTarget (selected_grid_item, i);
+                                               selected_grid_item.PropertyDescriptor.AddValueChanged(target, new EventHandler(HandlePropertyValueChanged));
+                                       }
+                               }
+                               OnSelectedGridItemChanged(new SelectedGridItemChangedEventArgs (oldItem, selected_grid_item));
                        }
                }
 
-               private void HandlePropertyValueChanged(object sender, EventArgs e)
-               {
+               private void HandlePropertyValueChanged(object sender, EventArgs e) {
                        OnPropertyValueChanged(new PropertyValueChangedEventArgs( selected_grid_item, current_property_value));
                }
 
@@ -496,25 +505,17 @@ namespace System.Windows.Forms
                [TypeConverter("System.Windows.Forms.PropertyGrid+SelectedObjectConverter, " + Consts.AssemblySystem_Windows_Forms)]
                public object SelectedObject {
                        get {
-                               return selected_objects[0];
+                               if (selected_objects.Length > 0)
+                                       return selected_objects[0];
+                               return null;
                        }
 
                        set {
-                               selected_objects = new object[] {value};
-                               if (this.SelectedObject == null)
-                                       return;
-                               PropertyTabAttribute[] propTabs = (PropertyTabAttribute[])this.SelectedObject.GetType().GetCustomAttributes(typeof(PropertyTabAttribute),true);
-                               if (propTabs.Length > 0)
-                               {
-                                       foreach (Type tabType in propTabs[0].TabClasses)
-                                       {
-                                               this.PropertyTabs.AddTabType(tabType);
-                                       }
-                               }
-                               RefreshTabs(PropertyTabScope.Component);
-                               Console.WriteLine("SelectedObject");
-                               ReflectObjects();
-                               property_grid_view.Refresh();
+                               if (value == null)
+                                       SelectedObjects = new object[0];
+                               else
+                                       SelectedObjects = new object[] {value};
+
                        }
                }
 
@@ -526,8 +527,33 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               selected_objects = value;
+                               if (value != null) {
+                                       for (int i = 0; i < value.Length; i++) {
+                                               if (value [i] == null)
+                                                       throw new ArgumentException (String.Format ("Item {0} in the objs array is null.", i));
+                                       }
+                                       selected_objects = value;
+                               } else {
+                                       selected_objects = new object [0];
+                               }
+
+                               if (selected_objects.Length > 0) {
+                                       PropertyTabAttribute[] propTabs = (PropertyTabAttribute[])this.SelectedObject.GetType().GetCustomAttributes(typeof(PropertyTabAttribute),true);
+                                       if (propTabs.Length > 0) {
+                                               foreach (Type tabType in propTabs[0].TabClasses) {
+                                                       this.PropertyTabs.AddTabType(tabType);
+                                               }
+                                       }
+                               }
+
+                               RefreshTabs(PropertyTabScope.Component);
                                ReflectObjects();
+                               if (root_grid_item != null) {
+                                       /* find the first non category grid item and select it */
+                                       SelectedGridItem = FindFirstItem (root_grid_item);
+                               }
+                               property_grid_view.Refresh();
+                               OnSelectedObjectsChanged (EventArgs.Empty);
                        }
                }
 
@@ -566,6 +592,9 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [DefaultValue ("Color [Window]")]
+#endif
                public Color ViewBackColor {
                        get {
                                return property_grid_view.BackColor;
@@ -580,6 +609,9 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [DefaultValue ("Color [WindowText]")]
+#endif
                public Color ViewForeColor {
                        get {
                                return property_grid_view.ForeColor;
@@ -636,34 +668,33 @@ namespace System.Windows.Forms
 
                #region Public Instance Methods
                
-               protected override void Dispose(bool val)
-               {
+               protected override void Dispose(bool val) {
                        base.Dispose(val);
                }
-               
-               public void CollapseAllGridItems () 
-               {
-                       foreach (GridItem item in this.grid_items)
-                       {
-                               item.Expanded = false;
+
+               [MonoTODO ("should this be recursive?  or just the toplevel items?")]
+               public void CollapseAllGridItems () {
+                       if (root_grid_item != null) {
+                               foreach (GridItem item in root_grid_item.GridItems) {
+                                       item.Expanded = false;
+                               }
                        }
                }
 
-               public void ExpandAllGridItems () 
-               {
-                       foreach (GridItem item in this.grid_items)
-                       {
-                               item.Expanded = true;
+               [MonoTODO ("should this be recursive?  or just the toplevel items?")]
+               public void ExpandAllGridItems () {
+                       if (root_grid_item != null) {
+                               foreach (GridItem item in root_grid_item.GridItems) {
+                                       item.Expanded = true;
+                               }
                        }
                }
 
-               public override void Refresh () 
-               {
+               public override void Refresh () {
                        base.Refresh ();
                }
 
-               public void RefreshTabs (PropertyTabScope tabScope) 
-               {
+               public void RefreshTabs (PropertyTabScope tabScope) {
                        
                        /*button = new ToolBarButton("C");
                        button.ImageIndex = 0;
@@ -684,8 +715,7 @@ namespace System.Windows.Forms
                        
                }
 
-               public void ResetSelectedProperty() 
-               {
+               public void ResetSelectedProperty() {
                        if (selected_grid_item == null || selected_grid_item.PropertyDescriptor == null)
                                return;
                        
@@ -695,145 +725,156 @@ namespace System.Windows.Forms
 
                #region Protected Instance Methods
 
-               protected virtual PropertyTab CreatePropertyTab(Type tabType) 
-               {
+               protected virtual PropertyTab CreatePropertyTab(Type tabType) {
                        return (PropertyTab)Activator.CreateInstance(tabType);
                }
                
                [MonoTODO]
                protected void OnComComponentNameChanged(ComponentRenameEventArgs e)
                {
-                       throw new NotImplementedException();
+                       ComponentRenameEventHandler eh = (ComponentRenameEventHandler)(Events [ComComponentNameChangedEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
-               protected override void OnFontChanged(EventArgs e) 
-               {
+               protected override void OnFontChanged(EventArgs e) {
                        base.OnFontChanged (e);
                }
 
-               protected override void OnGotFocus(EventArgs e) 
-               {
-                       has_focus=true;
+               protected override void OnGotFocus(EventArgs e) {
                        base.OnGotFocus(e);
                }
 
-               protected override void OnHandleCreated (EventArgs e) 
-               {
+               protected override void OnHandleCreated (EventArgs e) {
                        base.OnHandleCreated (e);
                }
 
-               protected override void OnHandleDestroyed (EventArgs e) 
-               {
+               protected override void OnHandleDestroyed (EventArgs e) {
                        base.OnHandleDestroyed (e);
                }
 
-               protected override void OnMouseDown (MouseEventArgs e) 
-               {
+               protected override void OnMouseDown (MouseEventArgs e) {
                        base.OnMouseDown (e);
                }
 
-               protected override void OnMouseMove (MouseEventArgs e) 
-               {
+               protected override void OnMouseMove (MouseEventArgs e) {
                        base.OnMouseMove (e);
                }
 
-               protected override void OnMouseUp (MouseEventArgs e) 
-               {
+               protected override void OnMouseUp (MouseEventArgs e) {
                        base.OnMouseUp (e);
                }
                
                [MonoTODO]
-               protected void OnNotifyPropertyValueUIItemsChanged(object sender, EventArgs e)
-               {
+               protected void OnNotifyPropertyValueUIItemsChanged(object sender, EventArgs e) {
                }
 
-               protected override void OnPaint (PaintEventArgs pevent) 
-               {
+               protected override void OnPaint (PaintEventArgs pevent) {
+                       pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
                        base.OnPaint (pevent);
                }
 
                [MonoTODO]
-               protected virtual void OnPropertyTabChanged (PropertyTabChangedEventArgs e) 
-               {
+               protected virtual void OnPropertyTabChanged (PropertyTabChangedEventArgs e) {
                        throw new NotImplementedException();
                }
 
-               protected virtual void OnPropertyValueChanged (PropertyValueChangedEventArgs e) 
-               {
-                       if (PropertyValueChanged != null) 
-                       {
-                               PropertyValueChanged(this, e);
+               protected virtual void OnPropertyValueChanged (PropertyValueChangedEventArgs e) {
+                       PropertyValueChangedEventHandler eh = (PropertyValueChangedEventHandler)(Events [PropertyValueChangedEvent]);
+                       if (eh != null) {
+                               eh (this, e);
                                current_property_value = selected_grid_item.Value;
                        }
                }
 
-               protected override void OnResize (EventArgs e) 
-               {
+               protected override void OnResize (EventArgs e) {
                        base.OnResize (e);
                }
 
-               protected virtual void OnSelectedGridItemChanged (SelectedGridItemChangedEventArgs e) 
-               {
-                       if (SelectedGridItemChanged != null) 
-                       {
-                               SelectedGridItemChanged(this, e);
-                       }
+               protected virtual void OnSelectedGridItemChanged (SelectedGridItemChangedEventArgs e) {
+                       SelectedGridItemChangedEventHandler eh = (SelectedGridItemChangedEventHandler)(Events [SelectedGridItemChangedEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
-               protected virtual void OnSelectedObjectsChanged (EventArgs e) 
-               {
-                       if (SelectedObjectsChanged != null) 
-                       {
-                               SelectedObjectsChanged(this, e);
-                       }
+               protected virtual void OnSelectedObjectsChanged (EventArgs e) {
+                       EventHandler eh = (EventHandler)(Events [SelectedObjectsChangedEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
-               protected override void OnSystemColorsChanged (EventArgs e) 
-               {
+               protected override void OnSystemColorsChanged (EventArgs e) {
                        base.OnSystemColorsChanged (e);
                }
 
-               protected override void OnVisibleChanged (EventArgs e) 
-               {
+               protected override void OnVisibleChanged (EventArgs e) {
                        base.OnVisibleChanged (e);
                }
 
-               protected override bool ProcessDialogKey (Keys keyData) 
-               {
+               protected override bool ProcessDialogKey (Keys keyData) {
                        return base.ProcessDialogKey (keyData);
                }
 
-               protected override void ScaleCore (float dx, float dy) 
-               {
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               protected override void ScaleCore (float dx, float dy) {
                        base.ScaleCore (dx, dy);
                }
                
                [MonoTODO]
-               protected void ShowEventsButton(bool value)
-               {
+               protected void ShowEventsButton(bool value) {
                        throw new NotImplementedException();
                }
 
-               protected override void WndProc (ref Message m) 
-               {
+               protected override void WndProc (ref Message m) {
                        base.WndProc (ref m);
                }
                #endregion
 
                #region Events
-               public event EventHandler PropertySortChanged;
-               public event PropertyTabChangedEventHandler PropertyTabChanged;
-               public event PropertyValueChangedEventHandler PropertyValueChanged;
-               public event SelectedGridItemChangedEventHandler SelectedGridItemChanged;
-               public event EventHandler SelectedObjectsChanged;
+               static object PropertySortChangedEvent = new object ();
+               static object PropertyTabChangedEvent = new object ();
+               static object PropertyValueChangedEvent = new object ();
+               static object SelectedGridItemChangedEvent = new object ();
+               static object SelectedObjectsChangedEvent = new object ();
+
+               public event EventHandler PropertySortChanged {
+                       add { Events.AddHandler (PropertySortChangedEvent, value); }
+                       remove { Events.RemoveHandler (PropertySortChangedEvent, value); }
+               }
+
+               public event PropertyTabChangedEventHandler PropertyTabChanged {
+                       add { Events.AddHandler (PropertyTabChangedEvent, value); }
+                       remove { Events.RemoveHandler (PropertyTabChangedEvent, value); }
+               }
+
+               public event PropertyValueChangedEventHandler PropertyValueChanged {
+                       add { Events.AddHandler (PropertyValueChangedEvent, value); }
+                       remove { Events.RemoveHandler (PropertyValueChangedEvent, value); }
+               }
+
+               public event SelectedGridItemChangedEventHandler SelectedGridItemChanged {
+                       add { Events.AddHandler (SelectedGridItemChangedEvent, value); }
+                       remove { Events.RemoveHandler (SelectedGridItemChangedEvent, value); }
+               }
+
+               public event EventHandler SelectedObjectsChanged {
+                       add { Events.AddHandler (SelectedObjectsChangedEvent, value); }
+                       remove { Events.RemoveHandler (SelectedObjectsChangedEvent, value); }
+               }
                
                [Browsable(false)]
                [EditorBrowsable(EditorBrowsableState.Never)]
-               public new event EventHandler BackgroundImageChanged;
+               public new event EventHandler BackgroundImageChanged {
+                       add { base.BackgroundImageChanged += value; }
+                       remove { base.BackgroundImageChanged -= value; }
+               }
 
                [Browsable(false)]
                [EditorBrowsable(EditorBrowsableState.Never)]
-               public new event EventHandler ForeColorChanged;
+               public new event EventHandler ForeColorChanged {
+                       add { base.ForeColorChanged += value; }
+                       remove { base.ForeColorChanged -= value; }
+               }
                #endregion
 
                #region Com2Interop.IComPropertyBrowser Interface
@@ -869,17 +910,15 @@ namespace System.Windows.Forms
                        throw new NotImplementedException();
                }
 
-               [MonoTODO]
-               private event ComponentRenameEventHandler com_component_name_changed;
+               static object ComComponentNameChangedEvent = new object ();
                event ComponentRenameEventHandler ComponentModel.Com2Interop.IComPropertyBrowser.ComComponentNameChanged {
-                       add { com_component_name_changed += value; }
-                       remove { com_component_name_changed -= value; }
+                       add { Events.AddHandler (ComComponentNameChangedEvent, value); }
+                       remove { Events.RemoveHandler (ComComponentNameChangedEvent, value); }
                }
                #endregion      // Com2Interop.IComPropertyBrowser Interface
 
                #region PropertyTabCollection Class
-               public class PropertyTabCollection : ICollection, IEnumerable
-               {
+               public class PropertyTabCollection : ICollection, IEnumerable {
                        System.Collections.ArrayList list;
                        #region Private Constructors
                        internal PropertyTabCollection() {
@@ -895,20 +934,17 @@ namespace System.Windows.Forms
                        }
                
                        #region ICollection Members
-                       bool ICollection.IsSynchronized
-                       {
+                       bool ICollection.IsSynchronized {
                                get {
                                        return list.IsSynchronized;
                                }
                        }
 
-                       void ICollection.CopyTo(Array array, int index)
-                       {
+                       void ICollection.CopyTo(Array array, int index) {
                                list.CopyTo(array, index);
                        }
 
-                       object ICollection.SyncRoot
-                       {
+                       object ICollection.SyncRoot {
                                get {
                                        return list.SyncRoot;
                                }
@@ -933,24 +969,20 @@ namespace System.Windows.Forms
                        #endregion
                        
                        #region Public Instance Methods
-                       public void AddTabType(System.Type propertyTabType)
-                       {
+                       public void AddTabType(System.Type propertyTabType) {
                                list.Add(Activator.CreateInstance(propertyTabType));
                        }
                        [MonoTODO]
                        public void AddTabType(System.Type propertyTabType,
-                               System.ComponentModel.PropertyTabScope tabScope)
-                       {
+                               System.ComponentModel.PropertyTabScope tabScope) {
                                AddTabType(propertyTabType);
                        }
                        [MonoTODO]
-                       public void Clear(System.ComponentModel.PropertyTabScope tabScope)
-                       {
+                       public void Clear(System.ComponentModel.PropertyTabScope tabScope) {
                                throw new NotImplementedException();
                        }
                        [MonoTODO]
-                       public void RemoveTabType(System.Type propertyTabType)
-                       {
+                       public void RemoveTabType(System.Type propertyTabType) {
                                throw new NotImplementedException();
                        }
                        #endregion
@@ -959,22 +991,31 @@ namespace System.Windows.Forms
 
                #region Private Helper Methods
 
-               private void toolbar_ButtonClick (object sender, ToolBarButtonClickEventArgs e) 
+               private GridItem FindFirstItem (GridItem root)
                {
+                       if (root.GridItemType == GridItemType.Property)
+                               return root;
+
+                       foreach (GridItem item in root.GridItems) {
+                               GridItem subitem = FindFirstItem (item);
+                               if (subitem != null)
+                                       return subitem;
+                       }
+
+                       return null;
+               }
+
+
+               private void toolbar_ButtonClick (object sender, ToolBarButtonClickEventArgs e) {
                        if (e.Button == alphabetic_toolbarbutton) {
                                this.PropertySort = PropertySort.Alphabetical;
                        }
                        else if (e.Button == categorized_toolbarbutton) {
                                this.PropertySort = PropertySort.Categorized;
                        }
-                       UpdateToolBarButtons();
-                       ReflectObjects();
-                       Console.WriteLine("toolbar_ButtonClick");
-                       property_grid_view.Refresh();
                }
 
-               internal void UpdateToolBarButtons () 
-               {
+               internal void UpdateToolBarButtons () {
                        if (PropertySort == PropertySort.Alphabetical) {
                                categorized_toolbarbutton.Pushed = false;
                                alphabetic_toolbarbutton.Pushed = true;
@@ -989,71 +1030,143 @@ namespace System.Windows.Forms
                        }
                }
 
-               private void OnResetPropertyClick (object sender, EventArgs e) 
-               {
+               private void OnResetPropertyClick (object sender, EventArgs e) {
                        ResetSelectedProperty();
                }
 
-               private void OnDescriptionClick (object sender, EventArgs e) 
-               {
+               private void OnDescriptionClick (object sender, EventArgs e) {
                        this.HelpVisible = !this.HelpVisible;
                        description_menuitem.Checked = this.HelpVisible;
 
                }
 
-               private void ReflectObjects () 
+               private void ReflectObjects () {
+                       if (selected_objects.Length > 0) {
+                               root_grid_item = new RootGridEntry (property_grid_view,
+                                                                   selected_objects.Length > 1 ? selected_objects : selected_objects[0]);
+                                                                          
+                               PopulateMergedGridItems (selected_objects, root_grid_item.GridItems, true, root_grid_item);
+                       }
+               }
+
+               private void PopulateMergedGridItems (object[] objs, GridItemCollection grid_item_coll, bool recurse, GridItem parent_grid_item)
                {
-                       grid_items = new GridItemCollection();
-                       foreach (object obj in selected_objects) {
-                               if (obj != null) {
-                                       PopulateGridItemCollection(obj,grid_items, true);
+                       ArrayList intersection = null;
+
+                       for (int i = 0; i < objs.Length; i ++) {
+                               if (objs [i] == null)
+                                       continue;
+
+                               ArrayList new_intersection = new ArrayList ();
+                               Type type = objs[i].GetType();
+
+                               /* i tried using filter attributes, but there's no way to do it for EditorBrowsableAttributes,
+                                  since that type lacks an override for IsDefaultAttribute, and for some reason the
+                                  BrowsableAttribute.Yes filter wasn't working */
+                               PropertyDescriptorCollection properties = null;
+
+                               if (typeof (ICustomTypeDescriptor).IsAssignableFrom (type)) {
+                                       properties = ((ICustomTypeDescriptor)objs[i]).GetProperties ();
+                               }
+                               if (properties == null) {
+                                       TypeConverter cvt = TypeDescriptor.GetConverter (objs[i]);
+                                       properties = cvt.GetProperties (objs[i]);
+                               }
+                               if (properties == null) {
+                                       properties = TypeDescriptor.GetProperties (objs[i]);
                                }
+
+                               foreach (PropertyDescriptor p in (i == 0 ? (ICollection)properties : (ICollection)intersection)) {
+                                       PropertyDescriptor property = (i == 0 ? p : properties [p.Name]);
+                                       if (property == null) {
+                                               /* since the property doesn't exist in at least one of the other types, 
+                                                  exclude it */
+                                       }
+                                       else if (!property.IsBrowsable
+                                           || (objs.Length > 1 && property.Attributes.Contains (MergablePropertyAttribute.No))
+                                           || property.Attributes.Contains (new EditorBrowsableAttribute (EditorBrowsableState.Never))
+                                           || property.Attributes.Contains (new EditorBrowsableAttribute (EditorBrowsableState.Advanced))) {
+                                               /* if the property isn't supposed to be displayed in the merged view,
+                                                  excluded it */
+                                       }
+                                       else {
+                                               Type p_type = p.ComponentType;
+                                               Type property_type = property.ComponentType;
+
+                                               if (p_type.IsAssignableFrom (type))
+                                                       new_intersection.Add (p);
+                                               else if (property_type.IsAssignableFrom (p_type))
+                                                       new_intersection.Add (property);
+                                       }
+                               }
+
+                               intersection = new_intersection;
                        }
+
+                       if (intersection != null && intersection.Count > 0)
+                               PopulateGridItemsFromProperties (objs, intersection, grid_item_coll, recurse, parent_grid_item);
                }
 
-               private void PopulateGridItemCollection (object obj, GridItemCollection grid_item_coll, bool recurse) 
-               {
-                       //TypeConverter converter = TypeDescriptor.GetConverter(obj);
-                       PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(obj);
+               private void PopulateGridItemsFromProperties (object[] objs, ArrayList properties,
+                                                             GridItemCollection grid_item_coll, bool recurse, GridItem parent_grid_item) {
                        foreach (PropertyDescriptor property in properties) {
-                               if (property.IsBrowsable) {
-                                       GridEntry grid_entry = new GridEntry(obj, property);
-                                       if (property_sort == PropertySort.Alphabetical || !recurse)
-                                       {
-                                               if (grid_item_coll[property.Name] == null)
-                                                       grid_item_coll.Add(property.Name,grid_entry);
+
+                               GridEntry grid_entry = new GridEntry (property_grid_view, objs, property);
+                               grid_entry.SetParent (parent_grid_item);
+                               if (property_sort == PropertySort.Alphabetical || /* XXX */property_sort == PropertySort.NoSort || !recurse) {
+                                       if (grid_item_coll[property.Name] == null) {
+                                               grid_item_coll.Add(property.Name,grid_entry);
+                                               grid_entry.SetParent ((GridEntry)parent_grid_item);
                                        }
-                                       else if (property_sort == PropertySort.Categorized || property_sort == PropertySort.CategorizedAlphabetical)
-                                       {
-
-                                               string category = property.Category;
-                                               GridItem cat_item = grid_item_coll[category];
-                                               if (cat_item == null) 
-                                               {
-                                                       cat_item = new CategoryGridEntry(category);
-                                                       grid_item_coll.Add(category,cat_item);
-                                               }
-                                               cat_item.GridItems.Add(property.Name,grid_entry);
+                               }
+                               else if (property_sort == PropertySort.Categorized || property_sort == PropertySort.CategorizedAlphabetical) {
+
+                                       string category = property.Category;
+                                       CategoryGridEntry cat_item = grid_item_coll[category] as CategoryGridEntry;
+                                       if (cat_item == null) {
+                                               cat_item = new CategoryGridEntry (property_grid_view, category);
+                                               cat_item.SetParent (parent_grid_item);
+                                               grid_item_coll.Add (category, cat_item);
                                        }
-                                       if (recurse)
-                                       {
-                                               object propObj = property.GetValue(obj);
-                                               if (propObj != null)
-                                                       PopulateGridItemCollection(propObj,grid_entry.GridItems, false);
+                                       if (cat_item.GridItems[property.Name] == null) {
+                                               cat_item.GridItems.Add(property.Name,grid_entry);
+                                               grid_entry.SetParent (cat_item);
                                        }
                                }
+
+                               if (recurse && property.Converter != null && property.Converter.GetPropertiesSupported()) {
+                                       object[] subobjs = new object[objs.Length];
+                                       for (int i = 0; i < objs.Length; i ++)
+                                               subobjs[i] = property.GetValue (objs[i]);
+                                       PopulateMergedGridItems (subobjs, grid_entry.GridItems, false, grid_entry);
+                               }
+                               grid_entry.Expanded = false;
                        }
                }
 
-               #endregion      // Private Helper Methods
-
-               private void help_panel_Paint(object sender, PaintEventArgs e)
-               {
+               private void help_panel_Paint(object sender, PaintEventArgs e) {
                        e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(help_panel.BackColor), help_panel.ClientRectangle );
                        e.Graphics.DrawRectangle(SystemPens.ControlDark, 0,0,help_panel.Width-1,help_panel.Height-1 );
                }
+
+               internal object GetTarget (GridItem item, int selected_index)
+               {
+                       object target = ((GridEntry)item).SelectedObjects[selected_index];
+
+                       while (item.Parent != null && item.Parent.GridItemType != GridItemType.Property)
+                               item = item.Parent;
+
+                       if (item.Parent != null && item.Parent.PropertyDescriptor != null)
+                               target = item.Parent.PropertyDescriptor.GetValue (((GridEntry)item.Parent).SelectedObjects[selected_index]);
+
+                       return target;
+               }
+               #endregion      // Private Helper Methods
+
+
 #if NET_2_0
 
+               [DefaultValue (false)]
                public bool UseCompatibleTextRendering {
                        get {
                                return use_compatible_text_rendering;
@@ -1064,5 +1177,45 @@ namespace System.Windows.Forms
                        }
                }
 #endif
+               
+               // as we can not change the color for BorderStyle.FixedSingle and we need the correct
+               // ClientRectangle so that the ScrollBar doesn't draw over the border we need this class
+               internal class BorderHelperControl : Control {
+
+                       public BorderHelperControl ()
+                       {
+                               BackColor = ThemeEngine.Current.ColorWindow;
+                       }
+
+                       protected override void OnPaint (PaintEventArgs e)
+                       {
+                               e.Graphics.DrawRectangle (SystemPens.ControlDark, 0 , 0 , Width - 1, Height - 1);
+                               base.OnPaint (e);
+                       }
+                       
+                       protected override void OnSizeChanged (EventArgs e)
+                       {
+                               if (Controls.Count == 1) {
+                                       Control control = Controls [0];
+                                       
+                                       if (control.Location.X != 1 || control.Location.Y != 1)
+                                               control.Location = new Point (1, 1);
+                                       
+                                       control.Width = ClientRectangle.Width - 2;
+                                       control.Height = ClientRectangle.Height - 2;
+                               }
+                               base.OnSizeChanged (e);
+                       }
+               }
+               
+               // needed! this little helper makes it possible to draw a different toolbar border
+               // and toolbar backcolor in ThemeWin32Classic
+               internal class PropertyToolBar : ToolBar {}
+
+
+               [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")]
+               internal class SelectedObjectConverter : TypeConverter
+               {
+               }
        }
 }