PageRenderTime 51ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Base/PropertySystem/PropertyCollection.cs

https://bitbucket.org/tuldok89/openpdn
C# | 250 lines | 199 code | 42 blank | 9 comment | 11 complexity | 199bcc1d8c70b96f24d8903d805375eb MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) Rick Brewster, Tom Jackson, and past contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using System;
  10. using System.Collections;
  11. using System.Collections.Generic;
  12. using System.ComponentModel;
  13. using System.Linq;
  14. //using PaintDotNet.PropertySystem; Unused Directive
  15. namespace PaintDotNet.Base.PropertySystem
  16. {
  17. public sealed class PropertyCollection
  18. : INotifyPropertyChanged,
  19. IEnumerable<Property>,
  20. ICloneable<PropertyCollection>
  21. {
  22. private bool _eventAddAllowed = true;
  23. private readonly Dictionary<string, Property> _properties = new Dictionary<string, Property>();
  24. private readonly List<PropertyCollectionRule> _rules = new List<PropertyCollectionRule>();
  25. public static PropertyCollection CreateEmpty()
  26. {
  27. return new PropertyCollection(new Property[0]);
  28. }
  29. public event PropertyChangedEventHandler PropertyChanged;
  30. private void OnPropertyChanged(string propertyName)
  31. {
  32. if (PropertyChanged != null)
  33. {
  34. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  35. }
  36. }
  37. public Property this[object propertyName]
  38. {
  39. get
  40. {
  41. string propertyNameString = propertyName.ToString();
  42. Property theProperty;
  43. _properties.TryGetValue(propertyNameString, out theProperty);
  44. return theProperty;
  45. }
  46. }
  47. public int Count
  48. {
  49. get
  50. {
  51. return _properties.Count;
  52. }
  53. }
  54. public IEnumerable<Property> Properties
  55. {
  56. get
  57. {
  58. return _properties.Values;
  59. }
  60. }
  61. public IEnumerable<PropertyCollectionRule> Rules
  62. {
  63. get
  64. {
  65. return _rules;
  66. }
  67. }
  68. public IEnumerable<string> PropertyNames
  69. {
  70. get
  71. {
  72. return _properties.Keys;
  73. }
  74. }
  75. public PropertyCollection(IEnumerable<Property> properties)
  76. {
  77. Initialize(properties, new PropertyCollectionRule[0]);
  78. }
  79. public PropertyCollection(
  80. IEnumerable<Property> properties,
  81. IEnumerable<PropertyCollectionRule> rules)
  82. {
  83. Initialize(properties, rules);
  84. }
  85. public IDisposable InternalBeginEventAddMoratorium()
  86. {
  87. if (!_eventAddAllowed)
  88. {
  89. throw new InvalidOperationException("An event add moratorium is already in effect");
  90. }
  91. var propUndoFns = new List<IDisposable>(_properties.Count);
  92. propUndoFns.AddRange(_properties.Values.Select(property => property.BeginEventAddMoratorium()));
  93. IDisposable undoFn = new CallbackOnDispose(() =>
  94. {
  95. _eventAddAllowed = true;
  96. foreach (IDisposable propUndoFn in propUndoFns)
  97. {
  98. propUndoFn.Dispose();
  99. }
  100. });
  101. _eventAddAllowed = false;
  102. return undoFn;
  103. }
  104. private void Initialize(
  105. IEnumerable<Property> properties,
  106. IEnumerable<PropertyCollectionRule> rules)
  107. {
  108. foreach (Property property in properties)
  109. {
  110. Property propertyClone = property.Clone();
  111. _properties.Add(propertyClone.Name, propertyClone);
  112. }
  113. foreach (PropertyCollectionRule rule in rules)
  114. {
  115. PropertyCollectionRule ruleClone = rule.Clone();
  116. _rules.Add(ruleClone);
  117. }
  118. foreach (PropertyCollectionRule rule in _rules)
  119. {
  120. rule.Initialize(this);
  121. }
  122. HookUpEvents();
  123. }
  124. private void PropertyValueChanged(object sender, EventArgs e)
  125. {
  126. OnPropertyChanged(((Property) sender).Name);
  127. }
  128. private void PropertyReadOnlyChanged(object sender, EventArgs e)
  129. {
  130. OnPropertyChanged(((Property) sender).Name);
  131. }
  132. private void HookUpEvents()
  133. {
  134. foreach (Property property in _properties.Values)
  135. {
  136. property.ValueChanged -= PropertyValueChanged;
  137. property.ValueChanged += PropertyValueChanged;
  138. property.ReadOnlyChanged -= PropertyReadOnlyChanged;
  139. property.ReadOnlyChanged += PropertyReadOnlyChanged;
  140. }
  141. }
  142. public void CopyCompatibleValuesFrom(PropertyCollection srcProps)
  143. {
  144. CopyCompatibleValuesFrom(srcProps, false);
  145. }
  146. public void CopyCompatibleValuesFrom(PropertyCollection srcProps, bool ignoreReadOnlyFlags)
  147. {
  148. foreach (Property srcProp in srcProps)
  149. {
  150. Property dstProp = this[srcProp.Name];
  151. if (dstProp != null && dstProp.ValueType == srcProp.ValueType)
  152. {
  153. if (dstProp.ReadOnly && ignoreReadOnlyFlags)
  154. {
  155. dstProp.ReadOnly = false;
  156. dstProp.Value = srcProp.Value;
  157. dstProp.ReadOnly = true;
  158. }
  159. else
  160. {
  161. dstProp.Value = srcProp.Value;
  162. }
  163. }
  164. }
  165. }
  166. public static PropertyCollection CreateMerged(PropertyCollection pc1, PropertyCollection pc2)
  167. {
  168. if (pc1.Properties.Select(p1 => pc2[p1.Name]).Any(p2 => p2 != null))
  169. {
  170. throw new ArgumentException("pc1 must not have any properties with the same name as in pc2");
  171. }
  172. var allProps = new Property[pc1.Count + pc2.Count];
  173. int index = 0;
  174. foreach (Property p1 in pc1)
  175. {
  176. allProps[index] = p1.Clone();
  177. ++index;
  178. }
  179. foreach (Property p2 in pc2)
  180. {
  181. allProps[index] = p2.Clone();
  182. ++index;
  183. }
  184. var allRules = pc1.Rules.ToList();
  185. allRules.AddRange(pc2.Rules);
  186. var mergedPC = new PropertyCollection(allProps, allRules);
  187. return mergedPC;
  188. }
  189. public PropertyCollection Clone()
  190. {
  191. var clonedProperties = Properties.Select(property => property.Clone()).ToList();
  192. var clonedRules = _rules.Select(rule => rule.Clone()).ToList();
  193. return new PropertyCollection(clonedProperties, clonedRules);
  194. }
  195. object ICloneable.Clone()
  196. {
  197. return Clone();
  198. }
  199. public IEnumerator<Property> GetEnumerator()
  200. {
  201. return Properties.GetEnumerator();
  202. }
  203. IEnumerator IEnumerable.GetEnumerator()
  204. {
  205. return GetEnumerator();
  206. }
  207. }
  208. }