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