wait a little to flush disk before quitting
[view.love.git] / drawing_tests.lua
blob91c4825a1a64b4d43a5df990a8cfdc66c60db4fc
1 -- major tests for drawings
2 -- We minimize assumptions about specific pixels, and try to test at the level
3 -- of specific shapes. In particular, no tests of freehand drawings.
5 function test_creating_drawing_saves()
6 App.screen.init{width=120, height=60}
7 Editor_state = edit.initialize_test_state()
8 Editor_state.filename = 'foo'
9 Editor_state.lines = load_array{}
10 Text.redraw_all(Editor_state)
11 edit.draw(Editor_state)
12 -- click on button to create drawing
13 edit.run_after_mouse_click(Editor_state, 8,Editor_state.top+8, 1)
14 -- file not immediately saved
15 edit.update(Editor_state, 0.01)
16 check_nil(App.filesystem['foo'], 'early')
17 -- wait until save
18 Current_time = Current_time + 3.1
19 edit.update(Editor_state, 0)
20 -- filesystem contains drawing and an empty line of text
21 check_eq(App.filesystem['foo'], '```lines\n```\n\n', 'check')
22 end
24 function test_draw_line()
25 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
26 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
27 Editor_state = edit.initialize_test_state()
28 Editor_state.filename = 'foo'
29 Editor_state.lines = load_array{'```lines', '```', ''}
30 Text.redraw_all(Editor_state)
31 Editor_state.current_drawing_mode = 'line'
32 edit.draw(Editor_state)
33 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
34 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
35 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
36 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
37 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
38 -- draw a line
39 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
40 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
41 local drawing = Editor_state.lines[1]
42 check_eq(#drawing.shapes, 1, '#shapes')
43 check_eq(#drawing.points, 2, '#points')
44 check_eq(drawing.shapes[1].mode, 'line', 'shape:1')
45 local p1 = drawing.points[drawing.shapes[1].p1]
46 local p2 = drawing.points[drawing.shapes[1].p2]
47 check_eq(p1.x, 5, 'p1:x')
48 check_eq(p1.y, 6, 'p1:y')
49 check_eq(p2.x, 35, 'p2:x')
50 check_eq(p2.y, 36, 'p2:y')
51 -- wait until save
52 Current_time = Current_time + 3.1
53 edit.update(Editor_state, 0)
54 -- The format on disk isn't perfectly stable. Table fields can be reordered.
55 -- So just reload from disk to verify.
56 load_from_disk(Editor_state)
57 Text.redraw_all(Editor_state)
58 local drawing = Editor_state.lines[1]
59 check_eq(#drawing.shapes, 1, 'save/#shapes')
60 check_eq(#drawing.points, 2, 'save/#points')
61 check_eq(drawing.shapes[1].mode, 'line', 'save/shape:1')
62 local p1 = drawing.points[drawing.shapes[1].p1]
63 local p2 = drawing.points[drawing.shapes[1].p2]
64 check_eq(p1.x, 5, 'save/p1:x')
65 check_eq(p1.y, 6, 'save/p1:y')
66 check_eq(p2.x, 35, 'save/p2:x')
67 check_eq(p2.y, 36, 'save/p2:y')
68 end
70 function test_draw_horizontal_line()
71 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
72 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
73 Editor_state = edit.initialize_test_state()
74 Editor_state.lines = load_array{'```lines', '```', ''}
75 Text.redraw_all(Editor_state)
76 Editor_state.current_drawing_mode = 'manhattan'
77 edit.draw(Editor_state)
78 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
79 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
80 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
81 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
82 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
83 -- draw a line that is more horizontal than vertical
84 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
85 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+26, 1)
86 local drawing = Editor_state.lines[1]
87 check_eq(#drawing.shapes, 1, '#shapes')
88 check_eq(#drawing.points, 2, '#points')
89 check_eq(drawing.shapes[1].mode, 'manhattan', 'shape_mode')
90 local p1 = drawing.points[drawing.shapes[1].p1]
91 local p2 = drawing.points[drawing.shapes[1].p2]
92 check_eq(p1.x, 5, 'p1:x')
93 check_eq(p1.y, 6, 'p1:y')
94 check_eq(p2.x, 35, 'p2:x')
95 check_eq(p2.y, p1.y, 'p2:y')
96 end
98 function test_draw_circle()
99 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
100 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
101 Editor_state = edit.initialize_test_state()
102 Editor_state.lines = load_array{'```lines', '```', ''}
103 Text.redraw_all(Editor_state)
104 Editor_state.current_drawing_mode = 'line'
105 edit.draw(Editor_state)
106 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
107 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
108 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
109 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
110 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
111 -- draw a circle
112 App.mouse_move(Editor_state.left+4, Editor_state.top+Drawing_padding_top+4) -- hover on drawing
113 edit.run_after_keychord(Editor_state, 'C-o')
114 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
115 edit.run_after_mouse_release(Editor_state, Editor_state.left+35+30, Editor_state.top+Drawing_padding_top+36, 1)
116 local drawing = Editor_state.lines[1]
117 check_eq(#drawing.shapes, 1, '#shapes')
118 check_eq(#drawing.points, 1, '#points')
119 check_eq(drawing.shapes[1].mode, 'circle', 'shape_mode')
120 check_eq(drawing.shapes[1].radius, 30, 'radius')
121 local center = drawing.points[drawing.shapes[1].center]
122 check_eq(center.x, 35, 'center:x')
123 check_eq(center.y, 36, 'center:y')
126 function test_cancel_stroke()
127 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
128 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
129 Editor_state = edit.initialize_test_state()
130 Editor_state.filename = 'foo'
131 Editor_state.lines = load_array{'```lines', '```', ''}
132 Text.redraw_all(Editor_state)
133 Editor_state.current_drawing_mode = 'line'
134 edit.draw(Editor_state)
135 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
136 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
137 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
138 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
139 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
140 -- start drawing a line
141 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
142 -- cancel
143 edit.run_after_keychord(Editor_state, 'escape')
144 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
145 local drawing = Editor_state.lines[1]
146 check_eq(#drawing.shapes, 0, '#shapes')
149 function test_keys_do_not_affect_shape_when_mouse_up()
150 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
151 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
152 Editor_state = edit.initialize_test_state()
153 Editor_state.lines = load_array{'```lines', '```', ''}
154 Text.redraw_all(Editor_state)
155 Editor_state.current_drawing_mode = 'line'
156 edit.draw(Editor_state)
157 -- hover over drawing and press 'o' without holding mouse
158 App.mouse_move(Editor_state.left+4, Editor_state.top+Drawing_padding_top+4) -- hover on drawing
159 edit.run_after_keychord(Editor_state, 'o')
160 -- no change to drawing mode
161 check_eq(Editor_state.current_drawing_mode, 'line', 'drawing_mode')
162 -- no change to text either because we didn't run the text_input event
165 function test_draw_circle_mid_stroke()
166 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
167 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
168 Editor_state = edit.initialize_test_state()
169 Editor_state.lines = load_array{'```lines', '```', ''}
170 Text.redraw_all(Editor_state)
171 Editor_state.current_drawing_mode = 'line'
172 edit.draw(Editor_state)
173 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
174 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
175 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
176 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
177 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
178 -- draw a circle
179 App.mouse_move(Editor_state.left+4, Editor_state.top+Drawing_padding_top+4) -- hover on drawing
180 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
181 edit.run_after_text_input(Editor_state, 'o')
182 edit.run_after_mouse_release(Editor_state, Editor_state.left+35+30, Editor_state.top+Drawing_padding_top+36, 1)
183 local drawing = Editor_state.lines[1]
184 check_eq(#drawing.shapes, 1, '#shapes')
185 check_eq(#drawing.points, 1, '#points')
186 check_eq(drawing.shapes[1].mode, 'circle', 'shape_mode')
187 check_eq(drawing.shapes[1].radius, 30, 'radius')
188 local center = drawing.points[drawing.shapes[1].center]
189 check_eq(center.x, 35, 'center:x')
190 check_eq(center.y, 36, 'center:y')
193 function test_draw_arc()
194 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
195 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
196 Editor_state = edit.initialize_test_state()
197 Editor_state.lines = load_array{'```lines', '```', ''}
198 Text.redraw_all(Editor_state)
199 Editor_state.current_drawing_mode = 'circle'
200 edit.draw(Editor_state)
201 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
202 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
203 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
204 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
205 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
206 -- draw an arc
207 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
208 App.mouse_move(Editor_state.left+35+30, Editor_state.top+Drawing_padding_top+36)
209 edit.run_after_text_input(Editor_state, 'a') -- arc mode
210 edit.run_after_mouse_release(Editor_state, Editor_state.left+35+50, Editor_state.top+Drawing_padding_top+36+50, 1) -- 45°
211 local drawing = Editor_state.lines[1]
212 check_eq(#drawing.shapes, 1, '#shapes')
213 check_eq(#drawing.points, 1, '#points')
214 check_eq(drawing.shapes[1].mode, 'arc', 'shape_mode')
215 local arc = drawing.shapes[1]
216 check_eq(arc.radius, 30, 'radius')
217 local center = drawing.points[arc.center]
218 check_eq(center.x, 35, 'center:x')
219 check_eq(center.y, 36, 'center:y')
220 check_eq(arc.start_angle, 0, 'start:angle')
221 check_eq(arc.end_angle, math.pi/4, 'end:angle')
224 function test_draw_polygon()
225 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
226 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
227 Editor_state = edit.initialize_test_state()
228 Editor_state.lines = load_array{'```lines', '```', ''}
229 Text.redraw_all(Editor_state)
230 edit.draw(Editor_state)
231 check_eq(Editor_state.current_drawing_mode, 'line', 'baseline/drawing_mode')
232 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
233 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
234 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
235 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
236 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
237 -- first point
238 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
239 edit.run_after_text_input(Editor_state, 'g') -- polygon mode
240 -- second point
241 App.mouse_move(Editor_state.left+65, Editor_state.top+Drawing_padding_top+36)
242 edit.run_after_text_input(Editor_state, 'p') -- add point
243 -- final point
244 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+26, 1)
245 local drawing = Editor_state.lines[1]
246 check_eq(#drawing.shapes, 1, '#shapes')
247 check_eq(#drawing.points, 3, 'vertices')
248 local shape = drawing.shapes[1]
249 check_eq(shape.mode, 'polygon', 'shape_mode')
250 check_eq(#shape.vertices, 3, 'vertices')
251 local p = drawing.points[shape.vertices[1]]
252 check_eq(p.x, 5, 'p1:x')
253 check_eq(p.y, 6, 'p1:y')
254 local p = drawing.points[shape.vertices[2]]
255 check_eq(p.x, 65, 'p2:x')
256 check_eq(p.y, 36, 'p2:y')
257 local p = drawing.points[shape.vertices[3]]
258 check_eq(p.x, 35, 'p3:x')
259 check_eq(p.y, 26, 'p3:y')
262 function test_draw_rectangle()
263 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
264 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
265 Editor_state = edit.initialize_test_state()
266 Editor_state.lines = load_array{'```lines', '```', ''}
267 Text.redraw_all(Editor_state)
268 edit.draw(Editor_state)
269 check_eq(Editor_state.current_drawing_mode, 'line', 'baseline/drawing_mode')
270 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
271 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
272 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
273 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
274 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
275 -- first point
276 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
277 edit.run_after_text_input(Editor_state, 'r') -- rectangle mode
278 -- second point/first edge
279 App.mouse_move(Editor_state.left+42, Editor_state.top+Drawing_padding_top+45)
280 edit.run_after_text_input(Editor_state, 'p')
281 -- override second point/first edge
282 App.mouse_move(Editor_state.left+75, Editor_state.top+Drawing_padding_top+76)
283 edit.run_after_text_input(Editor_state, 'p')
284 -- release (decides 'thickness' of rectangle perpendicular to first edge)
285 edit.run_after_mouse_release(Editor_state, Editor_state.left+15, Editor_state.top+Drawing_padding_top+26, 1)
286 local drawing = Editor_state.lines[1]
287 check_eq(#drawing.shapes, 1, '#shapes')
288 check_eq(#drawing.points, 5, '#points') -- currently includes every point added
289 local shape = drawing.shapes[1]
290 check_eq(shape.mode, 'rectangle', 'shape_mode')
291 check_eq(#shape.vertices, 4, 'vertices')
292 local p = drawing.points[shape.vertices[1]]
293 check_eq(p.x, 35, 'p1:x')
294 check_eq(p.y, 36, 'p1:y')
295 local p = drawing.points[shape.vertices[2]]
296 check_eq(p.x, 75, 'p2:x')
297 check_eq(p.y, 76, 'p2:y')
298 local p = drawing.points[shape.vertices[3]]
299 check_eq(p.x, 70, 'p3:x')
300 check_eq(p.y, 81, 'p3:y')
301 local p = drawing.points[shape.vertices[4]]
302 check_eq(p.x, 30, 'p4:x')
303 check_eq(p.y, 41, 'p4:y')
306 function test_draw_rectangle_intermediate()
307 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
308 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
309 Editor_state = edit.initialize_test_state()
310 Editor_state.lines = load_array{'```lines', '```', ''}
311 Text.redraw_all(Editor_state)
312 edit.draw(Editor_state)
313 check_eq(Editor_state.current_drawing_mode, 'line', 'baseline/drawing_mode')
314 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
315 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
316 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
317 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
318 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
319 -- first point
320 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
321 edit.run_after_text_input(Editor_state, 'r') -- rectangle mode
322 -- second point/first edge
323 App.mouse_move(Editor_state.left+42, Editor_state.top+Drawing_padding_top+45)
324 edit.run_after_text_input(Editor_state, 'p')
325 -- override second point/first edge
326 App.mouse_move(Editor_state.left+75, Editor_state.top+Drawing_padding_top+76)
327 edit.run_after_text_input(Editor_state, 'p')
328 local drawing = Editor_state.lines[1]
329 check_eq(#drawing.points, 3, '#points') -- currently includes every point added
330 local pending = drawing.pending
331 check_eq(pending.mode, 'rectangle', 'shape_mode')
332 check_eq(#pending.vertices, 2, 'vertices')
333 local p = drawing.points[pending.vertices[1]]
334 check_eq(p.x, 35, 'p1:x')
335 check_eq(p.y, 36, 'p1:y')
336 local p = drawing.points[pending.vertices[2]]
337 check_eq(p.x, 75, 'p2:x')
338 check_eq(p.y, 76, 'p2:y')
339 -- outline of rectangle is drawn based on where the mouse is, but we can't check that so far
342 function test_draw_square()
343 -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
344 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
345 Editor_state = edit.initialize_test_state()
346 Editor_state.lines = load_array{'```lines', '```', ''}
347 Text.redraw_all(Editor_state)
348 edit.draw(Editor_state)
349 check_eq(Editor_state.current_drawing_mode, 'line', 'baseline/drawing_mode')
350 check_eq(#Editor_state.lines, 2, 'baseline/#lines')
351 check_eq(Editor_state.lines[1].mode, 'drawing', 'baseline/mode')
352 check_eq(Editor_state.line_cache[1].starty, Editor_state.top+Drawing_padding_top, 'baseline/y')
353 check_eq(Editor_state.lines[1].h, 128, 'baseline/y')
354 check_eq(#Editor_state.lines[1].shapes, 0, 'baseline/#shapes')
355 -- first point
356 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
357 edit.run_after_text_input(Editor_state, 's') -- square mode
358 -- second point/first edge
359 App.mouse_move(Editor_state.left+42, Editor_state.top+Drawing_padding_top+45)
360 edit.run_after_text_input(Editor_state, 'p')
361 -- override second point/first edge
362 App.mouse_move(Editor_state.left+65, Editor_state.top+Drawing_padding_top+66)
363 edit.run_after_text_input(Editor_state, 'p')
364 -- release (decides which side of first edge to draw square on)
365 edit.run_after_mouse_release(Editor_state, Editor_state.left+15, Editor_state.top+Drawing_padding_top+26, 1)
366 local drawing = Editor_state.lines[1]
367 check_eq(#drawing.shapes, 1, '#shapes')
368 check_eq(#drawing.points, 5, '#points') -- currently includes every point added
369 check_eq(drawing.shapes[1].mode, 'square', 'shape_mode')
370 check_eq(#drawing.shapes[1].vertices, 4, 'vertices')
371 local p = drawing.points[drawing.shapes[1].vertices[1]]
372 check_eq(p.x, 35, 'p1:x')
373 check_eq(p.y, 36, 'p1:y')
374 local p = drawing.points[drawing.shapes[1].vertices[2]]
375 check_eq(p.x, 65, 'p2:x')
376 check_eq(p.y, 66, 'p2:y')
377 local p = drawing.points[drawing.shapes[1].vertices[3]]
378 check_eq(p.x, 35, 'p3:x')
379 check_eq(p.y, 96, 'p3:y')
380 local p = drawing.points[drawing.shapes[1].vertices[4]]
381 check_eq(p.x, 5, 'p4:x')
382 check_eq(p.y, 66, 'p4:y')
385 function test_name_point()
386 -- create a drawing with a line
387 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
388 Editor_state = edit.initialize_test_state()
389 Editor_state.filename = 'foo'
390 Editor_state.lines = load_array{'```lines', '```', ''}
391 Text.redraw_all(Editor_state)
392 Editor_state.current_drawing_mode = 'line'
393 edit.draw(Editor_state)
394 -- draw a line
395 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
396 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
397 local drawing = Editor_state.lines[1]
398 check_eq(#drawing.shapes, 1, 'baseline/#shapes')
399 check_eq(#drawing.points, 2, 'baseline/#points')
400 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
401 local p1 = drawing.points[drawing.shapes[1].p1]
402 local p2 = drawing.points[drawing.shapes[1].p2]
403 check_eq(p1.x, 5, 'baseline/p1:x')
404 check_eq(p1.y, 6, 'baseline/p1:y')
405 check_eq(p2.x, 35, 'baseline/p2:x')
406 check_eq(p2.y, 36, 'baseline/p2:y')
407 check_nil(p2.name, 'baseline/p2:name')
408 -- enter 'name' mode without moving the mouse
409 edit.run_after_keychord(Editor_state, 'C-n')
410 check_eq(Editor_state.current_drawing_mode, 'name', 'mode:1')
411 edit.run_after_text_input(Editor_state, 'A')
412 check_eq(p2.name, 'A', 'check1')
413 -- still in 'name' mode
414 check_eq(Editor_state.current_drawing_mode, 'name', 'mode:2')
415 -- exit 'name' mode
416 edit.run_after_keychord(Editor_state, 'return')
417 check_eq(Editor_state.current_drawing_mode, 'line', 'mode:3')
418 check_eq(p2.name, 'A', 'check2')
419 -- wait until save
420 Current_time = Current_time + 3.1
421 edit.update(Editor_state, 0)
422 -- change is saved
423 load_from_disk(Editor_state)
424 Text.redraw_all(Editor_state)
425 local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
426 check_eq(p2.name, 'A', 'save')
429 function test_move_point()
430 -- create a drawing with a line
431 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
432 Editor_state = edit.initialize_test_state()
433 Editor_state.filename = 'foo'
434 Editor_state.lines = load_array{'```lines', '```', ''}
435 Text.redraw_all(Editor_state)
436 Editor_state.current_drawing_mode = 'line'
437 edit.draw(Editor_state)
438 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
439 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
440 local drawing = Editor_state.lines[1]
441 check_eq(#drawing.shapes, 1, 'baseline/#shapes')
442 check_eq(#drawing.points, 2, 'baseline/#points')
443 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
444 local p1 = drawing.points[drawing.shapes[1].p1]
445 local p2 = drawing.points[drawing.shapes[1].p2]
446 check_eq(p1.x, 5, 'baseline/p1:x')
447 check_eq(p1.y, 6, 'baseline/p1:y')
448 check_eq(p2.x, 35, 'baseline/p2:x')
449 check_eq(p2.y, 36, 'baseline/p2:y')
450 -- wait until save
451 Current_time = Current_time + 3.1
452 edit.update(Editor_state, 0)
453 -- line is saved to disk
454 load_from_disk(Editor_state)
455 Text.redraw_all(Editor_state)
456 local drawing = Editor_state.lines[1]
457 local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
458 check_eq(p2.x, 35, 'save/x')
459 check_eq(p2.y, 36, 'save/y')
460 edit.draw(Editor_state)
461 -- enter 'move' mode without moving the mouse
462 edit.run_after_keychord(Editor_state, 'C-u')
463 check_eq(Editor_state.current_drawing_mode, 'move', 'mode:1')
464 -- point is lifted
465 check_eq(drawing.pending.mode, 'move', 'mode:2')
466 check_eq(drawing.pending.target_point, p2, 'target')
467 -- move point
468 App.mouse_move(Editor_state.left+26, Editor_state.top+Drawing_padding_top+44)
469 edit.update(Editor_state, 0.05)
470 local p2 = drawing.points[drawing.shapes[1].p2]
471 check_eq(p2.x, 26, 'x')
472 check_eq(p2.y, 44, 'y')
473 -- exit 'move' mode
474 edit.run_after_mouse_click(Editor_state, Editor_state.left+26, Editor_state.top+Drawing_padding_top+44, 1)
475 check_eq(Editor_state.current_drawing_mode, 'line', 'mode:3')
476 check_eq(drawing.pending, {}, 'pending')
477 -- wait until save
478 Current_time = Current_time + 3.1
479 edit.update(Editor_state, 0)
480 -- change is saved
481 load_from_disk(Editor_state)
482 Text.redraw_all(Editor_state)
483 local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
484 check_eq(p2.x, 26, 'save/x')
485 check_eq(p2.y, 44, 'save/y')
488 function test_move_point_on_manhattan_line()
489 -- create a drawing with a manhattan line
490 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
491 Editor_state = edit.initialize_test_state()
492 Editor_state.filename = 'foo'
493 Editor_state.lines = load_array{'```lines', '```', ''}
494 Text.redraw_all(Editor_state)
495 Editor_state.current_drawing_mode = 'manhattan'
496 edit.draw(Editor_state)
497 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
498 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+46, 1)
499 local drawing = Editor_state.lines[1]
500 check_eq(#drawing.shapes, 1, 'baseline/#shapes')
501 check_eq(#drawing.points, 2, 'baseline/#points')
502 check_eq(drawing.shapes[1].mode, 'manhattan', 'baseline/shape:1')
503 edit.draw(Editor_state)
504 -- enter 'move' mode
505 edit.run_after_keychord(Editor_state, 'C-u')
506 check_eq(Editor_state.current_drawing_mode, 'move', 'mode:1')
507 -- move point
508 App.mouse_move(Editor_state.left+26, Editor_state.top+Drawing_padding_top+44)
509 edit.update(Editor_state, 0.05)
510 -- line is no longer manhattan
511 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
514 function test_delete_lines_at_point()
515 -- create a drawing with two lines connected at a point
516 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
517 Editor_state = edit.initialize_test_state()
518 Editor_state.filename = 'foo'
519 Editor_state.lines = load_array{'```lines', '```', ''}
520 Text.redraw_all(Editor_state)
521 Editor_state.current_drawing_mode = 'line'
522 edit.draw(Editor_state)
523 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
524 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
525 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
526 edit.run_after_mouse_release(Editor_state, Editor_state.left+55, Editor_state.top+Drawing_padding_top+26, 1)
527 local drawing = Editor_state.lines[1]
528 check_eq(#drawing.shapes, 2, 'baseline/#shapes')
529 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
530 check_eq(drawing.shapes[2].mode, 'line', 'baseline/shape:2')
531 -- hover on the common point and delete
532 App.mouse_move(Editor_state.left+35, Editor_state.top+Drawing_padding_top+36)
533 edit.run_after_keychord(Editor_state, 'C-d')
534 check_eq(drawing.shapes[1].mode, 'deleted', 'shape:1')
535 check_eq(drawing.shapes[2].mode, 'deleted', 'shape:2')
536 -- wait for some time
537 Current_time = Current_time + 3.1
538 edit.update(Editor_state, 0)
539 -- deleted points disappear after file is reloaded
540 load_from_disk(Editor_state)
541 Text.redraw_all(Editor_state)
542 check_eq(#Editor_state.lines[1].shapes, 0, 'save')
545 function test_delete_line_under_mouse_pointer()
546 -- create a drawing with two lines connected at a point
547 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
548 Editor_state = edit.initialize_test_state()
549 Editor_state.lines = load_array{'```lines', '```', ''}
550 Text.redraw_all(Editor_state)
551 Editor_state.current_drawing_mode = 'line'
552 edit.draw(Editor_state)
553 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
554 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
555 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
556 edit.run_after_mouse_release(Editor_state, Editor_state.left+55, Editor_state.top+Drawing_padding_top+26, 1)
557 local drawing = Editor_state.lines[1]
558 check_eq(#drawing.shapes, 2, 'baseline/#shapes')
559 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
560 check_eq(drawing.shapes[2].mode, 'line', 'baseline/shape:2')
561 -- hover on one of the lines and delete
562 App.mouse_move(Editor_state.left+25, Editor_state.top+Drawing_padding_top+26)
563 edit.run_after_keychord(Editor_state, 'C-d')
564 -- only that line is deleted
565 check_eq(drawing.shapes[1].mode, 'deleted', 'shape:1')
566 check_eq(drawing.shapes[2].mode, 'line', 'shape:2')
569 function test_delete_point_from_polygon()
570 -- create a drawing with two lines connected at a point
571 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
572 Editor_state = edit.initialize_test_state()
573 Editor_state.lines = load_array{'```lines', '```', ''}
574 Text.redraw_all(Editor_state)
575 Editor_state.current_drawing_mode = 'line'
576 edit.draw(Editor_state)
577 -- first point
578 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
579 edit.run_after_text_input(Editor_state, 'g') -- polygon mode
580 -- second point
581 App.mouse_move(Editor_state.left+65, Editor_state.top+Drawing_padding_top+36)
582 edit.run_after_text_input(Editor_state, 'p') -- add point
583 -- third point
584 App.mouse_move(Editor_state.left+35, Editor_state.top+Drawing_padding_top+26)
585 edit.run_after_text_input(Editor_state, 'p') -- add point
586 -- fourth point
587 edit.run_after_mouse_release(Editor_state, Editor_state.left+14, Editor_state.top+Drawing_padding_top+16, 1)
588 local drawing = Editor_state.lines[1]
589 check_eq(#drawing.shapes, 1, 'baseline/#shapes')
590 check_eq(drawing.shapes[1].mode, 'polygon', 'baseline/mode')
591 check_eq(#drawing.shapes[1].vertices, 4, 'baseline/vertices')
592 -- hover on a point and delete
593 App.mouse_move(Editor_state.left+35, Editor_state.top+Drawing_padding_top+26)
594 edit.run_after_keychord(Editor_state, 'C-d')
595 -- just the one point is deleted
596 check_eq(drawing.shapes[1].mode, 'polygon', 'shape')
597 check_eq(#drawing.shapes[1].vertices, 3, 'vertices')
600 function test_delete_point_from_polygon()
601 -- create a drawing with two lines connected at a point
602 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
603 Editor_state = edit.initialize_test_state()
604 Editor_state.lines = load_array{'```lines', '```', ''}
605 Text.redraw_all(Editor_state)
606 Editor_state.current_drawing_mode = 'line'
607 edit.draw(Editor_state)
608 -- first point
609 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
610 edit.run_after_text_input(Editor_state, 'g') -- polygon mode
611 -- second point
612 App.mouse_move(Editor_state.left+65, Editor_state.top+Drawing_padding_top+36)
613 edit.run_after_text_input(Editor_state, 'p') -- add point
614 -- third point
615 edit.run_after_mouse_release(Editor_state, Editor_state.left+14, Editor_state.top+Drawing_padding_top+16, 1)
616 local drawing = Editor_state.lines[1]
617 check_eq(#drawing.shapes, 1, 'baseline/#shapes')
618 check_eq(drawing.shapes[1].mode, 'polygon', 'baseline/mode')
619 check_eq(#drawing.shapes[1].vertices, 3, 'baseline/vertices')
620 -- hover on a point and delete
621 App.mouse_move(Editor_state.left+65, Editor_state.top+Drawing_padding_top+36)
622 edit.run_after_keychord(Editor_state, 'C-d')
623 -- there's < 3 points left, so the whole polygon is deleted
624 check_eq(drawing.shapes[1].mode, 'deleted', 'check')
627 function test_undo_name_point()
628 -- create a drawing with a line
629 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
630 Editor_state = edit.initialize_test_state()
631 Editor_state.filename = 'foo'
632 Editor_state.lines = load_array{'```lines', '```', ''}
633 Text.redraw_all(Editor_state)
634 Editor_state.current_drawing_mode = 'line'
635 edit.draw(Editor_state)
636 -- draw a line
637 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
638 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
639 local drawing = Editor_state.lines[1]
640 check_eq(#drawing.shapes, 1, 'baseline/#shapes')
641 check_eq(#drawing.points, 2, 'baseline/#points')
642 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
643 local p1 = drawing.points[drawing.shapes[1].p1]
644 local p2 = drawing.points[drawing.shapes[1].p2]
645 check_eq(p1.x, 5, 'baseline/p1:x')
646 check_eq(p1.y, 6, 'baseline/p1:y')
647 check_eq(p2.x, 35, 'baseline/p2:x')
648 check_eq(p2.y, 36, 'baseline/p2:y')
649 check_nil(p2.name, 'baseline/p2:name')
650 check_eq(#Editor_state.history, 1, 'baseline/history:1')
651 --? print('a', Editor_state.lines.current_drawing)
652 -- enter 'name' mode without moving the mouse
653 edit.run_after_keychord(Editor_state, 'C-n')
654 edit.run_after_text_input(Editor_state, 'A')
655 edit.run_after_keychord(Editor_state, 'return')
656 check_eq(p2.name, 'A', 'baseline')
657 check_eq(#Editor_state.history, 3, 'baseline/history:2')
658 check_eq(Editor_state.next_history, 4, 'baseline/next_history')
659 --? print('b', Editor_state.lines.current_drawing)
660 -- undo
661 edit.run_after_keychord(Editor_state, 'C-z')
662 local drawing = Editor_state.lines[1]
663 local p2 = drawing.points[drawing.shapes[1].p2]
664 check_eq(Editor_state.next_history, 3, 'next_history')
665 check_eq(p2.name, '', 'undo') -- not quite what it was before, but close enough
666 -- wait until save
667 Current_time = Current_time + 3.1
668 edit.update(Editor_state, 0)
669 -- undo is saved
670 load_from_disk(Editor_state)
671 Text.redraw_all(Editor_state)
672 local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
673 check_eq(p2.name, '', 'save')
676 function test_undo_move_point()
677 -- create a drawing with a line
678 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
679 Editor_state = edit.initialize_test_state()
680 Editor_state.filename = 'foo'
681 Editor_state.lines = load_array{'```lines', '```', ''}
682 Text.redraw_all(Editor_state)
683 Editor_state.current_drawing_mode = 'line'
684 edit.draw(Editor_state)
685 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
686 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
687 local drawing = Editor_state.lines[1]
688 check_eq(#drawing.shapes, 1, 'baseline/#shapes')
689 check_eq(#drawing.points, 2, 'baseline/#points')
690 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
691 local p1 = drawing.points[drawing.shapes[1].p1]
692 local p2 = drawing.points[drawing.shapes[1].p2]
693 check_eq(p1.x, 5, 'baseline/p1:x')
694 check_eq(p1.y, 6, 'baseline/p1:y')
695 check_eq(p2.x, 35, 'baseline/p2:x')
696 check_eq(p2.y, 36, 'baseline/p2:y')
697 check_nil(p2.name, 'baseline/p2:name')
698 -- move p2
699 edit.run_after_keychord(Editor_state, 'C-u')
700 App.mouse_move(Editor_state.left+26, Editor_state.top+Drawing_padding_top+44)
701 edit.update(Editor_state, 0.05)
702 local p2 = drawing.points[drawing.shapes[1].p2]
703 check_eq(p2.x, 26, 'x')
704 check_eq(p2.y, 44, 'y')
705 -- exit 'move' mode
706 edit.run_after_mouse_click(Editor_state, Editor_state.left+26, Editor_state.top+Drawing_padding_top+44, 1)
707 check_eq(Editor_state.next_history, 4, 'next_history')
708 -- undo
709 edit.run_after_keychord(Editor_state, 'C-z')
710 edit.run_after_keychord(Editor_state, 'C-z') -- bug: need to undo twice
711 local drawing = Editor_state.lines[1]
712 local p2 = drawing.points[drawing.shapes[1].p2]
713 check_eq(Editor_state.next_history, 2, 'next_history')
714 check_eq(p2.x, 35, 'x')
715 check_eq(p2.y, 36, 'y')
716 -- wait until save
717 Current_time = Current_time + 3.1
718 edit.update(Editor_state, 0)
719 -- undo is saved
720 load_from_disk(Editor_state)
721 Text.redraw_all(Editor_state)
722 local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
723 check_eq(p2.x, 35, 'save/x')
724 check_eq(p2.y, 36, 'save/y')
727 function test_undo_delete_point()
728 -- create a drawing with two lines connected at a point
729 App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels
730 Editor_state = edit.initialize_test_state()
731 Editor_state.filename = 'foo'
732 Editor_state.lines = load_array{'```lines', '```', ''}
733 Text.redraw_all(Editor_state)
734 Editor_state.current_drawing_mode = 'line'
735 edit.draw(Editor_state)
736 edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1)
737 edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
738 edit.run_after_mouse_press(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1)
739 edit.run_after_mouse_release(Editor_state, Editor_state.left+55, Editor_state.top+Drawing_padding_top+26, 1)
740 local drawing = Editor_state.lines[1]
741 check_eq(#drawing.shapes, 2, 'baseline/#shapes')
742 check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1')
743 check_eq(drawing.shapes[2].mode, 'line', 'baseline/shape:2')
744 -- hover on the common point and delete
745 App.mouse_move(Editor_state.left+35, Editor_state.top+Drawing_padding_top+36)
746 edit.run_after_keychord(Editor_state, 'C-d')
747 check_eq(drawing.shapes[1].mode, 'deleted', 'shape:1')
748 check_eq(drawing.shapes[2].mode, 'deleted', 'shape:2')
749 -- undo
750 edit.run_after_keychord(Editor_state, 'C-z')
751 local drawing = Editor_state.lines[1]
752 local p2 = drawing.points[drawing.shapes[1].p2]
753 check_eq(Editor_state.next_history, 3, 'next_history')
754 check_eq(drawing.shapes[1].mode, 'line', 'shape:1')
755 check_eq(drawing.shapes[2].mode, 'line', 'shape:2')
756 -- wait until save
757 Current_time = Current_time + 3.1
758 edit.update(Editor_state, 0)
759 -- undo is saved
760 load_from_disk(Editor_state)
761 Text.redraw_all(Editor_state)
762 check_eq(#Editor_state.lines[1].shapes, 2, 'save')