PageRenderTime 63ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Base/PropertySystem/PropertyCollection.cs

https://bitbucket.org/tcz001/openpdn
C# | 280 lines | 225 code | 47 blank | 8 comment | 11 complexity | 9945cf130860284b3e6da8952a98eac1 MD5 | raw file
Possible License(s): Unlicense
  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.Runtime.Serialization;
  14. using System.Text;
  15. namespace PaintDotNet.PropertySystem
  16. {
  17. public sealed class PropertyCollection
  18. : INotifyPropertyChanged,
  19. IEnumerable<Property>,
  20. ICloneable<PropertyCollection>
  21. {
  22. private bool eventAddAllowed = true;
  23. private Dictionary<string, Property> properties = new Dictionary<string, Property>();
  24. private 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. this.properties.TryGetValue(propertyNameString, out theProperty);
  44. return theProperty;
  45. }
  46. }
  47. public int Count
  48. {
  49. get
  50. {
  51. return this.properties.Count;
  52. }
  53. }
  54. public IEnumerable<Property> Properties
  55. {
  56. get
  57. {
  58. return this.properties.Values;
  59. }
  60. }
  61. public IEnumerable<PropertyCollectionRule> Rules
  62. {
  63. get
  64. {
  65. return this.rules;
  66. }
  67. }
  68. public IEnumerable<string> PropertyNames
  69. {
  70. get
  71. {
  72. return this.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 __Internal_BeginEventAddMoratorium()
  86. {
  87. if (!this.eventAddAllowed)
  88. {
  89. throw new InvalidOperationException("An event add moratorium is already in effect");
  90. }
  91. List<IDisposable> propUndoFns = new List<IDisposable>(this.properties.Count);
  92. foreach (Property property in this.properties.Values)
  93. {
  94. IDisposable propUndoFn = property.BeginEventAddMoratorium();
  95. propUndoFns.Add(propUndoFn);
  96. }
  97. IDisposable undoFn = new CallbackOnDispose(() =>
  98. {
  99. this.eventAddAllowed = true;
  100. foreach (IDisposable propUndoFn in propUndoFns)
  101. {
  102. propUndoFn.Dispose();
  103. }
  104. });
  105. this.eventAddAllowed = false;
  106. return undoFn;
  107. }
  108. private void Initialize(
  109. IEnumerable<Property> properties,
  110. IEnumerable<PropertyCollectionRule> rules)
  111. {
  112. foreach (Property property in properties)
  113. {
  114. Property propertyClone = property.Clone();
  115. this.properties.Add(propertyClone.Name, propertyClone);
  116. }
  117. foreach (PropertyCollectionRule rule in rules)
  118. {
  119. PropertyCollectionRule ruleClone = rule.Clone();
  120. this.rules.Add(ruleClone);
  121. }
  122. foreach (PropertyCollectionRule rule in this.rules)
  123. {
  124. rule.Initialize(this);
  125. }
  126. HookUpEvents();
  127. }
  128. private void Property_ValueChanged(object sender, EventArgs e)
  129. {
  130. OnPropertyChanged((sender as Property).Name);
  131. }
  132. private void Property_ReadOnlyChanged(object sender, EventArgs e)
  133. {
  134. OnPropertyChanged((sender as Property).Name);
  135. }
  136. private void HookUpEvents()
  137. {
  138. foreach (Property property in this.properties.Values)
  139. {
  140. property.ValueChanged -= Property_ValueChanged;
  141. property.ValueChanged += Property_ValueChanged;
  142. property.ReadOnlyChanged -= Property_ReadOnlyChanged;
  143. property.ReadOnlyChanged += Property_ReadOnlyChanged;
  144. }
  145. }
  146. public void CopyCompatibleValuesFrom(PropertyCollection srcProps)
  147. {
  148. CopyCompatibleValuesFrom(srcProps, false);
  149. }
  150. public void CopyCompatibleValuesFrom(PropertyCollection srcProps, bool ignoreReadOnlyFlags)
  151. {
  152. foreach (Property srcProp in srcProps)
  153. {
  154. Property dstProp = this[srcProp.Name];
  155. if (dstProp != null && dstProp.ValueType == srcProp.ValueType)
  156. {
  157. if (dstProp.ReadOnly && ignoreReadOnlyFlags)
  158. {
  159. dstProp.ReadOnly = false;
  160. dstProp.Value = srcProp.Value;
  161. dstProp.ReadOnly = true;
  162. }
  163. else
  164. {
  165. dstProp.Value = srcProp.Value;
  166. }
  167. }
  168. }
  169. }
  170. public static PropertyCollection CreateMerged(PropertyCollection pc1, PropertyCollection pc2)
  171. {
  172. foreach (Property p1 in pc1.Properties)
  173. {
  174. Property p2 = pc2[p1.Name];
  175. if (p2 != null)
  176. {
  177. throw new ArgumentException("pc1 must not have any properties with the same name as in pc2");
  178. }
  179. }
  180. Property[] allProps = new Property[pc1.Count + pc2.Count];
  181. int index = 0;
  182. foreach (Property p1 in pc1)
  183. {
  184. allProps[index] = p1.Clone();
  185. ++index;
  186. }
  187. foreach (Property p2 in pc2)
  188. {
  189. allProps[index] = p2.Clone();
  190. ++index;
  191. }
  192. List<PropertyCollectionRule> allRules = new List<PropertyCollectionRule>();
  193. foreach (PropertyCollectionRule pcr1 in pc1.Rules)
  194. {
  195. allRules.Add(pcr1);
  196. }
  197. foreach (PropertyCollectionRule pcr2 in pc2.Rules)
  198. {
  199. allRules.Add(pcr2);
  200. }
  201. PropertyCollection mergedPC = new PropertyCollection(allProps, allRules);
  202. return mergedPC;
  203. }
  204. public PropertyCollection Clone()
  205. {
  206. List<Property> clonedProperties = new List<Property>();
  207. foreach (Property property in this.Properties)
  208. {
  209. Property clonedProperty = property.Clone();
  210. clonedProperties.Add(clonedProperty);
  211. }
  212. List<PropertyCollectionRule> clonedRules = new List<PropertyCollectionRule>();
  213. foreach (PropertyCollectionRule rule in this.rules)
  214. {
  215. PropertyCollectionRule clonedRule = rule.Clone();
  216. clonedRules.Add(clonedRule);
  217. }
  218. return new PropertyCollection(clonedProperties, clonedRules);
  219. }
  220. object ICloneable.Clone()
  221. {
  222. return Clone();
  223. }
  224. public IEnumerator<Property> GetEnumerator()
  225. {
  226. return Properties.GetEnumerator();
  227. }
  228. IEnumerator IEnumerable.GetEnumerator()
  229. {
  230. return GetEnumerator();
  231. }
  232. }
  233. }