LineCanvasTests.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. using System.Text;
  2. using UnitTests;
  3. using Xunit.Abstractions;
  4. namespace Terminal.Gui.DrawingTests;
  5. public class LineCanvasTests (ITestOutputHelper output)
  6. {
  7. [Theory]
  8. // Horizontal lines with a vertical zero-length
  9. [InlineData (
  10. 0,
  11. 0,
  12. 1,
  13. Orientation.Horizontal,
  14. LineStyle.Double,
  15. 0,
  16. 0,
  17. 0,
  18. Orientation.Vertical,
  19. LineStyle.Single,
  20. "╞"
  21. )]
  22. [InlineData (
  23. 0,
  24. 0,
  25. -1,
  26. Orientation.Horizontal,
  27. LineStyle.Double,
  28. 0,
  29. 0,
  30. 0,
  31. Orientation.Vertical,
  32. LineStyle.Single,
  33. "╡"
  34. )]
  35. [InlineData (
  36. 0,
  37. 0,
  38. 1,
  39. Orientation.Horizontal,
  40. LineStyle.Single,
  41. 0,
  42. 0,
  43. 0,
  44. Orientation.Vertical,
  45. LineStyle.Double,
  46. "╟"
  47. )]
  48. [InlineData (
  49. 0,
  50. 0,
  51. -1,
  52. Orientation.Horizontal,
  53. LineStyle.Single,
  54. 0,
  55. 0,
  56. 0,
  57. Orientation.Vertical,
  58. LineStyle.Double,
  59. "╢"
  60. )]
  61. [InlineData (
  62. 0,
  63. 0,
  64. 1,
  65. Orientation.Horizontal,
  66. LineStyle.Single,
  67. 0,
  68. 0,
  69. 0,
  70. Orientation.Vertical,
  71. LineStyle.Single,
  72. "├"
  73. )]
  74. [InlineData (
  75. 0,
  76. 0,
  77. -1,
  78. Orientation.Horizontal,
  79. LineStyle.Single,
  80. 0,
  81. 0,
  82. 0,
  83. Orientation.Vertical,
  84. LineStyle.Single,
  85. "┤"
  86. )]
  87. [InlineData (
  88. 0,
  89. 0,
  90. 1,
  91. Orientation.Horizontal,
  92. LineStyle.Double,
  93. 0,
  94. 0,
  95. 0,
  96. Orientation.Vertical,
  97. LineStyle.Double,
  98. "╠"
  99. )]
  100. [InlineData (
  101. 0,
  102. 0,
  103. -1,
  104. Orientation.Horizontal,
  105. LineStyle.Double,
  106. 0,
  107. 0,
  108. 0,
  109. Orientation.Vertical,
  110. LineStyle.Double,
  111. "╣"
  112. )]
  113. // Vertical lines with a horizontal zero-length
  114. [InlineData (
  115. 0,
  116. 0,
  117. 1,
  118. Orientation.Vertical,
  119. LineStyle.Double,
  120. 0,
  121. 0,
  122. 0,
  123. Orientation.Horizontal,
  124. LineStyle.Single,
  125. "╥"
  126. )]
  127. [InlineData (
  128. 0,
  129. 0,
  130. -1,
  131. Orientation.Vertical,
  132. LineStyle.Double,
  133. 0,
  134. 0,
  135. 0,
  136. Orientation.Horizontal,
  137. LineStyle.Single,
  138. "╨"
  139. )]
  140. [InlineData (
  141. 0,
  142. 0,
  143. 1,
  144. Orientation.Vertical,
  145. LineStyle.Single,
  146. 0,
  147. 0,
  148. 0,
  149. Orientation.Horizontal,
  150. LineStyle.Double,
  151. "╤"
  152. )]
  153. [InlineData (
  154. 0,
  155. 0,
  156. -1,
  157. Orientation.Vertical,
  158. LineStyle.Single,
  159. 0,
  160. 0,
  161. 0,
  162. Orientation.Horizontal,
  163. LineStyle.Double,
  164. "╧"
  165. )]
  166. [InlineData (
  167. 0,
  168. 0,
  169. 1,
  170. Orientation.Vertical,
  171. LineStyle.Single,
  172. 0,
  173. 0,
  174. 0,
  175. Orientation.Horizontal,
  176. LineStyle.Single,
  177. "┬"
  178. )]
  179. [InlineData (
  180. 0,
  181. 0,
  182. -1,
  183. Orientation.Vertical,
  184. LineStyle.Single,
  185. 0,
  186. 0,
  187. 0,
  188. Orientation.Horizontal,
  189. LineStyle.Single,
  190. "┴"
  191. )]
  192. [InlineData (
  193. 0,
  194. 0,
  195. 1,
  196. Orientation.Vertical,
  197. LineStyle.Double,
  198. 0,
  199. 0,
  200. 0,
  201. Orientation.Horizontal,
  202. LineStyle.Double,
  203. "╦"
  204. )]
  205. [InlineData (
  206. 0,
  207. 0,
  208. -1,
  209. Orientation.Vertical,
  210. LineStyle.Double,
  211. 0,
  212. 0,
  213. 0,
  214. Orientation.Horizontal,
  215. LineStyle.Double,
  216. "╩"
  217. )]
  218. // Crosses (two zero-length)
  219. [InlineData (
  220. 0,
  221. 0,
  222. 0,
  223. Orientation.Vertical,
  224. LineStyle.Double,
  225. 0,
  226. 0,
  227. 0,
  228. Orientation.Horizontal,
  229. LineStyle.Single,
  230. "╫"
  231. )]
  232. [InlineData (
  233. 0,
  234. 0,
  235. 0,
  236. Orientation.Vertical,
  237. LineStyle.Single,
  238. 0,
  239. 0,
  240. 0,
  241. Orientation.Horizontal,
  242. LineStyle.Double,
  243. "╪"
  244. )]
  245. [InlineData (
  246. 0,
  247. 0,
  248. 0,
  249. Orientation.Vertical,
  250. LineStyle.Single,
  251. 0,
  252. 0,
  253. 0,
  254. Orientation.Horizontal,
  255. LineStyle.Single,
  256. "┼"
  257. )]
  258. [InlineData (
  259. 0,
  260. 0,
  261. 0,
  262. Orientation.Vertical,
  263. LineStyle.Double,
  264. 0,
  265. 0,
  266. 0,
  267. Orientation.Horizontal,
  268. LineStyle.Double,
  269. "╬"
  270. )]
  271. public void Add_2_Lines (
  272. int x1,
  273. int y1,
  274. int len1,
  275. Orientation o1,
  276. LineStyle s1,
  277. int x2,
  278. int y2,
  279. int len2,
  280. Orientation o2,
  281. LineStyle s2,
  282. string expected
  283. )
  284. {
  285. View v = GetCanvas (out LineCanvas lc);
  286. v.Width = 10;
  287. v.Height = 10;
  288. v.Viewport = new (0, 0, 10, 10);
  289. lc.AddLine (new (x1, y1), len1, o1, s1);
  290. lc.AddLine (new (x2, y2), len2, o2, s2);
  291. OutputAssert.AssertEqual (output, expected, lc.ToString ());
  292. v.Dispose ();
  293. }
  294. [InlineData (
  295. 0,
  296. 0,
  297. 0,
  298. 0,
  299. 0,
  300. 1,
  301. 1
  302. )]
  303. [InlineData (
  304. 0,
  305. 0,
  306. 1,
  307. 0,
  308. 0,
  309. 1,
  310. 1
  311. )]
  312. [InlineData (
  313. 0,
  314. 0,
  315. 2,
  316. 0,
  317. 0,
  318. 2,
  319. 2
  320. )]
  321. [InlineData (
  322. 0,
  323. 0,
  324. 3,
  325. 0,
  326. 0,
  327. 3,
  328. 3
  329. )]
  330. [InlineData (
  331. 0,
  332. 0,
  333. -1,
  334. 0,
  335. 0,
  336. 1,
  337. 1
  338. )]
  339. [InlineData (
  340. 0,
  341. 0,
  342. -2,
  343. -1,
  344. -1,
  345. 2,
  346. 2
  347. )]
  348. [InlineData (
  349. 0,
  350. 0,
  351. -3,
  352. -2,
  353. -2,
  354. 3,
  355. 3
  356. )]
  357. [Theory]
  358. [SetupFakeDriver]
  359. public void Viewport_H_And_V_Lines_Both_Positive (
  360. int x,
  361. int y,
  362. int length,
  363. int expectedX,
  364. int expectedY,
  365. int expectedWidth,
  366. int expectedHeight
  367. )
  368. {
  369. var canvas = new LineCanvas ();
  370. canvas.AddLine (new (x, y), length, Orientation.Horizontal, LineStyle.Single);
  371. canvas.AddLine (new (x, y), length, Orientation.Vertical, LineStyle.Single);
  372. Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
  373. }
  374. [InlineData (
  375. 0,
  376. 0,
  377. 0,
  378. 0,
  379. 0,
  380. 1,
  381. 1
  382. )]
  383. [InlineData (
  384. 0,
  385. 0,
  386. 1,
  387. 0,
  388. 0,
  389. 1,
  390. 1
  391. )]
  392. [InlineData (
  393. 0,
  394. 0,
  395. 2,
  396. 0,
  397. 0,
  398. 2,
  399. 1
  400. )]
  401. [InlineData (
  402. 0,
  403. 0,
  404. 3,
  405. 0,
  406. 0,
  407. 3,
  408. 1
  409. )]
  410. [InlineData (
  411. 0,
  412. 0,
  413. -1,
  414. 0,
  415. 0,
  416. 1,
  417. 1
  418. )]
  419. [InlineData (
  420. 0,
  421. 0,
  422. -2,
  423. -1,
  424. 0,
  425. 2,
  426. 1
  427. )]
  428. [InlineData (
  429. 0,
  430. 0,
  431. -3,
  432. -2,
  433. 0,
  434. 3,
  435. 1
  436. )]
  437. [Theory]
  438. [SetupFakeDriver]
  439. public void Viewport_H_Line (
  440. int x,
  441. int y,
  442. int length,
  443. int expectedX,
  444. int expectedY,
  445. int expectedWidth,
  446. int expectedHeight
  447. )
  448. {
  449. var canvas = new LineCanvas ();
  450. canvas.AddLine (new (x, y), length, Orientation.Horizontal, LineStyle.Single);
  451. Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
  452. }
  453. [Fact]
  454. [SetupFakeDriver]
  455. public void Viewport_Specific ()
  456. {
  457. // Draw at 1,1 within client area of View (i.e. leave a top and left margin of 1)
  458. // This proves we aren't drawing excess above
  459. var x = 1;
  460. var y = 2;
  461. var width = 3;
  462. var height = 2;
  463. var lc = new LineCanvas ();
  464. // 01230
  465. // ╔╡╞╗1
  466. // ║ ║2
  467. // Add a short horiz line for ╔╡
  468. lc.AddLine (new (x, y), 2, Orientation.Horizontal, LineStyle.Double);
  469. Assert.Equal (new (x, y, 2, 1), lc.Bounds);
  470. //LHS line down
  471. lc.AddLine (new (x, y), height, Orientation.Vertical, LineStyle.Double);
  472. Assert.Equal (new (x, y, 2, 2), lc.Bounds);
  473. //Vertical line before Title, results in a ╡
  474. lc.AddLine (new (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
  475. Assert.Equal (new (x, y, 2, 2), lc.Bounds);
  476. //Vertical line after Title, results in a ╞
  477. lc.AddLine (new (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
  478. Assert.Equal (new (x, y, 3, 2), lc.Bounds);
  479. // remainder of top line
  480. lc.AddLine (new (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
  481. Assert.Equal (new (x, y, 4, 2), lc.Bounds);
  482. //RHS line down
  483. lc.AddLine (new (x + width, y), height, Orientation.Vertical, LineStyle.Double);
  484. Assert.Equal (new (x, y, 4, 2), lc.Bounds);
  485. OutputAssert.AssertEqual (
  486. output,
  487. @"
  488. ╔╡╞╗
  489. ║ ║",
  490. $"{Environment.NewLine}{lc}"
  491. );
  492. }
  493. [Fact]
  494. [SetupFakeDriver]
  495. public void Viewport_Specific_With_Ustring ()
  496. {
  497. // Draw at 1,1 within client area of View (i.e. leave a top and left margin of 1)
  498. // This proves we aren't drawing excess above
  499. var x = 1;
  500. var y = 2;
  501. var width = 3;
  502. var height = 2;
  503. var lc = new LineCanvas ();
  504. // 01230
  505. // ╔╡╞╗1
  506. // ║ ║2
  507. // Add a short horiz line for ╔╡
  508. lc.AddLine (new (x, y), 2, Orientation.Horizontal, LineStyle.Double);
  509. Assert.Equal (new (x, y, 2, 1), lc.Bounds);
  510. //LHS line down
  511. lc.AddLine (new (x, y), height, Orientation.Vertical, LineStyle.Double);
  512. Assert.Equal (new (x, y, 2, 2), lc.Bounds);
  513. //Vertical line before Title, results in a ╡
  514. lc.AddLine (new (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
  515. Assert.Equal (new (x, y, 2, 2), lc.Bounds);
  516. //Vertical line after Title, results in a ╞
  517. lc.AddLine (new (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
  518. Assert.Equal (new (x, y, 3, 2), lc.Bounds);
  519. // remainder of top line
  520. lc.AddLine (new (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
  521. Assert.Equal (new (x, y, 4, 2), lc.Bounds);
  522. //RHS line down
  523. lc.AddLine (new (x + width, y), height, Orientation.Vertical, LineStyle.Double);
  524. Assert.Equal (new (x, y, 4, 2), lc.Bounds);
  525. OutputAssert.AssertEqual (
  526. output,
  527. @"
  528. ╔╡╞╗
  529. ║ ║",
  530. $"{Environment.NewLine}{lc}"
  531. );
  532. }
  533. [Fact]
  534. [SetupFakeDriver]
  535. public void Canvas_Updates_On_Changes ()
  536. {
  537. var lc = new LineCanvas ();
  538. Assert.Equal (Rectangle.Empty, lc.Bounds);
  539. lc.AddLine (Point.Empty, 2, Orientation.Horizontal, LineStyle.Double);
  540. Assert.NotEqual (Rectangle.Empty, lc.Bounds);
  541. lc.Clear ();
  542. Assert.Equal (Rectangle.Empty, lc.Bounds);
  543. }
  544. [InlineData (0, 0, Orientation.Horizontal, "─")]
  545. [InlineData (1, 0, Orientation.Horizontal, "─")]
  546. [InlineData (0, 1, Orientation.Horizontal, "─")]
  547. [InlineData (-1, 0, Orientation.Horizontal, "─")]
  548. [InlineData (0, -1, Orientation.Horizontal, "─")]
  549. [InlineData (-1, -1, Orientation.Horizontal, "─")]
  550. [InlineData (0, 0, Orientation.Vertical, "│")]
  551. [InlineData (1, 0, Orientation.Vertical, "│")]
  552. [InlineData (0, 1, Orientation.Vertical, "│")]
  553. [InlineData (0, -1, Orientation.Vertical, "│")]
  554. [InlineData (-1, 0, Orientation.Vertical, "│")]
  555. [InlineData (-1, -1, Orientation.Vertical, "│")]
  556. [Theory]
  557. [SetupFakeDriver]
  558. public void Length_0_Is_1_Long (int x, int y, Orientation orientation, string expected)
  559. {
  560. var canvas = new LineCanvas ();
  561. // Add a line at 5, 5 that's has length of 1
  562. canvas.AddLine (new (x, y), 1, orientation, LineStyle.Single);
  563. OutputAssert.AssertEqual (output, $"{expected}", $"{canvas}");
  564. }
  565. // X is offset by 2
  566. [InlineData (0, 0, 1, Orientation.Horizontal, "─")]
  567. [InlineData (1, 0, 1, Orientation.Horizontal, "─")]
  568. [InlineData (0, 1, 1, Orientation.Horizontal, "─")]
  569. [InlineData (0, 0, 1, Orientation.Vertical, "│")]
  570. [InlineData (1, 0, 1, Orientation.Vertical, "│")]
  571. [InlineData (0, 1, 1, Orientation.Vertical, "│")]
  572. [InlineData (-1, 0, 1, Orientation.Horizontal, "─")]
  573. [InlineData (0, -1, 1, Orientation.Horizontal, "─")]
  574. [InlineData (-1, 0, 1, Orientation.Vertical, "│")]
  575. [InlineData (0, -1, 1, Orientation.Vertical, "│")]
  576. [InlineData (0, 0, -1, Orientation.Horizontal, "─")]
  577. [InlineData (1, 0, -1, Orientation.Horizontal, "─")]
  578. [InlineData (0, 1, -1, Orientation.Horizontal, "─")]
  579. [InlineData (0, 0, -1, Orientation.Vertical, "│")]
  580. [InlineData (1, 0, -1, Orientation.Vertical, "│")]
  581. [InlineData (0, 1, -1, Orientation.Vertical, "│")]
  582. [InlineData (-1, 0, -1, Orientation.Horizontal, "─")]
  583. [InlineData (0, -1, -1, Orientation.Horizontal, "─")]
  584. [InlineData (-1, 0, -1, Orientation.Vertical, "│")]
  585. [InlineData (0, -1, -1, Orientation.Vertical, "│")]
  586. [InlineData (0, 0, 2, Orientation.Horizontal, "──")]
  587. [InlineData (1, 0, 2, Orientation.Horizontal, "──")]
  588. [InlineData (0, 1, 2, Orientation.Horizontal, "──")]
  589. [InlineData (1, 1, 2, Orientation.Horizontal, "──")]
  590. [InlineData (0, 0, 2, Orientation.Vertical, "│\r\n│")]
  591. [InlineData (1, 0, 2, Orientation.Vertical, "│\r\n│")]
  592. [InlineData (0, 1, 2, Orientation.Vertical, "│\r\n│")]
  593. [InlineData (1, 1, 2, Orientation.Vertical, "│\r\n│")]
  594. [InlineData (-1, 0, 2, Orientation.Horizontal, "──")]
  595. [InlineData (0, -1, 2, Orientation.Horizontal, "──")]
  596. [InlineData (-1, 0, 2, Orientation.Vertical, "│\r\n│")]
  597. [InlineData (0, -1, 2, Orientation.Vertical, "│\r\n│")]
  598. [InlineData (-1, -1, 2, Orientation.Vertical, "│\r\n│")]
  599. [InlineData (0, 0, -2, Orientation.Horizontal, "──")]
  600. [InlineData (1, 0, -2, Orientation.Horizontal, "──")]
  601. [InlineData (0, 1, -2, Orientation.Horizontal, "──")]
  602. [InlineData (0, 0, -2, Orientation.Vertical, "│\r\n│")]
  603. [InlineData (1, 0, -2, Orientation.Vertical, "│\r\n│")]
  604. [InlineData (0, 1, -2, Orientation.Vertical, "│\r\n│")]
  605. [InlineData (1, 1, -2, Orientation.Vertical, "│\r\n│")]
  606. [InlineData (-1, 0, -2, Orientation.Horizontal, "──")]
  607. [InlineData (0, -1, -2, Orientation.Horizontal, "──")]
  608. [InlineData (-1, 0, -2, Orientation.Vertical, "│\r\n│")]
  609. [InlineData (0, -1, -2, Orientation.Vertical, "│\r\n│")]
  610. [InlineData (-1, -1, -2, Orientation.Vertical, "│\r\n│")]
  611. [Theory]
  612. [SetupFakeDriver]
  613. public void Length_n_Is_n_Long (int x, int y, int length, Orientation orientation, string expected)
  614. {
  615. var canvas = new LineCanvas ();
  616. canvas.AddLine (new (x, y), length, orientation, LineStyle.Single);
  617. var result = canvas.ToString ();
  618. OutputAssert.AssertEqual (output, expected, result);
  619. }
  620. [Fact]
  621. [SetupFakeDriver]
  622. public void Length_Negative ()
  623. {
  624. var offset = new Point (5, 5);
  625. var canvas = new LineCanvas ();
  626. canvas.AddLine (offset, -3, Orientation.Horizontal, LineStyle.Single);
  627. var looksLike = "───";
  628. Assert.Equal (looksLike, $"{canvas}");
  629. }
  630. [InlineData (Orientation.Horizontal, "─")]
  631. [InlineData (Orientation.Vertical, "│")]
  632. [Theory]
  633. [SetupFakeDriver]
  634. public void Length_Zero_Alone_Is_Line (Orientation orientation, string expected)
  635. {
  636. var lc = new LineCanvas ();
  637. // Add a line at 0, 0 that's has length of 0
  638. lc.AddLine (Point.Empty, 0, orientation, LineStyle.Single);
  639. OutputAssert.AssertEqual (output, expected, $"{lc}");
  640. }
  641. [InlineData (Orientation.Horizontal, "┼")]
  642. [InlineData (Orientation.Vertical, "┼")]
  643. [Theory]
  644. [SetupFakeDriver]
  645. public void Length_Zero_Cross_Is_Cross (Orientation orientation, string expected)
  646. {
  647. var lc = new LineCanvas ();
  648. // Add point at opposite orientation
  649. lc.AddLine (
  650. Point.Empty,
  651. 0,
  652. orientation == Orientation.Horizontal ? Orientation.Vertical : Orientation.Horizontal,
  653. LineStyle.Single
  654. );
  655. // Add a line at 0, 0 that's has length of 0
  656. lc.AddLine (Point.Empty, 0, orientation, LineStyle.Single);
  657. OutputAssert.AssertEqual (output, expected, $"{lc}");
  658. }
  659. [InlineData (Orientation.Horizontal, "╥")]
  660. [InlineData (Orientation.Vertical, "╞")]
  661. [Theory]
  662. [SetupFakeDriver]
  663. public void Length_Zero_NextTo_Opposite_Is_T (Orientation orientation, string expected)
  664. {
  665. var lc = new LineCanvas ();
  666. // Add line with length of 1 in opposite orientation starting at same location
  667. if (orientation == Orientation.Horizontal)
  668. {
  669. lc.AddLine (Point.Empty, 1, Orientation.Vertical, LineStyle.Double);
  670. }
  671. else
  672. {
  673. lc.AddLine (Point.Empty, 1, Orientation.Horizontal, LineStyle.Double);
  674. }
  675. // Add a line at 0, 0 that's has length of 0
  676. lc.AddLine (Point.Empty, 0, orientation, LineStyle.Single);
  677. OutputAssert.AssertEqual (output, expected, $"{lc}");
  678. }
  679. [Fact]
  680. public void TestLineCanvas_LeaveMargin_Top1_Left1 ()
  681. {
  682. var canvas = new LineCanvas ();
  683. // Upper box
  684. canvas.AddLine (Point.Empty, 2, Orientation.Horizontal, LineStyle.Single);
  685. canvas.AddLine (Point.Empty, 2, Orientation.Vertical, LineStyle.Single);
  686. var looksLike =
  687. @"
  688. ┌─
  689. │ ";
  690. OutputAssert.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
  691. }
  692. [Fact]
  693. [SetupFakeDriver]
  694. public void TestLineCanvas_Window_Heavy ()
  695. {
  696. View v = GetCanvas (out LineCanvas canvas);
  697. // outer box
  698. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, LineStyle.Heavy);
  699. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, LineStyle.Heavy);
  700. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, LineStyle.Heavy);
  701. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, LineStyle.Heavy);
  702. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, LineStyle.Heavy);
  703. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, LineStyle.Heavy);
  704. v.Draw ();
  705. var looksLike =
  706. @"
  707. ┏━━━━┳━━━┓
  708. ┃ ┃ ┃
  709. ┣━━━━╋━━━┫
  710. ┃ ┃ ┃
  711. ┗━━━━┻━━━┛";
  712. DriverAssert.AssertDriverContentsAre (looksLike, output);
  713. v.Dispose ();
  714. }
  715. [Theory]
  716. [SetupFakeDriver]
  717. [InlineData (LineStyle.Single)]
  718. [InlineData (LineStyle.Rounded)]
  719. public void TestLineCanvas_Window_HeavyTop_ThinSides (LineStyle thinStyle)
  720. {
  721. View v = GetCanvas (out LineCanvas canvas);
  722. // outer box
  723. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, LineStyle.Heavy);
  724. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, thinStyle);
  725. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, LineStyle.Heavy);
  726. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, thinStyle);
  727. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, thinStyle);
  728. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, LineStyle.Heavy);
  729. v.Draw ();
  730. var looksLike =
  731. @"
  732. ┍━━━━┯━━━┑
  733. │ │ │
  734. ┝━━━━┿━━━┥
  735. │ │ │
  736. ┕━━━━┷━━━┙
  737. ";
  738. DriverAssert.AssertDriverContentsAre (looksLike, output);
  739. v.Dispose ();
  740. }
  741. [Theory]
  742. [SetupFakeDriver]
  743. [InlineData (LineStyle.Single)]
  744. [InlineData (LineStyle.Rounded)]
  745. public void TestLineCanvas_Window_ThinTop_HeavySides (LineStyle thinStyle)
  746. {
  747. View v = GetCanvas (out LineCanvas canvas);
  748. // outer box
  749. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, thinStyle);
  750. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, LineStyle.Heavy);
  751. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, thinStyle);
  752. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, LineStyle.Heavy);
  753. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, LineStyle.Heavy);
  754. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, thinStyle);
  755. v.Draw ();
  756. var looksLike =
  757. @"
  758. ┎────┰───┒
  759. ┃ ┃ ┃
  760. ┠────╂───┨
  761. ┃ ┃ ┃
  762. ┖────┸───┚
  763. ";
  764. DriverAssert.AssertDriverContentsAre (looksLike, output);
  765. v.Dispose ();
  766. }
  767. [Fact]
  768. [SetupFakeDriver]
  769. public void Top_Left_From_TopRight_LeftUp ()
  770. {
  771. var canvas = new LineCanvas ();
  772. // Upper box
  773. canvas.AddLine (Point.Empty, 2, Orientation.Horizontal, LineStyle.Single);
  774. canvas.AddLine (new (0, 1), -2, Orientation.Vertical, LineStyle.Single);
  775. var looksLike =
  776. @"
  777. ┌─
  778. │ ";
  779. OutputAssert.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
  780. }
  781. [Fact]
  782. [SetupFakeDriver]
  783. public void Top_With_1Down ()
  784. {
  785. var canvas = new LineCanvas ();
  786. // Top ─
  787. canvas.AddLine (Point.Empty, 1, Orientation.Horizontal, LineStyle.Single);
  788. // Bottom ─
  789. canvas.AddLine (new (1, 1), -1, Orientation.Horizontal, LineStyle.Single);
  790. //// Right down
  791. //canvas.AddLine (new Point (9, 0), 3, Orientation.Vertical, LineStyle.Single);
  792. //// Bottom
  793. //canvas.AddLine (new Point (9, 3), -10, Orientation.Horizontal, LineStyle.Single);
  794. //// Left Up
  795. //canvas.AddLine (new Point (0, 3), -3, Orientation.Vertical, LineStyle.Single);
  796. Assert.Equal (new (0, 0, 2, 2), canvas.Bounds);
  797. Dictionary<Point, Rune> map = canvas.GetMap ();
  798. Assert.Equal (2, map.Count);
  799. OutputAssert.AssertEqual (
  800. output,
  801. @"
  802. ─",
  803. $"{Environment.NewLine}{canvas}"
  804. );
  805. }
  806. [Fact]
  807. [SetupFakeDriver]
  808. public void ToString_Empty ()
  809. {
  810. var lc = new LineCanvas ();
  811. OutputAssert.AssertEqual (output, string.Empty, lc.ToString ());
  812. }
  813. // 012
  814. [InlineData (0, 0, "═══")]
  815. [InlineData (1, 0, "═══")]
  816. [InlineData (0, 1, "═══")]
  817. [InlineData (1, 1, "═══")]
  818. [InlineData (2, 2, "═══")]
  819. [InlineData (-1, 0, "═══")]
  820. [InlineData (0, -1, "═══")]
  821. [InlineData (-1, -1, "═══")]
  822. [InlineData (-2, -2, "═══")]
  823. [Theory]
  824. [SetupFakeDriver]
  825. public void ToString_Positive_Horizontal_1Line_Offset (int x, int y, string expected)
  826. {
  827. var lc = new LineCanvas ();
  828. lc.AddLine (new (x, y), 3, Orientation.Horizontal, LineStyle.Double);
  829. OutputAssert.AssertEqual (output, expected, $"{lc}");
  830. }
  831. [InlineData (0, 0, 0, 0, "═══")]
  832. [InlineData (1, 0, 1, 0, "═══")]
  833. [InlineData (-1, 0, -1, 0, "═══")]
  834. [InlineData (0, 0, 1, 0, "════")]
  835. [InlineData (1, 0, 3, 0, "═════")]
  836. [InlineData (1, 0, 4, 0, "══════")]
  837. [InlineData (1, 0, 5, 0, "═══ ═══")]
  838. [InlineData (0, 0, 0, 1, "\u2550\u2550\u2550\r\n\u2550\u2550\u2550")]
  839. [InlineData (0, 0, 1, 1, "═══ \r\n ═══")]
  840. [InlineData (0, 0, 2, 1, "═══ \r\n ═══")]
  841. [InlineData (1, 0, 0, 1, " ═══\r\n═══ ")]
  842. [InlineData (0, 1, 0, 1, "═══")]
  843. [InlineData (1, 1, 0, 1, "════")]
  844. [InlineData (2, 2, 0, 1, "═══ \r\n ═══")]
  845. [Theory]
  846. [SetupFakeDriver]
  847. public void ToString_Positive_Horizontal_2Line_Offset (int x1, int y1, int x2, int y2, string expected)
  848. {
  849. var lc = new LineCanvas ();
  850. lc.AddLine (new (x1, y1), 3, Orientation.Horizontal, LineStyle.Double);
  851. lc.AddLine (new (x2, y2), 3, Orientation.Horizontal, LineStyle.Double);
  852. OutputAssert.AssertEqual (output, expected, $"{lc}");
  853. }
  854. // [Fact, SetupFakeDriver]
  855. // public void LeaveMargin_Top1_Left1 ()
  856. // {
  857. // var canvas = new LineCanvas ();
  858. // // Upper box
  859. // canvas.AddLine (Point.Empty, 9, Orientation.Horizontal, LineStyle.Single);
  860. // canvas.AddLine (new Point (8, 0), 3, Orientation.Vertical, LineStyle.Single);
  861. // canvas.AddLine (new Point (8, 3), -9, Orientation.Horizontal, LineStyle.Single);
  862. // canvas.AddLine (new Point (0, 2), -3, Orientation.Vertical, LineStyle.Single);
  863. // // Lower Box
  864. // canvas.AddLine (new Point (5, 0), 2, Orientation.Vertical, LineStyle.Single);
  865. // canvas.AddLine (new Point (0, 2), 9, Orientation.Horizontal, LineStyle.Single);
  866. // string looksLike =
  867. //@"
  868. //┌────┬──┐
  869. //│ │ │
  870. //├────┼──┤
  871. //└────┴──┘
  872. //";
  873. // Assert.Equal (looksLike, $"{Environment.NewLine}{canvas}");
  874. // }
  875. [InlineData (0, 0, 0, Orientation.Horizontal, LineStyle.Double, "═")]
  876. [InlineData (0, 0, 0, Orientation.Vertical, LineStyle.Double, "║")]
  877. [InlineData (0, 0, 0, Orientation.Horizontal, LineStyle.Single, "─")]
  878. [InlineData (0, 0, 0, Orientation.Vertical, LineStyle.Single, "│")]
  879. [InlineData (0, 0, 1, Orientation.Horizontal, LineStyle.Double, "═")]
  880. [InlineData (0, 0, 1, Orientation.Vertical, LineStyle.Double, "║")]
  881. [InlineData (0, 0, 1, Orientation.Horizontal, LineStyle.Single, "─")]
  882. [InlineData (0, 0, 1, Orientation.Vertical, LineStyle.Single, "│")]
  883. [InlineData (0, 0, 2, Orientation.Horizontal, LineStyle.Double, "══")]
  884. [InlineData (0, 0, 2, Orientation.Vertical, LineStyle.Double, "║\n║")]
  885. [InlineData (0, 0, 2, Orientation.Horizontal, LineStyle.Single, "──")]
  886. [InlineData (0, 0, 2, Orientation.Vertical, LineStyle.Single, "│\n│")]
  887. [SetupFakeDriver]
  888. [Theory]
  889. public void View_Draws_1LineTests (
  890. int x1,
  891. int y1,
  892. int length,
  893. Orientation o1,
  894. LineStyle s1,
  895. string expected
  896. )
  897. {
  898. View v = GetCanvas (out LineCanvas lc);
  899. v.Width = 10;
  900. v.Height = 10;
  901. v.Viewport = new (0, 0, 10, 10);
  902. lc.AddLine (new (x1, y1), length, o1, s1);
  903. v.Draw ();
  904. DriverAssert.AssertDriverContentsAre (expected, output);
  905. v.Dispose ();
  906. }
  907. /// <summary>This test demonstrates how to correctly trigger a corner. By overlapping the lines in the same cell</summary>
  908. [Fact]
  909. [SetupFakeDriver]
  910. public void View_Draws_Corner_Correct ()
  911. {
  912. View v = GetCanvas (out LineCanvas canvas);
  913. canvas.AddLine (Point.Empty, 2, Orientation.Horizontal, LineStyle.Single);
  914. canvas.AddLine (Point.Empty, 2, Orientation.Vertical, LineStyle.Single);
  915. v.Draw ();
  916. var looksLike =
  917. @"
  918. ┌─
  919. │";
  920. DriverAssert.AssertDriverContentsAre (looksLike, output);
  921. v.Dispose ();
  922. }
  923. /// <summary>
  924. /// This test demonstrates that corners are only drawn when lines overlap. Not when they terminate adjacent to one
  925. /// another.
  926. /// </summary>
  927. [Fact]
  928. [SetupFakeDriver]
  929. public void View_Draws_Corner_NoOverlap ()
  930. {
  931. View v = GetCanvas (out LineCanvas canvas);
  932. canvas.AddLine (Point.Empty, 2, Orientation.Horizontal, LineStyle.Single);
  933. canvas.AddLine (new (0, 1), 2, Orientation.Vertical, LineStyle.Single);
  934. v.Draw ();
  935. var looksLike =
  936. @"
  937. ──
  938. │";
  939. DriverAssert.AssertDriverContentsAre (looksLike, output);
  940. v.Dispose ();
  941. }
  942. [InlineData (LineStyle.Single)]
  943. [InlineData (LineStyle.Rounded)]
  944. [Theory]
  945. [SetupFakeDriver]
  946. public void View_Draws_Horizontal (LineStyle style)
  947. {
  948. View v = GetCanvas (out LineCanvas canvas);
  949. canvas.AddLine (Point.Empty, 2, Orientation.Horizontal, style);
  950. v.Draw ();
  951. var looksLike =
  952. @"
  953. ──";
  954. DriverAssert.AssertDriverContentsAre (looksLike, output);
  955. v.Dispose ();
  956. }
  957. [Fact]
  958. [SetupFakeDriver]
  959. public void View_Draws_Horizontal_Double ()
  960. {
  961. View v = GetCanvas (out LineCanvas canvas);
  962. canvas.AddLine (Point.Empty, 2, Orientation.Horizontal, LineStyle.Double);
  963. v.Draw ();
  964. var looksLike =
  965. @"
  966. ══";
  967. DriverAssert.AssertDriverContentsAre (looksLike, output);
  968. v.Dispose ();
  969. }
  970. [InlineData (LineStyle.Single)]
  971. [InlineData (LineStyle.Rounded)]
  972. [Theory]
  973. [SetupFakeDriver]
  974. public void View_Draws_Vertical (LineStyle style)
  975. {
  976. View v = GetCanvas (out LineCanvas canvas);
  977. canvas.AddLine (Point.Empty, 2, Orientation.Vertical, style);
  978. v.Draw ();
  979. var looksLike =
  980. @"
  981. │";
  982. DriverAssert.AssertDriverContentsAre (looksLike, output);
  983. v.Dispose ();
  984. }
  985. [Fact]
  986. [SetupFakeDriver]
  987. public void View_Draws_Vertical_Double ()
  988. {
  989. View v = GetCanvas (out LineCanvas canvas);
  990. canvas.AddLine (Point.Empty, 2, Orientation.Vertical, LineStyle.Double);
  991. v.Draw ();
  992. var looksLike =
  993. @"
  994. ║";
  995. DriverAssert.AssertDriverContentsAre (looksLike, output);
  996. v.Dispose ();
  997. }
  998. [Fact]
  999. [SetupFakeDriver]
  1000. public void View_Draws_Window_Double ()
  1001. {
  1002. View v = GetCanvas (out LineCanvas canvas);
  1003. // outer box
  1004. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, LineStyle.Double);
  1005. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, LineStyle.Double);
  1006. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, LineStyle.Double);
  1007. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, LineStyle.Double);
  1008. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, LineStyle.Double);
  1009. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, LineStyle.Double);
  1010. v.Draw ();
  1011. var looksLike =
  1012. @"
  1013. ╔════╦═══╗
  1014. ║ ║ ║
  1015. ╠════╬═══╣
  1016. ║ ║ ║
  1017. ╚════╩═══╝";
  1018. DriverAssert.AssertDriverContentsAre (looksLike, output);
  1019. v.Dispose ();
  1020. }
  1021. [Theory]
  1022. [SetupFakeDriver]
  1023. [InlineData (LineStyle.Single)]
  1024. [InlineData (LineStyle.Rounded)]
  1025. public void View_Draws_Window_DoubleTop_SingleSides (LineStyle thinStyle)
  1026. {
  1027. View v = GetCanvas (out LineCanvas canvas);
  1028. // outer box
  1029. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, LineStyle.Double);
  1030. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, thinStyle);
  1031. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, LineStyle.Double);
  1032. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, thinStyle);
  1033. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, thinStyle);
  1034. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, LineStyle.Double);
  1035. v.Draw ();
  1036. var looksLike =
  1037. @"
  1038. ╒════╤═══╕
  1039. │ │ │
  1040. ╞════╪═══╡
  1041. │ │ │
  1042. ╘════╧═══╛
  1043. ";
  1044. DriverAssert.AssertDriverContentsAre (looksLike, output);
  1045. v.Dispose ();
  1046. }
  1047. /// <summary>
  1048. /// Demonstrates when <see cref="LineStyle.Rounded"/> corners are used. Notice how not all lines declare rounded.
  1049. /// If there are 1+ lines intersecting and a corner is to be used then if any of them are rounded a rounded corner is
  1050. /// used.
  1051. /// </summary>
  1052. [Fact]
  1053. [SetupFakeDriver]
  1054. public void View_Draws_Window_Rounded ()
  1055. {
  1056. View v = GetCanvas (out LineCanvas canvas);
  1057. // outer box
  1058. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, LineStyle.Rounded);
  1059. // LineStyle.Single is ignored because corner overlaps with the above line which is Rounded
  1060. // this results in a rounded corner being used.
  1061. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, LineStyle.Single);
  1062. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, LineStyle.Rounded);
  1063. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, LineStyle.Single);
  1064. // These lines say rounded but they will result in the T sections which are never rounded.
  1065. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, LineStyle.Rounded);
  1066. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, LineStyle.Rounded);
  1067. v.Draw ();
  1068. var looksLike =
  1069. @"
  1070. ╭────┬───╮
  1071. │ │ │
  1072. ├────┼───┤
  1073. │ │ │
  1074. ╰────┴───╯";
  1075. DriverAssert.AssertDriverContentsAre (looksLike, output);
  1076. v.Dispose ();
  1077. }
  1078. [Theory]
  1079. [InlineData (LineStyle.Single)]
  1080. [InlineData (LineStyle.Rounded)]
  1081. [SetupFakeDriver]
  1082. public void View_Draws_Window_SingleTop_DoubleSides (LineStyle thinStyle)
  1083. {
  1084. View v = GetCanvas (out LineCanvas canvas);
  1085. // outer box
  1086. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, thinStyle);
  1087. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, LineStyle.Double);
  1088. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, thinStyle);
  1089. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, LineStyle.Double);
  1090. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, LineStyle.Double);
  1091. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, thinStyle);
  1092. v.Draw ();
  1093. var looksLike =
  1094. @"
  1095. ╓────╥───╖
  1096. ║ ║ ║
  1097. ╟────╫───╢
  1098. ║ ║ ║
  1099. ╙────╨───╜
  1100. ";
  1101. DriverAssert.AssertDriverContentsAre (looksLike, output);
  1102. v.Dispose ();
  1103. }
  1104. [Fact]
  1105. [SetupFakeDriver]
  1106. public void Window ()
  1107. {
  1108. var canvas = new LineCanvas ();
  1109. // Frame
  1110. canvas.AddLine (Point.Empty, 10, Orientation.Horizontal, LineStyle.Single);
  1111. canvas.AddLine (new (9, 0), 5, Orientation.Vertical, LineStyle.Single);
  1112. canvas.AddLine (new (9, 4), -10, Orientation.Horizontal, LineStyle.Single);
  1113. canvas.AddLine (new (0, 4), -5, Orientation.Vertical, LineStyle.Single);
  1114. // Cross
  1115. canvas.AddLine (new (5, 0), 5, Orientation.Vertical, LineStyle.Single);
  1116. canvas.AddLine (new (0, 2), 10, Orientation.Horizontal, LineStyle.Single);
  1117. var looksLike =
  1118. @"
  1119. ┌────┬───┐
  1120. │ │ │
  1121. ├────┼───┤
  1122. │ │ │
  1123. └────┴───┘";
  1124. OutputAssert.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
  1125. }
  1126. [Fact]
  1127. [SetupFakeDriver]
  1128. public void Zero_Length_Intersections ()
  1129. {
  1130. // Draw at 1,2 within client area of View (i.e. leave a top and left margin of 1)
  1131. // This proves we aren't drawing excess above
  1132. var x = 1;
  1133. var y = 2;
  1134. var width = 5;
  1135. var height = 2;
  1136. var lc = new LineCanvas ();
  1137. // ╔╡╞═════╗
  1138. // Add a short horiz line for ╔╡
  1139. lc.AddLine (new (x, y), 2, Orientation.Horizontal, LineStyle.Double);
  1140. //LHS line down
  1141. lc.AddLine (new (x, y), height, Orientation.Vertical, LineStyle.Double);
  1142. //Vertical line before Title, results in a ╡
  1143. lc.AddLine (new (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
  1144. //Vertical line after Title, results in a ╞
  1145. lc.AddLine (new (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
  1146. // remainder of top line
  1147. lc.AddLine (new (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
  1148. //RHS line down
  1149. lc.AddLine (new (x + width, y), height, Orientation.Vertical, LineStyle.Double);
  1150. var looksLike = @"
  1151. ╔╡╞══╗
  1152. ║ ║";
  1153. OutputAssert.AssertEqual (output, looksLike, $"{Environment.NewLine}{lc}");
  1154. }
  1155. [Fact]
  1156. public void LineCanvas_UsesFillCorrectly ()
  1157. {
  1158. // Arrange
  1159. var foregroundColor = new Color (255, 0); // Red
  1160. var backgroundColor = new Color (0, 0); // Black
  1161. var foregroundFill = new SolidFill (foregroundColor);
  1162. var backgroundFill = new SolidFill (backgroundColor);
  1163. var fillPair = new FillPair (foregroundFill, backgroundFill);
  1164. var lineCanvas = new LineCanvas
  1165. {
  1166. Fill = fillPair
  1167. };
  1168. // Act
  1169. lineCanvas.AddLine (new (0, 0), 5, Orientation.Horizontal, LineStyle.Single);
  1170. Dictionary<Point, Cell?> cellMap = lineCanvas.GetCellMap ();
  1171. // Assert
  1172. foreach (Cell? cell in cellMap.Values)
  1173. {
  1174. Assert.NotNull (cell);
  1175. Assert.Equal (foregroundColor, cell.Value.Attribute.Value.Foreground);
  1176. Assert.Equal (backgroundColor, cell.Value.Attribute.Value.Background);
  1177. }
  1178. }
  1179. [Fact]
  1180. public void LineCanvas_LineColorIgnoredBecauseOfFill ()
  1181. {
  1182. // Arrange
  1183. var foregroundColor = new Color (255, 0); // Red
  1184. var backgroundColor = new Color (0, 0); // Black
  1185. var lineColor = new Attribute (new Color (0, 255), new Color (255, 255, 255)); // Green on White
  1186. var foregroundFill = new SolidFill (foregroundColor);
  1187. var backgroundFill = new SolidFill (backgroundColor);
  1188. var fillPair = new FillPair (foregroundFill, backgroundFill);
  1189. var lineCanvas = new LineCanvas
  1190. {
  1191. Fill = fillPair
  1192. };
  1193. // Act
  1194. lineCanvas.AddLine (new (0, 0), 5, Orientation.Horizontal, LineStyle.Single, lineColor);
  1195. Dictionary<Point, Cell?> cellMap = lineCanvas.GetCellMap ();
  1196. // Assert
  1197. foreach (Cell? cell in cellMap.Values)
  1198. {
  1199. Assert.NotNull (cell);
  1200. Assert.Equal (foregroundColor, cell.Value.Attribute.Value.Foreground);
  1201. Assert.Equal (backgroundColor, cell.Value.Attribute.Value.Background);
  1202. }
  1203. }
  1204. [Fact]
  1205. public void LineCanvas_IntersectingLinesUseFillCorrectly ()
  1206. {
  1207. // Arrange
  1208. var foregroundColor = new Color (255, 0); // Red
  1209. var backgroundColor = new Color (0, 0); // Black
  1210. var foregroundFill = new SolidFill (foregroundColor);
  1211. var backgroundFill = new SolidFill (backgroundColor);
  1212. var fillPair = new FillPair (foregroundFill, backgroundFill);
  1213. var lineCanvas = new LineCanvas
  1214. {
  1215. Fill = fillPair
  1216. };
  1217. // Act
  1218. lineCanvas.AddLine (new (0, 0), 5, Orientation.Horizontal, LineStyle.Single);
  1219. lineCanvas.AddLine (new (2, -2), 5, Orientation.Vertical, LineStyle.Single);
  1220. Dictionary<Point, Cell?> cellMap = lineCanvas.GetCellMap ();
  1221. // Assert
  1222. foreach (Cell? cell in cellMap.Values)
  1223. {
  1224. Assert.NotNull (cell);
  1225. Assert.Equal (foregroundColor, cell.Value.Attribute.Value.Foreground);
  1226. Assert.Equal (backgroundColor, cell.Value.Attribute.Value.Background);
  1227. }
  1228. }
  1229. // TODO: Remove this and make all LineCanvas tests independent of View
  1230. /// <summary>
  1231. /// Creates a new <see cref="View"/> into which a <see cref="LineCanvas"/> is rendered at
  1232. /// <see cref="View.DrawComplete"/> time.
  1233. /// </summary>
  1234. /// <param name="canvas">The <see cref="LineCanvas"/> you can draw into.</param>
  1235. /// <param name="offsetX">How far to offset drawing in X</param>
  1236. /// <param name="offsetY">How far to offset drawing in Y</param>
  1237. /// <returns></returns>
  1238. private View GetCanvas (out LineCanvas canvas, int offsetX = 0, int offsetY = 0)
  1239. {
  1240. var v = new View { Width = 10, Height = 5, Viewport = new (0, 0, 10, 5) };
  1241. LineCanvas canvasCopy = canvas = new ();
  1242. v.DrawComplete += (s, e) =>
  1243. {
  1244. v.FillRect (v.Viewport);
  1245. foreach (KeyValuePair<Point, Rune> p in canvasCopy.GetMap ())
  1246. {
  1247. v.AddRune (
  1248. offsetX + p.Key.X,
  1249. offsetY + p.Key.Y,
  1250. p.Value
  1251. );
  1252. }
  1253. canvasCopy.Clear ();
  1254. };
  1255. return v;
  1256. }
  1257. }