1 module nodes.node_chain;
2 
3 import fluid;
4 
5 @safe:
6 
7 alias chainLink = nodeBuilder!ChainLink;
8 
9 class ChainLink : NodeChain {
10 
11     DebugSignalIO debugSignalIO;
12 
13     int drawChildCalls;
14     int beforeResizeCalls;
15     int afterResizeCalls;
16     int beforeDrawCalls;
17     int afterDrawCalls;
18 
19     this(Node next = null) {
20         super(next);
21     }
22 
23     override void drawChild(Node child, Rectangle space) {
24         drawChildCalls++;
25         super.drawChild(child, space);
26     }
27 
28     override void beforeResize(Vector2) {
29         require(debugSignalIO);
30         debugSignalIO.emitSignal("beforeResize");
31         beforeResizeCalls++;
32         assert(beforeResizeCalls == afterResizeCalls + 1);
33     }
34 
35     override void afterResize(Vector2) {
36         debugSignalIO.emitSignal("afterResize");
37         afterResizeCalls++;
38         assert(beforeResizeCalls == afterResizeCalls);
39     }
40 
41     override void beforeDraw(Rectangle, Rectangle) {
42         debugSignalIO.emitSignal("beforeDraw");
43         beforeDrawCalls++;
44         assert(beforeDrawCalls == afterDrawCalls + 1);
45     }
46 
47     override void afterDraw(Rectangle, Rectangle) {
48         debugSignalIO.emitSignal("afterDraw");
49         afterDrawCalls++;
50         assert(beforeDrawCalls == afterDrawCalls);
51     }
52 
53 }
54 
55 @("NodeChain can be empty")
56 unittest {
57 
58     auto link = chainLink();
59     auto root = testSpace(link);
60     root.drawAndAssert(
61         link.emits("beforeResize"),
62         link.emits("afterResize"),
63         link.emits("beforeDraw"),
64         link.emits("afterDraw"),
65         link.doesNotDraw,
66     );
67     assert(link.afterResizeCalls == 1);
68     assert(link.afterDrawCalls == 1);
69 
70 }
71 
72 @("Node chain can contain other nodes")
73 unittest {
74 
75     auto content = label("Child");
76     auto link = chainLink(content);
77     auto root = testSpace(link);
78     root.drawAndAssert(
79         link.drawsChild(content),
80         content.drawsImage(),
81     );
82     assert(link.afterResizeCalls == 1);
83     assert(link.afterDrawCalls == 1);
84 
85 }
86 
87 @("Chain nodes can be linked")
88 unittest {
89 
90     Label content;
91     ChainLink link1, link2, link3;
92 
93     auto link = chainLink(.layout!0,
94         link1 = chainLink(.layout!1,
95             link2 = chainLink(.layout!2,
96                 link3 = chainLink(.layout!3,
97                     content = label("hi"),
98                 ),
99             ),
100         ),
101     );
102     auto root = testSpace(link);
103 
104     // Root link draws all the links, but it is not exposed through tree actions
105     root.drawAndAssert(
106 
107         // Resize
108         link1.emits("beforeResize"),
109         link2.emits("beforeResize"),
110         link3.emits("beforeResize"),
111         link3.emits("afterResize"),
112         link2.emits("afterResize"),
113         link1.emits("afterResize"),
114 
115         // Draw
116         link.emits("beforeDraw"),
117         link.drawsChild(link1),
118         link1.emits("beforeDraw"),
119         link1.drawsChild(link2),
120         link2.emits("beforeDraw"),
121         link2.drawsChild(link3),
122         link3.emits("beforeDraw"),
123         link3.drawsChild(content),
124         link3.emits("afterDraw"),
125         link2.emits("afterDraw"),
126         link1.emits("afterDraw"),
127     );
128     assert(link3.afterResizeCalls == 1);
129     assert(link.afterDrawCalls  == 1);
130     assert(link1.afterDrawCalls == 1);
131     assert(link2.afterDrawCalls == 1);
132     assert(link3.afterDrawCalls == 1);
133     assert(link.drawChildCalls  == 1);
134     assert(link1.drawChildCalls == 0);
135     assert(link2.drawChildCalls == 0);
136     assert(link3.drawChildCalls == 0);
137 
138 }
139 
140 @("chain() can be used as a prettier alternative to the constructor")
141 unittest {
142 
143     Label content;
144     ChainLink link1, link2, link3;
145 
146     NodeChain link = chain(
147         link1 = chainLink(),
148         link2 = chainLink(),
149         link3 = chainLink(),
150         content = label("hi"),
151     );
152     auto root = testSpace(link);
153 
154     assert(link.opEquals(link1));
155 
156     root.drawAndAssert(
157         link1.drawsChild(link2),
158         link2.drawsChild(link3),
159         link3.drawsChild(content),
160     );
161 
162 }
163 
164 @("chain() returns a node if not given a chain")
165 unittest {
166 
167     Node node = chain(
168         label("Foo")
169     );
170     assert(node);
171 
172 }