/src/Base/PropertySystem/PropertyCollection.cs
C# | 250 lines | 199 code | 42 blank | 9 comment | 11 complexity | 199bcc1d8c70b96f24d8903d805375eb MD5 | raw file
- /////////////////////////////////////////////////////////////////////////////////
- // Paint.NET //
- // Copyright (C) Rick Brewster, Tom Jackson, and past contributors. //
- // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
- // See src/Resources/Files/License.txt for full licensing and attribution //
- // details. //
- // . //
- /////////////////////////////////////////////////////////////////////////////////
-
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
-
- //using PaintDotNet.PropertySystem; Unused Directive
-
- namespace PaintDotNet.Base.PropertySystem
- {
- public sealed class PropertyCollection
- : INotifyPropertyChanged,
- IEnumerable<Property>,
- ICloneable<PropertyCollection>
- {
- private bool _eventAddAllowed = true;
- private readonly Dictionary<string, Property> _properties = new Dictionary<string, Property>();
- private readonly List<PropertyCollectionRule> _rules = new List<PropertyCollectionRule>();
-
- public static PropertyCollection CreateEmpty()
- {
- return new PropertyCollection(new Property[0]);
- }
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- private void OnPropertyChanged(string propertyName)
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
-
- public Property this[object propertyName]
- {
- get
- {
- string propertyNameString = propertyName.ToString();
- Property theProperty;
- _properties.TryGetValue(propertyNameString, out theProperty);
- return theProperty;
- }
- }
-
- public int Count
- {
- get
- {
- return _properties.Count;
- }
- }
-
- public IEnumerable<Property> Properties
- {
- get
- {
- return _properties.Values;
- }
- }
-
- public IEnumerable<PropertyCollectionRule> Rules
- {
- get
- {
- return _rules;
- }
- }
-
- public IEnumerable<string> PropertyNames
- {
- get
- {
- return _properties.Keys;
- }
- }
-
- public PropertyCollection(IEnumerable<Property> properties)
- {
- Initialize(properties, new PropertyCollectionRule[0]);
- }
-
- public PropertyCollection(
- IEnumerable<Property> properties,
- IEnumerable<PropertyCollectionRule> rules)
- {
- Initialize(properties, rules);
- }
-
- public IDisposable InternalBeginEventAddMoratorium()
- {
- if (!_eventAddAllowed)
- {
- throw new InvalidOperationException("An event add moratorium is already in effect");
- }
-
- var propUndoFns = new List<IDisposable>(_properties.Count);
- propUndoFns.AddRange(_properties.Values.Select(property => property.BeginEventAddMoratorium()));
-
- IDisposable undoFn = new CallbackOnDispose(() =>
- {
- _eventAddAllowed = true;
-
- foreach (IDisposable propUndoFn in propUndoFns)
- {
- propUndoFn.Dispose();
- }
- });
-
- _eventAddAllowed = false;
-
- return undoFn;
- }
-
- private void Initialize(
- IEnumerable<Property> properties,
- IEnumerable<PropertyCollectionRule> rules)
- {
- foreach (Property property in properties)
- {
- Property propertyClone = property.Clone();
- _properties.Add(propertyClone.Name, propertyClone);
- }
-
- foreach (PropertyCollectionRule rule in rules)
- {
- PropertyCollectionRule ruleClone = rule.Clone();
- _rules.Add(ruleClone);
- }
-
- foreach (PropertyCollectionRule rule in _rules)
- {
- rule.Initialize(this);
- }
-
- HookUpEvents();
- }
-
- private void PropertyValueChanged(object sender, EventArgs e)
- {
- OnPropertyChanged(((Property) sender).Name);
- }
-
- private void PropertyReadOnlyChanged(object sender, EventArgs e)
- {
- OnPropertyChanged(((Property) sender).Name);
- }
-
- private void HookUpEvents()
- {
- foreach (Property property in _properties.Values)
- {
- property.ValueChanged -= PropertyValueChanged;
- property.ValueChanged += PropertyValueChanged;
-
- property.ReadOnlyChanged -= PropertyReadOnlyChanged;
- property.ReadOnlyChanged += PropertyReadOnlyChanged;
- }
- }
-
- public void CopyCompatibleValuesFrom(PropertyCollection srcProps)
- {
- CopyCompatibleValuesFrom(srcProps, false);
- }
-
- public void CopyCompatibleValuesFrom(PropertyCollection srcProps, bool ignoreReadOnlyFlags)
- {
- foreach (Property srcProp in srcProps)
- {
- Property dstProp = this[srcProp.Name];
-
- if (dstProp != null && dstProp.ValueType == srcProp.ValueType)
- {
- if (dstProp.ReadOnly && ignoreReadOnlyFlags)
- {
- dstProp.ReadOnly = false;
- dstProp.Value = srcProp.Value;
- dstProp.ReadOnly = true;
- }
- else
- {
- dstProp.Value = srcProp.Value;
- }
- }
- }
- }
-
- public static PropertyCollection CreateMerged(PropertyCollection pc1, PropertyCollection pc2)
- {
- if (pc1.Properties.Select(p1 => pc2[p1.Name]).Any(p2 => p2 != null))
- {
- throw new ArgumentException("pc1 must not have any properties with the same name as in pc2");
- }
-
- var allProps = new Property[pc1.Count + pc2.Count];
- int index = 0;
-
- foreach (Property p1 in pc1)
- {
- allProps[index] = p1.Clone();
- ++index;
- }
-
- foreach (Property p2 in pc2)
- {
- allProps[index] = p2.Clone();
- ++index;
- }
-
- var allRules = pc1.Rules.ToList();
- allRules.AddRange(pc2.Rules);
-
- var mergedPC = new PropertyCollection(allProps, allRules);
- return mergedPC;
- }
-
- public PropertyCollection Clone()
- {
- var clonedProperties = Properties.Select(property => property.Clone()).ToList();
-
- var clonedRules = _rules.Select(rule => rule.Clone()).ToList();
-
- return new PropertyCollection(clonedProperties, clonedRules);
- }
-
- object ICloneable.Clone()
- {
- return Clone();
- }
-
- public IEnumerator<Property> GetEnumerator()
- {
- return Properties.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
- }