File: winforms\Managed\System\WinForms\PropertyGridInternal\SingleSelectRootGridEntry.cs
Project: ndp\fx\src\System.Windows.Forms.csproj (System.Windows.Forms)
//------------------------------------------------------------------------------
// <copyright file="SingleSelectRootGridEntry.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
/*
 */
namespace System.Windows.Forms.PropertyGridInternal {
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System;
    using System.Collections;
    using System.Reflection;    
    using System.ComponentModel.Design;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    using System.Drawing;
    using Microsoft.Win32;
 
 
    internal class SingleSelectRootGridEntry : GridEntry, IRootGridEntry {
        protected object             objValue;
        protected String             objValueClassName;
        protected GridEntry          propDefault;
        protected IDesignerHost      host;
        protected IServiceProvider baseProvider = null;
        protected PropertyTab        tab = null;
        protected PropertyGridView     gridEntryHost    = null;
        protected AttributeCollection  browsableAttributes = null;
        private   IComponentChangeService changeService;
        protected bool forceReadOnlyChecked;
        
        // 
 
        [
            SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")  // GridEntry classes are internal so we have complete
                                                                                                    // control over who does what in the constructor.
        ]
        internal SingleSelectRootGridEntry(PropertyGridView gridEntryHost, object value, GridEntry parent, IServiceProvider baseProvider, IDesignerHost host, PropertyTab tab, PropertySort sortType)
        : base(gridEntryHost.OwnerGrid, parent) {
            Debug.Assert(value != null,"Can't browse a null object!");
            this.host = host;
            this.gridEntryHost = gridEntryHost;
            this.baseProvider = baseProvider;
            this.tab = tab;
            this.objValue = value;
            this.objValueClassName = TypeDescriptor.GetClassName(this.objValue);
 
            this.IsExpandable = true;
            // default to categories
            this.PropertySort = sortType;
            this.InternalExpanded = true;
        }
 
        [
            SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")  // GridEntry classes are internal so we have complete
                                                                                                    // control over who does what in the constructor.
        ]
        internal SingleSelectRootGridEntry(PropertyGridView view, object value, IServiceProvider baseProvider, IDesignerHost host, PropertyTab tab, PropertySort sortType) : this(view, value,null, baseProvider, host, tab, sortType) {
        }   
 
        /// <include file='doc\SingleSelectRootGridEntry.uex' path='docs/doc[@for="SingleSelectRootGridEntry.BrowsableAttributes"]/*' />
        /// <devdoc>
        /// The set of attributes that will be used for browse filtering
        /// </devdoc>
        public override AttributeCollection BrowsableAttributes {
            get {
                if (browsableAttributes == null) {
                    browsableAttributes = new AttributeCollection(new Attribute[]{BrowsableAttribute.Yes});
                }
                return this.browsableAttributes;
            }
            set {
                if (value == null) {
                    ResetBrowsableAttributes();
                    return;
                }
 
                bool same = true;
 
                if (this.browsableAttributes != null && value != null && this.browsableAttributes.Count == value.Count) {
                    Attribute[] attr1 = new Attribute[browsableAttributes.Count];
                    Attribute[] attr2 = new Attribute[value.Count];
 
                    browsableAttributes.CopyTo(attr1, 0);
                    value.CopyTo(attr2, 0);
                    
                    Array.Sort(attr1, GridEntry.AttributeTypeSorter);
                    Array.Sort(attr2, GridEntry.AttributeTypeSorter);
                    for (int i = 0; i < attr1.Length; i++) {
                        if (!attr1[i].Equals(attr2[i])) {
                            same = false;
                            break;
                        }
                    }
                }
                else {
                    same = false;
                }
 
                this.browsableAttributes = value;
 
                if (!same && Children != null && Children.Count > 0) {
                    DisposeChildren();
                }
            }
        }
        
        protected override IComponentChangeService ComponentChangeService {
            get {
               if (changeService == null) {
                    changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
               }
               return changeService;
            }
        }
        
        internal override bool AlwaysAllowExpand {
            get {
               return true;
            }
        }
 
        public override PropertyTab CurrentTab {
            get {
                return tab;
            }
            set {
                this.tab = value;
            }
        }
 
        internal override GridEntry DefaultChild {
            get {
                return propDefault;
            }
            set {
                this.propDefault = value;
            }
        }
 
        internal override IDesignerHost DesignerHost {
            get {
                return host;
            }
            set {
                host = value;
            }
        }
 
        internal override bool ForceReadOnly {
            get {
                if (!forceReadOnlyChecked) {
                    ReadOnlyAttribute readOnlyAttr = (ReadOnlyAttribute)TypeDescriptor.GetAttributes(this.objValue)[typeof(ReadOnlyAttribute)];
                    if ((readOnlyAttr != null && !readOnlyAttr.IsDefaultAttribute()) || TypeDescriptor.GetAttributes(this.objValue).Contains(InheritanceAttribute.InheritedReadOnly)) {
                        flags |= FLAG_FORCE_READONLY;
                    }
                    forceReadOnlyChecked = true;
                }
                return base.ForceReadOnly || (GridEntryHost != null && !GridEntryHost.Enabled);
            }
        }
 
        internal override PropertyGridView GridEntryHost {
            get {       
                return this.gridEntryHost;
            }
            set {
                this.gridEntryHost = value;
            }
        }
        
        public override GridItemType GridItemType {
            get {
                return GridItemType.Root;
            }
        } 
 
        /// <include file='doc\SingleSelectRootGridEntry.uex' path='docs/doc[@for="SingleSelectRootGridEntry.HelpKeyword"]/*' />
        /// <devdoc>
        ///     Retrieves the keyword that the VS help dynamic help window will
        ///     use when this IPE is selected.
        /// </devdoc>
        public override string HelpKeyword {
            get {
                
               HelpKeywordAttribute helpAttribute = (HelpKeywordAttribute)TypeDescriptor.GetAttributes(objValue)[typeof(HelpKeywordAttribute)];
 
               if (helpAttribute != null && !helpAttribute.IsDefaultAttribute()) {
                    return helpAttribute.HelpKeyword;
               }
 
               return this.objValueClassName;
            }
        }
 
        public override string PropertyLabel {
            get {
                if (objValue is IComponent) {
                    ISite site = ((IComponent)objValue).Site;
                    if (site == null) {
                        return objValue.GetType().Name;
                    }
                    else {
                        return site.Name;
                    }
                }
                else if (objValue != null) {
                    return objValue.ToString();
                }
                return null;
            }
        }
          
        /// <include file='doc\SingleSelectRootGridEntry.uex' path='docs/doc[@for="SingleSelectRootGridEntry.PropertyValue"]/*' />
        /// <devdoc>
        /// Gets or sets the value for the property that is represented 
        /// by this GridEntry.
        /// </devdoc>
        public override object PropertyValue{
            get {
                return objValue;
            }
            set {
                object old = objValue;
                objValue = value;
                objValueClassName = TypeDescriptor.GetClassName(objValue);
                ownerGrid.ReplaceSelectedObject(old, value);
            }
        }
 
        protected override bool CreateChildren() {
            bool fReturn = base.CreateChildren();
            CategorizePropEntries();
            return fReturn;
        }
        
        protected override void Dispose(bool disposing) {
            if (disposing) {
                host = null;
                baseProvider = null;
                tab = null;
                gridEntryHost = null;
                changeService = null;
            }
            this.objValue = null;
            this.objValueClassName = null;
            this.propDefault = null;
            base.Dispose(disposing);
        }
 
        public override object GetService(Type serviceType) {
            object service = null;
            
            if (host != null) {
                service = host.GetService(serviceType);
            }
            if (service == null && baseProvider != null) {
                service = baseProvider.GetService(serviceType);
            }
            return service;
        }
 
        /// <include file='doc\SingleSelectRootGridEntry.uex' path='docs/doc[@for="SingleSelectRootGridEntry.ResetBrowsableAttributes"]/*' />
        /// <devdoc>
        /// Reset the Browsable attributes to the default (BrowsableAttribute.Yes)
        /// </devdoc>
        public void ResetBrowsableAttributes() {
            this.browsableAttributes = new AttributeCollection(new Attribute[]{BrowsableAttribute.Yes});
        }
 
 
        /// <include file='doc\SingleSelectRootGridEntry.uex' path='docs/doc[@for="SingleSelectRootGridEntry.ShowCategories"]/*' />
        /// <devdoc>
        /// Sets the value of this GridEntry from text
        /// </devdoc>
        public virtual void ShowCategories(bool fCategories) {
            if (((this.PropertySort &= PropertySort.Categorized) !=0) != fCategories) {
                
                if (fCategories) { 
                  this.PropertySort |= PropertySort.Categorized;
                }
                else {
                  this.PropertySort &= ~PropertySort.Categorized;
                }
                
                
                // recreate the children
                if (this.Expandable && this.ChildCollection != null) {
                    CreateChildren();
                }
            }
        }
 
        internal void CategorizePropEntries() {
            if (Children.Count > 0) {
                
                GridEntry[] childEntries = new GridEntry[this.Children.Count];
                this.Children.CopyTo(childEntries, 0);
                
                if ((this.PropertySort & PropertySort.Categorized) != 0) {
 
 
                    // first, walk through all the entires and 
                    // group them by their category by adding
                    // them to a hashtable of arraylists.
                    //
                    Hashtable bins = new Hashtable();
                    for (int i = 0; i < childEntries.Length; i++) {
                        GridEntry pe = childEntries[i];
						Debug.Assert(pe != null);
						if (pe != null) {
							string category = pe.PropertyCategory;
							ArrayList bin = (ArrayList)bins[category];
							if (bin == null) {
								bin = new ArrayList();
								bins[category] = bin;
							}
							bin.Add(pe);
						}
                    }
 
                    // now walk through the hashtable
                    // and create a categorygridentry for each
                    // category that holds all the properties
                    // of that category.
                    //
                    ArrayList propList = new ArrayList();
                    IDictionaryEnumerator enumBins = (IDictionaryEnumerator)bins.GetEnumerator();
                    while (enumBins.MoveNext()) {
                        ArrayList bin = (ArrayList)enumBins.Value;
                        if (bin != null) {
                            string category = (string)enumBins.Key;
                            if (bin.Count > 0) {
                                GridEntry[] rgpes = new GridEntry[bin.Count];
                                bin.CopyTo(rgpes, 0);
                                try {
                                    propList.Add(new CategoryGridEntry(this.ownerGrid, this, category, rgpes));
                                }
                                catch {
                                }
                            }
                        }
                    }
 
                    childEntries = new GridEntry[propList.Count];
                    propList.CopyTo(childEntries, 0);
                    StringSorter.Sort(childEntries);
                    
                    ChildCollection.Clear();
                    ChildCollection.AddRange(childEntries);
              }
           }
        }
       }
}