* TabControl.cs: Show the tooltip depending on the value
[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-2008 Novell, Inc.
21 //
22 // Authors:
23 //      Jonathan Chambers (jonathan.chambers@ansys.com)
24 //      Ivan N. Zlatev    (contact@i-nz.net)
25 //
26
27 // NOT COMPLETE
28
29 using System;
30 using System.IO;
31 using System.Drawing;
32 using System.Drawing.Design;
33 using System.ComponentModel;
34 using System.Collections;
35 using System.ComponentModel.Design;
36 using System.Reflection;
37 using System.Runtime.InteropServices;
38 using System.Windows.Forms.Design;
39 using System.Windows.Forms.PropertyGridInternal;
40
41 namespace System.Windows.Forms 
42 {
43         [Designer("System.Windows.Forms.Design.PropertyGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
44 #if NET_2_0
45         [ClassInterface (ClassInterfaceType.AutoDispatch)]
46         [ComVisible (true)]
47 #endif
48         public class PropertyGrid : System.Windows.Forms.ContainerControl, ComponentModel.Com2Interop.IComPropertyBrowser 
49         {
50                 #region Private Members
51                 
52                 
53                 private const string UNCATEGORIZED_CATEGORY_LABEL = "Misc";
54                 private AttributeCollection browsable_attributes = null;
55                 private bool can_show_commands = false;
56                 private Color commands_back_color;
57                 private Color commands_fore_color;
58                 private bool commands_visible;
59                 private bool commands_visible_if_available;
60                 private Point context_menu_default_location;
61                 private bool large_buttons;
62                 private Color line_color;
63                 private PropertySort property_sort;
64                 private PropertyTabCollection property_tabs;
65                 private GridEntry selected_grid_item;
66                 private GridEntry root_grid_item;
67                 private object[] selected_objects;
68                 private PropertyTab properties_tab;
69                 private PropertyTab selected_tab;
70
71                 private ImageList toolbar_imagelist;
72                 private Image categorized_image;
73                 private Image alphabetical_image;
74                 private Image propertypages_image;
75                 private PropertyToolBarButton categorized_toolbarbutton;
76                 private PropertyToolBarButton alphabetic_toolbarbutton;
77                 private PropertyToolBarButton propertypages_toolbarbutton;
78                 private PropertyToolBarSeparator separator_toolbarbutton;
79                 private bool events_tab_visible;
80
81                 private PropertyToolBar toolbar;
82
83                 private PropertyGridView property_grid_view;
84                 private Splitter splitter;
85                 private Panel help_panel;
86                 private Label help_title_label;
87                 private Label help_description_label;
88                 private MenuItem reset_menuitem;
89                 private MenuItem description_menuitem;
90
91                 private Color category_fore_color;
92 #if NET_2_0
93                 private Color commands_active_link_color;
94                 private Color commands_disabled_link_color;
95                 private Color commands_link_color;
96 #endif
97                 #endregion      // Private Members
98                 
99                 #region Contructors
100                 public PropertyGrid ()
101                 {
102                         selected_objects = new object[0];
103                         property_tabs = new PropertyTabCollection(this);
104
105                         line_color = SystemColors.ScrollBar;
106                         category_fore_color = line_color;
107                         commands_visible = false;
108                         commands_visible_if_available = false;
109                         property_sort = PropertySort.CategorizedAlphabetical;
110                         property_grid_view = new PropertyGridView(this);
111
112                         splitter = new Splitter();
113                         splitter.Dock = DockStyle.Bottom;
114
115                         help_panel = new Panel();
116                         help_panel.Dock = DockStyle.Bottom;
117                         //help_panel.DockPadding.All = 3;
118                         help_panel.Height = 50;
119                         help_panel.BackColor = SystemColors.Control;
120
121
122                         help_title_label = new Label();
123                         help_title_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
124                         help_title_label.Name = "help_title_label";
125                         help_title_label.Font = new Font(this.Font,FontStyle.Bold);
126                         help_title_label.Location = new Point(2,2);
127                         help_title_label.Height = 17;
128                         help_title_label.Width = help_panel.Width - 4;
129
130                         
131                         help_description_label = new Label();
132                         help_description_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
133                         help_description_label.AutoEllipsis = true;
134                         help_description_label.AutoSize = false;
135                         help_description_label.Font = this.Font;
136                         help_description_label.Location = new Point(2,help_title_label.Top+help_title_label.Height);
137                         help_description_label.Width = help_panel.Width - 4;
138                         help_description_label.Height = help_panel.Height - help_description_label.Top - 2;
139
140                         help_panel.Controls.Add(help_description_label);
141                         help_panel.Controls.Add(help_title_label);
142                         help_panel.Paint+=new PaintEventHandler(help_panel_Paint);
143
144                         toolbar = new PropertyToolBar();
145                         toolbar.Dock = DockStyle.Top;
146                         categorized_toolbarbutton = new PropertyToolBarButton ();
147                         categorized_toolbarbutton.Pushed = true;
148                         alphabetic_toolbarbutton = new PropertyToolBarButton ();
149                         propertypages_toolbarbutton = new PropertyToolBarButton ();
150                         separator_toolbarbutton = new PropertyToolBarSeparator ();
151                         ContextMenu context_menu = new ContextMenu();
152                         context_menu_default_location = Point.Empty;
153
154                         categorized_image = new Bitmap (typeof (PropertyGrid), "propertygrid-categorized.png");
155                         alphabetical_image = new Bitmap (typeof (PropertyGrid), "propertygrid-alphabetical.png");
156                         propertypages_image = new Bitmap (typeof (PropertyGrid), "propertygrid-propertypages.png");
157
158                         toolbar_imagelist = new ImageList();
159                         toolbar_imagelist.ColorDepth = ColorDepth.Depth32Bit;
160                         toolbar_imagelist.ImageSize = new System.Drawing.Size(16, 16);
161                         toolbar_imagelist.TransparentColor = System.Drawing.Color.Transparent;
162
163                         toolbar.Appearance = ToolBarAppearance.Flat;
164                         toolbar.AutoSize = false;
165                         
166                         toolbar.ImageList = toolbar_imagelist;
167                         toolbar.Location = new System.Drawing.Point(0, 0);
168                         toolbar.ShowToolTips = true;
169                         toolbar.Size = new System.Drawing.Size(256, 27);
170                         toolbar.TabIndex = 0;
171 #if NET_2_0
172                         toolbar.Items.AddRange (new ToolStripItem [] {categorized_toolbarbutton,
173                                                                       alphabetic_toolbarbutton,
174                                                                       new PropertyToolBarSeparator (),
175                                                                       propertypages_toolbarbutton});
176                         //toolbar.ButtonSize = new System.Drawing.Size (20, 20);
177                         categorized_toolbarbutton.Click += new EventHandler (toolbarbutton_clicked);
178                         alphabetic_toolbarbutton.Click += new EventHandler (toolbarbutton_clicked);
179                         propertypages_toolbarbutton.Click += new EventHandler (toolbarbutton_clicked);
180 #else
181                         toolbar.Buttons.AddRange(new ToolBarButton [] {categorized_toolbarbutton,
182                                                                       alphabetic_toolbarbutton,
183                                                                       new PropertyToolBarSeparator (),
184                                                                       propertypages_toolbarbutton});
185                         toolbar.ButtonSize = new System.Drawing.Size(20, 20);
186                         toolbar.ButtonClick += new ToolBarButtonClickEventHandler(toolbar_ButtonClick);
187 #endif
188
189                         categorized_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
190                         categorized_toolbarbutton.ToolTipText = Locale.GetText ("Categorized");
191
192                         alphabetic_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
193                         alphabetic_toolbarbutton.ToolTipText = Locale.GetText ("Alphabetic");
194
195                         propertypages_toolbarbutton.Enabled = false;
196                         propertypages_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
197                         propertypages_toolbarbutton.ToolTipText = "Property Pages";
198
199                         properties_tab = CreatePropertyTab (this.DefaultTabType);
200                         selected_tab = properties_tab;
201                         RefreshToolbar (property_tabs);
202                         
203                         reset_menuitem = context_menu.MenuItems.Add("Reset");
204                         reset_menuitem.Click +=new EventHandler(OnResetPropertyClick);
205                         context_menu.MenuItems.Add("-");
206                         description_menuitem = context_menu.MenuItems.Add("Description");
207                         description_menuitem.Click += new EventHandler(OnDescriptionClick);
208                         description_menuitem.Checked = this.HelpVisible;
209                         this.ContextMenu = context_menu;
210                         toolbar.ContextMenu = context_menu;
211                         
212                         BorderHelperControl helper = new BorderHelperControl ();
213                         helper.Dock = DockStyle.Fill;
214                         helper.Controls.Add (property_grid_view);
215                         
216                         this.Controls.Add(helper);
217                         this.Controls.Add(toolbar);
218                         this.Controls.Add(splitter);
219                         this.Controls.Add(help_panel);
220                         this.Name = "PropertyGrid";
221                         this.Size = new System.Drawing.Size(256, 400);
222                 }
223                 #endregion      // Constructors
224
225                 #region Public Instance Properties
226
227                 [BrowsableAttribute(false)]
228                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
229                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
230                 public AttributeCollection BrowsableAttributes {
231                         get {
232                                 if (browsable_attributes == null) {
233                                         browsable_attributes = new AttributeCollection (new Attribute[] { 
234                                                 BrowsableAttribute.Yes });
235                                 }
236                                 return browsable_attributes;
237                         }
238                         set {
239                                 if (browsable_attributes == value)
240                                         return;
241
242                                 if (browsable_attributes == null || browsable_attributes.Count == 0)
243                                         browsable_attributes = null;
244                                 else
245                                         browsable_attributes = value;
246                         }
247                 }
248                 
249                 [Browsable(false)]
250                 [EditorBrowsable(EditorBrowsableState.Never)]
251                 public override bool AutoScroll {
252                         get {
253                                 return base.AutoScroll;
254                         }
255                         set {
256                                 base.AutoScroll = value;
257                         }
258                 }
259
260                 public override Color BackColor {
261                         get {
262                                 return base.BackColor;
263                         }
264
265                         set {
266                                 base.BackColor = value;
267                                 toolbar.BackColor = value;
268                                 Refresh ();
269                         }
270                 }
271                 
272                 [Browsable(false)]
273                 [EditorBrowsable(EditorBrowsableState.Never)]
274                 public override Image BackgroundImage {
275                         get {
276                                 return base.BackgroundImage;
277                         }               
278                         set {
279                                 base.BackgroundImage = value;
280                         }
281                 }
282
283 #if NET_2_0
284                 [EditorBrowsable(EditorBrowsableState.Never)]
285                 [Browsable(false)]
286                 public override ImageLayout BackgroundImageLayout {
287                         get { return base.BackgroundImageLayout; }
288                         set { base.BackgroundImageLayout = value; }
289                 }
290 #endif
291
292                 [BrowsableAttribute(false)]
293                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
294                 public virtual bool CanShowCommands {
295                         get {
296                                 return can_show_commands;
297                         }
298                 }
299 #if NET_2_0
300                 [DefaultValue(typeof(Color), "ControlText")]
301                 public
302 #else
303                 internal
304 #endif
305                 Color CategoryForeColor {
306                         get {
307                                 return category_fore_color;
308                         }
309                         set {
310                                 if (category_fore_color != value) {
311                                         category_fore_color = value;
312                                         Invalidate ();
313                                 }
314                         }
315                 }
316
317                 public Color CommandsBackColor {
318                         get {
319                                 return commands_back_color;
320                         }
321
322                         set {
323                                 if (commands_back_color == value) {
324                                         return;
325                                 }
326                                 commands_back_color = value;
327                         }
328                 }
329
330                 public Color CommandsForeColor {
331                         get {
332                                 return commands_fore_color;
333                         }
334
335                         set {
336                                 if (commands_fore_color == value) {
337                                         return;
338                                 }
339                                 commands_fore_color = value;
340                         }
341                 }
342 #if NET_2_0
343                 public Color CommandsActiveLinkColor {
344                         get {
345                                 return commands_active_link_color;
346                         }
347                         set {
348                                 commands_active_link_color = value;
349                         }
350                 }
351                 
352                 public Color CommandsDisabledLinkColor {
353                         get {
354                                 return commands_disabled_link_color;
355                         }
356                         set {
357                                 commands_disabled_link_color = value;
358                         }
359                 }
360
361                 public Color CommandsLinkColor {
362                         get {
363                                 return commands_link_color;
364                         }
365                         set {
366                                 commands_link_color = value;
367                         }
368                 }
369 #endif
370
371                 [BrowsableAttribute (false)]
372                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
373                 [MonoTODO ("Commands are not implemented yet.")]
374                 public virtual bool CommandsVisible {
375                         get {
376                                 return commands_visible;
377                         }
378                 }
379
380 #if NET_2_0
381                 [DefaultValue (true)]
382 #else
383                 [DefaultValue (false)]
384 #endif
385                 public virtual bool CommandsVisibleIfAvailable {
386                         get {
387                                 return commands_visible_if_available;
388                         }
389
390                         set {
391                                 if (commands_visible_if_available == value) {
392                                         return;
393                                 }
394                                 commands_visible_if_available = value;
395                         }
396                 }
397
398                 [BrowsableAttribute(false)]
399                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
400                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
401                 public Point ContextMenuDefaultLocation {
402                         get {
403                                 return context_menu_default_location;
404                         }
405                 }
406                 
407                 [Browsable(false)]
408                 [EditorBrowsable(EditorBrowsableState.Never)]
409                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
410                 public new Control.ControlCollection Controls {
411                         get {
412                                 return base.Controls;
413                         }
414                 }
415                 
416                 [Browsable(false)]
417                 [EditorBrowsable(EditorBrowsableState.Never)]
418                 public override Color ForeColor {
419                         get {
420                                 return base.ForeColor;
421                         }
422                         set {
423                                 base.ForeColor = value;
424                         }
425                 }
426
427 #if NET_2_0
428                 [DefaultValue ("Color [Control]")]
429 #endif
430                 public Color HelpBackColor {
431                         get {
432                                 return help_panel.BackColor;
433                         }
434                         set {
435                                 help_panel.BackColor = value;
436                         }
437                 }
438
439 #if NET_2_0
440                 [DefaultValue ("Color [ControlText]")]
441 #endif
442                 public Color HelpForeColor {
443                         get {
444                                 return help_panel.ForeColor;
445                         }
446
447                         set {
448                                 help_panel.ForeColor = value;
449                         }
450                 }
451
452                 [DefaultValue(true)]
453                 [Localizable(true)]
454                 public virtual bool HelpVisible {
455                         get {
456                                 return help_panel.Visible;
457                         }
458
459                         set {
460                                 splitter.Visible = value;
461                                 help_panel.Visible = value;
462                         }
463                 }
464
465 #if NET_2_0
466                 [DefaultValue (false)]
467 #endif
468                 public bool LargeButtons {
469                         get {
470                                 return large_buttons;
471                         }
472
473                         set {
474                                 if (large_buttons == value) {
475                                         return;
476                                 }
477
478                                 large_buttons = value;
479                         }
480                 }
481
482 #if NET_2_0
483                 [DefaultValue ("Color [InactiveBorder]")]
484 #endif
485                 public Color LineColor {
486                         get {
487                                 return line_color;
488                         }
489
490                         set {
491                                 if (line_color == value) {
492                                         return;
493                                 }
494
495                                 line_color = value;
496                         }
497                 }
498
499 #if NET_2_0
500                 [EditorBrowsable(EditorBrowsableState.Never)]
501                 [Browsable(false)]
502                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
503                 public new Padding Padding {
504                         get { return base.Padding; }
505                         set { base.Padding = value; }
506                 }
507 #endif
508                 
509                 [DefaultValue(PropertySort.CategorizedAlphabetical)]
510                 public PropertySort PropertySort {
511                         get {
512                                 return property_sort;
513                         }
514
515                         set {
516 #if NET_2_0
517                                 if (!Enum.IsDefined (typeof (PropertySort), value))
518                                         throw new InvalidEnumArgumentException ("value", (int) value, typeof (PropertySort));
519 #endif
520                                 if (property_sort == value)
521                                         return;
522
523                                 // we do not need to update the the grid items and fire
524                                 // a PropertySortChanged event when switching between
525                                 // Categorized and CateogizedAlphabetical
526                                 bool needUpdate = (property_sort & PropertySort.Categorized) == 0 ||
527                                         (value & PropertySort.Categorized) == 0;
528                                 property_sort = value;
529                                 if (needUpdate) {
530                                         UpdateSortLayout (root_grid_item);
531                                         // update selection
532                                         if (selected_grid_item != null) {
533                                                 if (selected_grid_item.GridItemType == GridItemType.Category && 
534                                                     (value == PropertySort.Alphabetical || value == PropertySort.NoSort))
535                                                         SelectItemCore (null, null);
536                                                 else
537                                                         SelectItemCore (null, selected_grid_item);
538                                         }
539                                         property_grid_view.UpdateView ();
540
541 #if NET_2_0
542                                         EventHandler eh = (EventHandler)(Events [PropertySortChangedEvent]);
543                                         if (eh != null)
544                                                 eh (this, EventArgs.Empty);
545 #endif
546                                 }
547                                 UpdatePropertySortButtonsState ();
548                         }
549                 }
550
551                 [BrowsableAttribute(false)]
552                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
553                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
554                 public PropertyTabCollection PropertyTabs {
555                         get { return property_tabs; }
556                 }
557
558                 [BrowsableAttribute(false)]
559                 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
560                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
561                 public GridItem SelectedGridItem {
562                         get { return selected_grid_item; }
563                         set {
564                                 if (value == null)
565                                         throw new ArgumentException ("GridItem specified to PropertyGrid.SelectedGridItem must be a valid GridItem.");
566                                 if (value != selected_grid_item) {
567                                         GridEntry oldItem = selected_grid_item;
568                                         SelectItemCore (oldItem, (GridEntry)value);
569                                         OnSelectedGridItemChanged (new SelectedGridItemChangedEventArgs (oldItem, value));
570                                 }
571                         }
572                 }
573
574                 internal GridItem RootGridItem {
575                         get { return root_grid_item; }
576                 }
577
578                 private void UpdateHelp (GridItem item)
579                 {
580                         if (item == null) {
581                                 help_title_label.Text = string.Empty;
582                                 help_description_label.Text = string.Empty;
583                         } else {
584                                 help_title_label.Text = item.Label;
585                                 if (item.PropertyDescriptor != null)
586                                         this.help_description_label.Text = item.PropertyDescriptor.Description;
587                         }
588                 }
589
590                 private void SelectItemCore (GridEntry oldItem, GridEntry item)
591                 {
592                         UpdateHelp (item);
593                         selected_grid_item = item;
594                         property_grid_view.SelectItem (oldItem, item);
595                 }
596
597                 internal void OnPropertyValueChangedInternal (GridItem item, object property_value) 
598                 {
599                         property_grid_view.UpdateView ();
600                         OnPropertyValueChanged (new PropertyValueChangedEventArgs (item, property_value));
601                 }
602
603                 internal void OnExpandItem (GridEntry item)
604                 {
605                         property_grid_view.ExpandItem (item);
606                 }
607
608                 internal void OnCollapseItem (GridEntry item)
609                 {
610                         property_grid_view.CollapseItem (item);
611                 }
612
613                 internal DialogResult ShowError (string text)
614                 {
615                         return this.ShowError (text, MessageBoxButtons.OK);
616                 }
617
618                 internal DialogResult ShowError (string text, MessageBoxButtons buttons)
619                 {
620                         if (text == null)
621                                 throw new ArgumentNullException ("text");
622                         return MessageBox.Show (this, text, "Properties Window", buttons, MessageBoxIcon.Exclamation);
623                 }
624
625                 [DefaultValue(null)]
626                 [TypeConverter("System.Windows.Forms.PropertyGrid+SelectedObjectConverter, " + Consts.AssemblySystem_Windows_Forms)]
627                 public object SelectedObject {
628                         get {
629                                 if (selected_objects.Length > 0)
630                                         return selected_objects[0];
631                                 return null;
632                         }
633
634                         set {
635                                 if (selected_objects != null && selected_objects.Length == 1 && selected_objects[0] == value)
636                                         return;
637                                 if (value == null)
638                                         SelectedObjects = new object[0];
639                                 else
640                                         SelectedObjects = new object[] {value};
641
642                         }
643                 }
644
645                 [BrowsableAttribute(false)]
646                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
647                 public object[] SelectedObjects {
648                         get {
649                                 return selected_objects;
650                         }
651
652                         set {
653                                 root_grid_item = null;
654                                 SelectItemCore (null, null); // unselect current item in the view
655                                 if (value != null) {
656                                         for (int i = 0; i < value.Length; i++) {
657                                                 if (value [i] == null)
658                                                         throw new ArgumentException (String.Format ("Item {0} in the objs array is null.", i));
659                                         }
660                                         selected_objects = value;
661                                 } else {
662                                         selected_objects = new object [0];
663                                 }
664
665                                 ShowEventsButton (false);
666                                 PopulateGrid (selected_objects);
667                                 RefreshTabs(PropertyTabScope.Component);
668                                 if (root_grid_item != null)
669                                         SelectItemCore (null, GetDefaultPropertyItem (root_grid_item, selected_tab));
670                                 property_grid_view.UpdateView ();
671                                 OnSelectedObjectsChanged (EventArgs.Empty);
672                         }
673                 }
674
675                 [BrowsableAttribute(false)]
676                 [EditorBrowsable(EditorBrowsableState.Advanced)]
677                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
678                 public PropertyTab SelectedTab {
679                         get { return selected_tab; }
680                 }
681
682                 public override ISite Site {
683                         get { return base.Site; }
684                         set { base.Site = value; }
685                 }
686
687 #if NET_2_0
688                 [Browsable (false)]
689                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
690                 public override string Text {
691                         get { return base.Text; }
692                         set { base.Text = value; }
693                 }
694  #endif
695
696                 [DefaultValue(true)]
697                 public virtual bool ToolbarVisible {
698                         get { return toolbar.Visible; }
699                         set {
700                                 if (toolbar.Visible == value) {
701                                         return;
702                                 }
703
704                                 toolbar.Visible = value;
705                         }
706                 }
707                 
708 #if NET_2_0
709                 protected ToolStripRenderer ToolStripRenderer {
710                         get {
711                                 if (toolbar != null) {
712                                         return toolbar.Renderer;
713                                 }
714                                 return null;
715                         }
716                         set {
717                                 if (toolbar != null) {
718                                         toolbar.Renderer = value;
719                                 }
720                         }
721                 }
722  
723 #endif
724
725 #if NET_2_0
726                 [DefaultValue ("Color [Window]")]
727 #endif
728                 public Color ViewBackColor {
729                         get { return property_grid_view.BackColor; }
730                         set {
731                                 if (property_grid_view.BackColor == value) {
732                                         return;
733                                 }
734
735                                 property_grid_view.BackColor = value;
736                         }
737                 }
738
739 #if NET_2_0
740                 [DefaultValue ("Color [WindowText]")]
741 #endif
742                 public Color ViewForeColor {
743                         get { return property_grid_view.ForeColor; }
744                         set {
745                                 if (property_grid_view.ForeColor == value) {
746                                         return;
747                                 }
748
749                                 property_grid_view.ForeColor = value;
750                         }
751                 }
752 #if NET_2_0
753
754                 [DefaultValue (false)]
755                 public bool UseCompatibleTextRendering {
756                         get { return use_compatible_text_rendering; }
757                         set {
758                                 if (use_compatible_text_rendering != value) {
759                                         use_compatible_text_rendering = value;
760                                         if (Parent != null)
761                                                 Parent.PerformLayout (this, "UseCompatibleTextRendering");
762                                         Invalidate ();
763                                 }
764                         }
765                 }
766 #endif
767
768                 #endregion      // Public Instance Properties
769
770                 #region Protected Instance Properties
771
772                 protected override Size DefaultSize {
773                         get { return base.DefaultSize; }
774                 }
775
776
777                 [Browsable(false)]
778                 [EditorBrowsable(EditorBrowsableState.Advanced)]
779                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
780                 protected virtual Type DefaultTabType {
781                         get { return typeof(PropertiesTab); }
782                 }
783                 
784                 protected bool DrawFlatToolbar {
785                         get { return (toolbar.Appearance == ToolBarAppearance.Flat); }                  
786                         set {
787                                 if (value) 
788                                         toolbar.Appearance = ToolBarAppearance.Flat;
789                                 else
790                                         toolbar.Appearance = ToolBarAppearance.Normal;
791                         }
792                 }
793
794                 protected internal override bool ShowFocusCues {
795                         get { return base.ShowFocusCues; }
796                 }
797
798                 #endregion      // Protected Instance Properties
799
800                 #region Public Instance Methods
801                 
802                 protected override void Dispose(bool disposing) {
803                         base.Dispose(disposing);
804                 }
805
806                 public void CollapseAllGridItems () 
807                 {
808                         GridEntry category = FindCategoryItem (selected_grid_item);
809                         if (category != null)
810                                 SelectedGridItem = category;
811                         CollapseItemRecursive (root_grid_item);
812                         property_grid_view.UpdateView ();
813                 }
814
815                 private void CollapseItemRecursive (GridItem item)
816                 {
817                         if (item == null)
818                                 return;
819
820                         foreach (GridItem child in item.GridItems) {
821                                 CollapseItemRecursive (child);
822                                 if (child.Expandable)
823                                         child.Expanded = false;
824                         }
825                 }
826
827                 private GridEntry FindCategoryItem (GridEntry entry)
828                 {
829                         if (entry == null || (property_sort != PropertySort.Categorized && 
830                             property_sort != PropertySort.CategorizedAlphabetical))
831                                 return null;
832
833                         if (entry.GridItemType == GridItemType.Category)
834                                 return entry;
835
836                         GridEntry category = null;
837                         GridItem current = (GridItem)entry;
838                         while (category == null) {
839                                 if (current.Parent != null && current.Parent.GridItemType == GridItemType.Category)
840                                         category = (GridEntry) current.Parent;
841                                 current = current.Parent;
842                                 if (current == null)
843                                         break;
844                         }
845                         return (GridEntry) category;
846                 }
847
848                 public void ExpandAllGridItems () 
849                 {
850                         ExpandItemRecursive (root_grid_item);
851                         property_grid_view.UpdateView ();
852                 }
853
854                 private void ExpandItemRecursive (GridItem item)
855                 {
856                         if (item == null)
857                                 return;
858
859                         foreach (GridItem child in item.GridItems) {
860                                 ExpandItemRecursive (child);
861                                 if (child.Expandable)
862                                         child.Expanded = true;
863                         }
864                 }
865
866                 public override void Refresh () 
867                 {
868                         base.Refresh ();
869                         // force a full reload here
870                         SelectedObjects = SelectedObjects;
871                 }
872
873                 private void toolbar_Clicked (PropertyToolBarButton button)
874                 {
875                         if (button == null) 
876                                 return;
877
878                         if (button == alphabetic_toolbarbutton) {
879                                 this.PropertySort = PropertySort.Alphabetical;
880                                 alphabetic_toolbarbutton.Pushed = true;
881                                 categorized_toolbarbutton.Pushed = false;
882                         } else if (button == categorized_toolbarbutton) {
883                                 this.PropertySort = PropertySort.CategorizedAlphabetical;
884                                 categorized_toolbarbutton.Pushed = true;
885                                 alphabetic_toolbarbutton.Pushed = false;
886                         } else {
887                                 if (button.Enabled)
888                                         SelectPropertyTab (button.PropertyTab);
889                         }
890                 }
891
892 #if NET_2_0
893                 private void toolbarbutton_clicked (object o, EventArgs args)
894                 {
895                         toolbar_Clicked (o as PropertyToolBarButton);
896                 }
897 #endif
898
899                 private void SelectPropertyTab (PropertyTab propertyTab)
900                 {
901                         if (propertyTab != null && selected_tab != propertyTab) {
902                                 foreach (object toolbarItem in toolbar.Items) {
903                                         PropertyToolBarButton button = toolbarItem as PropertyToolBarButton;
904                                         if (button != null && button.PropertyTab != null) {
905                                                 if (button.PropertyTab == selected_tab)
906                                                         button.Pushed = false;
907                                                 else if (button.PropertyTab == propertyTab)
908                                                         button.Pushed = true;
909                                         }
910                                 }
911                                 selected_tab = propertyTab;
912                                 PopulateGrid (selected_objects);
913                                 SelectItemCore (null, GetDefaultPropertyItem (root_grid_item, selected_tab));
914                                 property_grid_view.UpdateView ();
915                         }
916                 }
917
918                 private void UpdatePropertySortButtonsState ()
919                 {
920                         if (property_sort == PropertySort.NoSort) {
921                                 alphabetic_toolbarbutton.Pushed = false;
922                                 categorized_toolbarbutton.Pushed = false;
923                         } else if (property_sort == PropertySort.Alphabetical) {
924                                 alphabetic_toolbarbutton.Pushed = true;
925                                 categorized_toolbarbutton.Pushed = false;
926                         } else if (property_sort == PropertySort.Categorized || 
927                                    property_sort == PropertySort.CategorizedAlphabetical) {
928                                 alphabetic_toolbarbutton.Pushed = false;
929                                 categorized_toolbarbutton.Pushed = true;
930                         }
931                 }
932                 
933                 protected void ShowEventsButton (bool value) 
934                 {
935                         if (value && property_tabs.Contains (typeof (EventsTab)))
936                                 events_tab_visible = true;
937                         else
938                                 events_tab_visible = false;
939                         RefreshTabs (PropertyTabScope.Component);
940                 }
941
942                 public void RefreshTabs (PropertyTabScope tabScope) 
943                 {
944                         property_tabs.Clear (tabScope);
945                         if (selected_objects != null) {
946                                 Type[] tabTypes = null;
947                                 PropertyTabScope[] tabScopes = null;
948
949                                 if (events_tab_visible && property_tabs.Contains (typeof (EventsTab)))
950                                         property_tabs.InsertTab (0, properties_tab, PropertyTabScope.Component);
951
952                                 GetMergedPropertyTabs (selected_objects, out tabTypes, out tabScopes);
953                                 if (tabTypes != null && tabScopes != null && tabTypes.Length > 0) {
954                                         bool selectedTabPreserved = false;
955                                         for (int i=0; i < tabTypes.Length; i++) {
956                                                 property_tabs.AddTabType (tabTypes[i], tabScopes[i]);
957                                                 if (tabTypes[i] == selected_tab.GetType ())
958                                                         selectedTabPreserved = true;
959                                         }
960                                         if (!selectedTabPreserved)
961                                                 SelectPropertyTab (properties_tab);
962                                 }
963                         } else {
964                                 SelectPropertyTab (properties_tab);
965                         }
966                         RefreshToolbar (property_tabs);
967                 }
968
969                 private void RefreshToolbar (PropertyTabCollection tabs)
970                 {
971                         EnsurePropertiesTab ();
972
973                         toolbar.SuspendLayout ();
974                         toolbar.Items.Clear ();
975                         toolbar_imagelist.Images.Clear ();
976
977                         int imageIndex = 0;
978                         toolbar.Items.Add (categorized_toolbarbutton);
979                         toolbar_imagelist.Images.Add (categorized_image);
980                         categorized_toolbarbutton.ImageIndex = imageIndex;
981                         imageIndex++;
982                         toolbar.Items.Add (alphabetic_toolbarbutton);
983                         toolbar_imagelist.Images.Add (alphabetical_image);
984                         alphabetic_toolbarbutton.ImageIndex = imageIndex;
985                         imageIndex++;
986                         toolbar.Items.Add (separator_toolbarbutton);
987                         if (tabs != null && tabs.Count > 0) {
988                                 foreach (PropertyTab tab in tabs) {
989                                         PropertyToolBarButton button = new PropertyToolBarButton (tab);
990                                         toolbar.Items.Add (button);
991                                         if (tab.Bitmap != null) {
992                                                 tab.Bitmap.MakeTransparent ();
993                                                 toolbar_imagelist.Images.Add (tab.Bitmap);
994                                                 button.ImageIndex = imageIndex;
995                                                 imageIndex++;
996                                         }
997                                         if (tab == selected_tab)
998                                                 button.Pushed = true;
999                                 }
1000                                 toolbar.Items.Add (new PropertyToolBarSeparator ());
1001                         }
1002
1003                         toolbar.Items.Add (propertypages_toolbarbutton);
1004                         toolbar_imagelist.Images.Add (propertypages_image);
1005                         propertypages_toolbarbutton.ImageIndex = imageIndex;
1006                         
1007                         toolbar.ResumeLayout ();
1008                 }
1009
1010                 private void EnsurePropertiesTab ()
1011                 {
1012                         if (property_tabs == null)
1013                                 return;
1014
1015                         if (property_tabs.Count > 0 && !property_tabs.Contains (this.DefaultTabType))
1016                                 property_tabs.InsertTab (0, properties_tab, PropertyTabScope.Component);
1017                 }
1018
1019                 private void GetMergedPropertyTabs (object[] objects, out Type[] tabTypes, out PropertyTabScope[] tabScopes)
1020                 {
1021                         tabTypes = null;
1022                         tabScopes = null;
1023                         if (objects == null || objects.Length == 0)
1024                                 return;
1025
1026                         ArrayList intersection = null;
1027                         ArrayList scopes = new ArrayList ();
1028                         for (int i=0; i < objects.Length; i++) {
1029                                 if (objects[i] == null)
1030                                         continue;
1031                                 PropertyTabAttribute tabAttribute = (PropertyTabAttribute)TypeDescriptor.GetAttributes (objects[i])[typeof (PropertyTabAttribute)];
1032                                 if (tabAttribute == null || tabAttribute.TabClasses == null || tabAttribute.TabClasses.Length == 0)
1033                                         return;
1034
1035                                 ArrayList new_intersection = new ArrayList ();
1036                                 scopes.Clear ();
1037                                 IList currentIntersection = (i == 0 ? (IList)tabAttribute.TabClasses : (IList)intersection);
1038                                 for (int j=0; j < currentIntersection.Count; j++) {
1039                                         if ((Type)intersection[j] == tabAttribute.TabClasses[j]) {
1040                                                 new_intersection.Add (tabAttribute.TabClasses[j]);
1041                                                 scopes.Add (tabAttribute.TabScopes[j]);
1042                                         }
1043                                 }
1044                                 intersection = new_intersection;
1045                         }
1046
1047                         tabTypes = new Type[intersection.Count];
1048                         intersection.CopyTo (tabTypes);
1049                         tabScopes = new PropertyTabScope[tabTypes.Length];
1050                         scopes.CopyTo (tabScopes);
1051                 }
1052
1053                 public void ResetSelectedProperty() 
1054                 {
1055                         if (selected_grid_item == null)
1056                                 return;
1057                         selected_grid_item.ResetValue ();
1058                 }
1059                 #endregion      // Public Instance Methods
1060
1061                 #region Protected Instance Methods
1062
1063                 protected virtual PropertyTab CreatePropertyTab (Type tabType) 
1064                 {
1065                         if (!typeof(PropertyTab).IsAssignableFrom (tabType))
1066                                 return null;
1067
1068                         PropertyTab tab = null;
1069
1070                         ConstructorInfo ctor = tabType.GetConstructor (new Type[] { typeof (IServiceProvider) });
1071                         if (ctor != null)
1072                                 tab = (PropertyTab)ctor.Invoke (new object[] { this.Site });
1073                         else
1074                                 tab = (PropertyTab)Activator.CreateInstance (tabType);
1075                         return tab;
1076                 }
1077                 
1078                 [MonoTODO ("Never called")]
1079                 protected void OnComComponentNameChanged(ComponentRenameEventArgs e)
1080                 {
1081                         ComponentRenameEventHandler eh = (ComponentRenameEventHandler)(Events [ComComponentNameChangedEvent]);
1082                         if (eh != null)
1083                                 eh (this, e);
1084                 }
1085
1086 #if NET_2_0
1087                 protected override void OnEnabledChanged (EventArgs e) {
1088                         base.OnEnabledChanged (e);
1089                 }
1090
1091 #endif
1092                 
1093                 protected override void OnFontChanged(EventArgs e) {
1094                         base.OnFontChanged (e);
1095                 }
1096
1097                 protected override void OnGotFocus(EventArgs e) {
1098                         base.OnGotFocus(e);
1099                 }
1100
1101                 protected override void OnHandleCreated (EventArgs e) {
1102                         base.OnHandleCreated (e);
1103                 }
1104
1105                 protected override void OnHandleDestroyed (EventArgs e) {
1106                         base.OnHandleDestroyed (e);
1107                 }
1108
1109                 protected override void OnMouseDown (MouseEventArgs me) {
1110                         base.OnMouseDown (me);
1111                 }
1112
1113                 protected override void OnMouseMove (MouseEventArgs me) {
1114                         base.OnMouseMove (me);
1115                 }
1116
1117                 protected override void OnMouseUp (MouseEventArgs me) {
1118                         base.OnMouseUp (me);
1119                 }
1120                 
1121                 protected void OnNotifyPropertyValueUIItemsChanged(object sender, EventArgs e) 
1122                 {
1123                         property_grid_view.UpdateView ();
1124                 }
1125
1126                 protected override void OnPaint (PaintEventArgs pevent) {
1127                         pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
1128                         base.OnPaint (pevent);
1129                 }
1130
1131 #if NET_2_0
1132                 protected virtual void OnPropertySortChanged(EventArgs e) {
1133                         EventHandler eh = (EventHandler) Events [PropertySortChangedEvent];
1134                         if (eh != null)
1135                                 eh (this, e);
1136                 }               
1137 #endif
1138                 
1139                 protected virtual void OnPropertyTabChanged (PropertyTabChangedEventArgs e) 
1140                 {
1141                         PropertyTabChangedEventHandler eh = (PropertyTabChangedEventHandler)(Events [PropertyTabChangedEvent]);
1142                         if (eh != null)
1143                                 eh (this, e);
1144                 }
1145
1146                 protected virtual void OnPropertyValueChanged (PropertyValueChangedEventArgs e) {
1147                         PropertyValueChangedEventHandler eh = (PropertyValueChangedEventHandler)(Events [PropertyValueChangedEvent]);
1148                         if (eh != null)
1149                                 eh (this, e);
1150                 }
1151
1152                 protected override void OnResize (EventArgs e) {
1153                         base.OnResize (e);
1154                 }
1155
1156                 protected virtual void OnSelectedGridItemChanged (SelectedGridItemChangedEventArgs e) {
1157                         SelectedGridItemChangedEventHandler eh = (SelectedGridItemChangedEventHandler)(Events [SelectedGridItemChangedEvent]);
1158                         if (eh != null)
1159                                 eh (this, e);
1160                 }
1161
1162                 protected virtual void OnSelectedObjectsChanged (EventArgs e) {
1163                         EventHandler eh = (EventHandler)(Events [SelectedObjectsChangedEvent]);
1164                         if (eh != null)
1165                                 eh (this, e);
1166                 }
1167
1168                 protected override void OnSystemColorsChanged (EventArgs e) {
1169                         base.OnSystemColorsChanged (e);
1170                 }
1171
1172                 protected override void OnVisibleChanged (EventArgs e) {
1173                         base.OnVisibleChanged (e);
1174                 }
1175
1176                 protected override bool ProcessDialogKey (Keys keyData) {
1177                         return base.ProcessDialogKey (keyData);
1178                 }
1179
1180 #if NET_2_0
1181                 [EditorBrowsable (EditorBrowsableState.Never)]
1182 #endif
1183                 protected override void ScaleCore (float dx, float dy) {
1184                         base.ScaleCore (dx, dy);
1185                 }
1186                 
1187                 protected override void WndProc (ref Message m) 
1188                 {
1189                         base.WndProc (ref m);
1190                 }
1191                 #endregion
1192
1193                 #region Events
1194                 static object PropertySortChangedEvent = new object ();
1195                 static object PropertyTabChangedEvent = new object ();
1196                 static object PropertyValueChangedEvent = new object ();
1197                 static object SelectedGridItemChangedEvent = new object ();
1198                 static object SelectedObjectsChangedEvent = new object ();
1199
1200                 public event EventHandler PropertySortChanged {
1201                         add { Events.AddHandler (PropertySortChangedEvent, value); }
1202                         remove { Events.RemoveHandler (PropertySortChangedEvent, value); }
1203                 }
1204
1205                 public event PropertyTabChangedEventHandler PropertyTabChanged {
1206                         add { Events.AddHandler (PropertyTabChangedEvent, value); }
1207                         remove { Events.RemoveHandler (PropertyTabChangedEvent, value); }
1208                 }
1209
1210                 public event PropertyValueChangedEventHandler PropertyValueChanged {
1211                         add { Events.AddHandler (PropertyValueChangedEvent, value); }
1212                         remove { Events.RemoveHandler (PropertyValueChangedEvent, value); }
1213                 }
1214
1215                 public event SelectedGridItemChangedEventHandler SelectedGridItemChanged {
1216                         add { Events.AddHandler (SelectedGridItemChangedEvent, value); }
1217                         remove { Events.RemoveHandler (SelectedGridItemChangedEvent, value); }
1218                 }
1219
1220                 public event EventHandler SelectedObjectsChanged {
1221                         add { Events.AddHandler (SelectedObjectsChangedEvent, value); }
1222                         remove { Events.RemoveHandler (SelectedObjectsChangedEvent, value); }
1223                 }
1224                 
1225                 [Browsable(false)]
1226                 [EditorBrowsable(EditorBrowsableState.Never)]
1227                 public new event EventHandler BackgroundImageChanged {
1228                         add { base.BackgroundImageChanged += value; }
1229                         remove { base.BackgroundImageChanged -= value; }
1230                 }
1231
1232 #if NET_2_0
1233                 [Browsable(false)]
1234                 [EditorBrowsable(EditorBrowsableState.Never)]
1235                 public new event EventHandler BackgroundImageLayoutChanged {
1236                         add { base.BackgroundImageLayoutChanged += value; }
1237                         remove { base.BackgroundImageLayoutChanged -= value; }
1238                 }
1239 #endif
1240                 
1241                 [Browsable(false)]
1242                 [EditorBrowsable(EditorBrowsableState.Never)]
1243                 public new event EventHandler ForeColorChanged {
1244                         add { base.ForeColorChanged += value; }
1245                         remove { base.ForeColorChanged -= value; }
1246                 }
1247 #if NET_2_0
1248                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1249                 [Browsable(false)]
1250                 public new event KeyEventHandler KeyDown {
1251                         add { base.KeyDown += value; }
1252                         remove { base.KeyDown -= value; }
1253                 }
1254                 
1255                 [Browsable(false)]
1256                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1257                 public new event KeyPressEventHandler KeyPress {
1258                         add { base.KeyPress += value; }
1259                         remove { base.KeyPress -= value; }
1260                 }
1261                 
1262                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1263                 [Browsable(false)]
1264                 public new event KeyEventHandler KeyUp {
1265                         add { base.KeyUp += value; }
1266                         remove { base.KeyUp -= value; }
1267                 }
1268
1269                 [Browsable(false)]
1270                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1271                 public new event MouseEventHandler MouseDown {
1272                         add { base.MouseDown += value; }
1273                         remove { base.MouseDown -= value; }
1274                 }
1275                 
1276                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1277                 [Browsable(false)]
1278                 public new event EventHandler MouseEnter {
1279                         add { base.MouseEnter += value; }
1280                         remove { base.MouseEnter -= value; }
1281                 }
1282
1283                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1284                 [Browsable(false)]
1285                 public new event EventHandler MouseLeave {
1286                         add { base.MouseLeave += value; }
1287                         remove { base.MouseLeave -= value; }
1288                 }
1289
1290                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1291                 [Browsable(false)]
1292                 public new event MouseEventHandler MouseMove {
1293                         add { base.MouseMove += value; }
1294                         remove { base.MouseMove -= value; }
1295                 }
1296                 
1297                 [EditorBrowsable(EditorBrowsableState.Advanced)]
1298                 [Browsable(false)]
1299                 public new event MouseEventHandler MouseUp {
1300                         add { base.MouseUp += value; }
1301                         remove { base.MouseUp -= value; }
1302                 }
1303                 
1304                 [Browsable(false)]
1305                 [EditorBrowsable(EditorBrowsableState.Never)]
1306                 public new event EventHandler PaddingChanged {
1307                         add { base.PaddingChanged += value; }
1308                         remove { base.PaddingChanged -= value; }
1309                 }
1310                 
1311                 [Browsable(false)]
1312                 public new event EventHandler TextChanged {
1313                         add { base.TextChanged += value; }
1314                         remove { base.TextChanged -= value; }
1315                 }
1316 #endif
1317                 #endregion
1318
1319                 #region Com2Interop.IComPropertyBrowser Interface
1320                 [MonoTODO ("Not implemented, will throw NotImplementedException")]
1321                 bool ComponentModel.Com2Interop.IComPropertyBrowser.InPropertySet {
1322                         get {
1323                                 throw new NotImplementedException();
1324                         }
1325                 }
1326
1327                 [MonoTODO ("Stub, does nothing")]
1328                 void ComponentModel.Com2Interop.IComPropertyBrowser.DropDownDone ()
1329                 {
1330                 }
1331
1332                 [MonoTODO ("Not implemented, will throw NotImplementedException")]
1333                 bool ComponentModel.Com2Interop.IComPropertyBrowser.EnsurePendingChangesCommitted ()
1334                 {
1335                         throw new NotImplementedException ();
1336                 }
1337
1338                 [MonoTODO ("Stub, does nothing")]
1339                 void ComponentModel.Com2Interop.IComPropertyBrowser.HandleF4 ()
1340                 {
1341                 }
1342
1343                 [MonoTODO ("Stub, does nothing")]
1344                 void ComponentModel.Com2Interop.IComPropertyBrowser.LoadState (Microsoft.Win32.RegistryKey optRoot)
1345                 {
1346                 }
1347
1348                 [MonoTODO ("Stub, does nothing")]
1349                 void ComponentModel.Com2Interop.IComPropertyBrowser.SaveState (Microsoft.Win32.RegistryKey optRoot)
1350                 {
1351                 }
1352
1353                 static object ComComponentNameChangedEvent = new object ();
1354                 event ComponentRenameEventHandler ComponentModel.Com2Interop.IComPropertyBrowser.ComComponentNameChanged {
1355                         add { Events.AddHandler (ComComponentNameChangedEvent, value); }
1356                         remove { Events.RemoveHandler (ComComponentNameChangedEvent, value); }
1357                 }
1358                 #endregion      // Com2Interop.IComPropertyBrowser Interface
1359
1360                 #region PropertyTabCollection Class
1361                 public class PropertyTabCollection : ICollection, IEnumerable 
1362                 {
1363                         ArrayList property_tabs;
1364                         ArrayList property_tabs_scopes;
1365                         PropertyGrid property_grid;
1366
1367                         internal PropertyTabCollection (PropertyGrid propertyGrid) 
1368                         {
1369                                 property_grid = propertyGrid;
1370                                 property_tabs = new ArrayList ();
1371                                 property_tabs_scopes = new ArrayList ();
1372                         }
1373
1374                         public PropertyTab this[int index] {
1375                                 get { return (PropertyTab)property_tabs[index]; }
1376                         }
1377                 
1378                         bool ICollection.IsSynchronized {
1379                                 get { return property_tabs.IsSynchronized; }
1380                         }
1381
1382                         void ICollection.CopyTo (Array dest, int index)
1383                         {
1384                                 property_tabs.CopyTo (dest, index);
1385                         }
1386
1387                         object ICollection.SyncRoot {
1388                                 get { return property_tabs.SyncRoot; }
1389                         }
1390
1391                         public IEnumerator GetEnumerator ()
1392                         {
1393                                 return property_tabs.GetEnumerator ();
1394                         }
1395
1396                         public int Count {
1397                                 get { return property_tabs.Count; }
1398                         }
1399
1400                         public void AddTabType (Type propertyTabType)
1401                         {
1402                                 AddTabType (propertyTabType, PropertyTabScope.Global);
1403                         }
1404
1405                         public void AddTabType (Type propertyTabType, PropertyTabScope tabScope)
1406                         {
1407                                 if (propertyTabType == null)
1408                                         throw new ArgumentNullException ("propertyTabType");
1409
1410                                 // Avoid duplicates
1411                                 if (this.Contains (propertyTabType))
1412                                         return;
1413                                 PropertyTab tab = property_grid.CreatePropertyTab (propertyTabType);
1414                                 if (tab != null) {
1415                                         property_tabs.Add (tab);
1416                                         property_tabs_scopes.Add (tabScope);
1417                                 }
1418                                 property_grid.RefreshToolbar (this);
1419                         }
1420
1421                         internal PropertyTabScope GetTabScope (PropertyTab tab)
1422                         {
1423                                 if (tab == null)
1424                                         throw new ArgumentNullException ("tab");
1425
1426                                 int index = property_tabs.IndexOf (tab);
1427                                 if (index != -1)
1428                                         return (PropertyTabScope)property_tabs_scopes[index];
1429                                 return PropertyTabScope.Global;
1430                         }
1431
1432                         internal void InsertTab (int index, PropertyTab propertyTab, PropertyTabScope tabScope)
1433                         {
1434                                 if (propertyTab == null)
1435                                         throw new ArgumentNullException ("propertyTab");
1436                                 
1437                                 if (!this.Contains (propertyTab.GetType ())) {
1438                                         property_tabs.Insert (index, propertyTab);
1439                                         property_tabs_scopes.Insert (index, tabScope);
1440                                 }
1441                         }
1442
1443                         internal bool Contains (Type propertyType)
1444                         {
1445                                 if (propertyType == null)
1446                                         throw new ArgumentNullException ("propertyType");
1447
1448                                 foreach (PropertyTab t in property_tabs) {
1449                                         if (t.GetType () == propertyType)
1450                                                 return true;
1451                                 }
1452                                 return false;
1453                         }
1454
1455                         internal PropertyTab this[Type tabType] {
1456                                 get {
1457                                         foreach (PropertyTab tab in property_tabs) {
1458                                                 if (tabType == tab.GetType ())
1459                                                         return tab;
1460                                         }
1461                                         return null;
1462                                 }
1463                         }
1464
1465                         public void Clear (PropertyTabScope tabScope)
1466                         {
1467                                 ArrayList toRemove = new ArrayList ();
1468                                 for (int i=0; i < property_tabs_scopes.Count; i++) {
1469                                         if ((PropertyTabScope)property_tabs_scopes[i] == tabScope)
1470                                                 toRemove.Add (i);
1471                                 }
1472                                 foreach (int indexToRemove in toRemove) {
1473                                         property_tabs.RemoveAt (indexToRemove);
1474                                         property_tabs_scopes.RemoveAt (indexToRemove);
1475                                 }
1476                                 property_grid.RefreshToolbar (this);
1477                         }
1478
1479                         public void RemoveTabType (Type propertyTabType)
1480                         {
1481                                 if (propertyTabType == null)
1482                                         throw new ArgumentNullException ("propertyTabType");
1483
1484                                 ArrayList toRemove = new ArrayList ();
1485                                 for (int i=0; i < property_tabs.Count; i++) {
1486                                         if (property_tabs[i].GetType () == propertyTabType)
1487                                                 toRemove.Add (i);
1488                                 }
1489                                 foreach (int indexToRemove in toRemove) {
1490                                         property_tabs.RemoveAt (indexToRemove);
1491                                         property_tabs_scopes.RemoveAt (indexToRemove);
1492                                 }
1493                                 property_grid.RefreshToolbar (this);
1494                         }
1495                 }
1496                 #endregion      // PropertyTabCollection Class
1497
1498                 #region Private Helper Methods
1499
1500                 private GridItem FindFirstPropertyItem (GridItem root)
1501                 {
1502                         if (root.GridItemType == GridItemType.Property)
1503                                 return root;
1504
1505                         foreach (GridItem item in root.GridItems) {
1506                                 GridItem subitem = FindFirstPropertyItem (item);
1507                                 if (subitem != null)
1508                                         return subitem;
1509                         }
1510
1511                         return null;
1512                 }
1513
1514                 private GridEntry GetDefaultPropertyItem (GridEntry rootItem, PropertyTab propertyTab)
1515                 {
1516                         if (rootItem == null || rootItem.GridItems.Count == 0 || propertyTab == null)
1517                                 return null;
1518                         object[] propertyOwners = rootItem.Values;
1519                         if (propertyOwners == null || propertyOwners.Length == 0 || propertyOwners[0] == null)
1520                                 return null;
1521
1522                         GridItem defaultSelected = null;
1523                         if (propertyOwners.Length > 1)
1524                                 defaultSelected = rootItem.GridItems[0];
1525                         else {
1526                                 PropertyDescriptor defaultProperty = propertyTab.GetDefaultProperty (propertyOwners[0]);
1527                                 if (defaultProperty != null)
1528                                         defaultSelected = FindItem (defaultProperty.Name, rootItem);
1529                                 if (defaultSelected == null)
1530                                         defaultSelected = FindFirstPropertyItem (rootItem);
1531                         }
1532
1533                         return defaultSelected as GridEntry;
1534                 }
1535
1536                 private GridEntry FindItem (string name, GridEntry rootItem)
1537                 {
1538                         if (rootItem == null || name == null)
1539                                 return null;
1540
1541                         if (property_sort == PropertySort.Alphabetical || property_sort == PropertySort.NoSort) {
1542                                 foreach (GridItem item in rootItem.GridItems) {
1543                                         if (item.Label == name) {
1544                                                 return (GridEntry)item;
1545                                         }
1546                                 }
1547                         } else if (property_sort == PropertySort.Categorized || 
1548                                    property_sort == PropertySort.CategorizedAlphabetical) {
1549                                 foreach (GridItem categoryItem in rootItem.GridItems) {
1550                                         foreach (GridItem item in categoryItem.GridItems) {
1551                                                 if (item.Label == name) {
1552                                                         return (GridEntry)item;
1553                                                 }
1554                                         }
1555                                 }
1556                         }
1557
1558                         return null;
1559                 }
1560
1561 #if !NET_2_0
1562                 private void toolbar_ButtonClick (object sender, ToolBarButtonClickEventArgs e)
1563                 {
1564                         toolbar_Clicked (e.Button as PropertyToolBarButton);
1565                 }
1566 #endif
1567
1568                 private void OnResetPropertyClick (object sender, EventArgs e)
1569                 {
1570                         ResetSelectedProperty();
1571                 }
1572
1573                 private void OnDescriptionClick (object sender, EventArgs e)
1574                 {
1575                         this.HelpVisible = !this.HelpVisible;
1576                         description_menuitem.Checked = this.HelpVisible;
1577                 }
1578
1579                 private void PopulateGrid (object[] objects) 
1580                 {
1581                         if (objects.Length > 0) {
1582                                 root_grid_item = new RootGridEntry (this, objects);
1583                                 root_grid_item.Expanded = true;
1584                                 UpdateSortLayout (root_grid_item);
1585                         } else {
1586                                 root_grid_item = null;
1587                         }
1588                 }
1589
1590                 private void UpdateSortLayout (GridEntry rootItem)
1591                 {
1592                         if (rootItem == null)
1593                                 return;
1594
1595                         GridItemCollection reordered = new GridItemCollection ();
1596
1597                         if (property_sort == PropertySort.Alphabetical || property_sort == PropertySort.NoSort) {
1598                                 alphabetic_toolbarbutton.Pushed = true;
1599                                 categorized_toolbarbutton.Pushed = false;
1600                                 foreach (GridItem item in rootItem.GridItems) {
1601                                         if (item.GridItemType == GridItemType.Category) {
1602                                                 foreach (GridItem categoryChild in item.GridItems) {
1603                                                         reordered.Add (categoryChild);
1604                                                         ((GridEntry)categoryChild).SetParent (rootItem);
1605                                                 }
1606                                         } else {
1607                                                 reordered.Add (item);
1608                                         }
1609                                 }
1610                         } else if (property_sort == PropertySort.Categorized || 
1611                                    property_sort == PropertySort.CategorizedAlphabetical) {
1612                                 alphabetic_toolbarbutton.Pushed = false;
1613                                 categorized_toolbarbutton.Pushed = true;
1614                                 GridItemCollection categories = new GridItemCollection ();
1615
1616                                 foreach (GridItem item in rootItem.GridItems) {
1617                                         if (item.GridItemType == GridItemType.Category) {
1618                                                 categories.Add (item);
1619                                                 continue;
1620                                         }
1621
1622                                         string categoryName = item.PropertyDescriptor.Category;
1623                                         if (categoryName == null)
1624                                                 categoryName = UNCATEGORIZED_CATEGORY_LABEL;
1625                                         GridItem category_item = rootItem.GridItems [categoryName];
1626                                         if (category_item == null)
1627                                                 category_item = categories [categoryName];
1628
1629                                         if (category_item == null) {
1630                                                 // Create category grid items if they already don't
1631                                                 category_item = new CategoryGridEntry (this, categoryName, rootItem);
1632                                                 category_item.Expanded = true;
1633                                                 categories.Add (category_item);
1634                                         }
1635
1636                                         category_item.GridItems.Add (item);
1637                                         ((GridEntry)item).SetParent (category_item);
1638                                 }
1639
1640                                 reordered.AddRange (categories);
1641                         }
1642
1643                         rootItem.GridItems.Clear ();
1644                         rootItem.GridItems.AddRange (reordered);
1645                 }
1646
1647                 private void help_panel_Paint(object sender, PaintEventArgs e) {
1648                         e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(help_panel.BackColor), help_panel.ClientRectangle );
1649                         e.Graphics.DrawRectangle(SystemPens.ControlDark, 0,0,help_panel.Width-1,help_panel.Height-1 );
1650                 }
1651
1652                 #endregion      // Private Helper Methods
1653
1654 #region Internal helper classes
1655                 // as we can not change the color for BorderStyle.FixedSingle and we need the correct
1656                 // ClientRectangle so that the ScrollBar doesn't draw over the border we need this class
1657                 internal class BorderHelperControl : Control {
1658
1659                         public BorderHelperControl ()
1660                         {
1661                                 BackColor = ThemeEngine.Current.ColorWindow;
1662                         }
1663
1664                         protected override void OnPaint (PaintEventArgs e)
1665                         {
1666                                 e.Graphics.DrawRectangle (SystemPens.ControlDark, 0 , 0 , Width - 1, Height - 1);
1667                                 base.OnPaint (e);
1668                         }
1669                         
1670                         protected override void OnSizeChanged (EventArgs e)
1671                         {
1672                                 if (Controls.Count == 1) {
1673                                         Control control = Controls [0];
1674                                         
1675                                         if (control.Location.X != 1 || control.Location.Y != 1)
1676                                                 control.Location = new Point (1, 1);
1677                                         
1678                                         control.Width = ClientRectangle.Width - 2;
1679                                         control.Height = ClientRectangle.Height - 2;
1680                                 }
1681                                 base.OnSizeChanged (e);
1682                         }
1683                 }
1684
1685                 private class PropertyToolBarSeparator : 
1686 #if NET_2_0
1687                 ToolStripSeparator
1688 #else
1689                 ToolBarButton
1690 #endif
1691                 {
1692                         public PropertyToolBarSeparator ()
1693                         {
1694 #if !NET_2_0
1695                                 this.Style = ToolBarButtonStyle.Separator;
1696 #endif
1697                         }
1698                 }
1699
1700                 private class PropertyToolBarButton :
1701 #if NET_2_0
1702                 ToolStripButton
1703 #else
1704                 ToolBarButton
1705 #endif
1706                 {
1707                         private PropertyTab property_tab;
1708
1709                         public PropertyToolBarButton ()
1710                         {
1711                         }
1712
1713                         public PropertyToolBarButton (PropertyTab propertyTab)
1714                         {
1715                                 if (propertyTab == null)
1716                                         throw new ArgumentNullException ("propertyTab");
1717                                 property_tab = propertyTab;
1718                         }
1719
1720                         public PropertyTab PropertyTab {
1721                                 get { return property_tab; }
1722                         }
1723
1724 #if NET_2_0
1725                         public bool Pushed {
1726                                 get { return base.Checked; }
1727                                 set { base.Checked = value; }
1728                         }
1729                         
1730                         public ToolBarButtonStyle Style {
1731                                 get { return ToolBarButtonStyle.PushButton; }
1732                                 set { }
1733                         }
1734 #endif
1735                 }
1736                 
1737                 // needed! this little helper makes it possible to draw a different toolbar border
1738                 // and toolbar backcolor in ThemeWin32Classic
1739                 internal class PropertyToolBar : 
1740 #if NET_2_0
1741                 ToolStrip
1742 #else
1743                 ToolBar 
1744 #endif
1745                 {
1746                 
1747 #if NET_2_0
1748                         ToolBarAppearance appearance;
1749 #endif
1750                         public PropertyToolBar ()
1751                         {
1752                                 SetStyle (ControlStyles.ResizeRedraw, true);
1753 #if NET_2_0
1754                                 GripStyle = ToolStripGripStyle.Hidden;
1755                                 appearance = ToolBarAppearance.Normal;
1756 #endif
1757                         }
1758
1759 #if !NET_2_0
1760                         public IList Items {
1761                                 get { return base.Buttons; }
1762                         }
1763 #endif
1764
1765 #if NET_2_0
1766                         public bool ShowToolTips {
1767                                 get { return base.ShowItemToolTips; }
1768                                 set { base.ShowItemToolTips = value; }
1769                         }
1770                         
1771                         public ToolBarAppearance Appearance {
1772                                 get { return appearance; }
1773                                 set { 
1774                                         if (value == Appearance)
1775                                                 return;
1776                                                 
1777                                         switch (value) {
1778                                         case ToolBarAppearance.Flat:
1779                                                 Renderer = new ToolStripSystemRenderer ();
1780                                                 appearance = ToolBarAppearance.Flat;
1781                                                 break;
1782                                         case ToolBarAppearance.Normal:
1783                                                 ProfessionalColorTable table = new ProfessionalColorTable ();
1784                                                 table.UseSystemColors = true;
1785                                                 Renderer = new ToolStripProfessionalRenderer (table);
1786                                                 appearance = ToolBarAppearance.Normal;
1787                                                 break;
1788                                         }
1789                                 }
1790                         }
1791 #endif
1792                 }
1793
1794
1795                 [MonoInternalNote ("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")]
1796                 private class SelectedObjectConverter : TypeConverter
1797                 {
1798                 }
1799 #endregion
1800         }
1801 }