using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace JD.Serialization
{
///
/// Holds the curves of a clip.
///
///
/// Initialize itself using the reflection. Parses all the properties declared with a and adds them to the editable list.
///
public class CurveCollection : UAFList
{
private readonly Clip _clip;
public CurveCollection(Clip clip)
{
_clip = clip;
_clip.PropertyChanged += clip_PropertyChanged;
InitializeCurves();
}
public BezierCurveFloat this[BezierCurveType curveType]
{
get
{
return Items.FirstOrDefault(x => x.Type == curveType);
}
}
#region Curve Initialization With Reflection
///
/// Cache the curve properties, calling the reflection can be long.
///
private static readonly ConcurrentDictionary> _curvesProperties = new ConcurrentDictionary>();
private void InitializeCurves()
{
foreach (var property in GetCurveProperties())
{
var curve = (BezierCurveFloat)property.GetValue(_clip, null);
curve.Type = GetCurveType(property).Value;
curve.Clip = _clip;
Add(curve);
}
}
private IEnumerable GetCurveProperties()
{
return _curvesProperties.GetOrAdd(_clip.GetType(), x =>
{
return _clip.GetType().GetProperties().Where(property => GetCurveType(property) != null).ToList();
});
}
private BezierCurveType? GetCurveType(PropertyInfo property)
{
var attributes = property.GetCustomAttributes(typeof(BezierCurveTypeAttribute), true);
return attributes.Length > 0 ? ((BezierCurveTypeAttribute)attributes[0]).Type : (BezierCurveType?)null;
}
///
/// When a curve is reassigned, update the curve collection.
///
void clip_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (!string.IsNullOrEmpty(e.PropertyName) && GetCurveProperties().Any(property => property.Name == e.PropertyName))
{
Clear();
InitializeCurves();
}
}
#endregion
}
}