// Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Copyright (c) 2004-2008 Novell, Inc. // // Authors: // Jonathan Chambers (jonathan.chambers@ansys.com) // Ivan N. Zlatev (contact@i-nz.net) // // NOT COMPLETE using System; using System.IO; using System.Drawing; using System.Drawing.Design; using System.ComponentModel; using System.Collections; using System.ComponentModel.Design; using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms.Design; using System.Windows.Forms.PropertyGridInternal; namespace System.Windows.Forms { [Designer("System.Windows.Forms.Design.PropertyGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] [ClassInterface (ClassInterfaceType.AutoDispatch)] [ComVisible (true)] public class PropertyGrid : System.Windows.Forms.ContainerControl, ComponentModel.Com2Interop.IComPropertyBrowser { #region Private Members private const string UNCATEGORIZED_CATEGORY_LABEL = "Misc"; private AttributeCollection browsable_attributes = null; private bool can_show_commands = false; private Color commands_back_color; private Color commands_fore_color; private bool commands_visible; private bool commands_visible_if_available; private Point context_menu_default_location; private bool large_buttons; private Color line_color; private PropertySort property_sort; private PropertyTabCollection property_tabs; private GridEntry selected_grid_item; private GridEntry root_grid_item; private object[] selected_objects; private PropertyTab properties_tab; private PropertyTab selected_tab; private ImageList toolbar_imagelist; private Image categorized_image; private Image alphabetical_image; private Image propertypages_image; private PropertyToolBarButton categorized_toolbarbutton; private PropertyToolBarButton alphabetic_toolbarbutton; private PropertyToolBarButton propertypages_toolbarbutton; private PropertyToolBarSeparator separator_toolbarbutton; private bool events_tab_visible; private PropertyToolBar toolbar; private PropertyGridView property_grid_view; private Splitter splitter; private Panel help_panel; private Label help_title_label; private Label help_description_label; private MenuItem reset_menuitem; private MenuItem description_menuitem; private Color category_fore_color; private Color commands_active_link_color; private Color commands_disabled_link_color; private Color commands_link_color; #endregion // Private Members #region Contructors public PropertyGrid () { selected_objects = new object[0]; property_tabs = new PropertyTabCollection(this); line_color = SystemColors.ScrollBar; category_fore_color = line_color; commands_visible = false; commands_visible_if_available = false; property_sort = PropertySort.CategorizedAlphabetical; property_grid_view = new PropertyGridView(this); splitter = new Splitter(); splitter.Dock = DockStyle.Bottom; help_panel = new Panel(); help_panel.Dock = DockStyle.Bottom; //help_panel.DockPadding.All = 3; help_panel.Height = 50; help_panel.BackColor = SystemColors.Control; help_title_label = new Label(); help_title_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; help_title_label.Name = "help_title_label"; help_title_label.Font = new Font(this.Font,FontStyle.Bold); help_title_label.Location = new Point(2,2); help_title_label.Height = 17; help_title_label.Width = help_panel.Width - 4; help_description_label = new Label(); help_description_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom; help_description_label.AutoEllipsis = true; help_description_label.AutoSize = false; help_description_label.Font = this.Font; help_description_label.Location = new Point(2,help_title_label.Top+help_title_label.Height); help_description_label.Width = help_panel.Width - 4; help_description_label.Height = help_panel.Height - help_description_label.Top - 2; help_panel.Controls.Add(help_description_label); help_panel.Controls.Add(help_title_label); help_panel.Paint+=new PaintEventHandler(help_panel_Paint); toolbar = new PropertyToolBar(); toolbar.Dock = DockStyle.Top; categorized_toolbarbutton = new PropertyToolBarButton (); categorized_toolbarbutton.Pushed = true; alphabetic_toolbarbutton = new PropertyToolBarButton (); propertypages_toolbarbutton = new PropertyToolBarButton (); separator_toolbarbutton = new PropertyToolBarSeparator (); ContextMenu context_menu = new ContextMenu(); context_menu_default_location = Point.Empty; categorized_image = new Bitmap (typeof (PropertyGrid), "propertygrid-categorized.png"); alphabetical_image = new Bitmap (typeof (PropertyGrid), "propertygrid-alphabetical.png"); propertypages_image = new Bitmap (typeof (PropertyGrid), "propertygrid-propertypages.png"); toolbar_imagelist = new ImageList(); toolbar_imagelist.ColorDepth = ColorDepth.Depth32Bit; toolbar_imagelist.ImageSize = new System.Drawing.Size(16, 16); toolbar_imagelist.TransparentColor = System.Drawing.Color.Transparent; toolbar.Appearance = ToolBarAppearance.Flat; toolbar.AutoSize = false; toolbar.ImageList = toolbar_imagelist; toolbar.Location = new System.Drawing.Point(0, 0); toolbar.ShowToolTips = true; toolbar.Size = new System.Drawing.Size(256, 27); toolbar.TabIndex = 0; toolbar.Items.AddRange (new ToolStripItem [] {categorized_toolbarbutton, alphabetic_toolbarbutton, new PropertyToolBarSeparator (), propertypages_toolbarbutton}); //toolbar.ButtonSize = new System.Drawing.Size (20, 20); categorized_toolbarbutton.Click += new EventHandler (toolbarbutton_clicked); alphabetic_toolbarbutton.Click += new EventHandler (toolbarbutton_clicked); propertypages_toolbarbutton.Click += new EventHandler (toolbarbutton_clicked); categorized_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton; categorized_toolbarbutton.ToolTipText = Locale.GetText ("Categorized"); alphabetic_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton; alphabetic_toolbarbutton.ToolTipText = Locale.GetText ("Alphabetic"); propertypages_toolbarbutton.Enabled = false; propertypages_toolbarbutton.Style = ToolBarButtonStyle.ToggleButton; propertypages_toolbarbutton.ToolTipText = "Property Pages"; properties_tab = CreatePropertyTab (this.DefaultTabType); selected_tab = properties_tab; RefreshToolbar (property_tabs); reset_menuitem = context_menu.MenuItems.Add("Reset"); reset_menuitem.Click +=new EventHandler(OnResetPropertyClick); context_menu.MenuItems.Add("-"); description_menuitem = context_menu.MenuItems.Add("Description"); description_menuitem.Click += new EventHandler(OnDescriptionClick); description_menuitem.Checked = this.HelpVisible; this.ContextMenu = context_menu; toolbar.ContextMenu = context_menu; BorderHelperControl helper = new BorderHelperControl (); helper.Dock = DockStyle.Fill; helper.Controls.Add (property_grid_view); this.Controls.Add(helper); this.Controls.Add(toolbar); this.Controls.Add(splitter); this.Controls.Add(help_panel); this.Name = "PropertyGrid"; this.Size = new System.Drawing.Size(256, 400); } #endregion // Constructors #region Public Instance Properties [BrowsableAttribute(false)] [EditorBrowsableAttribute(EditorBrowsableState.Advanced)] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] public AttributeCollection BrowsableAttributes { get { if (browsable_attributes == null) { browsable_attributes = new AttributeCollection (new Attribute[] { BrowsableAttribute.Yes }); } return browsable_attributes; } set { if (browsable_attributes == value) return; if (browsable_attributes == null || browsable_attributes.Count == 0) browsable_attributes = null; else browsable_attributes = value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public override bool AutoScroll { get { return base.AutoScroll; } set { base.AutoScroll = value; } } public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; toolbar.BackColor = value; Refresh (); } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public override Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = value; } } [EditorBrowsable(EditorBrowsableState.Never)] [Browsable(false)] public override ImageLayout BackgroundImageLayout { get { return base.BackgroundImageLayout; } set { base.BackgroundImageLayout = value; } } [BrowsableAttribute(false)] [EditorBrowsableAttribute(EditorBrowsableState.Advanced)] public virtual bool CanShowCommands { get { return can_show_commands; } } [DefaultValue(typeof(Color), "ControlText")] public Color CategoryForeColor { get { return category_fore_color; } set { if (category_fore_color != value) { category_fore_color = value; Invalidate (); } } } public Color CommandsBackColor { get { return commands_back_color; } set { if (commands_back_color == value) { return; } commands_back_color = value; } } public Color CommandsForeColor { get { return commands_fore_color; } set { if (commands_fore_color == value) { return; } commands_fore_color = value; } } public Color CommandsActiveLinkColor { get { return commands_active_link_color; } set { commands_active_link_color = value; } } public Color CommandsDisabledLinkColor { get { return commands_disabled_link_color; } set { commands_disabled_link_color = value; } } public Color CommandsLinkColor { get { return commands_link_color; } set { commands_link_color = value; } } [BrowsableAttribute (false)] [EditorBrowsableAttribute(EditorBrowsableState.Advanced)] [MonoTODO ("Commands are not implemented yet.")] public virtual bool CommandsVisible { get { return commands_visible; } } [DefaultValue (true)] public virtual bool CommandsVisibleIfAvailable { get { return commands_visible_if_available; } set { if (commands_visible_if_available == value) { return; } commands_visible_if_available = value; } } [BrowsableAttribute(false)] [EditorBrowsableAttribute(EditorBrowsableState.Advanced)] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] public Point ContextMenuDefaultLocation { get { return context_menu_default_location; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new Control.ControlCollection Controls { get { return base.Controls; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } [DefaultValue ("Color [Control]")] public Color HelpBackColor { get { return help_panel.BackColor; } set { help_panel.BackColor = value; } } [DefaultValue ("Color [ControlText]")] public Color HelpForeColor { get { return help_panel.ForeColor; } set { help_panel.ForeColor = value; } } [DefaultValue(true)] [Localizable(true)] public virtual bool HelpVisible { get { return help_panel.Visible; } set { splitter.Visible = value; help_panel.Visible = value; } } [DefaultValue (false)] public bool LargeButtons { get { return large_buttons; } set { if (large_buttons == value) { return; } large_buttons = value; } } [DefaultValue ("Color [InactiveBorder]")] public Color LineColor { get { return line_color; } set { if (line_color == value) { return; } line_color = value; } } [EditorBrowsable(EditorBrowsableState.Never)] [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new Padding Padding { get { return base.Padding; } set { base.Padding = value; } } [DefaultValue(PropertySort.CategorizedAlphabetical)] public PropertySort PropertySort { get { return property_sort; } set { if (!Enum.IsDefined (typeof (PropertySort), value)) throw new InvalidEnumArgumentException ("value", (int) value, typeof (PropertySort)); if (property_sort == value) return; // we do not need to update the the grid items and fire // a PropertySortChanged event when switching between // Categorized and CateogizedAlphabetical bool needUpdate = (property_sort & PropertySort.Categorized) == 0 || (value & PropertySort.Categorized) == 0; property_sort = value; if (needUpdate) { UpdateSortLayout (root_grid_item); // update selection if (selected_grid_item != null) { if (selected_grid_item.GridItemType == GridItemType.Category && (value == PropertySort.Alphabetical || value == PropertySort.NoSort)) SelectItemCore (null, null); else SelectItemCore (null, selected_grid_item); } property_grid_view.UpdateView (); EventHandler eh = (EventHandler)(Events [PropertySortChangedEvent]); if (eh != null) eh (this, EventArgs.Empty); } UpdatePropertySortButtonsState (); } } [BrowsableAttribute(false)] [EditorBrowsableAttribute(EditorBrowsableState.Advanced)] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] public PropertyTabCollection PropertyTabs { get { return property_tabs; } } [BrowsableAttribute(false)] [EditorBrowsableAttribute(EditorBrowsableState.Advanced)] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] public GridItem SelectedGridItem { get { return selected_grid_item; } set { if (value == null) throw new ArgumentException ("GridItem specified to PropertyGrid.SelectedGridItem must be a valid GridItem."); if (value != selected_grid_item) { GridEntry oldItem = selected_grid_item; SelectItemCore (oldItem, (GridEntry)value); OnSelectedGridItemChanged (new SelectedGridItemChangedEventArgs (oldItem, value)); } } } internal GridItem RootGridItem { get { return root_grid_item; } } private void UpdateHelp (GridItem item) { if (item == null) { help_title_label.Text = string.Empty; help_description_label.Text = string.Empty; } else { help_title_label.Text = item.Label; if (item.PropertyDescriptor != null) this.help_description_label.Text = item.PropertyDescriptor.Description; } } private void SelectItemCore (GridEntry oldItem, GridEntry item) { UpdateHelp (item); selected_grid_item = item; property_grid_view.SelectItem (oldItem, item); } internal void OnPropertyValueChangedInternal (GridItem item, object property_value) { property_grid_view.UpdateView (); OnPropertyValueChanged (new PropertyValueChangedEventArgs (item, property_value)); } internal void OnExpandItem (GridEntry item) { property_grid_view.ExpandItem (item); } internal void OnCollapseItem (GridEntry item) { property_grid_view.CollapseItem (item); } internal DialogResult ShowError (string text) { return this.ShowError (text, MessageBoxButtons.OK); } internal DialogResult ShowError (string text, MessageBoxButtons buttons) { if (text == null) throw new ArgumentNullException ("text"); return MessageBox.Show (this, text, "Properties Window", buttons, MessageBoxIcon.Exclamation); } [DefaultValue(null)] [TypeConverter("System.Windows.Forms.PropertyGrid+SelectedObjectConverter, " + Consts.AssemblySystem_Windows_Forms)] public object SelectedObject { get { if (selected_objects.Length > 0) return selected_objects[0]; return null; } set { if (selected_objects != null && selected_objects.Length == 1 && selected_objects[0] == value) return; if (value == null) SelectedObjects = new object[0]; else SelectedObjects = new object[] {value}; } } [BrowsableAttribute(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public object[] SelectedObjects { get { return selected_objects; } set { root_grid_item = null; SelectItemCore (null, null); // unselect current item in the view if (value != null) { for (int i = 0; i < value.Length; i++) { if (value [i] == null) throw new ArgumentException (String.Format ("Item {0} in the objs array is null.", i)); } selected_objects = value; } else { selected_objects = new object [0]; } ShowEventsButton (false); PopulateGrid (selected_objects); RefreshTabs(PropertyTabScope.Component); if (root_grid_item != null) SelectItemCore (null, GetDefaultPropertyItem (root_grid_item, selected_tab)); property_grid_view.UpdateView (); OnSelectedObjectsChanged (EventArgs.Empty); } } [BrowsableAttribute(false)] [EditorBrowsable(EditorBrowsableState.Advanced)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PropertyTab SelectedTab { get { return selected_tab; } } public override ISite Site { get { return base.Site; } set { base.Site = value; } } [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public override string Text { get { return base.Text; } set { base.Text = value; } } [DefaultValue(true)] public virtual bool ToolbarVisible { get { return toolbar.Visible; } set { if (toolbar.Visible == value) { return; } toolbar.Visible = value; } } protected ToolStripRenderer ToolStripRenderer { get { if (toolbar != null) { return toolbar.Renderer; } return null; } set { if (toolbar != null) { toolbar.Renderer = value; } } } [DefaultValue ("Color [Window]")] public Color ViewBackColor { get { return property_grid_view.BackColor; } set { if (property_grid_view.BackColor == value) { return; } property_grid_view.BackColor = value; } } [DefaultValue ("Color [WindowText]")] public Color ViewForeColor { get { return property_grid_view.ForeColor; } set { if (property_grid_view.ForeColor == value) { return; } property_grid_view.ForeColor = value; } } [DefaultValue (false)] public bool UseCompatibleTextRendering { get { return use_compatible_text_rendering; } set { if (use_compatible_text_rendering != value) { use_compatible_text_rendering = value; if (Parent != null) Parent.PerformLayout (this, "UseCompatibleTextRendering"); Invalidate (); } } } #endregion // Public Instance Properties #region Protected Instance Properties protected override Size DefaultSize { get { return base.DefaultSize; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Advanced)] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] protected virtual Type DefaultTabType { get { return typeof(PropertiesTab); } } protected bool DrawFlatToolbar { get { return (toolbar.Appearance == ToolBarAppearance.Flat); } set { if (value) toolbar.Appearance = ToolBarAppearance.Flat; else toolbar.Appearance = ToolBarAppearance.Normal; } } protected internal override bool ShowFocusCues { get { return base.ShowFocusCues; } } #endregion // Protected Instance Properties #region Public Instance Methods protected override void Dispose(bool disposing) { base.Dispose(disposing); } public void CollapseAllGridItems () { GridEntry category = FindCategoryItem (selected_grid_item); if (category != null) SelectedGridItem = category; CollapseItemRecursive (root_grid_item); property_grid_view.UpdateView (); } private void CollapseItemRecursive (GridItem item) { if (item == null) return; foreach (GridItem child in item.GridItems) { CollapseItemRecursive (child); if (child.Expandable) child.Expanded = false; } } private GridEntry FindCategoryItem (GridEntry entry) { if (entry == null || (property_sort != PropertySort.Categorized && property_sort != PropertySort.CategorizedAlphabetical)) return null; if (entry.GridItemType == GridItemType.Category) return entry; GridEntry category = null; GridItem current = (GridItem)entry; while (category == null) { if (current.Parent != null && current.Parent.GridItemType == GridItemType.Category) category = (GridEntry) current.Parent; current = current.Parent; if (current == null) break; } return (GridEntry) category; } public void ExpandAllGridItems () { ExpandItemRecursive (root_grid_item); property_grid_view.UpdateView (); } private void ExpandItemRecursive (GridItem item) { if (item == null) return; foreach (GridItem child in item.GridItems) { ExpandItemRecursive (child); if (child.Expandable) child.Expanded = true; } } public override void Refresh () { base.Refresh (); // force a full reload here SelectedObjects = SelectedObjects; } private void toolbar_Clicked (PropertyToolBarButton button) { if (button == null) return; if (button == alphabetic_toolbarbutton) { this.PropertySort = PropertySort.Alphabetical; alphabetic_toolbarbutton.Pushed = true; categorized_toolbarbutton.Pushed = false; } else if (button == categorized_toolbarbutton) { this.PropertySort = PropertySort.CategorizedAlphabetical; categorized_toolbarbutton.Pushed = true; alphabetic_toolbarbutton.Pushed = false; } else { if (button.Enabled) SelectPropertyTab (button.PropertyTab); } } private void toolbarbutton_clicked (object o, EventArgs args) { toolbar_Clicked (o as PropertyToolBarButton); } private void SelectPropertyTab (PropertyTab propertyTab) { if (propertyTab != null && selected_tab != propertyTab) { foreach (object toolbarItem in toolbar.Items) { PropertyToolBarButton button = toolbarItem as PropertyToolBarButton; if (button != null && button.PropertyTab != null) { if (button.PropertyTab == selected_tab) button.Pushed = false; else if (button.PropertyTab == propertyTab) button.Pushed = true; } } selected_tab = propertyTab; PopulateGrid (selected_objects); SelectItemCore (null, GetDefaultPropertyItem (root_grid_item, selected_tab)); property_grid_view.UpdateView (); } } private void UpdatePropertySortButtonsState () { if (property_sort == PropertySort.NoSort) { alphabetic_toolbarbutton.Pushed = false; categorized_toolbarbutton.Pushed = false; } else if (property_sort == PropertySort.Alphabetical) { alphabetic_toolbarbutton.Pushed = true; categorized_toolbarbutton.Pushed = false; } else if (property_sort == PropertySort.Categorized || property_sort == PropertySort.CategorizedAlphabetical) { alphabetic_toolbarbutton.Pushed = false; categorized_toolbarbutton.Pushed = true; } } protected void ShowEventsButton (bool value) { if (value && property_tabs.Contains (typeof (EventsTab))) events_tab_visible = true; else events_tab_visible = false; RefreshTabs (PropertyTabScope.Component); } public void RefreshTabs (PropertyTabScope tabScope) { property_tabs.Clear (tabScope); if (selected_objects != null) { Type[] tabTypes = null; PropertyTabScope[] tabScopes = null; if (events_tab_visible && property_tabs.Contains (typeof (EventsTab))) property_tabs.InsertTab (0, properties_tab, PropertyTabScope.Component); GetMergedPropertyTabs (selected_objects, out tabTypes, out tabScopes); if (tabTypes != null && tabScopes != null && tabTypes.Length > 0) { bool selectedTabPreserved = false; for (int i=0; i < tabTypes.Length; i++) { property_tabs.AddTabType (tabTypes[i], tabScopes[i]); if (tabTypes[i] == selected_tab.GetType ()) selectedTabPreserved = true; } if (!selectedTabPreserved) SelectPropertyTab (properties_tab); } } else { SelectPropertyTab (properties_tab); } RefreshToolbar (property_tabs); } private void RefreshToolbar (PropertyTabCollection tabs) { EnsurePropertiesTab (); toolbar.SuspendLayout (); toolbar.Items.Clear (); toolbar_imagelist.Images.Clear (); int imageIndex = 0; toolbar.Items.Add (categorized_toolbarbutton); toolbar_imagelist.Images.Add (categorized_image); categorized_toolbarbutton.ImageIndex = imageIndex; imageIndex++; toolbar.Items.Add (alphabetic_toolbarbutton); toolbar_imagelist.Images.Add (alphabetical_image); alphabetic_toolbarbutton.ImageIndex = imageIndex; imageIndex++; toolbar.Items.Add (separator_toolbarbutton); if (tabs != null && tabs.Count > 0) { foreach (PropertyTab tab in tabs) { PropertyToolBarButton button = new PropertyToolBarButton (tab); toolbar.Items.Add (button); if (tab.Bitmap != null) { tab.Bitmap.MakeTransparent (); toolbar_imagelist.Images.Add (tab.Bitmap); button.ImageIndex = imageIndex; imageIndex++; } if (tab == selected_tab) button.Pushed = true; } toolbar.Items.Add (new PropertyToolBarSeparator ()); } toolbar.Items.Add (propertypages_toolbarbutton); toolbar_imagelist.Images.Add (propertypages_image); propertypages_toolbarbutton.ImageIndex = imageIndex; toolbar.ResumeLayout (); } private void EnsurePropertiesTab () { if (property_tabs == null) return; if (property_tabs.Count > 0 && !property_tabs.Contains (this.DefaultTabType)) property_tabs.InsertTab (0, properties_tab, PropertyTabScope.Component); } private void GetMergedPropertyTabs (object[] objects, out Type[] tabTypes, out PropertyTabScope[] tabScopes) { tabTypes = null; tabScopes = null; if (objects == null || objects.Length == 0) return; ArrayList intersection = null; ArrayList scopes = new ArrayList (); for (int i=0; i < objects.Length; i++) { if (objects[i] == null) continue; PropertyTabAttribute tabAttribute = (PropertyTabAttribute)TypeDescriptor.GetAttributes (objects[i])[typeof (PropertyTabAttribute)]; if (tabAttribute == null || tabAttribute.TabClasses == null || tabAttribute.TabClasses.Length == 0) return; ArrayList new_intersection = new ArrayList (); scopes.Clear (); IList currentIntersection = (i == 0 ? (IList)tabAttribute.TabClasses : (IList)intersection); for (int j=0; j < currentIntersection.Count; j++) { if ((Type)intersection[j] == tabAttribute.TabClasses[j]) { new_intersection.Add (tabAttribute.TabClasses[j]); scopes.Add (tabAttribute.TabScopes[j]); } } intersection = new_intersection; } tabTypes = new Type[intersection.Count]; intersection.CopyTo (tabTypes); tabScopes = new PropertyTabScope[tabTypes.Length]; scopes.CopyTo (tabScopes); } public void ResetSelectedProperty() { if (selected_grid_item == null) return; selected_grid_item.ResetValue (); } #endregion // Public Instance Methods #region Protected Instance Methods protected virtual PropertyTab CreatePropertyTab (Type tabType) { if (!typeof(PropertyTab).IsAssignableFrom (tabType)) return null; PropertyTab tab = null; ConstructorInfo ctor = tabType.GetConstructor (new Type[] { typeof (IServiceProvider) }); if (ctor != null) tab = (PropertyTab)ctor.Invoke (new object[] { this.Site }); else tab = (PropertyTab)Activator.CreateInstance (tabType); return tab; } [MonoTODO ("Never called")] protected void OnComComponentNameChanged(ComponentRenameEventArgs e) { ComponentRenameEventHandler eh = (ComponentRenameEventHandler)(Events [ComComponentNameChangedEvent]); if (eh != null) eh (this, e); } protected override void OnEnabledChanged (EventArgs e) { base.OnEnabledChanged (e); } protected override void OnFontChanged(EventArgs e) { base.OnFontChanged (e); } protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); } protected override void OnHandleCreated (EventArgs e) { base.OnHandleCreated (e); } protected override void OnHandleDestroyed (EventArgs e) { base.OnHandleDestroyed (e); } protected override void OnMouseDown (MouseEventArgs me) { base.OnMouseDown (me); } protected override void OnMouseMove (MouseEventArgs me) { base.OnMouseMove (me); } protected override void OnMouseUp (MouseEventArgs me) { base.OnMouseUp (me); } protected void OnNotifyPropertyValueUIItemsChanged(object sender, EventArgs e) { property_grid_view.UpdateView (); } protected override void OnPaint (PaintEventArgs pevent) { pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle); base.OnPaint (pevent); } protected virtual void OnPropertySortChanged(EventArgs e) { EventHandler eh = (EventHandler) Events [PropertySortChangedEvent]; if (eh != null) eh (this, e); } protected virtual void OnPropertyTabChanged (PropertyTabChangedEventArgs e) { PropertyTabChangedEventHandler eh = (PropertyTabChangedEventHandler)(Events [PropertyTabChangedEvent]); if (eh != null) eh (this, e); } protected virtual void OnPropertyValueChanged (PropertyValueChangedEventArgs e) { PropertyValueChangedEventHandler eh = (PropertyValueChangedEventHandler)(Events [PropertyValueChangedEvent]); if (eh != null) eh (this, e); } protected override void OnResize (EventArgs e) { base.OnResize (e); } protected virtual void OnSelectedGridItemChanged (SelectedGridItemChangedEventArgs e) { SelectedGridItemChangedEventHandler eh = (SelectedGridItemChangedEventHandler)(Events [SelectedGridItemChangedEvent]); if (eh != null) eh (this, e); } protected virtual void OnSelectedObjectsChanged (EventArgs e) { EventHandler eh = (EventHandler)(Events [SelectedObjectsChangedEvent]); if (eh != null) eh (this, e); } protected override void OnSystemColorsChanged (EventArgs e) { base.OnSystemColorsChanged (e); } protected override void OnVisibleChanged (EventArgs e) { base.OnVisibleChanged (e); } protected override bool ProcessDialogKey (Keys keyData) { return base.ProcessDialogKey (keyData); } [EditorBrowsable (EditorBrowsableState.Never)] protected override void ScaleCore (float dx, float dy) { base.ScaleCore (dx, dy); } protected override void WndProc (ref Message m) { base.WndProc (ref m); } #endregion #region Events static object PropertySortChangedEvent = new object (); static object PropertyTabChangedEvent = new object (); static object PropertyValueChangedEvent = new object (); static object SelectedGridItemChangedEvent = new object (); static object SelectedObjectsChangedEvent = new object (); public event EventHandler PropertySortChanged { add { Events.AddHandler (PropertySortChangedEvent, value); } remove { Events.RemoveHandler (PropertySortChangedEvent, value); } } public event PropertyTabChangedEventHandler PropertyTabChanged { add { Events.AddHandler (PropertyTabChangedEvent, value); } remove { Events.RemoveHandler (PropertyTabChangedEvent, value); } } public event PropertyValueChangedEventHandler PropertyValueChanged { add { Events.AddHandler (PropertyValueChangedEvent, value); } remove { Events.RemoveHandler (PropertyValueChangedEvent, value); } } public event SelectedGridItemChangedEventHandler SelectedGridItemChanged { add { Events.AddHandler (SelectedGridItemChangedEvent, value); } remove { Events.RemoveHandler (SelectedGridItemChangedEvent, value); } } public event EventHandler SelectedObjectsChanged { add { Events.AddHandler (SelectedObjectsChangedEvent, value); } remove { Events.RemoveHandler (SelectedObjectsChangedEvent, value); } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler BackgroundImageChanged { add { base.BackgroundImageChanged += value; } remove { base.BackgroundImageChanged -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler BackgroundImageLayoutChanged { add { base.BackgroundImageLayoutChanged += value; } remove { base.BackgroundImageLayoutChanged -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler ForeColorChanged { add { base.ForeColorChanged += value; } remove { base.ForeColorChanged -= value; } } [EditorBrowsable(EditorBrowsableState.Advanced)] [Browsable(false)] public new event KeyEventHandler KeyDown { add { base.KeyDown += value; } remove { base.KeyDown -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Advanced)] public new event KeyPressEventHandler KeyPress { add { base.KeyPress += value; } remove { base.KeyPress -= value; } } [EditorBrowsable(EditorBrowsableState.Advanced)] [Browsable(false)] public new event KeyEventHandler KeyUp { add { base.KeyUp += value; } remove { base.KeyUp -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Advanced)] public new event MouseEventHandler MouseDown { add { base.MouseDown += value; } remove { base.MouseDown -= value; } } [EditorBrowsable(EditorBrowsableState.Advanced)] [Browsable(false)] public new event EventHandler MouseEnter { add { base.MouseEnter += value; } remove { base.MouseEnter -= value; } } [EditorBrowsable(EditorBrowsableState.Advanced)] [Browsable(false)] public new event EventHandler MouseLeave { add { base.MouseLeave += value; } remove { base.MouseLeave -= value; } } [EditorBrowsable(EditorBrowsableState.Advanced)] [Browsable(false)] public new event MouseEventHandler MouseMove { add { base.MouseMove += value; } remove { base.MouseMove -= value; } } [EditorBrowsable(EditorBrowsableState.Advanced)] [Browsable(false)] public new event MouseEventHandler MouseUp { add { base.MouseUp += value; } remove { base.MouseUp -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler PaddingChanged { add { base.PaddingChanged += value; } remove { base.PaddingChanged -= value; } } [Browsable(false)] public new event EventHandler TextChanged { add { base.TextChanged += value; } remove { base.TextChanged -= value; } } #endregion #region Com2Interop.IComPropertyBrowser Interface [MonoTODO ("Not implemented, will throw NotImplementedException")] bool ComponentModel.Com2Interop.IComPropertyBrowser.InPropertySet { get { throw new NotImplementedException(); } } [MonoTODO ("Stub, does nothing")] void ComponentModel.Com2Interop.IComPropertyBrowser.DropDownDone () { } [MonoTODO ("Not implemented, will throw NotImplementedException")] bool ComponentModel.Com2Interop.IComPropertyBrowser.EnsurePendingChangesCommitted () { throw new NotImplementedException (); } [MonoTODO ("Stub, does nothing")] void ComponentModel.Com2Interop.IComPropertyBrowser.HandleF4 () { } [MonoTODO ("Stub, does nothing")] void ComponentModel.Com2Interop.IComPropertyBrowser.LoadState (Microsoft.Win32.RegistryKey optRoot) { } [MonoTODO ("Stub, does nothing")] void ComponentModel.Com2Interop.IComPropertyBrowser.SaveState (Microsoft.Win32.RegistryKey optRoot) { } static object ComComponentNameChangedEvent = new object (); event ComponentRenameEventHandler ComponentModel.Com2Interop.IComPropertyBrowser.ComComponentNameChanged { add { Events.AddHandler (ComComponentNameChangedEvent, value); } remove { Events.RemoveHandler (ComComponentNameChangedEvent, value); } } #endregion // Com2Interop.IComPropertyBrowser Interface #region PropertyTabCollection Class public class PropertyTabCollection : ICollection, IEnumerable { ArrayList property_tabs; ArrayList property_tabs_scopes; PropertyGrid property_grid; internal PropertyTabCollection (PropertyGrid propertyGrid) { property_grid = propertyGrid; property_tabs = new ArrayList (); property_tabs_scopes = new ArrayList (); } public PropertyTab this[int index] { get { return (PropertyTab)property_tabs[index]; } } bool ICollection.IsSynchronized { get { return property_tabs.IsSynchronized; } } void ICollection.CopyTo (Array dest, int index) { property_tabs.CopyTo (dest, index); } object ICollection.SyncRoot { get { return property_tabs.SyncRoot; } } public IEnumerator GetEnumerator () { return property_tabs.GetEnumerator (); } public int Count { get { return property_tabs.Count; } } public void AddTabType (Type propertyTabType) { AddTabType (propertyTabType, PropertyTabScope.Global); } public void AddTabType (Type propertyTabType, PropertyTabScope tabScope) { if (propertyTabType == null) throw new ArgumentNullException ("propertyTabType"); // Avoid duplicates if (this.Contains (propertyTabType)) return; PropertyTab tab = property_grid.CreatePropertyTab (propertyTabType); if (tab != null) { property_tabs.Add (tab); property_tabs_scopes.Add (tabScope); } property_grid.RefreshToolbar (this); } internal PropertyTabScope GetTabScope (PropertyTab tab) { if (tab == null) throw new ArgumentNullException ("tab"); int index = property_tabs.IndexOf (tab); if (index != -1) return (PropertyTabScope)property_tabs_scopes[index]; return PropertyTabScope.Global; } internal void InsertTab (int index, PropertyTab propertyTab, PropertyTabScope tabScope) { if (propertyTab == null) throw new ArgumentNullException ("propertyTab"); if (!this.Contains (propertyTab.GetType ())) { property_tabs.Insert (index, propertyTab); property_tabs_scopes.Insert (index, tabScope); } } internal bool Contains (Type propertyType) { if (propertyType == null) throw new ArgumentNullException ("propertyType"); foreach (PropertyTab t in property_tabs) { if (t.GetType () == propertyType) return true; } return false; } internal PropertyTab this[Type tabType] { get { foreach (PropertyTab tab in property_tabs) { if (tabType == tab.GetType ()) return tab; } return null; } } public void Clear (PropertyTabScope tabScope) { ArrayList toRemove = new ArrayList (); for (int i=0; i < property_tabs_scopes.Count; i++) { if ((PropertyTabScope)property_tabs_scopes[i] == tabScope) toRemove.Add (i); } foreach (int indexToRemove in toRemove) { property_tabs.RemoveAt (indexToRemove); property_tabs_scopes.RemoveAt (indexToRemove); } property_grid.RefreshToolbar (this); } public void RemoveTabType (Type propertyTabType) { if (propertyTabType == null) throw new ArgumentNullException ("propertyTabType"); ArrayList toRemove = new ArrayList (); for (int i=0; i < property_tabs.Count; i++) { if (property_tabs[i].GetType () == propertyTabType) toRemove.Add (i); } foreach (int indexToRemove in toRemove) { property_tabs.RemoveAt (indexToRemove); property_tabs_scopes.RemoveAt (indexToRemove); } property_grid.RefreshToolbar (this); } } #endregion // PropertyTabCollection Class #region Private Helper Methods private GridItem FindFirstPropertyItem (GridItem root) { if (root.GridItemType == GridItemType.Property) return root; foreach (GridItem item in root.GridItems) { GridItem subitem = FindFirstPropertyItem (item); if (subitem != null) return subitem; } return null; } private GridEntry GetDefaultPropertyItem (GridEntry rootItem, PropertyTab propertyTab) { if (rootItem == null || rootItem.GridItems.Count == 0 || propertyTab == null) return null; object[] propertyOwners = rootItem.Values; if (propertyOwners == null || propertyOwners.Length == 0 || propertyOwners[0] == null) return null; GridItem defaultSelected = null; if (propertyOwners.Length > 1) defaultSelected = rootItem.GridItems[0]; else { PropertyDescriptor defaultProperty = propertyTab.GetDefaultProperty (propertyOwners[0]); if (defaultProperty != null) defaultSelected = FindItem (defaultProperty.Name, rootItem); if (defaultSelected == null) defaultSelected = FindFirstPropertyItem (rootItem); } return defaultSelected as GridEntry; } private GridEntry FindItem (string name, GridEntry rootItem) { if (rootItem == null || name == null) return null; if (property_sort == PropertySort.Alphabetical || property_sort == PropertySort.NoSort) { foreach (GridItem item in rootItem.GridItems) { if (item.Label == name) { return (GridEntry)item; } } } else if (property_sort == PropertySort.Categorized || property_sort == PropertySort.CategorizedAlphabetical) { foreach (GridItem categoryItem in rootItem.GridItems) { foreach (GridItem item in categoryItem.GridItems) { if (item.Label == name) { return (GridEntry)item; } } } } return null; } private void OnResetPropertyClick (object sender, EventArgs e) { ResetSelectedProperty(); } private void OnDescriptionClick (object sender, EventArgs e) { this.HelpVisible = !this.HelpVisible; description_menuitem.Checked = this.HelpVisible; } private void PopulateGrid (object[] objects) { if (objects.Length > 0) { root_grid_item = new RootGridEntry (this, objects); root_grid_item.Expanded = true; UpdateSortLayout (root_grid_item); } else { root_grid_item = null; } } private void UpdateSortLayout (GridEntry rootItem) { if (rootItem == null) return; GridItemCollection reordered = new GridItemCollection (); if (property_sort == PropertySort.Alphabetical || property_sort == PropertySort.NoSort) { alphabetic_toolbarbutton.Pushed = true; categorized_toolbarbutton.Pushed = false; foreach (GridItem item in rootItem.GridItems) { if (item.GridItemType == GridItemType.Category) { foreach (GridItem categoryChild in item.GridItems) { reordered.Add (categoryChild); ((GridEntry)categoryChild).SetParent (rootItem); } } else { reordered.Add (item); } } } else if (property_sort == PropertySort.Categorized || property_sort == PropertySort.CategorizedAlphabetical) { alphabetic_toolbarbutton.Pushed = false; categorized_toolbarbutton.Pushed = true; GridItemCollection categories = new GridItemCollection (); foreach (GridItem item in rootItem.GridItems) { if (item.GridItemType == GridItemType.Category) { categories.Add (item); continue; } string categoryName = item.PropertyDescriptor.Category; if (categoryName == null) categoryName = UNCATEGORIZED_CATEGORY_LABEL; GridItem category_item = rootItem.GridItems [categoryName]; if (category_item == null) category_item = categories [categoryName]; if (category_item == null) { // Create category grid items if they already don't category_item = new CategoryGridEntry (this, categoryName, rootItem); category_item.Expanded = true; categories.Add (category_item); } category_item.GridItems.Add (item); ((GridEntry)item).SetParent (category_item); } reordered.AddRange (categories); } rootItem.GridItems.Clear (); rootItem.GridItems.AddRange (reordered); } private void help_panel_Paint(object sender, PaintEventArgs e) { e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(help_panel.BackColor), help_panel.ClientRectangle ); e.Graphics.DrawRectangle(SystemPens.ControlDark, 0,0,help_panel.Width-1,help_panel.Height-1 ); } #endregion // Private Helper Methods #region Internal helper classes // as we can not change the color for BorderStyle.FixedSingle and we need the correct // ClientRectangle so that the ScrollBar doesn't draw over the border we need this class internal class BorderHelperControl : Control { public BorderHelperControl () { BackColor = ThemeEngine.Current.ColorWindow; } protected override void OnPaint (PaintEventArgs e) { e.Graphics.DrawRectangle (SystemPens.ControlDark, 0 , 0 , Width - 1, Height - 1); base.OnPaint (e); } protected override void OnSizeChanged (EventArgs e) { if (Controls.Count == 1) { Control control = Controls [0]; if (control.Location.X != 1 || control.Location.Y != 1) control.Location = new Point (1, 1); control.Width = ClientRectangle.Width - 2; control.Height = ClientRectangle.Height - 2; } base.OnSizeChanged (e); } } private class PropertyToolBarSeparator : ToolStripSeparator { public PropertyToolBarSeparator () { } } private class PropertyToolBarButton : ToolStripButton { private PropertyTab property_tab; public PropertyToolBarButton () { } public PropertyToolBarButton (PropertyTab propertyTab) { if (propertyTab == null) throw new ArgumentNullException ("propertyTab"); property_tab = propertyTab; } public PropertyTab PropertyTab { get { return property_tab; } } public bool Pushed { get { return base.Checked; } set { base.Checked = value; } } public ToolBarButtonStyle Style { get { return ToolBarButtonStyle.PushButton; } set { } } } // needed! this little helper makes it possible to draw a different toolbar border // and toolbar backcolor in ThemeWin32Classic internal class PropertyToolBar : ToolStrip { ToolBarAppearance appearance; public PropertyToolBar () { SetStyle (ControlStyles.ResizeRedraw, true); GripStyle = ToolStripGripStyle.Hidden; appearance = ToolBarAppearance.Normal; } public bool ShowToolTips { get { return base.ShowItemToolTips; } set { base.ShowItemToolTips = value; } } public ToolBarAppearance Appearance { get { return appearance; } set { if (value == Appearance) return; switch (value) { case ToolBarAppearance.Flat: Renderer = new ToolStripSystemRenderer (); appearance = ToolBarAppearance.Flat; break; case ToolBarAppearance.Normal: ProfessionalColorTable table = new ProfessionalColorTable (); table.UseSystemColors = true; Renderer = new ToolStripProfessionalRenderer (table); appearance = ToolBarAppearance.Normal; break; } } } } [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")] private class SelectedObjectConverter : TypeConverter { } #endregion } }