Dim.AutoTests.cs 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. using System.Globalization;
  2. using System.Text;
  3. using Xunit.Abstractions;
  4. using static Terminal.Gui.Dim;
  5. namespace Terminal.Gui.PosDimTests;
  6. public class DimAutoTests (ITestOutputHelper output)
  7. {
  8. private readonly ITestOutputHelper _output = output;
  9. private class DimAutoTestView : View
  10. {
  11. public DimAutoTestView ()
  12. {
  13. ValidatePosDim = true;
  14. Width = Dim.Auto ();
  15. Height = Dim.Auto ();
  16. }
  17. public DimAutoTestView (Dim width, Dim height)
  18. {
  19. ValidatePosDim = true;
  20. Width = width;
  21. Height = height;
  22. }
  23. public DimAutoTestView (string text, Dim width, Dim height)
  24. {
  25. ValidatePosDim = true;
  26. Text = text;
  27. Width = width;
  28. Height = height;
  29. }
  30. }
  31. // Test min - ensure that if min is specified in the DimAuto constructor it is honored
  32. [Fact]
  33. public void Min_Is_Honored ()
  34. {
  35. var superView = new View
  36. {
  37. X = 0,
  38. Y = 0,
  39. Width = Dim.Auto (min: 10),
  40. Height = Dim.Auto (min: 10),
  41. ValidatePosDim = true
  42. };
  43. var subView = new View
  44. {
  45. X = 0,
  46. Y = 0,
  47. Width = 5,
  48. Height = 5
  49. };
  50. superView.Add (subView);
  51. superView.BeginInit ();
  52. superView.EndInit ();
  53. superView.SetRelativeLayout (new (10, 10));
  54. superView.LayoutSubviews (); // no throw
  55. Assert.Equal (10, superView.Frame.Width);
  56. Assert.Equal (10, superView.Frame.Height);
  57. }
  58. // what happens if DimAuto (min: 10) and the subview moves to a negative coord?
  59. [Fact]
  60. public void Min_Resets_If_Subview_Moves_Negative ()
  61. {
  62. var superView = new View
  63. {
  64. X = 0,
  65. Y = 0,
  66. Width = Dim.Auto (min: 10),
  67. Height = Dim.Auto (min: 10),
  68. ValidatePosDim = true
  69. };
  70. var subView = new View
  71. {
  72. X = 0,
  73. Y = 0,
  74. Width = 5,
  75. Height = 5
  76. };
  77. superView.Add (subView);
  78. superView.BeginInit ();
  79. superView.EndInit ();
  80. superView.SetRelativeLayout (new (10, 10));
  81. superView.LayoutSubviews (); // no throw
  82. Assert.Equal (10, superView.Frame.Width);
  83. Assert.Equal (10, superView.Frame.Height);
  84. subView.X = -1;
  85. subView.Y = -1;
  86. superView.SetRelativeLayout (new (10, 10));
  87. superView.LayoutSubviews (); // no throw
  88. Assert.Equal (5, subView.Frame.Width);
  89. Assert.Equal (5, subView.Frame.Height);
  90. Assert.Equal (10, superView.Frame.Width);
  91. Assert.Equal (10, superView.Frame.Height);
  92. }
  93. [Fact]
  94. public void Min_Resets_If_Subview_Shrinks ()
  95. {
  96. var superView = new View
  97. {
  98. X = 0,
  99. Y = 0,
  100. Width = Dim.Auto (min: 10),
  101. Height = Dim.Auto (min: 10),
  102. ValidatePosDim = true
  103. };
  104. var subView = new View
  105. {
  106. X = 0,
  107. Y = 0,
  108. Width = 5,
  109. Height = 5
  110. };
  111. superView.Add (subView);
  112. superView.BeginInit ();
  113. superView.EndInit ();
  114. superView.SetRelativeLayout (new (10, 10));
  115. superView.LayoutSubviews (); // no throw
  116. Assert.Equal (10, superView.Frame.Width);
  117. Assert.Equal (10, superView.Frame.Height);
  118. subView.Width = 3;
  119. subView.Height = 3;
  120. superView.SetRelativeLayout (new (10, 10));
  121. superView.LayoutSubviews (); // no throw
  122. Assert.Equal (3, subView.Frame.Width);
  123. Assert.Equal (3, subView.Frame.Height);
  124. Assert.Equal (10, superView.Frame.Width);
  125. Assert.Equal (10, superView.Frame.Height);
  126. }
  127. [Theory]
  128. [InlineData (0, 0, 0, 0, 0)]
  129. [InlineData (0, 0, 5, 0, 0)]
  130. [InlineData (0, 0, 0, 5, 5)]
  131. [InlineData (0, 0, 5, 5, 5)]
  132. [InlineData (1, 0, 5, 0, 0)]
  133. [InlineData (1, 0, 0, 5, 5)]
  134. [InlineData (1, 0, 5, 5, 5)]
  135. [InlineData (1, 1, 5, 5, 6)]
  136. [InlineData (-1, 0, 5, 0, 0)]
  137. [InlineData (-1, 0, 0, 5, 5)]
  138. [InlineData (-1, 0, 5, 5, 5)]
  139. [InlineData (-1, -1, 5, 5, 4)]
  140. public void Height_Auto_Width_Absolute_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedHeight)
  141. {
  142. var superView = new View
  143. {
  144. X = 0,
  145. Y = 0,
  146. Width = 10,
  147. Height = Dim.Auto (),
  148. ValidatePosDim = true
  149. };
  150. var subView = new View
  151. {
  152. X = subX,
  153. Y = subY,
  154. Width = subWidth,
  155. Height = subHeight,
  156. ValidatePosDim = true
  157. };
  158. superView.Add (subView);
  159. superView.BeginInit ();
  160. superView.EndInit ();
  161. superView.SetRelativeLayout (new (10, 10));
  162. Assert.Equal (new Rectangle (0, 0, 10, expectedHeight), superView.Frame);
  163. }
  164. [Fact]
  165. public void NoSubViews_Does_Nothing ()
  166. {
  167. var superView = new View
  168. {
  169. X = 0,
  170. Y = 0,
  171. Width = Dim.Auto (),
  172. Height = Dim.Auto (),
  173. ValidatePosDim = true
  174. };
  175. superView.BeginInit ();
  176. superView.EndInit ();
  177. superView.SetRelativeLayout (new (10, 10));
  178. Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame);
  179. superView.SetRelativeLayout (new (10, 10));
  180. Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame);
  181. }
  182. [Fact]
  183. public void NoSubViews_Does_Nothing_Vertical ()
  184. {
  185. var superView = new View
  186. {
  187. X = 0,
  188. Y = 0,
  189. Width = Dim.Auto (),
  190. Height = Dim.Auto (),
  191. TextDirection = TextDirection.TopBottom_LeftRight,
  192. ValidatePosDim = true
  193. };
  194. superView.BeginInit ();
  195. superView.EndInit ();
  196. superView.SetRelativeLayout (new (10, 10));
  197. Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame);
  198. superView.SetRelativeLayout (new (10, 10));
  199. Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame);
  200. }
  201. [Theory]
  202. [InlineData (0, 0, 0, 0, 0, 0)]
  203. [InlineData (0, 0, 5, 0, 5, 0)]
  204. [InlineData (0, 0, 0, 5, 0, 5)]
  205. [InlineData (0, 0, 5, 5, 5, 5)]
  206. [InlineData (1, 0, 5, 0, 6, 0)]
  207. [InlineData (1, 0, 0, 5, 1, 5)]
  208. [InlineData (1, 0, 5, 5, 6, 5)]
  209. [InlineData (1, 1, 5, 5, 6, 6)]
  210. [InlineData (-1, 0, 5, 0, 4, 0)]
  211. [InlineData (-1, 0, 0, 5, 0, 5)]
  212. [InlineData (-1, 0, 5, 5, 4, 5)]
  213. [InlineData (-1, -1, 5, 5, 4, 4)]
  214. public void SubView_Changes_SuperView_Size (int subX, int subY, int subWidth, int subHeight, int expectedWidth, int expectedHeight)
  215. {
  216. var superView = new View
  217. {
  218. X = 0,
  219. Y = 0,
  220. Width = Dim.Auto (),
  221. Height = Dim.Auto (),
  222. ValidatePosDim = true
  223. };
  224. var subView = new View
  225. {
  226. X = subX,
  227. Y = subY,
  228. Width = subWidth,
  229. Height = subHeight,
  230. ValidatePosDim = true
  231. };
  232. superView.Add (subView);
  233. superView.BeginInit ();
  234. superView.EndInit ();
  235. superView.SetRelativeLayout (new (10, 10));
  236. Assert.Equal (new Rectangle (0, 0, expectedWidth, expectedHeight), superView.Frame);
  237. }
  238. // Test validation
  239. [Fact]
  240. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims ()
  241. {
  242. var superView = new View
  243. {
  244. X = 0,
  245. Y = 0,
  246. Width = Dim.Auto (),
  247. Height = Dim.Auto (),
  248. ValidatePosDim = true
  249. };
  250. var subView = new View
  251. {
  252. X = 0,
  253. Y = 0,
  254. Width = Dim.Fill (),
  255. Height = 10,
  256. ValidatePosDim = true
  257. };
  258. superView.BeginInit ();
  259. superView.EndInit ();
  260. Assert.Throws<InvalidOperationException> (() => superView.Add (subView));
  261. subView.Width = 10;
  262. superView.Add (subView);
  263. superView.SetRelativeLayout (new (10, 10));
  264. superView.LayoutSubviews (); // no throw
  265. subView.Width = Dim.Fill ();
  266. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  267. subView.Width = 10;
  268. subView.Height = Dim.Fill ();
  269. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  270. subView.Height = 10;
  271. subView.Height = Dim.Percent (50);
  272. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  273. subView.Height = 10;
  274. subView.X = Pos.Center ();
  275. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  276. subView.X = 0;
  277. subView.Y = Pos.Center ();
  278. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  279. subView.Y = 0;
  280. subView.Width = 10;
  281. subView.Height = 10;
  282. subView.X = 0;
  283. subView.Y = 0;
  284. superView.SetRelativeLayout (new (0, 0));
  285. superView.LayoutSubviews ();
  286. }
  287. // Test validation
  288. [Fact]
  289. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims_Combine ()
  290. {
  291. var superView = new View
  292. {
  293. X = 0,
  294. Y = 0,
  295. Width = Dim.Auto (),
  296. Height = Dim.Auto (),
  297. ValidatePosDim = true
  298. };
  299. var subView = new View
  300. {
  301. X = 0,
  302. Y = 0,
  303. Width = 10,
  304. Height = 10
  305. };
  306. var subView2 = new View
  307. {
  308. X = 0,
  309. Y = 0,
  310. Width = 10,
  311. Height = 10
  312. };
  313. superView.Add (subView, subView2);
  314. superView.BeginInit ();
  315. superView.EndInit ();
  316. superView.SetRelativeLayout (new (0, 0));
  317. superView.LayoutSubviews (); // no throw
  318. subView.Height = Dim.Fill () + 3;
  319. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  320. subView.Height = 0;
  321. subView.Height = 3 + Dim.Fill ();
  322. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  323. subView.Height = 0;
  324. subView.Height = 3 + 5 + Dim.Fill ();
  325. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  326. subView.Height = 0;
  327. subView.Height = 3 + 5 + Dim.Percent (10);
  328. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  329. subView.Height = 0;
  330. // Tests nested Combine
  331. subView.Height = 5 + new Dim.DimCombine (true, 3, new Dim.DimCombine (true, Dim.Percent (10), 9));
  332. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  333. }
  334. [Fact]
  335. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Pos_Combine ()
  336. {
  337. var superView = new View
  338. {
  339. X = 0,
  340. Y = 0,
  341. Width = Dim.Auto (),
  342. Height = Dim.Auto (),
  343. ValidatePosDim = true
  344. };
  345. var subView = new View
  346. {
  347. X = 0,
  348. Y = 0,
  349. Width = 10,
  350. Height = 10
  351. };
  352. var subView2 = new View
  353. {
  354. X = 0,
  355. Y = 0,
  356. Width = 10,
  357. Height = 10
  358. };
  359. superView.Add (subView, subView2);
  360. superView.BeginInit ();
  361. superView.EndInit ();
  362. superView.SetRelativeLayout (new (0, 0));
  363. superView.LayoutSubviews (); // no throw
  364. subView.X = Pos.Right (subView2);
  365. superView.SetRelativeLayout (new (0, 0));
  366. superView.LayoutSubviews (); // no throw
  367. subView.X = Pos.Right (subView2) + 3;
  368. superView.SetRelativeLayout (new (0, 0)); // no throw
  369. superView.LayoutSubviews (); // no throw
  370. subView.X = new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, 7, 9));
  371. superView.SetRelativeLayout (new (0, 0)); // no throw
  372. subView.X = Pos.Center () + 3;
  373. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  374. subView.X = 0;
  375. subView.X = 3 + Pos.Center ();
  376. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  377. subView.X = 0;
  378. subView.X = 3 + 5 + Pos.Center ();
  379. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  380. subView.X = 0;
  381. subView.X = 3 + 5 + Pos.Percent (10);
  382. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  383. subView.X = 0;
  384. subView.X = Pos.Percent (10) + Pos.Center ();
  385. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  386. subView.X = 0;
  387. // Tests nested Combine
  388. subView.X = 5 + new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, Pos.Center (), 9));
  389. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new (0, 0)));
  390. subView.X = 0;
  391. }
  392. [Theory]
  393. [InlineData (0, 0, 0, 0, 0)]
  394. [InlineData (0, 0, 5, 0, 5)]
  395. [InlineData (0, 0, 0, 5, 0)]
  396. [InlineData (0, 0, 5, 5, 5)]
  397. [InlineData (1, 0, 5, 0, 6)]
  398. [InlineData (1, 0, 0, 5, 1)]
  399. [InlineData (1, 0, 5, 5, 6)]
  400. [InlineData (1, 1, 5, 5, 6)]
  401. [InlineData (-1, 0, 5, 0, 4)]
  402. [InlineData (-1, 0, 0, 5, 0)]
  403. [InlineData (-1, 0, 5, 5, 4)]
  404. [InlineData (-1, -1, 5, 5, 4)]
  405. public void Width_Auto_Height_Absolute_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedWidth)
  406. {
  407. var superView = new View
  408. {
  409. X = 0,
  410. Y = 0,
  411. Width = Dim.Auto (),
  412. Height = 10,
  413. ValidatePosDim = true
  414. };
  415. var subView = new View
  416. {
  417. X = subX,
  418. Y = subY,
  419. Width = subWidth,
  420. Height = subHeight,
  421. ValidatePosDim = true
  422. };
  423. superView.Add (subView);
  424. superView.BeginInit ();
  425. superView.EndInit ();
  426. superView.SetRelativeLayout (new (10, 10));
  427. Assert.Equal (new Rectangle (0, 0, expectedWidth, 10), superView.Frame);
  428. }
  429. // Test that when a view has Width set to DimAuto (min: x)
  430. // the width is never < x even if SetRelativeLayout is called with smaller bounds
  431. [Theory]
  432. [InlineData (0, 0)]
  433. [InlineData (1, 1)]
  434. [InlineData (3, 3)]
  435. [InlineData (4, 4)]
  436. [InlineData (5, 4)] // This is clearly invalid, but we choose to not throw but log a debug message
  437. public void Width_Auto_Min_Honored (int min, int expectedWidth)
  438. {
  439. var superView = new View
  440. {
  441. X = 0,
  442. Y = 0,
  443. Width = Dim.Auto (min: min),
  444. Height = 1,
  445. ValidatePosDim = true
  446. };
  447. superView.BeginInit ();
  448. superView.EndInit ();
  449. superView.SetRelativeLayout (new (4, 1));
  450. Assert.Equal (expectedWidth, superView.Frame.Width);
  451. }
  452. // Test Dim.Fill - Fill should not impact width of the DimAuto superview
  453. [Theory]
  454. [InlineData (0, 0, 0, 10, 10)]
  455. [InlineData (0, 1, 0, 10, 10)]
  456. [InlineData (0, 11, 0, 10, 10)]
  457. [InlineData (0, 10, 0, 10, 10)]
  458. [InlineData (0, 5, 0, 10, 10)]
  459. [InlineData (1, 5, 0, 10, 9)]
  460. [InlineData (1, 10, 0, 10, 9)]
  461. [InlineData (0, 0, 1, 10, 9)]
  462. [InlineData (0, 10, 1, 10, 9)]
  463. [InlineData (0, 5, 1, 10, 9)]
  464. [InlineData (1, 5, 1, 10, 8)]
  465. [InlineData (1, 10, 1, 10, 8)]
  466. public void Width_Fill_Fills (int subX, int superMinWidth, int fill, int expectedSuperWidth, int expectedSubWidth)
  467. {
  468. var superView = new View
  469. {
  470. X = 0,
  471. Y = 0,
  472. Width = Dim.Auto (min: superMinWidth),
  473. Height = 1,
  474. ValidatePosDim = true
  475. };
  476. var subView = new View
  477. {
  478. X = subX,
  479. Y = 0,
  480. Width = Dim.Fill (fill),
  481. Height = 1,
  482. ValidatePosDim = true
  483. };
  484. superView.Add (subView);
  485. superView.BeginInit ();
  486. superView.EndInit ();
  487. superView.SetRelativeLayout (new (10, 1));
  488. Assert.Equal (expectedSuperWidth, superView.Frame.Width);
  489. superView.LayoutSubviews ();
  490. Assert.Equal (expectedSubWidth, subView.Frame.Width);
  491. Assert.Equal (expectedSuperWidth, superView.Frame.Width);
  492. }
  493. [Theory]
  494. [InlineData (0, 1, 1)]
  495. [InlineData (1, 1, 1)]
  496. [InlineData (9, 1, 1)]
  497. [InlineData (10, 1, 1)]
  498. [InlineData (0, 10, 10)]
  499. [InlineData (1, 10, 10)]
  500. [InlineData (9, 10, 10)]
  501. [InlineData (10, 10, 10)]
  502. public void Width_Auto_Text_Does_Not_Constrain_To_SuperView (int subX, int textLen, int expectedSubWidth)
  503. {
  504. var superView = new View
  505. {
  506. X = 0,
  507. Y = 0,
  508. Width = 10,
  509. Height = 1,
  510. ValidatePosDim = true
  511. };
  512. var subView = new View
  513. {
  514. Text = new string ('*', textLen),
  515. X = subX,
  516. Y = 0,
  517. Width = Dim.Auto (Dim.DimAutoStyle.Text),
  518. Height = 1,
  519. ValidatePosDim = true
  520. };
  521. superView.Add (subView);
  522. superView.BeginInit ();
  523. superView.EndInit ();
  524. superView.SetRelativeLayout (superView.ContentSize.GetValueOrDefault ());
  525. superView.LayoutSubviews ();
  526. Assert.Equal (expectedSubWidth, subView.Frame.Width);
  527. }
  528. [Theory]
  529. [InlineData (0, 1, 1)]
  530. [InlineData (1, 1, 1)]
  531. [InlineData (9, 1, 1)]
  532. [InlineData (10, 1, 1)]
  533. [InlineData (0, 10, 10)]
  534. [InlineData (1, 10, 10)]
  535. [InlineData (9, 10, 10)]
  536. [InlineData (10, 10, 10)]
  537. public void Width_Auto_Subviews_Does_Not_Constrain_To_SuperView (int subX, int subSubViewWidth, int expectedSubWidth)
  538. {
  539. var superView = new View
  540. {
  541. X = 0,
  542. Y = 0,
  543. Width = 10,
  544. Height = 1,
  545. ValidatePosDim = true
  546. };
  547. var subView = new View
  548. {
  549. X = subX,
  550. Y = 0,
  551. Width = Dim.Auto (Dim.DimAutoStyle.Content),
  552. Height = 1,
  553. ValidatePosDim = true
  554. };
  555. var subSubView = new View
  556. {
  557. X = 0,
  558. Y = 0,
  559. Width = subSubViewWidth,
  560. Height = 1,
  561. ValidatePosDim = true
  562. };
  563. subView.Add (subSubView);
  564. superView.Add (subView);
  565. superView.BeginInit ();
  566. superView.EndInit ();
  567. superView.SetRelativeLayout (superView.ContentSize);
  568. superView.LayoutSubviews ();
  569. Assert.Equal (expectedSubWidth, subView.Frame.Width);
  570. }
  571. [Fact]
  572. public void DimAutoStyle_Text_Viewport_Stays_Set ()
  573. {
  574. var super = new View ()
  575. {
  576. Width = Dim.Fill (),
  577. Height = Dim.Fill ()
  578. };
  579. var view = new View ()
  580. {
  581. Text = "01234567",
  582. Width = Auto (DimAutoStyle.Text),
  583. Height = Auto (DimAutoStyle.Text),
  584. };
  585. super.Add (view);
  586. Rectangle expectedViewport = new (0, 0, 8, 1);
  587. Assert.Equal (expectedViewport.Size, view.ContentSize);
  588. Assert.Equal (expectedViewport, view.Frame);
  589. Assert.Equal (expectedViewport, view.Viewport);
  590. super.LayoutSubviews ();
  591. Assert.Equal (expectedViewport, view.Viewport);
  592. super.Dispose ();
  593. }
  594. // Test that changing TextFormatter does not impact View dimensions if Dim.Auto is not in play
  595. [Fact]
  596. public void Not_Used_TextFormatter_Does_Not_Change_View_Size ()
  597. {
  598. View view = new ()
  599. {
  600. Text = "_1234"
  601. };
  602. Assert.False (view.TextFormatter.AutoSize);
  603. Assert.Equal (Size.Empty, view.Frame.Size);
  604. view.TextFormatter.Text = "ABC";
  605. Assert.False (view.TextFormatter.AutoSize);
  606. Assert.Equal (Size.Empty, view.Frame.Size);
  607. view.TextFormatter.Alignment = TextAlignment.Justified;
  608. Assert.False (view.TextFormatter.AutoSize);
  609. Assert.Equal (Size.Empty, view.Frame.Size);
  610. view.TextFormatter.VerticalAlignment = VerticalTextAlignment.Middle;
  611. Assert.False (view.TextFormatter.AutoSize);
  612. Assert.Equal (Size.Empty, view.Frame.Size);
  613. view.TextFormatter.HotKeySpecifier = (Rune)'*';
  614. Assert.False (view.TextFormatter.AutoSize);
  615. Assert.Equal (Size.Empty, view.Frame.Size);
  616. view.TextFormatter.Text = "*ABC";
  617. Assert.False (view.TextFormatter.AutoSize);
  618. Assert.Equal (Size.Empty, view.Frame.Size);
  619. }
  620. [Fact]
  621. public void Not_Used_TextSettings_Do_Not_Change_View_Size ()
  622. {
  623. View view = new ()
  624. {
  625. Text = "_1234"
  626. };
  627. Assert.False (view.TextFormatter.AutoSize);
  628. Assert.Equal (Size.Empty, view.Frame.Size);
  629. view.TextAlignment = TextAlignment.Justified;
  630. Assert.False (view.TextFormatter.AutoSize);
  631. Assert.Equal (Size.Empty, view.Frame.Size);
  632. view.VerticalTextAlignment = VerticalTextAlignment.Middle;
  633. Assert.False (view.TextFormatter.AutoSize);
  634. Assert.Equal (Size.Empty, view.Frame.Size);
  635. view.HotKeySpecifier = (Rune)'*';
  636. Assert.False (view.TextFormatter.AutoSize);
  637. Assert.Equal (Size.Empty, view.Frame.Size);
  638. view.Text = "*ABC";
  639. Assert.False (view.TextFormatter.AutoSize);
  640. Assert.Equal (Size.Empty, view.Frame.Size);
  641. }
  642. [Fact]
  643. public void TextFormatter_Settings_Change_View_Size ()
  644. {
  645. View view = new ()
  646. {
  647. Text = "_1234",
  648. Width = Dim.Auto ()
  649. };
  650. Assert.False (view.TextFormatter.AutoSize);
  651. Assert.NotEqual (Size.Empty, view.Frame.Size);
  652. view.TextAlignment = TextAlignment.Justified;
  653. Assert.False (view.TextFormatter.AutoSize);
  654. Assert.NotEqual (Size.Empty, view.Frame.Size);
  655. view = new ()
  656. {
  657. Text = "_1234",
  658. Width = Dim.Auto ()
  659. };
  660. view.VerticalTextAlignment = VerticalTextAlignment.Middle;
  661. Assert.False (view.TextFormatter.AutoSize);
  662. Assert.NotEqual (Size.Empty, view.Frame.Size);
  663. view = new ()
  664. {
  665. Text = "_1234",
  666. Width = Dim.Auto ()
  667. };
  668. view.HotKeySpecifier = (Rune)'*';
  669. Assert.False (view.TextFormatter.AutoSize);
  670. Assert.NotEqual (Size.Empty, view.Frame.Size);
  671. view = new ()
  672. {
  673. Text = "_1234",
  674. Width = Dim.Auto ()
  675. };
  676. view.Text = "*ABC";
  677. Assert.False (view.TextFormatter.AutoSize);
  678. Assert.NotEqual (Size.Empty, view.Frame.Size);
  679. }
  680. // Ensure TextFormatter.AutoSize is never used for View.Text
  681. [Fact]
  682. public void TextFormatter_Is_Not_Auto ()
  683. {
  684. View view = new ();
  685. Assert.False (view.TextFormatter.AutoSize);
  686. view.Width = Dim.Auto ();
  687. Assert.False (view.TextFormatter.AutoSize);
  688. view = new ();
  689. Assert.False (view.TextFormatter.AutoSize);
  690. view.Height = Dim.Auto ();
  691. Assert.False (view.TextFormatter.AutoSize);
  692. }
  693. [Theory]
  694. [InlineData ("1234", 4)]
  695. [InlineData ("_1234", 4)]
  696. public void Width_Auto_HotKey_TextFormatter_Size_Correct (string text, int expected)
  697. {
  698. View view = new ()
  699. {
  700. Text = text,
  701. Height = 1,
  702. Width = Dim.Auto ()
  703. };
  704. Assert.Equal (new (expected, 1), view.TextFormatter.Size);
  705. }
  706. [Theory]
  707. [InlineData ("1234", 4)]
  708. [InlineData ("_1234", 4)]
  709. public void Height_Auto_HotKey_TextFormatter_Size_Correct (string text, int expected)
  710. {
  711. View view = new ()
  712. {
  713. HotKeySpecifier = (Rune)'_',
  714. Text = text,
  715. Width = Auto (),
  716. Height = 1,
  717. };
  718. Assert.Equal (new (expected, 1), view.TextFormatter.Size);
  719. view = new ()
  720. {
  721. HotKeySpecifier = (Rune)'_',
  722. TextDirection = TextDirection.TopBottom_LeftRight,
  723. Text = text,
  724. Width = 1,
  725. Height = Auto (),
  726. };
  727. Assert.Equal (new (1, expected), view.TextFormatter.Size);
  728. }
  729. [SetupFakeDriver]
  730. [Fact]
  731. public void Change_To_Non_Auto_Resets_ContentSize ()
  732. {
  733. View view = new ()
  734. {
  735. Width = Auto (),
  736. Height = Auto (),
  737. Text = "01234"
  738. };
  739. Assert.Equal (new Rectangle (0, 0, 5, 1), view.Frame);
  740. Assert.Equal (new Size (5, 1), view.ContentSize);
  741. // Change text to a longer string
  742. view.Text = "0123456789";
  743. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Frame);
  744. Assert.Equal (new Size (10, 1), view.ContentSize);
  745. // If ContentSize was reset, these should cause it to update
  746. view.Width = 5;
  747. view.Height = 1;
  748. Assert.Equal (new Size (5, 1), view.ContentSize);
  749. }
  750. // DimAutoStyle.Content tests
  751. [Fact]
  752. public void DimAutoStyle_Content_UsesContentSize_WhenSet ()
  753. {
  754. var view = new View () { ContentSize = new Size (10, 5) };
  755. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  756. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  757. Assert.Equal (10, calculatedWidth);
  758. }
  759. [Fact]
  760. public void DimAutoStyle_Content_IgnoresText_WhenContentSizeNotSet ()
  761. {
  762. var view = new View () { Text = "This is a test" };
  763. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  764. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  765. Assert.Equal (0, calculatedWidth); // Assuming 0 is the default when no ContentSize or Subviews are set
  766. }
  767. [Fact]
  768. public void DimAutoStyle_Content_UsesLargestSubview_WhenContentSizeNotSet ()
  769. {
  770. var view = new View ();
  771. view.Add (new View () { Frame = new Rectangle (0, 0, 5, 5) }); // Smaller subview
  772. view.Add (new View () { Frame = new Rectangle (0, 0, 10, 10) }); // Larger subview
  773. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  774. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  775. Assert.Equal (10, calculatedWidth); // Expecting the size of the largest subview
  776. }
  777. // All the Dim types
  778. [Theory]
  779. [InlineData (0, 15, 15)]
  780. [InlineData (1, 15, 16)]
  781. [InlineData (0, 15, 15)]
  782. [InlineData (-1, 15, 14)]
  783. public void With_Subview_Using_DimAbsolute (int subViewOffset, int dimAbsoluteSize, int expectedSize)
  784. {
  785. var view = new View ();
  786. var subview = new View ()
  787. {
  788. X = subViewOffset,
  789. Y = subViewOffset,
  790. Width = Dim.Sized (dimAbsoluteSize),
  791. Height = Dim.Sized (dimAbsoluteSize)
  792. };
  793. view.Add (subview);
  794. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  795. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  796. int calculatedHeight = dim.Calculate (0, 100, view, Dim.Dimension.Height);
  797. Assert.Equal (expectedSize, calculatedWidth);
  798. Assert.Equal (expectedSize, calculatedHeight);
  799. }
  800. [Theory]
  801. [InlineData (0, 50, 50)]
  802. [InlineData (1, 50, 51)]
  803. [InlineData (0, 25, 25)]
  804. [InlineData (-1, 50, 49)]
  805. public void With_Subview_Using_DimFactor (int subViewOffset, int dimFactor, int expectedSize)
  806. {
  807. var view = new View () { Width = 100, Height = 100 };
  808. var subview = new View ()
  809. {
  810. X = subViewOffset,
  811. Y = subViewOffset,
  812. Width = Dim.Percent (dimFactor),
  813. Height = Dim.Percent (dimFactor)
  814. };
  815. view.Add (subview);
  816. subview.SetRelativeLayout (new (100, 100));
  817. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  818. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  819. int calculatedHeight = dim.Calculate (0, 100, view, Dim.Dimension.Height);
  820. Assert.Equal (expectedSize, calculatedWidth);
  821. Assert.Equal (expectedSize, calculatedHeight);
  822. }
  823. [Theory]
  824. [InlineData (0, 0, 100)]
  825. [InlineData (1, 0, 100)]
  826. [InlineData (0, 1, 99)]
  827. [InlineData (1, 1, 99)]
  828. public void With_Subview_Using_DimFill (int subViewOffset, int dimFillMargin, int expectedSize)
  829. {
  830. var view = new View ();
  831. var subview = new View ()
  832. {
  833. X = subViewOffset,
  834. Y = subViewOffset,
  835. Width = Dim.Fill (dimFillMargin),
  836. Height = Dim.Fill (dimFillMargin)
  837. };
  838. view.Add (subview);
  839. subview.SetRelativeLayout (new (100, 100));
  840. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  841. // Assuming the view's size is 100x100 for calculation purposes
  842. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  843. int calculatedHeight = dim.Calculate (0, 100, view, Dim.Dimension.Height);
  844. Assert.Equal (expectedSize, calculatedWidth);
  845. Assert.Equal (expectedSize, calculatedHeight);
  846. }
  847. [Fact]
  848. public void With_Subview_Using_DimFunc ()
  849. {
  850. var view = new View ();
  851. var subview = new View () { Width = Dim.Function (() => 20), Height = Dim.Function (() => 25) };
  852. view.Add (subview);
  853. subview.SetRelativeLayout (new (100, 100));
  854. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  855. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  856. int calculatedHeight = dim.Calculate (0, 100, view, Dim.Dimension.Height);
  857. Assert.Equal (20, calculatedWidth);
  858. Assert.Equal (25, calculatedHeight);
  859. }
  860. [Fact]
  861. public void With_Subview_Using_DimView ()
  862. {
  863. var view = new View ();
  864. var subview = new View () { Width = 30, Height = 40 };
  865. var subSubview = new View () { Width = Dim.Width (subview), Height = Dim.Height (subview) };
  866. view.Add (subview);
  867. view.Add (subSubview);
  868. subview.SetRelativeLayout (new (100, 100));
  869. var dim = Dim.Auto (Dim.DimAutoStyle.Content);
  870. int calculatedWidth = dim.Calculate (0, 100, view, Dim.Dimension.Width);
  871. int calculatedHeight = dim.Calculate (0, 100, view, Dim.Dimension.Height);
  872. // Expecting the size to match the subview, which is the largest
  873. Assert.Equal (30, calculatedWidth);
  874. Assert.Equal (40, calculatedHeight);
  875. }
  876. // Testing all Pos combinations
  877. [Fact]
  878. public void With_Subview_At_PosAt ()
  879. {
  880. var view = new View ();
  881. var subview = new View () { X = Pos.At (10), Y = Pos.At (5), Width = 20, Height = 10 };
  882. view.Add (subview);
  883. var dimWidth = Dim.Auto ();
  884. var dimHeight = Dim.Auto ();
  885. int calculatedWidth = dimWidth.Calculate (0, 100, view, Dim.Dimension.Width);
  886. int calculatedHeight = dimHeight.Calculate (0, 100, view, Dim.Dimension.Height);
  887. // Expecting the size to include the subview's position and size
  888. Assert.Equal (30, calculatedWidth); // 10 (X position) + 20 (Width)
  889. Assert.Equal (15, calculatedHeight); // 5 (Y position) + 10 (Height)
  890. }
  891. [Fact (Skip = "TextOnly")]
  892. public void With_Subview_At_PosPercent ()
  893. {
  894. var view = new View () { Width = 100, Height = 100 };
  895. var subview = new View () { X = Pos.Percent (50), Y = Pos.Percent (50), Width = 20, Height = 10 };
  896. view.Add (subview);
  897. var dimWidth = Dim.Auto ();
  898. var dimHeight = Dim.Auto ();
  899. // Assuming the calculation is done after layout
  900. int calculatedWidth = dimWidth.Calculate (0, 100, view, Dim.Dimension.Width);
  901. int calculatedHeight = dimHeight.Calculate (0, 100, view, Dim.Dimension.Height);
  902. // Expecting the size to include the subview's position as a percentage of the parent view's size plus the subview's size
  903. Assert.Equal (70, calculatedWidth); // 50% of 100 (Width) + 20
  904. Assert.Equal (60, calculatedHeight); // 50% of 100 (Height) + 10
  905. }
  906. [Fact (Skip = "TextOnly")]
  907. public void With_Subview_At_PosCenter ()
  908. {
  909. var view = new View () { Width = 100, Height = 100 };
  910. var subview = new View () { X = Pos.Center (), Y = Pos.Center (), Width = 20, Height = 10 };
  911. view.Add (subview);
  912. var dimWidth = Dim.Auto ();
  913. var dimHeight = Dim.Auto ();
  914. // Assuming the calculation is done after layout
  915. int calculatedWidth = dimWidth.Calculate (0, 100, view, Dim.Dimension.Width);
  916. int calculatedHeight = dimHeight.Calculate (0, 100, view, Dim.Dimension.Height);
  917. // Expecting the size to include the subview's position at the center of the parent view plus the subview's size
  918. Assert.Equal (70, calculatedWidth); // Centered in 100 (Width) + 20
  919. Assert.Equal (60, calculatedHeight); // Centered in 100 (Height) + 10
  920. }
  921. [Fact (Skip = "TextOnly")]
  922. public void With_Subview_At_PosAnchorEnd ()
  923. {
  924. var dimWidth = Dim.Auto (min: 50);
  925. var dimHeight = Dim.Auto (min: 50);
  926. var view = new View ()
  927. {
  928. Width = dimWidth,
  929. Height = dimHeight
  930. };
  931. var subview = new View ()
  932. {
  933. X = Pos.AnchorEnd (),
  934. Y = Pos.AnchorEnd (),
  935. Width = 20,
  936. Height = 10
  937. };
  938. view.Add (subview);
  939. // Assuming the calculation is done after layout
  940. int calculatedWidth = dimWidth.Calculate (0, 100, view, Dim.Dimension.Width);
  941. int calculatedHeight = dimHeight.Calculate (0, 100, view, Dim.Dimension.Height);
  942. // Expecting the size to include the subview's position at the end of the parent view minus the offset plus the subview's size
  943. Assert.Equal (100, calculatedWidth);
  944. Assert.Equal (100, calculatedHeight);
  945. }
  946. [Fact]
  947. public void DimAutoStyle_Text_Pos_AnchorEnd_Locates_Correctly ()
  948. {
  949. DimAutoTestView view = new ("01234", Auto (DimAutoStyle.Text), Auto (DimAutoStyle.Text));
  950. view.SetRelativeLayout (new (10, 10));
  951. Assert.Equal (new (5, 1), view.Frame.Size);
  952. Assert.Equal (new (0, 0), view.Frame.Location);
  953. view.X = 0;
  954. view.Y = Pos.AnchorEnd (1);
  955. view.SetRelativeLayout (new (10, 10));
  956. Assert.Equal (new (5, 1), view.Frame.Size);
  957. Assert.Equal (new (0, 9), view.Frame.Location);
  958. view.Y = Pos.AnchorEnd ();
  959. view.SetRelativeLayout (new (10, 10));
  960. Assert.Equal (new (5, 1), view.Frame.Size);
  961. Assert.Equal (new (0, 9), view.Frame.Location);
  962. view.Y = Pos.AnchorEnd () - 1;
  963. view.SetRelativeLayout (new (10, 10));
  964. Assert.Equal (new (5, 1), view.Frame.Size);
  965. Assert.Equal (new (0, 8), view.Frame.Location);
  966. }
  967. [Fact]
  968. public void DimAutoStyle_Content_Pos_AnchorEnd_Locates_Correctly ()
  969. {
  970. DimAutoTestView view = new (Auto (DimAutoStyle.Content), Auto (DimAutoStyle.Content));
  971. View subView = new ()
  972. {
  973. Width = 5,
  974. Height = 1
  975. };
  976. view.Add (subView);
  977. view.SetRelativeLayout (new (10, 10));
  978. Assert.Equal (new (5, 1), view.Frame.Size);
  979. Assert.Equal (new (0, 0), view.Frame.Location);
  980. view.X = 0;
  981. view.Y = Pos.AnchorEnd (1);
  982. view.SetRelativeLayout (new (10, 10));
  983. Assert.Equal (new (5, 1), view.Frame.Size);
  984. Assert.Equal (new (0, 9), view.Frame.Location);
  985. view.Y = Pos.AnchorEnd ();
  986. view.SetRelativeLayout (new (10, 10));
  987. Assert.Equal (new (5, 1), view.Frame.Size);
  988. Assert.Equal (new (0, 9), view.Frame.Location);
  989. view.Y = Pos.AnchorEnd () - 1;
  990. view.SetRelativeLayout (new (10, 10));
  991. Assert.Equal (new (5, 1), view.Frame.Size);
  992. Assert.Equal (new (0, 8), view.Frame.Location);
  993. }
  994. [Theory]
  995. [InlineData("01234", 5, 5)]
  996. [InlineData ("01234", 6, 6)]
  997. [InlineData ("01234", 4, 5)]
  998. [InlineData ("01234", 0, 5)]
  999. [InlineData ("", 5, 5)]
  1000. [InlineData ("", 0, 0)]
  1001. public void DimAutoStyle_Auto_Larger_Wins (string text, int dimension, int expected)
  1002. {
  1003. View view = new ()
  1004. {
  1005. Width = Auto (),
  1006. Text = text
  1007. };
  1008. View subView = new ()
  1009. {
  1010. Width = dimension,
  1011. };
  1012. view.Add (subView);
  1013. view.SetRelativeLayout (new (10, 10));
  1014. Assert.Equal (expected, view.Frame.Width);
  1015. }
  1016. // Test variations of Frame
  1017. }