-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCompositeElement.cs
94 lines (71 loc) · 2.41 KB
/
CompositeElement.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using OfficeFlow.DocumentObjectModel.Exceptions;
namespace OfficeFlow.DocumentObjectModel;
public abstract class CompositeElement : Element, IEnumerable<Element>
{
private readonly ElementCollection _children;
public int Count
=> _children.Count;
public Element? FirstChild
=> _children.Head;
public Element? LastChild
=> _children.Tail;
protected CompositeElement()
=> _children = new ElementCollection(this);
public void AppendChild(Element element)
=> _children.Append(element);
public void InsertAfter(Element target, Element element)
=> _children.Insert(
GetIndexOrThrow(target) + 1,
element);
public void InsertBefore(Element target, Element element)
=> _children.Insert(
GetIndexOrThrow(target),
element);
public void PrependChild(Element element)
=> _children.Prepend(element);
public IEnumerable<Element> GetDescendants()
=> GetDescendants<Element>();
public IEnumerable<TElement> GetDescendants<TElement>()
where TElement : Element
{
var descedants = new Stack<Element?>(_children);
while (descedants.Count != 0)
{
var nextDescedant = descedants.Pop();
if (nextDescedant is TElement element)
{
yield return element;
}
if (nextDescedant is not CompositeElement composite)
{
continue;
}
foreach (var child in composite)
{
descedants.Push(child);
}
}
}
public void RemoveChild(Element element)
=> _children.Remove(element);
public void RemoveChildren()
=> _children.Clear();
public IEnumerator<Element> GetEnumerator()
=> _children.GetEnumerator();
[ExcludeFromCodeCoverage]
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
private int GetIndexOrThrow(Element element)
{
var index = _children.IndexOf(element);
if (index is -1)
{
throw new ElementNotFoundException(
$"The specified element \"{element.GetType().Name}\" is not part of the current composite element \"{GetType().Name}\"");
}
return index;
}
}