drawing_tests.lua 40 KB

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