// Copyright (C) Stichting Deltares 2016. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using Core.Common.Gui.Attributes; using Core.Common.Gui.Forms.PropertyGridView; namespace Core.Common.Gui.PropertyBag { /// /// Defines a custom type descriptor for an object to be used as view-model for . /// It processes the special attributes defined in Core.Common.Gui.Attributes /// to dynamically affect property order or adding/removing . /// /// This class makes sure the following special attributes on properties are processed: /// /// /// /// /// /// public class DynamicPropertyBag : ICustomTypeDescriptor { /// /// Instantiates a new instance of , wrapping another /// object and exposing properties for that object. /// /// The object to be wrapped. public DynamicPropertyBag(object propertyObject) { Properties = new HashSet(); WrappedObject = propertyObject; foreach (var propertyInfo in propertyObject.GetType().GetProperties() .OrderBy(x => x.MetadataToken)) { Properties.Add(new PropertySpec(propertyInfo)); } } /// /// Gets the collection of properties contained within this . /// public ICollection Properties { get; private set; } /// /// Gets the object wrapped inside this /// public object WrappedObject { get; private set; } public override string ToString() { return WrappedObject.ToString(); } #region ICustomTypeDescriptor explicit interface definitions #region Implementations delegated to System.ComponentModel.TypeDescriptor public AttributeCollection GetAttributes() { return TypeDescriptor.GetAttributes(this, true); } public string GetClassName() { return TypeDescriptor.GetClassName(this, true); } public string GetComponentName() { return TypeDescriptor.GetComponentName(this, true); } public TypeConverter GetConverter() { return TypeDescriptor.GetConverter(this, true); } public EventDescriptor GetDefaultEvent() { return TypeDescriptor.GetDefaultEvent(this, true); } public EventDescriptorCollection GetEvents() { return TypeDescriptor.GetEvents(this, true); } public EventDescriptorCollection GetEvents(Attribute[] attributes) { return TypeDescriptor.GetEvents(this, attributes, true); } public object GetEditor(Type editorBaseType) { return TypeDescriptor.GetEditor(this, editorBaseType, true); } #endregion public PropertyDescriptor GetDefaultProperty() { return Properties.Count > 0 ? new PropertySpecDescriptor(Properties.First(), WrappedObject) : null; } public PropertyDescriptorCollection GetProperties() { return GetProperties(new Attribute[0]); } public PropertyDescriptorCollection GetProperties(Attribute[] attributesFilter) { var propertyDescriptorsToReturn = Properties.Select(p => new PropertySpecDescriptor(p, WrappedObject)) .Where(t => ShouldDescriptorBeReturned(t, attributesFilter)); var propertySpecDescriptors = OrderPropertyDescriptors(propertyDescriptorsToReturn); return new PropertyDescriptorCollection(propertySpecDescriptors); } private static PropertyDescriptor[] OrderPropertyDescriptors(IEnumerable propertyDescriptorsToReturn) { var unorderedProperties = new List(); var propertiesWithOrdering = new List>(); foreach (PropertyDescriptor pd in propertyDescriptorsToReturn) { var propertyOrderAttribute = pd.Attributes.OfType().FirstOrDefault(); if (propertyOrderAttribute != null) { propertiesWithOrdering.Add(new Tuple(propertyOrderAttribute.Order, pd)); } else { unorderedProperties.Add(pd); } } var orderedProperties = propertiesWithOrdering.OrderBy(p => p.Item1).Select(p => p.Item2); return orderedProperties.Concat(unorderedProperties).ToArray(); } private static bool ShouldDescriptorBeReturned(PropertyDescriptor propertySpecDescriptor, IEnumerable attributesFilter) { var browsableAttribute = attributesFilter.OfType().FirstOrDefault(); return browsableAttribute == null || propertySpecDescriptor.IsBrowsable == browsableAttribute.Browsable; } public object GetPropertyOwner(PropertyDescriptor pd) { return WrappedObject; } #endregion } }