using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Linq;
using System.Runtime.CompilerServices;
namespace Vanara.Windows
{
/// A generic base to implement for a single extender type.
/// The type of the type that can be extended.
public abstract class ExtenderProviderBase : Component, IExtenderProvider, ISupportInitialize where TExtend : Component
{
/// A dictionary that holds a property bag for each extended type.
protected readonly Dictionary> propHash = new();
/// Initializes a new instance of the class.
protected ExtenderProviderBase() { }
/// Initializes a new instance of the class.
/// The parent.
protected ExtenderProviderBase(TExtend parent) => OnAddingExtender(parent);
/// Initializes a new instance of the class.
/// The container.
/// container
protected ExtenderProviderBase(IContainer container) : this()
{
if (container is null)
throw new ArgumentNullException(nameof(container));
container.Add(this);
}
/// Occurs when a new extender is being added.
protected event EventHandler AddingExtender;
/// Sets the site.
/// The site.
public override ISite Site
{
set
{
base.Site = value;
var parent = (value?.GetService(typeof(IDesignerHost)) as IDesignerHost)?.RootComponent as TExtend;
if (parent != null)
OnAddingExtender(parent);
}
}
/// Gets all extended components that have properties assigned.
/// Returns a value.
protected IEnumerable ExtendedComponents => propHash.Keys;
/// Gets the known properties stored against all components.
/// Returns a value.
protected IEnumerable KnownProperties => propHash.Values.SelectMany(d => d.Keys).Distinct();
/// Signals the object that initialization is starting.
public virtual void BeginInit() { }
/// Determines whether this instance can extend the specified extendee.
/// The extendee.
/// if this instance can extend the specified extendee; otherwise, .
public virtual bool CanExtend(object extendee) => extendee is TExtend;
/// Signals the object that initialization is complete.
public virtual void EndInit() { }
/// Gets the property value.
/// The type of the property to get.
/// The form.
/// The default value.
/// Name of the field.
///
protected virtual T GetPropertyValue(TExtend form, T defaultValue = default, [CallerMemberName] string propName = "")
{
if (propName.StartsWith("Get"))
propName = propName.Remove(0, 3);
return propHash.TryGetValue(form, out var props) && props.TryGetValue(propName, out var prop) ? (T)prop : defaultValue;
}
/// Calls the event.
/// The extender being added.
protected virtual void OnAddingExtender(TExtend extender)
{
var args = new AddExtenderEventArgs(extender);
AddingExtender?.Invoke(this, args);
propHash[extender] = args.ExtenderProperties;
}
/// Sets the property value.
/// The type of the property to set.
/// The form.
/// The value.
/// Name of the field.
protected virtual bool SetPropertyValue(TExtend form, T value, [CallerMemberName] string propName = "")
{
if (!propHash.ContainsKey(form))
OnAddingExtender(form);
if (propName.StartsWith("Set"))
propName = propName.Remove(0, 3);
if (propHash[form].TryGetValue(propName, out var prop) && Equals(prop, value))
return false;
propHash[form][propName] = value;
return true;
}
/// Arguments for the event.
public class AddExtenderEventArgs : EventArgs
{
internal AddExtenderEventArgs(TExtend parent)
{
Extender = parent;
ExtenderProperties = new Dictionary();
}
/// Gets the extender being added.
/// The extender.
public TExtend Extender { get; }
/// Gets or sets the property bag to be associated with this extender.
/// The extender property bag.
public Dictionary ExtenderProperties { get; set; }
}
}
}