PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Data/LayerList.cs

https://bitbucket.org/tuldok89/openpdn
C# | 284 lines | 186 code | 37 blank | 61 comment | 18 complexity | 72733eee670f8ccca3d06eb2a9471b4f MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and 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. namespace PaintDotNet
  12. {
  13. // TODO: reimplement to not use ArrayList, although we'll need to keep this class around
  14. // for compatibility with .PDN's saved with older versions
  15. /// <summary>
  16. /// Basically an ArrayList, but lets the containing Document instance be
  17. /// notified when the list is modified so it can know that it needs to
  18. /// re-render itself.
  19. /// This implementation also enforces that any contained layer must be
  20. /// of the same dimensions as the document it is contained within.
  21. /// If you try to add a layer that is the wrong size, an exception will
  22. /// be thrown.
  23. /// </summary>
  24. [Serializable]
  25. public sealed class LayerList
  26. : ArrayList
  27. {
  28. private readonly Document _parent;
  29. /// <summary>
  30. /// Defines a generic "the collection is changing" event
  31. /// This is always followed with a more specific event (RemovedAt, for instance).
  32. /// </summary>
  33. [field: NonSerialized]
  34. public event EventHandler Changing;
  35. /// <summary>
  36. /// Defines a generic "the collection's contents have changed" event
  37. /// This is always preceded by a more specific event.
  38. /// </summary>
  39. [field: NonSerialized]
  40. public event EventHandler Changed;
  41. /// <summary>
  42. /// This event is raised after the collection has been cleared out;
  43. /// thus, when you handle this event the collection is empty.
  44. /// </summary>
  45. [field: NonSerialized]
  46. public EventHandler Cleared;
  47. /// <summary>
  48. /// This event is raised when a new element is inserted into the collection.
  49. /// The new element is at the array index specified by the Index property
  50. /// of the IndexEventArgs.
  51. /// </summary>
  52. [field: NonSerialized]
  53. public event IndexEventHandler Inserted;
  54. /// <summary>
  55. /// This event is raised before an element is removed from the collection.
  56. /// The index specified by the Index property of the IndexEventArgs is where
  57. /// the element currently is.
  58. /// </summary>
  59. [field: NonSerialized]
  60. public event IndexEventHandler RemovingAt;
  61. /// <summary>
  62. /// This event is raised when an element is removed from the collection.
  63. /// The index specified by the Index property of the IndexEventArgs is where
  64. /// the element used to be.
  65. /// </summary>
  66. [field: NonSerialized]
  67. public event IndexEventHandler RemovedAt;
  68. private void OnRemovingAt(int index)
  69. {
  70. if (RemovingAt != null)
  71. {
  72. RemovingAt(this, new IndexEventArgs(index));
  73. }
  74. }
  75. private void OnRemovedAt(int index)
  76. {
  77. if (RemovedAt != null)
  78. {
  79. RemovedAt(this, new IndexEventArgs(index));
  80. }
  81. }
  82. private void OnInserted(int index)
  83. {
  84. if (Inserted != null)
  85. {
  86. Inserted(this, new IndexEventArgs(index));
  87. }
  88. }
  89. private void OnCleared()
  90. {
  91. if (Cleared != null)
  92. {
  93. Cleared(this, EventArgs.Empty);
  94. }
  95. }
  96. private void OnChanging()
  97. {
  98. if (Changing != null)
  99. {
  100. Changing(this, EventArgs.Empty);
  101. }
  102. }
  103. private void OnChanged()
  104. {
  105. if (Changed != null)
  106. {
  107. Changed(this, EventArgs.Empty);
  108. }
  109. }
  110. public LayerList(Document parent)
  111. {
  112. _parent = parent;
  113. }
  114. private void CheckLayerSize(object value)
  115. {
  116. var layer = (Layer)value;
  117. if (layer.Width != _parent.Width || layer.Height != _parent.Height)
  118. {
  119. throw new ArgumentException("Size of layer does not match size of containing document");
  120. }
  121. }
  122. public override int Add(object value)
  123. {
  124. if (!(value is BitmapLayer))
  125. {
  126. throw new ArgumentException("can only add bitmap layers");
  127. }
  128. OnChanging();
  129. CheckLayerSize(value);
  130. _parent.Invalidate(); // TODO: is this necessary? shouldn't Document just hook in to the Inserted event?
  131. int index = base.Add(value);
  132. OnInserted(index);
  133. OnChanged();
  134. return index;
  135. }
  136. public override void AddRange(ICollection c)
  137. {
  138. // Implemented using Add(), and thus we don't raise our own events
  139. foreach (object o in c)
  140. {
  141. Add(o);
  142. }
  143. }
  144. public override void Clear()
  145. {
  146. OnChanging();
  147. base.Clear();
  148. OnCleared();
  149. OnChanged();
  150. }
  151. public override void Insert(int index, object value)
  152. {
  153. OnChanging();
  154. CheckLayerSize(value);
  155. _parent.Invalidate(); // TODO: is this necessary? shouldn't Document just hook in to the Inserted event?
  156. base.Insert(index, value);
  157. OnInserted(index);
  158. OnChanged();
  159. }
  160. public override void InsertRange(int index, ICollection c)
  161. {
  162. // implemented using Insert, thus we don't raise our own events
  163. foreach (object o in c)
  164. {
  165. Insert(index, o);
  166. }
  167. }
  168. /*
  169. // Undocumented behavior of ArrayList: ArrayList.Remove actually uses ArrayList.RemoveAt!
  170. public override void Remove(object obj)
  171. {
  172. //OnChanging();
  173. int index = IndexOf(obj);
  174. RemoveAt(index);
  175. //base.Remove (obj);
  176. //OnRemovedAt(index);
  177. //OnChanged();
  178. }
  179. */
  180. public override void RemoveAt(int index)
  181. {
  182. OnChanging();
  183. OnRemovingAt(index);
  184. base.RemoveAt(index);
  185. OnRemovedAt(index);
  186. OnChanged();
  187. }
  188. public override void RemoveRange(int index, int count)
  189. {
  190. // Implemented by calling RemoveAt, thus we don't raise our own events
  191. while (count > 0)
  192. {
  193. RemoveAt(index);
  194. }
  195. }
  196. public override void Reverse()
  197. {
  198. throw new NotSupportedException();
  199. }
  200. public override void Reverse(int index, int count)
  201. {
  202. throw new NotSupportedException();
  203. }
  204. public override void SetRange(int index, ICollection c)
  205. {
  206. throw new NotSupportedException();
  207. }
  208. public override void Sort()
  209. {
  210. throw new NotSupportedException();
  211. }
  212. public override void Sort(int index, int count, IComparer comparer)
  213. {
  214. throw new NotSupportedException();
  215. }
  216. public override void Sort(IComparer comparer)
  217. {
  218. throw new NotSupportedException();
  219. }
  220. public override void TrimToSize()
  221. {
  222. throw new NotSupportedException();
  223. }
  224. public Layer GetAt(int index)
  225. {
  226. return (Layer)this[index];
  227. }
  228. public void SetAt(int index, Layer newValue)
  229. {
  230. this[index] = newValue;
  231. }
  232. public override object this[int index]
  233. {
  234. get
  235. {
  236. return base[index];
  237. }
  238. set
  239. {
  240. OnChanging();
  241. RemoveAt(index);
  242. Insert(index, value);
  243. OnChanged();
  244. }
  245. }
  246. }
  247. }