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