1 module auxil.test2;
2 
3 version(unittest)
4 import unit_threaded : should, be, Name;
5 import taggedalgebraic : TaggedAlgebraic;
6 
7 import auxil.model;
8 import auxil.test;
9 
10 struct Test
11 {
12 	ushort us;
13 	long l;
14 }
15 
16 struct Test2
17 {
18 	size_t st;
19 	string s;
20 	Test t;
21 	float[] fa;
22 }
23 
24 union Payload
25 {
26 	int i;
27 	float f;
28 	double d;
29 	string str;
30 	Test t;
31 	Test2 t2;
32 }
33 
34 alias Data = TaggedAlgebraic!Payload;
35 
36 Data[] data;
37 RelativeMeasurer v;
38 typeof(makeModel(data)) model;
39 
40 void setup()
41 {
42 	data = [
43 		Data(1),
44 		Data(2.0),
45 		Data(3.0f),
46 		Data(Test(100, -1001)),
47 		Data(Test2(1_000_000, "test2", Test(200, -11), [11, 12, 123])),
48 		Data("text"),
49 	];
50 
51 	v = RelativeMeasurer();
52 	model = makeModel(data);
53 	model.collapsed = false;
54 	setPropertyByTreePath!"collapsed"(data, model, [3], false);
55 	setPropertyByTreePath!"collapsed"(data, model, [4], false);
56 	setPropertyByTreePath!"collapsed"(data, model, [4, 2], false);
57 	setPropertyByTreePath!"collapsed"(data, model, [4, 3], false);
58 
59 	// measure size
60 	{
61 		auto mv = MeasuringVisitor(9);
62 		model.visitForward(data, mv);
63 	}
64 }
65 
66 version(unittest)
67 @Name("Test1")
68 unittest
69 {
70 	setup;
71 
72 	v.position = 0;
73 	v.destination = v.destination.max;
74 	model.visitForward(data, v);
75 	model.size.should.be == 180;
76 	v.output.should.be == [
77 		TreePosition([ ],         0),
78 		TreePosition([0],        10),
79 		TreePosition([1],        20),
80 		TreePosition([2],        30),
81 		TreePosition([3],        40),
82 		TreePosition([3, 0],     50),
83 		TreePosition([3, 1],     60),
84 		TreePosition([4],        70),
85 		TreePosition([4, 0],     80),
86 		TreePosition([4, 1],     90),
87 		TreePosition([4, 2],    100),
88 		TreePosition([4, 2, 0], 110),
89 		TreePosition([4, 2, 1], 120),
90 		TreePosition([4, 3],    130),
91 		TreePosition([4, 3, 0], 140),
92 		TreePosition([4, 3, 1], 150),
93 		TreePosition([4, 3, 2], 160),
94 		TreePosition([5],       170),
95 	];
96 	v.position.should.be == 170;
97 
98 	v.position = 0;
99 	v.path.value = [4,2,1];
100 	model.visitForward(data, v);
101 	v.output.should.be == [
102 		TreePosition([4, 2, 1],  0),
103 		TreePosition([4, 3],    10),
104 		TreePosition([4, 3, 0], 20),
105 		TreePosition([4, 3, 1], 30),
106 		TreePosition([4, 3, 2], 40),
107 		TreePosition([5],       50)
108 	];
109 }
110 
111 version(unittest)
112 @Name("Test2")
113 unittest
114 {
115 	setup;
116 
117 	// default
118 	{
119 		v.path.clear;
120 		v.position = 0;
121 		v.destination = v.destination.max;
122 		model.visitForward(data, v);
123 
124 		v.position.should.be == 170;
125 		v.path.value[].should.be == (int[]).init;
126 	}
127 
128 	// next position is between two elements
129 	{
130 		v.path.clear;
131 		v.position = 0;
132 		v.destination = 15;
133 		model.visitForward(data, v);
134 
135 		v.position.should.be == 10;
136 		v.destination.should.be == 15;
137 		v.path.value[].should.be == [0];
138 	}
139 
140 	// next position is equal to start of an element
141 	{
142 		v.path.clear;
143 		v.position = 0;
144 		v.destination = 30;
145 		model.visitForward(data, v);
146 
147 		v.position.should.be == 30;
148 		v.destination.should.be == 30;
149 		v.path.value[].should.be == [2];
150 	}
151 
152 	// start path is not null
153 	{
154 		v.path.value = [3, 0];
155 		v.position = 0;
156 		v.destination = 55;
157 		model.visitForward(data, v);
158 
159 		v.position.should.be == 50;
160 		v.destination.should.be == 55;
161 		v.path.value[].should.be == [4, 2];
162 	}
163 
164 	// reverse order, start path is not null
165 	{
166 		v.path.value = [4, 1];
167 		v.position = 90;
168 		v.destination = 41;
169 
170 		model.visitBackward(data, v);
171 
172 		v.position.should.be == 40;
173 		v.destination.should.be == 41;
174 		v.path.value[].should.be == [3];
175 
176 		// bubble to the next element
177 		v.destination = 19;
178 
179 		model.visitBackward(data, v);
180 
181 		v.path.value[].should.be == [0];
182 		v.position.should.be == 10;
183 		v.destination.should.be == 19;
184 		v.output.should.be == [
185 			TreePosition([3], 40),
186 			TreePosition([2], 30),
187 			TreePosition([1], 20),
188 			TreePosition([0], 10),
189 		];
190 	}
191 }
192 
193 version(unittest)
194 @Name("ScrollingTest")
195 unittest
196 {
197 	setup;
198 
199 	v.path.clear;
200 	v.position = 0;
201 
202 	// the element height is 10 px
203 
204 	// scroll 7 px forward
205 	visit(model, data, v, 7);
206 	// current element is the root one
207 	v.path.value[].should.be == (int[]).init;
208 	// position of the current element is 0 px
209 	v.position.should.be == 0;
210 	// the window starts from 7th px
211 	v.destination.should.be == 7;
212 
213 	// scroll the next 7th px forward
214 	visit(model, data, v, 14);
215 	// the current element is the first child element
216 	v.path.value[].should.be == [0];
217 	// position of the current element is 10 px
218 	v.position.should.be == 10;
219 	// the window starts from 14th px
220 	v.destination.should.be == 14;
221 
222 	// scroll the next 7th px forward
223 	visit(model, data, v, 21);
224 	// the current element is the second child element
225 	v.path.value[].should.be == [1];
226 	// position of the current element is 20 px
227 	v.position.should.be == 20;
228 	// the window starts from 21th px
229 	v.destination.should.be == 21;
230 
231 	// scroll the next 7th px forward
232 	visit(model, data, v, 28);
233 	// the current element is the second child element
234 	v.path.value[].should.be == [1];
235 	// position of the current element is 20 px
236 	v.position.should.be == 20;
237 	// the window starts from 28th px
238 	v.destination.should.be == 28;
239 
240 	// scroll the next 7th px forward
241 	visit(model, data, v, 35);
242 	// the current element is the third child element
243 	v.path.value[].should.be == [2];
244 	// position of the current element is 30 px
245 	v.position.should.be == 30;
246 	// the window starts from 35th px
247 	v.destination.should.be == 35;
248 
249 	// scroll 7th px backward
250 	visit(model, data, v, 27);
251 	// the current element is the second child element
252 	v.path.value[].should.be == [1];
253 	// position of the current element is 20 px
254 	v.position.should.be == 20;
255 	// the window starts from 27th px
256 	v.destination.should.be == 27;
257 
258 	// scroll the next 9th px backward
259 	visit(model, data, v, 18);
260 	// the current element is the first child element
261 	v.path.value[].should.be == [0];
262 	// position of the current element is 10 px
263 	v.position.should.be == 10;
264 	// the window starts from 18th px
265 	v.destination.should.be == 18;
266 
267 	// scroll the next 6th px backward
268 	visit(model, data, v, 12);
269 	// the current element is the first child element
270 	v.path.value[].should.be == [0];
271 	// position of the current element is 10 px
272 	v.position.should.be == 10;
273 	// the window starts from 12th px
274 	v.destination.should.be == 12;
275 
276 	// scroll the next 5th px backward
277 	visit(model, data, v, 7);
278 	// the current element is the root element
279 	v.path.value[].should.be == (int[]).init;
280 	// position of the current element is 0 px
281 	v.position.should.be == 0;
282 	// the window starts from 7th px
283 	v.destination.should.be == 7;
284 
285 	// scroll 76 px forward
286 	visit(model, data, v, 83);
287 	// // the current element is the second child element
288 	// v.path.value[].should.be == [4, 0];
289 	// // position of the current element is 20 px
290 	// v.position.should.be == 80;
291 	// the window starts from 27th px
292 	v.destination.should.be == 83;
293 
294 	visit(model, data, v, 81);
295 	v.path.value[].should.be == [4, 0];
296 	v.position.should.be == 80;
297 	v.destination.should.be == 81;
298 
299 	visit(model, data, v, 80);
300 	v.path.value[].should.be == [4, 0];
301 	v.position.should.be == 80;
302 	v.destination.should.be == 80;
303 
304 	visit(model, data, v, 79);
305 	v.path.value[].should.be == [4];
306 	v.position.should.be == 70;
307 	v.destination.should.be == 79;
308 
309 	visit(model, data, v, 133);
310 	v.path.value[].should.be == [4, 3];
311 	v.position.should.be == 130;
312 	v.destination.should.be == 133;
313 
314 	visit(model, data, v, 0);
315 	v.path.value[].should.be == (int[]).init;
316 	v.position.should.be == 0;
317 	v.destination.should.be == 0;
318 }