// 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
}
}