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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004-2008 Novell, Inc.
23 // Jonathan Chambers (jonathan.chambers@ansys.com)
24 // Ivan N. Zlatev (contact@i-nz.net)
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;
41 namespace System.Windows.Forms
43 [Designer("System.Windows.Forms.Design.PropertyGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
44 [ClassInterface (ClassInterfaceType.AutoDispatch)]
46 public class PropertyGrid : System.Windows.Forms.ContainerControl, ComponentModel.Com2Interop.IComPropertyBrowser
48 #region Private Members
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;
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;
79 private PropertyToolBar toolbar;
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;
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
96 public PropertyGrid ()
98 selected_objects = new object[0];
99 property_tabs = new PropertyTabCollection(this);
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);
108 splitter = new Splitter();
109 splitter.Dock = DockStyle.Bottom;
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;
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;
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;
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);
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;
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");
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;
159 toolbar.Appearance = ToolBarAppearance.Flat;
160 toolbar.AutoSize = false;
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;
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);
177 categorized_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
178 categorized_toolbarbutton.ToolTipText = Locale.GetText ("Categorized");
180 alphabetic_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
181 alphabetic_toolbarbutton.ToolTipText = Locale.GetText ("Alphabetic");
183 propertypages_toolbarbutton.Enabled = false;
184 propertypages_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton;
185 propertypages_toolbarbutton.ToolTipText = "Property Pages";
187 properties_tab = CreatePropertyTab (this.DefaultTabType);
188 selected_tab = properties_tab;
189 RefreshToolbar (property_tabs);
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;
200 BorderHelperControl helper = new BorderHelperControl ();
201 helper.Dock = DockStyle.Fill;
202 helper.Controls.Add (property_grid_view);
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);
211 #endregion // Constructors
213 #region Public Instance Properties
215 [BrowsableAttribute(false)]
216 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
217 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
218 public AttributeCollection BrowsableAttributes {
220 if (browsable_attributes == null) {
221 browsable_attributes = new AttributeCollection (new Attribute[] {
222 BrowsableAttribute.Yes });
224 return browsable_attributes;
227 if (browsable_attributes == value)
230 if (browsable_attributes == null || browsable_attributes.Count == 0)
231 browsable_attributes = null;
233 browsable_attributes = value;
238 [EditorBrowsable(EditorBrowsableState.Never)]
239 public override bool AutoScroll {
241 return base.AutoScroll;
244 base.AutoScroll = value;
248 public override Color BackColor {
250 return base.BackColor;
254 base.BackColor = value;
255 toolbar.BackColor = value;
261 [EditorBrowsable(EditorBrowsableState.Never)]
262 public override Image BackgroundImage {
264 return base.BackgroundImage;
267 base.BackgroundImage = value;
271 [EditorBrowsable(EditorBrowsableState.Never)]
273 public override ImageLayout BackgroundImageLayout {
274 get { return base.BackgroundImageLayout; }
275 set { base.BackgroundImageLayout = value; }
278 [BrowsableAttribute(false)]
279 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
280 public virtual bool CanShowCommands {
282 return can_show_commands;
286 [DefaultValue(typeof(Color), "ControlText")]
287 public Color CategoryForeColor {
289 return category_fore_color;
292 if (category_fore_color != value) {
293 category_fore_color = value;
299 public Color CommandsBackColor {
301 return commands_back_color;
305 if (commands_back_color == value) {
308 commands_back_color = value;
312 public Color CommandsForeColor {
314 return commands_fore_color;
318 if (commands_fore_color == value) {
321 commands_fore_color = value;
325 public Color CommandsActiveLinkColor {
327 return commands_active_link_color;
330 commands_active_link_color = value;
334 public Color CommandsDisabledLinkColor {
336 return commands_disabled_link_color;
339 commands_disabled_link_color = value;
343 public Color CommandsLinkColor {
345 return commands_link_color;
348 commands_link_color = value;
352 [BrowsableAttribute (false)]
353 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
354 [MonoTODO ("Commands are not implemented yet.")]
355 public virtual bool CommandsVisible {
357 return commands_visible;
361 [DefaultValue (true)]
362 public virtual bool CommandsVisibleIfAvailable {
364 return commands_visible_if_available;
368 if (commands_visible_if_available == value) {
371 commands_visible_if_available = value;
375 [BrowsableAttribute(false)]
376 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
377 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
378 public Point ContextMenuDefaultLocation {
380 return context_menu_default_location;
385 [EditorBrowsable(EditorBrowsableState.Never)]
386 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
387 public new Control.ControlCollection Controls {
389 return base.Controls;
394 [EditorBrowsable(EditorBrowsableState.Never)]
395 public override Color ForeColor {
397 return base.ForeColor;
400 base.ForeColor = value;
404 [DefaultValue ("Color [Control]")]
405 public Color HelpBackColor {
407 return help_panel.BackColor;
410 help_panel.BackColor = value;
414 [DefaultValue ("Color [ControlText]")]
415 public Color HelpForeColor {
417 return help_panel.ForeColor;
421 help_panel.ForeColor = value;
427 public virtual bool HelpVisible {
429 return help_panel.Visible;
433 splitter.Visible = value;
434 help_panel.Visible = value;
438 [DefaultValue (false)]
439 public bool LargeButtons {
441 return large_buttons;
445 if (large_buttons == value) {
449 large_buttons = value;
453 [DefaultValue ("Color [InactiveBorder]")]
454 public Color LineColor {
460 if (line_color == value) {
468 [EditorBrowsable(EditorBrowsableState.Never)]
470 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
471 public new Padding Padding {
472 get { return base.Padding; }
473 set { base.Padding = value; }
476 [DefaultValue(PropertySort.CategorizedAlphabetical)]
477 public PropertySort PropertySort {
479 return property_sort;
483 if (!Enum.IsDefined (typeof (PropertySort), value))
484 throw new InvalidEnumArgumentException ("value", (int) value, typeof (PropertySort));
485 if (property_sort == value)
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;
495 UpdateSortLayout (root_grid_item);
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);
502 SelectItemCore (null, selected_grid_item);
504 property_grid_view.UpdateView ();
506 EventHandler eh = (EventHandler)(Events [PropertySortChangedEvent]);
508 eh (this, EventArgs.Empty);
510 UpdatePropertySortButtonsState ();
514 [BrowsableAttribute(false)]
515 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
516 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
517 public PropertyTabCollection PropertyTabs {
518 get { return property_tabs; }
521 [BrowsableAttribute(false)]
522 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
523 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
524 public GridItem SelectedGridItem {
525 get { return selected_grid_item; }
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));
537 internal GridItem RootGridItem {
538 get { return root_grid_item; }
541 private void UpdateHelp (GridItem item)
544 help_title_label.Text = string.Empty;
545 help_description_label.Text = string.Empty;
547 help_title_label.Text = item.Label;
548 if (item.PropertyDescriptor != null)
549 this.help_description_label.Text = item.PropertyDescriptor.Description;
553 private void SelectItemCore (GridEntry oldItem, GridEntry item)
556 selected_grid_item = item;
557 property_grid_view.SelectItem (oldItem, item);
560 internal void OnPropertyValueChangedInternal (GridItem item, object property_value)
562 property_grid_view.UpdateView ();
563 OnPropertyValueChanged (new PropertyValueChangedEventArgs (item, property_value));
566 internal void OnExpandItem (GridEntry item)
568 property_grid_view.ExpandItem (item);
571 internal void OnCollapseItem (GridEntry item)
573 property_grid_view.CollapseItem (item);
576 internal DialogResult ShowError (string text)
578 return this.ShowError (text, MessageBoxButtons.OK);
581 internal DialogResult ShowError (string text, MessageBoxButtons buttons)
584 throw new ArgumentNullException ("text");
585 return MessageBox.Show (this, text, "Properties Window", buttons, MessageBoxIcon.Exclamation);
589 [TypeConverter("System.Windows.Forms.PropertyGrid+SelectedObjectConverter, " + Consts.AssemblySystem_Windows_Forms)]
590 public object SelectedObject {
592 if (selected_objects.Length > 0)
593 return selected_objects[0];
598 if (selected_objects != null && selected_objects.Length == 1 && selected_objects[0] == value)
601 SelectedObjects = new object[0];
603 SelectedObjects = new object[] {value};
608 [BrowsableAttribute(false)]
609 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
610 public object[] SelectedObjects {
612 return selected_objects;
616 root_grid_item = null;
617 SelectItemCore (null, null); // unselect current item in the view
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));
623 selected_objects = value;
625 selected_objects = new object [0];
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);
638 [BrowsableAttribute(false)]
639 [EditorBrowsable(EditorBrowsableState.Advanced)]
640 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
641 public PropertyTab SelectedTab {
642 get { return selected_tab; }
645 public override ISite Site {
646 get { return base.Site; }
647 set { base.Site = value; }
651 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
652 public override string Text {
653 get { return base.Text; }
654 set { base.Text = value; }
658 public virtual bool ToolbarVisible {
659 get { return toolbar.Visible; }
661 if (toolbar.Visible == value) {
665 toolbar.Visible = value;
669 protected ToolStripRenderer ToolStripRenderer {
671 if (toolbar != null) {
672 return toolbar.Renderer;
677 if (toolbar != null) {
678 toolbar.Renderer = value;
683 [DefaultValue ("Color [Window]")]
684 public Color ViewBackColor {
685 get { return property_grid_view.BackColor; }
687 if (property_grid_view.BackColor == value) {
691 property_grid_view.BackColor = value;
695 [DefaultValue ("Color [WindowText]")]
696 public Color ViewForeColor {
697 get { return property_grid_view.ForeColor; }
699 if (property_grid_view.ForeColor == value) {
703 property_grid_view.ForeColor = value;
707 [DefaultValue (false)]
708 public bool UseCompatibleTextRendering {
709 get { return use_compatible_text_rendering; }
711 if (use_compatible_text_rendering != value) {
712 use_compatible_text_rendering = value;
714 Parent.PerformLayout (this, "UseCompatibleTextRendering");
720 #endregion // Public Instance Properties
722 #region Protected Instance Properties
724 protected override Size DefaultSize {
725 get { return base.DefaultSize; }
730 [EditorBrowsable(EditorBrowsableState.Advanced)]
731 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
732 protected virtual Type DefaultTabType {
733 get { return typeof(PropertiesTab); }
736 protected bool DrawFlatToolbar {
737 get { return (toolbar.Appearance == ToolBarAppearance.Flat); }
740 toolbar.Appearance = ToolBarAppearance.Flat;
742 toolbar.Appearance = ToolBarAppearance.Normal;
746 protected internal override bool ShowFocusCues {
747 get { return base.ShowFocusCues; }
750 #endregion // Protected Instance Properties
752 #region Public Instance Methods
754 protected override void Dispose(bool disposing) {
755 base.Dispose(disposing);
758 public void CollapseAllGridItems ()
760 GridEntry category = FindCategoryItem (selected_grid_item);
761 if (category != null)
762 SelectedGridItem = category;
763 CollapseItemRecursive (root_grid_item);
764 property_grid_view.UpdateView ();
767 private void CollapseItemRecursive (GridItem item)
772 foreach (GridItem child in item.GridItems) {
773 CollapseItemRecursive (child);
774 if (child.Expandable)
775 child.Expanded = false;
779 private GridEntry FindCategoryItem (GridEntry entry)
781 if (entry == null || (property_sort != PropertySort.Categorized &&
782 property_sort != PropertySort.CategorizedAlphabetical))
785 if (entry.GridItemType == GridItemType.Category)
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;
797 return (GridEntry) category;
800 public void ExpandAllGridItems ()
802 ExpandItemRecursive (root_grid_item);
803 property_grid_view.UpdateView ();
806 private void ExpandItemRecursive (GridItem item)
811 foreach (GridItem child in item.GridItems) {
812 ExpandItemRecursive (child);
813 if (child.Expandable)
814 child.Expanded = true;
818 public override void Refresh ()
821 // force a full reload here
822 SelectedObjects = SelectedObjects;
825 private void toolbar_Clicked (PropertyToolBarButton button)
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;
840 SelectPropertyTab (button.PropertyTab);
844 private void toolbarbutton_clicked (object o, EventArgs args)
846 toolbar_Clicked (o as PropertyToolBarButton);
849 private void SelectPropertyTab (PropertyTab propertyTab)
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;
861 selected_tab = propertyTab;
862 PopulateGrid (selected_objects);
863 SelectItemCore (null, GetDefaultPropertyItem (root_grid_item, selected_tab));
864 property_grid_view.UpdateView ();
868 private void UpdatePropertySortButtonsState ()
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;
883 protected void ShowEventsButton (bool value)
885 if (value && property_tabs.Contains (typeof (EventsTab)))
886 events_tab_visible = true;
888 events_tab_visible = false;
889 RefreshTabs (PropertyTabScope.Component);
892 public void RefreshTabs (PropertyTabScope tabScope)
894 property_tabs.Clear (tabScope);
895 if (selected_objects != null) {
896 Type[] tabTypes = null;
897 PropertyTabScope[] tabScopes = null;
899 if (events_tab_visible && property_tabs.Contains (typeof (EventsTab)))
900 property_tabs.InsertTab (0, properties_tab, PropertyTabScope.Component);
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;
910 if (!selectedTabPreserved)
911 SelectPropertyTab (properties_tab);
914 SelectPropertyTab (properties_tab);
916 RefreshToolbar (property_tabs);
919 private void RefreshToolbar (PropertyTabCollection tabs)
921 EnsurePropertiesTab ();
923 toolbar.SuspendLayout ();
924 toolbar.Items.Clear ();
925 toolbar_imagelist.Images.Clear ();
928 toolbar.Items.Add (categorized_toolbarbutton);
929 toolbar_imagelist.Images.Add (categorized_image);
930 categorized_toolbarbutton.ImageIndex = imageIndex;
932 toolbar.Items.Add (alphabetic_toolbarbutton);
933 toolbar_imagelist.Images.Add (alphabetical_image);
934 alphabetic_toolbarbutton.ImageIndex = 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;
947 if (tab == selected_tab)
948 button.Pushed = true;
950 toolbar.Items.Add (new PropertyToolBarSeparator ());
953 toolbar.Items.Add (propertypages_toolbarbutton);
954 toolbar_imagelist.Images.Add (propertypages_image);
955 propertypages_toolbarbutton.ImageIndex = imageIndex;
957 toolbar.ResumeLayout ();
960 private void EnsurePropertiesTab ()
962 if (property_tabs == null)
965 if (property_tabs.Count > 0 && !property_tabs.Contains (this.DefaultTabType))
966 property_tabs.InsertTab (0, properties_tab, PropertyTabScope.Component);
969 private void GetMergedPropertyTabs (object[] objects, out Type[] tabTypes, out PropertyTabScope[] tabScopes)
973 if (objects == null || objects.Length == 0)
976 ArrayList intersection = null;
977 ArrayList scopes = new ArrayList ();
978 for (int i=0; i < objects.Length; i++) {
979 if (objects[i] == null)
981 PropertyTabAttribute tabAttribute = (PropertyTabAttribute)TypeDescriptor.GetAttributes (objects[i])[typeof (PropertyTabAttribute)];
982 if (tabAttribute == null || tabAttribute.TabClasses == null || tabAttribute.TabClasses.Length == 0)
985 ArrayList new_intersection = new ArrayList ();
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]);
994 intersection = new_intersection;
997 tabTypes = new Type[intersection.Count];
998 intersection.CopyTo (tabTypes);
999 tabScopes = new PropertyTabScope[tabTypes.Length];
1000 scopes.CopyTo (tabScopes);
1003 public void ResetSelectedProperty()
1005 if (selected_grid_item == null)
1007 selected_grid_item.ResetValue ();
1009 #endregion // Public Instance Methods
1011 #region Protected Instance Methods
1013 protected virtual PropertyTab CreatePropertyTab (Type tabType)
1015 if (!typeof(PropertyTab).IsAssignableFrom (tabType))
1018 PropertyTab tab = null;
1020 ConstructorInfo ctor = tabType.GetConstructor (new Type[] { typeof (IServiceProvider) });
1022 tab = (PropertyTab)ctor.Invoke (new object[] { this.Site });
1024 tab = (PropertyTab)Activator.CreateInstance (tabType);
1028 [MonoTODO ("Never called")]
1029 protected void OnComComponentNameChanged(ComponentRenameEventArgs e)
1031 ComponentRenameEventHandler eh = (ComponentRenameEventHandler)(Events [ComComponentNameChangedEvent]);
1036 protected override void OnEnabledChanged (EventArgs e) {
1037 base.OnEnabledChanged (e);
1040 protected override void OnFontChanged(EventArgs e) {
1041 base.OnFontChanged (e);
1044 protected override void OnGotFocus(EventArgs e) {
1048 protected override void OnHandleCreated (EventArgs e) {
1049 base.OnHandleCreated (e);
1052 protected override void OnHandleDestroyed (EventArgs e) {
1053 base.OnHandleDestroyed (e);
1056 protected override void OnMouseDown (MouseEventArgs me) {
1057 base.OnMouseDown (me);
1060 protected override void OnMouseMove (MouseEventArgs me) {
1061 base.OnMouseMove (me);
1064 protected override void OnMouseUp (MouseEventArgs me) {
1065 base.OnMouseUp (me);
1068 protected void OnNotifyPropertyValueUIItemsChanged(object sender, EventArgs e)
1070 property_grid_view.UpdateView ();
1073 protected override void OnPaint (PaintEventArgs pevent) {
1074 pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
1075 base.OnPaint (pevent);
1078 protected virtual void OnPropertySortChanged(EventArgs e) {
1079 EventHandler eh = (EventHandler) Events [PropertySortChangedEvent];
1084 protected virtual void OnPropertyTabChanged (PropertyTabChangedEventArgs e)
1086 PropertyTabChangedEventHandler eh = (PropertyTabChangedEventHandler)(Events [PropertyTabChangedEvent]);
1091 protected virtual void OnPropertyValueChanged (PropertyValueChangedEventArgs e) {
1092 PropertyValueChangedEventHandler eh = (PropertyValueChangedEventHandler)(Events [PropertyValueChangedEvent]);
1097 protected override void OnResize (EventArgs e) {
1101 protected virtual void OnSelectedGridItemChanged (SelectedGridItemChangedEventArgs e) {
1102 SelectedGridItemChangedEventHandler eh = (SelectedGridItemChangedEventHandler)(Events [SelectedGridItemChangedEvent]);
1107 protected virtual void OnSelectedObjectsChanged (EventArgs e) {
1108 EventHandler eh = (EventHandler)(Events [SelectedObjectsChangedEvent]);
1113 protected override void OnSystemColorsChanged (EventArgs e) {
1114 base.OnSystemColorsChanged (e);
1117 protected override void OnVisibleChanged (EventArgs e) {
1118 base.OnVisibleChanged (e);
1121 protected override bool ProcessDialogKey (Keys keyData) {
1122 return base.ProcessDialogKey (keyData);
1125 [EditorBrowsable (EditorBrowsableState.Never)]
1126 protected override void ScaleCore (float dx, float dy) {
1127 base.ScaleCore (dx, dy);
1130 protected override void WndProc (ref Message m)
1132 base.WndProc (ref m);
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 ();
1143 public event EventHandler PropertySortChanged {
1144 add { Events.AddHandler (PropertySortChangedEvent, value); }
1145 remove { Events.RemoveHandler (PropertySortChangedEvent, value); }
1148 public event PropertyTabChangedEventHandler PropertyTabChanged {
1149 add { Events.AddHandler (PropertyTabChangedEvent, value); }
1150 remove { Events.RemoveHandler (PropertyTabChangedEvent, value); }
1153 public event PropertyValueChangedEventHandler PropertyValueChanged {
1154 add { Events.AddHandler (PropertyValueChangedEvent, value); }
1155 remove { Events.RemoveHandler (PropertyValueChangedEvent, value); }
1158 public event SelectedGridItemChangedEventHandler SelectedGridItemChanged {
1159 add { Events.AddHandler (SelectedGridItemChangedEvent, value); }
1160 remove { Events.RemoveHandler (SelectedGridItemChangedEvent, value); }
1163 public event EventHandler SelectedObjectsChanged {
1164 add { Events.AddHandler (SelectedObjectsChangedEvent, value); }
1165 remove { Events.RemoveHandler (SelectedObjectsChangedEvent, value); }
1169 [EditorBrowsable(EditorBrowsableState.Never)]
1170 public new event EventHandler BackgroundImageChanged {
1171 add { base.BackgroundImageChanged += value; }
1172 remove { base.BackgroundImageChanged -= value; }
1176 [EditorBrowsable(EditorBrowsableState.Never)]
1177 public new event EventHandler BackgroundImageLayoutChanged {
1178 add { base.BackgroundImageLayoutChanged += value; }
1179 remove { base.BackgroundImageLayoutChanged -= value; }
1183 [EditorBrowsable(EditorBrowsableState.Never)]
1184 public new event EventHandler ForeColorChanged {
1185 add { base.ForeColorChanged += value; }
1186 remove { base.ForeColorChanged -= value; }
1189 [EditorBrowsable(EditorBrowsableState.Advanced)]
1191 public new event KeyEventHandler KeyDown {
1192 add { base.KeyDown += value; }
1193 remove { base.KeyDown -= value; }
1197 [EditorBrowsable(EditorBrowsableState.Advanced)]
1198 public new event KeyPressEventHandler KeyPress {
1199 add { base.KeyPress += value; }
1200 remove { base.KeyPress -= value; }
1203 [EditorBrowsable(EditorBrowsableState.Advanced)]
1205 public new event KeyEventHandler KeyUp {
1206 add { base.KeyUp += value; }
1207 remove { base.KeyUp -= value; }
1211 [EditorBrowsable(EditorBrowsableState.Advanced)]
1212 public new event MouseEventHandler MouseDown {
1213 add { base.MouseDown += value; }
1214 remove { base.MouseDown -= value; }
1217 [EditorBrowsable(EditorBrowsableState.Advanced)]
1219 public new event EventHandler MouseEnter {
1220 add { base.MouseEnter += value; }
1221 remove { base.MouseEnter -= value; }
1224 [EditorBrowsable(EditorBrowsableState.Advanced)]
1226 public new event EventHandler MouseLeave {
1227 add { base.MouseLeave += value; }
1228 remove { base.MouseLeave -= value; }
1231 [EditorBrowsable(EditorBrowsableState.Advanced)]
1233 public new event MouseEventHandler MouseMove {
1234 add { base.MouseMove += value; }
1235 remove { base.MouseMove -= value; }
1238 [EditorBrowsable(EditorBrowsableState.Advanced)]
1240 public new event MouseEventHandler MouseUp {
1241 add { base.MouseUp += value; }
1242 remove { base.MouseUp -= value; }
1246 [EditorBrowsable(EditorBrowsableState.Never)]
1247 public new event EventHandler PaddingChanged {
1248 add { base.PaddingChanged += value; }
1249 remove { base.PaddingChanged -= value; }
1253 public new event EventHandler TextChanged {
1254 add { base.TextChanged += value; }
1255 remove { base.TextChanged -= value; }
1259 #region Com2Interop.IComPropertyBrowser Interface
1260 [MonoTODO ("Not implemented, will throw NotImplementedException")]
1261 bool ComponentModel.Com2Interop.IComPropertyBrowser.InPropertySet {
1263 throw new NotImplementedException();
1267 [MonoTODO ("Stub, does nothing")]
1268 void ComponentModel.Com2Interop.IComPropertyBrowser.DropDownDone ()
1272 [MonoTODO ("Not implemented, will throw NotImplementedException")]
1273 bool ComponentModel.Com2Interop.IComPropertyBrowser.EnsurePendingChangesCommitted ()
1275 throw new NotImplementedException ();
1278 [MonoTODO ("Stub, does nothing")]
1279 void ComponentModel.Com2Interop.IComPropertyBrowser.HandleF4 ()
1283 [MonoTODO ("Stub, does nothing")]
1284 void ComponentModel.Com2Interop.IComPropertyBrowser.LoadState (Microsoft.Win32.RegistryKey optRoot)
1288 [MonoTODO ("Stub, does nothing")]
1289 void ComponentModel.Com2Interop.IComPropertyBrowser.SaveState (Microsoft.Win32.RegistryKey optRoot)
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); }
1298 #endregion // Com2Interop.IComPropertyBrowser Interface
1300 #region PropertyTabCollection Class
1301 public class PropertyTabCollection : ICollection, IEnumerable
1303 ArrayList property_tabs;
1304 ArrayList property_tabs_scopes;
1305 PropertyGrid property_grid;
1307 internal PropertyTabCollection (PropertyGrid propertyGrid)
1309 property_grid = propertyGrid;
1310 property_tabs = new ArrayList ();
1311 property_tabs_scopes = new ArrayList ();
1314 public PropertyTab this[int index] {
1315 get { return (PropertyTab)property_tabs[index]; }
1318 bool ICollection.IsSynchronized {
1319 get { return property_tabs.IsSynchronized; }
1322 void ICollection.CopyTo (Array dest, int index)
1324 property_tabs.CopyTo (dest, index);
1327 object ICollection.SyncRoot {
1328 get { return property_tabs.SyncRoot; }
1331 public IEnumerator GetEnumerator ()
1333 return property_tabs.GetEnumerator ();
1337 get { return property_tabs.Count; }
1340 public void AddTabType (Type propertyTabType)
1342 AddTabType (propertyTabType, PropertyTabScope.Global);
1345 public void AddTabType (Type propertyTabType, PropertyTabScope tabScope)
1347 if (propertyTabType == null)
1348 throw new ArgumentNullException ("propertyTabType");
1351 if (this.Contains (propertyTabType))
1353 PropertyTab tab = property_grid.CreatePropertyTab (propertyTabType);
1355 property_tabs.Add (tab);
1356 property_tabs_scopes.Add (tabScope);
1358 property_grid.RefreshToolbar (this);
1361 internal PropertyTabScope GetTabScope (PropertyTab tab)
1364 throw new ArgumentNullException ("tab");
1366 int index = property_tabs.IndexOf (tab);
1368 return (PropertyTabScope)property_tabs_scopes[index];
1369 return PropertyTabScope.Global;
1372 internal void InsertTab (int index, PropertyTab propertyTab, PropertyTabScope tabScope)
1374 if (propertyTab == null)
1375 throw new ArgumentNullException ("propertyTab");
1377 if (!this.Contains (propertyTab.GetType ())) {
1378 property_tabs.Insert (index, propertyTab);
1379 property_tabs_scopes.Insert (index, tabScope);
1383 internal bool Contains (Type propertyType)
1385 if (propertyType == null)
1386 throw new ArgumentNullException ("propertyType");
1388 foreach (PropertyTab t in property_tabs) {
1389 if (t.GetType () == propertyType)
1395 internal PropertyTab this[Type tabType] {
1397 foreach (PropertyTab tab in property_tabs) {
1398 if (tabType == tab.GetType ())
1405 public void Clear (PropertyTabScope tabScope)
1407 ArrayList toRemove = new ArrayList ();
1408 for (int i=0; i < property_tabs_scopes.Count; i++) {
1409 if ((PropertyTabScope)property_tabs_scopes[i] == tabScope)
1412 foreach (int indexToRemove in toRemove) {
1413 property_tabs.RemoveAt (indexToRemove);
1414 property_tabs_scopes.RemoveAt (indexToRemove);
1416 property_grid.RefreshToolbar (this);
1419 public void RemoveTabType (Type propertyTabType)
1421 if (propertyTabType == null)
1422 throw new ArgumentNullException ("propertyTabType");
1424 ArrayList toRemove = new ArrayList ();
1425 for (int i=0; i < property_tabs.Count; i++) {
1426 if (property_tabs[i].GetType () == propertyTabType)
1429 foreach (int indexToRemove in toRemove) {
1430 property_tabs.RemoveAt (indexToRemove);
1431 property_tabs_scopes.RemoveAt (indexToRemove);
1433 property_grid.RefreshToolbar (this);
1436 #endregion // PropertyTabCollection Class
1438 #region Private Helper Methods
1440 private GridItem FindFirstPropertyItem (GridItem root)
1442 if (root.GridItemType == GridItemType.Property)
1445 foreach (GridItem item in root.GridItems) {
1446 GridItem subitem = FindFirstPropertyItem (item);
1447 if (subitem != null)
1454 private GridEntry GetDefaultPropertyItem (GridEntry rootItem, PropertyTab propertyTab)
1456 if (rootItem == null || rootItem.GridItems.Count == 0 || propertyTab == null)
1458 object[] propertyOwners = rootItem.Values;
1459 if (propertyOwners == null || propertyOwners.Length == 0 || propertyOwners[0] == null)
1462 GridItem defaultSelected = null;
1463 if (propertyOwners.Length > 1)
1464 defaultSelected = rootItem.GridItems[0];
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);
1473 return defaultSelected as GridEntry;
1476 private GridEntry FindItem (string name, GridEntry rootItem)
1478 if (rootItem == null || name == null)
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;
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;
1501 private void OnResetPropertyClick (object sender, EventArgs e)
1503 ResetSelectedProperty();
1506 private void OnDescriptionClick (object sender, EventArgs e)
1508 this.HelpVisible = !this.HelpVisible;
1509 description_menuitem.Checked = this.HelpVisible;
1512 private void PopulateGrid (object[] objects)
1514 if (objects.Length > 0) {
1515 root_grid_item = new RootGridEntry (this, objects);
1516 root_grid_item.Expanded = true;
1517 UpdateSortLayout (root_grid_item);
1519 root_grid_item = null;
1523 private void UpdateSortLayout (GridEntry rootItem)
1525 if (rootItem == null)
1528 GridItemCollection reordered = new GridItemCollection ();
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);
1540 reordered.Add (item);
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 ();
1549 foreach (GridItem item in rootItem.GridItems) {
1550 if (item.GridItemType == GridItemType.Category) {
1551 categories.Add (item);
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];
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);
1569 category_item.GridItems.Add (item);
1570 ((GridEntry)item).SetParent (category_item);
1573 reordered.AddRange (categories);
1576 rootItem.GridItems.Clear ();
1577 rootItem.GridItems.AddRange (reordered);
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 );
1585 #endregion // Private Helper Methods
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 {
1592 public BorderHelperControl ()
1594 BackColor = ThemeEngine.Current.ColorWindow;
1597 protected override void OnPaint (PaintEventArgs e)
1599 e.Graphics.DrawRectangle (SystemPens.ControlDark, 0 , 0 , Width - 1, Height - 1);
1603 protected override void OnSizeChanged (EventArgs e)
1605 if (Controls.Count == 1) {
1606 Control control = Controls [0];
1608 if (control.Location.X != 1 || control.Location.Y != 1)
1609 control.Location = new Point (1, 1);
1611 control.Width = ClientRectangle.Width - 2;
1612 control.Height = ClientRectangle.Height - 2;
1614 base.OnSizeChanged (e);
1618 private class PropertyToolBarSeparator : ToolStripSeparator
1620 public PropertyToolBarSeparator ()
1625 private class PropertyToolBarButton : ToolStripButton
1627 private PropertyTab property_tab;
1629 public PropertyToolBarButton ()
1633 public PropertyToolBarButton (PropertyTab propertyTab)
1635 if (propertyTab == null)
1636 throw new ArgumentNullException ("propertyTab");
1637 property_tab = propertyTab;
1640 public PropertyTab PropertyTab {
1641 get { return property_tab; }
1644 public bool Pushed {
1645 get { return base.Checked; }
1646 set { base.Checked = value; }
1649 public ToolBarButtonStyle Style {
1650 get { return ToolBarButtonStyle.PushButton; }
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
1659 ToolBarAppearance appearance;
1661 public PropertyToolBar ()
1663 SetStyle (ControlStyles.ResizeRedraw, true);
1664 GripStyle = ToolStripGripStyle.Hidden;
1665 appearance = ToolBarAppearance.Normal;
1668 public bool ShowToolTips {
1669 get { return base.ShowItemToolTips; }
1670 set { base.ShowItemToolTips = value; }
1673 public ToolBarAppearance Appearance {
1674 get { return appearance; }
1676 if (value == Appearance)
1680 case ToolBarAppearance.Flat:
1681 Renderer = new ToolStripSystemRenderer ();
1682 appearance = ToolBarAppearance.Flat;
1684 case ToolBarAppearance.Normal:
1685 ProfessionalColorTable table = new ProfessionalColorTable ();
1686 table.UseSystemColors = true;
1687 Renderer = new ToolStripProfessionalRenderer (table);
1688 appearance = ToolBarAppearance.Normal;
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